@contentrain/query 5.1.1 → 5.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,9 +2,16 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/%40contentrain%2Fquery?label=%40contentrain%2Fquery)](https://www.npmjs.com/package/@contentrain/query)
4
4
  [![GitHub source](https://img.shields.io/badge/source-Contentrain%2Fai-181717?logo=github)](https://github.com/Contentrain/ai/tree/main/packages/sdk/js)
5
+ [![Docs](https://img.shields.io/badge/docs-ai.contentrain.io-0f172a)](https://ai.contentrain.io/packages/sdk)
5
6
 
6
7
  **Optional** type-safe generated query SDK for Contentrain.
7
8
 
9
+ Start here:
10
+
11
+ - [2-minute product demo](https://ai.contentrain.io/demo)
12
+ - [SDK docs](https://ai.contentrain.io/packages/sdk)
13
+ - [Framework integration guide](https://ai.contentrain.io/guides/frameworks)
14
+
8
15
  Contentrain stores content as plain JSON and Markdown in a git-backed `.contentrain/` directory. Any platform that reads JSON can consume this content directly. This package adds a TypeScript convenience layer that turns content models into a generated JS/TS client with:
9
16
 
10
17
  - exact TypeScript types from your models
@@ -97,14 +104,25 @@ For collection models.
97
104
  Supported methods:
98
105
 
99
106
  - `locale(lang)`
100
- - `where(field, value)`
107
+ - `where(field, value)` — equality shorthand
108
+ - `where(field, op, value)` — operators: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `contains`
101
109
  - `sort(field, order?)`
102
110
  - `limit(n)`
103
111
  - `offset(n)`
104
112
  - `include(...fields)`
113
+ - `count()`
105
114
  - `first()`
106
115
  - `all()`
107
116
 
117
+ Where operator examples:
118
+
119
+ ```ts
120
+ query('plans').where('slug', 'ne', 'free').all()
121
+ query('plans').where('price', 'gte', 10).where('price', 'lte', 50).all()
122
+ query('starters').where('framework', 'in', ['nuxt', 'next']).all()
123
+ query('blog').where('title', 'contains', 'Guide').count()
124
+ ```
125
+
108
126
  ### `singleton(model)`
109
127
 
110
128
  For singleton models.
@@ -132,9 +150,11 @@ For markdown/document models.
132
150
  Supported methods:
133
151
 
134
152
  - `locale(lang)`
135
- - `where(field, value)`
153
+ - `where(field, value)` — equality shorthand
154
+ - `where(field, op, value)` — same operators as `query()`
136
155
  - `include(...fields)`
137
156
  - `bySlug(slug)`
157
+ - `count()`
138
158
  - `first()`
139
159
  - `all()`
140
160
 
@@ -169,13 +189,14 @@ const posts = client.query('blog-post').locale('en').all()
169
189
 
170
190
  Public root exports:
171
191
 
172
- - `QueryBuilder`
173
- - `SingletonAccessor`
174
- - `DictionaryAccessor`
175
- - `DocumentQuery`
192
+ - `QueryBuilder`, `SingletonAccessor`, `DictionaryAccessor`, `DocumentQuery` — runtime classes
176
193
  - `createContentrainClient` — local generated client loader
177
194
  - `createContentrain` — CDN client factory
195
+ - `MediaAccessor` — CDN media manifest reader
196
+ - `FormsClient` — CDN forms API client
197
+ - `ConversationClient` — Conversation API client
178
198
  - `ContentrainError` — HTTP error class for CDN mode
199
+ - `applyWhere` — shared where filter helper
179
200
 
180
201
  ## CDN Transport
181
202
 
@@ -209,7 +230,88 @@ const filtered = await client.collection('faq')
209
230
  .all()
210
231
  ```
211
232
 
212
- CDN also exposes metadata endpoints:
233
+ CDN collection queries support `count()` and entry metadata:
234
+
235
+ ```ts
236
+ const total = await client.collection('faq').locale('en').count()
237
+
238
+ // Enrich entries with _meta (status, publish_at, expire_at)
239
+ const posts = await client.collection('blog')
240
+ .locale('en')
241
+ .withMeta()
242
+ .all()
243
+ // posts[0]._meta → { status: 'published', publish_at: '...', ... }
244
+ ```
245
+
246
+ ### Media
247
+
248
+ Access the media manifest and resolve asset variant URLs:
249
+
250
+ ```ts
251
+ const media = client.media()
252
+ const assets = await media.list() // All assets with paths
253
+ const asset = await media.asset('hero.jpg') // Single asset
254
+
255
+ // Resolve variant URL
256
+ const thumbUrl = media.url(asset, 'thumb') // Full CDN URL
257
+ const original = media.url(asset) // Original URL
258
+
259
+ // Asset metadata
260
+ asset.meta.width // 1920
261
+ asset.meta.blurhash // 'LEHV6nWB...'
262
+ asset.meta.alt // 'Hero image'
263
+ ```
264
+
265
+ ### Forms
266
+
267
+ Fetch form schema and submit data from external sites:
268
+
269
+ ```ts
270
+ const form = client.form()
271
+
272
+ // Get form field configuration
273
+ const config = await form.config('contact')
274
+ // config.fields → [{ id: 'name', type: 'string', required: true }, ...]
275
+
276
+ // Submit form data
277
+ const result = await form.submit('contact', {
278
+ name: 'Alice',
279
+ email: 'alice@example.com',
280
+ message: 'Hello!',
281
+ }, { captchaToken: 'tok_xxx' })
282
+ // result → { success: true, message: 'Thank you!' }
283
+ ```
284
+
285
+ ### Conversation API
286
+
287
+ Send messages to the AI content agent and manage conversation history:
288
+
289
+ ```ts
290
+ const conv = client.conversation()
291
+
292
+ // Send a message — returns complete response with tool results
293
+ const response = await conv.send('Create a new blog post about Vue 4')
294
+ response.conversationId // 'conv-abc123'
295
+ response.message // 'I created the blog post...'
296
+ response.toolResults // [{ id: 't-1', name: 'save_content', result: {...} }]
297
+ response.usage // { inputTokens: 150, outputTokens: 80 }
298
+
299
+ // Continue a conversation
300
+ const followUp = await conv.send('Now translate it to Turkish', {
301
+ conversationId: response.conversationId,
302
+ })
303
+
304
+ // Provide UI context
305
+ await conv.send('Update the hero section', {
306
+ context: { activeModelId: 'hero', activeLocale: 'en' },
307
+ })
308
+
309
+ // Fetch conversation history
310
+ const history = await conv.history('conv-abc123', { limit: 50 })
311
+ history.messages // [{ id, role, content, createdAt }, ...]
312
+ ```
313
+
314
+ ### Metadata Endpoints
213
315
 
214
316
  ```ts
215
317
  const manifest = await client.manifest()
@@ -270,7 +372,7 @@ Generator entry:
270
372
 
271
373
  CDN transport:
272
374
 
273
- - `@contentrain/query/cdn` — CDN client with `HttpTransport`, async query classes
375
+ - `@contentrain/query/cdn` — CDN client with `HttpTransport`, async query classes, `MediaAccessor`, `FormsClient`, `ConversationClient`
274
376
 
275
377
  ## 🧠 Design Constraints
276
378
 
@@ -1,9 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_cdn = require("../cdn-C8uXJe3A.cjs");
2
+ const require_cdn = require("../cdn-5ycdk2ET.cjs");
3
3
  exports.CdnCollectionQuery = require_cdn.CdnCollectionQuery;
4
4
  exports.CdnDictionaryAccessor = require_cdn.CdnDictionaryAccessor;
5
5
  exports.CdnDocumentQuery = require_cdn.CdnDocumentQuery;
6
6
  exports.CdnSingletonAccessor = require_cdn.CdnSingletonAccessor;
7
7
  exports.ContentrainError = require_cdn.ContentrainError;
8
+ exports.ConversationClient = require_cdn.ConversationClient;
9
+ exports.FormsClient = require_cdn.FormsClient;
8
10
  exports.HttpTransport = require_cdn.HttpTransport;
11
+ exports.MediaAccessor = require_cdn.MediaAccessor;
9
12
  exports.createContentrain = require_cdn.createContentrain;
@@ -1,2 +1,2 @@
1
- import { a as CdnDocumentQuery, c as CdnCollectionQuery, d as DictionaryDataSource, f as DocumentDataSource, i as ContentrainError, l as HttpTransport, n as ContentrainCDNConfig, o as CdnDictionaryAccessor, p as SingletonDataSource, r as createContentrain, s as CdnSingletonAccessor, t as ContentrainCDNClient, u as CollectionDataSource } from "../index-Xjd0isXU.cjs";
2
- export { CdnCollectionQuery, CdnDictionaryAccessor, CdnDocumentQuery, CdnSingletonAccessor, CollectionDataSource, ContentrainCDNClient, ContentrainCDNConfig, ContentrainError, DictionaryDataSource, DocumentDataSource, HttpTransport, SingletonDataSource, createContentrain };
1
+ import { C as CdnDocumentQuery, E as CdnCollectionQuery, F as SingletonDataSource, M as CollectionDataSource, N as DictionaryDataSource, P as DocumentDataSource, S as MediaManifest, T as CdnSingletonAccessor, _ as FormsClient, a as ConversationClient, b as MediaAsset, c as ConversationHistory, d as ConversationSendOptions, f as ConversationToolResult, g as FormSubmitResult, h as FormFieldConfig, i as ContentrainError, j as HttpTransport, l as ConversationMessage, m as FormConfig, n as ContentrainCDNConfig, o as ConversationClientConfig, p as ConversationUsage, r as createContentrain, s as ConversationContext, t as ContentrainCDNClient, u as ConversationResponse, v as FormsClientConfig, w as CdnDictionaryAccessor, x as MediaAssetMeta, y as MediaAccessor } from "../index-BChs94uA.cjs";
2
+ export { CdnCollectionQuery, CdnDictionaryAccessor, CdnDocumentQuery, CdnSingletonAccessor, CollectionDataSource, ContentrainCDNClient, ContentrainCDNConfig, ContentrainError, ConversationClient, ConversationClientConfig, ConversationContext, ConversationHistory, ConversationMessage, ConversationResponse, ConversationSendOptions, ConversationToolResult, ConversationUsage, DictionaryDataSource, DocumentDataSource, FormConfig, FormFieldConfig, FormSubmitResult, FormsClient, FormsClientConfig, HttpTransport, MediaAccessor, MediaAsset, MediaAssetMeta, MediaManifest, SingletonDataSource, createContentrain };
@@ -1,2 +1,2 @@
1
- import { a as CdnDocumentQuery, c as CdnCollectionQuery, d as DictionaryDataSource, f as DocumentDataSource, i as ContentrainError, l as HttpTransport, n as ContentrainCDNConfig, o as CdnDictionaryAccessor, p as SingletonDataSource, r as createContentrain, s as CdnSingletonAccessor, t as ContentrainCDNClient, u as CollectionDataSource } from "../index-D5zB3y75.mjs";
2
- export { CdnCollectionQuery, CdnDictionaryAccessor, CdnDocumentQuery, CdnSingletonAccessor, CollectionDataSource, ContentrainCDNClient, ContentrainCDNConfig, ContentrainError, DictionaryDataSource, DocumentDataSource, HttpTransport, SingletonDataSource, createContentrain };
1
+ import { C as CdnDocumentQuery, E as CdnCollectionQuery, F as SingletonDataSource, M as CollectionDataSource, N as DictionaryDataSource, P as DocumentDataSource, S as MediaManifest, T as CdnSingletonAccessor, _ as FormsClient, a as ConversationClient, b as MediaAsset, c as ConversationHistory, d as ConversationSendOptions, f as ConversationToolResult, g as FormSubmitResult, h as FormFieldConfig, i as ContentrainError, j as HttpTransport, l as ConversationMessage, m as FormConfig, n as ContentrainCDNConfig, o as ConversationClientConfig, p as ConversationUsage, r as createContentrain, s as ConversationContext, t as ContentrainCDNClient, u as ConversationResponse, v as FormsClientConfig, w as CdnDictionaryAccessor, x as MediaAssetMeta, y as MediaAccessor } from "../index-CsCpovuB.mjs";
2
+ export { CdnCollectionQuery, CdnDictionaryAccessor, CdnDocumentQuery, CdnSingletonAccessor, CollectionDataSource, ContentrainCDNClient, ContentrainCDNConfig, ContentrainError, ConversationClient, ConversationClientConfig, ConversationContext, ConversationHistory, ConversationMessage, ConversationResponse, ConversationSendOptions, ConversationToolResult, ConversationUsage, DictionaryDataSource, DocumentDataSource, FormConfig, FormFieldConfig, FormSubmitResult, FormsClient, FormsClientConfig, HttpTransport, MediaAccessor, MediaAsset, MediaAssetMeta, MediaManifest, SingletonDataSource, createContentrain };
@@ -1,2 +1,2 @@
1
- import { a as CdnCollectionQuery, i as CdnSingletonAccessor, n as CdnDocumentQuery, o as HttpTransport, r as CdnDictionaryAccessor, s as ContentrainError, t as createContentrain } from "../cdn-D66-Npqt.mjs";
2
- export { CdnCollectionQuery, CdnDictionaryAccessor, CdnDocumentQuery, CdnSingletonAccessor, ContentrainError, HttpTransport, createContentrain };
1
+ import { a as CdnDocumentQuery, c as CdnCollectionQuery, i as MediaAccessor, l as HttpTransport, n as ConversationClient, o as CdnDictionaryAccessor, r as FormsClient, s as CdnSingletonAccessor, t as createContentrain, u as ContentrainError } from "../cdn-SOuikUcY.mjs";
2
+ export { CdnCollectionQuery, CdnDictionaryAccessor, CdnDocumentQuery, CdnSingletonAccessor, ContentrainError, ConversationClient, FormsClient, HttpTransport, MediaAccessor, createContentrain };
@@ -1,3 +1,24 @@
1
+ //#region src/shared/where.ts
2
+ function applyWhere(item, clause) {
3
+ const val = item[clause.field];
4
+ switch (clause.op) {
5
+ case "eq":
6
+ if (Array.isArray(val)) return val.includes(clause.value);
7
+ return val === clause.value;
8
+ case "ne": return val !== clause.value;
9
+ case "gt": return val > clause.value;
10
+ case "gte": return val >= clause.value;
11
+ case "lt": return val < clause.value;
12
+ case "lte": return val <= clause.value;
13
+ case "in": return Array.isArray(clause.value) && clause.value.includes(val);
14
+ case "contains":
15
+ if (typeof val === "string") return val.includes(clause.value);
16
+ if (Array.isArray(val)) return val.includes(clause.value);
17
+ return false;
18
+ default: return true;
19
+ }
20
+ }
21
+ //#endregion
1
22
  //#region src/cdn/errors.ts
2
23
  var ContentrainError = class extends Error {
3
24
  constructor(status, message) {
@@ -18,6 +39,9 @@ var HttpTransport = class {
18
39
  this._projectId = config.projectId;
19
40
  this._apiKey = config.apiKey;
20
41
  }
42
+ buildUrl(path) {
43
+ return `${this._baseUrl}/${this._projectId}/${path}`;
44
+ }
21
45
  async fetch(path) {
22
46
  const url = `${this._baseUrl}/${this._projectId}/${path}`;
23
47
  const cached = this._cache.get(path);
@@ -75,6 +99,7 @@ var CdnCollectionQuery = class {
75
99
  _limit = null;
76
100
  _offset = 0;
77
101
  _includes = [];
102
+ _withMeta = false;
78
103
  constructor(transport, modelId, defaultLocale) {
79
104
  this._transport = transport;
80
105
  this._source = transport.collection(modelId);
@@ -110,9 +135,13 @@ var CdnCollectionQuery = class {
110
135
  this._includes.push(...fields);
111
136
  return this;
112
137
  }
138
+ withMeta() {
139
+ this._withMeta = true;
140
+ return this;
141
+ }
113
142
  async all() {
114
143
  let items = await this._source.getAll(this._locale);
115
- for (const clause of this._filters) items = items.filter((item) => applyWhere$1(item, clause));
144
+ for (const clause of this._filters) items = items.filter((item) => applyWhere(item, clause));
116
145
  if (this._sortField) {
117
146
  const field = this._sortField;
118
147
  const dir = this._sortOrder === "asc" ? 1 : -1;
@@ -132,8 +161,12 @@ var CdnCollectionQuery = class {
132
161
  items = items.slice(this._offset, end);
133
162
  }
134
163
  if (this._includes.length > 0) items = await this._resolveIncludes(items);
164
+ if (this._withMeta) items = await this._enrichMeta(items);
135
165
  return items;
136
166
  }
167
+ async count() {
168
+ return (await this.all()).length;
169
+ }
137
170
  async first() {
138
171
  return (await this.all())[0];
139
172
  }
@@ -173,24 +206,24 @@ var CdnCollectionQuery = class {
173
206
  return resolved;
174
207
  });
175
208
  }
176
- };
177
- function applyWhere$1(item, clause) {
178
- const val = item[clause.field];
179
- switch (clause.op) {
180
- case "eq": return val === clause.value;
181
- case "ne": return val !== clause.value;
182
- case "gt": return val > clause.value;
183
- case "gte": return val >= clause.value;
184
- case "lt": return val < clause.value;
185
- case "lte": return val <= clause.value;
186
- case "in": return Array.isArray(clause.value) && clause.value.includes(val);
187
- case "contains":
188
- if (typeof val === "string") return val.includes(clause.value);
189
- if (Array.isArray(val)) return val.includes(clause.value);
190
- return false;
191
- default: return true;
209
+ async _enrichMeta(items) {
210
+ let metaMap = {};
211
+ try {
212
+ metaMap = await this._transport.fetch(`meta/${this._modelId}/${this._locale}.json`);
213
+ } catch {
214
+ return items;
215
+ }
216
+ return items.map((item) => {
217
+ const id = item.id;
218
+ const meta = id ? metaMap[id] : void 0;
219
+ if (meta) return {
220
+ ...item,
221
+ _meta: meta
222
+ };
223
+ return item;
224
+ });
192
225
  }
193
- }
226
+ };
194
227
  //#endregion
195
228
  //#region src/cdn/singleton-accessor.ts
196
229
  var CdnSingletonAccessor = class {
@@ -263,6 +296,9 @@ var CdnDocumentQuery = class {
263
296
  for (const clause of this._filters) items = items.filter((item) => applyWhere(item, clause));
264
297
  return items;
265
298
  }
299
+ async count() {
300
+ return (await this.all()).length;
301
+ }
266
302
  async first() {
267
303
  return (await this.all())[0];
268
304
  }
@@ -270,23 +306,108 @@ var CdnDocumentQuery = class {
270
306
  return this._source.getBySlug(slug, this._locale);
271
307
  }
272
308
  };
273
- function applyWhere(item, clause) {
274
- const val = item[clause.field];
275
- switch (clause.op) {
276
- case "eq": return val === clause.value;
277
- case "ne": return val !== clause.value;
278
- case "gt": return val > clause.value;
279
- case "gte": return val >= clause.value;
280
- case "lt": return val < clause.value;
281
- case "lte": return val <= clause.value;
282
- case "in": return Array.isArray(clause.value) && clause.value.includes(val);
283
- case "contains":
284
- if (typeof val === "string") return val.includes(clause.value);
285
- if (Array.isArray(val)) return val.includes(clause.value);
286
- return false;
287
- default: return true;
309
+ //#endregion
310
+ //#region src/cdn/media-accessor.ts
311
+ var MediaAccessor = class {
312
+ _transport;
313
+ _manifest = null;
314
+ constructor(transport) {
315
+ this._transport = transport;
288
316
  }
289
- }
317
+ async manifest() {
318
+ if (!this._manifest) this._manifest = await this._transport.fetch("_media_manifest.json");
319
+ return this._manifest;
320
+ }
321
+ async assets() {
322
+ return (await this.manifest()).assets;
323
+ }
324
+ async asset(path) {
325
+ return (await this.assets())[path] ?? null;
326
+ }
327
+ async list() {
328
+ const all = await this.assets();
329
+ return Object.entries(all).map(([path, asset]) => Object.assign({ path }, asset));
330
+ }
331
+ resolve(asset, variant) {
332
+ if (variant && asset.variants[variant]) return asset.variants[variant];
333
+ return asset.original;
334
+ }
335
+ url(asset, variant) {
336
+ const path = this.resolve(asset, variant);
337
+ return this._transport.buildUrl(path);
338
+ }
339
+ };
340
+ //#endregion
341
+ //#region src/cdn/forms-client.ts
342
+ var FormsClient = class {
343
+ _baseUrl;
344
+ _projectId;
345
+ _apiKey;
346
+ constructor(config) {
347
+ this._baseUrl = config.baseUrl.replace(/\/+$/, "");
348
+ this._projectId = config.projectId;
349
+ this._apiKey = config.apiKey;
350
+ }
351
+ async config(modelId) {
352
+ const url = `${this._baseUrl}/${this._projectId}/${modelId}/config`;
353
+ const headers = {};
354
+ if (this._apiKey) headers["Authorization"] = `Bearer ${this._apiKey}`;
355
+ const res = await globalThis.fetch(url, { headers });
356
+ if (!res.ok) throw new ContentrainError(res.status, await res.text());
357
+ return await res.json();
358
+ }
359
+ async submit(modelId, data, options) {
360
+ const url = `${this._baseUrl}/${this._projectId}/${modelId}/submit`;
361
+ const headers = { "Content-Type": "application/json" };
362
+ if (this._apiKey) headers["Authorization"] = `Bearer ${this._apiKey}`;
363
+ const body = { ...data };
364
+ if (options?.captchaToken) body["cf-turnstile-response"] = options.captchaToken;
365
+ const res = await globalThis.fetch(url, {
366
+ method: "POST",
367
+ headers,
368
+ body: JSON.stringify(body)
369
+ });
370
+ const result = await res.json();
371
+ if (!res.ok && !result.errors) throw new ContentrainError(res.status, result.message ?? "Form submission failed");
372
+ return result;
373
+ }
374
+ };
375
+ //#endregion
376
+ //#region src/cdn/conversation-client.ts
377
+ var ConversationClient = class {
378
+ _baseUrl;
379
+ _projectId;
380
+ _apiKey;
381
+ constructor(config) {
382
+ this._baseUrl = config.baseUrl.replace(/\/+$/, "");
383
+ this._projectId = config.projectId;
384
+ this._apiKey = config.apiKey;
385
+ }
386
+ async send(message, options) {
387
+ const url = `${this._baseUrl}/${this._projectId}/message`;
388
+ const body = { message };
389
+ if (options?.conversationId) body.conversationId = options.conversationId;
390
+ if (options?.context) body.context = options.context;
391
+ const res = await globalThis.fetch(url, {
392
+ method: "POST",
393
+ headers: {
394
+ "Content-Type": "application/json",
395
+ "Authorization": `Bearer ${this._apiKey}`
396
+ },
397
+ body: JSON.stringify(body)
398
+ });
399
+ if (!res.ok) throw new ContentrainError(res.status, await res.text());
400
+ return await res.json();
401
+ }
402
+ async history(conversationId, options) {
403
+ const params = new URLSearchParams({ conversationId });
404
+ if (options?.limit) params.set("limit", String(options.limit));
405
+ const url = `${this._baseUrl}/${this._projectId}/history?${params}`;
406
+ const res = await globalThis.fetch(url, { headers: { "Authorization": `Bearer ${this._apiKey}` } });
407
+ if (!res.ok) throw new ContentrainError(res.status, await res.text());
408
+ return await res.json();
409
+ }
410
+ };
290
411
  //#endregion
291
412
  //#region src/cdn/index.ts
292
413
  function createContentrain(config) {
@@ -301,6 +422,17 @@ function createContentrain(config) {
301
422
  singleton: (modelId) => new CdnSingletonAccessor(transport.singleton(modelId), defaultLocale),
302
423
  dictionary: (modelId) => new CdnDictionaryAccessor(transport.dictionary(modelId), defaultLocale),
303
424
  document: (modelId) => new CdnDocumentQuery(transport.document(modelId), defaultLocale),
425
+ media: () => new MediaAccessor(transport),
426
+ form: () => new FormsClient({
427
+ baseUrl: (config.baseUrl ?? "https://studio.contentrain.io/api/cdn/v1").replace("/cdn/v1", "/forms/v1"),
428
+ projectId: config.projectId,
429
+ apiKey: config.apiKey
430
+ }),
431
+ conversation: () => new ConversationClient({
432
+ baseUrl: (config.baseUrl ?? "https://studio.contentrain.io/api/cdn/v1").replace("/cdn/v1", "/conversation/v1"),
433
+ projectId: config.projectId,
434
+ apiKey: config.apiKey
435
+ }),
304
436
  manifest: () => transport.fetch("_manifest.json"),
305
437
  models: () => transport.fetch("models/_index.json"),
306
438
  model: (id) => transport.fetch(`models/${id}.json`)
@@ -337,12 +469,36 @@ Object.defineProperty(exports, "ContentrainError", {
337
469
  return ContentrainError;
338
470
  }
339
471
  });
472
+ Object.defineProperty(exports, "ConversationClient", {
473
+ enumerable: true,
474
+ get: function() {
475
+ return ConversationClient;
476
+ }
477
+ });
478
+ Object.defineProperty(exports, "FormsClient", {
479
+ enumerable: true,
480
+ get: function() {
481
+ return FormsClient;
482
+ }
483
+ });
340
484
  Object.defineProperty(exports, "HttpTransport", {
341
485
  enumerable: true,
342
486
  get: function() {
343
487
  return HttpTransport;
344
488
  }
345
489
  });
490
+ Object.defineProperty(exports, "MediaAccessor", {
491
+ enumerable: true,
492
+ get: function() {
493
+ return MediaAccessor;
494
+ }
495
+ });
496
+ Object.defineProperty(exports, "applyWhere", {
497
+ enumerable: true,
498
+ get: function() {
499
+ return applyWhere;
500
+ }
501
+ });
346
502
  Object.defineProperty(exports, "createContentrain", {
347
503
  enumerable: true,
348
504
  get: function() {