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,无法执行 cart/order 业务 ID 自动生成迁移。'); process.exit(1); } const pb = new PocketBase(PB_URL); const TARGETS = [ { collectionName: 'tbl_cart', fieldName: 'cart_id', autogeneratePattern: 'CART-[0-9]{13}-[A-Za-z0-9]{6}', }, { collectionName: 'tbl_order', fieldName: 'order_id', autogeneratePattern: 'ORDER-[0-9]{13}-[A-Za-z0-9]{6}', }, ]; 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; } 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 ensureAutoGenerateField(target) { const collection = await pb.collections.getOne(target.collectionName); const fields = Array.isArray(collection.fields) ? collection.fields : []; const existingField = fields.find((field) => field && field.name === target.fieldName); if (!existingField) { throw new Error(`${target.collectionName}.${target.fieldName} 不存在`); } const currentPattern = String(existingField.autogeneratePattern || ''); if (existingField.type === 'text' && currentPattern === target.autogeneratePattern) { return { collectionName: target.collectionName, fieldName: target.fieldName, action: 'skipped', autogeneratePattern: currentPattern, }; } const nextFields = fields .filter((field) => field && field.name !== 'id') .map((field) => { if (field.name !== target.fieldName) { return normalizeFieldPayload(field); } return normalizeFieldPayload(field, { type: 'text', required: true, autogeneratePattern: target.autogeneratePattern, }); }); await pb.collections.update(collection.id, buildCollectionPayload(collection, nextFields)); return { collectionName: target.collectionName, fieldName: target.fieldName, action: 'updated', autogeneratePattern: target.autogeneratePattern, }; } async function verifyTargets() { const result = []; for (const target of TARGETS) { const collection = await pb.collections.getOne(target.collectionName); const field = (collection.fields || []).find((item) => item && item.name === target.fieldName); const pattern = String(field && field.autogeneratePattern || ''); const ok = !!field && field.type === 'text' && pattern === target.autogeneratePattern; result.push({ collectionName: target.collectionName, fieldName: target.fieldName, type: field ? field.type : '', required: !!(field && field.required), autogeneratePattern: pattern, ok, }); } const failed = result.filter((item) => !item.ok); if (failed.length) { throw new Error(`以下字段未正确启用自动生成: ${JSON.stringify(failed, 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 changed = []; for (const target of TARGETS) { changed.push(await ensureAutoGenerateField(target)); } console.log('📝 业务 ID 自动生成处理结果:'); console.log(JSON.stringify(changed, null, 2)); const verified = await verifyTargets(); console.log('📝 校验结果:'); console.log(JSON.stringify(verified, null, 2)); console.log('🎉 cart_id / order_id 自动生成规则已就绪。'); } catch (error) { console.error('❌ cart/order 业务 ID 自动生成迁移失败:', error.response?.data || error.message || error); process.exitCode = 1; } } main();