Files
Web_BAI_Manage_ApiServer/script/add-product-function-field.js
XuJiacheng cd0373be3c feat: 添加系统刷新令牌请求和用户统计响应的 OpenAPI 规范
feat: 添加微信认证相关的 OpenAPI 规范,包括用户信息、登录请求和个人资料请求

feat: 添加 is_delete 字段迁移脚本,支持在集合中添加软删除字段

feat: 添加软删除规则应用脚本,确保所有相关集合的查询规则包含软删除条件

feat: 添加购物车和订单业务 ID 自动生成的迁移脚本,确保字段类型和自动生成规则正确
2026-04-07 20:02:10 +08:00

156 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createRequire } from 'module';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import PocketBase from 'pocketbase';
const require = createRequire(import.meta.url);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
let runtimeConfig = {};
try {
runtimeConfig = require('../pocket-base/bai_api_pb_hooks/bai_api_shared/config/runtime.js');
} catch (_error) {
runtimeConfig = {};
}
function readEnvFile(filePath) {
if (!fs.existsSync(filePath)) return {};
const content = fs.readFileSync(filePath, 'utf8');
const result = {};
for (const rawLine of content.split(/\r?\n/)) {
const line = rawLine.trim();
if (!line || line.startsWith('#')) continue;
const index = line.indexOf('=');
if (index === -1) continue;
const key = line.slice(0, index).trim();
const value = line.slice(index + 1).trim();
result[key] = value;
}
return result;
}
const backendEnv = readEnvFile(path.resolve(__dirname, '..', 'back-end', '.env'));
const pbUrl = String(
process.env.PB_URL
|| backendEnv.POCKETBASE_API_URL
|| runtimeConfig.POCKETBASE_API_URL
|| 'http://127.0.0.1:8090'
).replace(/\/+$/, '');
const authToken = process.env.POCKETBASE_AUTH_TOKEN || runtimeConfig.POCKETBASE_AUTH_TOKEN || '';
if (!authToken) {
console.error('❌ 缺少 POCKETBASE_AUTH_TOKEN无法执行字段迁移。');
process.exit(1);
}
function normalizeFieldPayload(field, targetSpec) {
const payload = {
name: targetSpec && targetSpec.name ? targetSpec.name : field.name,
type: targetSpec && targetSpec.type ? targetSpec.type : field.type,
};
if (field && field.id) {
payload.id = field.id;
}
if (typeof field.required !== 'undefined') {
payload.required = !!field.required;
}
if (payload.type === 'autodate') {
payload.onCreate = typeof field.onCreate === 'boolean' ? field.onCreate : true;
payload.onUpdate = typeof field.onUpdate === 'boolean' ? field.onUpdate : false;
}
return payload;
}
async function run() {
const pb = new PocketBase(pbUrl);
pb.authStore.save(authToken, null);
console.log(`🔄 开始处理字段迁移PocketBase: ${pbUrl}`);
const collections = await pb.collections.getFullList({ sort: '-created' });
const collection = collections.find((item) => item.name === 'tbl_product_list');
if (!collection) {
throw new Error('未找到集合 tbl_product_list');
}
const targetFieldName = 'prod_list_function';
const targetFieldType = 'json';
const existingField = (collection.fields || []).find((field) => field.name === targetFieldName);
const hasBrokenCustomIdField = (collection.fields || []).some((field) => field && field.name === 'id');
if (existingField && existingField.type === targetFieldType && !hasBrokenCustomIdField) {
console.log('✅ 字段已存在且类型正确,无需变更。');
console.log('✅ 校验完成: tbl_product_list.prod_list_function (json)');
return;
}
const nextFields = [];
let patched = false;
for (let i = 0; i < (collection.fields || []).length; i += 1) {
const field = collection.fields[i];
if (field && field.name === 'id') {
// PocketBase system id is implicit; custom required id field will break record creation.
continue;
}
if (field.name === targetFieldName) {
nextFields.push(normalizeFieldPayload(field, { name: targetFieldName, type: targetFieldType }));
patched = true;
continue;
}
nextFields.push(normalizeFieldPayload(field));
}
if (!patched) {
nextFields.push({
name: targetFieldName,
type: targetFieldType,
required: false,
});
}
await pb.collections.update(collection.id, {
name: collection.name,
type: collection.type,
listRule: collection.listRule,
viewRule: collection.viewRule,
createRule: collection.createRule,
updateRule: collection.updateRule,
deleteRule: collection.deleteRule,
fields: nextFields,
indexes: collection.indexes || [],
});
const updated = await pb.collections.getOne(collection.id);
const verifiedField = (updated.fields || []).find((field) => field.name === targetFieldName);
if (!verifiedField || verifiedField.type !== targetFieldType) {
throw new Error('字段写入后校验失败prod_list_function 未成功写入 json 类型');
}
console.log('✅ 字段迁移成功: tbl_product_list.prod_list_function (json)');
}
run().catch((error) => {
console.error('❌ 迁移失败:', {
status: error && error.status,
message: error && error.message,
response: error && error.response,
});
process.exit(1);
});