109 lines
3.5 KiB
JavaScript
109 lines
3.5 KiB
JavaScript
#!/usr/bin/env node
|
|
"use strict";
|
|
|
|
const assert = require("node:assert/strict");
|
|
const fs = require("node:fs");
|
|
const os = require("node:os");
|
|
const path = require("node:path");
|
|
const { spawnSync } = require("node:child_process");
|
|
|
|
const repoRoot = path.resolve(__dirname, "..", "..", "..");
|
|
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "mnote-convex-export-plan-"));
|
|
const fixturePath = path.join(tmpRoot, "fixture.json");
|
|
const outRoot = path.join(tmpRoot, "local-workspace");
|
|
const manifestPath = path.join(tmpRoot, "migration-manifest.json");
|
|
const conflictPath = path.join(tmpRoot, "conflicts.json");
|
|
|
|
const fixture = {
|
|
workspace: {
|
|
id: "ws_legacy_plan",
|
|
name: "迁移计划空间",
|
|
ownerId: "user_plan",
|
|
},
|
|
documents: [
|
|
{
|
|
id: "doc_root",
|
|
title: "Project",
|
|
parent_id: null,
|
|
content: "# Project\n\n导出正文\n",
|
|
wide_layout: true,
|
|
},
|
|
],
|
|
mediaAssets: [
|
|
{
|
|
id: "asset_logo",
|
|
fileName: "logo.txt",
|
|
documentId: "doc_root",
|
|
content: "LOGO-NEW",
|
|
},
|
|
],
|
|
aiSessions: [],
|
|
};
|
|
|
|
function runExport(args, expectedStatus = 0) {
|
|
const result = spawnSync(
|
|
process.execPath,
|
|
[path.join(__dirname, "export-convex-workspace-to-local.js"), ...args],
|
|
{ cwd: repoRoot, encoding: "utf8" },
|
|
);
|
|
assert.equal(result.status, expectedStatus, result.stderr || result.stdout);
|
|
return result;
|
|
}
|
|
|
|
try {
|
|
fs.writeFileSync(fixturePath, JSON.stringify(fixture, null, 2), "utf8");
|
|
|
|
runExport([
|
|
"--fixture",
|
|
fixturePath,
|
|
"--out",
|
|
outRoot,
|
|
"--dry-run",
|
|
"--manifest",
|
|
manifestPath,
|
|
"--conflict-report",
|
|
conflictPath,
|
|
]);
|
|
assert.equal(fs.existsSync(path.join(outRoot, "pages", "Project.md")), false, "dry run 不应写入页面文件");
|
|
const dryRunManifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
assert.equal(dryRunManifest.dryRun, true);
|
|
assert.equal(dryRunManifest.operations.some((item) => item.action === "create" && item.relativePath === "pages/Project.md"), true);
|
|
|
|
fs.mkdirSync(path.join(outRoot, "pages"), { recursive: true });
|
|
fs.writeFileSync(path.join(outRoot, "pages", "Project.md"), "原有内容\n", "utf8");
|
|
const conflict = runExport([
|
|
"--fixture",
|
|
fixturePath,
|
|
"--out",
|
|
outRoot,
|
|
"--manifest",
|
|
manifestPath,
|
|
"--conflict-report",
|
|
conflictPath,
|
|
], 2);
|
|
assert.match(conflict.stderr + conflict.stdout, /migration_conflict/);
|
|
assert.equal(fs.readFileSync(path.join(outRoot, "pages", "Project.md"), "utf8"), "原有内容\n");
|
|
const conflictReport = JSON.parse(fs.readFileSync(conflictPath, "utf8"));
|
|
assert.equal(conflictReport.conflicts.some((item) => item.relativePath === "pages/Project.md"), true);
|
|
|
|
fs.rmSync(outRoot, { recursive: true, force: true });
|
|
runExport([
|
|
"--fixture",
|
|
fixturePath,
|
|
"--out",
|
|
outRoot,
|
|
"--manifest",
|
|
manifestPath,
|
|
]);
|
|
assert.match(fs.readFileSync(path.join(outRoot, "pages", "Project.md"), "utf8"), /导出正文/);
|
|
assert.equal(fs.existsSync(path.join(outRoot, ".mnote", "migration-manifest.json")), true);
|
|
|
|
runExport(["--rollback", path.join(outRoot, ".mnote", "migration-manifest.json")]);
|
|
assert.equal(fs.existsSync(path.join(outRoot, "pages", "Project.md")), false, "rollback 应删除本次新增页面");
|
|
assert.equal(fs.existsSync(path.join(outRoot, "pages", "Project.assets", "logo.txt")), false, "rollback 应删除本次新增资源");
|
|
|
|
console.log(JSON.stringify({ ok: true, smoke: "task455-convex-export-plan-rollback" }, null, 2));
|
|
} finally {
|
|
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
}
|