content-query 0.2.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.
Files changed (37) hide show
  1. package/README.md +28 -3
  2. package/dist/{build-Dxz7P1ur.mjs → build-CcqIpkes.mjs} +763 -39
  3. package/dist/build-DL1GzmRy.d.mts +55 -0
  4. package/dist/build.d.mts +2 -2
  5. package/dist/build.mjs +1 -1
  6. package/dist/cli.mjs +14 -8
  7. package/dist/computed.d.mts +2 -2
  8. package/dist/{content-N1gYshjg.mjs → content-BXrgP7nL.mjs} +271 -81
  9. package/dist/{content-G69dPPuo.d.mts → content-CwTKqRs9.d.mts} +49 -24
  10. package/dist/{types-ChaNhj42.d.mts → descriptor-bcPa6XLk.d.mts} +26 -1
  11. package/dist/{diagnostics-Cu94mZhl.mjs → diagnostics-DmUZtrJ6.mjs} +3 -1
  12. package/dist/{errors-C2iuBM0G.mjs → errors-Bfd0R4_P.mjs} +16 -1
  13. package/dist/file-DSOcdFj0.mjs +81 -0
  14. package/dist/{glob-Bv0dpvCQ.mjs → glob-BXJuwy_p.mjs} +94 -6
  15. package/dist/index.d.mts +61 -17
  16. package/dist/index.mjs +1 -1
  17. package/dist/internal.d.mts +11 -4
  18. package/dist/internal.mjs +29 -5
  19. package/dist/loaders.d.mts +2 -3
  20. package/dist/loaders.mjs +2 -81
  21. package/dist/next.d.mts +1 -1
  22. package/dist/next.mjs +2 -2
  23. package/dist/{operators-UqWUhKQJ.mjs → operators-Cwy8Kx4o.mjs} +88 -2
  24. package/dist/query-style-eXENQJ0O.d.mts +22 -0
  25. package/dist/query.d.mts +25 -2
  26. package/dist/query.mjs +1 -1
  27. package/dist/{relational-types-DgK3rLuw.d.mts → relational-types-C8xJtLG5.d.mts} +113 -38
  28. package/dist/runtime.d.mts +3 -2
  29. package/dist/runtime.mjs +1 -1
  30. package/dist/types-DbFfF6JE.d.mts +181 -0
  31. package/dist/vite.d.mts +15 -3
  32. package/dist/vite.mjs +25 -2
  33. package/package.json +2 -2
  34. package/dist/build-DfKd2bpf.d.mts +0 -25
  35. package/dist/descriptor-D9Th5hzk.d.mts +0 -18
  36. package/dist/types-C-kdMblM.d.mts +0 -69
  37. package/dist/validation-D_XdE1pF.mjs +0 -84
@@ -1,4 +1,4 @@
1
- import { c as Relationship, i as CollectionRegistry, l as RelationshipsOf, o as PayloadsOf, s as QueryData } from "./types-C-kdMblM.mjs";
1
+ import { S as VariantOf, _ as RelationshipsOf, g as Relationship, h as QueryData, i as CollectionRegistry, m as PayloadsOf } from "./types-DbFfF6JE.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 = {
@@ -12,15 +12,20 @@ type Expression = {
12
12
  field: string;
13
13
  target: string;
14
14
  expression: Expression;
15
+ } |
16
+ /** A fluent `has()` filter that query builders resolve into a `relation` expression. */
17
+ {
18
+ kind: "has";
19
+ field: string;
20
+ expression: Expression;
15
21
  } | {
16
22
  kind: "and" | "or" | "not";
17
23
  expressions: readonly Expression[];
18
24
  };
