/** * 把本地政策库上传到 DMS,并把返回的相对路径写进 `public/config.js` * 的 `dms.policyRemotePath`(DMS uploadFile **会改名**,不能假定固定文件名)。 * * node harness/tools/upload-policy-library.mjs * node harness/tools/upload-policy-library.mjs https://host/dms * * 需要 dev server 起着(默认 https://localhost:8083/dms)。 * 若 config 里已有路径且可读、条数一致 → 跳过上传。 */ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; const base = String(process.argv[2] || 'https://localhost:8083/dms').replace(/\/+$/, ''); globalThis.VITE_DMS_API = base; const { uploadDmsAttachment, buildDmsFileDisplayUrl } = await import('./_dms.mjs'); const { readFileSync, writeFileSync } = await import('node:fs'); const LOCAL_FILE = 'public/merchant-agent/policies_public.v2.json'; const CONFIG_FILE = 'public/config.js'; const FILE_NAME = 'policies_public.v2.json'; const bytes = readFileSync(LOCAL_FILE); const list = JSON.parse(bytes.toString('utf8')); const localCount = Array.isArray(list) ? list.length : null; const readConfiguredRel = () => { const src = readFileSync(CONFIG_FILE, 'utf8'); const m = src.match(/policyRemotePath\s*:\s*["']([^"']*)["']/); return m ? m[1].trim() : ''; }; const writeConfiguredRel = (rel) => { let src = readFileSync(CONFIG_FILE, 'utf8'); if (/policyRemotePath\s*:/.test(src)) { src = src.replace( /policyRemotePath\s*:\s*["'][^"']*["']/, `policyRemotePath:\n ${JSON.stringify(rel)}` ); } else { throw new Error(`${CONFIG_FILE} 里找不到 policyRemotePath 字段`); } writeFileSync(CONFIG_FILE, src, 'utf8'); }; const probe = async (url) => { const response = await fetch(url); const text = await response.text(); let parsed = null; try { parsed = JSON.parse(text); } catch { /* ignore */ } const count = Array.isArray(parsed) ? parsed.length : null; return { response, count }; }; console.log(`本地 ${LOCAL_FILE}(${(bytes.length / 1024).toFixed(0)} KB / ${localCount ?? '?'} 条)`); const configuredRel = readConfiguredRel(); if (configuredRel) { const url = configuredRel.startsWith('http') ? configuredRel : `${base}${configuredRel.startsWith('/') ? '' : '/'}${configuredRel}`; console.log(`config 已配置 ${configuredRel}`); const existing = await probe(url); if (existing.response.ok && existing.count != null) { console.log(`\n已可读:HTTP ${existing.response.status} · ${existing.count} 条`); if (localCount != null && existing.count === localCount) { console.log(' ✓ 与本地条数一致,无需上传'); process.exit(0); } console.warn(` ⚠️ 条数不一致(远端 ${existing.count} / 本地 ${localCount}),将重新上传并更新 config`); } else { console.log(` 不可读(HTTP ${existing.response.status}),将重新上传`); } } else { console.log('config 未配置 policyRemotePath,将上传并写入'); } console.log(`\n上传 ${FILE_NAME}(DMS 会改名,属正常)…`); const file = new File([bytes], FILE_NAME, { type: 'application/json' }); const relativePath = await uploadDmsAttachment(file, { isImage: false }); const displayUrl = buildDmsFileDisplayUrl(relativePath); console.log('\n上传结果:'); console.log(' 相对路径:' + relativePath); console.log(' 可访问地址:' + displayUrl); const after = await probe(displayUrl); console.log('\n自检:'); console.log(` HTTP ${after.response.status} · 条数=${after.count ?? '(解析失败)'}`); if (after.count !== localCount) { console.error(' ⚠️ 远端内容与本地不一致,未写入 config'); process.exit(1); } console.log(' ✓ 与本地一致'); writeConfiguredRel(relativePath); console.log(`\n已写入 ${CONFIG_FILE} → dms.policyRemotePath = ${JSON.stringify(relativePath)}`);