import fs from 'node:fs'; import path from 'node:path'; import crypto from 'node:crypto'; import assert from 'node:assert/strict'; import { fileURLToPath } from 'node:url'; import { login, root } from './role-permissions-live.mjs'; export { login }; export async function call(endpoint, token, body, method = body === undefined ? 'GET' : 'POST') { const response = await fetch(`http://127.0.0.1:6180/api/${endpoint}`, { method, headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) }, body: body === undefined ? undefined : JSON.stringify(body), signal: AbortSignal.timeout(120000), }); const value = await response.json(); return { status: response.status, code: value.code, data: value.data, message: value.message }; } export const report = path.join(root, 'ute2e/reports/model-editor-closure-20260906'); export const work = path.resolve(root, '../.codex-tmp/model-closure-20260906'); export const fixturePath = path.join(work, 'fixtures.json'); fs.mkdirSync(report, { recursive: true }); fs.mkdirSync(work, { recursive: true }); export const fixture = () => JSON.parse(fs.readFileSync(fixturePath, 'utf8')); export const writeFixture = value => fs.writeFileSync(fixturePath, JSON.stringify(value, null, 2)); const hash = value => crypto.createHash('sha256').update(JSON.stringify(value)).digest('hex'); async function prepare() { if (fs.existsSync(fixturePath) && !fixture().cleanedAt && !process.argv.includes('--resume')) throw new Error('This run already has fixtures; reuse them or clean up first'); const session = await login('root'); const data = process.argv.includes('--resume') ? fixture() : { createdAt: new Date().toISOString(), models: {}, extraProjectIds: [], originals: {} }; writeFixture(data); try { for (const [key, id, name] of [['fox', '157', '闭环验收-狐狸-20260906'], ['truck', '156', '闭环验收-牛奶卡车-20260906']]) { if (data.models[key]) continue; const original = await call(`tran/v1/content/projects/${id}`, session.accessToken); assert.equal(original.status, 200); data.originals[key] = { id, name: original.data.project.name, version: original.data.project.version, hash: hash(original.data) }; fs.writeFileSync(path.join(work, `original-${key}.json`), JSON.stringify(original.data, null, 2)); writeFixture(data); const copy = await call(`tran/v1/content/projects/${id}/copy`, session.accessToken, { name, version: original.data.project.version }); assert.equal(copy.status, 200, `Copy ${key}: ${copy.message}`); assert.ok(copy.data.project.id); data.models[key] = { id: copy.data.project.id, name, code: copy.data.project.code }; writeFixture(data); } console.log(JSON.stringify({ fixturesReady: true, models: data.models })); } finally { await call('auth/v1/auth/logout', session.accessToken, {}).catch(() => {}); } } if (process.argv[1] === fileURLToPath(import.meta.url)) prepare().catch(error => { console.error(error.message); process.exitCode = 1; });