19
25
  type QueryPlan = {
20
26
  collection: string;
27
+ /** Explicitly selected fields; scopes never include unselected fields, including `id`. */
21
28
  select?: readonly string[];
22
- allFields?: boolean;
23
- exclude?: readonly string[];
24
29
  filters: readonly Expression[];
25
30
  order: readonly {
26
31
  field: string;
@@ -29,10 +34,19 @@ type QueryPlan = {
29
34
  limit?: number;
30
35
  offset?: number;
31
36
  with: Readonly<Record<string, QueryPlan>>;
32
- adjacent?: true | QueryPlan;
37
+ adjacent?: AdjacentPlan;
33
38
  /** Payloads to attach under `_payloads` after filtering, ordering, and pagination. */
34
39
  payloads?: Readonly<Record<string, PlanPayload>>;
35
40
  };
41
+ /**
42
+ * Selects previous and next entries. `results` finds neighbors within the scope's own filtered and
43
+ * ordered entries, or a parent's related entries, and `plan` holds only their selection;
44
+ * `collection` finds neighbors in an independent sibling scope described by `plan`.
45
+ */
46
+ type AdjacentPlan = {
47
+ scope: "results" | "collection";
48
+ plan: QueryPlan;
49
+ };
36
50
  /** One requested payload; variant keys are empty for payloads without variants. */
37
51
  type PlanPayload = {
38
52
  variant: Readonly<Record<string, string>>;
@@ -46,15 +60,29 @@ type QueryRegistry = Record<string, {
46
60
  /** Payload names available to queries; omitted when the collection has none. */
47
61
  payloads?: Record<string, PayloadDescriptor>;
48
62
  }>;
63
+ /** Explains the explicit-selection rule wherever a scope returns rows without selecting data. */
64
+ declare const NO_SELECTION_MESSAGE: "Select fields, relationships, payloads, or adjacent entries before running this query.";
49
65
  //#endregion
50
66
  //#region src/query/types.d.ts
51
67
  declare const queryType: unique symbol;
68
+ /** Running an unselected query reports the explicit-selection rule as its required `this` type. */
69
+ type UnselectedTerminal = (this: typeof NO_SELECTION_MESSAGE, ...arguments_: readonly unknown[]) => never;
70
+ /** A `then` that cannot resolve a value, so awaiting an unselected query fails to compile. */
71
+ type UnselectedThen = (selectBeforeAwaiting: typeof NO_SELECTION_MESSAGE) => never;
52
72
  declare const fieldType: unique symbol;
53
73
  type Field$1<Value> = {
54
74
  readonly name: string;
55
75
  readonly [fieldType]: Value;
56
76
  };
57
77
  type Fields<Data> = { readonly [Name in keyof Data]-?: Field$1<Data[Name]>; };
78
+ declare const relationTarget: unique symbol;
79
+ /** A relationship in a fluent `where()` callback, filtered with `has()`. */
80
+ type RelationField<TargetFields> = {
81
+ readonly name: string;
82
+ readonly [relationTarget]: TargetFields;
83
+ };
84
+ /** Fields and relationships available to a fluent `where()` callback. */
85
+ type QueryFields<Registry extends CollectionRegistry, Name extends keyof Registry & string> = Fields<QueryData<Registry[Name]>> & { readonly [Key in keyof RelationshipsOf<Registry[Name]> & string]-?: RelationField<QueryFields<Registry, RelatedName$1<Registry, RelationOf<Registry, Name, Key>>>>; };
58
86
  type Scalar = string | number | bigint | boolean | Date | null | undefined;
59
87
  type ScalarField<Value> = Field$1<Value> & ([Value] extends [Scalar] ? unknown : never);
60
88
  type Ordered<Value> = NonNullable<Value> extends string ? unknown : NonNullable<Value> extends number ? unknown : NonNullable<Value> extends bigint ? unknown : NonNullable<Value> extends Date ? unknown : never;
@@ -82,7 +110,7 @@ type RelationshipResult<Definition, Relation extends Relationship, Result, Filte
82
110
  type RelationValue<Definition, Relation extends Relationship, Configured> = RelationshipResult<Definition, Relation, ResultOf<Configured>, FilteredOf<Configured>>;
83
111
  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> = QueryInfo<Result, Selected, Filtered> & {
84
112
  select<const Keys extends readonly [keyof QueryData<Registry[Name]> & string, ...(keyof QueryData<Registry[Name]> & string)[]]>(...keys: Keys): Query<Registry, Name, { [Key in Exclude<keyof Result, keyof QueryData<Registry[Name]>> | Keys[number]]: Key extends Keys[number] ? QueryData<Registry[Name]>[Key & keyof QueryData<Registry[Name]>] : Key extends keyof Result ? Result[Key] : never; }, true, Many, Root, Filtered, AllowAdjacent, Pagination>;
85
- where(configure: (fields: Fields<QueryData<Registry[Name]>>) => Expression): Query<Registry, Name, Result, Selected, Many, Root, true, AllowAdjacent, Pagination>;
113
+ where(configure: (fields: QueryFields<Registry, Name>) => Expression): Query<Registry, Name, Result, Selected, Many, Root, true, AllowAdjacent, Pagination>;
86
114
  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>;
87
115
  } & (Many extends true ? {
88
116
  orderBy(field: SortKey<QueryData<Registry[Name]>>, direction?: "asc" | "desc"): Query<Registry, Name, Result, Selected, Many, Root, Filtered, AllowAdjacent, Pagination>;
@@ -91,11 +119,10 @@ type Query<Registry extends CollectionRegistry, Name extends keyof Registry & st
91
119
  offset(value: number): Query<Registry, Name, Result, Selected, Many, Root, Filtered, AllowAdjacent, Pagination>;
92
120
  } : {} : {}) & (AllowAdjacent extends true ? {
93
121
  /** Attaches a payload under `_payloads` after filtering, ordering, and pagination. */
94
- withPayload<Key extends keyof PayloadsOf<Registry[Name]> & string>(name: Key): Query<Registry, Name, WithPayload<Result, Key, PayloadsOf<Registry[Name]>[Key]>, Selected, Many, Root, Filtered, AllowAdjacent, Pagination>;
95
- selectAdjacent(): Query<Registry, Name, Result & {
96
- _adjacent: Adjacent<{
97
- id: string;
98
- }>;
122
+ 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>;
123
+ /** Selects neighbor fields within this scope's filtered and ordered results. */
124
+ selectAdjacent<const Keys extends readonly [keyof QueryData<Registry[Name]> & string, ...(keyof QueryData<Registry[Name]> & string)[]]>(...fields: Keys): Query<Registry, Name, Result & {
125
+ _adjacent: Adjacent<{ [Key in Keys[number]]: QueryData<Registry[Name]>[Key & keyof QueryData<Registry[Name]>]; }>;
99
126
  }, true, Many, Root, Filtered, AllowAdjacent, Pagination>;
100
127
  selectAdjacent<Configured extends QueryInfo<unknown, true>>(configure: (siblings: Query<Registry, Name, {}, false, true, false, false, false, false>) => Configured): Query<Registry, Name, Result & {
101
128
  _adjacent: Adjacent<ResultOf<Configured>>;
@@ -104,11 +131,11 @@ type Query<Registry extends CollectionRegistry, Name extends keyof Registry & st
104
131
  _adjacent: Adjacent<SelectionResult<Registry, Name, Options["select"]>>;
105
132
  }, true, Many, Root, Filtered, AllowAdjacent, Pagination>;
106
133
  } : {}) & (Root extends true ? {
107
- all: Selected extends true ? () => Promise<Simplify$1<Result>[]> : never;
108
- execute: Selected extends true ? () => Promise<Simplify$1<Result>[]> : never;
109
- then: Selected extends true ? Promise<Simplify$1<Result>[]>["then"] : never;
110
- first: Selected extends true ? () => Promise<Simplify$1<Result> | undefined> : never;
111
- /** Counts matching entries; unavailable once payloads are requested. */
134
+ all: Selected extends true ? () => Promise<Simplify$1<Result>[]> : UnselectedTerminal;
135
+ execute: Selected extends true ? () => Promise<Simplify$1<Result>[]> : UnselectedTerminal;
136
+ then: Selected extends true ? Promise<Simplify$1<Result>[]>["then"] : UnselectedThen;
137
+ first: Selected extends true ? () => Promise<Simplify$1<Result> | undefined> : UnselectedTerminal;
138
+ /** Counts matching entries without a selection; unavailable once payloads are requested. */
112
139
  count: [Result] extends [never] ? () => Promise<number> : [Result] extends [{
113
140
  _payloads: unknown;
114
141
  }] ? never : () => Promise<number>;
@@ -149,7 +176,7 @@ type Where<Data> = { [Name in keyof Data]?: [Data[Name]] extends [Scalar] ? Data
149
176
  };
150
177
  type OrderBy<Data> = Partial<Record<SortKey<Data>, "asc" | "desc">>;
151
178
  type ObjectScope<Registry extends CollectionRegistry, Name extends keyof Registry & string, Many extends boolean> = {
152
- where?: Where<QueryData<Registry[Name]>> | ((fields: Fields<QueryData<Registry[Name]>>) => Expression);
179
+ where?: Where<QueryData<Registry[Name]>> | ((fields: QueryFields<Registry, Name>) => Expression);
153
180
  } & (Many extends true ? {
154
181
  orderBy?: OrderBy<QueryData<Registry[Name]>> | readonly OrderBy<QueryData<Registry[Name]>>[];
155
182
  limit?: number;
@@ -160,20 +187,27 @@ type QueryOptions<Registry extends CollectionRegistry, Name extends keyof Regist
160
187
  };
161
188
  type AdjacentOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string> = Omit<QueryOptions<Registry, Name, true, false>, "limit" | "offset">;
162
189
  type Selection<Registry extends CollectionRegistry, Name extends keyof Registry & string, AllowAdjacent extends boolean = true> = { [Field in keyof QueryData<Registry[Name]>]?: boolean; } & { [Key in keyof RelationshipsOf<Registry[Name]>]?: QueryOptions<Registry, RelatedName$1<Registry, RelationOf<Registry, Name, Key>>, RelationOf<Registry, Name, Key>["type"] extends "many" ? true : false, AllowAdjacent> | false; } & (AllowAdjacent extends true ? {
163
- _adjacent?: true | AdjacentOptions<Registry, Name>;
190
+ _adjacent?: {
191
+ scope: "results";
192
+ select: Selection<Registry, Name, false>;
193
+ } | (AdjacentOptions<Registry, Name> & {
194
+ scope?: "collection";
195
+ });
164
196
  } : {});
165
197
  type ObjectRelationValue<Registry extends CollectionRegistry, Name extends keyof Registry & string, Key extends keyof RelationshipsOf<Registry[Name]>, Options> = Options extends {
166
198
  select: infer Projection;
167
199
  } ? 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;
168
- type SelectionResult<Registry extends CollectionRegistry, Name extends keyof Registry & string, Projection> = { -readonly [Key in keyof Projection as Projection[Key] extends false | undefined ? never : Key]-?: Key extends "_adjacent" ? Projection[Key] extends true ? Adjacent<{
169
- id: string;
170
- }> : Projection[Key] extends {
200
+ type SelectionResult<Registry extends CollectionRegistry, Name extends keyof Registry & string, Projection> = { -readonly [Key in keyof Projection as Projection[Key] extends false | undefined ? never : Key]-?: Key extends "_adjacent" ? Projection[Key] extends {
171
201
  select: infer Neighbors;
172
202
  } ? Adjacent<SelectionResult<Registry, Name, Neighbors>> : never : Key extends keyof RelationshipsOf<Registry[Name]> ? ObjectRelationValue<Registry, Name, Key, Projection[Key]> : Key extends keyof QueryData<Registry[Name]> ? QueryData<Registry[Name]>[Key] : never; };
173
203
  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; };
174
204
  type CheckedWhereList$1<Data, Filters extends readonly unknown[]> = { [Index in keyof Filters]: CheckedWhere$1<Data, Filters[Index]>; };
175
205
  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; };
176
- type CheckedSelection<Registry extends CollectionRegistry, Name extends keyof Registry & string, Projection, AllowAdjacent extends boolean> = { [Key in keyof Projection]: Key extends "_adjacent" ? AllowAdjacent extends true ? Projection[Key] extends true ? true : CheckedOptions<Registry, Name, Projection[Key], true, false, false> : never : Key extends keyof RelationshipsOf<Registry[Name]> ? Projection[Key] extends false ? false : CheckedOptions<Registry, RelatedName$1<Registry, RelationOf<Registry, Name, Key>>, Projection[Key], RelationOf<Registry, Name, Key>["type"] extends "many" ? true : false, AllowAdjacent> : Key extends keyof QueryData<Registry[Name]> ? Projection[Key] : never; };
206
+ type CheckedSelection<Registry extends CollectionRegistry, Name extends keyof Registry & string, Projection, AllowAdjacent extends boolean> = { [Key in keyof Projection]: Key extends "_adjacent" ? AllowAdjacent extends true ? Projection[Key] extends {
207
+ scope: "results";
208
+ } ? { [Option in keyof Projection[Key]]: Option extends "scope" ? "results" : Option extends "select" ? CheckedSelection<Registry, Name, Projection[Key][Option], false> : never; } : CheckedOptions<Registry, Name, Omit<Projection[Key], "scope">, true, false, false> & {
209
+ scope?: "collection";
210
+ } : never : Key extends keyof RelationshipsOf<Registry[Name]> ? Projection[Key] extends false ? false : CheckedOptions<Registry, RelatedName$1<Registry, RelationOf<Registry, Name, Key>>, Projection[Key], RelationOf<Registry, Name, Key>["type"] extends "many" ? true : false, AllowAdjacent> : Key extends keyof QueryData<Registry[Name]> ? Projection[Key] : never; };
177
211
  /** Rejects extra properties throughout inferred options, including recursive neighbor projections. */
178
212
  type CheckedOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string, Options, Many extends boolean = true, AllowAdjacent extends boolean = true, Pagination extends boolean = true> = { [Key in keyof Options]: Key extends "select" ? CheckedSelection<Registry, Name, Options[Key], AllowAdjacent> : Key extends "where" ? CheckedWhere$1<QueryData<Registry[Name]>, Options[Key]> : Key extends "limit" | "offset" ? Pagination extends true ? Many extends true ? Options[Key] : never : never : Key extends keyof ObjectScope<Registry, Name, Many> ? Options[Key] : never; };
179
213
  //#endregion
@@ -221,36 +255,69 @@ type RelationalWhere<Registry extends CollectionRegistry, Name extends keyof Reg
221
255
  NOT?: RelationalWhere<Registry, Name> | readonly RelationalWhere<Registry, Name>[];
222
256
  RAW?: (fields: Fields<QueryData<Registry[Name]>>) => Expression;
223
257
  };
258
+ /** Requests one payload: `true` without variants, or a record giving every variant key. */
259
+ type PayloadRequest<Variant> = keyof Variant extends never ? true : Readonly<Variant>;
224
260
  /** Payloads to attach under `_payloads`; payloads set to false are omitted. */
225
- type PayloadOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string> = { [Key in keyof PayloadsOf<Registry[Name]>]?: boolean; };
226
- /** Collection-scoped metadata queries with Drizzle-style columns, relationships, and filters. */
261
+ type PayloadOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string> = { [Key in keyof PayloadsOf<Registry[Name]>]?: false | PayloadRequest<VariantOf<Registry[Name], Key>>; };
262
+ /** Rejects variant keys a payload does not declare, including through inferred variables. */
263
+ type CheckedPayloadRequest<Request, Variant> = Request extends boolean ? Request : { [Key in keyof Request]: Key extends keyof Variant ? string : never; };
264
+ /**
265
+ * Collection-scoped metadata queries with Drizzle-style columns, relationships, and filters.
266
+ * Nothing is selected implicitly, not even `id`: list fields in `columns`, include relationships
267
+ * with nested options, request payloads, or select adjacency.
268
+ */
227
269
  type RelationalQueryOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string, Many extends boolean = true, AllowAdjacent extends boolean = true, Pagination extends boolean = true> = {
228
- columns?: Partial<Record<keyof QueryData<Registry[Name]>, boolean>>;
270
+ /** Fields to include, each set to `true`. Omitted fields are never returned. */
271
+ columns?: Partial<Record<keyof QueryData<Registry[Name]>, true>>;
229
272
  where?: RelationalWhere<Registry, Name>;
230
- with?: { [Key in keyof RelationshipsOf<Registry[Name]>]?: boolean | RelationalQueryOptions<Registry, RelatedName<Registry, Name, Key>, IsMany<Registry, Name, Key>, AllowAdjacent>; };
273
+ /** Related entries to include; each selects its own data. `false` omits a relationship. */
274
+ with?: { [Key in keyof RelationshipsOf<Registry[Name]>]?: false | RelationalQueryOptions<Registry, RelatedName<Registry, Name, Key>, IsMany<Registry, Name, Key>, AllowAdjacent>; };
231
275
  } & (Many extends true ? {
232
276
  orderBy?: OrderBy<QueryData<Registry[Name]>>;
233
277
  } : {}) & (Many extends true ? (Pagination extends true ? {
234
278
  limit?: number;
235
279
  offset?: number;
236
280
  } : {}) : {}) & (AllowAdjacent extends true ? {
237
- adjacent?: true | RelationalQueryOptions<Registry, Name, true, false, false>;
281
+ /**
282
+ * Previous and next entries, which select their own data. `scope: "results"` finds
283
+ * neighbors within these results; other options describe an independent sibling scope.
284
+ */
285
+ adjacent?: ({
286
+ scope: "results";
287
+ } & Pick<RelationalQueryOptions<Registry, Name, true, false, false>, "columns" | "with">) | ({
288
+ scope?: "collection";
289
+ } & RelationalQueryOptions<Registry, Name, true, false, false>);
238
290
  payloads?: PayloadOptions<Registry, Name>;
239
291
  } : {});
240
292
  /** Options accepted by the root count helper, whose result ignores sorting and pagination. */
241
293
  type RelationalCountOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string> = Pick<RelationalQueryOptions<Registry, Name>, "where" | "orderBy" | "offset" | "limit">;
242
294
  type ColumnResult<Data, Options> = Options extends {
243
295
  columns: infer Columns;
244
- } ? keyof Columns extends never ? {} : true extends Columns[keyof Columns] ? { -readonly [Key in keyof Columns as Columns[Key] extends false | undefined ? never : Key]-?: Key extends keyof Data ? Data[Key] : never; } : Omit<Data, { [Key in keyof Columns]: Columns[Key] extends false ? Key : never; }[keyof Columns]> : Data;
296
+ } ? { -readonly [Key in keyof Columns as Columns[Key] extends true ? Key : never]-?: Key extends keyof Data ? Data[Key] : never; } : {};
297
+ /** Keys whose option values request something, as opposed to `false` or `undefined`. */
298
+ type Requested<Map> = keyof { [Key in keyof Map as Map[Key] extends false | undefined ? never : Key]: unknown; };
299
+ /** Whether options select fields, include relationships, request payloads, or select adjacency. */
300
+ type SelectsData<Options> = (Options extends {
301
+ columns: infer Columns;
302
+ } ? Requested<Columns> : never) | (Options extends {
303
+ with: infer Related;
304
+ } ? Requested<Related> : never) | (Options extends {
305
+ payloads: infer Payloads;
306
+ } ? Requested<Payloads> : never) | (Options extends {
307
+ adjacent: infer Neighbors;
308
+ } ? Neighbors extends false | undefined ? never : "adjacent" : never) extends never ? false : true;
309
+ /**
310
+ * Requires a row-returning scope to request data. An unselected scope must supply an impossible
311
+ * property named after the rule, so the compiler error states it.
312
+ */
313
+ type SelectionRequired<Options> = SelectsData<Options> extends true ? unknown : { [Rule in typeof NO_SELECTION_MESSAGE]: never; };
245
314
  type IncludedResult<Registry extends CollectionRegistry, Name extends keyof Registry & string, Options> = Options extends {
246
315
  with: infer Related;
247
- } ? { -readonly [Key in keyof Related as Related[Key] extends false | undefined ? never : Key]-?: Key extends keyof RelationshipsOf<Registry[Name]> ? RelationshipResult<Registry[Name], RelationshipsOf<Registry[Name]>[Key] & Relationship, RelationalQueryResult<Registry, RelatedName<Registry, Name, Key>, Related[Key] extends true ? {} : Related[Key]>, "where" extends keyof Related[Key] ? true : false> : never; } : {};
316
+ } ? { -readonly [Key in keyof Related as Related[Key] extends false | undefined ? never : Key]-?: Key extends keyof RelationshipsOf<Registry[Name]> ? RelationshipResult<Registry[Name], RelationshipsOf<Registry[Name]>[Key] & Relationship, RelationalQueryResult<Registry, RelatedName<Registry, Name, Key>, Related[Key]>, "where" extends keyof Related[Key] ? true : false> : never; } : {};
248
317
  type AdjacentResult<Registry extends CollectionRegistry, Name extends keyof Registry & string, Options> = Options extends {
249
318
  adjacent: infer Neighbors;
250
319
  } ? {
251
- _adjacent: Neighbors extends true ? Adjacent<{
252
- id: string;
253
- }> : Adjacent<RelationalQueryResult<Registry, Name, Neighbors>>;
320
+ _adjacent: Adjacent<RelationalQueryResult<Registry, Name, Neighbors>>;
254
321
  } : {};
255
322
  type Simplify<Value> = { [Key in keyof Value]: Value[Key]; };
256
323
  type RequestedPayloads<Payloads, Requested> = { -readonly [Key in keyof Requested as Requested[Key] extends false | undefined ? never : Key]-?: Key extends keyof Payloads ? Payloads[Key] : never; };
@@ -259,20 +326,28 @@ type PayloadResult<Registry extends CollectionRegistry, Name extends keyof Regis
259
326
  } ? keyof RequestedPayloads<PayloadsOf<Registry[Name]>, Requested> extends never ? {} : {
260
327
  _payloads: Simplify<RequestedPayloads<PayloadsOf<Registry[Name]>, Requested>>;
261
328
  } : {};
262
- /** Infers selected columns and relationships, preserving optional metadata in default projections. */
329
+ /** Infers exactly the selected columns, relationships, adjacency, and payloads. */
263
330
  type RelationalQueryResult<Registry extends CollectionRegistry, Name extends keyof Registry & string, Options> = Options extends unknown ? Simplify<ColumnResult<QueryData<Registry[Name]>, Options> & IncludedResult<Registry, Name, Options> & AdjacentResult<Registry, Name, Options> & PayloadResult<Registry, Name, Options>> : never;
264
331
  type CheckedConditions<Value, Filters extends readonly unknown[]> = { [Index in keyof Filters]: CheckedCondition<Value, Filters[Index]>; };
265
332
  type CheckedCondition<Value, Filter> = Filter extends Scalar ? Filter : { [Key in keyof Filter]: Key extends "AND" | "OR" ? Filter[Key] extends readonly unknown[] ? CheckedConditions<Value, Filter[Key]> : never : Key extends "NOT" ? CheckedCondition<Value, Filter[Key]> : Key extends keyof FieldFilter<Value> ? Filter[Key] : never; };
266
333
  type CheckedWhereList<Registry extends CollectionRegistry, Name extends keyof Registry & string, Filters extends readonly unknown[]> = { [Index in keyof Filters]: CheckedWhere<Registry, Name, Filters[Index]>; };
267
334
  type CheckedWhere<Registry extends CollectionRegistry, Name extends keyof Registry & string, Filter> = { [Key in keyof Filter]: Key extends "AND" | "OR" | "NOT" ? Filter[Key] extends readonly unknown[] ? CheckedWhereList<Registry, Name, Filter[Key]> : CheckedWhere<Registry, Name, Filter[Key]> : Key extends "RAW" ? Filter[Key] : Key extends keyof RelationshipsOf<Registry[Name]> ? Filter[Key] extends boolean ? Filter[Key] : CheckedWhere<Registry, RelatedName<Registry, Name, Key>, Filter[Key]> : Key extends keyof QueryData<Registry[Name]> ? CheckedCondition<QueryData<Registry[Name]>[Key], Filter[Key]> : never; };
268
335
  /** Rejects unknown options recursively, including options supplied through inferred variables. */
269
- type CheckedRelationalOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string, Options, Many extends boolean = true, AllowAdjacent extends boolean = true, Pagination extends boolean = true> = { [Key in keyof Options]: Key extends "columns" ? { [Column in keyof Options[Key]]: Column extends keyof QueryData<Registry[Name]> ? Options[Key][Column] : never; } : Key extends "where" ? CheckedWhere<Registry, Name, Options[Key]> : Key extends "with" ? { [Related in keyof Options[Key]]: Related extends keyof RelationshipsOf<Registry[Name]> ? Options[Key][Related] extends boolean ? Options[Key][Related] : CheckedRelationalOptions<Registry, RelatedName<Registry, Name, Related>, Options[Key][Related], IsMany<Registry, Name, Related>, AllowAdjacent> : never; } : Key extends "adjacent" ? AllowAdjacent extends true ? Options[Key] extends true ? true : CheckedRelationalOptions<Registry, Name, Options[Key], true, false, false> : never : Key extends "payloads" ? AllowAdjacent extends true ? { [Payload in keyof Options[Key]]: Payload extends keyof PayloadsOf<Registry[Name]> ? Options[Key][Payload] : never; } : never : Key extends "orderBy" ? Key extends keyof RelationalQueryOptions<Registry, Name, Many, AllowAdjacent, Pagination> ? { [Field in keyof Options[Key]]: Field extends keyof OrderBy<QueryData<Registry[Name]>> ? Options[Key][Field] : never; } : never : Key extends keyof RelationalQueryOptions<Registry, Name, Many, AllowAdjacent, Pagination> ? Options[Key] : never; };
336
+ type CheckedRelationalOptions<Registry extends CollectionRegistry, Name extends keyof Registry & string, Options, Many extends boolean = true, AllowAdjacent extends boolean = true, Pagination extends boolean = true> = { [Key in keyof Options]: Key extends "columns" ? { [Column in keyof Options[Key]]: Column extends keyof QueryData<Registry[Name]> ? Options[Key][Column] : never; } : Key extends "where" ? CheckedWhere<Registry, Name, Options[Key]> : Key extends "with" ? { [Related in keyof Options[Key]]: Related extends keyof RelationshipsOf<Registry[Name]> ? Options[Key][Related] extends false | undefined ? Options[Key][Related] : CheckedRelationalOptions<Registry, RelatedName<Registry, Name, Related>, Options[Key][Related], IsMany<Registry, Name, Related>, AllowAdjacent> & SelectionRequired<Options[Key][Related]> : never; } : Key extends "adjacent" ? AllowAdjacent extends true ? CheckedRelationalOptions<Registry, Name, Omit<Options[Key], "scope">, true, false, false> & SelectionRequired<Options[Key]> & (Options[Key] extends {
337
+ scope: "results";
338
+ } ? {
339
+ scope: "results";
340
+ where?: never;
341
+ orderBy?: never;
342
+ } : {
343
+ scope?: "collection";
344
+ }) : never : Key extends "payloads" ? AllowAdjacent extends true ? { [Payload in keyof Options[Key]]: Payload extends keyof PayloadsOf<Registry[Name]> ? CheckedPayloadRequest<Options[Key][Payload], VariantOf<Registry[Name], Payload>> : never; } : never : Key extends "orderBy" ? Key extends keyof RelationalQueryOptions<Registry, Name, Many, AllowAdjacent, Pagination> ? { [Field in keyof Options[Key]]: Field extends keyof OrderBy<QueryData<Registry[Name]>> ? Options[Key][Field] : never; } : never : Key extends keyof RelationalQueryOptions<Registry, Name, Many, AllowAdjacent, Pagination> ? Options[Key] : never; };
270
345
  /** Typed per-collection query entry points that never expose source configuration at runtime. */
271
346
  type RelationalQueries<Registry extends CollectionRegistry> = string extends keyof Registry ? {} : { readonly [Name in keyof Registry & string]: {
272
- /** Returns matching metadata rows and requested relationships. */
273
- findMany<const Options extends RelationalQueryOptions<Registry, Name> = {}>(options?: Options & CheckedRelationalOptions<Registry, Name, NoInfer<Options>>): Promise<RelationalQueryResult<Registry, Name, Options>[]>;
274
- /** Returns the first matching entry, or undefined when none matches. */
275
- findFirst<const Options extends RelationalQueryOptions<Registry, Name> = {}>(options?: Options & CheckedRelationalOptions<Registry, Name, NoInfer<Options>>): Promise<RelationalQueryResult<Registry, Name, Options> | undefined>;
347
+ /** Returns matching rows with exactly the selected data. Options must select something. */
348
+ findMany<const Options extends RelationalQueryOptions<Registry, Name>>(options: Options & CheckedRelationalOptions<Registry, Name, NoInfer<Options>> & SelectionRequired<NoInfer<Options>>): Promise<RelationalQueryResult<Registry, Name, Options>[]>;
349
+ /** Returns the first matching row, or undefined when none matches. */
350
+ findFirst<const Options extends RelationalQueryOptions<Registry, Name>>(options: Options & CheckedRelationalOptions<Registry, Name, NoInfer<Options>> & SelectionRequired<NoInfer<Options>>): Promise<RelationalQueryResult<Registry, Name, Options> | undefined>;
276
351
  }; };
277
352
  //#endregion
278
- export { QueryPlan as _, RelationalWhere as a, Fields as c, Scalar as d, ScalarField as f, Expression as g, Where as h, RelationalQueryResult as i, Ordered as l, SelectionResult as m, RelationalQueries as n, Adjacent as o, Selection as p, RelationalQueryOptions as r, Field$1 as s, RelationalCountOptions as t, Query as u, QueryRegistry as v };
353
+ export { Where as _, RelationalWhere as a, QueryRegistry as b, Fields as c, QueryFields as d, RelationField as f, SelectionResult as g, Selection as h, RelationalQueryResult as i, Ordered as l, ScalarField as m, RelationalQueries as n, Adjacent as o, Scalar as p, RelationalQueryOptions as r, Field$1 as s, RelationalCountOptions as t, Query as u, Expression as v, QueryPlan as y };
@@ -1,3 +1,4 @@
1
+ import { a as ContentDiagnostic, o as ContentError, s as ContentErrorCode, t as Content } from "./content-CwTKqRs9.mjs";
1
2
  import { n as ContentRenderResult, t as ContentHeading } from "./types-Dh-Sydyw.mjs";
2
- import { a as ContentError, i as ContentDiagnostic, o as ContentErrorCode, t as Content } from "./content-G69dPPuo.mjs";
3
- export { type Content, type ContentDiagnostic, ContentError, type ContentErrorCode, type ContentHeading, type ContentRenderResult };
3
+ import { n as QueryStyle, r as QueryStyleDisabled } from "./query-style-eXENQJ0O.mjs";
4
+ export { type Content, type ContentDiagnostic, ContentError, type ContentErrorCode, type ContentHeading, type ContentRenderResult, type QueryStyle, type QueryStyleDisabled };
package/dist/runtime.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  //#endregion
2
- export { t as ContentError } from "./errors-C2iuBM0G.mjs";
2
+ export { t as ContentError } from "./errors-Bfd0R4_P.mjs";
3
3
  import { t as assertServerOnly } from "./server-only-CIJUlyL-.mjs";
4
4
  //#region src/runtime.ts
5
5
  assertServerOnly();
@@ -0,0 +1,181 @@
1
+ import { c as Loader, n as GlobOptions, t as FileOptions } from "./descriptor-bcPa6XLk.mjs";
2
+ import { n as ContentRenderResult, r as RenderedContent } from "./types-Dh-Sydyw.mjs";
3
+ import { StandardSchemaV1 } from "@standard-schema/spec";
4
+ //#region src/collection/types.d.ts
5
+ declare const builtinPayloadsType: unique symbol;
6
+ declare const customPayloadsType: unique symbol;
7
+ type Schema = StandardSchemaV1;
8
+ type SchemaOutput<Value> = Value extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<Value> : Record<string, unknown>;
9
+ /** One file or record that a `files` helper read, shaped like a loader entry. */
10
+ type FileEntry<Data = Record<string, unknown>> = {
11
+ id: string;
12
+ data: Data;
13
+ /** The Markdown body, when the file is Markdown and `retainBody` is not `false`. */
14
+ body?: string;
15
+ /** The file's path relative to the project root. */
16
+ filePath: string;
17
+ };
18
+ /**
19
+ * Tracked file access for computed and payload resolvers. Paths are relative to the entry's
20
+ * folder and must stay inside it or one of the collection's `sharedFiles` directories. Every read
21
+ * is recorded, so editing, adding, or removing a file re-resolves only what read it.
22
+ */
23
+ type EntryFiles = {
24
+ /** Lists and parses files like `glob()`, with `base` relative to the entry's folder. */
25
+ glob<FileSchema extends Schema | undefined = undefined>(options: Omit<GlobOptions, "base" | "deferRender"> & {
26
+ base?: string;
27
+ schema?: FileSchema;
28
+ }): Promise<FileEntry<SchemaOutput<FileSchema>>[]>;
29
+ /** Parses one data file's records like `file()`, returning one entry per record. */
30
+ file<FileSchema extends Schema | undefined = undefined>(filePath: string, options?: FileOptions & {
31
+ schema?: FileSchema;
32
+ }): Promise<FileEntry<SchemaOutput<FileSchema>>[]>;
33
+ /** Reads a file as UTF-8 text. */
34
+ text(filePath: string): Promise<string>;
35
+ /** Reads a file's bytes. */
36
+ bytes(filePath: string): Promise<Uint8Array>;
37
+ /** Renders Markdown with the built-in renderer, like a loader's `renderMarkdown()`. */
38
+ renderMarkdown(body: string): Promise<RenderedContent>;
39
+ };
40
+ type ComputedContext<Data, Source = unknown> = {
41
+ /** The collection's key in the configured registry. */
42
+ collection: string;
43
+ id: string;
44
+ /** Loader-provided source metadata, detached from stored entries for this resolver. */
45
+ source?: Source extends object ? Readonly<Source> : Source;
46
+ data: Readonly<Data>;
47
+ readBody(this: void): Promise<string | undefined>;
48
+ /** Tracked reads of files beside the entry; edits re-prepare the entry. */
49
+ files: EntryFiles;
50
+ signal: AbortSignal;
51
+ };
52
+ type ComputedDefinition<Data = Record<string, unknown>, Source = unknown> = {
53
+ schema: Schema;
54
+ resolve(context: ComputedContext<Data, Source>): unknown;
55
+ };
56
+ /** Context for a payload's `combinations()` override, with the entry's prepared data. */
57
+ type VariantContext<Data, Source = unknown> = {
58
+ /** The collection's key in the configured registry. */
59
+ collection: string;
60
+ id: string;
61
+ /** Loader-provided source metadata, detached from stored entries for this resolver. */
62
+ source?: Source extends object ? Readonly<Source> : Source;
63
+ /** Validated metadata plus computed fields. */
64
+ data: Readonly<Data>;
65
+ signal: AbortSignal;
66
+ };
67
+ /** Context for a custom payload resolver, called once per entry and variant combination. */
68
+ type PayloadContext<Data, Source = unknown, Variant = {}> = VariantContext<Data, Source> & {
69
+ /** The variant combination being resolved; empty for payloads without variants. */
70
+ variant: Readonly<Variant>;
71
+ readBody(this: void): Promise<string | undefined>;
72
+ /** Tracked reads of files beside the entry; edits re-resolve only this variant. */
73
+ files: EntryFiles;
74
+ };
75
+ /** Data fields, including computed fields, whose values are string arrays. */
76
+ type VariantField<Data> = { [Field in keyof Data]-?: NonNullable<Data[Field]> extends readonly string[] ? Field : never; }[keyof Data] & string;
77
+ /**
78
+ * Enumerates one variant key's values: the name of a string-array data field, read per entry, or
79
+ * a fixed list. Derive values in a computed field when they need logic.
80
+ */
81
+ type VariantValues<Data> = VariantField<Data> | readonly string[];
82
+ /**
83
+ * A custom payload: schema-validated data resolved during preparation and loaded only when a
84
+ * query requests it. Names cannot start with `_`, which built-in payloads such as `_body` use.
85
+ */
86
+ type PayloadDefinition<Data = Record<string, unknown>, Source = unknown, Variant = {}> = {
87
+ schema: Schema;
88
+ /** Variant keys and their values for an entry. Omit for a single payload value. */
89
+ variants?: Record<string, VariantValues<Data>>;
90
+ /**
91
+ * Overrides the default cross product of enumerated values. Each combination must name every
92
+ * variant key with one of that key's enumerated values.
93
+ */
94
+ combinations?(context: VariantContext<Data, Source> & {
95
+ variants: Readonly<Record<string, readonly string[]>>;
96
+ }): Iterable<Variant> | PromiseLike<Iterable<Variant>>;
97
+ resolve(context: PayloadContext<Data, Source, Variant>): unknown;
98
+ /**
99
+ * Set to `false` to resolve again in every revision, for resolvers that read data `files` cannot
100
+ * track, such as a remote API. Defaults to `true`.
101
+ */
102
+ cache?: boolean;
103
+ };
104
+ /**
105
+ * Any payload declaration once its inferred types are erased, as registries and preparation see
106
+ * it. Typed declarations from `defineCollection` are always assignable.
107
+ */
108
+ type PayloadDeclaration = {
109
+ schema: Schema;
110
+ variants?: Record<string, string | readonly string[]>;
111
+ combinations?(context: never): unknown;
112
+ resolve(context: never): unknown;
113
+ cache?: boolean;
114
+ };
115
+ type Relationship = {
116
+ collection: string;
117
+ type: "one" | "many";
118
+ from: string;
119
+ to: string;
120
+ referenceSide: "from" | "to" | "none";
121
+ };
122
+ type CollectionDefinition<SourceSchema extends Schema | undefined = Schema | undefined, Computed extends Record<string, ComputedDefinition<never, never>> = Record<string, ComputedDefinition<never, never>>, Relationships extends Record<string, Relationship> = Record<string, Relationship>> = {
123
+ loader: Loader;
124
+ schema?: SourceSchema;
125
+ computed?: Computed;
126
+ relationships?: Relationships;
127
+ payloads?: Record<string, PayloadDeclaration>;
128
+ /** Directories, relative to the project root, that every entry's `files` helpers may read. */
129
+ sharedFiles?: readonly string[];
130
+ };
131
+ type CollectionRegistry = Record<string, CollectionDefinition>;
132
+ type EntryData<Definition> = Definition extends {
133
+ schema: infer SourceSchema;
134
+ } ? SchemaOutput<SourceSchema> : Record<string, unknown>;
135
+ type ComputedData<Definition> = Definition extends {
136
+ computed: infer Computed;
137
+ } ? { [Name in keyof Computed]: Computed[Name] extends {
138
+ schema: infer ResultSchema;
139
+ } ? SchemaOutput<ResultSchema> : never; } : {};
140
+ type QueryData<Definition> = {
141
+ id: string;
142
+ } & EntryData<Definition> & ComputedData<Definition>;
143
+ type RelationshipsOf<Definition> = Definition extends {
144
+ relationships: infer Relationships;
145
+ } ? Relationships : {};
146
+ /**
147
+ * Payloads that Markdown sources, `glob()`, and custom loaders provide for every entry.
148
+ * Built-in names start with an underscore, so they never collide with custom payloads.
149
+ */
150
+ type BuiltinPayloads = {
151
+ /** The retained raw body, or undefined when the entry has none or retention is disabled. */
152
+ _body: string | undefined;
153
+ /** HTML and headings; entries without a rendering path reject with `not-renderable`. */
154
+ _rendered: ContentRenderResult;
155
+ };
156
+ /** Type-only marker recording which built-in payloads a defined collection carries. */
157
+ type BuiltinPayloadMarker<Available extends keyof BuiltinPayloads> = {
158
+ readonly [builtinPayloadsType]?: Available;
159
+ };
160
+ /** One custom payload's validated value type and variant record, as recorded by a definition. */
161
+ type CustomPayload<Value = unknown, Variant = {}> = {
162
+ value: Value;
163
+ variant: Variant;
164
+ };
165
+ /** Type-only marker recording a defined collection's custom payload values and variant keys. */
166
+ type CustomPayloadMarker<Payloads extends Record<string, CustomPayload>> = {
167
+ readonly [customPayloadsType]?: Payloads;
168
+ };
169
+ type CustomPayloadsOf<Definition> = Definition extends {
170
+ readonly [customPayloadsType]?: infer Payloads;
171
+ } ? Payloads extends Record<string, CustomPayload> ? Payloads : {} : {};
172
+ /** Payload names and value types that queries can request for a collection definition. */
173
+ type PayloadsOf<Definition> = (Definition extends {
174
+ readonly [builtinPayloadsType]?: infer Available;
175
+ } ? Pick<BuiltinPayloads, Available & keyof BuiltinPayloads> : BuiltinPayloads) & { [Name in keyof CustomPayloadsOf<Definition>]: CustomPayloadsOf<Definition>[Name] extends CustomPayload<infer Value> ? Value : never; };
176
+ /** The value type of one payload that queries return under `_payloads`. */
177
+ type PayloadData<Definition, Name extends keyof PayloadsOf<Definition>> = PayloadsOf<Definition>[Name];
178
+ /** The variant keys a payload request must supply; empty for built-in and single-value payloads. */
179
+ type VariantOf<Definition, Name> = Name extends keyof CustomPayloadsOf<Definition> ? CustomPayloadsOf<Definition>[Name] extends CustomPayload<unknown, infer Variant> ? Variant : {} : {};
180
+ //#endregion
181
+ export { VariantValues as C, VariantOf as S, RelationshipsOf as _, ComputedContext as a, VariantContext as b, EntryFiles as c, PayloadData as d, PayloadDeclaration as f, Relationship as g, QueryData as h, CollectionRegistry as i, FileEntry as l, PayloadsOf as m, BuiltinPayloads as n, CustomPayload as o, PayloadDefinition as p, CollectionDefinition as r, CustomPayloadMarker as s, BuiltinPayloadMarker as t, PayloadContext as u, Schema as v, VariantField as x, SchemaOutput as y };
package/dist/vite.d.mts CHANGED
@@ -1,6 +1,18 @@
1
- import { t as BuildContentOptions } from "./build-DfKd2bpf.mjs";
1
+ import { a as ContentSourceEvent, o as ContentSourceSnapshot, t as BuildContentOptions } from "./build-DL1GzmRy.mjs";
2
2
  import { Plugin } from "vite";
3
3
  //#region src/integrations/vite/plugin.d.ts
4
+ /** Public, format-neutral hooks for integrations sharing this plugin's preparation session. */
5
+ type ContentQueryPluginApi = {
6
+ /** Prepares or awaits the shared session and returns its current source identities. */
7
+ prepare(): Promise<ContentSourceSnapshot>;
8
+ /** Observes subsequent source publications and errors without owning another watcher. */
9
+ subscribe(listener: (event: ContentSourceEvent) => void): () => void;
10
+ };
11
+ /** A normal Vite plugin with a typed source-integration API. */
12
+ interface ContentQueryPlugin extends Plugin<ContentQueryPluginApi> {
13
+ api: ContentQueryPluginApi;
14
+ }
4
15
  /** Integrates in-memory content with Vite; opt into generated storage for standalone artifacts. */
5
- export declare function contentQuery(options?: Omit<BuildContentOptions, "watch">): Plugin;
6
- //#endregion
16
+ export declare function contentQuery(options?: Omit<BuildContentOptions, "watch">): ContentQueryPlugin;
17
+ //#endregion
18
+ export type { ContentQueryPlugin, ContentQueryPluginApi };
package/dist/vite.mjs CHANGED
@@ -1,5 +1,5 @@
1
- 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-Dxz7P1ur.mjs";
2
- import { n as serializeContentError } from "./diagnostics-Cu94mZhl.mjs";
1
+ 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-CcqIpkes.mjs";
2
+ import { n as serializeContentError } from "./diagnostics-DmUZtrJ6.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import path from "node:path";
5
5
  import { randomUUID } from "node:crypto";
@@ -122,6 +122,7 @@ function contentQuery(options = {}) {
122
122
  let encoding;
123
123
  const bridgeKey = randomUUID();
124
124
  const refreshClients = /* @__PURE__ */ new WeakSet();
125
+ const sourceListeners = /* @__PURE__ */ new Set();
125
126
  /** Publishes type-only facade binding without importing configuration in executable code. */
126
127
  async function writeTypes(configPath) {
127
128
  const directory = path.join(config.root, ".content-query");
@@ -216,6 +217,14 @@ function contentQuery(options = {}) {
216
217
  if (config.command === "serve") changed(state).catch(deliveryFailed);
217
218
  });
218
219
  session = prepared;
220
+ prepared.subscribe((event) => {
221
+ const listeners = [...sourceListeners];
222
+ for (const listener of listeners) try {
223
+ listener(event);
224
+ } catch (cause) {
225
+ config.logger.error(`Content source subscriber failed: ${cause instanceof Error ? cause.message : String(cause)}`);
226
+ }
227
+ });
219
228
  try {
220
229
  if (config.command === "serve") {
221
230
  const global = globalThis;
@@ -235,6 +244,19 @@ function contentQuery(options = {}) {
235
244
  }
236
245
  return {
237
246
  name: "content-query",
247
+ api: {
248
+ async prepare() {
249
+ const prepared = await ensureSession();
250
+ await sessionInternals(prepared).idle();
251
+ return prepared.sources();
252
+ },
253
+ subscribe(listener) {
254
+ sourceListeners.add(listener);
255
+ return () => {
256
+ sourceListeners.delete(listener);
257
+ };
258
+ }
259
+ },
238
260
  enforce: "pre",
239
261
  configResolved(resolved) {
240
262
  config = resolved;
@@ -288,6 +310,7 @@ function contentQuery(options = {}) {
288
310
  server = void 0;
289
311
  await starting?.catch(() => void 0);
290
312
  await session?.dispose();
313
+ sourceListeners.clear();
291
314
  globalThis[bridgeSymbol]?.delete(bridgeKey);
292
315
  }
293
316
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "content-query",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Typed, framework-independent content collections, queries, and rendering.",
5
5
  "homepage": "https://github.com/yangshun/content-query#readme",
6
6
  "bugs": {
@@ -71,7 +71,7 @@
71
71
  "vite-plus": "1.3.0"
72
72
  },
73
73
  "peerDependencies": {
74
- "next": "^16.0.0",
74
+ "next": "^15.0.0 || ^16.0.0",
75
75
  "vite": "^8.0.0"
76
76
  },
77
77
  "peerDependenciesMeta": {
@@ -1,25 +0,0 @@
1
- import { i as CollectionRegistry } from "./types-C-kdMblM.mjs";
2
- import { s as InvalidRelationships, t as Content } from "./content-G69dPPuo.mjs";
3
- //#region src/preparation/session.d.ts
4
- type ContentSession<Registry extends CollectionRegistry = {}> = {
5
- content: Content<Registry>;
6
- dispose(): Promise<void>;
7
- };
8
- //#endregion
9
- //#region src/preparation/build.d.ts
10
- /** Options shared by standalone content builds and host integrations. */
11
- type BuildContentOptions = {
12
- /** Exact config path; omission discovers one content-query.config.{ts,mts,cts,js,mjs,cjs} file. */
13
- config?: string;
14
- backend?: "in-memory" | "generated";
15
- /** Generated backend output directory, relative to the application root; defaults to ./.content-query. */
16
- outDir?: string;
17
- watch?: boolean;
18
- };
19
- /**
20
- * Builds content independently of a bundler; bind the registry through an erased type import.
21
- * Generated watch sessions prune previous-run artifacts after their first successful publication.
22
- */
23
- declare function buildContent<Registry extends CollectionRegistry = {}>(...arguments_: InvalidRelationships<Registry> extends never ? [options?: BuildContentOptions] : [invalidRegistry: never]): Promise<ContentSession<Registry>>;
24
- //#endregion
25
- export { buildContent as n, ContentSession as r, BuildContentOptions as t };