superbee 0.1.5-pre.2 → 0.1.6-pre.1
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/bundle-descriptor/generated/bundle-descriptor-v1.d.ts +30 -0
- package/dist/bundle-descriptor/index.d.ts +3 -0
- package/dist/bundle-descriptor/schema/bundle-descriptor-v1.schema.json +42 -0
- package/dist/bundle-descriptor/schema.d.ts +5 -0
- package/dist/bundle-descriptor.mjs +58 -0
- package/dist/publication-bridge.mjs +198 -105
- package/dist/publication.mjs +198 -105
- package/dist/superbee.mjs +1178 -585
- package/package.json +6 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable authority-qualified identity. The publisher controls the first segment; directory policy owns collision handling.
|
|
3
|
+
*
|
|
4
|
+
* This interface was referenced by `SuperbeeBundleDescriptorV1`'s JSON-Schema
|
|
5
|
+
* via the `definition` "bundleId".
|
|
6
|
+
*/
|
|
7
|
+
export type BundleId = string;
|
|
8
|
+
/**
|
|
9
|
+
* Untrusted display text. Presenters must still escape it for their output context.
|
|
10
|
+
*
|
|
11
|
+
* This interface was referenced by `SuperbeeBundleDescriptorV1`'s JSON-Schema
|
|
12
|
+
* via the `definition` "displayText".
|
|
13
|
+
*/
|
|
14
|
+
export type DisplayText = string;
|
|
15
|
+
/**
|
|
16
|
+
* A bundle's minimal, portable self-description. This contract conveys no access, authority, ownership, lifecycle, policy, routing, or resolution claims.
|
|
17
|
+
*/
|
|
18
|
+
export interface SuperbeeBundleDescriptorV1 {
|
|
19
|
+
schema: "https://getsuperbee.com/schemas/bundle-descriptor/v1";
|
|
20
|
+
bundleId: BundleId;
|
|
21
|
+
/**
|
|
22
|
+
* Untrusted display text. Presenters must still escape it for their output context.
|
|
23
|
+
*/
|
|
24
|
+
name: string;
|
|
25
|
+
/**
|
|
26
|
+
* Untrusted display text. Presenters must still escape it for their output context.
|
|
27
|
+
*/
|
|
28
|
+
purpose: string;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=bundle-descriptor-v1.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://getsuperbee.com/schemas/bundle-descriptor/v1",
|
|
4
|
+
"title": "Superbee Bundle Descriptor v1",
|
|
5
|
+
"description": "A bundle's minimal, portable self-description. This contract conveys no access, authority, ownership, lifecycle, policy, routing, or resolution claims.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["schema", "bundleId", "name", "purpose"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"schema": {
|
|
11
|
+
"const": "https://getsuperbee.com/schemas/bundle-descriptor/v1"
|
|
12
|
+
},
|
|
13
|
+
"bundleId": {
|
|
14
|
+
"$ref": "#/$defs/bundleId"
|
|
15
|
+
},
|
|
16
|
+
"name": {
|
|
17
|
+
"$ref": "#/$defs/displayText",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"maxLength": 120
|
|
20
|
+
},
|
|
21
|
+
"purpose": {
|
|
22
|
+
"$ref": "#/$defs/displayText",
|
|
23
|
+
"type": "string",
|
|
24
|
+
"maxLength": 500
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"$defs": {
|
|
28
|
+
"bundleId": {
|
|
29
|
+
"description": "A stable authority-qualified identity. The publisher controls the first segment; directory policy owns collision handling.",
|
|
30
|
+
"type": "string",
|
|
31
|
+
"minLength": 3,
|
|
32
|
+
"maxLength": 128,
|
|
33
|
+
"pattern": "^[a-z0-9][a-z0-9_-]{0,62}(?:\\.[a-z0-9][a-z0-9_-]{0,62})+$"
|
|
34
|
+
},
|
|
35
|
+
"displayText": {
|
|
36
|
+
"description": "Untrusted display text. Presenters must still escape it for their output context.",
|
|
37
|
+
"type": "string",
|
|
38
|
+
"minLength": 1,
|
|
39
|
+
"pattern": "^(?=.*\\S)[^\\u0000-\\u001F\\u007F-\\u009F\\u061C\\u200E-\\u200F\\u202A-\\u202E\\u2066-\\u2069]+$"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The stable Bundle Descriptor v1 schema identifier. */
|
|
2
|
+
export declare const BUNDLE_DESCRIPTOR_V1: "https://getsuperbee.com/schemas/bundle-descriptor/v1";
|
|
3
|
+
/** The canonical JSON Schema 2020-12 contract, deeply immutable at runtime. */
|
|
4
|
+
export declare const BUNDLE_DESCRIPTOR_SCHEMA_V1: Readonly<Record<string, unknown>>;
|
|
5
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// ../bundle-descriptor/schema/bundle-descriptor-v1.schema.json
|
|
2
|
+
var bundle_descriptor_v1_schema_default = {
|
|
3
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
$id: "https://getsuperbee.com/schemas/bundle-descriptor/v1",
|
|
5
|
+
title: "Superbee Bundle Descriptor v1",
|
|
6
|
+
description: "A bundle's minimal, portable self-description. This contract conveys no access, authority, ownership, lifecycle, policy, routing, or resolution claims.",
|
|
7
|
+
type: "object",
|
|
8
|
+
additionalProperties: false,
|
|
9
|
+
required: ["schema", "bundleId", "name", "purpose"],
|
|
10
|
+
properties: {
|
|
11
|
+
schema: {
|
|
12
|
+
const: "https://getsuperbee.com/schemas/bundle-descriptor/v1"
|
|
13
|
+
},
|
|
14
|
+
bundleId: {
|
|
15
|
+
$ref: "#/$defs/bundleId"
|
|
16
|
+
},
|
|
17
|
+
name: {
|
|
18
|
+
$ref: "#/$defs/displayText",
|
|
19
|
+
type: "string",
|
|
20
|
+
maxLength: 120
|
|
21
|
+
},
|
|
22
|
+
purpose: {
|
|
23
|
+
$ref: "#/$defs/displayText",
|
|
24
|
+
type: "string",
|
|
25
|
+
maxLength: 500
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
$defs: {
|
|
29
|
+
bundleId: {
|
|
30
|
+
description: "A stable authority-qualified identity. The publisher controls the first segment; directory policy owns collision handling.",
|
|
31
|
+
type: "string",
|
|
32
|
+
minLength: 3,
|
|
33
|
+
maxLength: 128,
|
|
34
|
+
pattern: "^[a-z0-9][a-z0-9_-]{0,62}(?:\\.[a-z0-9][a-z0-9_-]{0,62})+$"
|
|
35
|
+
},
|
|
36
|
+
displayText: {
|
|
37
|
+
description: "Untrusted display text. Presenters must still escape it for their output context.",
|
|
38
|
+
type: "string",
|
|
39
|
+
minLength: 1,
|
|
40
|
+
pattern: "^(?=.*\\S)[^\\u0000-\\u001F\\u007F-\\u009F\\u061C\\u200E-\\u200F\\u202A-\\u202E\\u2066-\\u2069]+$"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ../bundle-descriptor/src/schema.ts
|
|
46
|
+
function deepFreeze(value) {
|
|
47
|
+
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
48
|
+
Object.freeze(value);
|
|
49
|
+
for (const child of Object.values(value)) deepFreeze(child);
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
var BUNDLE_DESCRIPTOR_V1 = "https://getsuperbee.com/schemas/bundle-descriptor/v1";
|
|
54
|
+
var BUNDLE_DESCRIPTOR_SCHEMA_V1 = deepFreeze(bundle_descriptor_v1_schema_default);
|
|
55
|
+
export {
|
|
56
|
+
BUNDLE_DESCRIPTOR_SCHEMA_V1,
|
|
57
|
+
BUNDLE_DESCRIPTOR_V1
|
|
58
|
+
};
|
|
@@ -3132,8 +3132,8 @@ var require_js_yaml = __commonJS({
|
|
|
3132
3132
|
var require_js_yaml2 = __commonJS({
|
|
3133
3133
|
"../../node_modules/js-yaml/index.js"(exports2, module2) {
|
|
3134
3134
|
"use strict";
|
|
3135
|
-
var
|
|
3136
|
-
module2.exports =
|
|
3135
|
+
var yaml4 = require_js_yaml();
|
|
3136
|
+
module2.exports = yaml4;
|
|
3137
3137
|
}
|
|
3138
3138
|
});
|
|
3139
3139
|
|
|
@@ -3537,6 +3537,53 @@ import path3 from "node:path";
|
|
|
3537
3537
|
// ../core/src/frontmatter.ts
|
|
3538
3538
|
var import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
3539
3539
|
var import_js_yaml = __toESM(require_js_yaml2(), 1);
|
|
3540
|
+
|
|
3541
|
+
// ../core/src/frontmatter-contract.ts
|
|
3542
|
+
var MalformedDocumentError = class extends Error {
|
|
3543
|
+
name = "MalformedDocumentError";
|
|
3544
|
+
context;
|
|
3545
|
+
detail;
|
|
3546
|
+
constructor(context, cause) {
|
|
3547
|
+
const detail = ((cause instanceof Error ? cause.message : String(cause)).split("\n")[0] ?? "").trim();
|
|
3548
|
+
super(
|
|
3549
|
+
`malformed frontmatter${context ? ` in '${context}'` : ""}: ${detail} \u2014 fix the YAML or remove the file`
|
|
3550
|
+
);
|
|
3551
|
+
if (context !== void 0) this.context = context;
|
|
3552
|
+
this.detail = detail;
|
|
3553
|
+
if (cause !== void 0) this.cause = cause;
|
|
3554
|
+
}
|
|
3555
|
+
};
|
|
3556
|
+
|
|
3557
|
+
// ../core/src/frontmatter-splitter.ts
|
|
3558
|
+
function delimiterLineEnd(input, offset) {
|
|
3559
|
+
if (!input.startsWith("---", offset)) return null;
|
|
3560
|
+
const suffix = offset + 3;
|
|
3561
|
+
if (suffix === input.length) return suffix;
|
|
3562
|
+
if (input[suffix] === "\n") return suffix + 1;
|
|
3563
|
+
if (input[suffix] === "\r" && input[suffix + 1] === "\n") return suffix + 2;
|
|
3564
|
+
return null;
|
|
3565
|
+
}
|
|
3566
|
+
function splitLeadingFrontmatter(raw, context) {
|
|
3567
|
+
const input = raw.startsWith("\uFEFF") ? raw.slice(1) : raw;
|
|
3568
|
+
const openingEnd = delimiterLineEnd(input, 0);
|
|
3569
|
+
if (openingEnd === null) return { body: input };
|
|
3570
|
+
let lineStart = openingEnd;
|
|
3571
|
+
while (lineStart < input.length) {
|
|
3572
|
+
const closingEnd = delimiterLineEnd(input, lineStart);
|
|
3573
|
+
if (closingEnd !== null) {
|
|
3574
|
+
return {
|
|
3575
|
+
yamlSource: input.slice(openingEnd, lineStart),
|
|
3576
|
+
body: input.slice(closingEnd)
|
|
3577
|
+
};
|
|
3578
|
+
}
|
|
3579
|
+
const nextLineFeed = input.indexOf("\n", lineStart);
|
|
3580
|
+
if (nextLineFeed === -1) break;
|
|
3581
|
+
lineStart = nextLineFeed + 1;
|
|
3582
|
+
}
|
|
3583
|
+
throw new MalformedDocumentError(context, new Error("unterminated YAML frontmatter delimiter"));
|
|
3584
|
+
}
|
|
3585
|
+
|
|
3586
|
+
// ../core/src/frontmatter.ts
|
|
3540
3587
|
var YAML_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp";
|
|
3541
3588
|
function requireYamlTimestampType() {
|
|
3542
3589
|
const type = import_js_yaml.default.DEFAULT_SAFE_SCHEMA.implicit.find(
|
|
@@ -3573,38 +3620,17 @@ function normalizeFrontmatter(data) {
|
|
|
3573
3620
|
}
|
|
3574
3621
|
return out;
|
|
3575
3622
|
}
|
|
3576
|
-
var MalformedDocumentError = class extends Error {
|
|
3577
|
-
name = "MalformedDocumentError";
|
|
3578
|
-
/** The document id/path the malformed content belongs to (when the caller supplied one). */
|
|
3579
|
-
context;
|
|
3580
|
-
/** The underlying parser message, first line only — for compact per-doc reporting. */
|
|
3581
|
-
detail;
|
|
3582
|
-
constructor(context, cause) {
|
|
3583
|
-
const detail = ((cause instanceof Error ? cause.message : String(cause)).split("\n")[0] ?? "").trim();
|
|
3584
|
-
super(
|
|
3585
|
-
`malformed frontmatter${context ? ` in '${context}'` : ""}: ${detail} \u2014 fix the YAML or remove the file`
|
|
3586
|
-
);
|
|
3587
|
-
if (context !== void 0) this.context = context;
|
|
3588
|
-
this.detail = detail;
|
|
3589
|
-
if (cause !== void 0) this.cause = cause;
|
|
3590
|
-
}
|
|
3591
|
-
};
|
|
3592
3623
|
function parseMarkdown(raw, context) {
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
const afterOpening = firstLineEnd === -1 ? "" : raw.slice(firstLineEnd + 1);
|
|
3596
|
-
if (!/^---\r?$/m.test(afterOpening)) {
|
|
3597
|
-
throw new MalformedDocumentError(context, new Error("unterminated YAML frontmatter delimiter"));
|
|
3598
|
-
}
|
|
3599
|
-
}
|
|
3624
|
+
const split = splitLeadingFrontmatter(raw, context);
|
|
3625
|
+
if (!("yamlSource" in split)) return { frontmatter: {}, body: split.body };
|
|
3600
3626
|
let parsed;
|
|
3601
3627
|
try {
|
|
3602
|
-
parsed = (
|
|
3628
|
+
parsed = yamlEngine.parse(split.yamlSource);
|
|
3603
3629
|
} catch (err) {
|
|
3604
3630
|
throw new MalformedDocumentError(context, err);
|
|
3605
3631
|
}
|
|
3606
|
-
const frontmatter2 = normalizeFrontmatter(parsed
|
|
3607
|
-
return { frontmatter: frontmatter2, body:
|
|
3632
|
+
const frontmatter2 = normalizeFrontmatter(parsed);
|
|
3633
|
+
return { frontmatter: frontmatter2, body: split.body };
|
|
3608
3634
|
}
|
|
3609
3635
|
function normalizeDocumentBodyForStorage(body) {
|
|
3610
3636
|
return body.endsWith("\n") ? body : `${body}
|
|
@@ -3612,13 +3638,13 @@ function normalizeDocumentBodyForStorage(body) {
|
|
|
3612
3638
|
}
|
|
3613
3639
|
function stringifyWithData(data, body) {
|
|
3614
3640
|
const engines2 = import_gray_matter.default.engines;
|
|
3615
|
-
const
|
|
3641
|
+
const yaml4 = engines2.yaml.stringify(data).trim();
|
|
3616
3642
|
const content = body ?? "";
|
|
3617
3643
|
const newline = (value) => value.endsWith("\n") ? value : `${value}
|
|
3618
3644
|
`;
|
|
3619
|
-
if (
|
|
3645
|
+
if (yaml4 === "{}") return normalizeDocumentBodyForStorage(content);
|
|
3620
3646
|
return `---
|
|
3621
|
-
${newline(
|
|
3647
|
+
${newline(yaml4)}---
|
|
3622
3648
|
${normalizeDocumentBodyForStorage(content)}`;
|
|
3623
3649
|
}
|
|
3624
3650
|
function stringifyDoc(frontmatter2, body) {
|
|
@@ -4524,25 +4550,12 @@ function mutationActorFromFrontmatter(frontmatter2) {
|
|
|
4524
4550
|
|
|
4525
4551
|
// ../core/src/versioning.ts
|
|
4526
4552
|
import { createHash as createHash3 } from "node:crypto";
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
}
|
|
4530
|
-
function versionOfBytes(raw) {
|
|
4531
|
-
return `sha256:${sha256Hex(raw)}`;
|
|
4532
|
-
}
|
|
4533
|
-
function blobVersion(bytes) {
|
|
4534
|
-
return `sha256:${createHash3("sha256").update(bytes).digest("hex")}`;
|
|
4535
|
-
}
|
|
4536
|
-
function defaultActor() {
|
|
4537
|
-
return process.env.USER?.trim() || process.env.USERNAME?.trim() || process.env.LOGNAME?.trim() || "local";
|
|
4538
|
-
}
|
|
4553
|
+
|
|
4554
|
+
// ../core/src/version-transport.ts
|
|
4539
4555
|
var VersionConflict = class extends Error {
|
|
4540
4556
|
name = "VersionConflict";
|
|
4541
|
-
/** The concept id whose write was rejected. */
|
|
4542
4557
|
id;
|
|
4543
|
-
/** The version the caller expected the backend to currently hold (`null` = expected absent). */
|
|
4544
4558
|
expected;
|
|
4545
|
-
/** The version the backend actually holds (`null` if the document does not exist). */
|
|
4546
4559
|
actual;
|
|
4547
4560
|
constructor(id, expected, actual) {
|
|
4548
4561
|
super(
|
|
@@ -4554,6 +4567,20 @@ var VersionConflict = class extends Error {
|
|
|
4554
4567
|
}
|
|
4555
4568
|
};
|
|
4556
4569
|
|
|
4570
|
+
// ../core/src/versioning.ts
|
|
4571
|
+
function sha256Hex(input) {
|
|
4572
|
+
return createHash3("sha256").update(input, "utf8").digest("hex");
|
|
4573
|
+
}
|
|
4574
|
+
function versionOfBytes(raw) {
|
|
4575
|
+
return `sha256:${sha256Hex(raw)}`;
|
|
4576
|
+
}
|
|
4577
|
+
function blobVersion(bytes) {
|
|
4578
|
+
return `sha256:${createHash3("sha256").update(bytes).digest("hex")}`;
|
|
4579
|
+
}
|
|
4580
|
+
function defaultActor() {
|
|
4581
|
+
return process.env.USER?.trim() || process.env.USERNAME?.trim() || process.env.LOGNAME?.trim() || "local";
|
|
4582
|
+
}
|
|
4583
|
+
|
|
4557
4584
|
// ../core/src/backend.ts
|
|
4558
4585
|
var publicationRoots = /* @__PURE__ */ new WeakMap();
|
|
4559
4586
|
function firstString(...vals) {
|
|
@@ -4792,16 +4819,51 @@ function normalizeSegments(segments) {
|
|
|
4792
4819
|
function joinPosix(base, rel) {
|
|
4793
4820
|
return normalizeSegments([...base.split("/"), ...rel.split("/")]).join("/");
|
|
4794
4821
|
}
|
|
4795
|
-
var MD_LINK_RE = /\[([^\]]*)\]\(([^)\s]+)\)/g;
|
|
4796
4822
|
function isExternalHref(href) {
|
|
4797
4823
|
const h = href.trim();
|
|
4798
4824
|
return /^[a-z][a-z0-9+.-]*:\/\//i.test(h) || h.startsWith("mailto:") || h.startsWith("#");
|
|
4799
4825
|
}
|
|
4800
4826
|
function extractMarkdownLinks(body) {
|
|
4801
4827
|
const out = [];
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4828
|
+
let textOpen = -1;
|
|
4829
|
+
let afterClose;
|
|
4830
|
+
let hrefFirst;
|
|
4831
|
+
let hrefRest;
|
|
4832
|
+
for (let cursor = 0; cursor < body.length; cursor++) {
|
|
4833
|
+
const char = body[cursor];
|
|
4834
|
+
if (hrefRest) {
|
|
4835
|
+
if (char === ")") {
|
|
4836
|
+
if (hrefRest.open === 0 || body[hrefRest.open - 1] !== "!") {
|
|
4837
|
+
out.push({
|
|
4838
|
+
text: body.slice(hrefRest.open + 1, hrefRest.close),
|
|
4839
|
+
href: body.slice(hrefRest.hrefStart, cursor)
|
|
4840
|
+
});
|
|
4841
|
+
}
|
|
4842
|
+
textOpen = -1;
|
|
4843
|
+
afterClose = void 0;
|
|
4844
|
+
hrefFirst = void 0;
|
|
4845
|
+
hrefRest = void 0;
|
|
4846
|
+
continue;
|
|
4847
|
+
}
|
|
4848
|
+
if (char.trim() === "") hrefRest = void 0;
|
|
4849
|
+
}
|
|
4850
|
+
if (hrefFirst) {
|
|
4851
|
+
if (char !== ")" && char.trim() !== "" && !hrefRest) {
|
|
4852
|
+
hrefRest = hrefFirst;
|
|
4853
|
+
}
|
|
4854
|
+
hrefFirst = void 0;
|
|
4855
|
+
}
|
|
4856
|
+
if (afterClose) {
|
|
4857
|
+
if (char === "(") {
|
|
4858
|
+
hrefFirst = { ...afterClose, hrefStart: cursor + 1 };
|
|
4859
|
+
}
|
|
4860
|
+
afterClose = void 0;
|
|
4861
|
+
}
|
|
4862
|
+
if (textOpen >= 0 && char === "]") {
|
|
4863
|
+
afterClose = { open: textOpen, close: cursor };
|
|
4864
|
+
textOpen = -1;
|
|
4865
|
+
}
|
|
4866
|
+
if (char === "[" && textOpen < 0) textOpen = cursor;
|
|
4805
4867
|
}
|
|
4806
4868
|
return out;
|
|
4807
4869
|
}
|
|
@@ -4838,6 +4900,24 @@ function parseLinksFromDoc(doc) {
|
|
|
4838
4900
|
return links;
|
|
4839
4901
|
}
|
|
4840
4902
|
|
|
4903
|
+
// ../core/src/portable-frontmatter.ts
|
|
4904
|
+
var import_js_yaml2 = __toESM(require_js_yaml2(), 1);
|
|
4905
|
+
function parseLeadingFrontmatter(raw, context) {
|
|
4906
|
+
const split = splitLeadingFrontmatter(raw, context);
|
|
4907
|
+
if (!("yamlSource" in split)) return {};
|
|
4908
|
+
try {
|
|
4909
|
+
const parsed = import_js_yaml2.default.safeLoad(split.yamlSource);
|
|
4910
|
+
if (parsed === void 0 || parsed === null) return {};
|
|
4911
|
+
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4912
|
+
throw new TypeError("YAML frontmatter must be a mapping");
|
|
4913
|
+
}
|
|
4914
|
+
return parsed;
|
|
4915
|
+
} catch (error) {
|
|
4916
|
+
if (error instanceof MalformedDocumentError) throw error;
|
|
4917
|
+
throw new MalformedDocumentError(context, error);
|
|
4918
|
+
}
|
|
4919
|
+
}
|
|
4920
|
+
|
|
4841
4921
|
// ../core/src/query-filter.ts
|
|
4842
4922
|
function matchesFilter(doc, filter) {
|
|
4843
4923
|
if (filter.prefix && !doc.id.startsWith(filter.prefix)) return false;
|
|
@@ -4857,25 +4937,27 @@ function matchesFilter(doc, filter) {
|
|
|
4857
4937
|
return true;
|
|
4858
4938
|
}
|
|
4859
4939
|
|
|
4860
|
-
// ../core/src/
|
|
4861
|
-
function
|
|
4862
|
-
|
|
4863
|
-
}
|
|
4864
|
-
async function readBundleOkfVersion(bundle) {
|
|
4865
|
-
const index = await backendFor(bundle).readReserved("", "index.md");
|
|
4940
|
+
// ../core/src/engine.ts
|
|
4941
|
+
async function readBundleOkfVersion(backend) {
|
|
4942
|
+
const index = await backend.readReserved("", "index.md");
|
|
4866
4943
|
if (!index) return void 0;
|
|
4867
|
-
const value =
|
|
4944
|
+
const value = parseLeadingFrontmatter(index.content, "index.md").okf_version;
|
|
4868
4945
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
4869
4946
|
}
|
|
4870
|
-
|
|
4947
|
+
function assertReadableConceptId(id) {
|
|
4871
4948
|
assertSafeConceptId(id);
|
|
4872
4949
|
const rel = pathFromConceptId(id);
|
|
4873
4950
|
if (isReservedFile(rel)) {
|
|
4874
4951
|
throw new InvalidInputError(`'${id}' is a reserved file (index.md / log.md), not a concept document.`);
|
|
4875
4952
|
}
|
|
4876
|
-
return backendFor(bundle).read(id);
|
|
4877
4953
|
}
|
|
4878
|
-
|
|
4954
|
+
async function readDocVersioned(backend, id) {
|
|
4955
|
+
assertReadableConceptId(id);
|
|
4956
|
+
return backend.read(id);
|
|
4957
|
+
}
|
|
4958
|
+
function isEnoent(err) {
|
|
4959
|
+
return typeof err === "object" && err !== null && err.code === "ENOENT";
|
|
4960
|
+
}
|
|
4879
4961
|
async function readManyExisting(backend, ids, onMalformed) {
|
|
4880
4962
|
try {
|
|
4881
4963
|
return await backend.readMany(ids);
|
|
@@ -4886,13 +4968,13 @@ async function readManyExisting(backend, ids, onMalformed) {
|
|
|
4886
4968
|
for (const id of ids) {
|
|
4887
4969
|
try {
|
|
4888
4970
|
out.push(await backend.read(id));
|
|
4889
|
-
} catch (
|
|
4890
|
-
if (isEnoent(
|
|
4891
|
-
if (
|
|
4892
|
-
onMalformed({ id, reason:
|
|
4971
|
+
} catch (candidate) {
|
|
4972
|
+
if (isEnoent(candidate)) continue;
|
|
4973
|
+
if (candidate instanceof MalformedDocumentError && onMalformed) {
|
|
4974
|
+
onMalformed({ id, reason: candidate.detail });
|
|
4893
4975
|
continue;
|
|
4894
4976
|
}
|
|
4895
|
-
throw
|
|
4977
|
+
throw candidate;
|
|
4896
4978
|
}
|
|
4897
4979
|
}
|
|
4898
4980
|
return out;
|
|
@@ -4902,25 +4984,25 @@ async function scanMatching(backend, filter, onSkip) {
|
|
|
4902
4984
|
const ids = await backend.list(filter.prefix);
|
|
4903
4985
|
const results = [];
|
|
4904
4986
|
for (const result of await readManyExisting(backend, ids, onSkip)) {
|
|
4905
|
-
if (
|
|
4906
|
-
results.push(result);
|
|
4987
|
+
if (matchesFilter(result.doc, filter)) results.push(result);
|
|
4907
4988
|
}
|
|
4908
4989
|
results.sort((a, b) => a.doc.id.localeCompare(b.doc.id));
|
|
4909
4990
|
return results;
|
|
4910
4991
|
}
|
|
4911
|
-
async function query(
|
|
4912
|
-
|
|
4913
|
-
return scanned.map((r) => r.doc);
|
|
4992
|
+
async function query(backend, filter = {}, options2 = {}) {
|
|
4993
|
+
return (await scanMatching(backend, filter, options2.onSkip)).map((result) => result.doc);
|
|
4914
4994
|
}
|
|
4915
|
-
async function queryHeads(
|
|
4916
|
-
const backend = backendFor(bundle);
|
|
4995
|
+
async function queryHeads(backend, filter = {}, options2 = {}) {
|
|
4917
4996
|
if (backend.queryHeads) {
|
|
4918
|
-
const rows = (await backend.queryHeads(filter)).filter((
|
|
4997
|
+
const rows = (await backend.queryHeads(filter)).filter((row) => matchesFilter(row, filter));
|
|
4919
4998
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
4920
4999
|
return rows;
|
|
4921
5000
|
}
|
|
4922
|
-
|
|
4923
|
-
|
|
5001
|
+
return (await scanMatching(backend, filter, options2.onSkip)).map(({ doc, version }) => ({
|
|
5002
|
+
id: doc.id,
|
|
5003
|
+
frontmatter: doc.frontmatter,
|
|
5004
|
+
version
|
|
5005
|
+
}));
|
|
4924
5006
|
}
|
|
4925
5007
|
function normalizeEdgeSelector(raw) {
|
|
4926
5008
|
if (raw.endsWith("/")) {
|
|
@@ -4933,25 +5015,19 @@ function normalizeEdgeSelector(raw) {
|
|
|
4933
5015
|
}
|
|
4934
5016
|
function matchesEdgeSelector(value, selectors) {
|
|
4935
5017
|
if (selectors === void 0) return true;
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
} else if (value === normalized) {
|
|
4940
|
-
return true;
|
|
4941
|
-
}
|
|
4942
|
-
}
|
|
4943
|
-
return false;
|
|
5018
|
+
return selectors.some(
|
|
5019
|
+
(selector2) => selector2.endsWith("/") ? value.startsWith(selector2) : value === selector2
|
|
5020
|
+
);
|
|
4944
5021
|
}
|
|
4945
|
-
function toSelectorList(
|
|
4946
|
-
if (
|
|
4947
|
-
return Array.isArray(
|
|
5022
|
+
function toSelectorList(value) {
|
|
5023
|
+
if (value === void 0) return void 0;
|
|
5024
|
+
return Array.isArray(value) ? value : [value];
|
|
4948
5025
|
}
|
|
4949
|
-
async function queryEdges(
|
|
5026
|
+
async function queryEdges(backend, filter = {}) {
|
|
4950
5027
|
const fromSelectors = toSelectorList(filter.from)?.map(normalizeEdgeSelector);
|
|
4951
5028
|
const toSelectors = toSelectorList(filter.to)?.map(normalizeEdgeSelector);
|
|
4952
|
-
const docs = await query(bundle);
|
|
4953
5029
|
const edges = [];
|
|
4954
|
-
for (const doc of
|
|
5030
|
+
for (const doc of await query(backend)) {
|
|
4955
5031
|
for (const link of parseLinksFromDoc(doc)) {
|
|
4956
5032
|
if (!matchesEdgeSelector(link.from, fromSelectors)) continue;
|
|
4957
5033
|
if (!matchesEdgeSelector(link.to, toSelectors)) continue;
|
|
@@ -4963,6 +5039,26 @@ async function queryEdges(bundle, filter = {}) {
|
|
|
4963
5039
|
return edges;
|
|
4964
5040
|
}
|
|
4965
5041
|
|
|
5042
|
+
// ../core/src/bundle.ts
|
|
5043
|
+
function backendFor(bundle) {
|
|
5044
|
+
return bundle.backend ?? new FilesystemBackend(bundle.root);
|
|
5045
|
+
}
|
|
5046
|
+
async function readBundleOkfVersion2(bundle) {
|
|
5047
|
+
return readBundleOkfVersion(backendFor(bundle));
|
|
5048
|
+
}
|
|
5049
|
+
async function readDocVersioned2(bundle, id) {
|
|
5050
|
+
return readDocVersioned(backendFor(bundle), id);
|
|
5051
|
+
}
|
|
5052
|
+
async function query2(bundle, filter = {}, options2 = {}) {
|
|
5053
|
+
return query(backendFor(bundle), filter, options2);
|
|
5054
|
+
}
|
|
5055
|
+
async function queryHeads2(bundle, filter = {}, options2 = {}) {
|
|
5056
|
+
return queryHeads(backendFor(bundle), filter, options2);
|
|
5057
|
+
}
|
|
5058
|
+
async function queryEdges2(bundle, filter = {}) {
|
|
5059
|
+
return queryEdges(backendFor(bundle), filter);
|
|
5060
|
+
}
|
|
5061
|
+
|
|
4966
5062
|
// ../core/src/kinds.ts
|
|
4967
5063
|
var CONVENTIONS_PREFIX = "conventions/";
|
|
4968
5064
|
var CONVENTION_TYPE = "Convention";
|
|
@@ -5555,7 +5651,7 @@ function applyQuerySelectionFilters(rows, params, kinds = []) {
|
|
|
5555
5651
|
// ../core/src/kinds-load.ts
|
|
5556
5652
|
async function loadKinds(bundle) {
|
|
5557
5653
|
const warnings = [];
|
|
5558
|
-
const docs = await
|
|
5654
|
+
const docs = await query2(bundle, { prefix: CONVENTIONS_PREFIX, type: CONVENTION_TYPE }, {
|
|
5559
5655
|
onSkip: ({ id, reason }) => warnings.push({
|
|
5560
5656
|
code: "KIND_CONVENTION_MALFORMED",
|
|
5561
5657
|
message: `skipped kind convention '${id}' with unparseable frontmatter: ${reason}`,
|
|
@@ -5838,13 +5934,13 @@ var BridgeService = class {
|
|
|
5838
5934
|
let outcome;
|
|
5839
5935
|
try {
|
|
5840
5936
|
outcome = await this.execute(before, request);
|
|
5841
|
-
} catch
|
|
5937
|
+
} catch {
|
|
5842
5938
|
outcome = {
|
|
5843
5939
|
reply: fail(
|
|
5844
5940
|
request.id,
|
|
5845
5941
|
request.bridge,
|
|
5846
5942
|
"RUNTIME",
|
|
5847
|
-
|
|
5943
|
+
"the View request failed"
|
|
5848
5944
|
)
|
|
5849
5945
|
};
|
|
5850
5946
|
}
|
|
@@ -5888,11 +5984,8 @@ var BridgeService = class {
|
|
|
5888
5984
|
let next;
|
|
5889
5985
|
try {
|
|
5890
5986
|
next = await this.subscriptionSnapshot();
|
|
5891
|
-
} catch
|
|
5892
|
-
return this.reload(
|
|
5893
|
-
launchId,
|
|
5894
|
-
error instanceof Error ? error.message : String(error)
|
|
5895
|
-
);
|
|
5987
|
+
} catch {
|
|
5988
|
+
return this.reload(launchId, "the View subscription could not be refreshed");
|
|
5896
5989
|
}
|
|
5897
5990
|
const after = await this.options.launches.resolve(launchId, true);
|
|
5898
5991
|
if (!after) return this.reload(launchId, "the View changed while its subscription was polled");
|
|
@@ -5927,7 +6020,7 @@ var BridgeService = class {
|
|
|
5927
6020
|
return { status: "reload-required", message };
|
|
5928
6021
|
}
|
|
5929
6022
|
async subscriptionSnapshot() {
|
|
5930
|
-
const rows = await
|
|
6023
|
+
const rows = await queryHeads2(this.options.bundle, {});
|
|
5931
6024
|
if (rows.length > MAX_SUBSCRIPTION_HEADS) {
|
|
5932
6025
|
throw new Error("the bundle is too large for the experimental View polling snapshot");
|
|
5933
6026
|
}
|
|
@@ -5942,7 +6035,7 @@ var BridgeService = class {
|
|
|
5942
6035
|
return { reply: null, openPageId: request.pageId };
|
|
5943
6036
|
}
|
|
5944
6037
|
try {
|
|
5945
|
-
const target = await
|
|
6038
|
+
const target = await readDocVersioned2(this.options.bundle, request.pageId);
|
|
5946
6039
|
if (!isAnyRegistryId(target.doc.id) || !parseRegistration(target.doc.id, target.doc.frontmatter)) {
|
|
5947
6040
|
throw new Error("invalid View target");
|
|
5948
6041
|
}
|
|
@@ -5963,13 +6056,13 @@ var BridgeService = class {
|
|
|
5963
6056
|
};
|
|
5964
6057
|
}
|
|
5965
6058
|
if (request.type === "query") {
|
|
5966
|
-
const rows = await
|
|
6059
|
+
const rows = await queryHeads2(this.options.bundle, {
|
|
5967
6060
|
...request.params.type ? { type: request.params.type } : {},
|
|
5968
6061
|
...request.params.prefix ? { prefix: request.params.prefix } : {}
|
|
5969
6062
|
});
|
|
5970
6063
|
const [registry, okfVersion] = await Promise.all([
|
|
5971
6064
|
loadKinds(this.options.bundle),
|
|
5972
|
-
|
|
6065
|
+
readBundleOkfVersion2(this.options.bundle)
|
|
5973
6066
|
]);
|
|
5974
6067
|
const result = boundedRows(
|
|
5975
6068
|
rows,
|
|
@@ -5984,9 +6077,9 @@ var BridgeService = class {
|
|
|
5984
6077
|
}
|
|
5985
6078
|
if (request.type === "read" || request.type === "read-versioned") {
|
|
5986
6079
|
const [result, registry, okfVersion] = await Promise.all([
|
|
5987
|
-
|
|
6080
|
+
readDocVersioned2(this.options.bundle, request.docId),
|
|
5988
6081
|
loadKinds(this.options.bundle),
|
|
5989
|
-
|
|
6082
|
+
readBundleOkfVersion2(this.options.bundle)
|
|
5990
6083
|
]);
|
|
5991
6084
|
if (Buffer.byteLength(result.doc.body, "utf8") > MAX_DOCUMENT_BODY_BYTES) {
|
|
5992
6085
|
return { reply: fail(request.id, request.bridge, "TOO_LARGE", "the document body exceeded the 1 MiB View limit") };
|
|
@@ -6005,7 +6098,7 @@ var BridgeService = class {
|
|
|
6005
6098
|
if (request.type === "render-document") {
|
|
6006
6099
|
let result;
|
|
6007
6100
|
try {
|
|
6008
|
-
result = await
|
|
6101
|
+
result = await readDocVersioned2(this.options.bundle, request.docId);
|
|
6009
6102
|
} catch (error) {
|
|
6010
6103
|
if (error?.code === "ENOENT") {
|
|
6011
6104
|
return {
|
|
@@ -6032,7 +6125,7 @@ var BridgeService = class {
|
|
|
6032
6125
|
};
|
|
6033
6126
|
}
|
|
6034
6127
|
if (request.type === "edges") {
|
|
6035
|
-
const edges = await
|
|
6128
|
+
const edges = await queryEdges2(this.options.bundle, request.params);
|
|
6036
6129
|
if (edges.length > MAX_EDGE_ROWS) {
|
|
6037
6130
|
return { reply: fail(request.id, request.bridge, "TOO_LARGE", `the edge query exceeded ${MAX_EDGE_ROWS} rows`) };
|
|
6038
6131
|
}
|