content-query 0.1.0 → 0.2.0

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.
Files changed (47) hide show
  1. package/README.md +23 -1
  2. package/dist/{build-DSyoRxkZ.d.mts → build-DfKd2bpf.d.mts} +6 -5
  3. package/dist/{build-C5ef0kkR.mjs → build-Dxz7P1ur.mjs} +68 -30
  4. package/dist/build.d.mts +1 -1
  5. package/dist/build.mjs +1 -2
  6. package/dist/cli.d.mts +1 -1
  7. package/dist/cli.mjs +3 -3
  8. package/dist/computed.d.mts +19 -13
  9. package/dist/computed.mjs +6 -5
  10. package/dist/{content-Crag1Uch.d.mts → content-G69dPPuo.d.mts} +26 -16
  11. package/dist/{content-Dj2fQCJ5.mjs → content-N1gYshjg.mjs} +203 -77
  12. package/dist/{descriptor-Xbo9u5eR.d.mts → descriptor-D9Th5hzk.d.mts} +1 -2
  13. package/dist/{diagnostics-Dol6ANtq.mjs → diagnostics-Cu94mZhl.mjs} +16 -15
  14. package/dist/{dist-BQGVLZyl.mjs → dist-C7_FOzY_.mjs} +21 -12
  15. package/dist/{glob-DJmebCMM.mjs → glob-Bv0dpvCQ.mjs} +3 -3
  16. package/dist/index.d.mts +34 -16
  17. package/dist/index.mjs +7 -4
  18. package/dist/internal/markdown.d.mts +3 -5
  19. package/dist/internal/markdown.mjs +1 -2
  20. package/dist/internal.d.mts +12 -12
  21. package/dist/internal.mjs +7 -7
  22. package/dist/loaders.d.mts +5 -6
  23. package/dist/loaders.mjs +6 -5
  24. package/dist/{markdown-CZBL4Ux_.mjs → markdown-CHvBBJNa.mjs} +2 -2
  25. package/dist/next.d.mts +3 -4
  26. package/dist/next.mjs +2 -2
  27. package/dist/{operators-BQpLfJlx.mjs → operators-UqWUhKQJ.mjs} +2 -2
  28. package/dist/query.d.mts +22 -23
  29. package/dist/query.mjs +1 -2
  30. package/dist/{relational-types-DLniKi5S.d.mts → relational-types-DgK3rLuw.d.mts} +62 -29
  31. package/dist/{chunk-CJs4Fogs.mjs → rolldown-runtime-Bg1v5YCA.mjs} +2 -2
  32. package/dist/runtime.d.mts +2 -2
  33. package/dist/runtime.mjs +3 -4
  34. package/dist/{schema-CnCbMosm.mjs → schema-C5Str-E8.mjs} +1 -1
  35. package/dist/schema.d.mts +0 -2
  36. package/dist/schema.mjs +1 -2
  37. package/dist/{types-BPh2cBPs.d.mts → types-C-kdMblM.d.mts} +27 -6
  38. package/dist/{types-hmDOw87q.d.mts → types-ChaNhj42.d.mts} +14 -6
  39. package/dist/{validation-BvvjSUFc.mjs → validation-D_XdE1pF.mjs} +2 -2
  40. package/dist/{values-B7lo_2_x.mjs → values-BbTV4QT-.mjs} +109 -108
  41. package/dist/vite.d.mts +3 -5
  42. package/dist/vite.mjs +5 -5
  43. package/package.json +6 -4
  44. /package/dist/{errors-C8lWyiy2.mjs → errors-C2iuBM0G.mjs} +0 -0
  45. /package/dist/{github-slugger-BCAkwEOL.mjs → github-slugger-BMgR_Q0I.mjs} +0 -0
  46. /package/dist/{server-only-CIE-FHx0.mjs → server-only-CIJUlyL-.mjs} +0 -0
  47. /package/dist/{types-DcvHRmxO.d.mts → types-Dh-Sydyw.d.mts} +0 -0
