content-query 0.3.0 → 0.4.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.
- package/README.md +21 -1
- package/dist/{build-CI4s0oFP.mjs → build-CcqIpkes.mjs} +709 -39
- package/dist/{build-jKnjDjQE.d.mts → build-DL1GzmRy.d.mts} +12 -5
- package/dist/build.d.mts +1 -1
- package/dist/build.mjs +1 -1
- package/dist/cli.mjs +14 -8
- package/dist/computed.d.mts +2 -2
- package/dist/{content-N1gYshjg.mjs → content-BXrgP7nL.mjs} +271 -81
- package/dist/{content-lwPxE9Yu.d.mts → content-CwTKqRs9.d.mts} +39 -14
- package/dist/{types-FmUJ3cH1.d.mts → descriptor-bcPa6XLk.d.mts} +17 -1
- package/dist/{diagnostics-Cu94mZhl.mjs → diagnostics-DmUZtrJ6.mjs} +3 -1
- package/dist/{errors-C2iuBM0G.mjs → errors-Bfd0R4_P.mjs} +16 -1
- package/dist/file-DSOcdFj0.mjs +81 -0
- package/dist/{glob-Bv0dpvCQ.mjs → glob-BXJuwy_p.mjs} +94 -6
- package/dist/index.d.mts +61 -18
- package/dist/index.mjs +1 -1
- package/dist/internal.d.mts +11 -4
- package/dist/internal.mjs +29 -5
- package/dist/loaders.d.mts +1 -2
- package/dist/loaders.mjs +2 -81
- package/dist/next.d.mts +1 -1
- package/dist/next.mjs +2 -2
- package/dist/{operators-UqWUhKQJ.mjs → operators-Cwy8Kx4o.mjs} +88 -2
- package/dist/query-style-eXENQJ0O.d.mts +22 -0
- package/dist/query.d.mts +25 -2
- package/dist/query.mjs +1 -1
- package/dist/{relational-types-B45zM34W.d.mts → relational-types-C8xJtLG5.d.mts} +113 -38
- package/dist/runtime.d.mts +3 -2
- package/dist/runtime.mjs +1 -1
- package/dist/types-DbFfF6JE.d.mts +181 -0
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +2 -2
- package/package.json +1 -1
- package/dist/descriptor-BUPT2J7X.d.mts +0 -18
- package/dist/types-BC8gVJ6u.d.mts +0 -69
- package/dist/validation-D_XdE1pF.mjs +0 -84
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { n as ContentRenderResult } from "./types-Dh-Sydyw.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { _ as RelationshipsOf, g as Relationship, h as QueryData, i as CollectionRegistry } from "./types-DbFfF6JE.mjs";
|
|
3
|
+
import { b as QueryRegistry, n as RelationalQueries, t as RelationalCountOptions, u as Query, y as QueryPlan } from "./relational-types-C8xJtLG5.mjs";
|
|
4
|
+
import { i as QueryStyleMember, n as QueryStyle, r as QueryStyleDisabled, t as MembersOf } from "./query-style-eXENQJ0O.mjs";
|
|
4
5
|
//#region src/shared/errors.d.ts
|
|
5
6
|
type ContentErrorCode = "variant-not-found" | "not-renderable" | "source-error" | "validation-error" | "duplicate-id" | "invalid-reference" | "invalid-query" | "artifact-error" | "render-error";
|
|
6
7
|
type ContentDiagnostic = {
|
|
@@ -11,6 +12,10 @@ type ContentDiagnostic = {
|
|
|
11
12
|
id?: string;
|
|
12
13
|
source?: string;
|
|
13
14
|
path?: readonly PropertyKey[];
|
|
15
|
+
/** The custom payload being resolved or loaded. */
|
|
16
|
+
payload?: string;
|
|
17
|
+
/** The payload's variant combination, with keys in sorted order. */
|
|
18
|
+
variant?: Readonly<Record<string, string>>;
|
|
14
19
|
issues?: readonly unknown[];
|
|
15
20
|
cause?: unknown;
|
|
16
21
|
};
|
|
@@ -24,6 +29,8 @@ declare class ContentError extends Error {
|
|
|
24
29
|
readonly id?: string;
|
|
25
30
|
readonly source?: string;
|
|
26
31
|
readonly path?: readonly PropertyKey[];
|
|
32
|
+
readonly payload?: string;
|
|
33
|
+
readonly variant?: Readonly<Record<string, string>>;
|
|
27
34
|
readonly issues?: readonly unknown[];
|
|
28
35
|
readonly diagnostics: readonly ContentDiagnostic[];
|
|
29
36
|
/** Creates one failure or a grouped report preserving individual causes and issues. */
|
|
@@ -41,17 +48,12 @@ type CheckRelation<Registry extends CollectionRegistry, Name extends keyof Regis
|
|
|
41
48
|
/** Registry-level relationship checks require the complete inferred collection map. */
|
|
42
49
|
type InvalidRelationships<Registry extends CollectionRegistry> = { [Name in keyof Registry]: { [Link in keyof RelationshipsOf<Registry[Name]>]: RelationshipsOf<Registry[Name]>[Link] extends Relationship ? CheckRelation<Registry, Name, RelationshipsOf<Registry[Name]>[Link]> : "invalid-relationship"; }[keyof RelationshipsOf<Registry[Name]>]; }[keyof Registry];
|
|
43
50
|
//#endregion
|
|
44
|
-
//#region src/query/select.d.ts
|
|
45
|
-
/** A selection whose collection and selected result are inferred when from() is supplied. */
|
|
46
|
-
type SelectFrom<Registry extends CollectionRegistry, Keys extends readonly string[]> = {
|
|
47
|
-
/** Binds the collection and rejects selected keys that are absent from its prepared data type. */
|
|
48
|
-
from<Name extends keyof Registry & string>(collection: Name & (Exclude<Keys[number], keyof QueryData<Registry[NoInfer<Name>]>> extends never ? unknown : never)): Query<Registry, Name, Keys extends readonly [] ? QueryData<Registry[Name]> : { [Key in Keys[number]]-?: Key extends keyof QueryData<Registry[Name]> ? QueryData<Registry[Name]>[Key] : never; }, true>;
|
|
49
|
-
};
|
|
50
|
-
//#endregion
|
|
51
51
|
//#region src/runtime/revision.d.ts
|
|
52
52
|
type QueryRecord = Record<string, unknown> & {
|
|
53
53
|
id: string;
|
|
54
54
|
};
|
|
55
|
+
/** Custom payload loaders by payload name, entry ID, and canonical variant key. */
|
|
56
|
+
type CustomPayloadTable = ReadonlyMap<string, ReadonlyMap<string, ReadonlyMap<string, () => Promise<unknown>>>>;
|
|
55
57
|
/** The built-in side payload shared by an entry's `_body` and `_rendered` payloads. */
|
|
56
58
|
type BuiltinPayload = {
|
|
57
59
|
body?: string;
|
|
@@ -63,6 +65,11 @@ type PreparedCollection = {
|
|
|
63
65
|
relationships: Record<string, Relationship>;
|
|
64
66
|
/** Lazy built-in payloads, present only for entries with a body or rendered output. */
|
|
65
67
|
builtins: ReadonlyMap<string, () => Promise<BuiltinPayload>>;
|
|
68
|
+
/**
|
|
69
|
+
* Lazy custom payloads by payload name, entry ID, and canonical variant key. A missing variant
|
|
70
|
+
* key means the entry has no such combination.
|
|
71
|
+
*/
|
|
72
|
+
payloads?: CustomPayloadTable;
|
|
66
73
|
sources?: ReadonlyMap<string, string | undefined>;
|
|
67
74
|
};
|
|
68
75
|
type PreparedRevision = {
|
|
@@ -70,9 +77,12 @@ type PreparedRevision = {
|
|
|
70
77
|
collections: Record<string, PreparedCollection>;
|
|
71
78
|
relations: Map<string, Map<string, readonly QueryRecord[]>>;
|
|
72
79
|
active: number;
|
|
73
|
-
|
|
80
|
+
/** Built-in payloads keyed by collection and ID; custom payloads also by name and variant. */
|
|
81
|
+
payloadCache: Map<string, Promise<unknown>>;
|
|
74
82
|
renderCache: Map<string, Promise<ContentRenderResult>>;
|
|
75
83
|
renderMarkdown?: (body: string) => Promise<ContentRenderResult>;
|
|
84
|
+
/** The only query style this revision's configuration allows; absent allows both. */
|
|
85
|
+
queryStyle?: QueryStyle;
|
|
76
86
|
execute?: (plan: QueryPlan, terminal: "all" | "first" | "count", requests: PayloadRequest[]) => Promise<unknown>;
|
|
77
87
|
};
|
|
78
88
|
/** A projected row awaiting the payloads its query scope requested. */
|
|
@@ -90,19 +100,34 @@ type ContentState = {
|
|
|
90
100
|
//#endregion
|
|
91
101
|
//#region src/runtime/content.d.ts
|
|
92
102
|
type ContentMethods<Registry extends CollectionRegistry = {}> = {
|
|
93
|
-
/**
|
|
94
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Starts a fluent query over one collection. Nothing is selected until `select()`, `with()`,
|
|
105
|
+
* `withPayload()`, or `selectAdjacent()` requests data, not even `id`.
|
|
106
|
+
*/
|
|
107
|
+
from<Name extends keyof Registry & string>(collection: Name): Query<Registry, Name>;
|
|
95
108
|
/** Collection-scoped relational queries with typed columns, relationships, payloads, and filters. */
|
|
96
109
|
readonly query: RelationalQueries<Registry>;
|
|
97
110
|
/** Counts matching entries before pagination, like the fluent count terminal. */
|
|
98
111
|
count<Name extends keyof Registry & string>(collection: Name, options?: RelationalCountOptions<Registry, Name>): Promise<number>;
|
|
99
112
|
};
|
|
100
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Root members outside the allowed style. Property access reports the message type directly; a
|
|
115
|
+
* call reports it as the required `this` type, whatever arguments it passes.
|
|
116
|
+
*/
|
|
117
|
+
type DisabledMembers<Style extends QueryStyle> = { readonly [Member in Exclude<QueryStyleMember, MembersOf<Style>>]: ContentMethods[Member] extends ((...arguments_: never) => unknown) ? (this: QueryStyleDisabled<Member, Style>, ...arguments_: readonly unknown[]) => never : QueryStyleDisabled<Member, Style>; };
|
|
118
|
+
/**
|
|
119
|
+
* The generated `content` export. `Style` narrows the root query APIs to the `queryStyle` exported
|
|
120
|
+
* by content-query.config; the default allows both fluent and relational queries.
|
|
121
|
+
*
|
|
122
|
+
* The gate avoids a conditional on `Style`: a conditional on a generic `Style` would make
|
|
123
|
+
* `ContentSession<Registry>` invariant in `Registry` and break assignment to wider sessions.
|
|
124
|
+
*/
|
|
125
|
+
type Content<Registry extends CollectionRegistry = {}, Style extends QueryStyle = QueryStyle> = InvalidRelationships<Registry> extends never ? Pick<ContentMethods<Registry>, MembersOf<Style>> & DisabledMembers<Style> : {
|
|
101
126
|
readonly invalidRelationships: InvalidRelationships<Registry>;
|
|
102
127
|
};
|
|
103
128
|
/** Keeps dev builders live across host-delivered revisions while pinning active operations. */
|
|
104
129
|
declare function createLiveRuntime(initial: ContentState): {
|
|
105
|
-
content: ContentMethods<CollectionRegistry>;
|
|
130
|
+
content: Pick<ContentMethods<CollectionRegistry>, "from" | "query" | "count"> & DisabledMembers<QueryStyle>;
|
|
106
131
|
update(next: ContentState): void;
|
|
107
132
|
};
|
|
108
133
|
//#endregion
|
|
@@ -149,4 +149,20 @@ type LoaderSource<Value> = Value extends {
|
|
|
149
149
|
readonly [loaderSourceType]?: infer Source;
|
|
150
150
|
} ? Source : unknown;
|
|
151
151
|
//#endregion
|
|
152
|
-
|
|
152
|
+
//#region src/loaders/descriptor.d.ts
|
|
153
|
+
type GlobOptions = {
|
|
154
|
+
pattern: string | string[];
|
|
155
|
+
base?: string | URL;
|
|
156
|
+
generateId?: (context: {
|
|
157
|
+
entry: string;
|
|
158
|
+
base: URL;
|
|
159
|
+
data: Record<string, unknown>;
|
|
160
|
+
}) => string;
|
|
161
|
+
retainBody?: boolean;
|
|
162
|
+
deferRender?: boolean;
|
|
163
|
+
};
|
|
164
|
+
type FileOptions = {
|
|
165
|
+
parser?: (text: string) => MaybePromise<unknown>;
|
|
166
|
+
};
|
|
167
|
+
//#endregion
|
|
168
|
+
export { DataStore as a, Loader as c, LoaderLogger as d, LoaderSource as f, MaybePromise as g, RecordLoader as h, DataEntry as i, LoaderConfig as l, MetaStore as m, GlobOptions as n, FileEntrySource as o, LoaderWatcher as p, BodyLoader as r, FileSource as s, FileOptions as t, LoaderContext as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ContentError } from "./errors-
|
|
1
|
+
import { t as ContentError } from "./errors-Bfd0R4_P.mjs";
|
|
2
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. */
|
|
@@ -59,6 +59,8 @@ function serializeContentError(error) {
|
|
|
59
59
|
id: error.id,
|
|
60
60
|
source: error.source,
|
|
61
61
|
path: error.path,
|
|
62
|
+
payload: error.payload,
|
|
63
|
+
variant: error.variant,
|
|
62
64
|
issues: error.issues,
|
|
63
65
|
cause: error.cause,
|
|
64
66
|
diagnostics: error.diagnostics
|
|
@@ -12,6 +12,8 @@ var ContentError = class extends Error {
|
|
|
12
12
|
id;
|
|
13
13
|
source;
|
|
14
14
|
path;
|
|
15
|
+
payload;
|
|
16
|
+
variant;
|
|
15
17
|
issues;
|
|
16
18
|
diagnostics;
|
|
17
19
|
/** Creates one failure or a grouped report preserving individual causes and issues. */
|
|
@@ -25,10 +27,23 @@ var ContentError = class extends Error {
|
|
|
25
27
|
this.id = options.id;
|
|
26
28
|
this.source = options.source;
|
|
27
29
|
this.path = options.path;
|
|
30
|
+
this.payload = options.payload;
|
|
31
|
+
this.variant = options.variant;
|
|
28
32
|
this.issues = options.issues;
|
|
29
33
|
this.diagnostics = options.diagnostics ?? [{ ...options }];
|
|
30
34
|
}
|
|
31
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* Formats a payload and its variant as a readable identity, such as `detail[locale=en-US]`.
|
|
38
|
+
*
|
|
39
|
+
* @param payload - The payload name.
|
|
40
|
+
* @param variant - The variant combination; keys are listed in sorted order.
|
|
41
|
+
* @returns The payload name, followed by its variant pairs when it has any.
|
|
42
|
+
*/
|
|
43
|
+
function payloadIdentity(payload, variant = {}) {
|
|
44
|
+
const pairs = Object.keys(variant).sort().map((key) => `${key}=${variant[key]}`);
|
|
45
|
+
return pairs.length ? `${payload}[${pairs.join(",")}]` : payload;
|
|
46
|
+
}
|
|
32
47
|
/** Rejects invalid query structure before any execution or payload access. */
|
|
33
48
|
function invalidQuery(message) {
|
|
34
49
|
throw new ContentError({
|
|
@@ -69,4 +84,4 @@ function withContext(cause, context) {
|
|
|
69
84
|
})));
|
|
70
85
|
}
|
|
71
86
|
//#endregion
|
|
72
|
-
export { invalidQuery as a, groupDiagnostics as i, contentError as n,
|
|
87
|
+
export { invalidQuery as a, groupDiagnostics as i, contentError as n, payloadIdentity as o, describeCause as r, withContext as s, ContentError as t };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { a as recordData, f as builtinPath, i as parseData, o as populateStore, p as builtinSymbol, r as coerceIdentity } from "./glob-BXJuwy_p.mjs";
|
|
2
|
+
import { i as groupDiagnostics, n as contentError, r as describeCause, t as ContentError } from "./errors-Bfd0R4_P.mjs";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
//#region src/loaders/file.ts
|
|
7
|
+
/** Declares a multi-entry data file with typed source paths and record keys, plus an optional parser. */
|
|
8
|
+
function file(filename, options = {}) {
|
|
9
|
+
if (typeof filename !== "string" || !filename) throw new TypeError("file() requires a filename.");
|
|
10
|
+
const descriptor = {
|
|
11
|
+
kind: "file",
|
|
12
|
+
filename,
|
|
13
|
+
options
|
|
14
|
+
};
|
|
15
|
+
return {
|
|
16
|
+
[builtinSymbol]: descriptor,
|
|
17
|
+
name: "content-query/file",
|
|
18
|
+
async load(context) {
|
|
19
|
+
const entries = await loadFile(descriptor, fileURLToPath(context.config.root), context.signal ?? new AbortController().signal);
|
|
20
|
+
await populateStore(context, entries);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Captures a complete multi-entry data source without applying collection validation. */
|
|
25
|
+
async function loadFile(descriptor, root, signal) {
|
|
26
|
+
const resolved = builtinPath(descriptor, root);
|
|
27
|
+
let parsed;
|
|
28
|
+
try {
|
|
29
|
+
const text = await readFile(resolved, {
|
|
30
|
+
encoding: "utf8",
|
|
31
|
+
signal
|
|
32
|
+
});
|
|
33
|
+
parsed = descriptor.options.parser ? await descriptor.options.parser(text) : parseData(text, resolved);
|
|
34
|
+
} catch (cause) {
|
|
35
|
+
signal.throwIfAborted();
|
|
36
|
+
throw contentError(cause, {
|
|
37
|
+
code: "source-error",
|
|
38
|
+
source: resolved,
|
|
39
|
+
message: `Could not load "${descriptor.filename}": ${describeCause(cause)}`,
|
|
40
|
+
cause
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const array = Array.isArray(parsed);
|
|
44
|
+
if (!array && (!parsed || typeof parsed !== "object")) throw new ContentError({
|
|
45
|
+
code: "source-error",
|
|
46
|
+
source: resolved,
|
|
47
|
+
message: `"${descriptor.filename}" must parse to an array or keyed record.`
|
|
48
|
+
});
|
|
49
|
+
const diagnostics = [];
|
|
50
|
+
const entries = Object.entries(parsed).flatMap(([key, value]) => {
|
|
51
|
+
if (!array && key === "$schema" && typeof value === "string") return [];
|
|
52
|
+
const source = `${resolved}#${key}`;
|
|
53
|
+
try {
|
|
54
|
+
const data = recordData(value);
|
|
55
|
+
const identity = array ? data.id ?? data.slug : key;
|
|
56
|
+
if (identity == null || coerceIdentity(identity) === "") throw new Error("Array entries require a nonempty id or slug.");
|
|
57
|
+
const { id: _transportId, ...metadata } = data;
|
|
58
|
+
return [{
|
|
59
|
+
id: coerceIdentity(identity),
|
|
60
|
+
data: metadata,
|
|
61
|
+
source: array ? source : `${resolved}#${coerceIdentity(identity)}`,
|
|
62
|
+
sourceData: {
|
|
63
|
+
filePath: path.relative(root, resolved).split(path.sep).join("/"),
|
|
64
|
+
key
|
|
65
|
+
}
|
|
66
|
+
}];
|
|
67
|
+
} catch (cause) {
|
|
68
|
+
diagnostics.push({
|
|
69
|
+
code: "source-error",
|
|
70
|
+
source,
|
|
71
|
+
message: `Invalid entry "${key}" in "${descriptor.filename}": ${describeCause(cause)}`,
|
|
72
|
+
cause
|
|
73
|
+
});
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
if (diagnostics.length) throw groupDiagnostics(diagnostics);
|
|
78
|
+
return entries;
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { loadFile as n, file as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import { i as
|
|
1
|
+
import { i as groupDiagnostics, n as contentError, r as describeCause, t as ContentError } from "./errors-Bfd0R4_P.mjs";
|
|
2
|
+
import { i as detach } from "./values-BbTV4QT-.mjs";
|
|
3
3
|
import { n as slug } from "./github-slugger-BMgR_Q0I.mjs";
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
@@ -8,6 +8,85 @@ import { glob } from "tinyglobby";
|
|
|
8
8
|
import matter from "gray-matter";
|
|
9
9
|
import { parse } from "yaml";
|
|
10
10
|
import { parse as parse$1 } from "smol-toml";
|
|
11
|
+
//#region src/loaders/descriptor.ts
|
|
12
|
+
const builtinSymbol = Symbol.for("content-query.builtin-loader");
|
|
13
|
+
/** Finds library-owned loader settings without depending on module instance identity. */
|
|
14
|
+
function builtinLoader(loader) {
|
|
15
|
+
return loader[builtinSymbol];
|
|
16
|
+
}
|
|
17
|
+
/** Resolves a loader's watch root from the application root, including file URLs. */
|
|
18
|
+
function builtinPath(descriptor, root) {
|
|
19
|
+
if (descriptor.kind === "file") return path.resolve(root, descriptor.filename);
|
|
20
|
+
return descriptor.options.base instanceof URL ? path.resolve(fileURLToPath(descriptor.options.base)) : path.resolve(root, descriptor.options.base ?? ".");
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/preparation/validation.ts
|
|
24
|
+
/** Checks records independently from validation-provider schema introspection. */
|
|
25
|
+
function isRecord(value) {
|
|
26
|
+
return !!value && typeof value === "object" && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
27
|
+
}
|
|
28
|
+
/** Validates one result, retaining structured provider issues and their original detail. */
|
|
29
|
+
async function validate(schema, value, context) {
|
|
30
|
+
if (!schema) return value;
|
|
31
|
+
try {
|
|
32
|
+
const result = await schema["~standard"].validate(value);
|
|
33
|
+
if (result.issues) {
|
|
34
|
+
const firstPath = result.issues[0]?.path?.map((segment) => typeof segment === "object" ? segment.key : segment);
|
|
35
|
+
throw new ContentError({
|
|
36
|
+
...context,
|
|
37
|
+
code: "validation-error",
|
|
38
|
+
message: result.issues.map((issue) => issue.message).join("; "),
|
|
39
|
+
issues: result.issues,
|
|
40
|
+
path: [...context.path ?? [], ...firstPath ?? []]
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return result.value;
|
|
44
|
+
} catch (cause) {
|
|
45
|
+
throw contentError(cause, {
|
|
46
|
+
...context,
|
|
47
|
+
code: "validation-error",
|
|
48
|
+
message: "Schema validation failed."
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Checks loader transport structure and rejects duplicate snapshot/upsert identities. */
|
|
53
|
+
function normalizeSnapshot(entries, collection) {
|
|
54
|
+
if (!Array.isArray(entries)) throw new ContentError({
|
|
55
|
+
code: "source-error",
|
|
56
|
+
collection,
|
|
57
|
+
message: "load() must return an array of structured entries."
|
|
58
|
+
});
|
|
59
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
60
|
+
for (const entry of entries) {
|
|
61
|
+
if (!entry || typeof entry.id !== "string" || !entry.id || !isRecord(entry.data) || entry.body !== void 0 && typeof entry.body !== "string" || entry.source !== void 0 && typeof entry.source !== "string") throw new ContentError({
|
|
62
|
+
code: "source-error",
|
|
63
|
+
collection,
|
|
64
|
+
id: entry && typeof entry === "object" && typeof entry.id === "string" ? entry.id : void 0,
|
|
65
|
+
source: entry && typeof entry === "object" && typeof entry.source === "string" ? entry.source : void 0,
|
|
66
|
+
message: "Invalid structured loader entry."
|
|
67
|
+
});
|
|
68
|
+
if (snapshot.has(entry.id)) throw new ContentError({
|
|
69
|
+
code: "duplicate-id",
|
|
70
|
+
collection,
|
|
71
|
+
id: entry.id,
|
|
72
|
+
source: entry.source,
|
|
73
|
+
message: `Duplicate entry ID "${entry.id}".`
|
|
74
|
+
});
|
|
75
|
+
snapshot.set(entry.id, entry);
|
|
76
|
+
}
|
|
77
|
+
return snapshot;
|
|
78
|
+
}
|
|
79
|
+
/** Validates supplied rendering data and normalizes omitted headings. */
|
|
80
|
+
function renderedPayload(entry) {
|
|
81
|
+
if (entry.rendered === void 0) return;
|
|
82
|
+
const rendered = entry.rendered;
|
|
83
|
+
if (!rendered || typeof rendered.html !== "string" || rendered.metadata !== void 0 && (!isRecord(rendered.metadata) || rendered.metadata.headings !== void 0 && (!Array.isArray(rendered.metadata.headings) || rendered.metadata.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 supplied HTML/headings payload.");
|
|
84
|
+
return {
|
|
85
|
+
html: rendered.html,
|
|
86
|
+
headings: detach(rendered.metadata?.headings ?? [])
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
11
90
|
//#region src/loaders/populate.ts
|
|
12
91
|
/** Validates a complete built-in source before replacing its collection store. */
|
|
13
92
|
async function populateStore(context, entries) {
|
|
@@ -67,15 +146,24 @@ function glob$1(options) {
|
|
|
67
146
|
}
|
|
68
147
|
};
|
|
69
148
|
}
|
|
70
|
-
/**
|
|
71
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Captures complete matching Markdown and data sources before deployment.
|
|
151
|
+
*
|
|
152
|
+
* @param descriptor - The glob loader's options.
|
|
153
|
+
* @param root - The project root that relative bases and source paths use.
|
|
154
|
+
* @param signal - Cancels outstanding reads.
|
|
155
|
+
* @param options - `warnEmpty: false` skips the warning when nothing matches, for callers where an
|
|
156
|
+
* empty result is expected, such as resolvers' `files.glob()`.
|
|
157
|
+
* @returns Loader entries in sorted path order.
|
|
158
|
+
*/
|
|
159
|
+
async function loadGlob(descriptor, root, signal, { warnEmpty = true } = {}) {
|
|
72
160
|
const resolved = builtinPath(descriptor, root);
|
|
73
161
|
const entries = await glob(descriptor.options.pattern, {
|
|
74
162
|
cwd: resolved,
|
|
75
163
|
onlyFiles: true,
|
|
76
164
|
dot: false
|
|
77
165
|
});
|
|
78
|
-
if (entries.length === 0) console.warn(`[content-query] No content matched ${JSON.stringify(descriptor.options.pattern)} in ${resolved}.`);
|
|
166
|
+
if (entries.length === 0 && warnEmpty) console.warn(`[content-query] No content matched ${JSON.stringify(descriptor.options.pattern)} in ${resolved}.`);
|
|
79
167
|
const base = pathToFileURL(`${resolved}${path.sep}`);
|
|
80
168
|
entries.sort();
|
|
81
169
|
const results = [];
|
|
@@ -156,4 +244,4 @@ async function loadEntry(descriptor, entry, filename, base, signal) {
|
|
|
156
244
|
};
|
|
157
245
|
}
|
|
158
246
|
//#endregion
|
|
159
|
-
export {
|
|
247
|
+
export { recordData as a, normalizeSnapshot as c, builtinLoader as d, builtinPath as f, parseData as i, renderedPayload as l, loadGlob as n, populateStore as o, builtinSymbol as p, coerceIdentity as r, isRecord as s, glob$1 as t, validate as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as DataStore, c as Loader, d as LoaderLogger, f as LoaderSource, g as MaybePromise, h as RecordLoader, i as DataEntry, l as LoaderConfig, m as MetaStore, n as GlobOptions, o as FileEntrySource, p as LoaderWatcher, r as BodyLoader, s as FileSource, u as LoaderContext } from "./descriptor-bcPa6XLk.mjs";
|
|
2
2
|
import { n as ContentRenderResult, r as RenderedContent, t as ContentHeading } from "./types-Dh-Sydyw.mjs";
|
|
3
|
-
import { a as ComputedContext, c as
|
|
4
|
-
import { n as
|
|
3
|
+
import { C as VariantValues, S as VariantOf, a as ComputedContext, b as VariantContext, c as EntryFiles, d as PayloadData, f as PayloadDeclaration, g as Relationship, h as QueryData, i as CollectionRegistry, l as FileEntry, m as PayloadsOf, n as BuiltinPayloads, o as CustomPayload, p as PayloadDefinition, r as CollectionDefinition, s as CustomPayloadMarker, t as BuiltinPayloadMarker, u as PayloadContext, v as Schema, x as VariantField, y as SchemaOutput } from "./types-DbFfF6JE.mjs";
|
|
4
|
+
import { n as QueryStyle } from "./query-style-eXENQJ0O.mjs";
|
|
5
5
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
6
|
//#region src/collection/source.d.ts
|
|
7
7
|
type CollectionSource = string | ({
|
|
@@ -15,7 +15,35 @@ type CollectionSource = string | ({
|
|
|
15
15
|
type RecordSource = Extract<CollectionSource, object> & {
|
|
16
16
|
type: "json" | "yaml" | "toml";
|
|
17
17
|
};
|
|
18
|
-
|
|
18
|
+
/** Variant values are typed `string`, so inference never depends on declaration order. */
|
|
19
|
+
type VariantRecord<Keys> = { [Key in keyof Keys]: string; };
|
|
20
|
+
/** Metadata plus computed fields, as payload enumerators and resolvers receive them. */
|
|
21
|
+
type PayloadData$1<SourceSchema extends Schema | undefined, ComputedSchemas extends Record<string, Schema>> = SchemaOutput<NoInfer<SourceSchema>> & { [Field in keyof NoInfer<ComputedSchemas>]: SchemaOutput<NoInfer<ComputedSchemas>[Field]>; };
|
|
22
|
+
/**
|
|
23
|
+
* Custom payload declarations. Schemas and variant keys are inferred through separate mapped
|
|
24
|
+
* types, so resolvers are contextually typed without annotations. Variant values are data field
|
|
25
|
+
* names or fixed lists rather than callbacks: TypeScript cannot infer keys from an object whose
|
|
26
|
+
* values are all unannotated callbacks.
|
|
27
|
+
*/
|
|
28
|
+
type PayloadDeclarations<SourceSchema extends Schema | undefined, ComputedSchemas extends Record<string, Schema>, PayloadSchemas extends Record<string, Schema>, PayloadVariants extends Record<string, unknown>, Source> = { [Name in keyof PayloadSchemas]: {
|
|
29
|
+
schema: PayloadSchemas[Name];
|
|
30
|
+
}; } & { [Name in keyof PayloadVariants]: {
|
|
31
|
+
variants?: { [Key in keyof PayloadVariants[Name]]: VariantValues<PayloadData$1<SourceSchema, ComputedSchemas>>; };
|
|
32
|
+
combinations?(context: VariantContext<PayloadData$1<SourceSchema, ComputedSchemas>, Source> & {
|
|
33
|
+
variants: Readonly<{ [Key in keyof NoInfer<PayloadVariants>[Name]]: readonly string[]; }>;
|
|
34
|
+
}): Iterable<VariantRecord<NoInfer<PayloadVariants>[Name]>> | PromiseLike<Iterable<VariantRecord<NoInfer<PayloadVariants>[Name]>>>;
|
|
35
|
+
resolve(context: PayloadContext<PayloadData$1<SourceSchema, ComputedSchemas>, Source, VariantRecord<NoInfer<PayloadVariants>[Name]>>): unknown;
|
|
36
|
+
/** Set to `false` to resolve again in every revision. */
|
|
37
|
+
cache?: boolean;
|
|
38
|
+
}; } & ReservedPayloadNames<NoInfer<PayloadSchemas>>;
|
|
39
|
+
/**
|
|
40
|
+
* Rejects underscore payload names, which built-ins own. A conditional keeps declaration inference
|
|
41
|
+
* intact, unlike a key-remapped mapped type.
|
|
42
|
+
*/
|
|
43
|
+
type ReservedPayloadNames<PayloadSchemas> = Extract<keyof PayloadSchemas, `_${string}`> extends never ? unknown : {
|
|
44
|
+
"Custom payload names cannot start with an underscore": Extract<keyof PayloadSchemas, `_${string}`>;
|
|
45
|
+
};
|
|
46
|
+
type CollectionFields<SourceSchema extends Schema | undefined, ComputedSchemas extends Record<string, Schema>, Relationships extends Record<string, Relationship>, PayloadSchemas extends Record<string, Schema>, PayloadVariants extends Record<string, unknown>, Source> = {
|
|
19
47
|
schema?: SourceSchema;
|
|
20
48
|
computed?: { [Name in keyof ComputedSchemas]: {
|
|
21
49
|
schema: ComputedSchemas[Name];
|
|
@@ -26,16 +54,22 @@ type CollectionFields<SourceSchema extends Schema | undefined, ComputedSchemas e
|
|
|
26
54
|
id: string;
|
|
27
55
|
} & { [Field in keyof ComputedSchemas]: SchemaOutput<ComputedSchemas[Field]>; }) & string;
|
|
28
56
|
}; };
|
|
57
|
+
/** Directories, relative to the project root, that resolvers' `files` helpers may also read. */
|
|
58
|
+
sharedFiles?: readonly string[];
|
|
59
|
+
/** Named per-entry data resolved during preparation and loaded only when a query requests it. */
|
|
60
|
+
payloads?: PayloadDeclarations<SourceSchema, ComputedSchemas, PayloadSchemas, PayloadVariants, Source>;
|
|
29
61
|
};
|
|
30
|
-
type Definition<SourceSchema extends Schema | undefined, ComputedSchemas extends Record<string, Schema>, Relationships extends Record<string, Relationship>, ContentLoader extends Loader> = ({
|
|
62
|
+
type Definition<SourceSchema extends Schema | undefined, ComputedSchemas extends Record<string, Schema>, Relationships extends Record<string, Relationship>, PayloadSchemas extends Record<string, Schema>, PayloadVariants extends Record<string, unknown>, ContentLoader extends Loader> = ({
|
|
31
63
|
source: CollectionSource;
|
|
32
64
|
loader?: never;
|
|
33
|
-
} & CollectionFields<SourceSchema, ComputedSchemas, Relationships, FileSource>) | ({
|
|
65
|
+
} & CollectionFields<SourceSchema, ComputedSchemas, Relationships, PayloadSchemas, PayloadVariants, FileSource>) | ({
|
|
34
66
|
loader: ContentLoader;
|
|
35
67
|
source?: never;
|
|
36
|
-
} & CollectionFields<SourceSchema, ComputedSchemas, Relationships, LoaderSource<NoInfer<ContentLoader>>>);
|
|
68
|
+
} & CollectionFields<SourceSchema, ComputedSchemas, Relationships, PayloadSchemas, PayloadVariants, LoaderSource<NoInfer<ContentLoader>>>);
|
|
69
|
+
/** Records each declared payload's validated value type and variant record. */
|
|
70
|
+
type PayloadMarker<PayloadSchemas extends Record<string, Schema>, PayloadVariants extends Record<string, unknown>> = CustomPayloadMarker<{ [Name in keyof PayloadSchemas & string]: CustomPayload<SchemaOutput<PayloadSchemas[Name]>, VariantRecord<PayloadVariants[Name & keyof PayloadVariants]>>; }>;
|
|
37
71
|
/** Normalizes either declaration form into a definition with a native loader. */
|
|
38
|
-
declare function collectionOf<SourceSchema extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined, ComputedSchemas extends Record<string, Schema>, Relationships extends Record<string, Relationship>, ContentLoader extends Loader>(definition: Definition<SourceSchema, ComputedSchemas, Relationships, ContentLoader>): {
|
|
72
|
+
declare function collectionOf<SourceSchema extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined, ComputedSchemas extends Record<string, Schema>, Relationships extends Record<string, Relationship>, PayloadSchemas extends Record<string, Schema>, PayloadVariants extends Record<string, unknown>, ContentLoader extends Loader>(definition: Definition<SourceSchema, ComputedSchemas, Relationships, PayloadSchemas, PayloadVariants, ContentLoader>): {
|
|
39
73
|
loader: ContentLoader | Loader<FileSource>;
|
|
40
74
|
schema: SourceSchema;
|
|
41
75
|
computed: { [Name in keyof ComputedSchemas]: {
|
|
@@ -47,6 +81,10 @@ declare function collectionOf<SourceSchema extends StandardSchemaV1<unknown, Rec
|
|
|
47
81
|
}; };
|
|
48
82
|
relationships: Relationships;
|
|
49
83
|
source: CollectionSource;
|
|
84
|
+
/** Directories, relative to the project root, that resolvers' `files` helpers may also read. */
|
|
85
|
+
sharedFiles?: readonly string[];
|
|
86
|
+
/** Named per-entry data resolved during preparation and loaded only when a query requests it. */
|
|
87
|
+
payloads?: PayloadDeclarations<SourceSchema, ComputedSchemas, PayloadSchemas, PayloadVariants, FileSource> | undefined;
|
|
50
88
|
} | {
|
|
51
89
|
loader: ContentLoader | Loader<FileSource>;
|
|
52
90
|
schema: SourceSchema;
|
|
@@ -59,21 +97,26 @@ declare function collectionOf<SourceSchema extends StandardSchemaV1<unknown, Rec
|
|
|
59
97
|
}; };
|
|
60
98
|
relationships: Relationships;
|
|
61
99
|
source?: never;
|
|
100
|
+
/** Directories, relative to the project root, that resolvers' `files` helpers may also read. */
|
|
101
|
+
sharedFiles?: readonly string[];
|
|
102
|
+
/** Named per-entry data resolved during preparation and loaded only when a query requests it. */
|
|
103
|
+
payloads?: PayloadDeclarations<SourceSchema, ComputedSchemas, PayloadSchemas, PayloadVariants, LoaderSource<NoInfer<ContentLoader>>> | undefined;
|
|
62
104
|
};
|
|
63
|
-
type Defined<SourceSchema extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined, ComputedSchemas extends Record<string, Schema>, Relationships extends Record<string, Relationship>, ContentLoader extends Loader> = ReturnType<typeof collectionOf<SourceSchema, ComputedSchemas, Relationships, ContentLoader
|
|
105
|
+
type Defined<SourceSchema extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined, ComputedSchemas extends Record<string, Schema>, Relationships extends Record<string, Relationship>, PayloadSchemas extends Record<string, Schema>, PayloadVariants extends Record<string, unknown>, ContentLoader extends Loader> = ReturnType<typeof collectionOf<SourceSchema, ComputedSchemas, Relationships, PayloadSchemas, PayloadVariants, ContentLoader>> & PayloadMarker<PayloadSchemas, PayloadVariants>;
|
|
64
106
|
/**
|
|
65
|
-
* Declares fields with inferred schema data and optional loader source metadata, plus
|
|
66
|
-
* JSON, YAML, and TOML sources carry no built-in `_body` or
|
|
107
|
+
* Declares fields with inferred schema data and optional loader source metadata, plus
|
|
108
|
+
* relationships and custom payloads. JSON, YAML, and TOML sources carry no built-in `_body` or
|
|
109
|
+
* `_rendered` payloads.
|
|
67
110
|
*/
|
|
68
|
-
export declare function defineCollection<const SourceSchema extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined = undefined, const ComputedSchemas extends Record<string, Schema> = {}, const Relationships extends Record<string, Relationship> = {}>(definition: {
|
|
111
|
+
export declare function defineCollection<const SourceSchema extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined = undefined, const ComputedSchemas extends Record<string, Schema> = {}, const Relationships extends Record<string, Relationship> = {}, const PayloadSchemas extends Record<string, Schema> = {}, const PayloadVariants extends Record<string, unknown> = {}>(definition: {
|
|
69
112
|
source: RecordSource;
|
|
70
113
|
loader?: never;
|
|
71
|
-
} & CollectionFields<SourceSchema, ComputedSchemas, Relationships, FileSource>): Defined<SourceSchema, ComputedSchemas, Relationships, Loader> & BuiltinPayloadMarker<never>;
|
|
114
|
+
} & CollectionFields<SourceSchema, ComputedSchemas, Relationships, PayloadSchemas, PayloadVariants, FileSource>): Defined<SourceSchema, ComputedSchemas, Relationships, PayloadSchemas, PayloadVariants, Loader> & BuiltinPayloadMarker<never>;
|
|
72
115
|
/**
|
|
73
|
-
* Declares fields with inferred schema data and optional loader source metadata, plus
|
|
74
|
-
* Record loaders such as `file()` carry no built-in `_body` or
|
|
75
|
-
* loaders carry `_body` without `_rendered`.
|
|
116
|
+
* Declares fields with inferred schema data and optional loader source metadata, plus
|
|
117
|
+
* relationships and custom payloads. Record loaders such as `file()` carry no built-in `_body` or
|
|
118
|
+
* `_rendered` payloads, and body loaders carry `_body` without `_rendered`.
|
|
76
119
|
*/
|
|
77
|
-
export declare function defineCollection<const SourceSchema extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined = undefined, const ComputedSchemas extends Record<string, Schema> = {}, const Relationships extends Record<string, Relationship> = {}, const ContentLoader extends Loader = Loader>(definition: Definition<SourceSchema, ComputedSchemas, Relationships, ContentLoader>): Defined<SourceSchema, ComputedSchemas, Relationships, ContentLoader> & BuiltinPayloadMarker<[ContentLoader] extends [RecordLoader] ? never : [ContentLoader] extends [BodyLoader] ? "_body" : keyof BuiltinPayloads>;
|
|
120
|
+
export declare function defineCollection<const SourceSchema extends StandardSchemaV1<unknown, Record<string, unknown>> | undefined = undefined, const ComputedSchemas extends Record<string, Schema> = {}, const Relationships extends Record<string, Relationship> = {}, const PayloadSchemas extends Record<string, Schema> = {}, const PayloadVariants extends Record<string, unknown> = {}, const ContentLoader extends Loader = Loader>(definition: Definition<SourceSchema, ComputedSchemas, Relationships, PayloadSchemas, PayloadVariants, ContentLoader>): Defined<SourceSchema, ComputedSchemas, Relationships, PayloadSchemas, PayloadVariants, ContentLoader> & BuiltinPayloadMarker<[ContentLoader] extends [RecordLoader] ? never : [ContentLoader] extends [BodyLoader] ? "_body" : keyof BuiltinPayloads>;
|
|
78
121
|
//#endregion
|
|
79
|
-
export type { BodyLoader, BuiltinPayloads, CollectionDefinition, CollectionRegistry, CollectionSource, ComputedContext, ContentHeading, ContentRenderResult, DataEntry, DataStore, FileEntrySource, FileSource, Loader, LoaderConfig, LoaderContext, LoaderLogger, LoaderSource, LoaderWatcher, MaybePromise, MetaStore, PayloadsOf, QueryData, RecordLoader, Relationship, RenderedContent };
|
|
122
|
+
export type { BodyLoader, BuiltinPayloads, CollectionDefinition, CollectionRegistry, CollectionSource, ComputedContext, ContentHeading, ContentRenderResult, DataEntry, DataStore, EntryFiles, FileEntry, FileEntrySource, FileSource, Loader, LoaderConfig, LoaderContext, LoaderLogger, LoaderSource, LoaderWatcher, MaybePromise, MetaStore, PayloadContext, PayloadData, PayloadDeclaration, PayloadDefinition, PayloadsOf, QueryData, QueryStyle, RecordLoader, Relationship, RenderedContent, VariantContext, VariantField, VariantOf, VariantValues };
|
package/dist/index.mjs
CHANGED
package/dist/internal.d.mts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { n as createLiveRuntime, o as ContentError, r as PreparedRevision, t as Content } from "./content-
|
|
1
|
+
import { n as createLiveRuntime, o as ContentError, r as PreparedRevision, t as Content } from "./content-CwTKqRs9.mjs";
|
|
2
2
|
import { n as ContentRenderResult } from "./types-Dh-Sydyw.mjs";
|
|
3
|
-
import { i as CollectionRegistry } from "./types-
|
|
4
|
-
import {
|
|
3
|
+
import { i as CollectionRegistry } from "./types-DbFfF6JE.mjs";
|
|
4
|
+
import { b as QueryRegistry } from "./relational-types-C8xJtLG5.mjs";
|
|
5
|
+
import { n as QueryStyle } from "./query-style-eXENQJ0O.mjs";
|
|
5
6
|
//#region src/artifacts/types.d.ts
|
|
6
7
|
type ArtifactManifest = {
|
|
7
8
|
version: number;
|
|
8
9
|
codec: string;
|
|
9
10
|
collections: QueryRegistry;
|
|
11
|
+
/** Optional and additive, so it needs no version bump; absent allows both query styles. */
|
|
12
|
+
queryStyle?: QueryStyle;
|
|
10
13
|
};
|
|
11
14
|
type EncodedCollection = {
|
|
12
15
|
records: readonly string[];
|
|
@@ -14,13 +17,17 @@ type EncodedCollection = {
|
|
|
14
17
|
builtins: Record<string, () => Promise<{
|
|
15
18
|
default: string;
|
|
16
19
|
}>>;
|
|
20
|
+
/** Lazy encoded custom payloads by payload name, entry ID, and canonical variant key. */
|
|
21
|
+
payloads?: Record<string, Record<string, Record<string, () => Promise<{
|
|
22
|
+
default: string;
|
|
23
|
+
}>>>>;
|
|
17
24
|
};
|
|
18
25
|
//#endregion
|
|
19
26
|
//#region src/artifacts/runtime.d.ts
|
|
20
27
|
/** Initializes generated/embedded prepared content. This versioned wiring is internal. */
|
|
21
28
|
export declare function createArtifactRevision(manifest: ArtifactManifest, collections: Record<string, EncodedCollection>, renderMarkdown?: (body: string) => Promise<ContentRenderResult>): PreparedRevision;
|
|
22
29
|
/** Initializes the public generated server export from a complete immutable artifact revision. */
|
|
23
|
-
export declare function createArtifactRuntime<Registry extends CollectionRegistry>(manifest: ArtifactManifest, collections: Record<string, EncodedCollection>, renderMarkdown?: (body: string) => Promise<ContentRenderResult>): Content<Registry>;
|
|
30
|
+
export declare function createArtifactRuntime<Registry extends CollectionRegistry>(manifest: ArtifactManifest, collections: Record<string, EncodedCollection>, renderMarkdown?: (body: string) => Promise<ContentRenderResult>): Content<Registry, QueryStyle>;
|
|
24
31
|
//#endregion
|
|
25
32
|
//#region src/artifacts/payloads.d.ts
|
|
26
33
|
/**
|
package/dist/internal.mjs
CHANGED
|
@@ -1,13 +1,35 @@
|
|
|
1
|
-
import { t as ContentError } from "./errors-
|
|
1
|
+
import { t as ContentError } from "./errors-Bfd0R4_P.mjs";
|
|
2
2
|
import { r as decode } from "./values-BbTV4QT-.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { t as restoreContentError } from "./diagnostics-
|
|
3
|
+
import { n as createRuntime, o as prepareRelationships, r as isQueryStyle, t as createLiveRuntime } from "./content-BXrgP7nL.mjs";
|
|
4
|
+
import { t as restoreContentError } from "./diagnostics-DmUZtrJ6.mjs";
|
|
5
5
|
import { gunzipSync } from "fflate/browser";
|
|
6
6
|
//#region src/artifacts/runtime.ts
|
|
7
|
+
/** Checks that a value is a plain record before reading generated payload tables from it. */
|
|
8
|
+
function isTable(value) {
|
|
9
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Restores lazy custom payload loaders from a generated payload table.
|
|
13
|
+
*
|
|
14
|
+
* @param collection - The collection name, for error messages.
|
|
15
|
+
* @param payloads - Encoded loaders by payload name, entry ID, and canonical variant key.
|
|
16
|
+
* @returns Decoding loaders with the same keys.
|
|
17
|
+
*/
|
|
18
|
+
function customPayloadTable(collection, payloads) {
|
|
19
|
+
if (!isTable(payloads)) throw new Error(`Invalid payload table for collection "${collection}".`);
|
|
20
|
+
return new Map(Object.entries(payloads).map(([payload, entries]) => {
|
|
21
|
+
if (!isTable(entries)) throw new Error(`Invalid payload table for collection "${collection}".`);
|
|
22
|
+
return [payload, new Map(Object.entries(entries).map(([id, variants]) => {
|
|
23
|
+
if (!isTable(variants) || Object.values(variants).some((load) => typeof load !== "function")) throw new Error(`Invalid payload table for collection "${collection}".`);
|
|
24
|
+
return [id, new Map(Object.entries(variants).map(([variant, load]) => [variant, async () => decode((await load()).default)]))];
|
|
25
|
+
}))];
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
7
28
|
/** Initializes generated/embedded prepared content. This versioned wiring is internal. */
|
|
8
29
|
function createArtifactRevision(manifest, collections, renderMarkdown) {
|
|
9
30
|
try {
|
|
10
31
|
if (manifest.version !== 2 || manifest.codec !== "devalue-6.0.2") throw new Error("Incompatible content artifact or codec version; regenerate content.");
|
|
32
|
+
if (manifest.queryStyle !== void 0 && !isQueryStyle(manifest.queryStyle)) throw new Error("Invalid query style in content artifact; regenerate content.");
|
|
11
33
|
const revision = {
|
|
12
34
|
registry: manifest.collections,
|
|
13
35
|
collections: Object.create(null),
|
|
@@ -15,7 +37,8 @@ function createArtifactRevision(manifest, collections, renderMarkdown) {
|
|
|
15
37
|
active: 0,
|
|
16
38
|
payloadCache: /* @__PURE__ */ new Map(),
|
|
17
39
|
renderCache: /* @__PURE__ */ new Map(),
|
|
18
|
-
renderMarkdown
|
|
40
|
+
renderMarkdown,
|
|
41
|
+
...manifest.queryStyle ? { queryStyle: manifest.queryStyle } : {}
|
|
19
42
|
};
|
|
20
43
|
for (const [name, descriptor] of Object.entries(manifest.collections)) {
|
|
21
44
|
const encoded = collections[name];
|
|
@@ -25,7 +48,8 @@ function createArtifactRevision(manifest, collections, renderMarkdown) {
|
|
|
25
48
|
revision.collections[name] = {
|
|
26
49
|
records,
|
|
27
50
|
relationships: descriptor.relationships,
|
|
28
|
-
builtins: new Map(Object.entries(encoded.builtins ?? {}).map(([id, load]) => [id, async () => decode((await load()).default)]))
|
|
51
|
+
builtins: new Map(Object.entries(encoded.builtins ?? {}).map(([id, load]) => [id, async () => decode((await load()).default)])),
|
|
52
|
+
...encoded.payloads ? { payloads: customPayloadTable(name, encoded.payloads) } : {}
|
|
29
53
|
};
|
|
30
54
|
}
|
|
31
55
|
const errors = prepareRelationships(revision);
|