content-query 0.5.0 → 0.6.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 +17 -0
- package/dist/{build-DfoncKL8.d.mts → build-DE4ZKHZR.d.mts} +4 -4
- package/dist/{build-DWpB69_c.mjs → build-DYw3z9ju.mjs} +3 -2
- package/dist/build.d.mts +1 -1
- package/dist/build.mjs +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/{collection-Cb5eWGnv.mjs → collection-txOFpidL.mjs} +52 -6
- package/dist/{collection-types-CsQtGw7_.d.mts → collection-types-Ch4YLG8t.d.mts} +17 -4
- package/dist/computed.d.mts +51 -2
- package/dist/computed.mjs +58 -1
- package/dist/index.d.mts +3 -3
- package/dist/internal.d.mts +5 -5
- package/dist/internal.mjs +1 -1
- package/dist/next.d.mts +1 -1
- package/dist/next.mjs +1 -1
- package/dist/{query-style-C2FcT1f9.d.mts → query-style-k8Qd7wh5.d.mts} +1 -1
- package/dist/query.d.mts +1 -1
- package/dist/{relational-types-CTcalUNW.d.mts → relational-types-DnI9wR5r.d.mts} +26 -15
- package/dist/{revision-DBwU-aC9.d.mts → revision-vhe9gRyk.d.mts} +4 -4
- package/dist/runtime.d.mts +2 -2
- package/dist/{types-Dz1vTXa2.d.mts → types-WOsFmNnN.d.mts} +18 -1
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,6 +78,12 @@ An entry imports only its own collection's data, so a route that imports `posts`
|
|
|
78
78
|
|
|
79
79
|
Queries return only the data they select, not even `id` implicitly. A query must select fields, include a relationship, request a payload, or select adjacent entries; otherwise it fails to type-check and throws an `invalid-query` error. Counts need no selection.
|
|
80
80
|
|
|
81
|
+
Later `select()` calls add fields, so a shared builder such as `const postLink = posts.select("id", "title")` can become `postLink.select("publishedAt")` where a page needs more. For detail pages, `posts.byId(id)` starts a query for one entry, and awaiting it returns that entry or `undefined`:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
const post = await posts.byId("hello").select("title").withPayload("_rendered");
|
|
85
|
+
```
|
|
86
|
+
|
|
81
87
|
To follow a relationship, pass its target collection to `using()`. Nothing related loads implicitly:
|
|
82
88
|
|
|
83
89
|
```ts
|
|
@@ -100,6 +106,17 @@ import type { ContentPost } from "#content-query/posts";
|
|
|
100
106
|
type PostLink = ContentPost<"id" | "title">; // What select("id", "title") returns.
|
|
101
107
|
```
|
|
102
108
|
|
|
109
|
+
To describe a field, write a JSDoc comment above it in the schema or above a computed field's name. Editors show the comment when you hover that field on `ContentPost`, on `ContentPost<"id" | "title">`, and on query results:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
schema: schema.object({
|
|
113
|
+
/** The headline, also used as the page title. */
|
|
114
|
+
title: schema.string(),
|
|
115
|
+
}),
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Zod's `.describe()` and `.meta()` store descriptions at runtime only, so they don't show up in types.
|
|
119
|
+
|
|
103
120
|
Type names are `Content` plus the export name, capitalized and made singular by dropping one trailing `s` (`jobs` gives `ContentJob`, `coding` gives `ContentCoding`). Set `typeName: "Category"` in `defineCollection()` for irregular plurals. Declared payloads are typed as `ContentPostPayload<"detail">`. Collection names that are not identifiers are converted for the export and import path, such as `blog-posts` to `blogPosts`; two collections that would share an export or type name fail the build.
|
|
104
121
|
|
|
105
122
|
Paginate root queries in one call. `paginate({ page: 2, size: 10 })` returns `items`, `total`, `page`, `pageCount`, `hasNextPage`, and `hasPreviousPage` for numbered archive pages. `paginate({ size: 10, after: previous.endCursor })` returns cursor pages with `startCursor` and `endCursor` for "load more" lists. Both work in fluent queries and in `posts.paginate()`; see [pagination](https://github.com/yangshun/content-query/blob/main/docs/API.md#pagination).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as InvalidRelationships, r as CollectionHandles, s as ContentError } from "./collection-types-
|
|
2
|
-
import { i as CollectionRegistry } from "./types-
|
|
3
|
-
import { n as QueryStyle } from "./query-style-
|
|
4
|
-
import "./revision-
|
|
1
|
+
import { a as InvalidRelationships, r as CollectionHandles, s as ContentError } from "./collection-types-Ch4YLG8t.mjs";
|
|
2
|
+
import { i as CollectionRegistry } from "./types-WOsFmNnN.mjs";
|
|
3
|
+
import { n as QueryStyle } from "./query-style-k8Qd7wh5.mjs";
|
|
4
|
+
import "./revision-vhe9gRyk.mjs";
|
|
5
5
|
//#region src/preparation/session.d.ts
|
|
6
6
|
/** A local source captured by a successfully prepared content revision. */
|
|
7
7
|
type ContentSourceEntry = Readonly<{
|
|
@@ -4,7 +4,7 @@ import { i as detach, l as valuePath, o as encode } from "./values-BbTV4QT-.mjs"
|
|
|
4
4
|
import { t as assertServerOnly } from "./server-only-CIJUlyL-.mjs";
|
|
5
5
|
import { n as loadFile } from "./file-DSOcdFj0.mjs";
|
|
6
6
|
import { I as collectionNames } from "./operators-D-w1-gDg.mjs";
|
|
7
|
-
import { a as variantKey, c as CODEC_VERSION, i as isQueryStyle, n as createCollections, o as isRelationship, s as prepareRelationships } from "./collection-
|
|
7
|
+
import { a as variantKey, c as CODEC_VERSION, i as isQueryStyle, n as createCollections, o as isRelationship, s as prepareRelationships } from "./collection-txOFpidL.mjs";
|
|
8
8
|
import { t as renderMarkdown } from "./markdown-CHvBBJNa.mjs";
|
|
9
9
|
import { access, link, mkdir, readFile, readdir, realpath, rm, rmdir, stat, writeFile } from "node:fs/promises";
|
|
10
10
|
import path from "node:path";
|
|
@@ -193,6 +193,7 @@ function configTypes(directory, config) {
|
|
|
193
193
|
* The entry type, such as `ContentJob`, is the full entry. `ContentJob<Field>` is the shape a
|
|
194
194
|
* query returns when it selects `Field`: every selected key is present, and optional fields read
|
|
195
195
|
* as `undefined` when missing, so query results and the type are assignable in both directions.
|
|
196
|
+
* Both forms keep JSDoc comments written on schema fields and computed field names.
|
|
196
197
|
*
|
|
197
198
|
* @param directory - Directory that will contain the declaration file.
|
|
198
199
|
* @param config - Absolute path of content-query.config.
|
|
@@ -209,7 +210,7 @@ function collectionDeclarations(directory, config, name, { exportName, typeName,
|
|
|
209
210
|
`/** The ${exportName} collection. Start queries here, or pass it to another collection's \`using()\` to follow relationships into it. */`,
|
|
210
211
|
`export declare const ${exportName}: import("content-query/runtime").Collection<Registry, ${key}, ConfiguredQueryStyle>;`,
|
|
211
212
|
`/** A ${exportName} entry: its ID, validated metadata, and computed fields. Pass field names, such as \`${typeName}<"id">\`, for the shape a query returns when it selects them. */`,
|
|
212
|
-
`export type ${typeName}<Field extends keyof ${data} = keyof ${data}> = keyof ${data} extends Field ? ${data} : {
|
|
213
|
+
`export type ${typeName}<Field extends keyof ${data} = keyof ${data}> = keyof ${data} extends Field ? ${data} : import("content-query").SelectedData<${data}, Field>;`,
|
|
213
214
|
`/** The value of one payload that the ${exportName} collection declares. */`,
|
|
214
215
|
`export type ${payloadTypeName}<Payload extends keyof import("content-query").PayloadsOf<${definition}>> = import("content-query").PayloadData<${definition}, Payload>;`,
|
|
215
216
|
``
|
package/dist/build.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ContentSourceEvent, i as ContentSourceEntry, n as buildContent, o as ContentSourceSnapshot, r as ContentSession, t as BuildContentOptions } from "./build-
|
|
1
|
+
import { a as ContentSourceEvent, i as ContentSourceEntry, n as buildContent, o as ContentSourceSnapshot, r as ContentSession, t as BuildContentOptions } from "./build-DE4ZKHZR.mjs";
|
|
2
2
|
export { type BuildContentOptions, type ContentSession, type ContentSourceEntry, type ContentSourceEvent, type ContentSourceSnapshot, buildContent };
|
package/dist/build.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { n as buildContent } from "./build-
|
|
1
|
+
export { n as buildContent } from "./build-DYw3z9ju.mjs";
|
package/dist/cli.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { o as payloadIdentity, t as ContentError } from "./errors-Bfd0R4_P.mjs";
|
|
3
|
-
import { t as buildAtRoot } from "./build-
|
|
3
|
+
import { t as buildAtRoot } from "./build-DYw3z9ju.mjs";
|
|
4
4
|
import { cac } from "cac";
|
|
5
5
|
//#region package.json
|
|
6
|
-
var version = "0.
|
|
6
|
+
var version = "0.6.0";
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/integrations/cli/arguments.ts
|
|
9
9
|
/** Validates one path option after CAC's automatic numeric conversion. */
|
|
@@ -481,7 +481,10 @@ function objectPlan(registry, collection, options, many = true, allowAdjacent =
|
|
|
481
481
|
//#region src/query/builder.ts
|
|
482
482
|
const planSymbol = Symbol("content-query.query-plan");
|
|
483
483
|
const scopeSymbol = Symbol("content-query.query-scope");
|
|
484
|
-
/**
|
|
484
|
+
/**
|
|
485
|
+
* Creates immutable root or relationship builders over one backend-independent plan. A root
|
|
486
|
+
* builder that is not `many` is a `byId()` query, which returns one entry or `undefined`.
|
|
487
|
+
*/
|
|
485
488
|
function createBuilder(registry, run, plan, many = true, root = true, scopeToken = {}, allowAdjacent = true, allowPagination = true) {
|
|
486
489
|
const scope = registry[plan.collection];
|
|
487
490
|
if (!scope) invalidQuery(`Unknown collection "${plan.collection}".`);
|
|
@@ -492,9 +495,12 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
|
|
|
492
495
|
const builder = {
|
|
493
496
|
[planSymbol]: plan,
|
|
494
497
|
[scopeSymbol]: scopeToken,
|
|
498
|
+
/** Selects fields, adding to earlier selections; a field selected again is kept once. */
|
|
495
499
|
select(...fields) {
|
|
496
|
-
if (
|
|
497
|
-
|
|
500
|
+
if (fields.length === 0) invalidQuery("select() requires at least one prepared field.");
|
|
501
|
+
const checked = checkedFields(registry, plan.collection, fields);
|
|
502
|
+
const earlier = plan.select ?? [];
|
|
503
|
+
return branch({ select: [...earlier, ...checked.filter((field) => !earlier.includes(field))] });
|
|
498
504
|
},
|
|
499
505
|
where(configure) {
|
|
500
506
|
if (typeof configure !== "function") invalidQuery("where() requires a configuration callback.");
|
|
@@ -503,6 +509,7 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
|
|
|
503
509
|
return branch({ filters: [...plan.filters, detach(resolveRelations(registry, plan.collection, expression))] });
|
|
504
510
|
},
|
|
505
511
|
orderBy(field, direction = "asc") {
|
|
512
|
+
assertList("orderBy()");
|
|
506
513
|
return branch({ order: checkedOrder(plan, field, direction, many) });
|
|
507
514
|
},
|
|
508
515
|
limit(value) {
|
|
@@ -541,6 +548,7 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
|
|
|
541
548
|
if (!allowAdjacent || plan.adjacent !== void 0) invalidQuery("Adjacency cannot be repeated or selected recursively.");
|
|
542
549
|
const [configure] = arguments_;
|
|
543
550
|
if (configure === void 0 || typeof configure === "string") {
|
|
551
|
+
assertList("Results-scope selectAdjacent()");
|
|
544
552
|
if (!arguments_.length || arguments_.some((field) => typeof field !== "string")) invalidQuery("selectAdjacent() requires neighbor fields, such as selectAdjacent(\"id\"), or a sibling query.");
|
|
545
553
|
const selection = {
|
|
546
554
|
...emptyPlan(plan.collection),
|
|
@@ -569,11 +577,12 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
|
|
|
569
577
|
} });
|
|
570
578
|
},
|
|
571
579
|
all() {
|
|
580
|
+
assertList("all()");
|
|
572
581
|
return rows("all");
|
|
573
582
|
},
|
|
574
583
|
/** Executes a selected root query, matching direct await behavior. */
|
|
575
584
|
execute() {
|
|
576
|
-
return rows("all");
|
|
585
|
+
return rows(many ? "all" : "first");
|
|
577
586
|
},
|
|
578
587
|
first() {
|
|
579
588
|
return rows("first");
|
|
@@ -589,6 +598,7 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
|
|
|
589
598
|
*/
|
|
590
599
|
paginate(options) {
|
|
591
600
|
if (!root) invalidQuery("Nested builders have no terminal methods.");
|
|
601
|
+
assertList("paginate()");
|
|
592
602
|
if (!hasSelection(plan)) invalidQuery(NO_SELECTION_MESSAGE);
|
|
593
603
|
return run({
|
|
594
604
|
...plan,
|
|
@@ -599,7 +609,7 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
|
|
|
599
609
|
if (root) Object.defineProperty(builder, "then", { value: (fulfilled, rejected) => {
|
|
600
610
|
let result;
|
|
601
611
|
try {
|
|
602
|
-
result = rows("all");
|
|
612
|
+
result = rows(many ? "all" : "first");
|
|
603
613
|
} catch (cause) {
|
|
604
614
|
result = Promise.reject(cause);
|
|
605
615
|
}
|
|
@@ -614,8 +624,13 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
|
|
|
614
624
|
if (!hasSelection(plan)) invalidQuery(NO_SELECTION_MESSAGE);
|
|
615
625
|
return run(plan, terminal);
|
|
616
626
|
}
|
|
627
|
+
/** Rejects a list-only clause or terminal on a `byId()` query, which returns one entry. */
|
|
628
|
+
function assertList(member) {
|
|
629
|
+
if (root && !many) invalidQuery(`${member} is unavailable after byId(), which returns one entry.`);
|
|
630
|
+
}
|
|
617
631
|
/** Checks pagination before creating an independent branch. */
|
|
618
632
|
function pagination(key, value) {
|
|
633
|
+
assertList(`${key}()`);
|
|
619
634
|
if (!allowPagination || plan[key] !== void 0) invalidQuery("Pagination requires a nonnegative safe integer, one call per clause, and a many-valued scope.");
|
|
620
635
|
return branch({ [key]: checkedPagination(value, many) });
|
|
621
636
|
}
|
|
@@ -633,9 +648,38 @@ function createBuilder(registry, run, plan, many = true, root = true, scopeToken
|
|
|
633
648
|
* @returns An immutable, reusable root builder.
|
|
634
649
|
*/
|
|
635
650
|
function createFrom(registry, run, collection) {
|
|
651
|
+
return createBuilder(currentRegistry(registry, collection), run, emptyPlan(collection));
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Starts a fluent query for the entry with one ID. The builder returns that entry or `undefined`
|
|
655
|
+
* when awaited, offers no ordering, pagination, `all()`, or results-scope adjacency, and still
|
|
656
|
+
* selects nothing until the query requests data.
|
|
657
|
+
*
|
|
658
|
+
* @param registry - Reads the current query registry, so development builders bind the latest one.
|
|
659
|
+
* @param run - Executes a plan against one pinned revision.
|
|
660
|
+
* @param collection - The collection to query.
|
|
661
|
+
* @param id - The entry's ID.
|
|
662
|
+
* @returns An immutable, reusable single-entry root builder.
|
|
663
|
+
*/
|
|
664
|
+
function createById(registry, run, collection, id) {
|
|
665
|
+
const current = currentRegistry(registry, collection);
|
|
666
|
+
if (typeof id !== "string") invalidQuery("byId() requires an entry ID string.");
|
|
667
|
+
const filter = {
|
|
668
|
+
kind: "predicate",
|
|
669
|
+
operator: "eq",
|
|
670
|
+
field: "id",
|
|
671
|
+
value: id
|
|
672
|
+
};
|
|
673
|
+
return createBuilder(current, run, {
|
|
674
|
+
...emptyPlan(collection),
|
|
675
|
+
filters: [filter]
|
|
676
|
+
}, false);
|
|
677
|
+
}
|
|
678
|
+
/** Reads the registry a new root query binds, rejecting unknown collections. */
|
|
679
|
+
function currentRegistry(registry, collection) {
|
|
636
680
|
const current = registry();
|
|
637
681
|
if (typeof collection !== "string" || !Object.hasOwn(current, collection)) invalidQuery(`Unknown collection "${String(collection)}".`);
|
|
638
|
-
return
|
|
682
|
+
return current;
|
|
639
683
|
}
|
|
640
684
|
//#endregion
|
|
641
685
|
//#region src/query/relational.ts
|
|
@@ -1376,6 +1420,7 @@ function createRunner(state) {
|
|
|
1376
1420
|
*/
|
|
1377
1421
|
const queryStyleMembers = {
|
|
1378
1422
|
fluent: [
|
|
1423
|
+
"byId",
|
|
1379
1424
|
"select",
|
|
1380
1425
|
"where",
|
|
1381
1426
|
"orderBy",
|
|
@@ -1602,6 +1647,7 @@ function createCollection(primary, supplied = []) {
|
|
|
1602
1647
|
};
|
|
1603
1648
|
for (const member of queryStyleMembers.fluent) handle[member] = (...arguments_) => {
|
|
1604
1649
|
allow(member);
|
|
1650
|
+
if (member === "byId") return createById(registry, run, name, arguments_[0]);
|
|
1605
1651
|
return createFrom(registry, run, name)[member](...arguments_);
|
|
1606
1652
|
};
|
|
1607
1653
|
handleSources.set(handle, sources);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { _ as Relationship, g as QueryData, i as CollectionRegistry, u as LoadedMarker, v as RelationshipsOf } from "./types-
|
|
2
|
-
import { n as RelationalCountOptions, t as RelationalCollectionQueries, v as Query } from "./relational-types-
|
|
3
|
-
import { i as QueryStyleMember, n as QueryStyle, r as QueryStyleDisabled, t as MembersOf } from "./query-style-
|
|
1
|
+
import { _ as Relationship, g as QueryData, i as CollectionRegistry, u as LoadedMarker, v as RelationshipsOf } from "./types-WOsFmNnN.mjs";
|
|
2
|
+
import { n as RelationalCountOptions, t as RelationalCollectionQueries, v as Query } from "./relational-types-DnI9wR5r.mjs";
|
|
3
|
+
import { i as QueryStyleMember, n as QueryStyle, r as QueryStyleDisabled, t as MembersOf } from "./query-style-k8Qd7wh5.mjs";
|
|
4
4
|
//#region src/shared/errors.d.ts
|
|
5
5
|
type ContentErrorCode = "variant-not-found" | "not-renderable" | "source-error" | "validation-error" | "duplicate-id" | "invalid-reference" | "invalid-query" | "invalid-cursor" | "artifact-error" | "render-error";
|
|
6
6
|
type ContentDiagnostic = {
|
|
@@ -58,8 +58,21 @@ type LoadedRegistry<Registry extends CollectionRegistry, Loaded extends keyof Re
|
|
|
58
58
|
type FluentMember = MembersOf<"fluent">;
|
|
59
59
|
/** The relational members, apart from `count`, which both styles share. */
|
|
60
60
|
type RelationalMember = "findMany" | "findFirst" | "paginate";
|
|
61
|
+
/** Fluent starters that only a collection handle offers, not a query builder. */
|
|
62
|
+
type HandleStarters<Registry extends CollectionRegistry, Name extends keyof Registry & string> = {
|
|
63
|
+
/**
|
|
64
|
+
* Starts a query for the entry with this ID. Select its data as usual; awaiting the query, or
|
|
65
|
+
* calling `first()` or `execute()`, returns the entry or `undefined`. Later `where()` filters
|
|
66
|
+
* also apply. Lookups use the collection's ID index.
|
|
67
|
+
*
|
|
68
|
+
* @param id - The entry's ID.
|
|
69
|
+
* @returns A single-entry root query, without ordering, pagination, `all()`, or results-scope
|
|
70
|
+
* adjacency.
|
|
71
|
+
*/
|
|
72
|
+
byId(id: string): Query<Registry, Name, {}, false, false>;
|
|
73
|
+
};
|
|
61
74
|
/** Every member before `queryStyle` gating. */
|
|
62
|
-
type CollectionMethods<Registry extends CollectionRegistry, Name extends keyof Registry & string> = Pick<Query<Registry, Name>, FluentMember & keyof Query<Registry, Name>> & RelationalCollectionQueries<Registry, Name>;
|
|
75
|
+
type CollectionMethods<Registry extends CollectionRegistry, Name extends keyof Registry & string> = Pick<Query<Registry, Name>, FluentMember & keyof Query<Registry, Name>> & HandleStarters<Registry, Name> & RelationalCollectionQueries<Registry, Name>;
|
|
63
76
|
/**
|
|
64
77
|
* Members outside the allowed style. Calls report the message as the required `this` type,
|
|
65
78
|
* whatever arguments they pass.
|
package/dist/computed.d.mts
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
import { g as MaybePromise } from "./descriptor-bcPa6XLk.mjs";
|
|
2
|
-
import { a as ComputedContext } from "./types-
|
|
2
|
+
import { a as ComputedContext } from "./types-WOsFmNnN.mjs";
|
|
3
3
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
4
|
+
//#region src/computed/fields.d.ts
|
|
5
|
+
/** Result schemas for computed fields that one resolver call fills, keyed by field name. */
|
|
6
|
+
type ComputedFieldSchemas = Record<string, StandardSchemaV1>;
|
|
7
|
+
/**
|
|
8
|
+
* The object a shared resolver returns: one value per field, checked by that field's schema.
|
|
9
|
+
* Fields whose schema accepts `undefined` may be omitted.
|
|
10
|
+
*/
|
|
11
|
+
type ComputedFieldValues<Fields extends ComputedFieldSchemas> = { [Key in keyof Fields as undefined extends StandardSchemaV1.InferInput<Fields[Key]> ? never : Key]: StandardSchemaV1.InferInput<Fields[Key]>; } & { [Key in keyof Fields as undefined extends StandardSchemaV1.InferInput<Fields[Key]> ? Key : never]?: StandardSchemaV1.InferInput<Fields[Key]>; };
|
|
12
|
+
/** Declares several computed fields and the one resolver that returns all of their values. */
|
|
13
|
+
type ComputedFieldsOptions<Fields extends ComputedFieldSchemas, Data = Record<string, unknown>, Source = unknown> = {
|
|
14
|
+
/**
|
|
15
|
+
* Each field's result schema, keyed by field name. A JSDoc comment on a key documents that
|
|
16
|
+
* field in entry types and query results.
|
|
17
|
+
*/
|
|
18
|
+
fields: Fields;
|
|
19
|
+
/**
|
|
20
|
+
* Returns every field's value for one entry. It runs once per entry each time the entry is
|
|
21
|
+
* prepared, however many fields it fills; files it reads through `files` are tracked as usual.
|
|
22
|
+
* Annotate the context, such as `(context: ComputedContext<Post>)`, to type `data`.
|
|
23
|
+
*/
|
|
24
|
+
resolve(this: void, context: ComputedContext<Data, Source>): MaybePromise<ComputedFieldValues<Fields>>;
|
|
25
|
+
};
|
|
26
|
+
/** The computed field definitions that {@link computedFields} returns, one per declared field. */
|
|
27
|
+
type ComputedFieldDefinitions<Fields extends ComputedFieldSchemas, Data = Record<string, unknown>, Source = unknown> = { [Key in keyof Fields]: {
|
|
28
|
+
schema: Fields[Key];
|
|
29
|
+
resolve(context: ComputedContext<Data, Source>): Promise<unknown>;
|
|
30
|
+
}; };
|
|
31
|
+
/**
|
|
32
|
+
* Creates computed fields that share one resolver call per entry, for values that come from the
|
|
33
|
+
* same expensive read, such as several properties of one JSON file beside the entry. Spread the
|
|
34
|
+
* result into `computed`; each field is validated by its own schema and is selected, filtered, and
|
|
35
|
+
* sorted like any other computed field.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* computed: {
|
|
40
|
+
* ...computedFields({
|
|
41
|
+
* fields: { title: schema.string(), description: schema.string() },
|
|
42
|
+
* resolve: async ({ files }) => JSON.parse(await files.text("info/en-US.json")),
|
|
43
|
+
* }),
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @param options - The fields' result schemas and the resolver that returns their values.
|
|
48
|
+
* @returns One computed field definition per key of `options.fields`.
|
|
49
|
+
* @throws TypeError - When `fields` declares no schemas or `resolve` is not a function.
|
|
50
|
+
*/
|
|
51
|
+
export declare function computedFields<const Fields extends ComputedFieldSchemas, Data = Record<string, unknown>, Source = unknown>(options: ComputedFieldsOptions<Fields, Data, Source>): ComputedFieldDefinitions<Fields, Data, Source>;
|
|
52
|
+
//#endregion
|
|
4
53
|
//#region src/computed/text.d.ts
|
|
5
54
|
/** The syntax removed before computing text-derived fields; literal text preserves all characters. */
|
|
6
55
|
type TextFormat = "markdown" | "text" | "html";
|
|
@@ -40,4 +89,4 @@ export declare function excerpt<Data = Record<string, unknown>, Source = unknown
|
|
|
40
89
|
resolve(context: ComputedContext<Data, Source>): Promise<string>;
|
|
41
90
|
};
|
|
42
91
|
//#endregion
|
|
43
|
-
export type { ExcerptOptions, ReadingTimeOptions, TextFormat, TextOptions };
|
|
92
|
+
export type { ComputedFieldDefinitions, ComputedFieldSchemas, ComputedFieldValues, ComputedFieldsOptions, ExcerptOptions, ReadingTimeOptions, TextFormat, TextOptions };
|
package/dist/computed.mjs
CHANGED
|
@@ -3,6 +3,63 @@ import { n as number, r as string } from "./schema-C5Str-E8.mjs";
|
|
|
3
3
|
import { t as src_default } from "./dist-C7_FOzY_.mjs";
|
|
4
4
|
import getReadingTime from "reading-time";
|
|
5
5
|
import { Parser } from "htmlparser2";
|
|
6
|
+
//#region src/computed/fields.ts
|
|
7
|
+
assertServerOnly();
|
|
8
|
+
/**
|
|
9
|
+
* Creates computed fields that share one resolver call per entry, for values that come from the
|
|
10
|
+
* same expensive read, such as several properties of one JSON file beside the entry. Spread the
|
|
11
|
+
* result into `computed`; each field is validated by its own schema and is selected, filtered, and
|
|
12
|
+
* sorted like any other computed field.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* computed: {
|
|
17
|
+
* ...computedFields({
|
|
18
|
+
* fields: { title: schema.string(), description: schema.string() },
|
|
19
|
+
* resolve: async ({ files }) => JSON.parse(await files.text("info/en-US.json")),
|
|
20
|
+
* }),
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @param options - The fields' result schemas and the resolver that returns their values.
|
|
25
|
+
* @returns One computed field definition per key of `options.fields`.
|
|
26
|
+
* @throws TypeError - When `fields` declares no schemas or `resolve` is not a function.
|
|
27
|
+
*/
|
|
28
|
+
function computedFields(options) {
|
|
29
|
+
const { fields, resolve } = options ?? {};
|
|
30
|
+
if (!fields || typeof fields !== "object" || Array.isArray(fields)) throw new TypeError("computedFields() fields must be an object of result schemas.");
|
|
31
|
+
const entries = Object.entries(fields);
|
|
32
|
+
if (!entries.length || entries.some(([, schema]) => !isSchema(schema))) throw new TypeError("computedFields() fields must declare at least one field, each with a Standard Schema.");
|
|
33
|
+
if (typeof resolve !== "function") throw new TypeError("computedFields() resolve must be a function.");
|
|
34
|
+
const resolutions = /* @__PURE__ */ new WeakMap();
|
|
35
|
+
/** Resolves every field's value once for the entry being prepared. */
|
|
36
|
+
function values(context) {
|
|
37
|
+
let pending = resolutions.get(context.files);
|
|
38
|
+
if (!pending) {
|
|
39
|
+
pending = (async () => {
|
|
40
|
+
context.signal.throwIfAborted();
|
|
41
|
+
const result = await resolve(context);
|
|
42
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) throw new TypeError("computedFields() resolve must return an object with a value for each field.");
|
|
43
|
+
return result;
|
|
44
|
+
})();
|
|
45
|
+
resolutions.set(context.files, pending);
|
|
46
|
+
}
|
|
47
|
+
return pending;
|
|
48
|
+
}
|
|
49
|
+
return Object.fromEntries(entries.map(([name, schema]) => [name, {
|
|
50
|
+
schema,
|
|
51
|
+
/** Reads this field's value from the entry's shared resolution. */
|
|
52
|
+
async resolve(context) {
|
|
53
|
+
const result = await values(context);
|
|
54
|
+
return Object.hasOwn(result, name) ? result[name] : void 0;
|
|
55
|
+
}
|
|
56
|
+
}]));
|
|
57
|
+
}
|
|
58
|
+
/** Checks for a Standard Schema V1 validator. */
|
|
59
|
+
function isSchema(value) {
|
|
60
|
+
return (typeof value === "object" || typeof value === "function") && value !== null && "~standard" in value;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
6
63
|
//#region src/computed/plain-text.ts
|
|
7
64
|
const markdown = new src_default({ html: true });
|
|
8
65
|
const ignoredElements = /* @__PURE__ */ new Set([
|
|
@@ -136,4 +193,4 @@ function excerpt(options = {}) {
|
|
|
136
193
|
return textField(string(), options, (text) => truncate(text, maxLength));
|
|
137
194
|
}
|
|
138
195
|
//#endregion
|
|
139
|
-
export { excerpt, readingTime, wordCount };
|
|
196
|
+
export { computedFields, excerpt, readingTime, wordCount };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
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 {
|
|
4
|
-
import { n as QueryStyle } from "./query-style-
|
|
3
|
+
import { D as VariantValues, E as VariantOf, T as VariantField, _ as Relationship, a as ComputedContext, b as SchemaOutput, c as EntryFiles, d as PayloadContext, f as PayloadData, g as QueryData, h as PayloadsOf, i as CollectionRegistry, l as FileEntry, m as PayloadDefinition, n as BuiltinPayloads, o as CustomPayload, p as PayloadDeclaration, r as CollectionDefinition, s as CustomPayloadMarker, t as BuiltinPayloadMarker, w as VariantContext, x as SelectedData, y as Schema } from "./types-WOsFmNnN.mjs";
|
|
4
|
+
import { n as QueryStyle } from "./query-style-k8Qd7wh5.mjs";
|
|
5
5
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
6
|
//#region src/collection/source.d.ts
|
|
7
7
|
type CollectionSource = string | ({
|
|
@@ -134,4 +134,4 @@ export declare function defineCollection<const SourceSchema extends StandardSche
|
|
|
134
134
|
*/
|
|
135
135
|
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>;
|
|
136
136
|
//#endregion
|
|
137
|
-
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 };
|
|
137
|
+
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, SelectedData, VariantContext, VariantField, VariantOf, VariantValues };
|
package/dist/internal.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { n as Collection, r as CollectionHandles, s as ContentError } from "./collection-types-
|
|
1
|
+
import { n as Collection, r as CollectionHandles, s as ContentError } from "./collection-types-Ch4YLG8t.mjs";
|
|
2
2
|
import { n as ContentRenderResult } from "./types-Dh-Sydyw.mjs";
|
|
3
|
-
import { i as CollectionRegistry } from "./types-
|
|
4
|
-
import { O as QueryRegistry } from "./relational-types-
|
|
5
|
-
import { n as QueryStyle } from "./query-style-
|
|
6
|
-
import { n as PreparedRevision, t as ContentState } from "./revision-
|
|
3
|
+
import { i as CollectionRegistry } from "./types-WOsFmNnN.mjs";
|
|
4
|
+
import { O as QueryRegistry } from "./relational-types-DnI9wR5r.mjs";
|
|
5
|
+
import { n as QueryStyle } from "./query-style-k8Qd7wh5.mjs";
|
|
6
|
+
import { n as PreparedRevision, t as ContentState } from "./revision-vhe9gRyk.mjs";
|
|
7
7
|
//#region src/artifacts/types.d.ts
|
|
8
8
|
type ArtifactManifest = {
|
|
9
9
|
version: number;
|
package/dist/internal.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as ContentError } from "./errors-Bfd0R4_P.mjs";
|
|
2
2
|
import { r as decode } from "./values-BbTV4QT-.mjs";
|
|
3
|
-
import { i as isQueryStyle, n as createCollections, r as createLiveCollection, t as createCollection } from "./collection-
|
|
3
|
+
import { i as isQueryStyle, n as createCollections, r as createLiveCollection, t as createCollection } from "./collection-txOFpidL.mjs";
|
|
4
4
|
import { t as restoreContentError } from "./diagnostics-DmUZtrJ6.mjs";
|
|
5
5
|
//#region src/artifacts/runtime.ts
|
|
6
6
|
/** Checks that a value is a plain record before reading generated payload tables from it. */
|
package/dist/next.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as BuildContentOptions } from "./build-
|
|
1
|
+
import { t as BuildContentOptions } from "./build-DE4ZKHZR.mjs";
|
|
2
2
|
import { NextConfig } from "next";
|
|
3
3
|
//#region src/integrations/next/plugin.d.ts
|
|
4
4
|
/** Content locations for Next.js; the adapter chooses generated storage and the watch lifecycle. */
|
package/dist/next.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { I as collectionNames } from "./operators-D-w1-gDg.mjs";
|
|
2
|
-
import { c as collectionDeclarations, i as resolveConfigPath, t as buildAtRoot } from "./build-
|
|
2
|
+
import { c as collectionDeclarations, i as resolveConfigPath, t as buildAtRoot } from "./build-DYw3z9ju.mjs";
|
|
3
3
|
import { n as serializeContentError } from "./diagnostics-DmUZtrJ6.mjs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
@@ -7,7 +7,7 @@ type QueryStyle = "fluent" | "relational";
|
|
|
7
7
|
* belongs to both styles; `count(options)` takes relational options.
|
|
8
8
|
*/
|
|
9
9
|
declare const queryStyleMembers: {
|
|
10
|
-
readonly fluent: readonly ["select", "where", "orderBy", "limit", "offset", "with", "withPayload", "selectAdjacent"];
|
|
10
|
+
readonly fluent: readonly ["byId", "select", "where", "orderBy", "limit", "offset", "with", "withPayload", "selectAdjacent"];
|
|
11
11
|
readonly relational: readonly ["findMany", "findFirst", "paginate", "count(options)"];
|
|
12
12
|
};
|
|
13
13
|
/** A collection member that belongs to exactly one query style. */
|
package/dist/query.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Selection, E as Expression, S as ScalarField, T as Where, _ as PaginateResult, a as RelationalQueryOptions, b as RelationField, c as Adjacent, d as Field, f as Fields, g as PaginateOptions, h as PageOptions, i as RelationalQueries, l as CursorOptions, m as Ordered, n as RelationalCountOptions, o as RelationalQueryResult, p as NumberedPage, r as RelationalPaginateOptions, s as RelationalWhere, u as CursorPage, w as SelectionResult, x as Scalar, y as QueryFields } from "./relational-types-
|
|
1
|
+
import { C as Selection, E as Expression, S as ScalarField, T as Where, _ as PaginateResult, a as RelationalQueryOptions, b as RelationField, c as Adjacent, d as Field, f as Fields, g as PaginateOptions, h as PageOptions, i as RelationalQueries, l as CursorOptions, m as Ordered, n as RelationalCountOptions, o as RelationalQueryResult, p as NumberedPage, r as RelationalPaginateOptions, s as RelationalWhere, u as CursorPage, w as SelectionResult, x as Scalar, y as QueryFields } from "./relational-types-DnI9wR5r.mjs";
|
|
2
2
|
//#region src/query/operators.d.ts
|
|
3
3
|
/** Matches a scalar using strict value/date equality. */
|
|
4
4
|
export declare function eq<Value>(field: ScalarField<Value>, value: NoInfer<Value>): Expression;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as UnavailableRelationshipsOf, E as VariantOf, S as UnavailableRelationship, _ as Relationship, g as QueryData, h as PayloadsOf, i as CollectionRegistry, v as RelationshipsOf, x as SelectedData } from "./types-WOsFmNnN.mjs";
|
|
2
2
|
//#region src/query/plan.d.ts
|
|
3
3
|
type PredicateOperator = "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in-array" | "not-in-array" | "contains" | "starts-with" | "ends-with" | "like" | "ilike" | "array-contains" | "array-contains-any" | "array-contains-all" | "array-contained" | "is-null" | "is-undefined" | "is-missing";
|
|
4
4
|
type Expression = {
|
|
@@ -142,7 +142,8 @@ type RelatedName$1<Registry extends CollectionRegistry, Relation extends Relatio
|
|
|
142
142
|
type RelationshipResult<Definition, Relation extends Relationship, Result, Filtered extends boolean = false> = Relation["type"] extends "many" ? Result[] : Result | (Filtered extends true ? null : Relation["referenceSide"] extends "from" ? Relation["from"] extends keyof QueryData<Definition> ? null extends QueryData<Definition>[Relation["from"]] ? null : undefined extends QueryData<Definition>[Relation["from"]] ? null : never : null : null);
|
|
143
143
|
type RelationValue<Definition, Relation extends Relationship, Configured> = RelationshipResult<Definition, Relation, ResultOf<Configured>, FilteredOf<Configured>>;
|
|
144
144
|
type Query<Registry extends CollectionRegistry, Name extends keyof Registry & string, Result = {}, Selected extends boolean = false, Many extends boolean = true, Root extends boolean = true, Filtered extends boolean = false, AllowAdjacent extends boolean = true, Pagination extends boolean = true, Paged extends boolean = false> = QueryInfo<Result, Selected, Filtered> & {
|
|
145
|
-
|
|
145
|
+
/** Selects fields, adding to fields that earlier `select()` calls on this scope selected. */
|
|
146
|
+
select<const Keys extends readonly [keyof QueryData<Registry[Name]> & string, ...(keyof QueryData<Registry[Name]> & string)[]]>(...keys: Keys): Query<Registry, Name, Simplify$1<Result & SelectedData<QueryData<Registry[Name]>, Keys[number]>>, true, Many, Root, Filtered, AllowAdjacent, Pagination, Paged>;
|
|
146
147
|
where(configure: (fields: QueryFields<Registry, Name>) => Expression): Query<Registry, Name, Result, Selected, Many, Root, true, AllowAdjacent, Pagination, Paged>;
|
|
147
148
|
with<Key extends keyof RelationshipsOf<Registry[Name]> & string, Configured extends QueryInfo<unknown, true>>(name: Key, configure: (query: Query<Registry, RelatedName$1<Registry, RelationOf<Registry, Name, Key>>, {}, false, RelationOf<Registry, Name, Key>["type"] extends "many" ? true : false, false, false, AllowAdjacent>) => Configured): Query<Registry, Name, Result & { [Property in Key]: RelationValue<Registry[Name], RelationOf<Registry, Name, Key>, Configured>; }, true, Many, Root, Filtered, AllowAdjacent, Pagination, Paged>;
|
|
148
149
|
/** A relationship into a collection the query has not loaded reports which one to supply. */
|
|
@@ -152,33 +153,41 @@ type Query<Registry extends CollectionRegistry, Name extends keyof Registry & st
|
|
|
152
153
|
} : {}) & (Many extends true ? Pagination extends true ? {
|
|
153
154
|
limit(value: number): Query<Registry, Name, Result, Selected, Many, Root, Filtered, AllowAdjacent, Pagination, true>;
|
|
154
155
|
offset(value: number): Query<Registry, Name, Result, Selected, Many, Root, Filtered, AllowAdjacent, Pagination, true>;
|
|
155
|
-
} : {} : {}) & (AllowAdjacent extends true ? {
|
|
156
|
-
/** Attaches a payload under `_payloads` after filtering, ordering, and pagination. */
|
|
157
|
-
withPayload<Key extends keyof PayloadsOf<Registry[Name]> & string>(name: Key, ...variant: keyof VariantOf<Registry[Name], Key> extends never ? [] : [variant: Readonly<VariantOf<Registry[Name], Key>>]): Query<Registry, Name, WithPayload<Result, Key, PayloadsOf<Registry[Name]>[Key]>, true, Many, Root, Filtered, AllowAdjacent, Pagination, Paged>;
|
|
156
|
+
} : {} : {}) & (AllowAdjacent extends true ? [Root, Many] extends [true, false] ? {} : {
|
|
158
157
|
/** Selects neighbor fields within this scope's filtered and ordered results. */
|
|
159
158
|
selectAdjacent<const Keys extends readonly [keyof QueryData<Registry[Name]> & string, ...(keyof QueryData<Registry[Name]> & string)[]]>(...fields: Keys): Query<Registry, Name, Result & {
|
|
160
|
-
_adjacent: Adjacent<
|
|
159
|
+
_adjacent: Adjacent<SelectedData<QueryData<Registry[Name]>, Keys[number]>>;
|
|
161
160
|
}, true, Many, Root, Filtered, AllowAdjacent, Pagination, Paged>;
|
|
161
|
+
} : {}) & (AllowAdjacent extends true ? {
|
|
162
|
+
/** Attaches a payload under `_payloads` after filtering, ordering, and pagination. */
|
|
163
|
+
withPayload<Key extends keyof PayloadsOf<Registry[Name]> & string>(name: Key, ...variant: keyof VariantOf<Registry[Name], Key> extends never ? [] : [variant: Readonly<VariantOf<Registry[Name], Key>>]): Query<Registry, Name, WithPayload<Result, Key, PayloadsOf<Registry[Name]>[Key]>, true, Many, Root, Filtered, AllowAdjacent, Pagination, Paged>;
|
|
164
|
+
/** Selects neighbors from an independent sibling scope. */
|
|
162
165
|
selectAdjacent<Configured extends QueryInfo<unknown, true>>(configure: (siblings: Query<Registry, Name, {}, false, true, false, false, false, false>) => Configured): Query<Registry, Name, Result & {
|
|
163
166
|
_adjacent: Adjacent<ResultOf<Configured>>;
|
|
164
167
|
}, true, Many, Root, Filtered, AllowAdjacent, Pagination, Paged>;
|
|
165
168
|
selectAdjacent<const Options extends AdjacentOptions<Registry, Name>>(options: Options & CheckedOptions<Registry, Name, NoInfer<Options>, true, false, false>): Query<Registry, Name, Result & {
|
|
166
169
|
_adjacent: Adjacent<SelectionResult<Registry, Name, Options["select"]>>;
|
|
167
170
|
}, true, Many, Root, Filtered, AllowAdjacent, Pagination, Paged>;
|
|
168
|
-
} : {}) & (Root extends true ? {
|
|
171
|
+
} : {}) & (Root extends true ? (Many extends true ? {
|
|
169
172
|
all: Selected extends true ? () => Promise<Simplify$1<Result>[]> : UnselectedTerminal;
|
|
170
173
|
execute: Selected extends true ? () => Promise<Simplify$1<Result>[]> : UnselectedTerminal;
|
|
171
174
|
then: Selected extends true ? Promise<Simplify$1<Result>[]>["then"] : UnselectedThen;
|
|
175
|
+
/**
|
|
176
|
+
* Returns one page from one revision: `{ page, size }` for page numbers, or
|
|
177
|
+
* `{ size, after?, before?, total? }` for cursors. Unavailable after `limit()` or
|
|
178
|
+
* `offset()`.
|
|
179
|
+
*/
|
|
180
|
+
paginate: Selected extends true ? [Paged] extends [true] ? PaginateAfterLimit : Paginate<Simplify$1<Result>> : UnselectedTerminal;
|
|
181
|
+
} : {
|
|
182
|
+
/** Runs a `byId()` query, matching direct await: the entry, or `undefined`. */
|
|
183
|
+
execute: Selected extends true ? () => Promise<Simplify$1<Result> | undefined> : UnselectedTerminal;
|
|
184
|
+
then: Selected extends true ? Promise<Simplify$1<Result> | undefined>["then"] : UnselectedThen;
|
|
185
|
+
}) & {
|
|
172
186
|
first: Selected extends true ? () => Promise<Simplify$1<Result> | undefined> : UnselectedTerminal;
|
|
173
187
|
/** Counts matching entries without a selection; unavailable once payloads are requested. */
|
|
174
188
|
count: [Result] extends [never] ? () => Promise<number> : [Result] extends [{
|
|
175
189
|
_payloads: unknown;
|
|
176
190
|
}] ? never : () => Promise<number>;
|
|
177
|
-
/**
|
|
178
|
-
* Returns one page from one revision: `{ page, size }` for page numbers, or
|
|
179
|
-
* `{ size, after?, before?, total? }` for cursors. Unavailable after `limit()` or `offset()`.
|
|
180
|
-
*/
|
|
181
|
-
paginate: Selected extends true ? [Paged] extends [true] ? PaginateAfterLimit : Paginate<Simplify$1<Result>> : UnselectedTerminal;
|
|
182
191
|
} : {});
|
|
183
192
|
/** `paginate()` after `limit()` or `offset()` reports why as its required `this` type. */
|
|
184
193
|
type PaginateAfterLimit = (this: typeof PAGINATE_AFTER_LIMIT_MESSAGE, ...arguments_: readonly unknown[]) => never;
|
|
@@ -304,9 +313,11 @@ type Selection<Registry extends CollectionRegistry, Name extends keyof Registry
|
|
|
304
313
|
type ObjectRelationValue<Registry extends CollectionRegistry, Name extends keyof Registry & string, Key extends keyof RelationshipsOf<Registry[Name]>, Options> = Options extends {
|
|
305
314
|
select: infer Projection;
|
|
306
315
|
} ? RelationValue<Registry[Name], RelationOf<Registry, Name, Key>, QueryInfo<SelectionResult<Registry, RelatedName$1<Registry, RelationOf<Registry, Name, Key>>, Projection>, true, "where" extends keyof Options ? true : false>> : never;
|
|
307
|
-
|
|
316
|
+
/** Data fields an object projection requests, excluding relationships and `_adjacent`. */
|
|
317
|
+
type ProjectedFields<Registry extends CollectionRegistry, Name extends keyof Registry & string, Projection> = Exclude<{ [Key in keyof Projection]-?: Projection[Key] extends false | undefined ? never : Key; }[keyof Projection], "_adjacent" | keyof RelationshipsOf<Registry[Name]>> & keyof QueryData<Registry[Name]>;
|
|
318
|
+
type SelectionResult<Registry extends CollectionRegistry, Name extends keyof Registry & string, Projection> = Simplify$1<{ -readonly [Key in keyof Projection as Projection[Key] extends false | undefined ? never : Key extends ProjectedFields<Registry, Name, Projection> ? never : Key]-?: Key extends "_adjacent" ? Projection[Key] extends {
|
|
308
319
|
select: infer Neighbors;
|
|
309
|
-
} ? Adjacent<SelectionResult<Registry, Name, Neighbors>> : never : Key extends keyof RelationshipsOf<Registry[Name]> ? ObjectRelationValue<Registry, Name, Key, Projection[Key]> :
|
|
320
|
+
} ? Adjacent<SelectionResult<Registry, Name, Neighbors>> : never : Key extends keyof RelationshipsOf<Registry[Name]> ? ObjectRelationValue<Registry, Name, Key, Projection[Key]> : never; } & SelectedData<QueryData<Registry[Name]>, ProjectedFields<Registry, Name, Projection>>>;
|
|
310
321
|
type CheckedField<Value, Filter> = Filter extends Scalar ? Filter : { [Operator in keyof Filter]: Operator extends keyof FieldFilter$1<Value> ? Operator extends "not" ? CheckedField<Value, Filter[Operator]> : Filter[Operator] : never; };
|
|
311
322
|
type CheckedWhereList$1<Data, Filters extends readonly unknown[]> = { [Index in keyof Filters]: CheckedWhere$1<Data, Filters[Index]>; };
|
|
312
323
|
type CheckedWhere$1<Data, Filter> = Filter extends ((...arguments_: never[]) => unknown) ? Filter : { [Key in keyof Filter]: Key extends "AND" | "OR" | "NOT" ? Filter[Key] extends readonly unknown[] ? CheckedWhereList$1<Data, Filter[Key]> : CheckedWhere$1<Data, Filter[Key]> : Key extends keyof Data ? CheckedField<Data[Key], Filter[Key]> : never; };
|
|
@@ -402,7 +413,7 @@ type RelationalPaginateOptions<Registry extends CollectionRegistry, Name extends
|
|
|
402
413
|
type RelationalCountOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string> = Pick<RelationalQueryOptions<Registry, Name>, "where" | "orderBy" | "offset" | "limit">;
|
|
403
414
|
type ColumnResult<Data, Options> = Options extends {
|
|
404
415
|
columns: infer Columns;
|
|
405
|
-
} ? {
|
|
416
|
+
} ? SelectedData<Data, { [Key in keyof Columns]-?: Columns[Key] extends true ? Key : never; }[keyof Columns] & keyof Data> : {};
|
|
406
417
|
/** Keys whose option values request something, as opposed to `false` or `undefined`. */
|
|
407
418
|
type Requested<Map> = keyof { [Key in keyof Map as Map[Key] extends false | undefined ? never : Key]: unknown; };
|
|
408
419
|
/** Whether options select fields, include relationships, request payloads, or select adjacency. */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { s as ContentError } from "./collection-types-
|
|
1
|
+
import { s as ContentError } from "./collection-types-Ch4YLG8t.mjs";
|
|
2
2
|
import { n as ContentRenderResult } from "./types-Dh-Sydyw.mjs";
|
|
3
|
-
import { _ as Relationship } from "./types-
|
|
4
|
-
import { D as QueryPlan, O as QueryRegistry, k as QueryTerminal } from "./relational-types-
|
|
5
|
-
import { n as QueryStyle } from "./query-style-
|
|
3
|
+
import { _ as Relationship } from "./types-WOsFmNnN.mjs";
|
|
4
|
+
import { D as QueryPlan, O as QueryRegistry, k as QueryTerminal } from "./relational-types-DnI9wR5r.mjs";
|
|
5
|
+
import { n as QueryStyle } from "./query-style-k8Qd7wh5.mjs";
|
|
6
6
|
//#region src/runtime/revision.d.ts
|
|
7
7
|
type QueryRecord = Record<string, unknown> & {
|
|
8
8
|
id: string;
|
package/dist/runtime.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as ContentErrorCode, i as LoadedRegistry, n as Collection, o as ContentDiagnostic, r as CollectionHandles, s as ContentError, t as AnyCollection } from "./collection-types-
|
|
1
|
+
import { c as ContentErrorCode, i as LoadedRegistry, n as Collection, o as ContentDiagnostic, r as CollectionHandles, s as ContentError, t as AnyCollection } from "./collection-types-Ch4YLG8t.mjs";
|
|
2
2
|
import { n as ContentRenderResult, t as ContentHeading } from "./types-Dh-Sydyw.mjs";
|
|
3
|
-
import { n as QueryStyle, r as QueryStyleDisabled } from "./query-style-
|
|
3
|
+
import { n as QueryStyle, r as QueryStyleDisabled } from "./query-style-k8Qd7wh5.mjs";
|
|
4
4
|
export { type AnyCollection, type Collection, type CollectionHandles, type ContentDiagnostic, ContentError, type ContentErrorCode, type ContentHeading, type ContentRenderResult, type LoadedRegistry, type QueryStyle, type QueryStyleDisabled };
|
|
@@ -143,9 +143,26 @@ type ComputedData<Definition> = Definition extends {
|
|
|
143
143
|
} ? { [Name in keyof Computed]: Computed[Name] extends {
|
|
144
144
|
schema: infer ResultSchema;
|
|
145
145
|
} ? SchemaOutput<ResultSchema> : never; } : {};
|
|
146
|
+
/**
|
|
147
|
+
* An entry's ID, validated metadata, and computed fields. JSDoc comments on schema fields and
|
|
148
|
+
* computed field names carry through, so editors show them when hovering a field.
|
|
149
|
+
*/
|
|
146
150
|
type QueryData<Definition> = {
|
|
151
|
+
/** The entry's ID, unique within its collection. */
|
|
147
152
|
id: string;
|
|
148
153
|
} & EntryData<Definition> & ComputedData<Definition>;
|
|
154
|
+
/** Maps `Field` without reading `Data`'s modifiers, so every key is required. */
|
|
155
|
+
type PresentFields<Data, Field extends PropertyKey> = { [Key in Field]: Key extends keyof Data ? Data[Key] : never; };
|
|
156
|
+
/** Flattens an intersection into one mutable object type, keeping each property's declaration. */
|
|
157
|
+
type MutableObject<Value> = { -readonly [Key in keyof Value]: Value[Key]; };
|
|
158
|
+
/**
|
|
159
|
+
* The shape of `Data` when a query selects `Field`. Every selected key is present and mutable,
|
|
160
|
+
* and an optional field's value includes `undefined` instead of the key being optional.
|
|
161
|
+
*
|
|
162
|
+
* Each property stays linked to its declaration in `Data`, so JSDoc comments written on schema
|
|
163
|
+
* fields show when hovering a selected field, and go to definition opens the schema.
|
|
164
|
+
*/
|
|
165
|
+
type SelectedData<Data, Field extends keyof Data> = MutableObject<PresentFields<Data, Field> & Pick<Data, Field>>;
|
|
149
166
|
/**
|
|
150
167
|
* Type-only marker recording which collections a query scope loaded. A marked definition offers
|
|
151
168
|
* only the relationships whose target is loaded; an unmarked one offers every relationship.
|
|
@@ -211,4 +228,4 @@ type PayloadData<Definition, Name extends keyof PayloadsOf<Definition>> = Payloa
|
|
|
211
228
|
/** The variant keys a payload request must supply; empty for built-in and single-value payloads. */
|
|
212
229
|
type VariantOf<Definition, Name> = Name extends keyof CustomPayloadsOf<Definition> ? CustomPayloadsOf<Definition>[Name] extends CustomPayload<unknown, infer Variant> ? Variant : {} : {};
|
|
213
230
|
//#endregion
|
|
214
|
-
export {
|
|
231
|
+
export { UnavailableRelationshipsOf as C, VariantValues as D, VariantOf as E, UnavailableRelationship as S, VariantField as T, Relationship as _, ComputedContext as a, SchemaOutput as b, EntryFiles as c, PayloadContext as d, PayloadData as f, QueryData as g, PayloadsOf as h, CollectionRegistry as i, FileEntry as l, PayloadDefinition as m, BuiltinPayloads as n, CustomPayload as o, PayloadDeclaration as p, CollectionDefinition as r, CustomPayloadMarker as s, BuiltinPayloadMarker as t, LoadedMarker as u, RelationshipsOf as v, VariantContext as w, SelectedData as x, Schema as y };
|
package/dist/vite.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ContentSourceEvent, o as ContentSourceSnapshot, t as BuildContentOptions } from "./build-
|
|
1
|
+
import { a as ContentSourceEvent, o as ContentSourceSnapshot, t as BuildContentOptions } from "./build-DE4ZKHZR.mjs";
|
|
2
2
|
import { Plugin } from "vite";
|
|
3
3
|
//#region src/integrations/vite/plugin.d.ts
|
|
4
4
|
/** Public, format-neutral hooks for integrations sharing this plugin's preparation session. */
|
package/dist/vite.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { I as collectionNames } from "./operators-D-w1-gDg.mjs";
|
|
2
|
-
import { a as sessionInternals, i as resolveConfigPath, l as virtualDeclarations, o as withinDirectory, r as configCandidates, s as writeChanged, t as buildAtRoot, u as revisionModules } from "./build-
|
|
2
|
+
import { a as sessionInternals, i as resolveConfigPath, l as virtualDeclarations, o as withinDirectory, r as configCandidates, s as writeChanged, t as buildAtRoot, u as revisionModules } from "./build-DYw3z9ju.mjs";
|
|
3
3
|
import { n as serializeContentError } from "./diagnostics-DmUZtrJ6.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import path from "node:path";
|
package/package.json
CHANGED