@@ -1,7 +1,7 @@
1
- import { a as invalidQuery, n as contentError, t as ContentError } from "./errors-C8lWyiy2.mjs";
2
- import { a as detachSelection, c as isScalar, i as detach, n as compareStrings, s as equal, t as compare } from "./values-B7lo_2_x.mjs";
3
- import { t as assertServerOnly } from "./server-only-CIE-FHx0.mjs";
4
- import { _ as not, t as and, x as validateExpression, y as or } from "./operators-BQpLfJlx.mjs";
1
+ import { a as invalidQuery, n as contentError, t as ContentError } from "./errors-C2iuBM0G.mjs";
2
+ import { a as detachSelection, c as isScalar, i as detach, n as compareStrings, s as equal, t as compare } from "./values-BbTV4QT-.mjs";
3
+ import { t as assertServerOnly } from "./server-only-CIJUlyL-.mjs";
4
+ import { _ as not, t as and, x as validateExpression, y as or } from "./operators-UqWUhKQJ.mjs";
5
5
  //#region src/artifacts/types.ts
6
6
  const CODEC_VERSION = "devalue-6.0.2";
7
7
  //#endregion
@@ -144,11 +144,42 @@ function isRelationship(value) {
144
144
  ].includes(String(value.referenceSide));
145
145
  }
146
146
  //#endregion
147
+ //#region src/shared/concurrency.ts
148
+ /**
149
+ * Maps items through an asynchronous callback with at most `limit` callbacks in flight.
150
+ * Results keep input order; the first rejection rejects the whole map after started work settles.
151
+ *
152
+ * @param items - Values to process.
153
+ * @param limit - Maximum number of concurrent callbacks; values below one are treated as one.
154
+ * @param callback - Asynchronous work for one item and its index.
155
+ * @returns The callback results in input order.
156
+ */
157
+ async function mapConcurrent(items, limit, callback) {
158
+ const results = Array.from({ length: items.length });
159
+ let next = 0;
160
+ let failure;
161
+ /** Claims the next unprocessed item until the list is exhausted or work has failed. */
162
+ async function worker() {
163
+ while (next < items.length && !failure) {
164
+ const index = next++;
165
+ try {
166
+ results[index] = await callback(items[index], index);
167
+ } catch (cause) {
168
+ failure ??= { cause };
169
+ }
170
+ }
171
+ }
172
+ const workers = Array.from({ length: Math.min(Math.max(1, limit), items.length) }, worker);
173
+ await Promise.all(workers);
174
+ if (failure) throw failure.cause;
175
+ return results;
176
+ }
177
+ //#endregion
147
178
  //#region src/query/clauses.ts
148
179
  /** Checks scalar field selection for both public query frontends without a schema field catalog. */
149
180
  function checkedFields(registry, collection, fields) {
150
181
  const scope = registry[collection];
151
- if (!scope || fields.some((field) => typeof field !== "string" || !field || field === "_adjacent" || Object.hasOwn(scope.relationships, field)) || new Set(fields).size !== fields.length) invalidQuery("Selection requires distinct prepared fields; use relationship or adjacency selection explicitly.");
182
+ if (!scope || fields.some((field) => typeof field !== "string" || !field || field === "_adjacent" || field === "_payloads" || Object.hasOwn(scope.relationships, field)) || new Set(fields).size !== fields.length) invalidQuery("Selection requires distinct prepared fields; use relationship or adjacency selection explicitly.");
152
183
  return [...fields];
153
184
  }
154
185
  /** Checks one sort clause with the same cardinality and duplicate rules in either API. */
@@ -164,6 +195,35 @@ function checkedPagination(value, many) {
164
195
  if (!many || !Number.isSafeInteger(value) || value < 0) invalidQuery("Pagination requires a nonnegative safe integer and a many-valued scope.");
165
196
  return value;
166
197
  }
198
+ /** Finds a payload declaration that queries may request, rejecting unknown names. */
199
+ function payloadDescriptor(registry, collection, name) {
200
+ const payloads = registry[collection]?.payloads ?? {};
201
+ if (typeof name !== "string" || !Object.hasOwn(payloads, name)) invalidQuery(`Unknown payload "${String(name)}" for collection "${collection}".`);
202
+ return payloads[name];
203
+ }
204
+ /** Checks one payload request against the collection's payload names and variant keys. */
205
+ function checkedPayload(registry, collection, name, request) {
206
+ const { variants } = payloadDescriptor(registry, collection, name);
207
+ if (request === true || request === void 0) {
208
+ if (variants.length) invalidQuery(`Payload "${name}" requires variant keys: ${variants.join(", ")}.`);
209
+ return { variant: {} };
210
+ }
211
+ const variant = request;
212
+ if (!variant || typeof variant !== "object" || Array.isArray(variant) || Object.keys(variant).length !== variants.length || variants.some((key) => !Object.hasOwn(variant, key) || typeof variant[key] !== "string")) invalidQuery(`Payload "${name}" requires exactly these string variant keys: ${variants.join(", ") || "none"}.`);
213
+ return { variant: Object.fromEntries([...variants].sort().map((key) => [key, variant[key]])) };
214
+ }
215
+ /** Compiles a payloads option into plan requests, omitting payloads set to false. */
216
+ function checkedPayloads(registry, collection, payloads) {
217
+ const requested = Object.create(null);
218
+ for (const [name, request] of Object.entries(payloads)) {
219
+ if (request === false || request === void 0) {
220
+ payloadDescriptor(registry, collection, name);
221
+ continue;
222
+ }
223
+ requested[name] = checkedPayload(registry, collection, name, request);
224
+ }
225
+ return Object.keys(requested).length ? requested : void 0;
226
+ }
167
227
  //#endregion
