@dotcms/client 1.2.0 → 1.2.1-next.2

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/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { consola } from 'consola';
2
- import { BaseHttpClient, DotHttpError, DotErrorContent, DotErrorNavigation, DotErrorPage } from '@dotcms/types';
2
+ import { BaseHttpClient, DISTANCE_FUNCTIONS, DotHttpError, DotErrorAISearch, DotErrorContent, DotErrorNavigation, DotErrorPage } from '@dotcms/types';
3
3
  import { graphqlToPageEntity } from './internal.esm.js';
4
4
 
5
5
  /**
@@ -145,6 +145,366 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
145
145
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
146
146
  };
147
147
 
148
+ /**
149
+ * Utility functions for AI search parameter mapping and processing
150
+ */
151
+ /**
152
+ * Appends mapped parameters to URLSearchParams based on a mapping configuration.
153
+ * Only includes parameters that have defined values.
154
+ *
155
+ * @param searchParams - The URLSearchParams object to append to
156
+ * @param sourceObject - The source object containing values
157
+ * @param mapping - Array of [targetKey, sourceKey] pairs for parameter mapping, or [key] to use same key
158
+ * @example
159
+ * ```typescript
160
+ * const params = new URLSearchParams();
161
+ * const query = { limit: 10, offset: 0, siteId: 'default', indexName: 'content' };
162
+ * const mapping = [
163
+ * ['searchLimit', 'limit'], // Maps limit -> searchLimit
164
+ * ['searchOffset', 'offset'], // Maps offset -> searchOffset
165
+ * ['site', 'siteId'], // Maps siteId -> site
166
+ * ['indexName'] // Uses indexName -> indexName (same key)
167
+ * ];
168
+ * appendMappedParams(params, query, mapping);
169
+ * // Results in: searchLimit=10&searchOffset=0&site=default&indexName=content
170
+ * ```
171
+ */
172
+ function appendMappedParams(searchParams, sourceObject, mapping) {
173
+ mapping.forEach((item) => {
174
+ const targetKey = item[0];
175
+ const sourceKey = item[1] ?? item[0];
176
+ const value = sourceObject[sourceKey];
177
+ if (value !== undefined) {
178
+ searchParams.append(targetKey, String(value));
179
+ }
180
+ });
181
+ }
182
+
183
+ var _BaseApiClient_requestOptions, _BaseApiClient_config, _BaseApiClient_httpClient;
184
+ /**
185
+ * Base class for all DotCMS API clients.
186
+ * Provides common constructor parameters and properties that all API clients need.
187
+ * Uses JavaScript private fields (#) for true runtime privacy.
188
+ */
189
+ class BaseApiClient {
190
+ /**
191
+ * Creates a new API client instance.
192
+ *
193
+ * @param {DotCMSClientConfig} config - Configuration options for the DotCMS client
194
+ * @param {DotRequestOptions} requestOptions - Options for fetch requests including authorization headers
195
+ * @param {DotHttpClient} httpClient - HTTP client for making requests
196
+ */
197
+ constructor(config, requestOptions = {}, httpClient) {
198
+ /**
199
+ * Request options including authorization headers.
200
+ * @private
201
+ */
202
+ _BaseApiClient_requestOptions.set(this, void 0);
203
+ /**
204
+ * DotCMS client configuration.
205
+ * @private
206
+ */
207
+ _BaseApiClient_config.set(this, void 0);
208
+ /**
209
+ * HTTP client for making requests.
210
+ * @private
211
+ */
212
+ _BaseApiClient_httpClient.set(this, void 0);
213
+ __classPrivateFieldSet(this, _BaseApiClient_config, {
214
+ siteId: '',
215
+ ...config
216
+ }, "f");
217
+ __classPrivateFieldSet(this, _BaseApiClient_requestOptions, {
218
+ ...requestOptions
219
+ }, "f");
220
+ __classPrivateFieldSet(this, _BaseApiClient_httpClient, httpClient, "f");
221
+ }
222
+ /**
223
+ * Gets the request options including authorization headers.
224
+ * @protected
225
+ */
226
+ get requestOptions() {
227
+ return __classPrivateFieldGet(this, _BaseApiClient_requestOptions, "f");
228
+ }
229
+ /**
230
+ * Gets the DotCMS client configuration.
231
+ * @protected
232
+ */
233
+ get config() {
234
+ return __classPrivateFieldGet(this, _BaseApiClient_config, "f");
235
+ }
236
+ /**
237
+ * Gets the HTTP client for making requests.
238
+ * @protected
239
+ */
240
+ get httpClient() {
241
+ return __classPrivateFieldGet(this, _BaseApiClient_httpClient, "f");
242
+ }
243
+ /**
244
+ * Gets the DotCMS URL from config.
245
+ * @protected
246
+ */
247
+ get dotcmsUrl() {
248
+ return __classPrivateFieldGet(this, _BaseApiClient_config, "f").dotcmsUrl;
249
+ }
250
+ /**
251
+ * Gets the site ID from config.
252
+ * @protected
253
+ */
254
+ get siteId() {
255
+ return __classPrivateFieldGet(this, _BaseApiClient_config, "f").siteId || '';
256
+ }
257
+ }
258
+ _BaseApiClient_requestOptions = new WeakMap(), _BaseApiClient_config = new WeakMap(), _BaseApiClient_httpClient = new WeakMap();
259
+
260
+ /**
261
+ * Default values for AI configuration
262
+ */
263
+ const DEFAULT_AI_CONFIG = {
264
+ threshold: 0.5,
265
+ distanceFunction: DISTANCE_FUNCTIONS.cosine,
266
+ responseLength: 1024
267
+ };
268
+ /**
269
+ * Default values for search query
270
+ */
271
+ const DEFAULT_QUERY = {
272
+ limit: 1000,
273
+ offset: 0,
274
+ indexName: 'default'
275
+ };
276
+
277
+ var _AISearch_params, _AISearch_prompt, _AISearch_indexName;
278
+ /**
279
+ * Class for executing AI searches.
280
+ *
281
+ * @template T - The type of the contentlet.
282
+ * @param config - The configuration for the client.
283
+ * @param requestOptions - The request options for the client.
284
+ * @param httpClient - The HTTP client for the client.
285
+ * @param params - The parameters for the search.
286
+ * @param prompt - The prompt for the search.
287
+ */
288
+ class AISearch extends BaseApiClient {
289
+ constructor(config, requestOptions, httpClient, prompt, indexName, params = {}) {
290
+ super(config, requestOptions, httpClient);
291
+ _AISearch_params.set(this, void 0);
292
+ _AISearch_prompt.set(this, void 0);
293
+ _AISearch_indexName.set(this, void 0);
294
+ __classPrivateFieldSet(this, _AISearch_params, params, "f");
295
+ __classPrivateFieldSet(this, _AISearch_prompt, prompt, "f");
296
+ __classPrivateFieldSet(this, _AISearch_indexName, indexName, "f");
297
+ }
298
+ /**
299
+ * Executes the AI search and returns a promise with the search results.
300
+ *
301
+ * @param onfulfilled - Callback function to handle the search results.
302
+ * @param onrejected - Callback function to handle the search error.
303
+ * @returns Promise with the search results or the error.
304
+ * @example
305
+ * ```typescript
306
+ * const results = await client.ai.search('machine learning articles', 'content_index', {
307
+ * query: {
308
+ * limit: 20,
309
+ * contentType: 'BlogPost',
310
+ * languageId: '1' // or 1
311
+ * },
312
+ * config: {
313
+ * threshold: 0.7
314
+ * }
315
+ * });
316
+ * ```
317
+ * @example
318
+ * ```typescript
319
+ * client.ai.search('machine learning articles', 'content_index', {
320
+ * query: {
321
+ * limit: 20,
322
+ * contentType: 'BlogPost',
323
+ * languageId: '1' // or 1
324
+ * },
325
+ * config: {
326
+ * threshold: 0.7
327
+ * }
328
+ * }).then((results) => {
329
+ * console.log(results);
330
+ * }).catch((error) => {
331
+ * console.error(error);
332
+ * });
333
+ * ```
334
+ */
335
+ then(onfulfilled, onrejected) {
336
+ return this.fetch().then((data) => {
337
+ const response = {
338
+ ...data,
339
+ results: data.dotCMSResults
340
+ };
341
+ if (typeof onfulfilled === 'function') {
342
+ const result = onfulfilled(response);
343
+ // Ensure we always return a value, fallback to data if callback returns undefined
344
+ return result ?? response;
345
+ }
346
+ return response;
347
+ }, (error) => {
348
+ // Wrap error in DotCMSContentError
349
+ let contentError;
350
+ if (error instanceof DotHttpError) {
351
+ contentError = new DotErrorAISearch({
352
+ message: `AI Search failed (fetch): ${error.message}`,
353
+ httpError: error,
354
+ params: __classPrivateFieldGet(this, _AISearch_params, "f"),
355
+ prompt: __classPrivateFieldGet(this, _AISearch_prompt, "f"),
356
+ indexName: __classPrivateFieldGet(this, _AISearch_indexName, "f")
357
+ });
358
+ }
359
+ else {
360
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
361
+ contentError = new DotErrorAISearch({
362
+ message: `AI Search failed (fetch): ${errorMessage}`,
363
+ httpError: undefined,
364
+ params: __classPrivateFieldGet(this, _AISearch_params, "f"),
365
+ prompt: __classPrivateFieldGet(this, _AISearch_prompt, "f"),
366
+ indexName: __classPrivateFieldGet(this, _AISearch_indexName, "f")
367
+ });
368
+ }
369
+ if (typeof onrejected === 'function') {
370
+ const result = onrejected(contentError);
371
+ // Ensure we always return a value, fallback to original error if callback returns undefined
372
+ return result ?? contentError;
373
+ }
374
+ // Throw the wrapped error to trigger .catch()
375
+ throw contentError;
376
+ });
377
+ }
378
+ fetch() {
379
+ const searchParams = this.buildSearchParams(__classPrivateFieldGet(this, _AISearch_prompt, "f"), __classPrivateFieldGet(this, _AISearch_params, "f"));
380
+ const url = new URL('/api/v1/ai/search', this.dotcmsUrl);
381
+ url.search = searchParams.toString();
382
+ return this.httpClient.request(url.toString(), {
383
+ ...this.requestOptions,
384
+ headers: {
385
+ ...this.requestOptions.headers
386
+ },
387
+ method: 'GET'
388
+ });
389
+ }
390
+ /**
391
+ * Builds URLSearchParams from the SDK interface, mapping to backend parameter names.
392
+ * Only includes parameters that have values.
393
+ *
394
+ * @param params - Search parameters with SDK naming
395
+ * @returns URLSearchParams with backend parameter names
396
+ * @private
397
+ */
398
+ buildSearchParams(prompt, params = {}) {
399
+ const searchParams = new URLSearchParams();
400
+ const { query = {}, config = {} } = params;
401
+ const combinedQuery = {
402
+ ...DEFAULT_QUERY,
403
+ siteId: this.siteId,
404
+ ...query
405
+ };
406
+ const combinedConfig = {
407
+ ...DEFAULT_AI_CONFIG,
408
+ ...config
409
+ };
410
+ const entriesQueryParameters = [
411
+ ['searchLimit', 'limit'],
412
+ ['searchOffset', 'offset'],
413
+ ['site', 'siteId'],
414
+ ['language', 'languageId'],
415
+ ['contentType']
416
+ ];
417
+ // Map SDK query parameters to backend parameter names
418
+ appendMappedParams(searchParams, combinedQuery, entriesQueryParameters);
419
+ // Map config parameters using the same key names
420
+ appendMappedParams(searchParams, combinedConfig, Object.keys(combinedConfig).map((key) => [key]));
421
+ // Add search-specific parameters
422
+ searchParams.append('indexName', __classPrivateFieldGet(this, _AISearch_indexName, "f"));
423
+ searchParams.append('query', prompt);
424
+ return searchParams;
425
+ }
426
+ }
427
+ _AISearch_params = new WeakMap(), _AISearch_prompt = new WeakMap(), _AISearch_indexName = new WeakMap();
428
+
429
+ /**
430
+ * Client for interacting with the DotCMS AI API.
431
+ * Provides methods to interact with AI features.
432
+ * @experimental This client is experimental and may be subject to change.
433
+ */
434
+ class AIClient extends BaseApiClient {
435
+ /**
436
+ * Creates a new AIClient instance.
437
+ *
438
+ * @param {DotCMSClientConfig} config - Configuration options for the DotCMS client
439
+ * @param {DotRequestOptions} requestOptions - Options for fetch requests including authorization headers
440
+ * @param {DotHttpClient} httpClient - HTTP client for making requests
441
+ * @example
442
+ * ```typescript
443
+ * const aiClient = new AIClient(
444
+ * {
445
+ * dotcmsUrl: 'https://demo.dotcms.com',
446
+ * authToken: 'your-auth-token',
447
+ * siteId: 'demo.dotcms.com'
448
+ * },
449
+ * {
450
+ * headers: {
451
+ * Authorization: 'Bearer your-auth-token'
452
+ * }
453
+ * },
454
+ * httpClient
455
+ * );
456
+ * ```
457
+ */
458
+ constructor(config, requestOptions, httpClient) {
459
+ super(config, requestOptions, httpClient);
460
+ }
461
+ /**
462
+ * Performs an AI-powered search.
463
+ *
464
+ * @param params - Search parameters with query and AI configuration
465
+ * @returns Promise with search results
466
+ * @experimental This method is experimental and may be subject to change.
467
+ * @template T - The type of the contentlet.
468
+ * @param prompt - The prompt for the search.
469
+ * @param indexName - The name of the index you want to search in.
470
+ * @param params - Search parameters with query and AI configuration.
471
+ * @example
472
+ * @example
473
+ * ```typescript
474
+ * const response = await client.ai.search('machine learning articles', 'content_index', {
475
+ * query: {
476
+ * limit: 20,
477
+ * contentType: 'BlogPost',
478
+ * languageId: "1" // or 1
479
+ * },
480
+ * config: {
481
+ * threshold: 0.7
482
+ * }
483
+ * });
484
+ * ```
485
+ * @example
486
+ * ```typescript
487
+ * client.ai.search('machine learning articles', 'content_index', {
488
+ * query: {
489
+ * limit: 20,
490
+ * contentType: 'BlogPost',
491
+ * languageId: "1" // or 1
492
+ * },
493
+ * config: {
494
+ * threshold: 0.7,
495
+ * distanceFunction: DISTANCE_FUNCTIONS.cosine
496
+ * }
497
+ * }).then((response) => {
498
+ * console.log(response.results);
499
+ * }).catch((error) => {
500
+ * console.error(error);
501
+ * });
502
+ */
503
+ search(prompt, indexName, params = {}) {
504
+ return new AISearch(this.config, this.requestOptions, this.httpClient, prompt, indexName, params);
505
+ }
506
+ }
507
+
148
508
  /**
149
509
  * Default variant identifier used in the application.
150
510
  */
