@dotcms/client 1.2.0 → 1.2.1-next.10
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 +538 -13
- package/index.cjs.js +424 -60
- package/index.esm.js +425 -61
- package/package.json +5 -5
- package/src/lib/client/ai/ai-api.d.ts +77 -0
- package/src/lib/client/ai/search/search.d.ts +65 -0
- package/src/lib/client/ai/shared/const.d.ts +16 -0
- package/src/lib/client/ai/shared/types.d.ts +19 -0
- package/src/lib/client/base/base-api.d.ts +42 -0
- package/src/lib/client/client.d.ts +6 -0
- package/src/lib/client/content/builders/collection/collection.d.ts +3 -10
- package/src/lib/client/content/content-api.d.ts +3 -3
- package/src/lib/client/content/shared/types.d.ts +5 -4
- package/src/lib/client/navigation/navigation-api.d.ts +8 -3
- package/src/lib/client/page/page-api.d.ts +2 -21
- package/src/lib/client/page/utils.d.ts +1 -1
- package/src/lib/utils/params/utils.d.ts +25 -0
- package/index.esm.d.ts +0 -1
- package/internal.esm.d.ts +0 -1
- /package/{index.cjs.d.ts → index.d.ts} +0 -0
- /package/{internal.cjs.d.ts → internal.d.ts} +0 -0
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
|
-
|
|
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
|
|
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 `${
|
|
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
|
|
1078
|
-
...
|
|
1423
|
+
return this.httpClient.request(this.url, {
|
|
1424
|
+
...this.requestOptions,
|
|
1079
1425
|
method: 'POST',
|
|
1080
1426
|
headers: {
|
|
1081
|
-
...
|
|
1427
|
+
...this.requestOptions.headers,
|
|
1082
1428
|
'Content-Type': 'application/json'
|
|
1083
1429
|
},
|
|
1084
1430
|
body: JSON.stringify({
|
|
@@ -1087,7 +1433,8 @@ class CollectionBuilder {
|
|
|
1087
1433
|
sort: this.sort,
|
|
1088
1434
|
limit: __classPrivateFieldGet(this, _CollectionBuilder_limit, "f"),
|
|
1089
1435
|
offset: this.offset,
|
|
1090
|
-
depth: __classPrivateFieldGet(this, _CollectionBuilder_depth, "f")
|
|
1436
|
+
depth: __classPrivateFieldGet(this, _CollectionBuilder_depth, "f"),
|
|
1437
|
+
languageId: __classPrivateFieldGet(this, _CollectionBuilder_languageId, "f")
|
|
1091
1438
|
//userId: This exist but we currently don't use it
|
|
1092
1439
|
//allCategoriesInfo: This exist but we currently don't use it
|
|
1093
1440
|
})
|
|
@@ -1116,7 +1463,7 @@ class CollectionBuilder {
|
|
|
1116
1463
|
*
|
|
1117
1464
|
* @example
|
|
1118
1465
|
* // For draft content without site constraint:
|
|
1119
|
-
* // Returns: "+contentType:Blog +languageId:1 +live:false"
|
|
1466
|
+
* // Returns: "+contentType:Blog +languageId:1 +(live:false AND working:true AND deleted:false)"
|
|
1120
1467
|
*
|
|
1121
1468
|
* @example
|
|
1122
1469
|
* // For content with explicit exclusion of current site (site ID 123):
|
|
@@ -1129,26 +1476,30 @@ class CollectionBuilder {
|
|
|
1129
1476
|
* // Returns: "+contentType:Blog -conhost:456 +languageId:1 +live:true +conhost:123" (site ID still added)
|
|
1130
1477
|
*/
|
|
1131
1478
|
getFinalQuery() {
|
|
1132
|
-
// Build base query with language and live/draft constraints
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
.
|
|
1479
|
+
// Build base query with language and live/draft constraints.
|
|
1480
|
+
// NOTE: languageId is intentionally sent in BOTH places:
|
|
1481
|
+
// - in the Lucene query (backend requires this)
|
|
1482
|
+
// - as a top-level request body field (backend also requires this)
|
|
1483
|
+
let baseQuery = this.currentQuery.field('languageId').equals(__classPrivateFieldGet(this, _CollectionBuilder_languageId, "f").toString());
|
|
1484
|
+
if (__classPrivateFieldGet(this, _CollectionBuilder_draft, "f")) {
|
|
1485
|
+
baseQuery = baseQuery.raw('+(live:false AND working:true AND deleted:false)');
|
|
1486
|
+
}
|
|
1487
|
+
else {
|
|
1488
|
+
baseQuery = baseQuery.field('live').equals('true');
|
|
1489
|
+
}
|
|
1490
|
+
const builtQuery = baseQuery.build();
|
|
1139
1491
|
// Check if site ID constraint should be added using utility function
|
|
1140
|
-
const shouldAddSiteId = shouldAddSiteIdConstraint(
|
|
1492
|
+
const shouldAddSiteId = shouldAddSiteIdConstraint(builtQuery, this.siteId);
|
|
1141
1493
|
// Add site ID constraint if needed
|
|
1142
1494
|
if (shouldAddSiteId) {
|
|
1143
|
-
const queryWithSiteId = `${
|
|
1495
|
+
const queryWithSiteId = `${builtQuery} +conhost:${this.siteId}`;
|
|
1144
1496
|
return sanitizeQuery(queryWithSiteId);
|
|
1145
1497
|
}
|
|
1146
|
-
return
|
|
1498
|
+
return builtQuery;
|
|
1147
1499
|
}
|
|
1148
1500
|
}
|
|
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()
|
|
1501
|
+
_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
1502
|
|
|
1151
|
-
var _Content_requestOptions, _Content_httpClient, _Content_config;
|
|
1152
1503
|
/**
|
|
1153
1504
|
* Creates a builder to filter and fetch a collection of content items.
|
|
1154
1505
|
* @param contentType - The content type to retrieve.
|
|
@@ -1198,20 +1549,15 @@ var _Content_requestOptions, _Content_httpClient, _Content_config;
|
|
|
1198
1549
|
* });
|
|
1199
1550
|
* ```
|
|
1200
1551
|
*/
|
|
1201
|
-
class Content {
|
|
1552
|
+
class Content extends BaseApiClient {
|
|
1202
1553
|
/**
|
|
1203
1554
|
* Creates an instance of Content.
|
|
1555
|
+
* @param {DotCMSClientConfig} config - Configuration options for the DotCMS client
|
|
1204
1556
|
* @param {DotRequestOptions} requestOptions - The options for the client request.
|
|
1205
|
-
* @param {string} serverUrl - The server URL.
|
|
1206
1557
|
* @param {DotHttpClient} httpClient - HTTP client for making requests.
|
|
1207
1558
|
*/
|
|
1208
1559
|
constructor(config, requestOptions, httpClient) {
|
|
1209
|
-
|
|
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");
|
|
1560
|
+
super(config, requestOptions, httpClient);
|
|
1215
1561
|
}
|
|
1216
1562
|
/**
|
|
1217
1563
|
* Takes a content type and returns a builder to filter and fetch the collection.
|
|
@@ -1279,16 +1625,20 @@ class Content {
|
|
|
1279
1625
|
*
|
|
1280
1626
|
*/
|
|
1281
1627
|
getCollection(contentType) {
|
|
1282
|
-
return new CollectionBuilder(
|
|
1628
|
+
return new CollectionBuilder(this.requestOptions, this.config, contentType, this.httpClient);
|
|
1283
1629
|
}
|
|
1284
1630
|
}
|
|
1285
|
-
_Content_requestOptions = new WeakMap(), _Content_httpClient = new WeakMap(), _Content_config = new WeakMap();
|
|
1286
1631
|
|
|
1287
|
-
class NavigationClient {
|
|
1632
|
+
class NavigationClient extends BaseApiClient {
|
|
1633
|
+
/**
|
|
1634
|
+
* Creates a new NavigationClient instance.
|
|
1635
|
+
* @param {DotCMSClientConfig} config - Configuration options for the DotCMS client
|
|
1636
|
+
* @param {DotRequestOptions} requestOptions - Options for fetch requests including authorization headers
|
|
1637
|
+
* @param {DotHttpClient} httpClient - HTTP client for making requests
|
|
1638
|
+
*/
|
|
1288
1639
|
constructor(config, requestOptions, httpClient) {
|
|
1289
|
-
|
|
1640
|
+
super(config, requestOptions, httpClient);
|
|
1290
1641
|
this.BASE_URL = `${config?.dotcmsUrl}/api/v1/nav`;
|
|
1291
|
-
this.httpClient = httpClient;
|
|
1292
1642
|
}
|
|
1293
1643
|
/**
|
|
1294
1644
|
* Retrieves information about the dotCMS file and folder tree.
|
|
@@ -1418,6 +1768,8 @@ const buildPageQuery = ({ page, fragments, additionalQueries }) => {
|
|
|
1418
1768
|
canLock
|
|
1419
1769
|
canRead
|
|
1420
1770
|
runningExperimentId
|
|
1771
|
+
lockedBy
|
|
1772
|
+
lockedByName
|
|
1421
1773
|
urlContentMap {
|
|
1422
1774
|
_map
|
|
1423
1775
|
}
|
|
@@ -1483,6 +1835,7 @@ const buildPageQuery = ({ page, fragments, additionalQueries }) => {
|
|
|
1483
1835
|
}
|
|
1484
1836
|
}
|
|
1485
1837
|
viewAs {
|
|
1838
|
+
variantId
|
|
1486
1839
|
visitor {
|
|
1487
1840
|
persona {
|
|
1488
1841
|
modDate
|
|
@@ -1585,7 +1938,7 @@ async function fetchGraphQL({ baseURL, body, headers, httpClient }) {
|
|
|
1585
1938
|
* Client for interacting with the DotCMS Page API.
|
|
1586
1939
|
* Provides methods to retrieve and manipulate pages.
|
|
1587
1940
|
*/
|
|
1588
|
-
class PageClient {
|
|
1941
|
+
class PageClient extends BaseApiClient {
|
|
1589
1942
|
/**
|
|
1590
1943
|
* Creates a new PageClient instance.
|
|
1591
1944
|
*
|
|
@@ -1610,10 +1963,7 @@ class PageClient {
|
|
|
1610
1963
|
* ```
|
|
1611
1964
|
*/
|
|
1612
1965
|
constructor(config, requestOptions, httpClient) {
|
|
1613
|
-
|
|
1614
|
-
this.siteId = config.siteId || '';
|
|
1615
|
-
this.dotcmsUrl = config.dotcmsUrl;
|
|
1616
|
-
this.httpClient = httpClient;
|
|
1966
|
+
super(config, requestOptions, httpClient);
|
|
1617
1967
|
}
|
|
1618
1968
|
/**
|
|
1619
1969
|
* Retrieves a page from DotCMS using GraphQL.
|
|
@@ -1701,12 +2051,25 @@ class PageClient {
|
|
|
1701
2051
|
response.errors.forEach((error) => {
|
|
1702
2052
|
consola.error('[DotCMS GraphQL Error]: ', error.message);
|
|
1703
2053
|
});
|
|
2054
|
+
const pageError = response.errors.find((error) => error.message.includes('DotPage'));
|
|
2055
|
+
if (pageError) {
|
|
2056
|
+
// Throw HTTP error - will be caught and wrapped in DotErrorPage below
|
|
2057
|
+
throw new DotHttpError({
|
|
2058
|
+
status: 400,
|
|
2059
|
+
statusText: 'Bad Request',
|
|
2060
|
+
message: `GraphQL query failed for URL '${url}': ${pageError.message}`,
|
|
2061
|
+
data: response.errors
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
1704
2064
|
}
|
|
1705
2065
|
const pageResponse = graphqlToPageEntity(response.data.page);
|
|
1706
2066
|
if (!pageResponse) {
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
2067
|
+
// Throw HTTP error - will be caught and wrapped in DotErrorPage below
|
|
2068
|
+
throw new DotHttpError({
|
|
2069
|
+
status: 404,
|
|
2070
|
+
statusText: 'Not Found',
|
|
2071
|
+
message: `Page ${url} not found. Check the page URL and permissions.`,
|
|
2072
|
+
data: response.errors
|
|
1710
2073
|
});
|
|
1711
2074
|
}
|
|
1712
2075
|
const contentResponse = mapContentResponse(response.data, Object.keys(content));
|
|
@@ -1720,7 +2083,7 @@ class PageClient {
|
|
|
1720
2083
|
};
|
|
1721
2084
|
}
|
|
1722
2085
|
catch (error) {
|
|
1723
|
-
// Handle DotHttpError instances
|
|
2086
|
+
// Handle DotHttpError instances
|
|
1724
2087
|
if (error instanceof DotHttpError) {
|
|
1725
2088
|
throw new DotErrorPage(`Page request failed for URL '${url}': ${error.message}`, error, {
|
|
1726
2089
|
query: completeQuery,
|
|
@@ -1778,6 +2141,7 @@ class DotCMSClient {
|
|
|
1778
2141
|
this.page = new PageClient(this.config, this.requestOptions, this.httpClient);
|
|
1779
2142
|
this.nav = new NavigationClient(this.config, this.requestOptions, this.httpClient);
|
|
1780
2143
|
this.content = new Content(this.config, this.requestOptions, this.httpClient);
|
|
2144
|
+
this.ai = new AIClient(this.config, this.requestOptions, this.httpClient);
|
|
1781
2145
|
}
|
|
1782
2146
|
/**
|
|
1783
2147
|
* 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.
|
|
3
|
+
"version": "1.2.1-next.10",
|
|
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.
|
|
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.
|
|
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.
|
|
59
|
-
}
|
|
58
|
+
"types": "./index.d.ts"
|
|
59
|
+
}
|