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 PB_URL = String( process.env.PB_URL || backendEnv.POCKETBASE_API_URL || runtimeConfig.POCKETBASE_API_URL || 'http://127.0.0.1:8090' ).replace(/\/+$/, ''); const AUTH_TOKEN = process.env.POCKETBASE_AUTH_TOKEN || runtimeConfig.POCKETBASE_AUTH_TOKEN || ''; if (!AUTH_TOKEN) { console.error('❌ 缺少 POCKETBASE_AUTH_TOKEN,无法执行 tbl_order 字段迁移。'); process.exit(1); } const pb = new PocketBase(PB_URL); const TARGET_FIELD = { name: 'order_pay_status', type: 'text', required: false, }; function normalizeFieldPayload(field, overrides) { const payload = Object.assign({}, field, overrides || {}); if (payload.type === 'number') { if (Object.prototype.hasOwnProperty.call(payload, 'onlyInt')) { payload.onlyInt = !!payload.onlyInt; } } if (payload.type === 'autodate') { payload.onCreate = typeof payload.onCreate === 'boolean' ? payload.onCreate : true; payload.onUpdate = typeof payload.onUpdate === 'boolean' ? payload.onUpdate : false; } if (payload.type === 'file') { payload.maxSelect = typeof payload.maxSelect === 'number' ? payload.maxSelect : 0; payload.maxSize = typeof payload.maxSize === 'number' ? payload.maxSize : 0; payload.mimeTypes = Array.isArray(payload.mimeTypes) ? payload.mimeTypes : null; } if (payload.type === 'relation') { payload.maxSelect = typeof payload.maxSelect === 'number' ? payload.maxSelect : 1; payload.cascadeDelete = typeof payload.cascadeDelete === 'boolean' ? payload.cascadeDelete : false; } return payload; } function buildCollectionPayload(collection, fields) { return { name: collection.name, type: collection.type, listRule: collection.listRule, viewRule: collection.viewRule, createRule: collection.createRule, updateRule: collection.updateRule, deleteRule: collection.deleteRule, fields, indexes: collection.indexes || [], }; } async function migrateField() { const collection = await pb.collections.getOne('tbl_order'); const fields = Array.isArray(collection.fields) ? collection.fields : []; const existingField = fields.find((field) => field && field.name === TARGET_FIELD.name); const fieldReady = !!existingField && existingField.type === TARGET_FIELD.type && existingField.required === TARGET_FIELD.required; if (fieldReady) { return { action: 'skipped', field: { name: existingField.name, type: existingField.type, required: !!existingField.required, }, }; } const nextFields = fields .filter((field) => field && field.name !== 'id') .map((field) => { if (field.name === TARGET_FIELD.name) { return normalizeFieldPayload(field, TARGET_FIELD); } return normalizeFieldPayload(field); }); if (!existingField) { nextFields.push(normalizeFieldPayload(null, TARGET_FIELD)); } await pb.collections.update(collection.id, buildCollectionPayload(collection, nextFields)); return { action: existingField ? 'normalized' : 'added', }; } async function verifyField() { const collection = await pb.collections.getOne('tbl_order'); const field = (collection.fields || []).find((item) => item && item.name === TARGET_FIELD.name); const result = { name: field ? field.name : '', type: field ? field.type : '', required: !!(field && field.required), ok: !!field && field.type === TARGET_FIELD.type && field.required === TARGET_FIELD.required, }; if (!result.ok) { throw new Error('order_pay_status 字段校验失败: ' + JSON.stringify(result, null, 2)); } return result; } async function main() { try { console.log(`🔄 正在连接 PocketBase: ${PB_URL}`); pb.authStore.save(AUTH_TOKEN, null); console.log('✅ 已使用 POCKETBASE_AUTH_TOKEN 载入认证状态。'); const migrated = await migrateField(); console.log('📝 迁移结果:'); console.log(JSON.stringify(migrated, null, 2)); const verified = await verifyField(); console.log('📝 校验结果:'); console.log(JSON.stringify(verified, null, 2)); console.log('🎉 tbl_order.order_pay_status 字段已就绪。'); } catch (error) { console.error('❌ tbl_order 字段迁移失败:'); console.error('status:', error && error.status); console.error('message:', error && error.message); console.error('response:', error && error.response); console.error('originalError:', error && error.originalError); console.error('stack:', error && error.stack); process.exitCode = 1; } } main();