168
228
  //#region src/query/plan.ts
169
229
  /** Starts a fresh query without binding a content revision until execution. */
@@ -272,7 +332,10 @@ function relationalWhere(registry, collection, where) {
272
332
  validateExpression(expression);
273
333
  return detach(expression);
274
334
  }
275
- /** Compiles Drizzle-style columns/with options into the shared immutable query plan. */
335
+ /**
336
+ * Compiles Drizzle-style columns/with options into the shared immutable query plan.
337
+ * Payloads are allowed wherever adjacency is, so sibling scopes never load them.
338
+ */
276
339
  function relationalPlan(registry, collection, options = {}, many = true, allowAdjacent = true, pagination = true) {
277
340
  if (!Object.hasOwn(registry, collection)) invalidQuery(`Unknown collection "${collection}".`);
278
341
  record$1(options, "Query");
@@ -282,7 +345,7 @@ function relationalPlan(registry, collection, options = {}, many = true, allowAd
282
345
  "with",
283
346
  ...many ? ["orderBy"] : [],
284
347
  ...many && pagination ? ["limit", "offset"] : [],
285
- ...allowAdjacent ? ["adjacent"] : []
348
+ ...allowAdjacent ? ["adjacent", "payloads"] : []
286
349
  ];
287
350
  if (Object.keys(options).some((key) => !allowed.includes(key))) invalidQuery("Unknown relational query option or unsupported scope option.");
288
351
  const plan = emptyPlan(collection);
@@ -317,6 +380,11 @@ function relationalPlan(registry, collection, options = {}, many = true, allowAd
317
380
  for (const [field, direction] of Object.entries(options.orderBy)) plan.order = checkedOrder(plan, field, direction, many);
318
381
  }
319
382
  for (const key of ["limit", "offset"]) if (options[key] !== void 0) plan[key] = checkedPagination(options[key], many);
383
+ if (options.payloads !== void 0) {
384
+ record$1(options.payloads, "payloads");
385
+ const payloads = checkedPayloads(registry, collection, options.payloads);
386
+ if (payloads) plan.payloads = payloads;
387
+ }
320
388
  if (options.adjacent !== void 0) plan.adjacent = options.adjacent === true ? true : relationalPlan(registry, collection, options.adjacent, true, false, false);
321
389
  return plan;
322
390
  }
@@ -523,6 +591,13 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
523
591
  [name]: nested
524
592
  } });
525
593
  },
594
+ withPayload(name, variant) {
595
+ if (!allowAdjacent || Object.hasOwn(plan.payloads ?? {}, name)) invalidQuery("Payloads cannot be repeated or requested in adjacent scopes.");
596
+ return branch({ payloads: {
597
+ ...plan.payloads,
598
+ [name]: checkedPayload(registry, plan.collection, name, variant)
599
+ } });
600
+ },
526
601
  selectAdjacent(configure) {
527
602
  if (!allowAdjacent || plan.adjacent !== void 0) invalidQuery("Adjacency cannot be repeated or selected recursively.");
528
603
  if (configure === void 0) return branch({ adjacent: true });
@@ -541,6 +616,7 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
541
616
  if (!root) invalidQuery("Nested builders have no terminal methods.");
542
617
  return run(plan, "all");
543
618
  },
