198 lines
6.3 KiB
JavaScript
198 lines
6.3 KiB
JavaScript
|
|
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();
|