superbee 0.1.5 → 0.1.6

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 CHANGED
@@ -49,7 +49,7 @@ Ubuntu, or Docker. On Windows, Superbee keeps per-user operational state under
49
49
  Superbee currently has two npm release channels:
50
50
 
51
51
  - `latest` is the stable channel selected by bare `superbee`, including native Windows support.
52
- - `next` is the prerelease channel for future release candidates.
52
+ - `next` is the prerelease channel for release candidates.
53
53
 
54
54
  Install Superbee on Windows:
55
55
 
@@ -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,3 @@
1
+ export { BUNDLE_DESCRIPTOR_SCHEMA_V1, BUNDLE_DESCRIPTOR_V1 } from "./schema.js";
2
+ export type { SuperbeeBundleDescriptorV1 as BundleDescriptorV1 } from "./generated/bundle-descriptor-v1.js";
3
+ //# sourceMappingURL=index.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 yaml3 = require_js_yaml();
3136
- module2.exports = yaml3;
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
- if (/^---(?:\r?\n|$)/.test(raw)) {
3594
- const firstLineEnd = raw.indexOf("\n");
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 = (0, import_gray_matter.default)(raw, { engines: { yaml: yamlEngine } });
3628
+ parsed = yamlEngine.parse(split.yamlSource);
3603
3629
  } catch (err) {
3604
3630
  throw new MalformedDocumentError(context, err);
3605
3631
  }
3606
- const frontmatter2 = normalizeFrontmatter(parsed.data ?? {});
3607
- return { frontmatter: frontmatter2, body: parsed.content };
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 yaml3 = engines2.yaml.stringify(data).trim();
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 (yaml3 === "{}") return normalizeDocumentBodyForStorage(content);
3645
+ if (yaml4 === "{}") return normalizeDocumentBodyForStorage(content);
3620
3646
  return `---
3621
- ${newline(yaml3)}---
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
- function sha256Hex(input) {
4528
- return createHash3("sha256").update(input, "utf8").digest("hex");
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
- for (const m of body.matchAll(MD_LINK_RE)) {
4803
- if (typeof m.index === "number" && m.index > 0 && body[m.index - 1] === "!") continue;
4804
- out.push({ text: m[1] ?? "", href: m[2] ?? "" });
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/bundle.ts
4861
- function backendFor(bundle) {
4862
- return bundle.backend ?? new FilesystemBackend(bundle.root);
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 = parseMarkdown(index.content, "index.md").frontmatter.okf_version;
4944
+ const value = parseLeadingFrontmatter(index.content, "index.md").okf_version;
4868
4945
  return typeof value === "string" && value.trim() !== "" ? value : void 0;
4869
4946
  }
4870
- async function readDocVersioned(bundle, id) {
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
- var isEnoent = (err) => err?.code === "ENOENT";
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 (e) {
4890
- if (isEnoent(e)) continue;
4891
- if (e instanceof MalformedDocumentError && onMalformed) {
4892
- onMalformed({ id, reason: e.detail });
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 e;
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 (!matchesFilter(result.doc, filter)) continue;
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(bundle, filter = {}, options2 = {}) {
4912
- const scanned = await scanMatching(backendFor(bundle), filter, options2.onSkip);
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(bundle, filter = {}, options2 = {}) {
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((r) => matchesFilter(r, 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
- const scanned = await scanMatching(backend, filter, options2.onSkip);
4923
- return scanned.map(({ doc, version }) => ({ id: doc.id, frontmatter: doc.frontmatter, version }));
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
- for (const normalized of selectors) {
4937
- if (normalized.endsWith("/")) {
4938
- if (value.startsWith(normalized)) return true;
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(v) {
4946
- if (v === void 0) return void 0;
4947
- return Array.isArray(v) ? v : [v];
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(bundle, filter = {}) {
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 docs) {
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 query(bundle, { prefix: CONVENTIONS_PREFIX, type: CONVENTION_TYPE }, {
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 (error) {
5937
+ } catch {
5842
5938
  outcome = {
5843
5939
  reply: fail(
5844
5940
  request.id,
5845
5941
  request.bridge,
5846
5942
  "RUNTIME",
5847
- error instanceof Error ? error.message : String(error)
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 (error) {
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 queryHeads(this.options.bundle, {});
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 readDocVersioned(this.options.bundle, request.pageId);
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 queryHeads(this.options.bundle, {
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
- readBundleOkfVersion(this.options.bundle)
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
- readDocVersioned(this.options.bundle, request.docId),
6080
+ readDocVersioned2(this.options.bundle, request.docId),
5988
6081
  loadKinds(this.options.bundle),
5989
- readBundleOkfVersion(this.options.bundle)
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 readDocVersioned(this.options.bundle, request.docId);
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 queryEdges(this.options.bundle, request.params);
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
  }