superbee 0.4.6-pre.1 → 0.4.6-pre.3
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/README.md +7 -2
- package/SKILL.md +13 -5
- package/dist/THIRD-PARTY-NOTICES.txt +2 -2
- package/dist/portable-export.mjs +1 -1
- package/dist/publication/types.d.ts +8 -0
- package/dist/publication-bridge.mjs +330 -144
- package/dist/publication.mjs +347 -146
- package/dist/superbee.mjs +84205 -78550
- package/package.json +2 -2
- package/references/hosted-checkout.md +1 -1
- package/references/modeling-and-delivery.md +1 -1
- package/references/recipes/review-workflow/references/view-authoring-v0.md +1 -2
- package/references/views/references/view-authoring-v0.md +1 -2
package/dist/publication.mjs
CHANGED
|
@@ -30844,15 +30844,30 @@ var FrontmatterRefusedError = class extends InvalidInputError {
|
|
|
30844
30844
|
}
|
|
30845
30845
|
};
|
|
30846
30846
|
var FilesystemIdentityAliasError = class extends InvalidInputError {
|
|
30847
|
+
reason = "filesystem_alias";
|
|
30847
30848
|
rel;
|
|
30848
30849
|
segment;
|
|
30849
|
-
|
|
30850
|
+
existing;
|
|
30851
|
+
suggestedPath;
|
|
30852
|
+
/**
|
|
30853
|
+
* `noun` names the existing entry ("folder" or "file"); `index` is the position of `segment`
|
|
30854
|
+
* in `rel`. Both default from the position of the first segment spelled `segment`.
|
|
30855
|
+
*/
|
|
30856
|
+
constructor(rel, segment, existing, noun, index2) {
|
|
30857
|
+
const segments = rel.split("/").filter((part) => part !== "" && part !== ".");
|
|
30858
|
+
const at = index2 ?? segments.indexOf(segment);
|
|
30859
|
+
const kind2 = noun ?? (at === segments.length - 1 ? "file" : "folder");
|
|
30860
|
+
const clash = existing === void 0 ? `but a ${kind2} with that name in a different case or Unicode form already exists` : existing.normalize("NFC") === segment.normalize("NFC") ? `but ${kind2} '${existing}' already exists, written in a different Unicode form` : `but ${kind2} '${existing}' already exists`;
|
|
30861
|
+
const difference = existing === void 0 ? "case or Unicode form" : existing.normalize("NFC") === segment.normalize("NFC") ? "Unicode form" : existing.toLowerCase() === segment.toLowerCase() ? "case" : "case and Unicode form";
|
|
30850
30862
|
super(
|
|
30851
|
-
`Path '${rel}'
|
|
30863
|
+
`Path '${rel}' uses ${kind2} '${segment}', ${clash}, and this disk treats names that differ only by ${difference} as the same name. Use the existing spelling.`
|
|
30852
30864
|
);
|
|
30853
30865
|
this.name = "FilesystemIdentityAliasError";
|
|
30854
30866
|
this.rel = rel;
|
|
30855
30867
|
this.segment = segment;
|
|
30868
|
+
this.existing = existing;
|
|
30869
|
+
const unusable = existing === void 0 || at < 0 || segments[at] !== segment || kind2 === "file" && at < segments.length - 1 || existing.normalize("NFC") === segment.normalize("NFC");
|
|
30870
|
+
this.suggestedPath = unusable ? void 0 : segments.map((part, position2) => position2 === at ? existing : part).join("/");
|
|
30856
30871
|
}
|
|
30857
30872
|
};
|
|
30858
30873
|
var ConcurrentReplacementError = class extends Error {
|
|
@@ -31057,6 +31072,9 @@ function delimiterLineEnd(input, offset) {
|
|
|
31057
31072
|
if (input[suffix] === "\r" && input[suffix + 1] === "\n") return suffix + 2;
|
|
31058
31073
|
return null;
|
|
31059
31074
|
}
|
|
31075
|
+
function startsWithFrontmatterSyntax(text4) {
|
|
31076
|
+
return text4.startsWith("\uFEFF") || delimiterLineEnd(text4, 0) !== null;
|
|
31077
|
+
}
|
|
31060
31078
|
function splitLeadingFrontmatter(raw, context) {
|
|
31061
31079
|
const input = raw.startsWith("\uFEFF") ? raw.slice(1) : raw;
|
|
31062
31080
|
const openingEnd = delimiterLineEnd(input, 0);
|
|
@@ -31162,7 +31180,10 @@ function stringifyWithSerializedFrontmatter(dumped, body) {
|
|
|
31162
31180
|
const content3 = body ?? "";
|
|
31163
31181
|
const newline = (value) => value.endsWith("\n") ? value : `${value}
|
|
31164
31182
|
`;
|
|
31165
|
-
if (dumped === "{}")
|
|
31183
|
+
if (dumped === "{}") {
|
|
31184
|
+
const stored = normalizeDocumentBodyForStorage(content3);
|
|
31185
|
+
return `${startsWithFrontmatterSyntax(stored) ? "---\n---\n" : ""}${stored}`;
|
|
31186
|
+
}
|
|
31166
31187
|
return `---
|
|
31167
31188
|
${newline(dumped)}---
|
|
31168
31189
|
${normalizeDocumentBodyForStorage(content3)}`;
|
|
@@ -31605,6 +31626,8 @@ function extractMarkdownLinkSpans(source, options = {}) {
|
|
|
31605
31626
|
const body = options.skipCode ? maskMarkdownCode(source) : source;
|
|
31606
31627
|
const out = [];
|
|
31607
31628
|
let textOpen = -1;
|
|
31629
|
+
let codeOpen = -1;
|
|
31630
|
+
let masked;
|
|
31608
31631
|
let afterClose;
|
|
31609
31632
|
let hrefFirst;
|
|
31610
31633
|
let hrefRest;
|
|
@@ -31623,6 +31646,7 @@ function extractMarkdownLinkSpans(source, options = {}) {
|
|
|
31623
31646
|
image
|
|
31624
31647
|
});
|
|
31625
31648
|
textOpen = -1;
|
|
31649
|
+
codeOpen = -1;
|
|
31626
31650
|
afterClose = void 0;
|
|
31627
31651
|
hrefFirst = void 0;
|
|
31628
31652
|
hrefRest = void 0;
|
|
@@ -31643,10 +31667,22 @@ function extractMarkdownLinkSpans(source, options = {}) {
|
|
|
31643
31667
|
afterClose = void 0;
|
|
31644
31668
|
}
|
|
31645
31669
|
if (textOpen >= 0 && char === "]") {
|
|
31646
|
-
|
|
31670
|
+
const open = codeOpen >= 0 && masked[cursor] !== "]" ? codeOpen : textOpen;
|
|
31671
|
+
afterClose = { open, close: cursor };
|
|
31647
31672
|
textOpen = -1;
|
|
31673
|
+
codeOpen = -1;
|
|
31674
|
+
}
|
|
31675
|
+
if (char === "[") {
|
|
31676
|
+
if (textOpen >= 0 && !options.skipCode) {
|
|
31677
|
+
masked ??= maskMarkdownCode(source);
|
|
31678
|
+
if (masked[cursor] !== "[" && masked[textOpen] === "[") {
|
|
31679
|
+
codeOpen = cursor;
|
|
31680
|
+
continue;
|
|
31681
|
+
}
|
|
31682
|
+
}
|
|
31683
|
+
textOpen = cursor;
|
|
31684
|
+
codeOpen = -1;
|
|
31648
31685
|
}
|
|
31649
|
-
if (char === "[" && textOpen < 0) textOpen = cursor;
|
|
31650
31686
|
}
|
|
31651
31687
|
return out;
|
|
31652
31688
|
}
|
|
@@ -31980,36 +32016,57 @@ function hasSourceIdentity(sources, identity) {
|
|
|
31980
32016
|
return Array.isArray(sources) && sources.some((entry) => matchesSourceIdentity(entry, identity));
|
|
31981
32017
|
}
|
|
31982
32018
|
|
|
32019
|
+
// ../core/src/skip-reasons.ts
|
|
32020
|
+
var PERMISSION_DENIED_PREFIX = "permission denied (";
|
|
32021
|
+
function permissionDeniedReason(code2) {
|
|
32022
|
+
return `${PERMISSION_DENIED_PREFIX}${code2})`;
|
|
32023
|
+
}
|
|
32024
|
+
function isPermissionDeniedSkip(skip) {
|
|
32025
|
+
return skip.reason.startsWith(PERMISSION_DENIED_PREFIX);
|
|
32026
|
+
}
|
|
32027
|
+
|
|
31983
32028
|
// ../core/src/document-scan.ts
|
|
31984
32029
|
function isEnoent(err) {
|
|
31985
32030
|
return typeof err === "object" && err !== null && err.code === "ENOENT";
|
|
31986
32031
|
}
|
|
31987
|
-
|
|
31988
|
-
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
|
|
31992
|
-
|
|
31993
|
-
|
|
31994
|
-
|
|
31995
|
-
|
|
31996
|
-
|
|
31997
|
-
|
|
31998
|
-
|
|
31999
|
-
|
|
32000
|
-
|
|
32001
|
-
onMalformed({ id, reason: candidate.detail });
|
|
32002
|
-
continue;
|
|
32003
|
-
}
|
|
32004
|
-
if (candidate instanceof FilesystemIdentityAliasError && onAliased) {
|
|
32005
|
-
onAliased({ id, reason: candidate.message });
|
|
32006
|
-
continue;
|
|
32007
|
-
}
|
|
32008
|
-
throw candidate;
|
|
32032
|
+
function deniedReason(err) {
|
|
32033
|
+
const code2 = typeof err === "object" && err !== null ? err.code : void 0;
|
|
32034
|
+
return code2 === "EACCES" || code2 === "EPERM" ? permissionDeniedReason(code2) : void 0;
|
|
32035
|
+
}
|
|
32036
|
+
async function readManyExisting(backend, ids, onMalformed, onAliased, onDenied) {
|
|
32037
|
+
const tolerated = (err) => isEnoent(err) || err instanceof MalformedDocumentError && onMalformed !== void 0 || err instanceof FilesystemIdentityAliasError && onAliased !== void 0 || deniedReason(err) !== void 0 && onDenied !== void 0;
|
|
32038
|
+
const readOne = async (id) => {
|
|
32039
|
+
try {
|
|
32040
|
+
return [await backend.read(id)];
|
|
32041
|
+
} catch (candidate) {
|
|
32042
|
+
if (isEnoent(candidate)) return [];
|
|
32043
|
+
if (candidate instanceof MalformedDocumentError && onMalformed) {
|
|
32044
|
+
onMalformed({ id, reason: candidate.detail });
|
|
32045
|
+
return [];
|
|
32009
32046
|
}
|
|
32047
|
+
if (candidate instanceof FilesystemIdentityAliasError && onAliased) {
|
|
32048
|
+
onAliased({ id, reason: candidate.message });
|
|
32049
|
+
return [];
|
|
32050
|
+
}
|
|
32051
|
+
const reason = deniedReason(candidate);
|
|
32052
|
+
if (reason !== void 0 && onDenied) {
|
|
32053
|
+
onDenied({ id, reason });
|
|
32054
|
+
return [];
|
|
32055
|
+
}
|
|
32056
|
+
throw candidate;
|
|
32010
32057
|
}
|
|
32011
|
-
|
|
32012
|
-
|
|
32058
|
+
};
|
|
32059
|
+
const readBatch = async (batch) => {
|
|
32060
|
+
try {
|
|
32061
|
+
return await backend.readMany(batch);
|
|
32062
|
+
} catch (err) {
|
|
32063
|
+
if (!tolerated(err)) throw err;
|
|
32064
|
+
if (batch.length === 1) return readOne(batch[0]);
|
|
32065
|
+
const half = Math.ceil(batch.length / 2);
|
|
32066
|
+
return [...await readBatch(batch.slice(0, half)), ...await readBatch(batch.slice(half))];
|
|
32067
|
+
}
|
|
32068
|
+
};
|
|
32069
|
+
return readBatch(ids);
|
|
32013
32070
|
}
|
|
32014
32071
|
|
|
32015
32072
|
// ../core/src/engine.ts
|
|
@@ -32033,7 +32090,7 @@ async function readDocVersioned(backend, id) {
|
|
|
32033
32090
|
async function scanMatching(backend, filter, onSkip) {
|
|
32034
32091
|
const ids = await backend.list(filter.prefix);
|
|
32035
32092
|
const results = [];
|
|
32036
|
-
for (const result of await readManyExisting(backend, ids, onSkip)) {
|
|
32093
|
+
for (const result of await readManyExisting(backend, ids, onSkip, void 0, onSkip)) {
|
|
32037
32094
|
if (matchesFilter(result.doc, filter)) results.push(result);
|
|
32038
32095
|
}
|
|
32039
32096
|
results.sort((a, b) => compareCodeUnits(a.doc.id, b.doc.id));
|
|
@@ -32158,7 +32215,7 @@ function assertStorableReservedWrite(dir, name, content3) {
|
|
|
32158
32215
|
// ../core/src/filesystem-identity.ts
|
|
32159
32216
|
import { promises as fs2 } from "node:fs";
|
|
32160
32217
|
import path2 from "node:path";
|
|
32161
|
-
import { createHash as createHash2
|
|
32218
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
32162
32219
|
|
|
32163
32220
|
// ../core/src/filesystem-lock.ts
|
|
32164
32221
|
import { promises as fs, realpathSync } from "node:fs";
|
|
@@ -32213,6 +32270,8 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
32213
32270
|
var OWNER_FILE = "owner.json";
|
|
32214
32271
|
var DEFAULT_WAIT_MS = 5e3;
|
|
32215
32272
|
var DEFAULT_POLL_MS = 25;
|
|
32273
|
+
var UNREADABLE_OWNER_POLL_MS = 2e3;
|
|
32274
|
+
var ABANDONED_CLAIM_AGE_MS = 2e3;
|
|
32216
32275
|
var FilesystemMutationLockError = class extends Error {
|
|
32217
32276
|
lockPath;
|
|
32218
32277
|
owner;
|
|
@@ -32300,9 +32359,13 @@ async function readOwnerRecord(lockPath) {
|
|
|
32300
32359
|
return owner === null ? { state: "absent" } : { state: "record", owner };
|
|
32301
32360
|
}
|
|
32302
32361
|
async function resolveOwnerRecord(lockPath, started, waitMs, pollMs) {
|
|
32362
|
+
let firstUnreadable;
|
|
32303
32363
|
while (true) {
|
|
32304
32364
|
const record3 = await readOwnerRecord(lockPath);
|
|
32305
|
-
if (record3.state !== "unreadable"
|
|
32365
|
+
if (record3.state !== "unreadable") return record3;
|
|
32366
|
+
const now = Date.now();
|
|
32367
|
+
firstUnreadable ??= now;
|
|
32368
|
+
if (now - started >= waitMs || now - firstUnreadable >= UNREADABLE_OWNER_POLL_MS) return record3;
|
|
32306
32369
|
await delay(pollMs);
|
|
32307
32370
|
}
|
|
32308
32371
|
}
|
|
@@ -32353,6 +32416,17 @@ async function quarantineStaleLock(lockPath, owner, policy) {
|
|
|
32353
32416
|
throw err;
|
|
32354
32417
|
}
|
|
32355
32418
|
}
|
|
32419
|
+
async function removeAbandonedClaim(lockPath) {
|
|
32420
|
+
try {
|
|
32421
|
+
const info = await fs.lstat(lockPath);
|
|
32422
|
+
const age = Date.now() - info.mtimeMs;
|
|
32423
|
+
if (!info.isDirectory() || age < ABANDONED_CLAIM_AGE_MS) return false;
|
|
32424
|
+
await fs.rmdir(lockPath);
|
|
32425
|
+
return true;
|
|
32426
|
+
} catch {
|
|
32427
|
+
return false;
|
|
32428
|
+
}
|
|
32429
|
+
}
|
|
32356
32430
|
function delay(ms) {
|
|
32357
32431
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
32358
32432
|
}
|
|
@@ -32403,7 +32477,7 @@ async function timeoutError(lockPath, snapshot, guarded) {
|
|
|
32403
32477
|
const sameHost = owner?.hostname === hostname();
|
|
32404
32478
|
let message;
|
|
32405
32479
|
if (malformed) {
|
|
32406
|
-
message = `timed out waiting for filesystem mutation lock '${lockPath}'; its owner metadata is missing or malformed.
|
|
32480
|
+
message = `timed out waiting for filesystem mutation lock '${lockPath}'; its owner metadata is missing or malformed. Remove the lock directory once no Superbee process is running, then retry.`;
|
|
32407
32481
|
} else if (stale) {
|
|
32408
32482
|
message = `stale filesystem mutation lock '${lockPath}' belongs to absent PID ${owner.pid} on ${owner.hostname}. Inspect and remove the lock, then retry.`;
|
|
32409
32483
|
} else if (!sameHost) {
|
|
@@ -32452,7 +32526,9 @@ async function claimLockPath(lockPath, owner, waitMs, pollMs, policy) {
|
|
|
32452
32526
|
} else {
|
|
32453
32527
|
unwitnessedRetryUsed = false;
|
|
32454
32528
|
}
|
|
32455
|
-
|
|
32529
|
+
const existing = await readOwnerRecord(lockPath);
|
|
32530
|
+
let existingOwner = existing.state === "record" ? existing.owner : null;
|
|
32531
|
+
if (existing.state === "absent" && await removeAbandonedClaim(lockPath)) continue;
|
|
32456
32532
|
if (existingOwner !== null) {
|
|
32457
32533
|
if (await quarantineStaleLock(lockPath, existingOwner, policy)) continue;
|
|
32458
32534
|
existingOwner = await readOwner(lockPath);
|
|
@@ -32472,14 +32548,13 @@ async function claimLockPath(lockPath, owner, waitMs, pollMs, policy) {
|
|
|
32472
32548
|
});
|
|
32473
32549
|
} catch (err) {
|
|
32474
32550
|
const code2 = err.code;
|
|
32475
|
-
if (code2 === "EEXIST") {
|
|
32551
|
+
if (code2 === "EEXIST" || code2 === "ENOENT" || code2 === "ENOTDIR" || await claimDirectoryLost(lockPath, claimed)) {
|
|
32476
32552
|
heldTokens.delete(owner.token);
|
|
32477
32553
|
continue;
|
|
32478
32554
|
}
|
|
32479
32555
|
await rollBackOwnClaim(lockPath, owner, claimed, waitMs, pollMs, policy).catch(() => {
|
|
32480
32556
|
});
|
|
32481
32557
|
heldTokens.delete(owner.token);
|
|
32482
|
-
if (code2 === "ENOENT" || code2 === "ENOTDIR") continue;
|
|
32483
32558
|
throw err;
|
|
32484
32559
|
}
|
|
32485
32560
|
let inFlight;
|
|
@@ -32509,9 +32584,18 @@ async function rollBackOwnClaim(lockPath, owner, claimed, waitMs, pollMs, policy
|
|
|
32509
32584
|
return;
|
|
32510
32585
|
}
|
|
32511
32586
|
if (record3.state === "unreadable" || !await isClaimedDirectory(lockPath, claimed)) return;
|
|
32512
|
-
|
|
32513
|
-
|
|
32514
|
-
|
|
32587
|
+
await fs.rmdir(lockPath);
|
|
32588
|
+
}
|
|
32589
|
+
async function claimDirectoryLost(lockPath, claimed) {
|
|
32590
|
+
try {
|
|
32591
|
+
const current = await fs.lstat(lockPath, { bigint: true });
|
|
32592
|
+
if (claimed === null) return false;
|
|
32593
|
+
const reborn = claimed.birthtimeNs > 0n && current.birthtimeNs > 0n && current.birthtimeNs !== claimed.birthtimeNs;
|
|
32594
|
+
return current.dev !== claimed.dev || current.ino !== claimed.ino || reborn;
|
|
32595
|
+
} catch (err) {
|
|
32596
|
+
const code2 = err.code;
|
|
32597
|
+
return code2 === "ENOENT" || code2 === "ENOTDIR";
|
|
32598
|
+
}
|
|
32515
32599
|
}
|
|
32516
32600
|
async function isClaimedDirectory(lockPath, claimed) {
|
|
32517
32601
|
if (claimed === null || claimed.birthtimeNs <= 0n) return false;
|
|
@@ -32608,9 +32692,20 @@ async function acquireFilesystemIdentityLock(key, identity, options = {}) {
|
|
|
32608
32692
|
return claimLockPath(path.join(lockRoot, `${key}.lock`), owner, waitMs, pollMs, policy);
|
|
32609
32693
|
}
|
|
32610
32694
|
|
|
32695
|
+
// ../core/src/path-fold.ts
|
|
32696
|
+
function foldPath(path6) {
|
|
32697
|
+
return path6.normalize("NFD").toLowerCase().toUpperCase().toLowerCase().normalize("NFC");
|
|
32698
|
+
}
|
|
32699
|
+
|
|
32611
32700
|
// ../core/src/identity-fold.ts
|
|
32612
32701
|
function foldSegment(segment) {
|
|
32613
|
-
return segment.normalize("
|
|
32702
|
+
return foldPath(segment).normalize("NFD");
|
|
32703
|
+
}
|
|
32704
|
+
|
|
32705
|
+
// ../core/src/filesystem-temp-name.ts
|
|
32706
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
32707
|
+
function identityTempName(leaf) {
|
|
32708
|
+
return `.${leaf}.${process.pid}.${Date.now()}.${randomUUID2()}.tmp`;
|
|
32614
32709
|
}
|
|
32615
32710
|
|
|
32616
32711
|
// ../core/src/filesystem-identity.ts
|
|
@@ -32676,7 +32771,10 @@ async function existingAnchor(resolved) {
|
|
|
32676
32771
|
async function foldedPhysicalRoot(root) {
|
|
32677
32772
|
const { anchor, tail } = await existingAnchor(path2.resolve(root));
|
|
32678
32773
|
const anchorSegments = anchor.split(path2.sep).filter((segment, index2) => index2 === 0 || segment !== "");
|
|
32679
|
-
return [...anchorSegments, ...tail].map(
|
|
32774
|
+
return [...anchorSegments, ...tail].map(foldRootSegment).join("/");
|
|
32775
|
+
}
|
|
32776
|
+
function foldRootSegment(segment) {
|
|
32777
|
+
return segment.normalize("NFKD").toLowerCase().toUpperCase().toLowerCase();
|
|
32680
32778
|
}
|
|
32681
32779
|
async function identityKey(root, rel) {
|
|
32682
32780
|
const foldedRel = relSegments(rel).map(foldSegment).join("/");
|
|
@@ -32757,10 +32855,32 @@ async function probeSegment(port, candidate, rel, segment) {
|
|
|
32757
32855
|
function hasExact(listing, segment) {
|
|
32758
32856
|
return listing.some((entry) => entry.name === segment);
|
|
32759
32857
|
}
|
|
32858
|
+
function existingSpelling(names, segment) {
|
|
32859
|
+
const folded = foldSegment(segment);
|
|
32860
|
+
const matches = [...names].filter((name) => name !== segment && foldSegment(name) === folded);
|
|
32861
|
+
return matches.length === 1 ? matches[0] : void 0;
|
|
32862
|
+
}
|
|
32863
|
+
function entryNoun(kind2, leaf) {
|
|
32864
|
+
if (kind2 === void 0) return leaf ? "file" : "folder";
|
|
32865
|
+
return kind2 === "directory" ? "folder" : "file";
|
|
32866
|
+
}
|
|
32867
|
+
function aliasRefusal(rel, segments, index2, names, kind2) {
|
|
32868
|
+
const segment = segments[index2];
|
|
32869
|
+
return new FilesystemIdentityAliasError(rel, segment, existingSpelling(names, segment), entryNoun(kind2, index2 === segments.length - 1), index2);
|
|
32870
|
+
}
|
|
32871
|
+
function aliasRefusalFromListing(rel, index2, listing, leaf) {
|
|
32872
|
+
const segment = relSegments(rel)[index2];
|
|
32873
|
+
const existing = existingSpelling(listing.map((entry) => entry.name), segment);
|
|
32874
|
+
const kind2 = existing === void 0 ? void 0 : listing.find((entry) => entry.name === existing)?.kind;
|
|
32875
|
+
return new FilesystemIdentityAliasError(rel, segment, existing, entryNoun(kind2, leaf), index2);
|
|
32876
|
+
}
|
|
32877
|
+
function listingView(names) {
|
|
32878
|
+
return { has: (name) => names.has(name), names: () => names };
|
|
32879
|
+
}
|
|
32760
32880
|
function freshListings(port) {
|
|
32761
32881
|
return async (dir) => {
|
|
32762
32882
|
const listing = await port.entries(dir);
|
|
32763
|
-
return listing === null ? null : { has: (name) => hasExact(listing, name) };
|
|
32883
|
+
return listing === null ? null : { has: (name) => hasExact(listing, name), names: () => listing.map((entry) => entry.name) };
|
|
32764
32884
|
};
|
|
32765
32885
|
}
|
|
32766
32886
|
async function walkExact(port, rootResolved, segments, rel) {
|
|
@@ -32772,7 +32892,7 @@ async function walkExact(port, rootResolved, segments, rel) {
|
|
|
32772
32892
|
if (probed === null) return { state: "absent", depth: index2 };
|
|
32773
32893
|
const listing = await port.entries(parent);
|
|
32774
32894
|
if (listing === null) return { state: "absent", depth: index2 };
|
|
32775
|
-
if (!hasExact(listing, segment)) throw
|
|
32895
|
+
if (!hasExact(listing, segment)) throw aliasRefusal(rel, segments, index2, listing.map((entry) => entry.name), probed.kind);
|
|
32776
32896
|
if (index2 === segments.length - 1) return { state: "exact", leaf: probed };
|
|
32777
32897
|
if (probed.kind !== "directory") return { state: "shape-mismatch", segment };
|
|
32778
32898
|
parent = candidate;
|
|
@@ -32787,35 +32907,53 @@ async function recordWalk(port, rootResolved, segments, rel) {
|
|
|
32787
32907
|
const segment = segments[index2];
|
|
32788
32908
|
const candidate = path2.join(parent, segment);
|
|
32789
32909
|
const probed = await probeSegment(port, candidate, rel, segment);
|
|
32790
|
-
if (probed === null) return
|
|
32791
|
-
if (index2 < segments.length - 1 && probed.kind !== "directory") return null;
|
|
32910
|
+
if (probed === null) return { recorded, complete: false };
|
|
32792
32911
|
recorded.push(probed);
|
|
32912
|
+
if (index2 < segments.length - 1 && probed.kind !== "directory") return { recorded, complete: false };
|
|
32793
32913
|
parent = candidate;
|
|
32794
32914
|
}
|
|
32795
|
-
return recorded;
|
|
32915
|
+
return { recorded, complete: true };
|
|
32796
32916
|
}
|
|
32797
|
-
async function confirmedWalk(port, rootResolved, segments, rel, recorded, handle, listings = freshListings(port)) {
|
|
32917
|
+
async function confirmedWalk(port, rootResolved, segments, rel, recorded, handle, listings = freshListings(port), stopAt = segments.length) {
|
|
32798
32918
|
let parent = rootResolved;
|
|
32799
|
-
for (let index2 = 0; index2 <
|
|
32919
|
+
for (let index2 = 0; index2 < stopAt; index2++) {
|
|
32800
32920
|
const segment = segments[index2];
|
|
32801
32921
|
const candidate = path2.join(parent, segment);
|
|
32802
32922
|
const listing = await listings(parent);
|
|
32803
32923
|
if (listing === null) return "absent";
|
|
32804
32924
|
const listed = listing.has(segment);
|
|
32805
32925
|
if (handle !== null && index2 === segments.length - 1) {
|
|
32806
|
-
const
|
|
32807
|
-
|
|
32926
|
+
const probe = await probeSegment(port, candidate, rel, segment);
|
|
32927
|
+
const verdict = classifyLeaf({ listed, probe, handle });
|
|
32928
|
+
if (verdict === "aliased") throw aliasRefusal(rel, segments, index2, listing.names(), probe?.kind);
|
|
32808
32929
|
return verdict === "replaced" ? "restart" : verdict;
|
|
32809
32930
|
}
|
|
32810
32931
|
if (index2 < segments.length - 1 || !listed) {
|
|
32811
|
-
const
|
|
32812
|
-
|
|
32932
|
+
const probe = await probeSegment(port, candidate, rel, segment);
|
|
32933
|
+
const verdict = confirmAlias(listed, probe, recorded[index2]);
|
|
32934
|
+
if (verdict === "aliased") throw aliasRefusal(rel, segments, index2, listing.names(), probe?.kind);
|
|
32813
32935
|
if (verdict !== "continue") return verdict;
|
|
32814
32936
|
}
|
|
32815
32937
|
parent = candidate;
|
|
32816
32938
|
}
|
|
32817
32939
|
return "continue";
|
|
32818
32940
|
}
|
|
32941
|
+
async function confirmPrefix(port, rootResolved, segments, rel, recorded) {
|
|
32942
|
+
if (recorded.length === 0) return "absent";
|
|
32943
|
+
let kept = prefixListings.get(port);
|
|
32944
|
+
if (kept === void 0) prefixListings.set(port, kept = /* @__PURE__ */ new Map());
|
|
32945
|
+
const cached = witnessedListings(port, kept, Date.now, PREFIX_LISTING_CAPACITY);
|
|
32946
|
+
let verdict;
|
|
32947
|
+
try {
|
|
32948
|
+
verdict = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, cached.source, recorded.length);
|
|
32949
|
+
} catch (error) {
|
|
32950
|
+
if (!cached.reused()) throw error;
|
|
32951
|
+
kept.clear();
|
|
32952
|
+
verdict = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, freshListings(port), recorded.length);
|
|
32953
|
+
}
|
|
32954
|
+
if (verdict === "restart" && cached.reused()) kept.clear();
|
|
32955
|
+
return verdict === "restart" ? "restart" : "absent";
|
|
32956
|
+
}
|
|
32819
32957
|
function countRestart(restarts, rel) {
|
|
32820
32958
|
if (restarts >= MAX_RESTARTS) throw new ConcurrentReplacementError(rel, restarts + 1);
|
|
32821
32959
|
return restarts + 1;
|
|
@@ -32827,8 +32965,14 @@ async function observeWith(port, rootResolved, rel, read, listings, onExact) {
|
|
|
32827
32965
|
const segments = relSegments(rel);
|
|
32828
32966
|
const target = path2.join(rootResolved, ...segments);
|
|
32829
32967
|
for (let restarts = 0; ; ) {
|
|
32830
|
-
const
|
|
32831
|
-
if (
|
|
32968
|
+
const walk = await recordWalk(port, rootResolved, segments, rel);
|
|
32969
|
+
if (!walk.complete) {
|
|
32970
|
+
const prefix = await confirmPrefix(port, rootResolved, segments, rel, walk.recorded);
|
|
32971
|
+
if (prefix === "absent") return { state: "absent" };
|
|
32972
|
+
restarts = countRestart(restarts, rel);
|
|
32973
|
+
continue;
|
|
32974
|
+
}
|
|
32975
|
+
const recorded = walk.recorded;
|
|
32832
32976
|
const verified = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, listings);
|
|
32833
32977
|
if (verified === "absent") return { state: "absent" };
|
|
32834
32978
|
if (verified === "restart") {
|
|
@@ -32867,8 +33011,14 @@ async function probeExact(port, root, rel) {
|
|
|
32867
33011
|
const segments = relSegments(rel);
|
|
32868
33012
|
const rootResolved = path2.resolve(root);
|
|
32869
33013
|
for (let restarts = 0; ; ) {
|
|
32870
|
-
const
|
|
32871
|
-
if (
|
|
33014
|
+
const walk = await recordWalk(port, rootResolved, segments, rel);
|
|
33015
|
+
if (!walk.complete) {
|
|
33016
|
+
const prefix = await confirmPrefix(port, rootResolved, segments, rel, walk.recorded);
|
|
33017
|
+
if (prefix === "absent") return { state: "absent" };
|
|
33018
|
+
restarts = countRestart(restarts, rel);
|
|
33019
|
+
continue;
|
|
33020
|
+
}
|
|
33021
|
+
const recorded = walk.recorded;
|
|
32872
33022
|
const leaf = recorded[recorded.length - 1];
|
|
32873
33023
|
const verified = await confirmedWalk(port, rootResolved, segments, rel, recorded, null);
|
|
32874
33024
|
const verdict = verified === "continue" ? await confirmedWalk(port, rootResolved, segments, rel, recorded, leaf) : verified;
|
|
@@ -32878,45 +33028,56 @@ async function probeExact(port, root, rel) {
|
|
|
32878
33028
|
}
|
|
32879
33029
|
}
|
|
32880
33030
|
var SETTLED_AFTER_NS = 3000000000n;
|
|
33031
|
+
function witnessCanDetectChange(witness) {
|
|
33032
|
+
return witness.mtimeNs > 0n && witness.ctimeNs > 0n;
|
|
33033
|
+
}
|
|
32881
33034
|
function witnessKey(witness) {
|
|
32882
33035
|
return `${witness.dev}:${witness.ino}:${witness.mtimeNs}:${witness.ctimeNs}`;
|
|
32883
33036
|
}
|
|
32884
|
-
function
|
|
32885
|
-
|
|
32886
|
-
const
|
|
32887
|
-
|
|
32888
|
-
const
|
|
32889
|
-
|
|
33037
|
+
function witnessedListings(port, kept, now, capacity = Infinity) {
|
|
33038
|
+
let reused = false;
|
|
33039
|
+
const portWitness = port.directoryWitness?.bind(port);
|
|
33040
|
+
if (portWitness === void 0) return { source: freshListings(port), reused: () => false };
|
|
33041
|
+
const witnessOf = async (dir) => {
|
|
33042
|
+
const witness = await portWitness(dir);
|
|
33043
|
+
return witness !== null && witnessCanDetectChange(witness) ? witness : null;
|
|
33044
|
+
};
|
|
32890
33045
|
const settled = (witness) => {
|
|
32891
33046
|
const nowNs = BigInt(Math.floor(now())) * 1000000n;
|
|
32892
33047
|
const latest = witness.mtimeNs > witness.ctimeNs ? witness.mtimeNs : witness.ctimeNs;
|
|
32893
33048
|
return nowNs - latest >= SETTLED_AFTER_NS;
|
|
32894
33049
|
};
|
|
32895
|
-
const
|
|
32896
|
-
|
|
32897
|
-
if (
|
|
32898
|
-
|
|
32899
|
-
|
|
32900
|
-
|
|
32901
|
-
|
|
32902
|
-
|
|
32903
|
-
|
|
32904
|
-
|
|
32905
|
-
|
|
32906
|
-
|
|
32907
|
-
|
|
32908
|
-
|
|
32909
|
-
|
|
32910
|
-
|
|
32911
|
-
|
|
32912
|
-
|
|
32913
|
-
|
|
32914
|
-
|
|
32915
|
-
|
|
32916
|
-
return names;
|
|
32917
|
-
};
|
|
32918
|
-
return { source, reused: () => reused };
|
|
33050
|
+
const source = async (dir) => {
|
|
33051
|
+
const keep = kept.get(dir);
|
|
33052
|
+
if (keep !== void 0) {
|
|
33053
|
+
const current = await witnessOf(dir);
|
|
33054
|
+
if (current !== null && witnessKey(current) === keep.witness) {
|
|
33055
|
+
reused = true;
|
|
33056
|
+
return listingView(keep.names);
|
|
33057
|
+
}
|
|
33058
|
+
kept.delete(dir);
|
|
33059
|
+
}
|
|
33060
|
+
const before = await witnessOf(dir);
|
|
33061
|
+
const listing = await port.entries(dir);
|
|
33062
|
+
if (listing === null) return null;
|
|
33063
|
+
const names = new Set(listing.map((entry) => entry.name));
|
|
33064
|
+
const after = await witnessOf(dir);
|
|
33065
|
+
if (before !== null && after !== null && witnessKey(before) === witnessKey(after) && settled(after)) {
|
|
33066
|
+
kept.delete(dir);
|
|
33067
|
+
kept.set(dir, { witness: witnessKey(after), names });
|
|
33068
|
+
while (kept.size > capacity) kept.delete(kept.keys().next().value);
|
|
33069
|
+
}
|
|
33070
|
+
return listingView(names);
|
|
32919
33071
|
};
|
|
33072
|
+
return { source, reused: () => reused };
|
|
33073
|
+
}
|
|
33074
|
+
var prefixListings = /* @__PURE__ */ new WeakMap();
|
|
33075
|
+
var PREFIX_LISTING_CAPACITY = 64;
|
|
33076
|
+
function openObservationPass(port, root, now = Date.now) {
|
|
33077
|
+
const rootResolved = path2.resolve(root);
|
|
33078
|
+
const kept = /* @__PURE__ */ new Map();
|
|
33079
|
+
const reusedVerdicts = [];
|
|
33080
|
+
const listingsFor = () => witnessedListings(port, kept, now);
|
|
32920
33081
|
return {
|
|
32921
33082
|
async observe(rel, read) {
|
|
32922
33083
|
const listings = listingsFor();
|
|
@@ -33019,7 +33180,7 @@ async function readWhole(port, target) {
|
|
|
33019
33180
|
await port.close(opened.handle);
|
|
33020
33181
|
}
|
|
33021
33182
|
}
|
|
33022
|
-
async function mkdirExact(port, parent, segment, isTail, rel) {
|
|
33183
|
+
async function mkdirExact(port, parent, segment, isTail, rel, index2 = -1) {
|
|
33023
33184
|
const outcome = await port.mkdir(path2.join(parent, segment));
|
|
33024
33185
|
if (outcome === "created") return;
|
|
33025
33186
|
const listing = await port.entries(parent);
|
|
@@ -33028,7 +33189,9 @@ async function mkdirExact(port, parent, segment, isTail, rel) {
|
|
|
33028
33189
|
throw new FilesystemSymlinkEntryError(rel, segment);
|
|
33029
33190
|
}
|
|
33030
33191
|
const verdict = classifyMkdir(outcome, listing, segment, isTail);
|
|
33031
|
-
if (verdict === "aliased")
|
|
33192
|
+
if (verdict === "aliased") {
|
|
33193
|
+
throw aliasRefusalFromListing(rel, index2, listing, false);
|
|
33194
|
+
}
|
|
33032
33195
|
if (verdict === "shape-mismatch") throw new FilesystemShapeMismatchError(rel, segment);
|
|
33033
33196
|
}
|
|
33034
33197
|
async function ensureExactDirectories(port, rootResolved, segments, existingDepth, rel) {
|
|
@@ -33048,8 +33211,9 @@ async function ensureExactDirectories(port, rootResolved, segments, existingDept
|
|
|
33048
33211
|
}
|
|
33049
33212
|
}
|
|
33050
33213
|
let parent = path2.join(rootResolved, ...segments.slice(0, existingDepth));
|
|
33051
|
-
for (
|
|
33052
|
-
|
|
33214
|
+
for (let index2 = existingDepth; index2 < segments.length - 1; index2++) {
|
|
33215
|
+
const segment = segments[index2];
|
|
33216
|
+
await mkdirExact(port, parent, segment, false, rel, index2);
|
|
33053
33217
|
parent = path2.join(parent, segment);
|
|
33054
33218
|
}
|
|
33055
33219
|
}
|
|
@@ -33067,7 +33231,7 @@ async function createExactLeaf(port, tmp, target, rel, leaf, rootResolved) {
|
|
|
33067
33231
|
}
|
|
33068
33232
|
const listing = await port.entries(path2.dirname(target)) ?? [];
|
|
33069
33233
|
if (hasExact(listing, leaf)) throw new ConcurrentReplacementError(rel, 1);
|
|
33070
|
-
throw
|
|
33234
|
+
throw aliasRefusalFromListing(rel, relSegments(rel).length - 1, listing, true);
|
|
33071
33235
|
}
|
|
33072
33236
|
async function mutateExact(port, root, rel, body) {
|
|
33073
33237
|
const segments = relSegments(rel);
|
|
@@ -33089,11 +33253,13 @@ async function mutateExact(port, root, rel, body) {
|
|
|
33089
33253
|
async replace(bytes) {
|
|
33090
33254
|
await ensureExactDirectories(port, rootResolved, segments, existingDepth, rel);
|
|
33091
33255
|
const dir = path2.dirname(target);
|
|
33092
|
-
const tmpName =
|
|
33256
|
+
const tmpName = identityTempName(leaf);
|
|
33093
33257
|
const tmp = path2.join(dir, tmpName);
|
|
33094
33258
|
await port.writeTemp(dir, tmpName, bytes);
|
|
33095
33259
|
try {
|
|
33096
33260
|
if (realized.state === "exact") {
|
|
33261
|
+
await port.copyMode?.(target, tmp).catch(() => {
|
|
33262
|
+
});
|
|
33097
33263
|
await replaceExistingLeaf(port, tmp, target, rel);
|
|
33098
33264
|
return;
|
|
33099
33265
|
}
|
|
@@ -33253,6 +33419,9 @@ function createNodeFilesystemIdentityPort(hostPolicy) {
|
|
|
33253
33419
|
async rename(from, to) {
|
|
33254
33420
|
await fs2.rename(from, to);
|
|
33255
33421
|
},
|
|
33422
|
+
async copyMode(from, to) {
|
|
33423
|
+
await fs2.chmod(to, (await fs2.lstat(from)).mode & 511);
|
|
33424
|
+
},
|
|
33256
33425
|
async unlink(target) {
|
|
33257
33426
|
await fs2.unlink(target);
|
|
33258
33427
|
},
|
|
@@ -33275,6 +33444,7 @@ function blobVersion(bytes) {
|
|
|
33275
33444
|
|
|
33276
33445
|
// ../core/src/backend.ts
|
|
33277
33446
|
var publicationContexts = /* @__PURE__ */ new WeakMap();
|
|
33447
|
+
var fileMutations = /* @__PURE__ */ new WeakMap();
|
|
33278
33448
|
function firstString(...vals) {
|
|
33279
33449
|
for (const v of vals) {
|
|
33280
33450
|
if (typeof v === "string" && v.trim() !== "") return v;
|
|
@@ -33391,6 +33561,7 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
33391
33561
|
this.#root = path3.resolve(root);
|
|
33392
33562
|
this.#coordinator = createFilesystemMutationCoordinator(this.#port, this.#root, options.hostPolicy);
|
|
33393
33563
|
publicationContexts.set(this, { root: this.#root, port: this.#port });
|
|
33564
|
+
fileMutations.set(this, (rel, body) => this.#mutateExact(rel, body));
|
|
33394
33565
|
}
|
|
33395
33566
|
async read(id) {
|
|
33396
33567
|
return this.#readWithEdition(id, () => this.#readEdition());
|
|
@@ -33776,6 +33947,7 @@ var KIND_FIELD_TYPE_SET = new Set(KIND_FIELD_TYPES);
|
|
|
33776
33947
|
function isKindFieldType(value) {
|
|
33777
33948
|
return typeof value === "string" && KIND_FIELD_TYPE_SET.has(value);
|
|
33778
33949
|
}
|
|
33950
|
+
var UNDECLARED_FIELDS_POLICIES = ["warn", "error"];
|
|
33779
33951
|
function buildKindRegistry(docs, initialWarnings = [], options = {}) {
|
|
33780
33952
|
const accepted = /* @__PURE__ */ new Map();
|
|
33781
33953
|
const warnings = [...initialWarnings];
|
|
@@ -34370,6 +34542,19 @@ function parseConventionDoc(doc, options = {}) {
|
|
|
34370
34542
|
});
|
|
34371
34543
|
}
|
|
34372
34544
|
}
|
|
34545
|
+
let undeclaredFields;
|
|
34546
|
+
if (fm.undeclared_fields !== void 0) {
|
|
34547
|
+
if (UNDECLARED_FIELDS_POLICIES.includes(fm.undeclared_fields)) {
|
|
34548
|
+
undeclaredFields = fm.undeclared_fields;
|
|
34549
|
+
} else {
|
|
34550
|
+
warnings.push({
|
|
34551
|
+
code: "KIND_CONVENTION_BAD_SHAPE",
|
|
34552
|
+
message: `kind convention '${doc.id}' has an invalid 'undeclared_fields' (${describeShape(fm.undeclared_fields)}; expected warn or error); using warn.`,
|
|
34553
|
+
field: "undeclared_fields",
|
|
34554
|
+
severity: "warning"
|
|
34555
|
+
});
|
|
34556
|
+
}
|
|
34557
|
+
}
|
|
34373
34558
|
const kind2 = {
|
|
34374
34559
|
id: doc.id,
|
|
34375
34560
|
title,
|
|
@@ -34387,6 +34572,7 @@ function parseConventionDoc(doc, options = {}) {
|
|
|
34387
34572
|
if (browseCollapsed !== void 0) kind2.browseCollapsed = browseCollapsed;
|
|
34388
34573
|
if (order !== void 0) kind2.order = order;
|
|
34389
34574
|
if (claim !== void 0) kind2.claim = claim;
|
|
34575
|
+
if (undeclaredFields !== void 0) kind2.undeclaredFields = undeclaredFields;
|
|
34390
34576
|
if (Object.hasOwn(fm, "deprecated")) {
|
|
34391
34577
|
kind2.deprecated = parseKindDeprecation(fm.deprecated, kind2, RESERVED_KIND_FIELD_NAMES, claimCoordinates(options.okfVersion, kind2)?.fields ?? []);
|
|
34392
34578
|
warnings.push(...kind2.deprecated.problems ?? []);
|
|
@@ -34423,58 +34609,6 @@ function isTerminal(kind2, frontmatter2) {
|
|
|
34423
34609
|
return false;
|
|
34424
34610
|
}
|
|
34425
34611
|
|
|
34426
|
-
// ../core/src/query-selection.ts
|
|
34427
|
-
function applyQuerySelectionFilters(rows, params, kinds = []) {
|
|
34428
|
-
let out = rows;
|
|
34429
|
-
const byGoverns = new Map(kinds.map((kind2) => [kind2.governs, kind2]));
|
|
34430
|
-
if (params.field) {
|
|
34431
|
-
const eq = params.field.indexOf("=");
|
|
34432
|
-
if (eq > 0) {
|
|
34433
|
-
const key = params.field.slice(0, eq).trim();
|
|
34434
|
-
const values = params.field.slice(eq + 1).split(",").map((value) => value.trim()).filter(Boolean);
|
|
34435
|
-
out = out.filter((row) => {
|
|
34436
|
-
if (key !== PROGRESS_STATUS_FIELD) {
|
|
34437
|
-
return values.some((value) => matchesFilter(row, { fields: { [key]: value } }));
|
|
34438
|
-
}
|
|
34439
|
-
const kind2 = byGoverns.get(String(row.frontmatter.type ?? ""));
|
|
34440
|
-
if (!kind2) return false;
|
|
34441
|
-
const raw = readKindField(params.okfVersion, kind2, row.frontmatter, key);
|
|
34442
|
-
const actual = raw === void 0 || raw === null ? [] : (Array.isArray(raw) ? raw : [raw]).map((value) => String(value));
|
|
34443
|
-
return values.some((value) => actual.includes(value));
|
|
34444
|
-
});
|
|
34445
|
-
}
|
|
34446
|
-
}
|
|
34447
|
-
if (params.open) {
|
|
34448
|
-
out = out.filter((row) => {
|
|
34449
|
-
const kind2 = byGoverns.get(String(row.frontmatter.type ?? ""));
|
|
34450
|
-
return !kind2 || !isTerminal(kind2, row.frontmatter);
|
|
34451
|
-
});
|
|
34452
|
-
}
|
|
34453
|
-
const count = out.length;
|
|
34454
|
-
if (typeof params.limit === "number" && params.limit > 0) {
|
|
34455
|
-
out = out.slice(0, params.limit);
|
|
34456
|
-
}
|
|
34457
|
-
return { rows: out, count };
|
|
34458
|
-
}
|
|
34459
|
-
|
|
34460
|
-
// ../core/src/kinds-load.ts
|
|
34461
|
-
async function loadKinds(bundle) {
|
|
34462
|
-
const warnings = [];
|
|
34463
|
-
const docs = await query2(bundle, { prefix: CONVENTIONS_PREFIX, type: CONVENTION_TYPE }, {
|
|
34464
|
-
onSkip: ({ id, reason }) => warnings.push({
|
|
34465
|
-
code: "KIND_CONVENTION_MALFORMED",
|
|
34466
|
-
message: `skipped kind convention '${id}' with unparseable frontmatter: ${reason}`,
|
|
34467
|
-
field: id,
|
|
34468
|
-
severity: "warning"
|
|
34469
|
-
})
|
|
34470
|
-
});
|
|
34471
|
-
const okfVersion = await readBundleOkfVersion2(bundle).catch((error) => {
|
|
34472
|
-
if (!(error instanceof MalformedDocumentError)) throw error;
|
|
34473
|
-
return void 0;
|
|
34474
|
-
});
|
|
34475
|
-
return buildKindRegistry(docs, warnings, { okfVersion });
|
|
34476
|
-
}
|
|
34477
|
-
|
|
34478
34612
|
// ../core/src/page.ts
|
|
34479
34613
|
var PAGE_REGISTRY_PREFIX = "pages-registry/";
|
|
34480
34614
|
var PAGE_ENTRY_PREFIX = "pages/";
|
|
@@ -34556,6 +34690,58 @@ function parseRegistration(id, frontmatter2) {
|
|
|
34556
34690
|
};
|
|
34557
34691
|
}
|
|
34558
34692
|
|
|
34693
|
+
// ../core/src/query-selection.ts
|
|
34694
|
+
function applyQuerySelectionFilters(rows, params, kinds = []) {
|
|
34695
|
+
let out = rows;
|
|
34696
|
+
const byGoverns = new Map(kinds.map((kind2) => [kind2.governs, kind2]));
|
|
34697
|
+
if (params.field) {
|
|
34698
|
+
const eq = params.field.indexOf("=");
|
|
34699
|
+
if (eq > 0) {
|
|
34700
|
+
const key = params.field.slice(0, eq).trim();
|
|
34701
|
+
const values = params.field.slice(eq + 1).split(",").map((value) => value.trim()).filter(Boolean);
|
|
34702
|
+
out = out.filter((row) => {
|
|
34703
|
+
if (key !== PROGRESS_STATUS_FIELD) {
|
|
34704
|
+
return values.some((value) => matchesFilter(row, { fields: { [key]: value } }));
|
|
34705
|
+
}
|
|
34706
|
+
const kind2 = byGoverns.get(String(row.frontmatter.type ?? ""));
|
|
34707
|
+
if (!kind2) return false;
|
|
34708
|
+
const raw = readKindField(params.okfVersion, kind2, row.frontmatter, key);
|
|
34709
|
+
const actual = raw === void 0 || raw === null ? [] : (Array.isArray(raw) ? raw : [raw]).map((value) => String(value));
|
|
34710
|
+
return values.some((value) => actual.includes(value));
|
|
34711
|
+
});
|
|
34712
|
+
}
|
|
34713
|
+
}
|
|
34714
|
+
if (params.open) {
|
|
34715
|
+
out = out.filter((row) => {
|
|
34716
|
+
const kind2 = byGoverns.get(String(row.frontmatter.type ?? ""));
|
|
34717
|
+
return !kind2 || !isTerminal(kind2, row.frontmatter);
|
|
34718
|
+
});
|
|
34719
|
+
}
|
|
34720
|
+
const count = out.length;
|
|
34721
|
+
if (typeof params.limit === "number" && params.limit > 0) {
|
|
34722
|
+
out = out.slice(0, params.limit);
|
|
34723
|
+
}
|
|
34724
|
+
return { rows: out, count };
|
|
34725
|
+
}
|
|
34726
|
+
|
|
34727
|
+
// ../core/src/kinds-load.ts
|
|
34728
|
+
async function loadKinds(bundle) {
|
|
34729
|
+
const warnings = [];
|
|
34730
|
+
const docs = await query2(bundle, { prefix: CONVENTIONS_PREFIX, type: CONVENTION_TYPE }, {
|
|
34731
|
+
onSkip: ({ id, reason }) => warnings.push({
|
|
34732
|
+
code: "KIND_CONVENTION_MALFORMED",
|
|
34733
|
+
message: isPermissionDeniedSkip({ reason }) ? `skipped kind convention '${id}' that could not be read: ${reason}` : `skipped kind convention '${id}' with unparseable frontmatter: ${reason}`,
|
|
34734
|
+
field: id,
|
|
34735
|
+
severity: "warning"
|
|
34736
|
+
})
|
|
34737
|
+
});
|
|
34738
|
+
const okfVersion = await readBundleOkfVersion2(bundle).catch((error) => {
|
|
34739
|
+
if (!(error instanceof MalformedDocumentError)) throw error;
|
|
34740
|
+
return void 0;
|
|
34741
|
+
});
|
|
34742
|
+
return buildKindRegistry(docs, warnings, { okfVersion });
|
|
34743
|
+
}
|
|
34744
|
+
|
|
34559
34745
|
// ../markdown-renderer/src/static.tsx
|
|
34560
34746
|
var import_server = __toESM(require_server_node(), 1);
|
|
34561
34747
|
|
|
@@ -44601,12 +44787,27 @@ var CAPABILITIES = [
|
|
|
44601
44787
|
];
|
|
44602
44788
|
async function authorizePublicationRoot(requested) {
|
|
44603
44789
|
const entry = await lstat(requested);
|
|
44604
|
-
if (entry.isSymbolicLink()
|
|
44790
|
+
if (entry.isSymbolicLink()) {
|
|
44791
|
+
const target = await realpath(requested).catch(() => void 0);
|
|
44792
|
+
if (target === void 0) {
|
|
44793
|
+
throw new PublicationError("INVALID_OBJECT_IDENTITY", `the filesystem publication root ${JSON.stringify(requested)} is a symlink that does not resolve to a directory`, { actual: requested });
|
|
44794
|
+
}
|
|
44795
|
+
throw new PublicationError(
|
|
44796
|
+
"INVALID_OBJECT_IDENTITY",
|
|
44797
|
+
`the filesystem publication root ${JSON.stringify(requested)} is a symlink to ${JSON.stringify(target)}; capture does not follow symlinks, so pass the resolved path (await fs.realpath(root))`,
|
|
44798
|
+
{ expected: target, actual: requested }
|
|
44799
|
+
);
|
|
44800
|
+
}
|
|
44801
|
+
if (!entry.isDirectory()) {
|
|
44605
44802
|
throw new PublicationError("INVALID_OBJECT_IDENTITY", "the filesystem publication root must be a real directory");
|
|
44606
44803
|
}
|
|
44607
44804
|
const canonical2 = await realpath(requested);
|
|
44608
44805
|
if (canonical2 !== requested) {
|
|
44609
|
-
throw new PublicationError(
|
|
44806
|
+
throw new PublicationError(
|
|
44807
|
+
"INVALID_OBJECT_IDENTITY",
|
|
44808
|
+
`the filesystem publication root ${JSON.stringify(requested)} is not in canonical form (it resolves to ${JSON.stringify(canonical2)}); capture does not follow symlinks or normalize paths, so pass the resolved path (await fs.realpath(root))`,
|
|
44809
|
+
{ expected: canonical2, actual: requested }
|
|
44810
|
+
);
|
|
44610
44811
|
}
|
|
44611
44812
|
const identity = await stat(requested);
|
|
44612
44813
|
return { requested, canonical: canonical2, dev: identity.dev, ino: identity.ino };
|