@dotcms/client 1.1.1 → 1.2.0-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 +546 -25
- package/index.cjs.js +418 -58
- package/index.esm.js +419 -59
- package/package.json +2 -2
- 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 +18 -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/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/README.md
CHANGED
|
@@ -19,6 +19,7 @@ The `@dotcms/client` is a powerful JavaScript/TypeScript SDK designed to simplif
|
|
|
19
19
|
|
|
20
20
|
> **📋 Migration Guides:**
|
|
21
21
|
> - **From Alpha Version?** If you're upgrading from the alpha version of `@dotcms/client`, please see our [Migration Guide](./MIGRATION.md) for step-by-step instructions.
|
|
22
|
+
> - **From v1.2.x to v1.3.0?** See the [Changelog](#v130) section below for new AI Search API features.
|
|
22
23
|
> - **From v1.0.x to v1.1.1?** See the [Changelog](#v111) section below for new features and improvements.
|
|
23
24
|
|
|
24
25
|
## Table of Contents
|
|
@@ -31,6 +32,7 @@ The `@dotcms/client` is a powerful JavaScript/TypeScript SDK designed to simplif
|
|
|
31
32
|
- [How-to Guides](#how-to-guides)
|
|
32
33
|
- [How to Fetch Complete Pages](#how-to-fetch-complete-pages)
|
|
33
34
|
- [How to Query Content Collections](#how-to-query-content-collections)
|
|
35
|
+
- [How to Use AI-Powered Search](#how-to-use-ai-powered-search)
|
|
34
36
|
- [How to Work with GraphQL](#how-to-work-with-graphql)
|
|
35
37
|
- [How to Use with TypeScript](#how-to-use-with-typescript)
|
|
36
38
|
- [How to Enable Page Editing](#how-to-enable-page-editing)
|
|
@@ -39,17 +41,18 @@ The `@dotcms/client` is a powerful JavaScript/TypeScript SDK designed to simplif
|
|
|
39
41
|
- [HTTP Client Configuration](#http-client-configuration)
|
|
40
42
|
- [page.get() Method](#pageget-method)
|
|
41
43
|
- [content.getCollection() Method](#contentgetcollection-method)
|
|
44
|
+
- [ai.search() Method](#aisearch-method)
|
|
42
45
|
- [navigation.get() Method](#navigationget-method)
|
|
43
46
|
- [Error Handling](#error-handling)
|
|
44
47
|
- [Concepts & Architecture](#concepts--architecture)
|
|
45
48
|
- [Key Concepts](#key-concepts)
|
|
46
49
|
- [Choosing the Right Method](#choosing-the-right-method)
|
|
47
50
|
- [Architecture Overview](#architecture-overview)
|
|
48
|
-
- [Support
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- [Licensing Information](#licensing-information)
|
|
51
|
+
- [Support](#support)
|
|
52
|
+
- [Contributing](#contributing)
|
|
53
|
+
- [Licensing](#licensing)
|
|
52
54
|
- [Changelog](#changelog)
|
|
55
|
+
- [v1.3.0](#v130)
|
|
53
56
|
- [v1.1.1](#v111)
|
|
54
57
|
|
|
55
58
|
## Getting Started
|
|
@@ -215,6 +218,352 @@ const products = await client.content
|
|
|
215
218
|
.limit(10);
|
|
216
219
|
```
|
|
217
220
|
|
|
221
|
+
### How to Use AI-Powered Search
|
|
222
|
+
|
|
223
|
+
> [!WARNING]
|
|
224
|
+
> **Experimental Feature:** The AI API is currently experimental and may undergo breaking changes in future releases. Use with caution in production environments.
|
|
225
|
+
|
|
226
|
+
The `client.ai.search()` method enables semantic search using AI embeddings to find content based on meaning rather than exact keyword matches.
|
|
227
|
+
|
|
228
|
+
#### Prerequisites
|
|
229
|
+
|
|
230
|
+
Before using AI-powered search, ensure your dotCMS instance is properly configured:
|
|
231
|
+
|
|
232
|
+
> [!IMPORTANT]
|
|
233
|
+
> **Required Setup:**
|
|
234
|
+
> 1. **dotAI must be activated** in your dotCMS instance
|
|
235
|
+
> 2. **OpenAI API Key** must be configured in dotCMS
|
|
236
|
+
> 3. **PostgreSQL 15+ with pgvector extension** must be installed
|
|
237
|
+
> 4. **Content indexes** must be created and configured in dotAI
|
|
238
|
+
>
|
|
239
|
+
> For detailed setup instructions, see the [dotCMS dotAI documentation](https://dev.dotcms.com/docs/dotai).
|
|
240
|
+
|
|
241
|
+
#### Basic AI Search
|
|
242
|
+
```typescript
|
|
243
|
+
// Search for content semantically related to your query
|
|
244
|
+
const response = await client.ai.search(
|
|
245
|
+
'articles about machine learning',
|
|
246
|
+
'content_index'
|
|
247
|
+
);
|
|
248
|
+
console.log(response.results);
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### Customizing Search Parameters
|
|
252
|
+
```typescript
|
|
253
|
+
// Fine-tune search with query parameters
|
|
254
|
+
const response = await client.ai.search(
|
|
255
|
+
'artificial intelligence tutorials',
|
|
256
|
+
'content_index',
|
|
257
|
+
{
|
|
258
|
+
query: {
|
|
259
|
+
limit: 20,
|
|
260
|
+
offset: 0,
|
|
261
|
+
contentType: 'BlogPost',
|
|
262
|
+
languageId: '1'
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### Adjusting AI Configuration
|
|
269
|
+
```typescript
|
|
270
|
+
import { DISTANCE_FUNCTIONS } from '@dotcms/types';
|
|
271
|
+
|
|
272
|
+
// Customize AI search behavior with threshold and distance function
|
|
273
|
+
const response = await client.ai.search(
|
|
274
|
+
'deep learning concepts',
|
|
275
|
+
'content_index',
|
|
276
|
+
{
|
|
277
|
+
config: {
|
|
278
|
+
threshold: 0.75, // Higher threshold = more relevant results
|
|
279
|
+
distanceFunction: DISTANCE_FUNCTIONS.cosine, // Distance calculation method
|
|
280
|
+
responseLength: 2048 // Maximum response length
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### Complete Example with All Options
|
|
287
|
+
```typescript
|
|
288
|
+
// Combine query and AI parameters for precise control
|
|
289
|
+
const response = await client.ai.search(
|
|
290
|
+
'best practices for content management',
|
|
291
|
+
'articles_index',
|
|
292
|
+
{
|
|
293
|
+
query: {
|
|
294
|
+
limit: 10,
|
|
295
|
+
offset: 0,
|
|
296
|
+
contentType: 'Article',
|
|
297
|
+
languageId: '1',
|
|
298
|
+
siteId: 'my-site'
|
|
299
|
+
},
|
|
300
|
+
config: {
|
|
301
|
+
threshold: 0.8,
|
|
302
|
+
distanceFunction: DISTANCE_FUNCTIONS.innerProduct,
|
|
303
|
+
responseLength: 1024
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
// Access results with match scores
|
|
309
|
+
resp[onse].results.forEach(result => {
|
|
310
|
+
console.log(result.title);
|
|
311
|
+
console.log('Matches:', result.matches); // Distance and extracted text
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### Understanding Distance Functions
|
|
316
|
+
|
|
317
|
+
The SDK supports multiple distance functions for vector similarity:
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { DISTANCE_FUNCTIONS } from '@dotcms/types';
|
|
321
|
+
|
|
322
|
+
// Available distance functions:
|
|
323
|
+
DISTANCE_FUNCTIONS.cosine // '<=>' - Cosine similarity (default)
|
|
324
|
+
DISTANCE_FUNCTIONS.innerProduct // '<#>' - Inner product similarity
|
|
325
|
+
DISTANCE_FUNCTIONS.L2 // '<->' - Euclidean distance
|
|
326
|
+
DISTANCE_FUNCTIONS.L1 // '<+>' - Manhattan distance
|
|
327
|
+
DISTANCE_FUNCTIONS.hamming // '<~>' - Hamming distance
|
|
328
|
+
DISTANCE_FUNCTIONS.jaccard // '<%>' - Jaccard similarity
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### How to Use with TypeScript
|
|
332
|
+
|
|
333
|
+
The SDK is built with TypeScript and provides comprehensive type definitions through the `@dotcms/types` package for enhanced developer experience and type safety.
|
|
334
|
+
|
|
335
|
+
#### Basic Type Usage
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
import { createDotCMSClient } from '@dotcms/client';
|
|
339
|
+
import type {
|
|
340
|
+
DotCMSPageAsset,
|
|
341
|
+
DotCMSPageResponse,
|
|
342
|
+
DotCMSBasicContentlet,
|
|
343
|
+
DotCMSNavigationItem,
|
|
344
|
+
DotCMSAISearchResponse,
|
|
345
|
+
DotErrorPage,
|
|
346
|
+
DotErrorContent,
|
|
347
|
+
DotErrorAISearch
|
|
348
|
+
} from '@dotcms/types';
|
|
349
|
+
|
|
350
|
+
const client = createDotCMSClient({
|
|
351
|
+
dotcmsUrl: 'https://your-dotcms-instance.com',
|
|
352
|
+
authToken: 'your-auth-token',
|
|
353
|
+
siteId: 'your-site-id'
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### Typing Page Responses
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
import type { DotCMSPageAsset } from '@dotcms/types';
|
|
361
|
+
|
|
362
|
+
// Basic page fetch with type inference
|
|
363
|
+
const { pageAsset } = await client.page.get('/about-us');
|
|
364
|
+
// pageAsset is automatically typed as DotCMSPageAsset
|
|
365
|
+
|
|
366
|
+
// Explicit typing
|
|
367
|
+
const response: { pageAsset: DotCMSPageAsset } = await client.page.get('/about-us');
|
|
368
|
+
|
|
369
|
+
// Access typed properties
|
|
370
|
+
console.log(pageAsset.page.title); // string
|
|
371
|
+
console.log(pageAsset.layout.body.rows); // Row[]
|
|
372
|
+
console.log(pageAsset.viewAs.language); // LanguageView
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
#### Typing Content Collections
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
import type { DotCMSBasicContentlet } from '@dotcms/types';
|
|
379
|
+
|
|
380
|
+
// Define your custom content type interface
|
|
381
|
+
interface BlogPost extends DotCMSBasicContentlet {
|
|
382
|
+
title: string;
|
|
383
|
+
body: string;
|
|
384
|
+
author: string;
|
|
385
|
+
publishDate: string;
|
|
386
|
+
tags: string[];
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Use the generic type parameter for type-safe content
|
|
390
|
+
const response = await client.content
|
|
391
|
+
.getCollection<BlogPost>('Blog')
|
|
392
|
+
.limit(10);
|
|
393
|
+
|
|
394
|
+
// Now contentlets are typed as BlogPost[]
|
|
395
|
+
response.contentlets.forEach(post => {
|
|
396
|
+
console.log(post.title); // ✅ Type-safe: string
|
|
397
|
+
console.log(post.author); // ✅ Type-safe: string
|
|
398
|
+
console.log(post.publishDate); // ✅ Type-safe: string
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
#### Typing AI Search Results
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
import type {
|
|
406
|
+
DotCMSAISearchResponse,
|
|
407
|
+
DotCMSBasicContentlet,
|
|
408
|
+
DISTANCE_FUNCTIONS
|
|
409
|
+
} from '@dotcms/types';
|
|
410
|
+
|
|
411
|
+
// Define your content type
|
|
412
|
+
interface Article extends DotCMSBasicContentlet {
|
|
413
|
+
title: string;
|
|
414
|
+
content: string;
|
|
415
|
+
category: string;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Type-safe AI search
|
|
419
|
+
const response: DotCMSAISearchResponse<Article> = await client.ai.search<Article>(
|
|
420
|
+
'machine learning tutorials',
|
|
421
|
+
'content_index',
|
|
422
|
+
{
|
|
423
|
+
query: {
|
|
424
|
+
limit: 20,
|
|
425
|
+
contentType: 'Article'
|
|
426
|
+
},
|
|
427
|
+
config: {
|
|
428
|
+
threshold: 0.75,
|
|
429
|
+
distanceFunction: DISTANCE_FUNCTIONS.cosine
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
// Access typed results with match information
|
|
435
|
+
response.results.forEach(article => {
|
|
436
|
+
console.log(article.title); // ✅ Type-safe: string
|
|
437
|
+
console.log(article.category); // ✅ Type-safe: string
|
|
438
|
+
|
|
439
|
+
// Access AI match data
|
|
440
|
+
article.matches?.forEach(match => {
|
|
441
|
+
console.log(match.distance); // ✅ Type-safe: number
|
|
442
|
+
console.log(match.extractedText); // ✅ Type-safe: string
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
#### Typing Navigation
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
import type { DotCMSNavigationItem } from '@dotcms/types';
|
|
451
|
+
|
|
452
|
+
// Navigation is automatically typed
|
|
453
|
+
const nav: DotCMSNavigationItem[] = await client.navigation.get('/', {
|
|
454
|
+
depth: 2,
|
|
455
|
+
languageId: 1
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
// Access typed navigation properties
|
|
459
|
+
nav.forEach(item => {
|
|
460
|
+
console.log(item.title); // ✅ Type-safe: string
|
|
461
|
+
console.log(item.href); // ✅ Type-safe: string
|
|
462
|
+
console.log(item.children); // ✅ Type-safe: DotCMSNavigationItem[] | undefined
|
|
463
|
+
});
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
#### Type-Safe Error Handling
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
import type {
|
|
470
|
+
DotHttpError,
|
|
471
|
+
DotErrorPage,
|
|
472
|
+
DotErrorContent,
|
|
473
|
+
DotErrorAISearch
|
|
474
|
+
} from '@dotcms/types';
|
|
475
|
+
|
|
476
|
+
try {
|
|
477
|
+
const { pageAsset } = await client.page.get('/about-us');
|
|
478
|
+
} catch (error) {
|
|
479
|
+
// Type guard for specific error types
|
|
480
|
+
if (error instanceof DotErrorPage) {
|
|
481
|
+
// TypeScript knows this is DotErrorPage
|
|
482
|
+
console.error('Page error:', error.message);
|
|
483
|
+
console.error('Context:', error.context);
|
|
484
|
+
if (error.httpError) {
|
|
485
|
+
console.error('Status:', error.httpError.status); // ✅ Type-safe
|
|
486
|
+
}
|
|
487
|
+
} else if (error instanceof DotErrorContent) {
|
|
488
|
+
// TypeScript knows this is DotErrorContent
|
|
489
|
+
console.error('Content error:', error.contentType);
|
|
490
|
+
console.error('Operation:', error.operation);
|
|
491
|
+
} else if (error instanceof DotErrorAISearch) {
|
|
492
|
+
// TypeScript knows this is DotErrorAISearch
|
|
493
|
+
console.error('AI Search error:', error.prompt);
|
|
494
|
+
console.error('Parameters:', error.params);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
#### Custom Content Types with Relationships
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
import type { DotCMSBasicContentlet } from '@dotcms/types';
|
|
503
|
+
|
|
504
|
+
// Define related content types
|
|
505
|
+
interface Author extends DotCMSBasicContentlet {
|
|
506
|
+
name: string;
|
|
507
|
+
email: string;
|
|
508
|
+
bio: string;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
interface Category extends DotCMSBasicContentlet {
|
|
512
|
+
categoryName: string;
|
|
513
|
+
description: string;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Main content type with relationships
|
|
517
|
+
interface BlogPost extends DotCMSBasicContentlet {
|
|
518
|
+
title: string;
|
|
519
|
+
body: string;
|
|
520
|
+
author: Author; // Nested type
|
|
521
|
+
category: Category; // Nested type
|
|
522
|
+
tags: string[];
|
|
523
|
+
publishDate: string;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Fetch with depth to include relationships
|
|
527
|
+
const response = await client.content
|
|
528
|
+
.getCollection<BlogPost>('Blog')
|
|
529
|
+
.depth(2)
|
|
530
|
+
.limit(5);
|
|
531
|
+
|
|
532
|
+
// Access nested typed properties
|
|
533
|
+
response.contentlets.forEach(post => {
|
|
534
|
+
console.log(post.title); // ✅ string
|
|
535
|
+
console.log(post.author.name); // ✅ string
|
|
536
|
+
console.log(post.author.email); // ✅ string
|
|
537
|
+
console.log(post.category.categoryName); // ✅ string
|
|
538
|
+
});
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
#### Using with Async/Await and Promises
|
|
542
|
+
|
|
543
|
+
```typescript
|
|
544
|
+
import type {
|
|
545
|
+
DotCMSPageAsset,
|
|
546
|
+
GetCollectionResponse
|
|
547
|
+
} from '@dotcms/types';
|
|
548
|
+
|
|
549
|
+
// Async function with typed return
|
|
550
|
+
async function fetchBlogPosts(): Promise<GetCollectionResponse<BlogPost>> {
|
|
551
|
+
return await client.content
|
|
552
|
+
.getCollection<BlogPost>('Blog')
|
|
553
|
+
.limit(10);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Promise chain with types
|
|
557
|
+
client.page.get('/about-us')
|
|
558
|
+
.then((response: { pageAsset: DotCMSPageAsset }) => {
|
|
559
|
+
console.log(response.pageAsset.page.title);
|
|
560
|
+
return response;
|
|
561
|
+
})
|
|
562
|
+
.catch((error: DotErrorPage) => {
|
|
563
|
+
console.error(error.message);
|
|
564
|
+
});
|
|
565
|
+
```
|
|
566
|
+
|
|
218
567
|
### How to Work with GraphQL
|
|
219
568
|
|
|
220
569
|
GraphQL allows you to fetch exactly the data you need in a single request:
|
|
@@ -421,6 +770,111 @@ getCollection<T = DotCMSBasicContentlet>(
|
|
|
421
770
|
const blogs = await client.content.getCollection('Blog').limit(10).page(1);
|
|
422
771
|
```
|
|
423
772
|
|
|
773
|
+
### ai.search() Method
|
|
774
|
+
|
|
775
|
+
> [!WARNING]
|
|
776
|
+
> **Experimental Feature:** The AI API is currently experimental and may undergo breaking changes in future releases. Use with caution in production environments.
|
|
777
|
+
|
|
778
|
+
Performs semantic search using AI embeddings to find content based on meaning rather than exact keyword matches.
|
|
779
|
+
|
|
780
|
+
> [!NOTE]
|
|
781
|
+
> **Prerequisites:** This feature requires dotAI to be activated in your dotCMS instance with a configured OpenAI API key. See the [dotAI setup documentation](https://dev.dotcms.com/docs/dotai) for configuration details.
|
|
782
|
+
|
|
783
|
+
```typescript
|
|
784
|
+
search<T extends DotCMSBasicContentlet>(
|
|
785
|
+
prompt: string,
|
|
786
|
+
indexName: string,
|
|
787
|
+
params?: DotCMSAISearchParams
|
|
788
|
+
): Promise<DotCMSAISearchResponse<T>>
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
#### Parameters
|
|
792
|
+
|
|
793
|
+
| Parameter | Type | Required | Description |
|
|
794
|
+
| ----------- | --------------------- | -------- | ------------------------------------- |
|
|
795
|
+
| `prompt` | string | ✅ | Natural language search query |
|
|
796
|
+
| `indexName` | string | ✅ | Name of the AI search index to query |
|
|
797
|
+
| `params` | DotCMSAISearchParams | ❌ | Search configuration options |
|
|
798
|
+
|
|
799
|
+
#### Search Parameters (params.query)
|
|
800
|
+
|
|
801
|
+
| Option | Type | Description |
|
|
802
|
+
| ------------- | ---------------- | ---------------------------------------- |
|
|
803
|
+
| `limit` | number | Maximum number of results (default: 1000) |
|
|
804
|
+
| `offset` | number | Number of results to skip (default: 0) |
|
|
805
|
+
| `contentType` | string | Filter by specific content type |
|
|
806
|
+
| `languageId` | string | Filter by language ID |
|
|
807
|
+
| `siteId` | string | Filter by site ID |
|
|
808
|
+
|
|
809
|
+
#### AI Configuration (params.config)
|
|
810
|
+
|
|
811
|
+
| Option | Type | Description |
|
|
812
|
+
| ------------------ | ------ | ----------------------------------------------- |
|
|
813
|
+
| `threshold` | number | Minimum similarity score (0-1, default: 0.5) |
|
|
814
|
+
| `distanceFunction` | string | Distance calculation method (default: cosine) |
|
|
815
|
+
| `responseLength` | number | Maximum response length (default: 1024) |
|
|
816
|
+
|
|
817
|
+
#### Response
|
|
818
|
+
|
|
819
|
+
```typescript
|
|
820
|
+
interface DotCMSAISearchResponse<T> {
|
|
821
|
+
results: Array<T & {
|
|
822
|
+
matches?: Array<{
|
|
823
|
+
distance: number; // Similarity score
|
|
824
|
+
extractedText: string; // Matched text excerpt
|
|
825
|
+
}>;
|
|
826
|
+
}>;
|
|
827
|
+
}
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
#### Examples
|
|
831
|
+
|
|
832
|
+
**Basic Search:**
|
|
833
|
+
```typescript
|
|
834
|
+
const results = await client.ai.search(
|
|
835
|
+
'machine learning articles',
|
|
836
|
+
'content_index'
|
|
837
|
+
);
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
**With Parameters:**
|
|
841
|
+
```typescript
|
|
842
|
+
import { DISTANCE_FUNCTIONS } from '@dotcms/types';
|
|
843
|
+
|
|
844
|
+
const results = await client.ai.search(
|
|
845
|
+
'AI tutorials',
|
|
846
|
+
'content_index',
|
|
847
|
+
{
|
|
848
|
+
query: {
|
|
849
|
+
limit: 20,
|
|
850
|
+
contentType: 'BlogPost',
|
|
851
|
+
languageId: '1'
|
|
852
|
+
},
|
|
853
|
+
config: {
|
|
854
|
+
threshold: 0.75,
|
|
855
|
+
distanceFunction: DISTANCE_FUNCTIONS.cosine
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
);
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
**Promise-Style:**
|
|
862
|
+
```typescript
|
|
863
|
+
client.ai.search(
|
|
864
|
+
'content management best practices',
|
|
865
|
+
'content_index',
|
|
866
|
+
{
|
|
867
|
+
query: { limit: 10 },
|
|
868
|
+
config: { threshold: 0.8 }
|
|
869
|
+
}
|
|
870
|
+
).then((response) => {
|
|
871
|
+
console.log('Found:', response.results.length);
|
|
872
|
+
return response;
|
|
873
|
+
}).catch((error) => {
|
|
874
|
+
console.error('Search failed:', error.message);
|
|
875
|
+
});
|
|
876
|
+
```
|
|
877
|
+
|
|
424
878
|
### navigation.get() Method
|
|
425
879
|
|
|
426
880
|
```typescript
|
|
@@ -458,12 +912,13 @@ The SDK provides comprehensive error handling with specific error types for diff
|
|
|
458
912
|
|
|
459
913
|
#### Error Types
|
|
460
914
|
|
|
461
|
-
| Error Type
|
|
462
|
-
|
|
|
463
|
-
| `DotHttpError`
|
|
464
|
-
| `DotErrorPage`
|
|
465
|
-
| `DotErrorContent`
|
|
466
|
-
| `
|
|
915
|
+
| Error Type | When It's Thrown | Properties |
|
|
916
|
+
| -------------------- | ------------------------------------------ | --------------------------------------------------- |
|
|
917
|
+
| `DotHttpError` | HTTP/network failures (4xx/5xx, timeouts) | `status`, `statusText`, `headers`, `body` |
|
|
918
|
+
| `DotErrorPage` | Page API failures | `httpError?`, `context` (query, variables) |
|
|
919
|
+
| `DotErrorContent` | Content API failures | `contentType`, `operation`, `httpError?`, `query?` |
|
|
920
|
+
| `DotErrorAISearch` | AI Search API failures | `prompt`, `params`, `httpError?` |
|
|
921
|
+
| `DotErrorNavigation` | Navigation API failures | `path`, `httpError?` |
|
|
467
922
|
|
|
468
923
|
#### Basic Error Handling
|
|
469
924
|
```typescript
|
|
@@ -513,6 +968,23 @@ try {
|
|
|
513
968
|
}
|
|
514
969
|
```
|
|
515
970
|
|
|
971
|
+
#### AI Search Error Handling
|
|
972
|
+
```typescript
|
|
973
|
+
try {
|
|
974
|
+
const results = await client.ai.search('machine learning', 'content_index');
|
|
975
|
+
} catch (error) {
|
|
976
|
+
if (error instanceof DotErrorAISearch) {
|
|
977
|
+
console.error('AI Search error:', error.message);
|
|
978
|
+
console.error('Prompt:', error.prompt);
|
|
979
|
+
console.error('Index Name:', error.indexName);
|
|
980
|
+
console.error('Parameters:', error.params);
|
|
981
|
+
if (error.httpError) {
|
|
982
|
+
console.error('HTTP status:', error.httpError.status);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
```
|
|
987
|
+
|
|
516
988
|
#### Promise-Style Error Handling
|
|
517
989
|
```typescript
|
|
518
990
|
// Content collections support .then() with error handling
|
|
@@ -571,13 +1043,14 @@ DotHttpError: "Network request failed"
|
|
|
571
1043
|
|
|
572
1044
|
### Choosing the Right Method
|
|
573
1045
|
|
|
574
|
-
The dotCMS Client SDK provides
|
|
1046
|
+
The dotCMS Client SDK provides four core methods for fetching data. Use this quick guide to decide which one is best for your use case:
|
|
575
1047
|
|
|
576
|
-
| Method
|
|
577
|
-
|
|
|
578
|
-
| `client.page.get()`
|
|
1048
|
+
| Method | Use When You Need... | Best For |
|
|
1049
|
+
| -------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1050
|
+
| `client.page.get()` | A full page with layout, containers, and related content | **Rendering entire pages** with a single request. Ideal for headless setups, SSR/SSG frameworks, and cases where you want everything—page structure, content, and navigation—tied to a URL path. |
|
|
579
1051
|
| `client.content.getCollection()` | A filtered list of content items from a specific content type | Populating dynamic blocks, lists, search results, widgets, or reusable components. |
|
|
580
|
-
| `client.
|
|
1052
|
+
| `client.ai.search()` | Semantic/AI-powered content discovery based on natural language | **Intelligent search experiences** where users describe what they're looking for in natural language. Great for search features, content recommendations, and finding relevant content by meaning rather than exact keywords. ⚠️ **Experimental API** |
|
|
1053
|
+
| `client.navigation.get()` | Only the site's navigation structure (folders and links) | Standalone menus or use cases where navigation is needed outside of page context. |
|
|
581
1054
|
|
|
582
1055
|
#### Start with `page.get()`: The One-Request Solution
|
|
583
1056
|
|
|
@@ -595,27 +1068,27 @@ Only use `content.getCollection()` or `navigation.get()` if you have advanced ne
|
|
|
595
1068
|
|
|
596
1069
|
### Architecture Overview
|
|
597
1070
|
|
|
598
|
-
The SDK follows a client-builder pattern with
|
|
1071
|
+
The SDK follows a client-builder pattern with four main APIs:
|
|
599
1072
|
|
|
600
1073
|
- **Page API** (`client.page.get()`) - Fetches complete page content with layout and containers
|
|
601
1074
|
- **Content API** (`client.content.getCollection()`) - Builder pattern for querying content collections
|
|
1075
|
+
- **AI API** (`client.ai.search()`) - AI-powered semantic search using embeddings and vector similarity ⚠️ **Experimental**
|
|
602
1076
|
- **Navigation API** (`client.navigation.get()`) - Fetches site navigation structure
|
|
603
1077
|
|
|
604
1078
|
All APIs support:
|
|
605
1079
|
- Type-safe responses with TypeScript
|
|
606
|
-
- GraphQL query extensions
|
|
1080
|
+
- GraphQL query extensions (Page API)
|
|
607
1081
|
- Localization and personalization
|
|
608
1082
|
- Browser and Node.js compatibility
|
|
609
1083
|
|
|
610
|
-
## Support
|
|
611
|
-
|
|
612
|
-
### dotCMS Support
|
|
1084
|
+
## Support
|
|
613
1085
|
|
|
614
1086
|
We offer multiple channels to get help with the dotCMS Client SDK:
|
|
615
1087
|
|
|
616
1088
|
- **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository.
|
|
617
1089
|
- **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions.
|
|
618
1090
|
- **Stack Overflow**: Use the tag `dotcms-client` when posting questions.
|
|
1091
|
+
- **Enterprise Support**: Enterprise customers can access premium support through the [dotCMS Support Portal](https://helpdesk.dotcms.com/support/).
|
|
619
1092
|
|
|
620
1093
|
When reporting issues, please include:
|
|
621
1094
|
|
|
@@ -624,11 +1097,9 @@ When reporting issues, please include:
|
|
|
624
1097
|
- Minimal reproduction steps
|
|
625
1098
|
- Expected vs. actual behavior
|
|
626
1099
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
### How To Contribute
|
|
1100
|
+
## Contributing
|
|
630
1101
|
|
|
631
|
-
GitHub pull requests are the preferred method to contribute code to dotCMS. We welcome contributions to the
|
|
1102
|
+
GitHub pull requests are the preferred method to contribute code to dotCMS. We welcome contributions to the dotCMS Client SDK! If you'd like to contribute, please follow these steps:
|
|
632
1103
|
|
|
633
1104
|
1. Fork the repository [dotCMS/core](https://github.com/dotCMS/core)
|
|
634
1105
|
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
@@ -640,6 +1111,56 @@ Please ensure your code follows the existing style and includes appropriate test
|
|
|
640
1111
|
|
|
641
1112
|
## Changelog
|
|
642
1113
|
|
|
1114
|
+
### v1.3.0
|
|
1115
|
+
|
|
1116
|
+
#### ✨ Added - AI Search API (Experimental)
|
|
1117
|
+
|
|
1118
|
+
> **⚠️ Experimental Feature:** The AI API is experimental and may undergo breaking changes in future releases.
|
|
1119
|
+
|
|
1120
|
+
**New Features:**
|
|
1121
|
+
- **`client.ai.search()`** - AI-powered semantic search using embeddings and vector similarity
|
|
1122
|
+
- Search content by meaning rather than exact keyword matches
|
|
1123
|
+
- Support for custom AI search indexes
|
|
1124
|
+
- Configurable similarity thresholds and distance functions
|
|
1125
|
+
- `DotErrorAISearch` error class for AI-specific error handling with prompt and index context
|
|
1126
|
+
|
|
1127
|
+
**Prerequisites:**
|
|
1128
|
+
- Requires dotAI to be activated in your dotCMS instance
|
|
1129
|
+
- OpenAI API key must be configured
|
|
1130
|
+
- PostgreSQL 15+ with pgvector extension
|
|
1131
|
+
- Content indexes must be created in dotAI
|
|
1132
|
+
|
|
1133
|
+
**Basic Usage:**
|
|
1134
|
+
```typescript
|
|
1135
|
+
// Semantic search with required index name
|
|
1136
|
+
const results = await client.ai.search(
|
|
1137
|
+
'machine learning articles',
|
|
1138
|
+
'content_index'
|
|
1139
|
+
);
|
|
1140
|
+
|
|
1141
|
+
// With advanced configuration
|
|
1142
|
+
const results = await client.ai.search(
|
|
1143
|
+
'AI tutorials',
|
|
1144
|
+
'content_index',
|
|
1145
|
+
{
|
|
1146
|
+
query: {
|
|
1147
|
+
limit: 20,
|
|
1148
|
+
contentType: 'BlogPost'
|
|
1149
|
+
},
|
|
1150
|
+
config: {
|
|
1151
|
+
threshold: 0.75,
|
|
1152
|
+
distanceFunction: DISTANCE_FUNCTIONS.cosine
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
);
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
**Key Features:**
|
|
1159
|
+
- Type-safe with full TypeScript support
|
|
1160
|
+
- Supports multiple distance functions (cosine, L2, inner product, etc.)
|
|
1161
|
+
- Returns match scores and extracted text excerpts
|
|
1162
|
+
- Integrates seamlessly with existing content workflows
|
|
1163
|
+
|
|
643
1164
|
### v1.1.1
|
|
644
1165
|
|
|
645
1166
|
Version 1.1.1 introduces significant improvements to error handling and HTTP client architecture. Most applications will continue to work without changes.
|
|
@@ -748,7 +1269,7 @@ import { RequestOptions } from '@dotcms/types';
|
|
|
748
1269
|
import { DotRequestOptions } from '@dotcms/types';
|
|
749
1270
|
```
|
|
750
1271
|
|
|
751
|
-
|
|
1272
|
+
## Licensing
|
|
752
1273
|
|
|
753
1274
|
dotCMS comes in multiple editions and as such is dual-licensed. The dotCMS Community Edition is licensed under the GPL 3.0 and is freely available for download, customization, and deployment for use within organizations of all stripes. dotCMS Enterprise Editions (EE) adds several enterprise features and is available via a supported, indemnified commercial license from dotCMS. For the differences between the editions, see [the feature page](http://www.dotcms.com/cms-platform/features).
|
|
754
1275
|
|