import fs from 'node:fs'; import path from 'node:path'; import crypto from 'node:crypto'; import assert from 'node:assert/strict'; import { call, login, fixture, writeFixture, report } from './model-editor-closure-live.mjs'; const data = fixture(); const session = await login('root'); const result = { time: new Date().toISOString(), status: 'PENDING', originals: [], projects: [] }; try { const me = await call('auth/v1/auth/me', session.accessToken); assert.equal(me.status, 200); for (const original of Object.values(data.originals)) { const current = await call(`tran/v1/content/projects/${original.id}`, session.accessToken); assert.equal(current.status, 200); const hash = crypto.createHash('sha256').update(JSON.stringify(current.data)).digest('hex'); assert.equal(hash, original.hash, `Original ${original.id} full document must be unchanged`); result.originals.push({ id: original.id, name: original.name, version: current.data.project.version, unchanged: true }); } const originals = new Set(Object.values(data.originals).map(item => String(item.id))); const ids = [...new Set([...Object.values(data.models).map(item => item.id), ...data.extraProjectIds].map(String))]; for (const id of ids) { assert.ok(!originals.has(id), 'Never delete original reference projects'); const current = await call(`tran/v1/content/projects/${id}`, session.accessToken); if (current.status === 404) { result.projects.push({ id, alreadyAbsent: true }); continue; } assert.equal(current.status, 200); let p = current.data.project; assert.ok(/^闭环(?:验收|新建|补充|工具补充)-/.test(p.name) || p.name === `闭环导航名称-${id}`, 'Only names created or renamed by this review may be removed'); assert.equal(String(p.ownerUserId), String(me.data.id)); assert.ok(p.addTime >= Math.floor(Date.parse(data.createdAt) / 1000)); let withdrawn = false; if (p.status === 'PUBLISHED' || p.statusCode === 'PUBLISHED') { const withdrawal = await call(`tran/v1/content/projects/${id}/review`, session.accessToken, { action: 'REVOKE', version: p.version, comment: '装备模型编辑闭环验收结束,清理本次隔离测试副本', }); assert.equal(withdrawal.status, 200, `Withdraw isolated project ${id}`); p = withdrawal.data.project; withdrawn = true; } const removed = await call(`tran/v1/content/projects/${id}?version=${p.version}`, session.accessToken, undefined, 'DELETE'); assert.equal(removed.status, 200, `Remove isolated project ${id}: ${removed.message}`); result.projects.push({ id, name: p.name, withdrawn, removed: true }); } result.status = 'PASS'; data.cleanedAt = result.time; writeFixture(data); console.log(JSON.stringify({ status: result.status, unchangedOriginals: result.originals.length, cleanedProjects: result.projects.length })); } catch (error) { result.status = 'FAIL'; result.error = error.message; process.exitCode = 1; console.error(error.message); } finally { fs.writeFileSync(path.join(report, 'cleanup.json'), JSON.stringify(result, null, 2)); await call('auth/v1/auth/logout', session.accessToken, {}).catch(() => {}); }