@contentrain/query 7.0.15 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +92 -6
  2. package/dist/astro/index.cjs +142 -0
  3. package/dist/astro/index.d.cts +81 -0
  4. package/dist/astro/index.d.cts.map +1 -0
  5. package/dist/astro/index.d.mts +81 -0
  6. package/dist/astro/index.d.mts.map +1 -0
  7. package/dist/astro/index.mjs +143 -0
  8. package/dist/astro/index.mjs.map +1 -0
  9. package/dist/cdn/index.cjs +2 -1
  10. package/dist/cdn/index.d.cts +2 -2
  11. package/dist/cdn/index.d.mts +2 -2
  12. package/dist/cdn/index.mjs +2 -2
  13. package/dist/{cdn-C8dqHhdG.mjs → cdn-C5yiVdfQ.mjs} +102 -27
  14. package/dist/cdn-C5yiVdfQ.mjs.map +1 -0
  15. package/dist/{cdn-DrQCLLj6.cjs → cdn-DJw9oksO.cjs} +106 -25
  16. package/dist/cli.cjs +1 -1
  17. package/dist/cli.mjs +1 -1
  18. package/dist/frontmatter-CVjPyhOq.mjs +248 -0
  19. package/dist/frontmatter-CVjPyhOq.mjs.map +1 -0
  20. package/dist/frontmatter-DSFLOTwS.cjs +287 -0
  21. package/dist/{generate-mpKW9Y8v.mjs → generate-B7jooE0f.mjs} +4 -244
  22. package/dist/generate-B7jooE0f.mjs.map +1 -0
  23. package/dist/{generate-DN3mAbvC.cjs → generate-D3C6itur.cjs} +14 -254
  24. package/dist/generator/generate.cjs +1 -1
  25. package/dist/generator/generate.mjs +1 -1
  26. package/dist/{index-TgljULTn.d.mts → index-BFurv7WX.d.cts} +134 -28
  27. package/dist/index-BFurv7WX.d.cts.map +1 -0
  28. package/dist/{index-mxo0dHvb.d.cts → index-VXFz-DDN.d.mts} +134 -28
  29. package/dist/index-VXFz-DDN.d.mts.map +1 -0
  30. package/dist/index.cjs +2 -1
  31. package/dist/index.d.cts +2 -2
  32. package/dist/index.d.mts +2 -2
  33. package/dist/index.mjs +2 -2
  34. package/dist/index.mjs.map +1 -1
  35. package/package.json +39 -15
  36. package/dist/cdn-C8dqHhdG.mjs.map +0 -1
  37. package/dist/generate-mpKW9Y8v.mjs.map +0 -1
  38. package/dist/index-TgljULTn.d.mts.map +0 -1
  39. package/dist/index-mxo0dHvb.d.cts.map +0 -1
@@ -1,3 +1,5 @@
1
+ import { FieldDef } from "@contentrain/types";
2
+
1
3
  //#region src/cdn/data-source.d.ts
