feat: align local-first workspace direction
Document the VSCode-like local-first product shape, demote Convex to a control-plane role, and retire stale architecture drafts. Add local workspace migration/export references plus smoke coverage for no-Convex managed workspace startup, local markdown title/body/options persistence, asset upload behavior, and Convex fixture export. Verification: git diff --cached --check; node scripts/check-local-first-convex-guard.js --staged; node scripts/task444-convex-workspace-export-local-fixture-smoke.js; node scripts/task166-local-first-managed-workspace-no-convex-smoke.js; node scripts/task167-local-markdown-title-body-options-no-convex-smoke.js
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
#!/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-"));
|
||||
const fixturePath = path.join(tmpRoot, "fixture.json");
|
||||
const outRoot = path.join(tmpRoot, "local-workspace");
|
||||
|
||||
const fixture = {
|
||||
workspace: {
|
||||
id: "ws_legacy_1",
|
||||
name: "旧云端空间",
|
||||
ownerId: "user_1",
|
||||
},
|
||||
documents: [
|
||||
{
|
||||
id: "doc_root",
|
||||
title: "Project",
|
||||
parent_id: null,
|
||||
sort_order: 1,
|
||||
content: "# Project\n\n\n",
|
||||
wide_layout: true,
|
||||
created_at: "2026-05-01T00:00:00.000Z",
|
||||
updated_at: "2026-05-02T00:00:00.000Z",
|
||||
},
|
||||
{
|
||||
id: "doc_child",
|
||||
title: "Child Spec",
|
||||
parent_id: "doc_root",
|
||||
sort_order: 1,
|
||||
content: "Child body with [file](/api/media/sign?assetId=asset_pdf).\n",
|
||||
created_at: "2026-05-01T00:00:00.000Z",
|
||||
updated_at: "2026-05-02T00:00:00.000Z",
|
||||
},
|
||||
],
|
||||
mediaAssets: [
|
||||
{
|
||||
id: "asset_logo",
|
||||
fileName: "logo.png",
|
||||
contentBase64: Buffer.from("PNG-FIXTURE").toString("base64"),
|
||||
},
|
||||
{
|
||||
id: "asset_pdf",
|
||||
fileName: "spec.pdf",
|
||||
content: "PDF-FIXTURE",
|
||||
},
|
||||
],
|
||||
aiSessions: [
|
||||
{
|
||||
sessionId: "sess_1",
|
||||
visibility: "private",
|
||||
events: [
|
||||
{ eventType: "session.created", sessionId: "sess_1", userId: "user_1" },
|
||||
{ eventType: "run.completed", sessionId: "sess_1", status: "completed" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
fs.writeFileSync(fixturePath, JSON.stringify(fixture, null, 2), "utf8");
|
||||
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
path.join(repoRoot, "scripts", "export-convex-workspace-to-local.js"),
|
||||
"--fixture",
|
||||
fixturePath,
|
||||
"--out",
|
||||
outRoot,
|
||||
],
|
||||
{ cwd: repoRoot, encoding: "utf8" },
|
||||
);
|
||||
|
||||
assert.equal(result.status, 0, result.stderr || result.stdout);
|
||||
|
||||
const projectMd = fs.readFileSync(path.join(outRoot, "pages", "Project.md"), "utf8");
|
||||
const childMd = fs.readFileSync(path.join(outRoot, "pages", "Project", "Child Spec.md"), "utf8");
|
||||
const pageIds = JSON.parse(fs.readFileSync(path.join(outRoot, ".mnote", "page-ids.json"), "utf8"));
|
||||
const pageOptions = JSON.parse(fs.readFileSync(path.join(outRoot, ".mnote", "page-options.json"), "utf8"));
|
||||
const resourceIndex = JSON.parse(fs.readFileSync(path.join(outRoot, ".mnote", "resource-index.json"), "utf8"));
|
||||
const sessionJsonl = fs.readFileSync(path.join(outRoot, "ai-sessions", "private", "sess_1.jsonl"), "utf8");
|
||||
|
||||
assert.match(projectMd, /mnote_id: doc_root/);
|
||||
assert.match(projectMd, /!\[logo\]\(Project\.assets\/logo\.png\)/);
|
||||
assert.match(childMd, /\[file\]\(Child Spec\.assets\/spec\.pdf\)/);
|
||||
assert.equal(pageIds.pages["pages/Project.md"], "local-mdid:doc_root");
|
||||
assert.equal(pageIds.pages["pages/Project/Child Spec.md"], "local-mdid:doc_child");
|
||||
assert.equal(pageOptions.pages["local-mdid:doc_root"].wideLayout, true);
|
||||
assert.equal(resourceIndex.assets.asset_logo.relativePath, "pages/Project.assets/logo.png");
|
||||
assert.match(sessionJsonl, /"eventType":"run.completed"/);
|
||||
assert.equal(fs.readFileSync(path.join(outRoot, "pages", "Project.assets", "logo.png"), "utf8"), "PNG-FIXTURE");
|
||||
assert.equal(fs.readFileSync(path.join(outRoot, "pages", "Project", "Child Spec.assets", "spec.pdf"), "utf8"), "PDF-FIXTURE");
|
||||
|
||||
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
||||
console.log(JSON.stringify({ ok: true, smoke: "task444-convex-workspace-export-local-fixture" }, null, 2));
|
||||
Reference in New Issue
Block a user