@@ -184,7 +544,9 @@ const CONTENT_API_URL = '/api/content/_search';
184
544
  * @returns {string} The sanitized query string.
185
545
  */
186
546
  function sanitizeQueryForContentType(query, contentType) {
187
- return query.replace(/\+([^+:]*?):/g, (original, field) => {
547
+ // Match field names that start with letter/underscore, followed by alphanumeric/underscore/dot
548
+ // This excludes Lucene grouping operators like +(...)
549
+ return query.replace(/\+([a-zA-Z_][a-zA-Z0-9_.]*):/g, (original, field) => {
188
550
  return !CONTENT_TYPE_MAIN_FIELDS.includes(field) // Fields that are not content type fields
189
551
  ? `+${contentType}.${field}:` // Should have this format: +contentTypeVar.field:
190
552
  : original; // Return the field if it is a content type field
@@ -744,7 +1106,7 @@ class QueryBuilder {
744
1106
  }
745
1107
  _QueryBuilder_query = new WeakMap();
746
1108
 
747
- var _CollectionBuilder_page, _CollectionBuilder_limit, _CollectionBuilder_depth, _CollectionBuilder_render, _CollectionBuilder_sortBy, _CollectionBuilder_contentType, _CollectionBuilder_defaultQuery, _CollectionBuilder_query, _CollectionBuilder_rawQuery, _CollectionBuilder_languageId, _CollectionBuilder_draft, _CollectionBuilder_requestOptions, _CollectionBuilder_httpClient, _CollectionBuilder_config;
1109
+ var _CollectionBuilder_page, _CollectionBuilder_limit, _CollectionBuilder_depth, _CollectionBuilder_render, _CollectionBuilder_sortBy, _CollectionBuilder_contentType, _CollectionBuilder_defaultQuery, _CollectionBuilder_query, _CollectionBuilder_rawQuery, _CollectionBuilder_languageId, _CollectionBuilder_draft;
748
1110
  /**
749
1111
  * Creates a Builder to filter and fetch content from the content API for a specific content type.
750
1112
  *
@@ -752,7 +1114,7 @@ var _CollectionBuilder_page, _CollectionBuilder_limit, _CollectionBuilder_depth,
752
1114
  * @class CollectionBuilder
753
1115
  * @template T Represents the type of the content type to fetch. Defaults to unknown.
754
1116
  */
755
- class CollectionBuilder {
1117
+ class CollectionBuilder extends BaseApiClient {
756
1118
  /**
757
1119
  * Creates an instance of CollectionBuilder.
758
1120
  * @param {ClientOptions} requestOptions Options for the client request.
@@ -762,6 +1124,7 @@ class CollectionBuilder {
762
1124
  * @memberof CollectionBuilder
763
1125
  */
764
1126
  constructor(requestOptions, config, contentType, httpClient) {
1127
+ super(config, requestOptions, httpClient);
765
1128
  _CollectionBuilder_page.set(this, 1);
766
1129
  _CollectionBuilder_limit.set(this, 10);
767
1130
  _CollectionBuilder_depth.set(this, 0);
@@ -773,14 +1136,7 @@ class CollectionBuilder {
773
1136
  _CollectionBuilder_rawQuery.set(this, void 0);
774
1137
  _CollectionBuilder_languageId.set(this, 1);
775
1138
  _CollectionBuilder_draft.set(this, false);
776
- _CollectionBuilder_requestOptions.set(this, void 0);
777
- _CollectionBuilder_httpClient.set(this, void 0);
778
- _CollectionBuilder_config.set(this, void 0);
779
- __classPrivateFieldSet(this, _CollectionBuilder_requestOptions, requestOptions, "f");
780
- __classPrivateFieldSet(this, _CollectionBuilder_config, config, "f");
781
1139
  __classPrivateFieldSet(this, _CollectionBuilder_contentType, contentType, "f");
782
- __classPrivateFieldSet(this, _CollectionBuilder_httpClient, httpClient, "f");
783
- __classPrivateFieldSet(this, _CollectionBuilder_config, config, "f");
784
1140
  // Build the default query with the contentType field
785
1141
  __classPrivateFieldSet(this, _CollectionBuilder_defaultQuery, new QueryBuilder().field('contentType').equals(__classPrivateFieldGet(this, _CollectionBuilder_contentType, "f")), "f");
786
1142
  }
@@ -812,17 +1168,7 @@ class CollectionBuilder {
812
1168
  * @memberof CollectionBuilder
813
1169
  */
814
1170
  get url() {
815
- return `${__classPrivateFieldGet(this, _CollectionBuilder_config, "f").dotcmsUrl}${CONTENT_API_URL}`;
816
- }
817
- /**
818
- * Returns the site ID from the configuration.
819
- *
820
- * @readonly
821
- * @private
822
- * @memberof CollectionBuilder
823
- */
824
- get siteId() {
825
- return __classPrivateFieldGet(this, _CollectionBuilder_config, "f").siteId;
1171
+ return `${this.config.dotcmsUrl}${CONTENT_API_URL}`;
826
1172
  }
827
1173
  /**
828
1174
  * Returns the current query built.
@@ -1074,11 +1420,11 @@ class CollectionBuilder {
1074
1420
  const finalQuery = this.getFinalQuery();
1075
1421
  const sanitizedQuery = sanitizeQueryForContentType(finalQuery, __classPrivateFieldGet(this, _CollectionBuilder_contentType, "f"));
1076
1422
  const query = __classPrivateFieldGet(this, _CollectionBuilder_rawQuery, "f") ? `${sanitizedQuery} ${__classPrivateFieldGet(this, _CollectionBuilder_rawQuery, "f")}` : sanitizedQuery;
1077
- return __classPrivateFieldGet(this, _CollectionBuilder_httpClient, "f").request(this.url, {
1078
- ...__classPrivateFieldGet(this, _CollectionBuilder_requestOptions, "f"),
1423
+ return this.httpClient.request(this.url, {
1424
+ ...this.requestOptions,
1079
1425
  method: 'POST',
1080
1426
  headers: {
1081
- ...__classPrivateFieldGet(this, _CollectionBuilder_requestOptions, "f").headers,
1427
+ ...this.requestOptions.headers,
1082
1428
  'Content-Type': 'application/json'
1083
1429
  },
1084
1430
  body: JSON.stringify({
@@ -1116,7 +1462,7 @@ class CollectionBuilder {
1116
1462
  *
1117
1463
  * @example
1118
1464
  * // For draft content without site constraint:
1119
- * // Returns: "+contentType:Blog +languageId:1 +live:false"
1465
+ * // Returns: "+contentType:Blog +languageId:1 +(live:false AND working:true AND deleted:false)"
1120
1466
  *
1121
1467
  * @example
1122
1468
  * // For content with explicit exclusion of current site (site ID 123):
@@ -1130,25 +1476,26 @@ class CollectionBuilder {
1130
1476
  */
1131
1477
  getFinalQuery() {
1132
1478
  // Build base query with language and live/draft constraints
1133
- const baseQuery = this.currentQuery
1134
- .field('languageId')
1135
- .equals(__classPrivateFieldGet(this, _CollectionBuilder_languageId, "f").toString())
1136
- .field('live')
1137
- .equals((!__classPrivateFieldGet(this, _CollectionBuilder_draft, "f")).toString())
1138
- .build();
1479
+ let baseQuery = this.currentQuery.field('languageId').equals(__classPrivateFieldGet(this, _CollectionBuilder_languageId, "f").toString());
1480
+ if (__classPrivateFieldGet(this, _CollectionBuilder_draft, "f")) {
1481
+ baseQuery = baseQuery.raw('+(live:false AND working:true AND deleted:false)');
1482
+ }
1483
+ else {
1484
+ baseQuery = baseQuery.field('live').equals('true');
1485
+ }
1486
+ const builtQuery = baseQuery.build();
1139
1487
  // Check if site ID constraint should be added using utility function
1140
- const shouldAddSiteId = shouldAddSiteIdConstraint(baseQuery, this.siteId);
1488
+ const shouldAddSiteId = shouldAddSiteIdConstraint(builtQuery, this.siteId);
1141
1489
  // Add site ID constraint if needed
1142
1490
  if (shouldAddSiteId) {
1143
- const queryWithSiteId = `${baseQuery} +conhost:${this.siteId}`;
1491
+ const queryWithSiteId = `${builtQuery} +conhost:${this.siteId}`;
1144
1492
  return sanitizeQuery(queryWithSiteId);
1145
1493
  }
1146
- return baseQuery;
1494
+ return builtQuery;
1147
1495
  }
1148
1496
  }
1149
- _CollectionBuilder_page = new WeakMap(), _CollectionBuilder_limit = new WeakMap(), _CollectionBuilder_depth = new WeakMap(), _CollectionBuilder_render = new WeakMap(), _CollectionBuilder_sortBy = new WeakMap(), _CollectionBuilder_contentType = new WeakMap(), _CollectionBuilder_defaultQuery = new WeakMap(), _CollectionBuilder_query = new WeakMap(), _CollectionBuilder_rawQuery = new WeakMap(), _CollectionBuilder_languageId = new WeakMap(), _CollectionBuilder_draft = new WeakMap(), _CollectionBuilder_requestOptions = new WeakMap(), _CollectionBuilder_httpClient = new WeakMap(), _CollectionBuilder_config = new WeakMap();
1497
+ _CollectionBuilder_page = new WeakMap(), _CollectionBuilder_limit = new WeakMap(), _CollectionBuilder_depth = new WeakMap(), _CollectionBuilder_render = new WeakMap(), _CollectionBuilder_sortBy = new WeakMap(), _CollectionBuilder_contentType = new WeakMap(), _CollectionBuilder_defaultQuery = new WeakMap(), _CollectionBuilder_query = new WeakMap(), _CollectionBuilder_rawQuery = new WeakMap(), _CollectionBuilder_languageId = new WeakMap(), _CollectionBuilder_draft = new WeakMap();
1150
1498
 
1151
- var _Content_requestOptions, _Content_httpClient, _Content_config;
1152
1499
  /**
1153
1500
  * Creates a builder to filter and fetch a collection of content items.
1154
1501
  * @param contentType - The content type to retrieve.
@@ -1198,20 +1545,15 @@ var _Content_requestOptions, _Content_httpClient, _Content_config;
1198
1545
  * });
1199
1546
  * ```
1200
1547
  */
1201
- class Content {
1548
+ class Content extends BaseApiClient {
1202
1549
  /**
1203
1550
  * Creates an instance of Content.
1551
+ * @param {DotCMSClientConfig} config - Configuration options for the DotCMS client
1204
1552
  * @param {DotRequestOptions} requestOptions - The options for the client request.
1205
- * @param {string} serverUrl - The server URL.
1206
1553
  * @param {DotHttpClient} httpClient - HTTP client for making requests.
1207
1554
  */
1208
1555
  constructor(config, requestOptions, httpClient) {
1209
- _Content_requestOptions.set(this, void 0);
1210
- _Content_httpClient.set(this, void 0);
1211
- _Content_config.set(this, void 0);
1212
- __classPrivateFieldSet(this, _Content_requestOptions, requestOptions, "f");
1213
- __classPrivateFieldSet(this, _Content_config, config, "f");
1214
- __classPrivateFieldSet(this, _Content_httpClient, httpClient, "f");
1556
+ super(config, requestOptions, httpClient);
1215
1557
  }
1216
1558
  /**
1217
1559
  * Takes a content type and returns a builder to filter and fetch the collection.
@@ -1279,16 +1621,20 @@ class Content {
1279
1621
  *
1280
1622
  */
1281
1623
  getCollection(contentType) {
1282
- return new CollectionBuilder(__classPrivateFieldGet(this, _Content_requestOptions, "f"), __classPrivateFieldGet(this, _Content_config, "f"), contentType, __classPrivateFieldGet(this, _Content_httpClient, "f"));
1624
+ return new CollectionBuilder(this.requestOptions, this.config, contentType, this.httpClient);
1283
1625
  }
1284
1626
  }
1285
- _Content_requestOptions = new WeakMap(), _Content_httpClient = new WeakMap(), _Content_config = new WeakMap();
1286
1627
 
1287
- class NavigationClient {
1628
+ class NavigationClient extends BaseApiClient {
1629
+ /**
1630
+ * Creates a new NavigationClient instance.
1631
+ * @param {DotCMSClientConfig} config - Configuration options for the DotCMS client
1632
+ * @param {DotRequestOptions} requestOptions - Options for fetch requests including authorization headers
1633
+ * @param {DotHttpClient} httpClient - HTTP client for making requests
1634
+ */
1288
1635
  constructor(config, requestOptions, httpClient) {
1289
- this.requestOptions = requestOptions;
1636
+ super(config, requestOptions, httpClient);
1290
1637
  this.BASE_URL = `${config?.dotcmsUrl}/api/v1/nav`;
1291
- this.httpClient = httpClient;
1292
1638
  }
1293
1639
  /**
1294
1640
  * Retrieves information about the dotCMS file and folder tree.
@@ -1418,6 +1764,8 @@ const buildPageQuery = ({ page, fragments, additionalQueries }) => {
1418
1764
  canLock
1419
1765
  canRead
1420
1766
  runningExperimentId
1767
+ lockedBy
1768
+ lockedByName
1421
1769
  urlContentMap {
1422
1770
  _map
1423
1771
  }
@@ -1483,6 +1831,7 @@ const buildPageQuery = ({ page, fragments, additionalQueries }) => {
1483
1831
  }
1484
1832
  }
1485
1833
  viewAs {
1834
+ variantId
1486
1835
  visitor {
1487
1836
  persona {
1488
1837
  modDate
@@ -1585,7 +1934,7 @@ async function fetchGraphQL({ baseURL, body, headers, httpClient }) {
1585
1934
  * Client for interacting with the DotCMS Page API.
1586
1935
  * Provides methods to retrieve and manipulate pages.
1587
1936
  */
1588
- class PageClient {
1937
+ class PageClient extends BaseApiClient {
1589
1938
  /**
1590
1939
  * Creates a new PageClient instance.
1591
1940
  *
@@ -1610,10 +1959,7 @@ class PageClient {
1610
1959
  * ```
1611
1960
  */
1612
1961
  constructor(config, requestOptions, httpClient) {
1613
- this.requestOptions = requestOptions;
1614
- this.siteId = config.siteId || '';
1615
- this.dotcmsUrl = config.dotcmsUrl;
1616
- this.httpClient = httpClient;
1962
+ super(config, requestOptions, httpClient);
1617
1963
  }
1618
1964
  /**
1619
1965
  * Retrieves a page from DotCMS using GraphQL.
@@ -1701,12 +2047,25 @@ class PageClient {
1701
2047
  response.errors.forEach((error) => {
1702
2048
  consola.error('[DotCMS GraphQL Error]: ', error.message);
1703
2049
  });
2050
+ const pageError = response.errors.find((error) => error.message.includes('DotPage'));
2051
+ if (pageError) {
2052
+ // Throw HTTP error - will be caught and wrapped in DotErrorPage below
2053
+ throw new DotHttpError({
2054
+ status: 400,
2055
+ statusText: 'Bad Request',
2056
+ message: `GraphQL query failed for URL '${url}': ${pageError.message}`,
2057
+ data: response.errors
2058
+ });
2059
+ }
1704
2060
  }
1705
2061
  const pageResponse = graphqlToPageEntity(response.data.page);
1706
2062
  if (!pageResponse) {
1707
- throw new DotErrorPage(`Page ${url} not found. Check the page URL and permissions.`, undefined, {
1708
- query: completeQuery,
1709
- variables: requestVariables
2063
+ // Throw HTTP error - will be caught and wrapped in DotErrorPage below
2064
+ throw new DotHttpError({
2065
+ status: 404,
2066
+ statusText: 'Not Found',
2067
+ message: `Page ${url} not found. Check the page URL and permissions.`,
2068
+ data: response.errors
1710
2069
  });
1711
2070
  }
1712
2071
  const contentResponse = mapContentResponse(response.data, Object.keys(content));
@@ -1720,7 +2079,7 @@ class PageClient {
1720
2079
  };
1721
2080
  }
1722
2081
  catch (error) {
1723
- // Handle DotHttpError instances from httpClient.request
2082
+ // Handle DotHttpError instances
1724
2083
  if (error instanceof DotHttpError) {
1725
2084
  throw new DotErrorPage(`Page request failed for URL '${url}': ${error.message}`, error, {
1726
2085
  query: completeQuery,
@@ -1778,6 +2137,7 @@ class DotCMSClient {
1778
2137
  this.page = new PageClient(this.config, this.requestOptions, this.httpClient);
1779
2138
  this.nav = new NavigationClient(this.config, this.requestOptions, this.httpClient);
1780
2139
  this.content = new Content(this.config, this.requestOptions, this.httpClient);
2140
+ this.ai = new AIClient(this.config, this.requestOptions, this.httpClient);
1781
2141
  }
1782
2142
  /**
1783
2143
  * Creates request options with authentication headers.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotcms/client",
3
- "version": "1.2.0",
3
+ "version": "1.2.1-next.2",
4
4
  "description": "Official JavaScript library for interacting with DotCMS REST APIs.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,13 +26,13 @@
26
26
  "./package.json": "./package.json",
27
27
  ".": {
28
28
  "module": "./index.esm.js",
29
- "types": "./index.esm.d.ts",
29
+ "types": "./index.d.ts",
30
30
  "import": "./index.cjs.mjs",
31
31
  "default": "./index.cjs.js"
32
32
  },
33
33
  "./internal": {
34
34
  "module": "./internal.esm.js",
35
- "types": "./internal.esm.d.ts",
35
+ "types": "./internal.d.ts",
36
36
  "import": "./internal.cjs.mjs",
37
37
  "default": "./internal.cjs.js"
38
38
  }
@@ -55,5 +55,5 @@
55
55
  "homepage": "https://github.com/dotCMS/core/tree/main/core-web/libs/sdk/client/README.md",
56
56
  "module": "./index.esm.js",
57
57
  "main": "./index.cjs.js",
58
- "types": "./index.esm.d.ts"
59
- }
58
+ "types": "./index.d.ts"
59
+ }