| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- #!/usr/bin/env node
- const SOURCE_URL = (process.env.XIAOSHU_READING_PROMPT_SOURCE_URL || 'https://server.fmode.cn/parse').replace(/\/$/, '');
- const SOURCE_APP_ID = process.env.XIAOSHU_READING_PROMPT_SOURCE_APP_ID || 'ncloudmaster';
- const TARGET_URL = (process.env.XIAOSHU_PARSE_URL || 'https://server.xiaoshu.pro/parse').replace(/\/$/, '');
- const TARGET_APP_ID = process.env.XIAOSHU_PARSE_APP_ID || '7pIbDBJmKx_main';
- const MASTER_KEY = process.env.XIAOSHU_MASTER_KEY || '';
- const commit = process.argv.includes('--commit');
- const CODES = [
- 'english-reading-article-tpl',
- 'english-reading-article-supply-tpl',
- 'english-reading-question-json-tpl',
- ];
- if (commit && !MASTER_KEY) throw new Error('缺少 XIAOSHU_MASTER_KEY,不会写入生产数据');
- async function parseRequest(url, headers, init = {}) {
- const response = await fetch(url, { ...init, headers: { ...headers, ...(init.headers || {}) } });
- const text = await response.text();
- let payload;
- try { payload = text ? JSON.parse(text) : {}; }
- catch { throw new Error(`Parse 返回了无效 JSON(${response.status})`); }
- if (!response.ok || payload.error) throw new Error(payload.error || `Parse 请求失败(${response.status})`);
- return payload;
- }
- function classQuery(baseUrl, where) {
- return `${baseUrl}/classes/PromptTemplate?where=${encodeURIComponent(JSON.stringify(where))}&limit=100`;
- }
- const sourceHeaders = { 'X-Parse-Application-Id': SOURCE_APP_ID };
- const targetHeaders = {
- 'X-Parse-Application-Id': TARGET_APP_ID,
- ...(MASTER_KEY ? { 'X-Parse-Master-Key': MASTER_KEY } : {}),
- 'Content-Type': 'application/json',
- };
- const sourcePayload = await parseRequest(classQuery(SOURCE_URL, { code: { $in: CODES } }), sourceHeaders);
- const sourceRows = Array.isArray(sourcePayload.results) ? sourcePayload.results : [];
- const sourceByCode = new Map(sourceRows.map((row) => [String(row.code || ''), row]));
- const missingSource = CODES.filter((code) => !sourceByCode.has(code));
- if (missingSource.length) throw new Error(`原系统缺少阅读模板:${missingSource.join(', ')}`);
- let targetRows = [];
- try {
- const targetPayload = await parseRequest(classQuery(TARGET_URL, { code: { $in: CODES } }), targetHeaders);
- targetRows = Array.isArray(targetPayload.results) ? targetPayload.results : [];
- } catch (error) {
- if (!commit) throw error;
- targetRows = [];
- }
- const targetByCode = new Map(targetRows.map((row) => [String(row.code || ''), row]));
- const summary = { source: sourceRows.length, targetBefore: targetRows.length, create: 0, update: 0, unchanged: 0, committed: commit };
- for (const code of CODES) {
- const source = sourceByCode.get(code);
- const target = targetByCode.get(code);
- const value = {
- code,
- name: String(source.name || code),
- template: String(source.template || ''),
- ...(source.output === undefined ? {} : { output: source.output }),
- };
- const unchanged = target
- && String(target.name || '') === value.name
- && String(target.template || '') === value.template
- && JSON.stringify(target.output ?? null) === JSON.stringify(value.output ?? null);
- if (unchanged) { summary.unchanged += 1; continue; }
- if (target) summary.update += 1;
- else summary.create += 1;
- if (!commit) continue;
- const url = target
- ? `${TARGET_URL}/classes/PromptTemplate/${encodeURIComponent(target.objectId)}`
- : `${TARGET_URL}/classes/PromptTemplate`;
- await parseRequest(url, targetHeaders, { method: target ? 'PUT' : 'POST', body: JSON.stringify(value) });
- }
- console.log(JSON.stringify(summary, null, 2));
|