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); if (existingField && existingField.type === targetFieldType) { 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.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); });