619
+ /** Executes a selected root query, matching direct await behavior. */
544
620
  execute() {
545
621
  if (!root) invalidQuery("Nested builders have no terminal methods.");
546
622
  return run(plan, "all");
@@ -567,7 +643,9 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
567
643
  /** Defers collection validation until from(), preserving the immutable selection across reuse. */
568
644
  function createSelect(registry, run, fields) {
569
645
  const selected = [...fields];
570
- return { from(collection) {
646
+ return {
647
+ /** Binds the current registry and prepares a reusable root query. */
648
+ from(collection) {
571
649
  const current = registry();
572
650
  if (!Object.hasOwn(current, collection)) invalidQuery(`Unknown collection "${collection}".`);
573
651
  const plan = emptyPlan(collection);
@@ -718,6 +796,7 @@ function neighborScope(plan, records, preserveOrder, scopes, revision) {
718
796
  exclude: void 0,
719
797
  with: {},
720
798
  adjacent: void 0,
799
+ payloads: void 0,
721
800
  limit: void 0,
722
801
  offset: void 0
723
802
  } : selection;
@@ -739,16 +818,20 @@ function neighborScope(plan, records, preserveOrder, scopes, revision) {
739
818
  }
740
819
  return scope;
741
820
  }
742
- /** Projects one entry and requested relationships/adjacency from one pinned revision. */
743
- function project(record, plan, revision, scopes, scopeRecords, preserveScopeOrder = false) {
821
+ /**
822
+ * Projects one entry and requested relationships/adjacency from one pinned revision.
823
+ * Requested payloads are recorded for the caller to load after projection.
824
+ */
825
+ function project(record, plan, revision, scopes, scopeRecords, requests, preserveScopeOrder = false) {
744
826
  if (!plan.select && !plan.allFields && !plan.adjacent) invalidQuery("Row-returning queries require select().");
745
- const result = detachSelection(record, plan.allFields ? Object.keys(record).filter((field) => !plan.exclude?.includes(field)) : plan.select ?? []);
827
+ const fields = plan.allFields ? Object.keys(record).filter((field) => !plan.exclude?.includes(field)) : plan.select ?? [];
828
+ const result = detachSelection(record, fields);
746
829
  for (const [name, nested] of Object.entries(plan.with)) {
747
830
  const relation = revision.registry[plan.collection].relationships[name];
748
831
  if (!relation || relation.collection !== nested.collection || relation.type === "one" && (nested.limit !== void 0 || nested.offset !== void 0 || nested.order.length > 0)) invalidQuery(`Relationship "${name}" no longer matches the prepared query scope.`);
749
832
  const candidates = revision.relations.get(relationKey(plan.collection, name))?.get(record.id) ?? [];
750
833
  const preserveOrder = relation.referenceSide === "from" && Array.isArray(record[relation.from]);
751
- const selected = pageRecords(candidates, nested, revision, preserveOrder).map((entry) => project(entry, nested, revision, scopes, candidates, preserveOrder));
834
+ const selected = pageRecords(candidates, nested, revision, preserveOrder).map((entry) => project(entry, nested, revision, scopes, candidates, requests, preserveOrder));
752
835
  Object.defineProperty(result, name, {
753
836
  value: relation.type === "many" ? selected : selected[0] ?? null,
754
837
  enumerable: true,
@@ -763,25 +846,39 @@ function project(record, plan, revision, scopes, scopeRecords, preserveScopeOrde
763
846
  const previous = index === void 0 ? void 0 : scope.records[index - 1];
764
847
  const next = index === void 0 ? void 0 : scope.records[index + 1];
765
848
  result._adjacent = {
766
- previous: previous ? project(previous, scope.plan, revision, scopes, candidates) : null,
767
- next: next ? project(next, scope.plan, revision, scopes, candidates) : null
849
+ previous: previous ? project(previous, scope.plan, revision, scopes, candidates, requests) : null,
850
+ next: next ? project(next, scope.plan, revision, scopes, candidates, requests) : null
768
851
  };
769
852
  }
853
+ if (plan.payloads) requests.push({
854
+ target: result,
855
+ collection: plan.collection,
856
+ id: record.id,
857
+ payloads: plan.payloads
858
+ });
770
859
  return result;
771
860
  }
772
- /** Runs the shared JavaScript executor; future adapters can execute the same plan. */
773
- async function executeQuery(revision, plan, terminal) {
861
+ /**
862
+ * Runs the shared JavaScript executor; future adapters can execute the same plan.
863
+ * Rows that requested payloads are appended to `requests` for loading after execution.
864
+ */
865
+ async function executeQuery(revision, plan, terminal, requests = []) {
774
866
  const collection = revision.collections[plan.collection];
775
867
  if (!collection) invalidQuery(`Unknown collection "${plan.collection}".`);
776
- if (terminal === "count") return queryCandidates(collection.records, plan).filter((record) => plan.filters.every((expression) => matches(record, expression, revision, plan.collection))).length;
868
+ if (terminal === "count") {
869
+ if (plan.payloads) invalidQuery("Counts cannot request payloads.");
870
+ return queryCandidates(collection.records, plan).filter((record) => plan.filters.every((expression) => matches(record, expression, revision, plan.collection))).length;
871
+ }
777
872
  if (!plan.select && !plan.allFields && !plan.adjacent) invalidQuery("Row-returning queries require select().");
778
873
  const records = pageRecords(queryCandidates(collection.records, plan), plan, revision);
779
874
  const scopes = /* @__PURE__ */ new WeakMap();
780
- return terminal === "first" ? records[0] ? project(records[0], plan, revision, scopes, collection.records) : void 0 : records.map((record) => project(record, plan, revision, scopes, collection.records));
875
+ return terminal === "first" ? records[0] ? project(records[0], plan, revision, scopes, collection.records, requests) : void 0 : records.map((record) => project(record, plan, revision, scopes, collection.records, requests));
781
876
  }
782
877
  //#endregion
783
878
  //#region src/runtime/content.ts
784
879
  assertServerOnly();
880
+ /** Maximum payload loads in flight for one query. */
881
+ const PAYLOAD_CONCURRENCY = 16;
785
882
  /** Pins the latest valid revision for an entire asynchronous operation. */
786
883
  async function pinned(state, operation) {
787
884
  if (state.error) throw state.error;
@@ -797,38 +894,26 @@ async function pinned(state, operation) {
797
894
  revision.active--;
798
895
  }
799
896
  }
800
- const idSets = /* @__PURE__ */ new WeakMap();
801
- /** Indexes immutable prepared records once, so body/render lookups avoid collection scans. */
802
- function entryIds(records) {
803
- let ids = idSets.get(records);
804
- if (!ids) {
805
- ids = new Set(records.map((record) => record.id));
806
- idSets.set(records, ids);
807
- }
808
- return ids;
809
- }
810
- /** Looks up an entry and lazily loads only its revision-specific payload. */
811
- async function loadPayload(revision, collectionName, id) {
812
- const collection = revision.collections[collectionName];
813
- if (!collection || typeof collectionName !== "string" || typeof id !== "string") invalidQuery("Body/render access requires a registered collection and string ID.");
814
- if (!entryIds(collection.records).has(id)) throw new ContentError({
815
- code: "entry-not-found",
816
- collection: collectionName,
817
- id,
818
- message: `Entry "${id}" does not exist in "${collectionName}".`
819
- });
820
- const key = JSON.stringify([collectionName, id]);
897
+ /** Checks a decoded built-in payload before any of its values reach a query result. */
898
+ function validBuiltinPayload(payload) {
899
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return false;
900
+ const { body, markdown, rendered } = payload;
901
+ return (body === void 0 || typeof body === "string") && (markdown === void 0 || typeof markdown === "string") && (rendered === void 0 || !!rendered && typeof rendered.html === "string" && Array.isArray(rendered.headings) && rendered.headings.every((heading) => !!heading && Number.isInteger(heading.depth) && heading.depth >= 1 && heading.depth <= 6 && typeof heading.slug === "string" && typeof heading.text === "string"));
902
+ }
903
+ /** Lazily loads one entry's built-in payload once per revision, retrying after failures. */
904
+ function loadBuiltin(revision, collection, id) {
905
+ const key = JSON.stringify([collection, id]);
821
906
  let loaded = revision.payloadCache.get(key);
822
907
  if (!loaded) {
823
908
  loaded = Promise.resolve().then(async () => {
824
- const payload = await (collection.payloads.get(id)?.() ?? {});
825
- if (!payload || typeof payload !== "object" || Array.isArray(payload) || payload.body !== void 0 && typeof payload.body !== "string" || payload.markdown !== void 0 && typeof payload.markdown !== "string" || payload.rendered !== void 0 && (!payload.rendered || typeof payload.rendered.html !== "string" || !Array.isArray(payload.rendered.headings) || payload.rendered.headings.some((heading) => !heading || !Number.isInteger(heading.depth) || heading.depth < 1 || heading.depth > 6 || typeof heading.slug !== "string" || typeof heading.text !== "string"))) throw new Error("Invalid prepared payload shape.");
909
+ const payload = await revision.collections[collection].builtins.get(id)?.() ?? {};
910
+ if (!validBuiltinPayload(payload)) throw new Error("Invalid prepared payload shape.");
826
911
  return payload;
827
912
  }).catch((cause) => {
828
913
  revision.payloadCache.delete(key);
829
914
  throw contentError(cause, {
830
915
  code: "artifact-error",
831
- collection: collectionName,
916
+ collection,
832
917
  id,
833
918
  message: "Could not load the prepared entry payload."
834
919
  });
@@ -837,10 +922,84 @@ async function loadPayload(revision, collectionName, id) {
837
922
  }
838
923
  return loaded;
839
924
  }
925
+ /** Returns supplied or eagerly compiled output, or renders captured Markdown once per revision. */
926
+ async function renderedPayload(revision, collection, id) {
927
+ const payload = await loadBuiltin(revision, collection, id);
928
+ if (payload.rendered) return payload.rendered;
929
+ if (payload.markdown === void 0) throw new ContentError({
930
+ code: "not-renderable",
931
+ collection,
932
+ id,
933
+ message: "This entry has no supplied output or supported rendering path."
934
+ });
935
+ const key = JSON.stringify([collection, id]);
936
+ let rendered = revision.renderCache.get(key);
937
+ if (!rendered) {
938
+ rendered = Promise.resolve().then(() => {
939
+ if (!revision.renderMarkdown) throw new Error("Missing packaged Markdown renderer.");
940
+ return revision.renderMarkdown(payload.markdown);
941
+ }).catch((cause) => {
942
+ revision.renderCache.delete(key);
943
+ throw contentError(cause, {
944
+ code: "render-error",
945
+ collection,
946
+ id,
947
+ message: "Markdown rendering failed."
948
+ });
949
+ });
950
+ revision.renderCache.set(key, rendered);
951
+ }
952
+ return rendered;
953
+ }
954
+ /** Loads one requested payload value from the pinned revision. */
955
+ async function loadPayload(revision, collection, id, name) {
956
+ if (name === "_body") return (await loadBuiltin(revision, collection, id)).body;
957
+ if (name === "_rendered") return renderedPayload(revision, collection, id);
958
+ invalidQuery(`Payload "${name}" no longer matches the prepared collection.`);
959
+ }
960
+ /**
961
+ * Loads every requested payload with bounded concurrency, then attaches detached copies under
962
+ * `_payloads`. Each distinct payload loads once; rows that share an entry get independent values.
963
+ */
964
+ async function attachPayloads(revision, requests) {
965
+ if (!requests.length) return;
966
+ const loads = /* @__PURE__ */ new Map();
967
+ for (const request of requests) for (const name of Object.keys(request.payloads)) {
968
+ const key = JSON.stringify([
969
+ request.collection,
970
+ request.id,
971
+ name,
972
+ request.payloads[name]
973
+ ]);
974
+ if (!loads.has(key)) loads.set(key, {
975
+ collection: request.collection,
976
+ id: request.id,
977
+ name
978
+ });
979
+ }
980
+ const keys = [...loads.keys()];
981
+ const values = await mapConcurrent(keys, PAYLOAD_CONCURRENCY, (key) => {
982
+ const { collection, id, name } = loads.get(key);
983
+ return loadPayload(revision, collection, id, name);
984
+ });
985
+ const loaded = new Map(keys.map((key, index) => [key, values[index]]));
986
+ for (const request of requests) request.target._payloads = Object.fromEntries(Object.keys(request.payloads).map((name) => [name, detach(loaded.get(JSON.stringify([
987
+ request.collection,
988
+ request.id,
989
+ name,
990
+ request.payloads[name]
991
+ ])))]));
992
+ }
840
993
  /** Creates the initialized runtime without importing source configuration or schemas. */
841
994
  function createRuntime(state) {
842
- /** Pins both query frontends to exactly the same revision and backend executor. */
843
- const run = (plan, terminal) => pinned(state, (revision) => revision.execute ? revision.execute(normalizePlan(plan), terminal) : executeQuery(revision, normalizePlan(plan), terminal));
995
+ /** Pins query execution and payload loading to exactly the same revision and executor. */
996
+ const run = (plan, terminal) => pinned(state, async (revision) => {
997
+ const normalized = normalizePlan(plan);
998
+ const requests = [];
999
+ const result = revision.execute ? await revision.execute(normalized, terminal, requests) : await executeQuery(revision, normalized, terminal, requests);
1000
+ await attachPayloads(revision, requests);
1001
+ return result;
1002
+ });
844
1003
  /** Reads the current registry without capturing a development revision in either API. */
845
1004
  const registry = () => state.registry ?? state.revision?.registry ?? {};
846
1005
  return {
@@ -850,39 +1009,6 @@ function createRuntime(state) {
850
1009
  query: createQueryNamespace(registry, run),
851
1010
  count(collection, options = {}) {
852
1011
  return run(relationalPlan(registry(), collection, options), "count");
853
- },
854
- readBody(collection, id) {
855
- return pinned(state, async (revision) => (await loadPayload(revision, collection, id)).body);
856
- },
857
- render(collection, id) {
858
- return pinned(state, async (revision) => {
859
- const payload = await loadPayload(revision, collection, id);
860
- if (payload.rendered) return detach(payload.rendered);
861
- if (payload.markdown === void 0) throw new ContentError({
862
- code: "not-renderable",
863
- collection,
864
- id,
865
- message: "This entry has no supplied output or supported rendering path."
866
- });
867
- const key = JSON.stringify([collection, id]);
868
- let rendered = revision.renderCache.get(key);
869
- if (!rendered) {
870
- rendered = Promise.resolve().then(() => {
871
- if (!revision.renderMarkdown) throw new Error("Missing packaged Markdown renderer.");
872
- return revision.renderMarkdown(payload.markdown);
873
- }).catch((cause) => {
874
- revision.renderCache.delete(key);
875
- throw contentError(cause, {
876
- code: "render-error",
877
- collection,
878
- id,
879
- message: "Markdown rendering failed."
880
- });
881
- });
882
- revision.renderCache.set(key, rendered);
883
- }
884
- return detach(await rendered);
885
- });
886
1012
  }
887
1013
  };
888
1014
  }
@@ -1,5 +1,4 @@
1
- import { f as MaybePromise } from "./types-hmDOw87q.mjs";
2
-
1
+ import { p as MaybePromise } from "./types-ChaNhj42.mjs";
3
2
  //#region src/loaders/descriptor.d.ts
4
3
  type GlobOptions = {
5
4
  pattern: string | string[];
@@ -1,5 +1,5 @@
1
- import { t as ContentError } from "./errors-C8lWyiy2.mjs";
2
- import { o as encode, r as decode } from "./values-B7lo_2_x.mjs";
1
+ import { t as ContentError } from "./errors-C2iuBM0G.mjs";
2
+ import { o as encode, r as decode } from "./values-BbTV4QT-.mjs";
3
3
  //#region src/runtime/diagnostics.ts
4
4
  /** Transports Error nodes as records while preserving the supported diagnostic value graph. */
5
5
  function diagnosticGraph(value, causes, restore, seen = /* @__PURE__ */ new Map()) {
@@ -50,20 +50,21 @@ function diagnosticGraph(value, causes, restore, seen = /* @__PURE__ */ new Map(
50
50
  /** Encodes contextual development failures without reducing BigInts or structured issues to JSON. */
51
51
  function serializeContentError(error) {
52
52
  const causes = /* @__PURE__ */ new Set();
53
+ const details = {
54
+ code: error.code,
55
+ message: error.message,
56
+ stack: error.stack,
57
+ operation: error.operation,
58
+ collection: error.collection,
59
+ id: error.id,
60
+ source: error.source,
61
+ path: error.path,
62
+ issues: error.issues,
63
+ cause: error.cause,
64
+ diagnostics: error.diagnostics
65
+ };
53
66
  return encode({
54
- error: diagnosticGraph({
55
- code: error.code,
56
- message: error.message,
57
- stack: error.stack,
58
- operation: error.operation,
59
- collection: error.collection,
60
- id: error.id,
61
- source: error.source,
62
- path: error.path,
63
- issues: error.issues,
64
- cause: error.cause,
65
- diagnostics: error.diagnostics
66
- }, causes, false),
67
+ error: diagnosticGraph(details, causes, false),
67
68
  causes: [...causes]
68
69
  });
69
70
  }