2
4
  interface CollectionDataSource<T> {
3
5
  getAll(locale: string): Promise<T[]>;
@@ -194,49 +196,152 @@ declare class MediaAccessor {
194
196
  }
195
197
  //#endregion
196
198
  //#region src/cdn/forms-client.d.ts
197
- interface FormFieldConfig {
198
- id: string;
199
- type: string;
200
- required?: boolean;
201
- label?: string;
202
- placeholder?: string;
203
- options?: Array<{
204
- value: string;
205
- label: string;
206
- }>;
207
- pattern?: string;
208
- min?: number;
209
- max?: number;
210
- }
199
+ /** One exposed field, as the model defines it. */
200
+ type FormFieldConfig = FieldDef;
211
201
  interface FormConfig {
212
202
  modelId: string;
213
- fields: FormFieldConfig[];
214
- captchaType?: 'turnstile' | null;
203
+ /** The project's default locale — what a submission is validated against and written to. */
204
+ locale: string;
205
+ /** Exposed fields only, keyed by field id. */
206
+ fields: Record<string, FormFieldConfig>;
207
+ captcha: 'turnstile' | null;
208
+ /** Turnstile widget key, when `captcha` is set and the operator configured one. */
209
+ captchaSiteKey: string | null;
215
210
  successMessage?: string;
216
- honeypotField?: string;
211
+ /** Name of the hidden honeypot input to render (and leave empty), or null. */
212
+ honeypotField: string | null;
213
+ }
214
+ interface FormFieldError {
215
+ field: string;
216
+ message: string;
217
217
  }
218
218
  interface FormSubmitResult {
219
219
  success: boolean;
220
+ /** The model's `successMessage` on success. */
220
221
  message?: string;
221
- errors?: Array<{
222
- field: string;
223
- message: string;
224
- }>;
222
+ /** Validation errors against the exposed fields, or `captcha`. */
223
+ errors?: FormFieldError[];
224
+ }
225
+ interface FormSubmitOptions {
226
+ /** Turnstile token, when the config's `captcha` is set. */
227
+ captchaToken?: string;
228
+ /** Value of the honeypot input. A human leaves it empty; a filled one is silently dropped server-side. */
229
+ honeypot?: string;
225
230
  }
226
231
  interface FormsClientConfig {
232
+ /** Public API root — `https://studio.contentrain.io/api/forms/v1`. */
227
233
  baseUrl: string;
228
234
  projectId: string;
229
- apiKey?: string;
230
235
  }
231
236
  declare class FormsClient {
232
237
  private _baseUrl;
233
238
  private _projectId;
234
- private _apiKey;
235
239
  constructor(config: FormsClientConfig);
236
240
  config(modelId: string): Promise<FormConfig>;
237
- submit(modelId: string, data: Record<string, unknown>, options?: {
238
- captchaToken?: string;
239
- }): Promise<FormSubmitResult>;
241
+ /**
242
+ * Resolves with the server's verdict for 2xx responses — including
243
+ * `{ success: false, errors }` for validation failures, which are not
244
+ * exceptions. Rejects with `ContentrainError` on 403/404/429/5xx.
245
+ */
246
+ submit(modelId: string, data: Record<string, unknown>, options?: FormSubmitOptions): Promise<FormSubmitResult>;
247
+ }
248
+ //#endregion
249
+ //#region src/cdn/comments-client.d.ts
250
+ type CommentType = 'comment' | 'pingback' | 'trackback';
251
+ interface CommentAuthor {
252
+ name: string;
253
+ url: string | null;
254
+ /** Written from Studio by a workspace member. */
255
+ isModerator: boolean;
256
+ }
257
+ interface PublicComment {
258
+ id: string;
259
+ parentId: string | null;
260
+ depth: number;
261
+ author: CommentAuthor;
262
+ /** Plain text. */
263
+ body: string;
264
+ type: CommentType;
265
+ /** ISO 8601. */
266
+ createdAt: string;
267
+ replies: PublicComment[];
268
+ }
269
+ interface CommentThreadConfig {
270
+ /** Thread closed → render the comments, hide the form. */
271
+ closed: boolean;
272
+ requireApproval: boolean;
273
+ requireEmail: boolean;
274
+ /** Reply nesting cap for new submissions (0 = flat). */
275
+ maxDepth: number;
276
+ maxBodyLength: number;
277
+ captcha: 'turnstile' | null;
278
+ captchaSiteKey: string | null;
279
+ honeypotField: string | null;
280
+ }
281
+ interface CommentThread {
282
+ entry: {
283
+ modelId: string;
284
+ entryId: string;
285
+ locale: string;
286
+ };
287
+ config: CommentThreadConfig;
288
+ /** Root comments of this page, replies nested. */
289
+ comments: PublicComment[];
290
+ /** Root comments in total. */
291
+ total: number;
292
+ page: number;
293
+ limit: number;
294
+ }
295
+ interface CommentThreadQuery {
296
+ locale?: string;
297
+ page?: number;
298
+ limit?: number;
299
+ sort?: 'oldest' | 'newest';
300
+ }
301
+ interface CommentSubmission {
302
+ author: {
303
+ name: string;
304
+ email?: string;
305
+ url?: string;
306
+ };
307
+ body: string;
308
+ /** Reply target — an approved comment's id. */
309
+ parentId?: string;
310
+ captchaToken?: string;
311
+ /** Value of the honeypot input (`config.honeypotField`); a human leaves it empty. */
312
+ honeypot?: string;
313
+ }
314
+ interface CommentFieldError {
315
+ /** `author.name` · `author.email` · `author.url` · `body` · `parentId` · `captcha` */
316
+ field: string;
317
+ message: string;
318
+ }
319
+ interface CommentSubmitResult {
320
+ success: boolean;
321
+ /** `approved` renders now; `pending` is only echoed back to its author. */
322
+ status?: 'pending' | 'approved';
323
+ /** The stored comment, in the public shape. Absent when the honeypot swallowed the post. */
324
+ comment?: PublicComment;
325
+ errors?: CommentFieldError[];
326
+ }
327
+ interface CommentsClientConfig {
328
+ /** Public API root — `https://studio.contentrain.io/api/comments/v1`. */
329
+ baseUrl: string;
330
+ projectId: string;
331
+ }
332
+ declare class CommentsClient {
333
+ private _baseUrl;
334
+ private _projectId;
335
+ constructor(config: CommentsClientConfig);
336
+ thread(modelId: string, entryId: string, query?: CommentThreadQuery): Promise<CommentThread>;
337
+ /**
338
+ * Resolves with the server's verdict for 2xx responses — including
339
+ * `{ success: false, errors }`. Rejects with `ContentrainError` on
340
+ * 403 (thread closed / plan), 404, 429 and 5xx.
341
+ */
342
+ submit(modelId: string, entryId: string, submission: CommentSubmission, options?: {
343
+ locale?: string;
344
+ }): Promise<CommentSubmitResult>;
240
345
  }
241
346
  //#endregion
242
347
  //#region src/cdn/conversation-client.d.ts
@@ -320,6 +425,7 @@ declare function createContentrain(config: ContentrainCDNConfig): {
320
425
  document: <T extends object = Record<string, unknown>>(modelId: string) => CdnDocumentQuery<T>;
321
426
  media: () => MediaAccessor;
322
427
  form: () => FormsClient;
428
+ comments: () => CommentsClient;
323
429
  conversation: () => ConversationClient;
324
430
  manifest: () => Promise<unknown>;
325
431
  models: () => Promise<unknown[]>;
@@ -327,5 +433,5 @@ declare function createContentrain(config: ContentrainCDNConfig): {
327
433
  preload: (locale?: string) => Promise<boolean>;
328
434
  };
329
435
  //#endregion
330
- export { applyWhere as A, CdnDocumentQuery as C, EntryMeta as D, CdnCollectionQuery as E, DocumentDataSource as F, DocumentIndexEntry as I, SingletonDataSource as L, TransportConfig as M, CollectionDataSource as N, WhereClause as O, DictionaryDataSource as P, MediaManifest as S, CdnSingletonAccessor as T, FormsClient as _, ConversationClient as a, MediaAsset as b, ConversationHistory as c, ConversationSendOptions as d, ConversationToolResult as f, FormSubmitResult as g, FormFieldConfig as h, ContentrainError as i, HttpTransport as j, WhereOp as k, ConversationMessage as l, FormConfig as m, ContentrainCDNConfig as n, ConversationClientConfig as o, ConversationUsage as p, createContentrain as r, ConversationContext as s, ContentrainCDNClient as t, ConversationResponse as u, FormsClientConfig as v, CdnDictionaryAccessor as w, MediaAssetMeta as x, MediaAccessor as y };
331
- //# sourceMappingURL=index-mxo0dHvb.d.cts.map
436
+ export { FormsClient as A, EntryMeta as B, CommentsClientConfig as C, FormFieldError as D, FormFieldConfig as E, MediaManifest as F, TransportConfig as G, WhereOp as H, CdnDocumentQuery as I, DocumentDataSource as J, CollectionDataSource as K, CdnDictionaryAccessor as L, MediaAccessor as M, MediaAsset as N, FormSubmitOptions as O, MediaAssetMeta as P, CdnSingletonAccessor as R, CommentsClient as S, FormConfig as T, applyWhere as U, WhereClause as V, HttpTransport as W, SingletonDataSource as X, DocumentIndexEntry as Y, CommentSubmitResult as _, ConversationClient as a, CommentThreadQuery as b, ConversationHistory as c, ConversationSendOptions as d, ConversationToolResult as f, CommentSubmission as g, CommentFieldError as h, ContentrainError as i, FormsClientConfig as j, FormSubmitResult as k, ConversationMessage as l, CommentAuthor as m, ContentrainCDNConfig as n, ConversationClientConfig as o, ConversationUsage as p, DictionaryDataSource as q, createContentrain as r, ConversationContext as s, ContentrainCDNClient as t, ConversationResponse as u, CommentThread as v, PublicComment as w, CommentType as x, CommentThreadConfig as y, CdnCollectionQuery as z };
437
+ //# sourceMappingURL=index-VXFz-DDN.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-VXFz-DDN.d.mts","names":[],"sources":["../src/cdn/data-source.ts","../src/cdn/http-transport.ts","../src/shared/where.ts","../src/cdn/collection-query.ts","../src/cdn/singleton-accessor.ts","../src/cdn/dictionary-accessor.ts","../src/cdn/document-query.ts","../src/cdn/media-accessor.ts","../src/cdn/forms-client.ts","../src/cdn/comments-client.ts","../src/cdn/conversation-client.ts","../src/cdn/errors.ts","../src/cdn/index.ts"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_cdn = require("./cdn-DrQCLLj6.cjs");
5
+ const require_cdn = require("./cdn-DJw9oksO.cjs");
6
6
  //#region src/runtime/query.ts
7
7
  var QueryBuilder = class {
8
8
  _data;
@@ -390,6 +390,7 @@ async function createContentrainClient(projectRoot) {
390
390
  return await import(pathToFileURL(resolve(projectRoot ?? process.cwd(), ".contentrain", "client", "index.mjs")).href);
391
391
  }
392
392
  //#endregion
393
+ exports.CommentsClient = require_cdn.CommentsClient;
393
394
  exports.ContentrainError = require_cdn.ContentrainError;
394
395
  exports.ConversationClient = require_cdn.ConversationClient;
395
396
  exports.DictionaryAccessor = DictionaryAccessor;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as applyWhere, D as EntryMeta, I as DocumentIndexEntry, O as WhereClause, S as MediaManifest, _ as FormsClient, a as ConversationClient, b as MediaAsset, c as ConversationHistory, g as FormSubmitResult, h as FormFieldConfig, i as ContentrainError, k as WhereOp, l as ConversationMessage, m as FormConfig, n as ContentrainCDNConfig, o as ConversationClientConfig, r as createContentrain, t as ContentrainCDNClient, u as ConversationResponse, v as FormsClientConfig, x as MediaAssetMeta, y as MediaAccessor } from "./index-mxo0dHvb.cjs";
1
+ import { A as FormsClient, B as EntryMeta, C as CommentsClientConfig, D as FormFieldError, E as FormFieldConfig, F as MediaManifest, H as WhereOp, M as MediaAccessor, N as MediaAsset, O as FormSubmitOptions, P as MediaAssetMeta, S as CommentsClient, T as FormConfig, U as applyWhere, V as WhereClause, Y as DocumentIndexEntry, _ as CommentSubmitResult, a as ConversationClient, b as CommentThreadQuery, c as ConversationHistory, g as CommentSubmission, h as CommentFieldError, i as ContentrainError, j as FormsClientConfig, k as FormSubmitResult, l as ConversationMessage, m as CommentAuthor, n as ContentrainCDNConfig, o as ConversationClientConfig, r as createContentrain, t as ContentrainCDNClient, u as ConversationResponse, v as CommentThread, w as PublicComment, y as CommentThreadConfig } from "./index-BFurv7WX.cjs";
2
2
  import { ContentStatus, ContentrainConfig, FieldDef, FieldType, ModelDefinition, ModelKind } from "@contentrain/types";
3
3
 
4
4
  //#region src/runtime/query.d.ts
@@ -112,5 +112,5 @@ declare function createContentrainClient(projectRoot?: string): Promise<{
112
112
  document: (model: string) => DocumentQuery<Record<string, unknown>>;
113
113
  }>;
114
114
  //#endregion
115
- export { type ContentStatus, type ContentrainCDNClient, type ContentrainCDNConfig, type ContentrainConfig, ContentrainError, ConversationClient, type ConversationClientConfig, type ConversationHistory, type ConversationMessage, type ConversationResponse, DictionaryAccessor, type DocumentIndexEntry, DocumentQuery, type EntryMeta, type FieldDef, type FieldType, type FormConfig, type FormFieldConfig, type FormSubmitResult, FormsClient, type FormsClientConfig, MediaAccessor, type MediaAsset, type MediaAssetMeta, type MediaManifest, type ModelDefinition, type ModelKind, QueryBuilder, type RelationMeta, type RelationResolver, SingletonAccessor, type WhereClause, type WhereOp, applyWhere, createContentrain, createContentrainClient, createContentrainClient as default };
115
+ export { type CommentAuthor, type CommentFieldError, type CommentSubmission, type CommentSubmitResult, type CommentThread, type CommentThreadConfig, type CommentThreadQuery, CommentsClient, type CommentsClientConfig, type ContentStatus, type ContentrainCDNClient, type ContentrainCDNConfig, type ContentrainConfig, ContentrainError, ConversationClient, type ConversationClientConfig, type ConversationHistory, type ConversationMessage, type ConversationResponse, DictionaryAccessor, type DocumentIndexEntry, DocumentQuery, type EntryMeta, type FieldDef, type FieldType, type FormConfig, type FormFieldConfig, type FormFieldError, type FormSubmitOptions, type FormSubmitResult, FormsClient, type FormsClientConfig, MediaAccessor, type MediaAsset, type MediaAssetMeta, type MediaManifest, type ModelDefinition, type ModelKind, type PublicComment, QueryBuilder, type RelationMeta, type RelationResolver, SingletonAccessor, type WhereClause, type WhereOp, applyWhere, createContentrain, createContentrainClient, createContentrainClient as default };
116
116
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as applyWhere, D as EntryMeta, I as DocumentIndexEntry, O as WhereClause, S as MediaManifest, _ as FormsClient, a as ConversationClient, b as MediaAsset, c as ConversationHistory, g as FormSubmitResult, h as FormFieldConfig, i as ContentrainError, k as WhereOp, l as ConversationMessage, m as FormConfig, n as ContentrainCDNConfig, o as ConversationClientConfig, r as createContentrain, t as ContentrainCDNClient, u as ConversationResponse, v as FormsClientConfig, x as MediaAssetMeta, y as MediaAccessor } from "./index-TgljULTn.mjs";
1
+ import { A as FormsClient, B as EntryMeta, C as CommentsClientConfig, D as FormFieldError, E as FormFieldConfig, F as MediaManifest, H as WhereOp, M as MediaAccessor, N as MediaAsset, O as FormSubmitOptions, P as MediaAssetMeta, S as CommentsClient, T as FormConfig, U as applyWhere, V as WhereClause, Y as DocumentIndexEntry, _ as CommentSubmitResult, a as ConversationClient, b as CommentThreadQuery, c as ConversationHistory, g as CommentSubmission, h as CommentFieldError, i as ContentrainError, j as FormsClientConfig, k as FormSubmitResult, l as ConversationMessage, m as CommentAuthor, n as ContentrainCDNConfig, o as ConversationClientConfig, r as createContentrain, t as ContentrainCDNClient, u as ConversationResponse, v as CommentThread, w as PublicComment, y as CommentThreadConfig } from "./index-VXFz-DDN.mjs";
2
2
  import { ContentStatus, ContentrainConfig, FieldDef, FieldType, ModelDefinition, ModelKind } from "@contentrain/types";
3
3
 
4
4
  //#region src/runtime/query.d.ts
@@ -112,5 +112,5 @@ declare function createContentrainClient(projectRoot?: string): Promise<{
112
112
  document: (model: string) => DocumentQuery<Record<string, unknown>>;
113
113
  }>;
114
114
  //#endregion
115
- export { type ContentStatus, type ContentrainCDNClient, type ContentrainCDNConfig, type ContentrainConfig, ContentrainError, ConversationClient, type ConversationClientConfig, type ConversationHistory, type ConversationMessage, type ConversationResponse, DictionaryAccessor, type DocumentIndexEntry, DocumentQuery, type EntryMeta, type FieldDef, type FieldType, type FormConfig, type FormFieldConfig, type FormSubmitResult, FormsClient, type FormsClientConfig, MediaAccessor, type MediaAsset, type MediaAssetMeta, type MediaManifest, type ModelDefinition, type ModelKind, QueryBuilder, type RelationMeta, type RelationResolver, SingletonAccessor, type WhereClause, type WhereOp, applyWhere, createContentrain, createContentrainClient, createContentrainClient as default };
115
+ export { type CommentAuthor, type CommentFieldError, type CommentSubmission, type CommentSubmitResult, type CommentThread, type CommentThreadConfig, type CommentThreadQuery, CommentsClient, type CommentsClientConfig, type ContentStatus, type ContentrainCDNClient, type ContentrainCDNConfig, type ContentrainConfig, ContentrainError, ConversationClient, type ConversationClientConfig, type ConversationHistory, type ConversationMessage, type ConversationResponse, DictionaryAccessor, type DocumentIndexEntry, DocumentQuery, type EntryMeta, type FieldDef, type FieldType, type FormConfig, type FormFieldConfig, type FormFieldError, type FormSubmitOptions, type FormSubmitResult, FormsClient, type FormsClientConfig, MediaAccessor, type MediaAsset, type MediaAssetMeta, type MediaManifest, type ModelDefinition, type ModelKind, type PublicComment, QueryBuilder, type RelationMeta, type RelationResolver, SingletonAccessor, type WhereClause, type WhereOp, applyWhere, createContentrain, createContentrainClient, createContentrainClient as default };
116
116
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { d as applyWhere, i as MediaAccessor, n as ConversationClient, r as FormsClient, t as createContentrain, u as ContentrainError } from "./cdn-C8dqHhdG.mjs";
1
+ import { a as MediaAccessor, d as ContentrainError, f as applyWhere, i as FormsClient, n as ConversationClient, r as CommentsClient, t as createContentrain } from "./cdn-C5yiVdfQ.mjs";
2
2
  //#region src/runtime/query.ts
3
3
  var QueryBuilder = class {
4
4
  _data;
@@ -386,6 +386,6 @@ async function createContentrainClient(projectRoot) {
386
386
  return await import(pathToFileURL(resolve(projectRoot ?? process.cwd(), ".contentrain", "client", "index.mjs")).href);
387
387
  }
388
388
  //#endregion
389
- export { ContentrainError, ConversationClient, DictionaryAccessor, DocumentQuery, FormsClient, MediaAccessor, QueryBuilder, SingletonAccessor, applyWhere, createContentrain, createContentrainClient, createContentrainClient as default };
389
+ export { CommentsClient, ContentrainError, ConversationClient, DictionaryAccessor, DocumentQuery, FormsClient, MediaAccessor, QueryBuilder, SingletonAccessor, applyWhere, createContentrain, createContentrainClient, createContentrainClient as default };
390
390
 
391
391
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/runtime/query.ts","../src/runtime/singleton.ts","../src/runtime/dictionary.ts","../src/runtime/document.ts","../src/index.ts"],"sourcesContent":["import type { WhereOp, WhereClause } from '../shared/where.js'\nimport { applyWhere } from '../shared/where.js'\n\nexport type { WhereOp }\n\nexport interface RelationMeta {\n target: string | string[]\n multi: boolean\n}\n\nexport type RelationResolver = (model: string, id: string, locale: string | null) => Record<string, unknown> | undefined\n\nexport class QueryBuilder<T extends object> {\n private _data: Map<string, T[]>\n private _locale: string | null = null\n private _filters: WhereClause[] = []\n private _sortField: string | null = null\n private _sortOrder: 'asc' | 'desc' = 'asc'\n private _limit: number | null = null\n private _offset = 0\n private _includes: string[] = []\n private _relationMeta: Record<string, RelationMeta>\n private _resolver: RelationResolver | null\n private _defaultLocale: string | null\n\n constructor(\n data: Map<string, T[]>,\n relationMeta?: Record<string, RelationMeta>,\n resolver?: RelationResolver,\n defaultLocale?: string,\n ) {\n this._data = data\n this._relationMeta = relationMeta ?? {}\n this._resolver = resolver ?? null\n this._defaultLocale = defaultLocale ?? null\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n where<K extends string & keyof T>(field: K, value: T[K]): this\n where<K extends string & keyof T>(field: K, op: WhereOp, value: unknown): this\n where<K extends string & keyof T>(field: K, opOrValue: WhereOp | T[K], value?: unknown): this {\n if (value !== undefined) {\n this._filters.push({ field, op: opOrValue as WhereOp, value })\n } else {\n this._filters.push({ field, op: 'eq', value: opOrValue })\n }\n return this\n }\n\n sort<K extends string & keyof T>(field: K, order: 'asc' | 'desc' = 'asc'): this {\n this._sortField = field\n this._sortOrder = order\n return this\n }\n\n limit(n: number): this {\n this._limit = n\n return this\n }\n\n offset(n: number): this {\n this._offset = n\n return this\n }\n\n include(...fields: string[]): this {\n this._includes.push(...fields)\n return this\n }\n\n count(): number {\n return this.all().length\n }\n\n all(): T[] {\n let items = this._resolveData()\n\n // Filter\n for (const clause of this._filters) {\n items = items.filter(item => applyWhere(item, clause))\n }\n\n // Sort\n if (this._sortField) {\n const field = this._sortField\n const dir = this._sortOrder === 'asc' ? 1 : -1\n items.sort((a, b) => {\n const va = (a as Record<string, unknown>)[field]\n const vb = (b as Record<string, unknown>)[field]\n if (va == null && vb == null) return 0\n if (va == null) return dir\n if (vb == null) return -dir\n if (va < vb) return -dir\n if (va > vb) return dir\n return 0\n })\n }\n\n // Pagination\n if (this._offset > 0 || this._limit !== null) {\n const end = this._limit !== null ? this._offset + this._limit : undefined\n items = items.slice(this._offset, end)\n }\n\n // Resolve relations (after pagination for efficiency)\n if (this._includes.length > 0 && this._resolver) {\n items = items.map(item => this._resolveIncludes(item))\n }\n\n return items\n }\n\n first(): T | undefined {\n return this.all()[0]\n }\n\n private _resolveData(): T[] {\n if (this._locale) {\n return [...(this._data.get(this._locale) ?? [])]\n }\n if (this._defaultLocale) {\n const defaultData = this._data.get(this._defaultLocale)\n if (defaultData) return [...defaultData]\n }\n const firstKey = this._data.keys().next().value\n if (firstKey !== undefined) {\n return [...(this._data.get(firstKey) ?? [])]\n }\n return []\n }\n\n private _resolveIncludes(item: T): T {\n const resolved = { ...item }\n const src = item as Record<string, unknown>\n const dst = resolved as Record<string, unknown>\n for (const field of this._includes) {\n const meta = this._relationMeta[field]\n if (!meta) continue\n const targets = Array.isArray(meta.target) ? meta.target : [meta.target]\n\n if (meta.multi) {\n const ids = src[field]\n if (Array.isArray(ids)) {\n dst[field] = ids.map((id) => {\n if (typeof id === 'string') {\n return this._resolveId(targets, id) ?? id\n }\n if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n return this._resolveId([polyObj.model], polyObj.ref) ?? id\n }\n return id\n })\n }\n } else {\n const id = src[field]\n if (typeof id === 'string') {\n dst[field] = this._resolveId(targets, id) ?? id\n } else if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n dst[field] = this._resolveId([polyObj.model], polyObj.ref) ?? id\n }\n }\n }\n return resolved\n }\n\n private _resolveId(targets: string[], id: string): Record<string, unknown> | undefined {\n const loc = this._locale ?? this._defaultLocale\n for (const target of targets) {\n const result = this._resolver!(target, id, loc)\n if (result) return result\n }\n return undefined\n }\n}\n","export class SingletonAccessor<T extends Record<string, unknown>> {\n private _data: Map<string, T>\n private _locale: string | null = null\n private _defaultLocale: string | null\n private _includes: string[] = []\n private _relationMeta: Record<string, { target: string | string[]; multi: boolean }> = {}\n private _resolveEntry?: (model: string, id: string, locale: string) => unknown\n\n constructor(\n data: Map<string, T>,\n defaultLocale?: string,\n relationMeta?: Record<string, { target: string | string[]; multi: boolean }>,\n resolveEntry?: (model: string, id: string, locale: string) => unknown,\n ) {\n this._data = data\n this._defaultLocale = defaultLocale ?? null\n if (relationMeta) this._relationMeta = relationMeta\n this._resolveEntry = resolveEntry\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n include(...fields: string[]): this {\n this._includes.push(...fields)\n return this\n }\n\n get(): T {\n if (this._locale) {\n const d = this._data.get(this._locale)\n if (!d) throw new Error(`No data for locale \"${this._locale}\"`)\n if (this._includes.length > 0) return this._resolveIncludes(d, this._locale)\n return d\n }\n\n const locale = this._defaultLocale ?? undefined\n let data: T | undefined\n\n if (locale) {\n data = this._data.get(locale)\n }\n if (!data) {\n const firstKey = this._data.keys().next().value\n if (firstKey !== undefined) {\n data = this._data.get(firstKey)\n }\n }\n if (!data) throw new Error('No data available')\n\n if (this._includes.length > 0) {\n return this._resolveIncludes(data, locale ?? 'en')\n }\n return data\n }\n\n private _resolveIncludes(item: T, locale: string): T {\n if (!this._resolveEntry || this._includes.length === 0) return item\n const resolved = { ...item }\n const src = item as Record<string, unknown>\n const dst = resolved as Record<string, unknown>\n\n for (const field of this._includes) {\n const meta = this._relationMeta[field]\n if (!meta) continue\n const targets = Array.isArray(meta.target) ? meta.target : [meta.target]\n\n if (meta.multi) {\n const ids = src[field]\n if (Array.isArray(ids)) {\n dst[field] = ids.map((id) => {\n if (typeof id === 'string') {\n return this._resolveId(targets, id, locale) ?? id\n }\n if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n return this._resolveId([polyObj.model], polyObj.ref, locale) ?? id\n }\n return id\n })\n }\n } else {\n const id = src[field]\n if (typeof id === 'string') {\n dst[field] = this._resolveId(targets, id, locale) ?? id\n } else if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n dst[field] = this._resolveId([polyObj.model], polyObj.ref, locale) ?? id\n }\n }\n }\n\n return resolved\n }\n\n private _resolveId(targets: string[], id: string, locale: string): unknown {\n if (!this._resolveEntry) return undefined\n for (const model of targets) {\n const result = this._resolveEntry(model, id, locale)\n if (result) return result\n }\n return undefined\n }\n}\n","export class DictionaryAccessor {\n private _data: Map<string, Record<string, string>>\n private _locale: string | null = null\n private _defaultLocale: string | null\n\n constructor(data: Map<string, Record<string, string>>, defaultLocale?: string) {\n this._data = data\n this._defaultLocale = defaultLocale ?? null\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n get(): Record<string, string>\n get(key: string): string | undefined\n get(key: string, params: Record<string, string | number>): string\n get(key?: string, params?: Record<string, string | number>): Record<string, string> | string | undefined {\n const dict = this._resolveData()\n if (key === undefined) return dict\n const value = dict[key]\n if (value === undefined) return undefined\n if (params) return interpolate(value, params)\n return value\n }\n\n private _resolveData(): Record<string, string> {\n if (this._locale) {\n return this._data.get(this._locale) ?? {}\n }\n if (this._defaultLocale) {\n const d = this._data.get(this._defaultLocale)\n if (d) return d\n }\n const firstKey = this._data.keys().next().value\n if (firstKey !== undefined) {\n return this._data.get(firstKey) ?? {}\n }\n return {}\n }\n}\n\nfunction interpolate(template: string, params: Record<string, string | number>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => {\n const val = params[key]\n return val !== undefined ? String(val) : match\n })\n}\n","import type { RelationMeta, RelationResolver } from './query.js'\nimport type { WhereOp, WhereClause } from '../shared/where.js'\nimport { applyWhere } from '../shared/where.js'\n\nexport class DocumentQuery<T extends object> {\n private _data: Map<string, T[]>\n private _locale: string | null = null\n private _filters: WhereClause[] = []\n private _sortField: string | null = null\n private _sortOrder: 'asc' | 'desc' = 'asc'\n private _includes: string[] = []\n private _relationMeta: Record<string, RelationMeta>\n private _resolver: RelationResolver | null\n private _defaultLocale: string | null\n\n constructor(\n data: Map<string, T[]>,\n relationMeta?: Record<string, RelationMeta>,\n resolver?: RelationResolver,\n defaultLocale?: string,\n ) {\n this._data = data\n this._relationMeta = relationMeta ?? {}\n this._resolver = resolver ?? null\n this._defaultLocale = defaultLocale ?? null\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n where<K extends string & keyof T>(field: K, value: T[K]): this\n where<K extends string & keyof T>(field: K, op: WhereOp, value: unknown): this\n where<K extends string & keyof T>(field: K, opOrValue: WhereOp | T[K], value?: unknown): this {\n if (value !== undefined) {\n this._filters.push({ field, op: opOrValue as WhereOp, value })\n } else {\n this._filters.push({ field, op: 'eq', value: opOrValue })\n }\n return this\n }\n\n sort<K extends string & keyof T>(field: K, order: 'asc' | 'desc' = 'asc'): this {\n this._sortField = field\n this._sortOrder = order\n return this\n }\n\n include(...fields: string[]): this {\n this._includes.push(...fields)\n return this\n }\n\n bySlug(slug: string): T | undefined {\n const items = this._resolveData()\n const item = items.find(i => (i as Record<string, unknown>)['slug'] === slug)\n if (item && this._includes.length > 0 && this._resolver) {\n return this._resolveIncludes(item)\n }\n return item\n }\n\n count(): number {\n return this.all().length\n }\n\n all(): T[] {\n let items = this._resolveData()\n for (const clause of this._filters) {\n items = items.filter(item => applyWhere(item, clause))\n }\n if (this._sortField) {\n const sf = this._sortField\n const dir = this._sortOrder === 'asc' ? 1 : -1\n items = items.toSorted((a, b) => {\n const va = (a as Record<string, unknown>)[sf] as number | string | null | undefined\n const vb = (b as Record<string, unknown>)[sf] as number | string | null | undefined\n if (va == null && vb == null) return 0\n if (va == null) return dir\n if (vb == null) return -dir\n return va < vb ? -dir : va > vb ? dir : 0\n })\n }\n if (this._includes.length > 0 && this._resolver) {\n items = items.map(item => this._resolveIncludes(item))\n }\n return items\n }\n\n first(): T | undefined {\n return this.all()[0]\n }\n\n private _resolveData(): T[] {\n if (this._locale) {\n return [...(this._data.get(this._locale) ?? [])]\n }\n if (this._defaultLocale) {\n const defaultData = this._data.get(this._defaultLocale)\n if (defaultData) return [...defaultData]\n }\n const firstKey = this._data.keys().next().value\n if (firstKey !== undefined) {\n return [...(this._data.get(firstKey) ?? [])]\n }\n return []\n }\n\n private _resolveIncludes(item: T): T {\n const resolved = { ...item }\n const src = item as Record<string, unknown>\n const dst = resolved as Record<string, unknown>\n for (const field of this._includes) {\n const meta = this._relationMeta[field]\n if (!meta) continue\n const targets = Array.isArray(meta.target) ? meta.target : [meta.target]\n\n if (meta.multi) {\n const ids = src[field]\n if (Array.isArray(ids)) {\n dst[field] = ids.map((id) => {\n if (typeof id === 'string') {\n return this._resolveId(targets, id) ?? id\n }\n if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n return this._resolveId([polyObj.model], polyObj.ref) ?? id\n }\n return id\n })\n }\n } else {\n const id = src[field]\n if (typeof id === 'string') {\n dst[field] = this._resolveId(targets, id) ?? id\n } else if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n dst[field] = this._resolveId([polyObj.model], polyObj.ref) ?? id\n }\n }\n }\n return resolved\n }\n\n private _resolveId(targets: string[], id: string): Record<string, unknown> | undefined {\n const loc = this._locale ?? this._defaultLocale\n for (const target of targets) {\n const result = this._resolver!(target, id, loc)\n if (result) return result\n }\n return undefined\n }\n}\n","// Runtime exports — used by framework SDK authors and generated client\nexport { QueryBuilder } from './runtime/query.js'\nexport type { RelationMeta, RelationResolver, WhereOp } from './runtime/query.js'\nexport { SingletonAccessor } from './runtime/singleton.js'\nexport { DictionaryAccessor } from './runtime/dictionary.js'\nexport { DocumentQuery } from './runtime/document.js'\n\n// Shared utilities\nexport type { WhereClause } from './shared/where.js'\nexport { applyWhere } from './shared/where.js'\n\n// Re-export types from @contentrain/types that SDK consumers need\nexport type {\n FieldType,\n ModelKind,\n ContentStatus,\n FieldDef,\n ModelDefinition,\n ContentrainConfig,\n} from '@contentrain/types'\n\n/**\n * Factory for framework SDK authors.\n * Returns the generated client module loaded from .contentrain/client/.\n *\n * Usage (Nuxt composable):\n * ```ts\n * import { createContentrainClient } from '@contentrain/query'\n * const client = createContentrainClient()\n * const posts = client.query('blog-post').locale('en').all()\n * ```\n */\nexport async function createContentrainClient(\n projectRoot?: string,\n): Promise<{\n query: (model: string) => import('./runtime/query.js').QueryBuilder<Record<string, unknown>>\n singleton: (model: string) => import('./runtime/singleton.js').SingletonAccessor<Record<string, unknown>>\n dictionary: (model: string) => import('./runtime/dictionary.js').DictionaryAccessor\n document: (model: string) => import('./runtime/document.js').DocumentQuery<Record<string, unknown>>\n}> {\n const { resolve } = await import('node:path')\n const { pathToFileURL } = await import('node:url')\n const root = projectRoot ?? process.cwd()\n const clientPath = resolve(root, '.contentrain', 'client', 'index.mjs')\n const client = await import(pathToFileURL(clientPath).href)\n return client\n}\n\n// CDN client factory — async, HTTP-based\nexport { createContentrain } from './cdn/index.js'\nexport type { ContentrainCDNConfig, ContentrainCDNClient } from './cdn/index.js'\nexport type { DocumentIndexEntry } from './cdn/data-source.js'\nexport { ContentrainError } from './cdn/errors.js'\n\n// CDN module re-exports — media, forms, metadata\nexport { MediaAccessor } from './cdn/media-accessor.js'\nexport type { MediaAsset, MediaAssetMeta, MediaManifest } from './cdn/media-accessor.js'\nexport { FormsClient } from './cdn/forms-client.js'\nexport type { FormConfig, FormFieldConfig, FormSubmitResult, FormsClientConfig } from './cdn/forms-client.js'\nexport type { EntryMeta } from './cdn/collection-query.js'\nexport { ConversationClient } from './cdn/conversation-client.js'\nexport type {\n ConversationClientConfig,\n ConversationResponse,\n ConversationMessage,\n ConversationHistory,\n} from './cdn/conversation-client.js'\n\n// Sync factory for CJS — requires generated client to be pre-loaded\nexport { createContentrainClient as default }\n"],"mappings":";;AAYA,IAAa,eAAb,MAA4C;CAC1C;CACA,UAAiC;CACjC,WAAkC,EAAE;CACpC,aAAoC;CACpC,aAAqC;CACrC,SAAgC;CAChC,UAAkB;CAClB,YAA8B,EAAE;CAChC;CACA;CACA;CAEA,YACE,MACA,cACA,UACA,eACA;AACA,OAAK,QAAQ;AACb,OAAK,gBAAgB,gBAAgB,EAAE;AACvC,OAAK,YAAY,YAAY;AAC7B,OAAK,iBAAiB,iBAAiB;;CAGzC,OAAO,MAAoB;AACzB,OAAK,UAAU;AACf,SAAO;;CAKT,MAAkC,OAAU,WAA2B,OAAuB;AAC5F,MAAI,UAAU,KAAA,EACZ,MAAK,SAAS,KAAK;GAAE;GAAO,IAAI;GAAsB;GAAO,CAAC;MAE9D,MAAK,SAAS,KAAK;GAAE;GAAO,IAAI;GAAM,OAAO;GAAW,CAAC;AAE3D,SAAO;;CAGT,KAAiC,OAAU,QAAwB,OAAa;AAC9E,OAAK,aAAa;AAClB,OAAK,aAAa;AAClB,SAAO;;CAGT,MAAM,GAAiB;AACrB,OAAK,SAAS;AACd,SAAO;;CAGT,OAAO,GAAiB;AACtB,OAAK,UAAU;AACf,SAAO;;CAGT,QAAQ,GAAG,QAAwB;AACjC,OAAK,UAAU,KAAK,GAAG,OAAO;AAC9B,SAAO;;CAGT,QAAgB;AACd,SAAO,KAAK,KAAK,CAAC;;CAGpB,MAAW;EACT,IAAI,QAAQ,KAAK,cAAc;AAG/B,OAAK,MAAM,UAAU,KAAK,SACxB,SAAQ,MAAM,QAAO,SAAQ,WAAW,MAAM,OAAO,CAAC;AAIxD,MAAI,KAAK,YAAY;GACnB,MAAM,QAAQ,KAAK;GACnB,MAAM,MAAM,KAAK,eAAe,QAAQ,IAAI;AAC5C,SAAM,MAAM,GAAG,MAAM;IACnB,MAAM,KAAM,EAA8B;IAC1C,MAAM,KAAM,EAA8B;AAC1C,QAAI,MAAM,QAAQ,MAAM,KAAM,QAAO;AACrC,QAAI,MAAM,KAAM,QAAO;AACvB,QAAI,MAAM,KAAM,QAAO,CAAC;AACxB,QAAI,KAAK,GAAI,QAAO,CAAC;AACrB,QAAI,KAAK,GAAI,QAAO;AACpB,WAAO;KACP;;AAIJ,MAAI,KAAK,UAAU,KAAK,KAAK,WAAW,MAAM;GAC5C,MAAM,MAAM,KAAK,WAAW,OAAO,KAAK,UAAU,KAAK,SAAS,KAAA;AAChE,WAAQ,MAAM,MAAM,KAAK,SAAS,IAAI;;AAIxC,MAAI,KAAK,UAAU,SAAS,KAAK,KAAK,UACpC,SAAQ,MAAM,KAAI,SAAQ,KAAK,iBAAiB,KAAK,CAAC;AAGxD,SAAO;;CAGT,QAAuB;AACrB,SAAO,KAAK,KAAK,CAAC;;CAGpB,eAA4B;AAC1B,MAAI,KAAK,QACP,QAAO,CAAC,GAAI,KAAK,MAAM,IAAI,KAAK,QAAQ,IAAI,EAAE,CAAE;AAElD,MAAI,KAAK,gBAAgB;GACvB,MAAM,cAAc,KAAK,MAAM,IAAI,KAAK,eAAe;AACvD,OAAI,YAAa,QAAO,CAAC,GAAG,YAAY;;EAE1C,MAAM,WAAW,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC;AAC1C,MAAI,aAAa,KAAA,EACf,QAAO,CAAC,GAAI,KAAK,MAAM,IAAI,SAAS,IAAI,EAAE,CAAE;AAE9C,SAAO,EAAE;;CAGX,iBAAyB,MAAY;EACnC,MAAM,WAAW,EAAE,GAAG,MAAM;EAC5B,MAAM,MAAM;EACZ,MAAM,MAAM;AACZ,OAAK,MAAM,SAAS,KAAK,WAAW;GAClC,MAAM,OAAO,KAAK,cAAc;AAChC,OAAI,CAAC,KAAM;GACX,MAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,GAAG,KAAK,SAAS,CAAC,KAAK,OAAO;AAExE,OAAI,KAAK,OAAO;IACd,MAAM,MAAM,IAAI;AAChB,QAAI,MAAM,QAAQ,IAAI,CACpB,KAAI,SAAS,IAAI,KAAK,OAAO;AAC3B,SAAI,OAAO,OAAO,SAChB,QAAO,KAAK,WAAW,SAAS,GAAG,IAAI;AAEzC,SAAI,OAAO,OAAO,YAAY,OAAO,QAAQ,WAAW,MAAM,SAAS,IAAI;MACzE,MAAM,UAAU;AAChB,aAAO,KAAK,WAAW,CAAC,QAAQ,MAAM,EAAE,QAAQ,IAAI,IAAI;;AAE1D,YAAO;MACP;UAEC;IACL,MAAM,KAAK,IAAI;AACf,QAAI,OAAO,OAAO,SAChB,KAAI,SAAS,KAAK,WAAW,SAAS,GAAG,IAAI;aACpC,OAAO,OAAO,YAAY,OAAO,QAAQ,WAAW,MAAM,SAAS,IAAI;KAChF,MAAM,UAAU;AAChB,SAAI,SAAS,KAAK,WAAW,CAAC,QAAQ,MAAM,EAAE,QAAQ,IAAI,IAAI;;;;AAIpE,SAAO;;CAGT,WAAmB,SAAmB,IAAiD;EACrF,MAAM,MAAM,KAAK,WAAW,KAAK;AACjC,OAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,SAAS,KAAK,UAAW,QAAQ,IAAI,IAAI;AAC/C,OAAI,OAAQ,QAAO;;;;;;AC/KzB,IAAa,oBAAb,MAAkE;CAChE;CACA,UAAiC;CACjC;CACA,YAA8B,EAAE;CAChC,gBAAuF,EAAE;CACzF;CAEA,YACE,MACA,eACA,cACA,cACA;AACA,OAAK,QAAQ;AACb,OAAK,iBAAiB,iBAAiB;AACvC,MAAI,aAAc,MAAK,gBAAgB;AACvC,OAAK,gBAAgB;;CAGvB,OAAO,MAAoB;AACzB,OAAK,UAAU;AACf,SAAO;;CAGT,QAAQ,GAAG,QAAwB;AACjC,OAAK,UAAU,KAAK,GAAG,OAAO;AAC9B,SAAO;;CAGT,MAAS;AACP,MAAI,KAAK,SAAS;GAChB,MAAM,IAAI,KAAK,MAAM,IAAI,KAAK,QAAQ;AACtC,OAAI,CAAC,EAAG,OAAM,IAAI,MAAM,uBAAuB,KAAK,QAAQ,GAAG;AAC/D,OAAI,KAAK,UAAU,SAAS,EAAG,QAAO,KAAK,iBAAiB,GAAG,KAAK,QAAQ;AAC5E,UAAO;;EAGT,MAAM,SAAS,KAAK,kBAAkB,KAAA;EACtC,IAAI;AAEJ,MAAI,OACF,QAAO,KAAK,MAAM,IAAI,OAAO;AAE/B,MAAI,CAAC,MAAM;GACT,MAAM,WAAW,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC;AAC1C,OAAI,aAAa,KAAA,EACf,QAAO,KAAK,MAAM,IAAI,SAAS;;AAGnC,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,oBAAoB;AAE/C,MAAI,KAAK,UAAU,SAAS,EAC1B,QAAO,KAAK,iBAAiB,MAAM,UAAU,KAAK;AAEpD,SAAO;;CAGT,iBAAyB,MAAS,QAAmB;AACnD,MAAI,CAAC,KAAK,iBAAiB,KAAK,UAAU,WAAW,EAAG,QAAO;EAC/D,MAAM,WAAW,EAAE,GAAG,MAAM;EAC5B,MAAM,MAAM;EACZ,MAAM,MAAM;AAEZ,OAAK,MAAM,SAAS,KAAK,WAAW;GAClC,MAAM,OAAO,KAAK,cAAc;AAChC,OAAI,CAAC,KAAM;GACX,MAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,GAAG,KAAK,SAAS,CAAC,KAAK,OAAO;AAExE,OAAI,KAAK,OAAO;IACd,MAAM,MAAM,IAAI;AAChB,QAAI,MAAM,QAAQ,IAAI,CACpB,KAAI,SAAS,IAAI,KAAK,OAAO;AAC3B,SAAI,OAAO,OAAO,SAChB,QAAO,KAAK,WAAW,SAAS,IAAI,OAAO,IAAI;AAEjD,SAAI,OAAO,OAAO,YAAY,OAAO,QAAQ,WAAW,MAAM,SAAS,IAAI;MACzE,MAAM,UAAU;AAChB,aAAO,KAAK,WAAW,CAAC,QAAQ,MAAM,EAAE,QAAQ,KAAK,OAAO,IAAI;;AAElE,YAAO;MACP;UAEC;IACL,MAAM,KAAK,IAAI;AACf,QAAI,OAAO,OAAO,SAChB,KAAI,SAAS,KAAK,WAAW,SAAS,IAAI,OAAO,IAAI;aAC5C,OAAO,OAAO,YAAY,OAAO,QAAQ,WAAW,MAAM,SAAS,IAAI;KAChF,MAAM,UAAU;AAChB,SAAI,SAAS,KAAK,WAAW,CAAC,QAAQ,MAAM,EAAE,QAAQ,KAAK,OAAO,IAAI;;;;AAK5E,SAAO;;CAGT,WAAmB,SAAmB,IAAY,QAAyB;AACzE,MAAI,CAAC,KAAK,cAAe,QAAO,KAAA;AAChC,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,SAAS,KAAK,cAAc,OAAO,IAAI,OAAO;AACpD,OAAI,OAAQ,QAAO;;;;;;ACrGzB,IAAa,qBAAb,MAAgC;CAC9B;CACA,UAAiC;CACjC;CAEA,YAAY,MAA2C,eAAwB;AAC7E,OAAK,QAAQ;AACb,OAAK,iBAAiB,iBAAiB;;CAGzC,OAAO,MAAoB;AACzB,OAAK,UAAU;AACf,SAAO;;CAMT,IAAI,KAAc,QAAuF;EACvG,MAAM,OAAO,KAAK,cAAc;AAChC,MAAI,QAAQ,KAAA,EAAW,QAAO;EAC9B,MAAM,QAAQ,KAAK;AACnB,MAAI,UAAU,KAAA,EAAW,QAAO,KAAA;AAChC,MAAI,OAAQ,QAAO,YAAY,OAAO,OAAO;AAC7C,SAAO;;CAGT,eAA+C;AAC7C,MAAI,KAAK,QACP,QAAO,KAAK,MAAM,IAAI,KAAK,QAAQ,IAAI,EAAE;AAE3C,MAAI,KAAK,gBAAgB;GACvB,MAAM,IAAI,KAAK,MAAM,IAAI,KAAK,eAAe;AAC7C,OAAI,EAAG,QAAO;;EAEhB,MAAM,WAAW,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC;AAC1C,MAAI,aAAa,KAAA,EACf,QAAO,KAAK,MAAM,IAAI,SAAS,IAAI,EAAE;AAEvC,SAAO,EAAE;;;AAIb,SAAS,YAAY,UAAkB,QAAiD;AACtF,QAAO,SAAS,QAAQ,eAAe,OAAO,QAAgB;EAC5D,MAAM,MAAM,OAAO;AACnB,SAAO,QAAQ,KAAA,IAAY,OAAO,IAAI,GAAG;GACzC;;;;AC3CJ,IAAa,gBAAb,MAA6C;CAC3C;CACA,UAAiC;CACjC,WAAkC,EAAE;CACpC,aAAoC;CACpC,aAAqC;CACrC,YAA8B,EAAE;CAChC;CACA;CACA;CAEA,YACE,MACA,cACA,UACA,eACA;AACA,OAAK,QAAQ;AACb,OAAK,gBAAgB,gBAAgB,EAAE;AACvC,OAAK,YAAY,YAAY;AAC7B,OAAK,iBAAiB,iBAAiB;;CAGzC,OAAO,MAAoB;AACzB,OAAK,UAAU;AACf,SAAO;;CAKT,MAAkC,OAAU,WAA2B,OAAuB;AAC5F,MAAI,UAAU,KAAA,EACZ,MAAK,SAAS,KAAK;GAAE;GAAO,IAAI;GAAsB;GAAO,CAAC;MAE9D,MAAK,SAAS,KAAK;GAAE;GAAO,IAAI;GAAM,OAAO;GAAW,CAAC;AAE3D,SAAO;;CAGT,KAAiC,OAAU,QAAwB,OAAa;AAC9E,OAAK,aAAa;AAClB,OAAK,aAAa;AAClB,SAAO;;CAGT,QAAQ,GAAG,QAAwB;AACjC,OAAK,UAAU,KAAK,GAAG,OAAO;AAC9B,SAAO;;CAGT,OAAO,MAA6B;EAElC,MAAM,OADQ,KAAK,cAAc,CACd,MAAK,MAAM,EAA8B,YAAY,KAAK;AAC7E,MAAI,QAAQ,KAAK,UAAU,SAAS,KAAK,KAAK,UAC5C,QAAO,KAAK,iBAAiB,KAAK;AAEpC,SAAO;;CAGT,QAAgB;AACd,SAAO,KAAK,KAAK,CAAC;;CAGpB,MAAW;EACT,IAAI,QAAQ,KAAK,cAAc;AAC/B,OAAK,MAAM,UAAU,KAAK,SACxB,SAAQ,MAAM,QAAO,SAAQ,WAAW,MAAM,OAAO,CAAC;AAExD,MAAI,KAAK,YAAY;GACnB,MAAM,KAAK,KAAK;GAChB,MAAM,MAAM,KAAK,eAAe,QAAQ,IAAI;AAC5C,WAAQ,MAAM,UAAU,GAAG,MAAM;IAC/B,MAAM,KAAM,EAA8B;IAC1C,MAAM,KAAM,EAA8B;AAC1C,QAAI,MAAM,QAAQ,MAAM,KAAM,QAAO;AACrC,QAAI,MAAM,KAAM,QAAO;AACvB,QAAI,MAAM,KAAM,QAAO,CAAC;AACxB,WAAO,KAAK,KAAK,CAAC,MAAM,KAAK,KAAK,MAAM;KACxC;;AAEJ,MAAI,KAAK,UAAU,SAAS,KAAK,KAAK,UACpC,SAAQ,MAAM,KAAI,SAAQ,KAAK,iBAAiB,KAAK,CAAC;AAExD,SAAO;;CAGT,QAAuB;AACrB,SAAO,KAAK,KAAK,CAAC;;CAGpB,eAA4B;AAC1B,MAAI,KAAK,QACP,QAAO,CAAC,GAAI,KAAK,MAAM,IAAI,KAAK,QAAQ,IAAI,EAAE,CAAE;AAElD,MAAI,KAAK,gBAAgB;GACvB,MAAM,cAAc,KAAK,MAAM,IAAI,KAAK,eAAe;AACvD,OAAI,YAAa,QAAO,CAAC,GAAG,YAAY;;EAE1C,MAAM,WAAW,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC;AAC1C,MAAI,aAAa,KAAA,EACf,QAAO,CAAC,GAAI,KAAK,MAAM,IAAI,SAAS,IAAI,EAAE,CAAE;AAE9C,SAAO,EAAE;;CAGX,iBAAyB,MAAY;EACnC,MAAM,WAAW,EAAE,GAAG,MAAM;EAC5B,MAAM,MAAM;EACZ,MAAM,MAAM;AACZ,OAAK,MAAM,SAAS,KAAK,WAAW;GAClC,MAAM,OAAO,KAAK,cAAc;AAChC,OAAI,CAAC,KAAM;GACX,MAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,GAAG,KAAK,SAAS,CAAC,KAAK,OAAO;AAExE,OAAI,KAAK,OAAO;IACd,MAAM,MAAM,IAAI;AAChB,QAAI,MAAM,QAAQ,IAAI,CACpB,KAAI,SAAS,IAAI,KAAK,OAAO;AAC3B,SAAI,OAAO,OAAO,SAChB,QAAO,KAAK,WAAW,SAAS,GAAG,IAAI;AAEzC,SAAI,OAAO,OAAO,YAAY,OAAO,QAAQ,WAAW,MAAM,SAAS,IAAI;MACzE,MAAM,UAAU;AAChB,aAAO,KAAK,WAAW,CAAC,QAAQ,MAAM,EAAE,QAAQ,IAAI,IAAI;;AAE1D,YAAO;MACP;UAEC;IACL,MAAM,KAAK,IAAI;AACf,QAAI,OAAO,OAAO,SAChB,KAAI,SAAS,KAAK,WAAW,SAAS,GAAG,IAAI;aACpC,OAAO,OAAO,YAAY,OAAO,QAAQ,WAAW,MAAM,SAAS,IAAI;KAChF,MAAM,UAAU;AAChB,SAAI,SAAS,KAAK,WAAW,CAAC,QAAQ,MAAM,EAAE,QAAQ,IAAI,IAAI;;;;AAIpE,SAAO;;CAGT,WAAmB,SAAmB,IAAiD;EACrF,MAAM,MAAM,KAAK,WAAW,KAAK;AACjC,OAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,SAAS,KAAK,UAAW,QAAQ,IAAI,IAAI;AAC/C,OAAI,OAAQ,QAAO;;;;;;;;;;;;;;;;;ACrHzB,eAAsB,wBACpB,aAMC;CACD,MAAM,EAAE,YAAY,MAAM,OAAO;CACjC,MAAM,EAAE,kBAAkB,MAAM,OAAO;AAIvC,QADe,MAAM,OAAO,cADT,QADN,eAAe,QAAQ,KAAK,EACR,gBAAgB,UAAU,YAAY,CAClB,CAAC"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/runtime/query.ts","../src/runtime/singleton.ts","../src/runtime/dictionary.ts","../src/runtime/document.ts","../src/index.ts"],"sourcesContent":["import type { WhereOp, WhereClause } from '../shared/where.js'\nimport { applyWhere } from '../shared/where.js'\n\nexport type { WhereOp }\n\nexport interface RelationMeta {\n target: string | string[]\n multi: boolean\n}\n\nexport type RelationResolver = (model: string, id: string, locale: string | null) => Record<string, unknown> | undefined\n\nexport class QueryBuilder<T extends object> {\n private _data: Map<string, T[]>\n private _locale: string | null = null\n private _filters: WhereClause[] = []\n private _sortField: string | null = null\n private _sortOrder: 'asc' | 'desc' = 'asc'\n private _limit: number | null = null\n private _offset = 0\n private _includes: string[] = []\n private _relationMeta: Record<string, RelationMeta>\n private _resolver: RelationResolver | null\n private _defaultLocale: string | null\n\n constructor(\n data: Map<string, T[]>,\n relationMeta?: Record<string, RelationMeta>,\n resolver?: RelationResolver,\n defaultLocale?: string,\n ) {\n this._data = data\n this._relationMeta = relationMeta ?? {}\n this._resolver = resolver ?? null\n this._defaultLocale = defaultLocale ?? null\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n where<K extends string & keyof T>(field: K, value: T[K]): this\n where<K extends string & keyof T>(field: K, op: WhereOp, value: unknown): this\n where<K extends string & keyof T>(field: K, opOrValue: WhereOp | T[K], value?: unknown): this {\n if (value !== undefined) {\n this._filters.push({ field, op: opOrValue as WhereOp, value })\n } else {\n this._filters.push({ field, op: 'eq', value: opOrValue })\n }\n return this\n }\n\n sort<K extends string & keyof T>(field: K, order: 'asc' | 'desc' = 'asc'): this {\n this._sortField = field\n this._sortOrder = order\n return this\n }\n\n limit(n: number): this {\n this._limit = n\n return this\n }\n\n offset(n: number): this {\n this._offset = n\n return this\n }\n\n include(...fields: string[]): this {\n this._includes.push(...fields)\n return this\n }\n\n count(): number {\n return this.all().length\n }\n\n all(): T[] {\n let items = this._resolveData()\n\n // Filter\n for (const clause of this._filters) {\n items = items.filter(item => applyWhere(item, clause))\n }\n\n // Sort\n if (this._sortField) {\n const field = this._sortField\n const dir = this._sortOrder === 'asc' ? 1 : -1\n items.sort((a, b) => {\n const va = (a as Record<string, unknown>)[field]\n const vb = (b as Record<string, unknown>)[field]\n if (va == null && vb == null) return 0\n if (va == null) return dir\n if (vb == null) return -dir\n if (va < vb) return -dir\n if (va > vb) return dir\n return 0\n })\n }\n\n // Pagination\n if (this._offset > 0 || this._limit !== null) {\n const end = this._limit !== null ? this._offset + this._limit : undefined\n items = items.slice(this._offset, end)\n }\n\n // Resolve relations (after pagination for efficiency)\n if (this._includes.length > 0 && this._resolver) {\n items = items.map(item => this._resolveIncludes(item))\n }\n\n return items\n }\n\n first(): T | undefined {\n return this.all()[0]\n }\n\n private _resolveData(): T[] {\n if (this._locale) {\n return [...(this._data.get(this._locale) ?? [])]\n }\n if (this._defaultLocale) {\n const defaultData = this._data.get(this._defaultLocale)\n if (defaultData) return [...defaultData]\n }\n const firstKey = this._data.keys().next().value\n if (firstKey !== undefined) {\n return [...(this._data.get(firstKey) ?? [])]\n }\n return []\n }\n\n private _resolveIncludes(item: T): T {\n const resolved = { ...item }\n const src = item as Record<string, unknown>\n const dst = resolved as Record<string, unknown>\n for (const field of this._includes) {\n const meta = this._relationMeta[field]\n if (!meta) continue\n const targets = Array.isArray(meta.target) ? meta.target : [meta.target]\n\n if (meta.multi) {\n const ids = src[field]\n if (Array.isArray(ids)) {\n dst[field] = ids.map((id) => {\n if (typeof id === 'string') {\n return this._resolveId(targets, id) ?? id\n }\n if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n return this._resolveId([polyObj.model], polyObj.ref) ?? id\n }\n return id\n })\n }\n } else {\n const id = src[field]\n if (typeof id === 'string') {\n dst[field] = this._resolveId(targets, id) ?? id\n } else if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n dst[field] = this._resolveId([polyObj.model], polyObj.ref) ?? id\n }\n }\n }\n return resolved\n }\n\n private _resolveId(targets: string[], id: string): Record<string, unknown> | undefined {\n const loc = this._locale ?? this._defaultLocale\n for (const target of targets) {\n const result = this._resolver!(target, id, loc)\n if (result) return result\n }\n return undefined\n }\n}\n","export class SingletonAccessor<T extends Record<string, unknown>> {\n private _data: Map<string, T>\n private _locale: string | null = null\n private _defaultLocale: string | null\n private _includes: string[] = []\n private _relationMeta: Record<string, { target: string | string[]; multi: boolean }> = {}\n private _resolveEntry?: (model: string, id: string, locale: string) => unknown\n\n constructor(\n data: Map<string, T>,\n defaultLocale?: string,\n relationMeta?: Record<string, { target: string | string[]; multi: boolean }>,\n resolveEntry?: (model: string, id: string, locale: string) => unknown,\n ) {\n this._data = data\n this._defaultLocale = defaultLocale ?? null\n if (relationMeta) this._relationMeta = relationMeta\n this._resolveEntry = resolveEntry\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n include(...fields: string[]): this {\n this._includes.push(...fields)\n return this\n }\n\n get(): T {\n if (this._locale) {\n const d = this._data.get(this._locale)\n if (!d) throw new Error(`No data for locale \"${this._locale}\"`)\n if (this._includes.length > 0) return this._resolveIncludes(d, this._locale)\n return d\n }\n\n const locale = this._defaultLocale ?? undefined\n let data: T | undefined\n\n if (locale) {\n data = this._data.get(locale)\n }\n if (!data) {\n const firstKey = this._data.keys().next().value\n if (firstKey !== undefined) {\n data = this._data.get(firstKey)\n }\n }\n if (!data) throw new Error('No data available')\n\n if (this._includes.length > 0) {\n return this._resolveIncludes(data, locale ?? 'en')\n }\n return data\n }\n\n private _resolveIncludes(item: T, locale: string): T {\n if (!this._resolveEntry || this._includes.length === 0) return item\n const resolved = { ...item }\n const src = item as Record<string, unknown>\n const dst = resolved as Record<string, unknown>\n\n for (const field of this._includes) {\n const meta = this._relationMeta[field]\n if (!meta) continue\n const targets = Array.isArray(meta.target) ? meta.target : [meta.target]\n\n if (meta.multi) {\n const ids = src[field]\n if (Array.isArray(ids)) {\n dst[field] = ids.map((id) => {\n if (typeof id === 'string') {\n return this._resolveId(targets, id, locale) ?? id\n }\n if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n return this._resolveId([polyObj.model], polyObj.ref, locale) ?? id\n }\n return id\n })\n }\n } else {\n const id = src[field]\n if (typeof id === 'string') {\n dst[field] = this._resolveId(targets, id, locale) ?? id\n } else if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n dst[field] = this._resolveId([polyObj.model], polyObj.ref, locale) ?? id\n }\n }\n }\n\n return resolved\n }\n\n private _resolveId(targets: string[], id: string, locale: string): unknown {\n if (!this._resolveEntry) return undefined\n for (const model of targets) {\n const result = this._resolveEntry(model, id, locale)\n if (result) return result\n }\n return undefined\n }\n}\n","export class DictionaryAccessor {\n private _data: Map<string, Record<string, string>>\n private _locale: string | null = null\n private _defaultLocale: string | null\n\n constructor(data: Map<string, Record<string, string>>, defaultLocale?: string) {\n this._data = data\n this._defaultLocale = defaultLocale ?? null\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n get(): Record<string, string>\n get(key: string): string | undefined\n get(key: string, params: Record<string, string | number>): string\n get(key?: string, params?: Record<string, string | number>): Record<string, string> | string | undefined {\n const dict = this._resolveData()\n if (key === undefined) return dict\n const value = dict[key]\n if (value === undefined) return undefined\n if (params) return interpolate(value, params)\n return value\n }\n\n private _resolveData(): Record<string, string> {\n if (this._locale) {\n return this._data.get(this._locale) ?? {}\n }\n if (this._defaultLocale) {\n const d = this._data.get(this._defaultLocale)\n if (d) return d\n }\n const firstKey = this._data.keys().next().value\n if (firstKey !== undefined) {\n return this._data.get(firstKey) ?? {}\n }\n return {}\n }\n}\n\nfunction interpolate(template: string, params: Record<string, string | number>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => {\n const val = params[key]\n return val !== undefined ? String(val) : match\n })\n}\n","import type { RelationMeta, RelationResolver } from './query.js'\nimport type { WhereOp, WhereClause } from '../shared/where.js'\nimport { applyWhere } from '../shared/where.js'\n\nexport class DocumentQuery<T extends object> {\n private _data: Map<string, T[]>\n private _locale: string | null = null\n private _filters: WhereClause[] = []\n private _sortField: string | null = null\n private _sortOrder: 'asc' | 'desc' = 'asc'\n private _includes: string[] = []\n private _relationMeta: Record<string, RelationMeta>\n private _resolver: RelationResolver | null\n private _defaultLocale: string | null\n\n constructor(\n data: Map<string, T[]>,\n relationMeta?: Record<string, RelationMeta>,\n resolver?: RelationResolver,\n defaultLocale?: string,\n ) {\n this._data = data\n this._relationMeta = relationMeta ?? {}\n this._resolver = resolver ?? null\n this._defaultLocale = defaultLocale ?? null\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n where<K extends string & keyof T>(field: K, value: T[K]): this\n where<K extends string & keyof T>(field: K, op: WhereOp, value: unknown): this\n where<K extends string & keyof T>(field: K, opOrValue: WhereOp | T[K], value?: unknown): this {\n if (value !== undefined) {\n this._filters.push({ field, op: opOrValue as WhereOp, value })\n } else {\n this._filters.push({ field, op: 'eq', value: opOrValue })\n }\n return this\n }\n\n sort<K extends string & keyof T>(field: K, order: 'asc' | 'desc' = 'asc'): this {\n this._sortField = field\n this._sortOrder = order\n return this\n }\n\n include(...fields: string[]): this {\n this._includes.push(...fields)\n return this\n }\n\n bySlug(slug: string): T | undefined {\n const items = this._resolveData()\n const item = items.find(i => (i as Record<string, unknown>)['slug'] === slug)\n if (item && this._includes.length > 0 && this._resolver) {\n return this._resolveIncludes(item)\n }\n return item\n }\n\n count(): number {\n return this.all().length\n }\n\n all(): T[] {\n let items = this._resolveData()\n for (const clause of this._filters) {\n items = items.filter(item => applyWhere(item, clause))\n }\n if (this._sortField) {\n const sf = this._sortField\n const dir = this._sortOrder === 'asc' ? 1 : -1\n items = items.toSorted((a, b) => {\n const va = (a as Record<string, unknown>)[sf] as number | string | null | undefined\n const vb = (b as Record<string, unknown>)[sf] as number | string | null | undefined\n if (va == null && vb == null) return 0\n if (va == null) return dir\n if (vb == null) return -dir\n return va < vb ? -dir : va > vb ? dir : 0\n })\n }\n if (this._includes.length > 0 && this._resolver) {\n items = items.map(item => this._resolveIncludes(item))\n }\n return items\n }\n\n first(): T | undefined {\n return this.all()[0]\n }\n\n private _resolveData(): T[] {\n if (this._locale) {\n return [...(this._data.get(this._locale) ?? [])]\n }\n if (this._defaultLocale) {\n const defaultData = this._data.get(this._defaultLocale)\n if (defaultData) return [...defaultData]\n }\n const firstKey = this._data.keys().next().value\n if (firstKey !== undefined) {\n return [...(this._data.get(firstKey) ?? [])]\n }\n return []\n }\n\n private _resolveIncludes(item: T): T {\n const resolved = { ...item }\n const src = item as Record<string, unknown>\n const dst = resolved as Record<string, unknown>\n for (const field of this._includes) {\n const meta = this._relationMeta[field]\n if (!meta) continue\n const targets = Array.isArray(meta.target) ? meta.target : [meta.target]\n\n if (meta.multi) {\n const ids = src[field]\n if (Array.isArray(ids)) {\n dst[field] = ids.map((id) => {\n if (typeof id === 'string') {\n return this._resolveId(targets, id) ?? id\n }\n if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n return this._resolveId([polyObj.model], polyObj.ref) ?? id\n }\n return id\n })\n }\n } else {\n const id = src[field]\n if (typeof id === 'string') {\n dst[field] = this._resolveId(targets, id) ?? id\n } else if (typeof id === 'object' && id !== null && 'model' in id && 'ref' in id) {\n const polyObj = id as { model: string; ref: string }\n dst[field] = this._resolveId([polyObj.model], polyObj.ref) ?? id\n }\n }\n }\n return resolved\n }\n\n private _resolveId(targets: string[], id: string): Record<string, unknown> | undefined {\n const loc = this._locale ?? this._defaultLocale\n for (const target of targets) {\n const result = this._resolver!(target, id, loc)\n if (result) return result\n }\n return undefined\n }\n}\n","// Runtime exports — used by framework SDK authors and generated client\nexport { QueryBuilder } from './runtime/query.js'\nexport type { RelationMeta, RelationResolver, WhereOp } from './runtime/query.js'\nexport { SingletonAccessor } from './runtime/singleton.js'\nexport { DictionaryAccessor } from './runtime/dictionary.js'\nexport { DocumentQuery } from './runtime/document.js'\n\n// Shared utilities\nexport type { WhereClause } from './shared/where.js'\nexport { applyWhere } from './shared/where.js'\n\n// Re-export types from @contentrain/types that SDK consumers need\nexport type {\n FieldType,\n ModelKind,\n ContentStatus,\n FieldDef,\n ModelDefinition,\n ContentrainConfig,\n} from '@contentrain/types'\n\n/**\n * Factory for framework SDK authors.\n * Returns the generated client module loaded from .contentrain/client/.\n *\n * Usage (Nuxt composable):\n * ```ts\n * import { createContentrainClient } from '@contentrain/query'\n * const client = createContentrainClient()\n * const posts = client.query('blog-post').locale('en').all()\n * ```\n */\nexport async function createContentrainClient(\n projectRoot?: string,\n): Promise<{\n query: (model: string) => import('./runtime/query.js').QueryBuilder<Record<string, unknown>>\n singleton: (model: string) => import('./runtime/singleton.js').SingletonAccessor<Record<string, unknown>>\n dictionary: (model: string) => import('./runtime/dictionary.js').DictionaryAccessor\n document: (model: string) => import('./runtime/document.js').DocumentQuery<Record<string, unknown>>\n}> {\n const { resolve } = await import('node:path')\n const { pathToFileURL } = await import('node:url')\n const root = projectRoot ?? process.cwd()\n const clientPath = resolve(root, '.contentrain', 'client', 'index.mjs')\n const client = await import(pathToFileURL(clientPath).href)\n return client\n}\n\n// CDN client factory — async, HTTP-based\nexport { createContentrain } from './cdn/index.js'\nexport type { ContentrainCDNConfig, ContentrainCDNClient } from './cdn/index.js'\nexport type { DocumentIndexEntry } from './cdn/data-source.js'\nexport { ContentrainError } from './cdn/errors.js'\n\n// CDN module re-exports — media, forms, comments, metadata\nexport { MediaAccessor } from './cdn/media-accessor.js'\nexport type { MediaAsset, MediaAssetMeta, MediaManifest } from './cdn/media-accessor.js'\nexport { FormsClient } from './cdn/forms-client.js'\nexport type { FormConfig, FormFieldConfig, FormFieldError, FormSubmitOptions, FormSubmitResult, FormsClientConfig } from './cdn/forms-client.js'\nexport { CommentsClient } from './cdn/comments-client.js'\nexport type {\n CommentAuthor,\n CommentFieldError,\n CommentSubmission,\n CommentSubmitResult,\n CommentThread,\n CommentThreadConfig,\n CommentThreadQuery,\n CommentsClientConfig,\n PublicComment,\n} from './cdn/comments-client.js'\nexport type { EntryMeta } from './cdn/collection-query.js'\nexport { ConversationClient } from './cdn/conversation-client.js'\nexport type {\n ConversationClientConfig,\n ConversationResponse,\n ConversationMessage,\n ConversationHistory,\n} from './cdn/conversation-client.js'\n\n// Sync factory for CJS — requires generated client to be pre-loaded\nexport { createContentrainClient as default }\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/query",
3
- "version": "7.0.15",
3
+ "version": "7.2.0",
4
4
  "license": "MIT",
5
5
  "description": "Optional type-safe query SDK for Contentrain — generated TypeScript client for platform-independent JSON content",
6
6
  "type": "module",
@@ -39,33 +39,57 @@
39
39
  },
40
40
  "exports": {
41
41
  ".": {
42
- "types": "./dist/index.d.ts",
43
- "import": "./dist/index.mjs",
44
- "require": "./dist/index.cjs",
45
- "default": "./dist/index.mjs"
42
+ "import": {
43
+ "types": "./dist/index.d.mts",
44
+ "default": "./dist/index.mjs"
45
+ },
46
+ "require": {
47
+ "types": "./dist/index.d.cts",
48
+ "default": "./dist/index.cjs"
49
+ }
46
50
  },
47
51
  "./generate": {
48
- "types": "./dist/generator/generate.d.ts",
49
- "import": "./dist/generator/generate.mjs",
50
- "require": "./dist/generator/generate.cjs"
52
+ "import": {
53
+ "types": "./dist/generator/generate.d.mts",
54
+ "default": "./dist/generator/generate.mjs"
55
+ },
56
+ "require": {
57
+ "types": "./dist/generator/generate.d.cts",
58
+ "default": "./dist/generator/generate.cjs"
59
+ }
51
60
  },
52
61
  "./cdn": {
53
- "types": "./dist/cdn/index.d.ts",
54
- "import": "./dist/cdn/index.mjs",
55
- "require": "./dist/cdn/index.cjs"
62
+ "import": {
63
+ "types": "./dist/cdn/index.d.mts",
64
+ "default": "./dist/cdn/index.mjs"
65
+ },
66
+ "require": {
67
+ "types": "./dist/cdn/index.d.cts",
68
+ "default": "./dist/cdn/index.cjs"
69
+ }
70
+ },
71
+ "./astro": {
72
+ "import": {
73
+ "types": "./dist/astro/index.d.mts",
74
+ "default": "./dist/astro/index.mjs"
75
+ },
76
+ "require": {
77
+ "types": "./dist/astro/index.d.cts",
78
+ "default": "./dist/astro/index.cjs"
79
+ }
56
80
  },
57
81
  "./skills/*": "./skills/*"
58
82
  },
59
83
  "main": "./dist/index.cjs",
60
84
  "module": "./dist/index.mjs",
61
- "types": "./dist/index.d.ts",
85
+ "types": "./dist/index.d.cts",
62
86
  "sideEffects": false,
63
87
  "files": [
64
88
  "dist",
65
89
  "skills"
66
90
  ],
67
91
  "dependencies": {
68
- "@contentrain/types": "1.10.0"
92
+ "@contentrain/types": "1.11.0"
69
93
  },
70
94
  "devDependencies": {
71
95
  "@types/node": "^22.0.0",
@@ -74,8 +98,8 @@
74
98
  "vitest": "^3.0.0"
75
99
  },
76
100
  "scripts": {
77
- "build": "tsdown src/index.ts src/cdn/index.ts src/generator/generate.ts src/cli.ts --format esm,cjs --dts",
78
- "dev": "tsdown src/index.ts src/cdn/index.ts src/generator/generate.ts src/cli.ts --format esm,cjs --dts --watch",
101
+ "build": "tsdown src/index.ts src/cdn/index.ts src/astro/index.ts src/generator/generate.ts src/cli.ts --format esm,cjs --dts",
102
+ "dev": "tsdown src/index.ts src/cdn/index.ts src/astro/index.ts src/generator/generate.ts src/cli.ts --format esm,cjs --dts --watch",
79
103
  "test": "vitest run",
80
104
  "typecheck": "tsc --noEmit",
81
105
  "clean": "rm -rf dist"
@@ -1 +0,0 @@
1
- {"version":3,"file":"cdn-C8dqHhdG.mjs","names":[],"sources":["../src/shared/where.ts","../src/cdn/errors.ts","../src/cdn/http-transport.ts","../src/cdn/collection-query.ts","../src/cdn/singleton-accessor.ts","../src/cdn/dictionary-accessor.ts","../src/cdn/document-query.ts","../src/cdn/media-accessor.ts","../src/cdn/forms-client.ts","../src/cdn/conversation-client.ts","../src/cdn/index.ts"],"sourcesContent":["export type WhereOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'contains'\n\nexport interface WhereClause {\n field: string\n op: WhereOp\n value: unknown\n}\n\nexport function applyWhere<T>(item: T, clause: WhereClause): boolean {\n const val = (item as Record<string, unknown>)[clause.field]\n switch (clause.op) {\n case 'eq': {\n if (Array.isArray(val)) return val.includes(clause.value)\n return val === clause.value\n }\n case 'ne': {\n if (Array.isArray(val)) return !val.includes(clause.value)\n return val !== clause.value\n }\n case 'gt': return (val as number) > (clause.value as number)\n case 'gte': return (val as number) >= (clause.value as number)\n case 'lt': return (val as number) < (clause.value as number)\n case 'lte': return (val as number) <= (clause.value as number)\n case 'in': return Array.isArray(clause.value) && (clause.value as unknown[]).includes(val)\n case 'contains': {\n if (typeof val === 'string') return val.includes(clause.value as string)\n if (Array.isArray(val)) return val.includes(clause.value)\n return false\n }\n default: return true\n }\n}\n","export class ContentrainError extends Error {\n constructor(\n public status: number,\n message: string,\n ) {\n super(message)\n this.name = 'ContentrainError'\n }\n}\n","import { ContentrainError } from './errors.js'\nimport type { CollectionDataSource, SingletonDataSource, DictionaryDataSource, DocumentDataSource, DocumentIndexEntry } from './data-source.js'\n\ninterface CacheEntry {\n data: unknown\n etag: string\n}\n\nexport interface TransportConfig {\n baseUrl: string\n projectId: string\n apiKey: string\n /** Bundle preload mode. `true` → `{ revalidateMs: 60_000 }` */\n bundle?: boolean | { revalidateMs?: number }\n defaultLocale?: string\n}\n\ninterface BundleState {\n fetchedAt: number\n paths: Set<string>\n missing: boolean\n inflight: Promise<void> | null\n}\n\ninterface BundlePayload {\n version?: string\n paths?: Record<string, unknown>\n}\n\n/** Paths eligible for bundle serving — everything else (manifests, models/*) has no locale segment. */\nconst BUNDLE_SCOPE = /^(content|documents|meta)\\//\n\nexport class HttpTransport {\n private _baseUrl: string\n private _projectId: string\n private _apiKey: string\n private _cache = new Map<string, CacheEntry>()\n private _bundleMode: boolean\n private _revalidateMs: number\n private _defaultLocale: string\n private _primed = new Map<string, unknown>()\n private _bundles = new Map<string, BundleState>()\n\n constructor(config: TransportConfig) {\n this._baseUrl = config.baseUrl.replace(/\\/+$/, '')\n this._projectId = config.projectId\n this._apiKey = config.apiKey\n const b = config.bundle\n this._bundleMode = !!b\n this._revalidateMs = typeof b === 'object' && typeof b.revalidateMs === 'number' ? b.revalidateMs : 60_000\n this._defaultLocale = config.defaultLocale ?? 'en'\n }\n\n buildUrl(path: string): string {\n return `${this._baseUrl}/${this._projectId}/${path}`\n }\n\n /** Eager warmup (e.g. SSR boot). Resolves `true` when a bundle was found and primed. */\n async preload(locale?: string): Promise<boolean> {\n if (!this._bundleMode) return false\n const l = locale ?? this._defaultLocale\n await this._ensureBundle(l)\n return !this._bundles.get(l)?.missing\n }\n\n async fetch<T>(path: string): Promise<T> {\n if (this._bundleMode && BUNDLE_SCOPE.test(path)) {\n await this._ensureBundle(this._localeOf(path))\n if (this._primed.has(path)) return this._primed.get(path) as T\n // out-of-scope path (doc body, meta, ...) → regular per-path fetch\n }\n return this._networkFetch<T>(path)\n }\n\n /** Locale from a path's last segment (sans `.json`). `data` (non-i18n) → defaultLocale bundle. */\n private _localeOf(path: string): string {\n const last = path.slice(path.lastIndexOf('/') + 1).replace(/\\.json$/, '')\n return last === 'data' ? this._defaultLocale : last\n }\n\n private _ensureBundle(locale: string): Promise<void> | void {\n const state = this._bundles.get(locale)\n if (state?.inflight) return state.inflight\n if (state && Date.now() - state.fetchedAt < this._revalidateMs) return\n\n const next: BundleState = state ?? { fetchedAt: 0, paths: new Set(), missing: false, inflight: null }\n this._bundles.set(locale, next)\n next.inflight = (async () => {\n try {\n // _networkFetch is conditional: unchanged bundle → 304 → cached payload (cheap)\n const bundle = await this._networkFetch<BundlePayload>(`_bundle/${locale}.json`)\n if (bundle?.version !== '1' || !bundle.paths || typeof bundle.paths !== 'object') {\n next.missing = true\n return\n }\n // Evict primed paths absent from the fresh bundle (deleted models must not serve stale)\n const fresh = new Set(Object.keys(bundle.paths))\n for (const p of next.paths) {\n if (!fresh.has(p)) this._primed.delete(p)\n }\n for (const [p, body] of Object.entries(bundle.paths)) this._primed.set(p, body)\n next.paths = fresh\n next.missing = false\n }\n catch {\n // 404 (bundle not built yet) or network error → per-path fallback until next revalidate\n next.missing = true\n }\n finally {\n next.fetchedAt = Date.now()\n next.inflight = null\n }\n })()\n return next.inflight\n }\n\n private async _networkFetch<T>(path: string): Promise<T> {\n const url = `${this._baseUrl}/${this._projectId}/${path}`\n const cached = this._cache.get(path)\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this._apiKey}`,\n }\n if (cached?.etag) {\n headers['If-None-Match'] = cached.etag\n }\n\n const res = await globalThis.fetch(url, { headers })\n\n if (res.status === 304 && cached) return cached.data as T\n if (!res.ok) throw new ContentrainError(res.status, await res.text())\n\n const data = (await res.json()) as T\n const etag = res.headers.get('etag') ?? ''\n if (etag) {\n this._cache.set(path, { data, etag })\n }\n return data\n }\n\n collection<T>(modelId: string): CollectionDataSource<T> {\n return {\n getAll: async (locale) => {\n const map = await this.fetch<Record<string, T>>(`content/${modelId}/${locale}.json`)\n return Object.entries(map).map(([id, entry]) => Object.assign({ id }, entry as object) as T)\n },\n getOne: async (id, locale) => {\n const map = await this.fetch<Record<string, T>>(`content/${modelId}/${locale}.json`)\n const entry = map[id]\n return entry ? { id, ...entry as object } as T : null\n },\n }\n }\n\n singleton<T>(modelId: string): SingletonDataSource<T> {\n return {\n get: (locale) => this.fetch<T>(`content/${modelId}/${locale}.json`),\n }\n }\n\n dictionary(modelId: string): DictionaryDataSource {\n return {\n get: (locale) => this.fetch<Record<string, string>>(`content/${modelId}/${locale}.json`),\n }\n }\n\n document<T>(modelId: string): DocumentDataSource<T> {\n return {\n // `_index` carries frontmatter only — the body is in the per-slug document.\n getIndex: (locale) => this.fetch<DocumentIndexEntry<T>[]>(`documents/${modelId}/_index/${locale}.json`),\n getBySlug: (slug, locale) => this.fetch(`documents/${modelId}/${slug}/${locale}.json`),\n }\n }\n}\n","import type { CollectionDataSource } from './data-source.js'\nimport type { HttpTransport } from './http-transport.js'\nimport type { WhereOp, WhereClause } from '../shared/where.js'\nimport { applyWhere } from '../shared/where.js'\n\nexport interface EntryMeta {\n status?: string\n publish_at?: string\n expire_at?: string\n updated_by?: string\n approved_by?: string\n [key: string]: unknown\n}\n\nexport class CdnCollectionQuery<T extends object> {\n private _transport: HttpTransport\n private _source: CollectionDataSource<T>\n private _modelId: string\n private _locale: string = 'en'\n private _filters: WhereClause[] = []\n private _sortField: string | null = null\n private _sortOrder: 'asc' | 'desc' = 'asc'\n private _limit: number | null = null\n private _offset = 0\n private _includes: string[] = []\n private _withMeta = false\n\n constructor(transport: HttpTransport, modelId: string, defaultLocale?: string) {\n this._transport = transport\n this._source = transport.collection<T>(modelId)\n this._modelId = modelId\n if (defaultLocale) this._locale = defaultLocale\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n where(field: string, op: WhereOp, value: unknown): this {\n this._filters.push({ field, op, value })\n return this\n }\n\n sort(field: string, order: 'asc' | 'desc' = 'asc'): this {\n this._sortField = field\n this._sortOrder = order\n return this\n }\n\n limit(n: number): this {\n this._limit = n\n return this\n }\n\n offset(n: number): this {\n this._offset = n\n return this\n }\n\n include(...fields: string[]): this {\n this._includes.push(...fields)\n return this\n }\n\n withMeta(): this {\n this._withMeta = true\n return this\n }\n\n async all(): Promise<T[]> {\n let items = await this._source.getAll(this._locale)\n\n // Filter\n for (const clause of this._filters) {\n items = items.filter(item => applyWhere(item, clause))\n }\n\n // Sort\n if (this._sortField) {\n const field = this._sortField\n const dir = this._sortOrder === 'asc' ? 1 : -1\n items = items.toSorted((a, b) => {\n const va = (a as Record<string, unknown>)[field]\n const vb = (b as Record<string, unknown>)[field]\n if (va == null && vb == null) return 0\n if (va == null) return dir\n if (vb == null) return -dir\n if (va < vb) return -dir\n if (va > vb) return dir\n return 0\n })\n }\n\n // Pagination\n if (this._offset > 0 || this._limit !== null) {\n const end = this._limit !== null ? this._offset + this._limit : undefined\n items = items.slice(this._offset, end)\n }\n\n // Resolve relations\n if (this._includes.length > 0) {\n items = await this._resolveIncludes(items)\n }\n\n // Enrich with entry metadata\n if (this._withMeta) {\n items = await this._enrichMeta(items)\n }\n\n return items\n }\n\n async count(): Promise<number> {\n const items = await this.all()\n return items.length\n }\n\n async first(): Promise<T | undefined> {\n const items = await this.all()\n return items[0]\n }\n\n private async _resolveIncludes(items: T[]): Promise<T[]> {\n // Prefetch related collections to avoid N+1\n const cache = new Map<string, Map<string, Record<string, unknown>>>()\n\n for (const field of this._includes) {\n // Collect all IDs for this field\n for (const item of items) {\n const val = (item as Record<string, unknown>)[field]\n const ids = Array.isArray(val) ? val : val ? [val] : []\n for (const id of ids) {\n if (typeof id !== 'string') continue\n // We don't know the target model from here, so we use field name as hint\n // In production, model metadata would provide this mapping\n if (!cache.has(field)) {\n try {\n const related = await this._transport.fetch<Record<string, unknown>>(`content/${field}/${this._locale}.json`)\n const map = new Map<string, Record<string, unknown>>()\n for (const [entryId, entry] of Object.entries(related)) {\n map.set(entryId, { id: entryId, ...entry as object })\n }\n cache.set(field, map)\n } catch {\n cache.set(field, new Map())\n }\n break\n }\n }\n }\n }\n\n return items.map(item => {\n const resolved = { ...item }\n const dst = resolved as Record<string, unknown>\n for (const field of this._includes) {\n const related = cache.get(field)\n if (!related) continue\n const val = (item as Record<string, unknown>)[field]\n if (Array.isArray(val)) {\n dst[field] = val.map(id => typeof id === 'string' ? (related.get(id) ?? id) : id)\n } else if (typeof val === 'string') {\n dst[field] = related.get(val) ?? val\n }\n }\n return resolved\n })\n }\n\n private async _enrichMeta(items: T[]): Promise<T[]> {\n let metaMap: Record<string, EntryMeta> = {}\n try {\n metaMap = await this._transport.fetch<Record<string, EntryMeta>>(`meta/${this._modelId}/${this._locale}.json`)\n } catch {\n // No meta available — return items unchanged\n return items\n }\n return items.map(item => {\n const id = (item as Record<string, unknown>).id as string\n const meta = id ? metaMap[id] : undefined\n if (meta) {\n return { ...item, _meta: meta }\n }\n return item\n })\n }\n}\n\n","import type { SingletonDataSource } from './data-source.js'\n\nexport class CdnSingletonAccessor<T extends Record<string, unknown>> {\n private _source: SingletonDataSource<T>\n private _locale: string = 'en'\n\n constructor(source: SingletonDataSource<T>, defaultLocale?: string) {\n this._source = source\n if (defaultLocale) this._locale = defaultLocale\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n async get(): Promise<T> {\n return this._source.get(this._locale)\n }\n}\n","import type { DictionaryDataSource } from './data-source.js'\n\nexport class CdnDictionaryAccessor {\n private _source: DictionaryDataSource\n private _locale: string = 'en'\n\n constructor(source: DictionaryDataSource, defaultLocale?: string) {\n this._source = source\n if (defaultLocale) this._locale = defaultLocale\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n async get(): Promise<Record<string, string>>\n async get(key: string): Promise<string | undefined>\n async get(key: string, params: Record<string, string | number>): Promise<string>\n async get(key?: string, params?: Record<string, string | number>): Promise<Record<string, string> | string | undefined> {\n const dict = await this._source.get(this._locale)\n if (key === undefined) return dict\n const value = dict[key]\n if (value === undefined) return undefined\n if (params) return interpolate(value, params)\n return value\n }\n}\n\nfunction interpolate(template: string, params: Record<string, string | number>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => {\n const val = params[key]\n return val !== undefined ? String(val) : match\n })\n}\n","import type { DocumentDataSource, DocumentIndexEntry } from './data-source.js'\nimport type { WhereOp, WhereClause } from '../shared/where.js'\nimport { applyWhere } from '../shared/where.js'\n\nexport class CdnDocumentQuery<T extends object> {\n private _source: DocumentDataSource<T>\n private _locale: string = 'en'\n private _filters: WhereClause[] = []\n private _sortField: string | null = null\n private _sortOrder: 'asc' | 'desc' = 'asc'\n\n constructor(source: DocumentDataSource<T>, defaultLocale?: string) {\n this._source = source\n if (defaultLocale) this._locale = defaultLocale\n }\n\n locale(lang: string): this {\n this._locale = lang\n return this\n }\n\n where(field: string, op: WhereOp, value: unknown): this {\n this._filters.push({ field, op, value })\n return this\n }\n\n sort(field: string, order: 'asc' | 'desc' = 'asc'): this {\n this._sortField = field\n this._sortOrder = order\n return this\n }\n\n /**\n * Every entry's frontmatter, from the model's `_index`.\n *\n * Bodies are not included — fetch one with {@link bySlug}. See\n * {@link DocumentIndexEntry}.\n */\n async all(): Promise<DocumentIndexEntry<T>[]> {\n let items = await this._source.getIndex(this._locale)\n\n for (const clause of this._filters) {\n items = items.filter(item => applyWhere(item, clause))\n }\n\n if (this._sortField) {\n const sf = this._sortField\n const dir = this._sortOrder === 'asc' ? 1 : -1\n items = items.toSorted((a, b) => {\n const va = (a as Record<string, unknown>)[sf] as number | string | null | undefined\n const vb = (b as Record<string, unknown>)[sf] as number | string | null | undefined\n if (va == null && vb == null) return 0\n if (va == null) return dir\n if (vb == null) return -dir\n return va < vb ? -dir : va > vb ? dir : 0\n })\n }\n\n return items\n }\n\n async count(): Promise<number> {\n const items = await this.all()\n return items.length\n }\n\n async first(): Promise<DocumentIndexEntry<T> | undefined> {\n const items = await this.all()\n return items[0]\n }\n\n /** The full document: frontmatter plus its rendered body. */\n async bySlug(slug: string): Promise<{ frontmatter: T; body: string; html: string } | null> {\n return this._source.getBySlug(slug, this._locale)\n }\n}\n","import type { HttpTransport } from './http-transport.js'\n\nexport interface MediaAssetMeta {\n width?: number\n height?: number\n format?: string\n size?: number\n blurhash?: string | null\n alt?: string | null\n}\n\nexport interface MediaAsset {\n original: string\n variants: Record<string, string>\n meta: MediaAssetMeta\n}\n\nexport interface MediaManifest {\n version: string\n assets: Record<string, MediaAsset>\n}\n\nexport class MediaAccessor {\n private _transport: HttpTransport\n private _manifest: MediaManifest | null = null\n\n constructor(transport: HttpTransport) {\n this._transport = transport\n }\n\n async manifest(): Promise<MediaManifest> {\n if (!this._manifest) {\n this._manifest = await this._transport.fetch<MediaManifest>('_media_manifest.json')\n }\n return this._manifest\n }\n\n async assets(): Promise<Record<string, MediaAsset>> {\n const m = await this.manifest()\n return m.assets\n }\n\n async asset(path: string): Promise<MediaAsset | null> {\n const all = await this.assets()\n return all[path] ?? null\n }\n\n async list(): Promise<Array<{ path: string } & MediaAsset>> {\n const all = await this.assets()\n return Object.entries(all).map(([path, asset]) =>\n Object.assign({ path }, asset),\n )\n }\n\n resolve(asset: MediaAsset, variant?: string): string {\n if (variant && asset.variants[variant]) {\n return asset.variants[variant]\n }\n return asset.original\n }\n\n url(asset: MediaAsset, variant?: string): string {\n const path = this.resolve(asset, variant)\n return this._transport.buildUrl(path)\n }\n}\n","import { ContentrainError } from './errors.js'\n\nexport interface FormFieldConfig {\n id: string\n type: string\n required?: boolean\n label?: string\n placeholder?: string\n options?: Array<{ value: string; label: string }>\n pattern?: string\n min?: number\n max?: number\n}\n\nexport interface FormConfig {\n modelId: string\n fields: FormFieldConfig[]\n captchaType?: 'turnstile' | null\n successMessage?: string\n honeypotField?: string\n}\n\nexport interface FormSubmitResult {\n success: boolean\n message?: string\n errors?: Array<{ field: string; message: string }>\n}\n\nexport interface FormsClientConfig {\n baseUrl: string\n projectId: string\n apiKey?: string\n}\n\nexport class FormsClient {\n private _baseUrl: string\n private _projectId: string\n private _apiKey: string | undefined\n\n constructor(config: FormsClientConfig) {\n this._baseUrl = config.baseUrl.replace(/\\/+$/, '')\n this._projectId = config.projectId\n this._apiKey = config.apiKey\n }\n\n async config(modelId: string): Promise<FormConfig> {\n const url = `${this._baseUrl}/${this._projectId}/${modelId}/config`\n const headers: Record<string, string> = {}\n if (this._apiKey) headers['Authorization'] = `Bearer ${this._apiKey}`\n\n const res = await globalThis.fetch(url, { headers })\n if (!res.ok) throw new ContentrainError(res.status, await res.text())\n return (await res.json()) as FormConfig\n }\n\n async submit(modelId: string, data: Record<string, unknown>, options?: {\n captchaToken?: string\n }): Promise<FormSubmitResult> {\n const url = `${this._baseUrl}/${this._projectId}/${modelId}/submit`\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n if (this._apiKey) headers['Authorization'] = `Bearer ${this._apiKey}`\n\n const body: Record<string, unknown> = { ...data }\n if (options?.captchaToken) {\n body['cf-turnstile-response'] = options.captchaToken\n }\n\n const res = await globalThis.fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n const result = (await res.json()) as FormSubmitResult\n\n if (!res.ok && !result.errors) {\n throw new ContentrainError(res.status, result.message ?? 'Form submission failed')\n }\n\n return result\n }\n}\n","import { ContentrainError } from './errors.js'\n\nexport interface ConversationContext {\n activeModelId?: string | null\n activeLocale?: string\n activeEntryId?: string | null\n panelState?: string\n activeBranch?: string | null\n}\n\nexport interface ConversationSendOptions {\n conversationId?: string\n context?: ConversationContext\n}\n\nexport interface ConversationToolResult {\n id: string\n name: string\n result: unknown\n}\n\nexport interface ConversationUsage {\n inputTokens: number\n outputTokens: number\n}\n\nexport interface ConversationResponse {\n conversationId: string\n message: string\n toolResults?: ConversationToolResult[]\n usage: ConversationUsage\n}\n\nexport interface ConversationMessage {\n id: string\n role: 'user' | 'assistant'\n content: string | unknown[]\n toolCalls?: unknown[]\n model?: string\n usage?: ConversationUsage\n createdAt: string\n}\n\nexport interface ConversationHistory {\n conversationId: string\n messages: ConversationMessage[]\n}\n\nexport interface ConversationClientConfig {\n baseUrl: string\n projectId: string\n apiKey: string\n}\n\nexport class ConversationClient {\n private _baseUrl: string\n private _projectId: string\n private _apiKey: string\n\n constructor(config: ConversationClientConfig) {\n this._baseUrl = config.baseUrl.replace(/\\/+$/, '')\n this._projectId = config.projectId\n this._apiKey = config.apiKey\n }\n\n async send(message: string, options?: ConversationSendOptions): Promise<ConversationResponse> {\n const url = `${this._baseUrl}/${this._projectId}/message`\n\n const body: Record<string, unknown> = { message }\n if (options?.conversationId) body.conversationId = options.conversationId\n if (options?.context) body.context = options.context\n\n const res = await globalThis.fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this._apiKey}`,\n },\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n throw new ContentrainError(res.status, await res.text())\n }\n\n return (await res.json()) as ConversationResponse\n }\n\n async history(conversationId: string, options?: { limit?: number }): Promise<ConversationHistory> {\n const params = new URLSearchParams({ conversationId })\n if (options?.limit) params.set('limit', String(options.limit))\n\n const url = `${this._baseUrl}/${this._projectId}/history?${params}`\n\n const res = await globalThis.fetch(url, {\n headers: {\n 'Authorization': `Bearer ${this._apiKey}`,\n },\n })\n\n if (!res.ok) {\n throw new ContentrainError(res.status, await res.text())\n }\n\n return (await res.json()) as ConversationHistory\n }\n}\n","import { HttpTransport } from './http-transport.js'\nimport { CdnCollectionQuery } from './collection-query.js'\nimport { CdnSingletonAccessor } from './singleton-accessor.js'\nimport { CdnDictionaryAccessor } from './dictionary-accessor.js'\nimport { CdnDocumentQuery } from './document-query.js'\nimport { MediaAccessor } from './media-accessor.js'\nimport { FormsClient } from './forms-client.js'\nimport { ConversationClient } from './conversation-client.js'\n\nexport interface ContentrainCDNConfig {\n projectId: string\n apiKey: string\n baseUrl?: string\n defaultLocale?: string\n /** Bundle preload mode. `true` → `{ revalidateMs: 60_000 }` */\n bundle?: boolean | { revalidateMs?: number }\n}\n\nexport type ContentrainCDNClient = ReturnType<typeof createContentrain>\n\nexport function createContentrain(config: ContentrainCDNConfig) {\n const transport = new HttpTransport({\n baseUrl: config.baseUrl ?? 'https://studio.contentrain.io/api/cdn/v1',\n projectId: config.projectId,\n apiKey: config.apiKey,\n bundle: config.bundle,\n defaultLocale: config.defaultLocale,\n })\n const defaultLocale = config.defaultLocale\n\n return {\n collection: <T extends object = Record<string, unknown>>(modelId: string) =>\n new CdnCollectionQuery<T>(transport, modelId, defaultLocale),\n\n singleton: <T extends Record<string, unknown> = Record<string, unknown>>(modelId: string) =>\n new CdnSingletonAccessor<T>(transport.singleton<T>(modelId), defaultLocale),\n\n dictionary: (modelId: string) =>\n new CdnDictionaryAccessor(transport.dictionary(modelId), defaultLocale),\n\n document: <T extends object = Record<string, unknown>>(modelId: string) =>\n new CdnDocumentQuery<T>(transport.document<T>(modelId), defaultLocale),\n\n media: () => new MediaAccessor(transport),\n\n form: () => new FormsClient({\n baseUrl: (config.baseUrl ?? 'https://studio.contentrain.io/api/cdn/v1').replace('/cdn/v1', '/forms/v1'),\n projectId: config.projectId,\n apiKey: config.apiKey,\n }),\n\n conversation: () => new ConversationClient({\n baseUrl: (config.baseUrl ?? 'https://studio.contentrain.io/api/cdn/v1').replace('/cdn/v1', '/conversation/v1'),\n projectId: config.projectId,\n apiKey: config.apiKey,\n }),\n\n manifest: () => transport.fetch<unknown>('_manifest.json'),\n models: () => transport.fetch<unknown[]>('models/_index.json'),\n model: (id: string) => transport.fetch<unknown>(`models/${id}.json`),\n\n preload: (locale?: string) => transport.preload(locale),\n }\n}\n\n// Re-exports\nexport { ContentrainError } from './errors.js'\nexport type { CollectionDataSource, SingletonDataSource, DictionaryDataSource, DocumentDataSource, DocumentIndexEntry } from './data-source.js'\nexport { HttpTransport } from './http-transport.js'\nexport type { TransportConfig } from './http-transport.js'\nexport { CdnCollectionQuery } from './collection-query.js'\nexport { CdnSingletonAccessor } from './singleton-accessor.js'\nexport { CdnDictionaryAccessor } from './dictionary-accessor.js'\nexport { CdnDocumentQuery } from './document-query.js'\nexport { MediaAccessor } from './media-accessor.js'\nexport type { MediaAsset, MediaAssetMeta, MediaManifest } from './media-accessor.js'\nexport { FormsClient } from './forms-client.js'\nexport type { FormConfig, FormFieldConfig, FormSubmitResult, FormsClientConfig } from './forms-client.js'\nexport { ConversationClient } from './conversation-client.js'\nexport type {\n ConversationClientConfig,\n ConversationContext,\n ConversationSendOptions,\n ConversationResponse,\n ConversationToolResult,\n ConversationUsage,\n ConversationMessage,\n ConversationHistory,\n} from './conversation-client.js'\n"],"mappings":"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"}