yamlover 0.3.7 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-docs/AGENTS.md +267 -0
- package/dist/agent-docs/CLAUDE.md +7 -0
- package/dist/client/assets/{decoded-BOcSNNro.js → decoded-4gqlad5X.js} +1 -1
- package/dist/client/assets/{djvu-BlBoGQOr.js → djvu-Dex1F0s7.js} +1 -1
- package/dist/client/assets/{docx-DHMG3jBZ.js → docx-DJzgnQG5.js} +1 -1
- package/dist/client/assets/{heic-DyzDZBbr.js → heic-DqYoM-Wf.js} +1 -1
- package/dist/client/assets/{imagemap-dBuJBDcO.js → imagemap-DaET_nLG.js} +1 -1
- package/dist/client/assets/{index-DAOxKLZS.css → index-CkbHoSh8.css} +1 -1
- package/dist/client/assets/index-IlC0sRFA.js +620 -0
- package/dist/client/assets/{map-DZ0HIGla.js → map-BmG6sq1M.js} +1 -1
- package/dist/client/assets/{paged-WKVquIPj.js → paged-Bxb-d5c7.js} +1 -1
- package/dist/client/assets/{panzoom--sfux6SK.js → panzoom-BoL5vDfI.js} +1 -1
- package/dist/client/assets/{pdf-BVBH0bXQ.js → pdf-BpkDRVTL.js} +1 -1
- package/dist/client/assets/{psd-CsYV_1P8.js → psd-DC6nmZST.js} +1 -1
- package/dist/client/assets/{spreadsheet-m5FCnukV.js → spreadsheet-DIfzBeGR.js} +1 -1
- package/dist/client/assets/{tiff-BX8kKhqw.js → tiff-CBO4Dy15.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server.js +236 -20
- package/package.json +1 -1
- package/dist/client/assets/index-c8LVvQSJ.js +0 -617
package/dist/server.js
CHANGED
|
@@ -62331,6 +62331,7 @@ var require_ignore = __commonJS({
|
|
|
62331
62331
|
// src/server/engine-api.ts
|
|
62332
62332
|
import path9 from "node:path";
|
|
62333
62333
|
import fs9 from "node:fs";
|
|
62334
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
62334
62335
|
|
|
62335
62336
|
// ../parser/ts/src/ir.ts
|
|
62336
62337
|
function isPointer(v) {
|
|
@@ -62441,13 +62442,13 @@ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
|
|
|
62441
62442
|
let steps = ptr.steps;
|
|
62442
62443
|
let chain;
|
|
62443
62444
|
const linkAuthority = ptr.base.scope === "link" ? ptr.base.authority : "";
|
|
62444
|
-
|
|
62445
|
+
const isWorld = ptr.base.scope === "link" && ptr.base.world === true;
|
|
62445
62446
|
const external = () => ({ kind: "external", authority: linkAuthority, steps: ptr.steps });
|
|
62446
62447
|
switch (ptr.base.scope) {
|
|
62447
62448
|
case "link": {
|
|
62448
|
-
isLink = true;
|
|
62449
62449
|
chain = chains.get(root) ?? [root];
|
|
62450
|
-
|
|
62450
|
+
const selfImport = ptr.base.authority === "yamlover" && !root.entries?.some((e3) => e3.key === "yamlover");
|
|
62451
|
+
steps = selfImport ? ptr.steps : [{ sel: "key", name: ptr.base.authority }, ...ptr.steps];
|
|
62451
62452
|
break;
|
|
62452
62453
|
}
|
|
62453
62454
|
case "document": {
|
|
@@ -62470,7 +62471,7 @@ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
|
|
|
62470
62471
|
}
|
|
62471
62472
|
for (const st of steps) {
|
|
62472
62473
|
if (st.sel === "parent") {
|
|
62473
|
-
if (chain.length <= 1) return
|
|
62474
|
+
if (chain.length <= 1) return isWorld ? external() : { kind: "unresolved", reason: '".." above the document root' };
|
|
62474
62475
|
chain = chain.slice(0, -1);
|
|
62475
62476
|
continue;
|
|
62476
62477
|
}
|
|
@@ -62485,8 +62486,8 @@ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
|
|
|
62485
62486
|
continue;
|
|
62486
62487
|
}
|
|
62487
62488
|
}
|
|
62488
|
-
if (!node.entries) return
|
|
62489
|
-
return
|
|
62489
|
+
if (!node.entries) return isWorld ? external() : { kind: "unresolved", reason: "step into a node with no fields" };
|
|
62490
|
+
return isWorld ? external() : { kind: "unresolved", reason: `no ${st.sel === "key" ? `key "${st.name}"` : `index [${st.n}]`}` };
|
|
62490
62491
|
}
|
|
62491
62492
|
if (isPointer(entry.value)) {
|
|
62492
62493
|
if (visited.has(entry.value)) return { kind: "unresolved", reason: "pointer cycle" };
|
|
@@ -62631,6 +62632,71 @@ var Store = class {
|
|
|
62631
62632
|
throw e3;
|
|
62632
62633
|
}
|
|
62633
62634
|
}
|
|
62635
|
+
/** Patch the index for a SINGLE changed subtree instead of rebuilding the whole DB. `doc` is the
|
|
62636
|
+
* FULL, freshly-resolved document (the cached tree with the changed file's subtree spliced back
|
|
62637
|
+
* in and schemas re-applied) — correctness comes from resolving against the whole tree in
|
|
62638
|
+
* memory; speed comes from writing only the rows under `prefix` (the store path P of the changed
|
|
62639
|
+
* subtree). Every node/edge/dangling/file row whose owner lies under P is replaced; rows outside
|
|
62640
|
+
* P are left untouched (their resolution did not change). `files` is the re-walked manifest for
|
|
62641
|
+
* the subtree (POSIX paths under `relPrefix`).
|
|
62642
|
+
*
|
|
62643
|
+
* Returns false WITHOUT writing when the patch is not provably equal to a full rebuild: if any
|
|
62644
|
+
* external `ref`/`back` edge pointing INTO the subtree changed (a referenced node added/removed/
|
|
62645
|
+
* re-resolved), the caller must fall back to a full reindex. The boundary `contain` edge into P
|
|
62646
|
+
* (from P's parent, outside the subtree) is stable and intentionally left in place. */
|
|
62647
|
+
patchSubtree(doc, prefix, files, relPrefix) {
|
|
62648
|
+
const colon = prefix + ":";
|
|
62649
|
+
const brack = prefix + "[";
|
|
62650
|
+
const underP = (p2) => p2 === prefix || p2.startsWith(colon) || p2.startsWith(brack);
|
|
62651
|
+
const edges = resolveDocument(doc);
|
|
62652
|
+
const edgeKey = (from, to2, label, kind, pos) => JSON.stringify([from, to2, label, kind, pos]);
|
|
62653
|
+
const extInNew = edges.filter((r2) => r2.target.kind === "node" && underP(r2.target.path) && !underP(r2.holder)).map((r2) => edgeKey(r2.holder, r2.target.path, r2.label, r2.edge, r2.pos)).sort();
|
|
62654
|
+
const extInOld = this.db.prepare("SELECT from_path, to_path, label, kind, pos FROM edge WHERE kind IN ('ref','back')").all().filter((r2) => underP(r2.to_path) && !underP(r2.from_path)).map((r2) => edgeKey(r2.from_path, r2.to_path, r2.label ?? null, r2.kind, r2.pos ?? null)).sort();
|
|
62655
|
+
if (extInOld.length !== extInNew.length || extInOld.some((k, i2) => k !== extInNew[i2])) return false;
|
|
62656
|
+
const insNode = this.db.prepare(
|
|
62657
|
+
`INSERT INTO node (path, type, format, value, content_hash, size, is_array, meta)
|
|
62658
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
|
62659
|
+
);
|
|
62660
|
+
const insEdge = this.db.prepare(
|
|
62661
|
+
`INSERT INTO edge (from_path, to_path, label, kind, pos) VALUES (?, ?, ?, ?, ?)`
|
|
62662
|
+
);
|
|
62663
|
+
const insDangling = this.db.prepare("INSERT INTO dangling (from_path, raw, reason) VALUES (?, ?, ?)");
|
|
62664
|
+
const insFile = this.db.prepare("INSERT OR REPLACE INTO file (path, hash, size, mtime_ms) VALUES (?, ?, ?, ?)");
|
|
62665
|
+
this.db.exec("BEGIN");
|
|
62666
|
+
try {
|
|
62667
|
+
const delUnder = (col, table) => {
|
|
62668
|
+
this.db.prepare(`DELETE FROM ${table} WHERE ${col} = ? OR substr(${col},1,?) = ? OR substr(${col},1,?) = ?`).run(prefix, colon.length, colon, brack.length, brack);
|
|
62669
|
+
};
|
|
62670
|
+
delUnder("path", "node");
|
|
62671
|
+
delUnder("from_path", "edge");
|
|
62672
|
+
delUnder("from_path", "dangling");
|
|
62673
|
+
if (relPrefix) this.db.prepare("DELETE FROM file WHERE substr(path,1,?) = ?").run(relPrefix.length, relPrefix);
|
|
62674
|
+
walkNodes(doc.root, ":", (p2, node, parent, label, pos) => {
|
|
62675
|
+
if (!underP(p2)) return;
|
|
62676
|
+
const meta = node.meta ? JSON.stringify(node.meta) : null;
|
|
62677
|
+
const owned = node.entries?.filter((e3) => e3.edge !== "back") ?? [];
|
|
62678
|
+
const isArray = node.array || node.kind === "mapping" && owned.length > 0 && owned.every((e3) => e3.key === null);
|
|
62679
|
+
const value = node.kind === "scalar" ? JSON.stringify(node.value) : null;
|
|
62680
|
+
const format = node.kind === "blob" ? node.format : formatFromMeta(node);
|
|
62681
|
+
const hash = node.kind === "blob" ? node.contentHash : null;
|
|
62682
|
+
const size = node.kind === "blob" ? node.size : null;
|
|
62683
|
+
insNode.run(p2, node.kind, format, value, hash, size, isArray ? 1 : 0, meta);
|
|
62684
|
+
if (parent !== null && underP(parent)) insEdge.run(parent, p2, label, "contain", pos);
|
|
62685
|
+
});
|
|
62686
|
+
for (const r2 of edges) {
|
|
62687
|
+
if (!underP(r2.holder)) continue;
|
|
62688
|
+
if (r2.target.kind === "node") insEdge.run(r2.holder, r2.target.path, r2.label, r2.edge, r2.pos);
|
|
62689
|
+
else if (r2.target.kind === "unresolved") insDangling.run(r2.from, r2.raw, r2.target.reason);
|
|
62690
|
+
}
|
|
62691
|
+
for (const f2 of files) insFile.run(f2.path, f2.hash, f2.size, f2.mtimeMs);
|
|
62692
|
+
this.db.exec("COMMIT");
|
|
62693
|
+
this._stale = false;
|
|
62694
|
+
return true;
|
|
62695
|
+
} catch (e3) {
|
|
62696
|
+
this.db.exec("ROLLBACK");
|
|
62697
|
+
throw e3;
|
|
62698
|
+
}
|
|
62699
|
+
}
|
|
62634
62700
|
/** Incrementally add ONE annotation document at `annStorePath`, with a forward `target` ref edge
|
|
62635
62701
|
* to `targetStorePath` and (when given) a keyless `back` edge to `tagStorePath` — the applied
|
|
62636
62702
|
* tag's `~-` membership. This avoids a full re-walk/rebuild (which re-reads and re-hashes every
|
|
@@ -64312,15 +64378,16 @@ function* walkTreeGen(absDir, opts = {}) {
|
|
|
64312
64378
|
root.meta = { ...root.meta, documentRoot: true };
|
|
64313
64379
|
const defsRoot = findDefsRoot(absDir);
|
|
64314
64380
|
const defsDir = path.join(defsRoot, "$defs");
|
|
64381
|
+
const selfRoot = path.resolve(absDir) === defsRoot;
|
|
64315
64382
|
const arrayRoot = root.array || (root.entries?.length ? root.entries.every((e3) => e3.key === null) : false);
|
|
64316
64383
|
let builtinDefs;
|
|
64317
64384
|
if (!arrayRoot && root.entries && !root.entries.some((e3) => e3.key === "yamlover")) {
|
|
64318
|
-
if (fs.existsSync(defsDir)) {
|
|
64385
|
+
if (fs.existsSync(defsDir) && !selfRoot) {
|
|
64319
64386
|
const shared = [{ key: "$defs", edge: "contain", value: yield* dirNode(defsDir, ctx) }];
|
|
64320
64387
|
const tagsDir = path.join(defsRoot, "tags");
|
|
64321
64388
|
if (fs.existsSync(tagsDir)) shared.push({ key: "tags", edge: "contain", value: yield* dirNode(tagsDir, ctx) });
|
|
64322
64389
|
root.entries.push({ key: "yamlover", edge: "contain", value: { kind: "mapping", entries: shared, array: false } });
|
|
64323
|
-
} else {
|
|
64390
|
+
} else if (!fs.existsSync(defsDir)) {
|
|
64324
64391
|
const built = builtinYamloverGraft();
|
|
64325
64392
|
root.entries.push({ key: "yamlover", edge: "contain", value: built.node });
|
|
64326
64393
|
builtinDefs = built.defs;
|
|
@@ -64338,7 +64405,7 @@ function reindex(store, absDir, opts = {}) {
|
|
|
64338
64405
|
store.indexDocument(doc, files);
|
|
64339
64406
|
return diffManifest(prev, files);
|
|
64340
64407
|
}
|
|
64341
|
-
async function
|
|
64408
|
+
async function reindexAsyncDoc(store, absDir, opts = {}) {
|
|
64342
64409
|
const prev = store.stale ? /* @__PURE__ */ new Map() : store.manifest();
|
|
64343
64410
|
const onProgress = opts.onProgress;
|
|
64344
64411
|
const total = onProgress ? await countChildren(path.resolve(absDir), opts) : void 0;
|
|
@@ -64350,7 +64417,49 @@ async function reindexAsync(store, absDir, opts = {}) {
|
|
|
64350
64417
|
onProgress?.({ done: total ?? files.length, total, message: "writing index\u2026" });
|
|
64351
64418
|
await yieldLoop();
|
|
64352
64419
|
store.indexDocument(doc, files);
|
|
64353
|
-
return diffManifest(prev, files);
|
|
64420
|
+
return { diff: diffManifest(prev, files), doc, files };
|
|
64421
|
+
}
|
|
64422
|
+
async function reindexPathAsync(store, absDir, cachedDoc, changedRel, opts = {}) {
|
|
64423
|
+
const root = path.resolve(absDir);
|
|
64424
|
+
const parts = changedRel.split("/");
|
|
64425
|
+
const yi = parts.indexOf(YAMLOVER_DIR);
|
|
64426
|
+
const dirSegs = yi >= 0 ? parts.slice(0, yi) : parts.slice(0, -1);
|
|
64427
|
+
if (dirSegs.length === 0) return null;
|
|
64428
|
+
if (dirSegs[0] === "$defs" || dirSegs[0] === "tags") return null;
|
|
64429
|
+
let entries = cachedDoc.root.entries;
|
|
64430
|
+
let target = null;
|
|
64431
|
+
for (let d = 0; d < dirSegs.length; d++) {
|
|
64432
|
+
if (!entries) return null;
|
|
64433
|
+
const i2 = entries.findIndex((e3) => e3.key === dirSegs[d] && !isPointer(e3.value));
|
|
64434
|
+
if (i2 < 0) return null;
|
|
64435
|
+
if (d === dirSegs.length - 1) target = { arr: entries, i: i2 };
|
|
64436
|
+
else entries = entries[i2].value.entries;
|
|
64437
|
+
}
|
|
64438
|
+
if (!target) return null;
|
|
64439
|
+
const absSpliceDir = path.join(root, ...dirSegs);
|
|
64440
|
+
if (!fs.existsSync(absSpliceDir) || !fs.statSync(absSpliceDir).isDirectory()) return null;
|
|
64441
|
+
const prev = store.stale ? /* @__PURE__ */ new Map() : store.manifest();
|
|
64442
|
+
const ctx = { root, opts: { ...opts, cache: opts.cache ?? manifestCache(prev) }, files: /* @__PURE__ */ new Map(), count: 0 };
|
|
64443
|
+
const gen = dirNode(absSpliceDir, ctx);
|
|
64444
|
+
let r2 = gen.next();
|
|
64445
|
+
while (!r2.done) r2 = gen.next();
|
|
64446
|
+
target.arr[target.i].value = r2.value;
|
|
64447
|
+
applySchemas(cachedDoc.root, findDefsRoot(absDir), graftDefs(cachedDoc.root));
|
|
64448
|
+
const relPrefix = dirSegs.join("/") + "/";
|
|
64449
|
+
const P = ":" + dirSegs.join(":");
|
|
64450
|
+
const prevSub = new Map([...prev].filter(([k]) => k.startsWith(relPrefix)));
|
|
64451
|
+
const files = [...ctx.files.values()];
|
|
64452
|
+
const diff2 = diffManifest(prevSub, files);
|
|
64453
|
+
if (!store.patchSubtree(cachedDoc, P, files, relPrefix)) return null;
|
|
64454
|
+
return { diff: diff2, doc: cachedDoc };
|
|
64455
|
+
}
|
|
64456
|
+
function graftDefs(root) {
|
|
64457
|
+
const yam = root.entries?.find((e3) => e3.key === "yamlover" && !isPointer(e3.value))?.value;
|
|
64458
|
+
const defs = yam?.entries?.find((e3) => e3.key === "$defs" && !isPointer(e3.value))?.value;
|
|
64459
|
+
if (!defs?.entries) return void 0;
|
|
64460
|
+
const m = /* @__PURE__ */ new Map();
|
|
64461
|
+
for (const e3 of defs.entries) if (e3.key && !isPointer(e3.value)) m.set(e3.key, e3.value);
|
|
64462
|
+
return m.size ? m : void 0;
|
|
64354
64463
|
}
|
|
64355
64464
|
function manifestCache(prev) {
|
|
64356
64465
|
return (rel, size, mtimeMs) => {
|
|
@@ -64629,6 +64738,7 @@ function applySchemas(root, defsRoot, builtinDefs) {
|
|
|
64629
64738
|
const addl = field(s2, "additionalProperties");
|
|
64630
64739
|
for (const e3 of inst.entries ?? []) {
|
|
64631
64740
|
if (e3.key == null || isPointer(e3.value)) continue;
|
|
64741
|
+
if (e3.value.meta?.schema && isPointer(e3.value.meta.schema)) continue;
|
|
64632
64742
|
const declared = props && !isPointer(props) ? field(props, e3.key) : null;
|
|
64633
64743
|
const sub = declared ?? addl;
|
|
64634
64744
|
if (sub) apply(e3.value, sub, depth + 1);
|
|
@@ -65380,6 +65490,10 @@ function evalQuery(s2, text, from = ":") {
|
|
|
65380
65490
|
binds = [docRootOf(s2, from)];
|
|
65381
65491
|
break;
|
|
65382
65492
|
case "link": {
|
|
65493
|
+
if (q.base.authority === "yamlover" && childByKey(s2, ":", "yamlover") === null) {
|
|
65494
|
+
binds = [":"];
|
|
65495
|
+
break;
|
|
65496
|
+
}
|
|
65383
65497
|
const hit = childByKey(s2, ":", q.base.authority);
|
|
65384
65498
|
binds = hit === null ? [] : [hit];
|
|
65385
65499
|
break;
|
|
@@ -65994,6 +66108,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
65994
66108
|
fs9.mkdirSync(path9.dirname(dbPath), { recursive: true });
|
|
65995
66109
|
const store0 = new Store(dbPath);
|
|
65996
66110
|
const store = () => store0;
|
|
66111
|
+
let cachedDoc = null;
|
|
65997
66112
|
const log = opts.log ?? (() => {
|
|
65998
66113
|
});
|
|
65999
66114
|
let closed = false;
|
|
@@ -66099,14 +66214,32 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66099
66214
|
}
|
|
66100
66215
|
})();
|
|
66101
66216
|
};
|
|
66102
|
-
const doReindex = () =>
|
|
66217
|
+
const doReindex = async () => {
|
|
66218
|
+
const { diff: diff2, doc } = await reindexAsyncDoc(store0, dataRoot, { ignore: ignore2 });
|
|
66219
|
+
cachedDoc = doc;
|
|
66220
|
+
return diff2;
|
|
66221
|
+
};
|
|
66222
|
+
const doReindexFile = async (absFile) => {
|
|
66223
|
+
if (cachedDoc) {
|
|
66224
|
+
const rel = path9.relative(dataRoot, absFile).split(path9.sep).join("/");
|
|
66225
|
+
try {
|
|
66226
|
+
const res = await reindexPathAsync(store0, dataRoot, cachedDoc, rel, { ignore: ignore2 });
|
|
66227
|
+
if (res) {
|
|
66228
|
+
cachedDoc = res.doc;
|
|
66229
|
+
return res.diff;
|
|
66230
|
+
}
|
|
66231
|
+
} catch {
|
|
66232
|
+
}
|
|
66233
|
+
}
|
|
66234
|
+
return doReindex();
|
|
66235
|
+
};
|
|
66103
66236
|
const runIndexTask = (label) => enqueue(async () => {
|
|
66104
66237
|
const h = tasks.start(label);
|
|
66105
66238
|
const t0 = Date.now();
|
|
66106
66239
|
let lastLog = 0;
|
|
66107
66240
|
log(`${label}\u2026`);
|
|
66108
66241
|
try {
|
|
66109
|
-
const diff2 = await
|
|
66242
|
+
const { diff: diff2, doc } = await reindexAsyncDoc(store0, dataRoot, {
|
|
66110
66243
|
ignore: ignore2,
|
|
66111
66244
|
onProgress: (p2) => {
|
|
66112
66245
|
h.progress(p2.done, p2.total, p2.message);
|
|
@@ -66117,6 +66250,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66117
66250
|
}
|
|
66118
66251
|
}
|
|
66119
66252
|
});
|
|
66253
|
+
cachedDoc = doc;
|
|
66120
66254
|
h.done();
|
|
66121
66255
|
log(
|
|
66122
66256
|
`${label} done in ${((Date.now() - t0) / 1e3).toFixed(1)}s (+${diff2.added.length} ~${diff2.changed.length} \u2212${diff2.removed.length} \u2192${diff2.moved.length})`
|
|
@@ -66139,6 +66273,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66139
66273
|
if (r2.editedFiles.length > 0) {
|
|
66140
66274
|
const follow = reindex(store0, dataRoot, { ignore: ignore2 });
|
|
66141
66275
|
diff2.changed = [.../* @__PURE__ */ new Set([...diff2.changed, ...follow.changed])];
|
|
66276
|
+
cachedDoc = null;
|
|
66142
66277
|
}
|
|
66143
66278
|
}
|
|
66144
66279
|
h.done();
|
|
@@ -66202,8 +66337,8 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66202
66337
|
if (!a2?.tag || s2.node(tagStore)?.format !== TAG_FORMAT) {
|
|
66203
66338
|
throw new Error("annotation needs a `tag` that is an x-yamlover-tag node");
|
|
66204
66339
|
}
|
|
66205
|
-
embedAnnotation(dataRoot, s2, a2);
|
|
66206
|
-
broadcast(await
|
|
66340
|
+
const bodyFile = embedAnnotation(dataRoot, s2, a2);
|
|
66341
|
+
broadcast(await doReindexFile(bodyFile));
|
|
66207
66342
|
scheduleHasher();
|
|
66208
66343
|
return { ok: true };
|
|
66209
66344
|
})
|
|
@@ -66228,8 +66363,8 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66228
66363
|
const tag = url.searchParams.get("tag") || "";
|
|
66229
66364
|
enqueue(async () => {
|
|
66230
66365
|
if (!tag) throw new Error("delete needs a `tag`");
|
|
66231
|
-
unembedAnnotation(dataRoot, s2, target, tag);
|
|
66232
|
-
broadcast(await
|
|
66366
|
+
const bodyFile = unembedAnnotation(dataRoot, s2, target, tag);
|
|
66367
|
+
broadcast(await doReindexFile(bodyFile));
|
|
66233
66368
|
}).then(() => sendJson(res, 200, { ok: true })).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66234
66369
|
return;
|
|
66235
66370
|
}
|
|
@@ -66255,6 +66390,22 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66255
66390
|
).then((body) => sendJson(res, 201, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66256
66391
|
return;
|
|
66257
66392
|
}
|
|
66393
|
+
if (req.method === "POST" && url.pathname === "/api/board") {
|
|
66394
|
+
readBody(req).then(
|
|
66395
|
+
(data) => enqueue(async () => {
|
|
66396
|
+
const b = data;
|
|
66397
|
+
const cols = Array.isArray(b?.columns) ? b.columns.map((lane) => Array.isArray(lane) ? lane.map((p3) => String(p3)) : []) : [];
|
|
66398
|
+
const { bodyFile } = hostFor(dataRoot, s2, strToSegs(b?.path || ":"));
|
|
66399
|
+
fs9.mkdirSync(path9.dirname(bodyFile), { recursive: true });
|
|
66400
|
+
const src = fs9.existsSync(bodyFile) ? fs9.readFileSync(bodyFile, "utf8") : "";
|
|
66401
|
+
fs9.writeFileSync(bodyFile, writeBoardColumns(src, cols));
|
|
66402
|
+
broadcast(await doReindex());
|
|
66403
|
+
scheduleHasher();
|
|
66404
|
+
return { ok: true };
|
|
66405
|
+
})
|
|
66406
|
+
).then((body) => sendJson(res, 201, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66407
|
+
return;
|
|
66408
|
+
}
|
|
66258
66409
|
if (req.method === "POST" && url.pathname === "/api/paste") {
|
|
66259
66410
|
readBody(req).then(
|
|
66260
66411
|
(data) => enqueue(async () => {
|
|
@@ -66284,6 +66435,31 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66284
66435
|
).then((body) => sendJson(res, 200, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66285
66436
|
return;
|
|
66286
66437
|
}
|
|
66438
|
+
if (req.method === "POST" && url.pathname === "/api/agent-docs") {
|
|
66439
|
+
readBody(req).then(
|
|
66440
|
+
(data) => enqueue(async () => {
|
|
66441
|
+
const overwrite = !!data?.overwrite;
|
|
66442
|
+
const files = [];
|
|
66443
|
+
let wrote = false;
|
|
66444
|
+
for (const doc of loadAgentDocs()) {
|
|
66445
|
+
const exists = fs9.existsSync(path9.resolve(dataRoot, doc.name));
|
|
66446
|
+
if (exists && !overwrite) {
|
|
66447
|
+
files.push({ name: doc.name, status: "exists" });
|
|
66448
|
+
continue;
|
|
66449
|
+
}
|
|
66450
|
+
writeInside(dataRoot, dataRoot, doc.name, Buffer.from(doc.content, "utf8"));
|
|
66451
|
+
files.push({ name: doc.name, status: exists ? "overwritten" : "created" });
|
|
66452
|
+
wrote = true;
|
|
66453
|
+
}
|
|
66454
|
+
if (wrote) {
|
|
66455
|
+
broadcast(await doReindex());
|
|
66456
|
+
scheduleHasher();
|
|
66457
|
+
}
|
|
66458
|
+
return { files };
|
|
66459
|
+
})
|
|
66460
|
+
).then((body) => sendJson(res, 201, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66461
|
+
return;
|
|
66462
|
+
}
|
|
66287
66463
|
const segs = strToSegs(url.searchParams.get("path") || ":");
|
|
66288
66464
|
const p2 = storePath(segs);
|
|
66289
66465
|
const depth = parseDepth(url.searchParams.get("depth"));
|
|
@@ -66350,7 +66526,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66350
66526
|
const viewDepth = depth ?? 1;
|
|
66351
66527
|
const kind = displayKind(s2, p2, row);
|
|
66352
66528
|
if (url.pathname === "/api/json") {
|
|
66353
|
-
const wantBytes =
|
|
66529
|
+
const wantBytes = row.type === "blob" && url.searchParams.get("binary") === "1";
|
|
66354
66530
|
sendJson(res, 200, {
|
|
66355
66531
|
path: segsToStr(segs),
|
|
66356
66532
|
type: tocType(s2, p2, row),
|
|
@@ -66389,7 +66565,19 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66389
66565
|
function tocType(s2, p2, row) {
|
|
66390
66566
|
return typeName(s2, p2, row);
|
|
66391
66567
|
}
|
|
66568
|
+
var JSON_EXT = { ".json": "json", ".json5": "json5", ".json5p": "json5p" };
|
|
66392
66569
|
function concreteOf(dataRoot, segs, row) {
|
|
66570
|
+
const last = segs[segs.length - 1];
|
|
66571
|
+
if (typeof last === "string") {
|
|
66572
|
+
const json = JSON_EXT[path9.extname(last).toLowerCase()];
|
|
66573
|
+
if (json) {
|
|
66574
|
+
const abs2 = path9.resolve(dataRoot, ...segs.map(String));
|
|
66575
|
+
try {
|
|
66576
|
+
if (fs9.statSync(abs2).isFile()) return json;
|
|
66577
|
+
} catch {
|
|
66578
|
+
}
|
|
66579
|
+
}
|
|
66580
|
+
}
|
|
66393
66581
|
if (row.type !== "mapping") return null;
|
|
66394
66582
|
if (segs.some((g) => typeof g === "number")) return null;
|
|
66395
66583
|
const abs = path9.resolve(dataRoot, ...segs.map(String));
|
|
@@ -66645,6 +66833,21 @@ function pointerRaw(clientPath) {
|
|
|
66645
66833
|
}
|
|
66646
66834
|
return "::" + out;
|
|
66647
66835
|
}
|
|
66836
|
+
function writeBoardColumns(src, cols) {
|
|
66837
|
+
const laneLine = (lane) => `- [${lane.map((p2) => pointerToken(pointerRaw(p2))).join(", ")}]`;
|
|
66838
|
+
const block = cols.length === 0 ? ["columns: []"] : ["columns:", ...cols.map(laneLine)];
|
|
66839
|
+
let lines = src.replace(/\n+$/, "").split("\n");
|
|
66840
|
+
if (src.trim() === "") lines = ["!!<*yamlover:$defs:board>"];
|
|
66841
|
+
const start = lines.findIndex((l2) => /^columns:/.test(l2));
|
|
66842
|
+
if (start >= 0) {
|
|
66843
|
+
let end = start + 1;
|
|
66844
|
+
while (end < lines.length && (lines[end] === "" || /^[ \t-]/.test(lines[end]))) end++;
|
|
66845
|
+
lines.splice(start, end - start, ...block);
|
|
66846
|
+
} else {
|
|
66847
|
+
lines.push(...block);
|
|
66848
|
+
}
|
|
66849
|
+
return lines.join("\n") + "\n";
|
|
66850
|
+
}
|
|
66648
66851
|
function sidecarTarget(dataRoot, mode, subdir, bodyFile) {
|
|
66649
66852
|
const dirOverlay = bodyFile.endsWith(path9.join(".yamlover", "body.yamlover"));
|
|
66650
66853
|
if (mode === "per-directory" && dirOverlay) {
|
|
@@ -66704,6 +66907,7 @@ function embedAnnotation(dataRoot, s2, a2) {
|
|
|
66704
66907
|
fs9.mkdirSync(path9.dirname(bodyFile), { recursive: true });
|
|
66705
66908
|
const src = fs9.existsSync(bodyFile) ? fs9.readFileSync(bodyFile, "utf8") : "";
|
|
66706
66909
|
fs9.writeFileSync(bodyFile, appendAnnotation(src, within, (indent) => annotationItemLines(a2, indent)));
|
|
66910
|
+
return bodyFile;
|
|
66707
66911
|
}
|
|
66708
66912
|
function embedFragment(dataRoot, s2, mode, f2) {
|
|
66709
66913
|
const segs = strToSegs(f2.target || ":");
|
|
@@ -66760,10 +66964,11 @@ async function ensureThumbnail(dataRoot, s2, mode, segs, row, w, h) {
|
|
|
66760
66964
|
}
|
|
66761
66965
|
function unembedAnnotation(dataRoot, s2, target, tag) {
|
|
66762
66966
|
const { bodyFile, within } = hostFor(dataRoot, s2, strToSegs(target || ":"));
|
|
66763
|
-
if (!fs9.existsSync(bodyFile)) return;
|
|
66764
|
-
const
|
|
66967
|
+
if (!fs9.existsSync(bodyFile)) return bodyFile;
|
|
66968
|
+
const needlePath = ":" + pointerRaw(tag).replace(/^:+/, "");
|
|
66765
66969
|
const src = fs9.readFileSync(bodyFile, "utf8");
|
|
66766
|
-
fs9.writeFileSync(bodyFile, removeAnnotation(src, within, (itemText) => itemText.includes(
|
|
66970
|
+
fs9.writeFileSync(bodyFile, removeAnnotation(src, within, (itemText) => itemText.replace(/\s+/g, "").includes(needlePath)));
|
|
66971
|
+
return bodyFile;
|
|
66767
66972
|
}
|
|
66768
66973
|
function writeTag(dataRoot, location, name) {
|
|
66769
66974
|
if (/[/\\\r\n:]/.test(name)) throw new Error("a tag name cannot contain '/', '\\', ':' or line breaks");
|
|
@@ -66980,6 +67185,17 @@ function writeInside(dataRoot, dir, name, bytes) {
|
|
|
66980
67185
|
if (target !== root && !target.startsWith(root + path9.sep)) throw new Error("target escapes the data root");
|
|
66981
67186
|
fs9.writeFileSync(target, bytes);
|
|
66982
67187
|
}
|
|
67188
|
+
var AGENT_DOCS_DIR = path9.join(path9.dirname(fileURLToPath2(import.meta.url)), "agent-docs");
|
|
67189
|
+
function loadAgentDocs() {
|
|
67190
|
+
let names3;
|
|
67191
|
+
try {
|
|
67192
|
+
names3 = fs9.readdirSync(AGENT_DOCS_DIR).filter((f2) => f2.endsWith(".md")).sort();
|
|
67193
|
+
} catch {
|
|
67194
|
+
throw new Error(`agent-docs resources not found at ${AGENT_DOCS_DIR}`);
|
|
67195
|
+
}
|
|
67196
|
+
if (names3.length === 0) throw new Error(`no agent-docs resources at ${AGENT_DOCS_DIR}`);
|
|
67197
|
+
return names3.map((name) => ({ name, content: fs9.readFileSync(path9.join(AGENT_DOCS_DIR, name), "utf8") }));
|
|
67198
|
+
}
|
|
66983
67199
|
var indentOf2 = (line) => {
|
|
66984
67200
|
let i2 = 0;
|
|
66985
67201
|
while (line[i2] === " ") i2++;
|