@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/README.md +538 -13
- package/index.cjs.js +418 -58
- package/index.esm.js +419 -59
- 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 +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/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/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,6 +41,7 @@ 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)
|
|
@@ -49,6 +52,7 @@ The `@dotcms/client` is a powerful JavaScript/TypeScript SDK designed to simplif
|
|
|
49
52
|
- [Contributing](#contributing)
|
|
50
53
|
- [Licensing](#licensing)
|
|
51
54
|
- [Changelog](#changelog)
|
|
55
|
+
- [v1.3.0](#v130)
|
|
52
56
|
- [v1.1.1](#v111)
|
|
53
57
|
|
|
54
58
|
## Getting Started
|
|
@@ -214,6 +218,352 @@ const products = await client.content
|
|
|
214
218
|
.limit(10);
|
|
215
219
|
```
|
|
216
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
|
+
|
|
217
567
|
### How to Work with GraphQL
|
|
218
568
|
|
|
219
569
|
GraphQL allows you to fetch exactly the data you need in a single request:
|
|
@@ -420,6 +770,111 @@ getCollection<T = DotCMSBasicContentlet>(
|
|
|
420
770
|
const blogs = await client.content.getCollection('Blog').limit(10).page(1);
|
|
421
771
|
```
|
|
422
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
|
+
|
|
423
878
|
### navigation.get() Method
|
|
424
879
|
|
|
425
880
|
```typescript
|
|
@@ -457,12 +912,13 @@ The SDK provides comprehensive error handling with specific error types for diff
|
|
|
457
912
|
|
|
458
913
|
#### Error Types
|
|
459
914
|
|
|
460
|
-
| Error Type
|
|
461
|
-
|
|
|
462
|
-
| `DotHttpError`
|
|
463
|
-
| `DotErrorPage`
|
|
464
|
-
| `DotErrorContent`
|
|
465
|
-
| `
|
|
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?` |
|
|
466
922
|
|
|
467
923
|
#### Basic Error Handling
|
|
468
924
|
```typescript
|
|
@@ -512,6 +968,23 @@ try {
|
|
|
512
968
|
}
|
|
513
969
|
```
|
|
514
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
|
+
|
|
515
988
|
#### Promise-Style Error Handling
|
|
516
989
|
```typescript
|
|
517
990
|
// Content collections support .then() with error handling
|
|
@@ -570,13 +1043,14 @@ DotHttpError: "Network request failed"
|
|
|
570
1043
|
|
|
571
1044
|
### Choosing the Right Method
|
|
572
1045
|
|
|
573
|
-
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:
|
|
574
1047
|
|
|
575
|
-
| Method
|
|
576
|
-
|
|
|
577
|
-
| `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. |
|
|
578
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. |
|
|
579
|
-
| `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. |
|
|
580
1054
|
|
|
581
1055
|
#### Start with `page.get()`: The One-Request Solution
|
|
582
1056
|
|
|
@@ -594,15 +1068,16 @@ Only use `content.getCollection()` or `navigation.get()` if you have advanced ne
|
|
|
594
1068
|
|
|
595
1069
|
### Architecture Overview
|
|
596
1070
|
|
|
597
|
-
The SDK follows a client-builder pattern with
|
|
1071
|
+
The SDK follows a client-builder pattern with four main APIs:
|
|
598
1072
|
|
|
599
1073
|
- **Page API** (`client.page.get()`) - Fetches complete page content with layout and containers
|
|
600
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**
|
|
601
1076
|
- **Navigation API** (`client.navigation.get()`) - Fetches site navigation structure
|
|
602
1077
|
|
|
603
1078
|
All APIs support:
|
|
604
1079
|
- Type-safe responses with TypeScript
|
|
605
|
-
- GraphQL query extensions
|
|
1080
|
+
- GraphQL query extensions (Page API)
|
|
606
1081
|
- Localization and personalization
|
|
607
1082
|
- Browser and Node.js compatibility
|
|
608
1083
|
|
|
@@ -636,6 +1111,56 @@ Please ensure your code follows the existing style and includes appropriate test
|
|
|
636
1111
|
|
|
637
1112
|
## Changelog
|
|
638
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
|
+
|
|
639
1164
|
### v1.1.1
|
|
640
1165
|
|
|
641
1166
|
Version 1.1.1 introduces significant improvements to error handling and HTTP client architecture. Most applications will continue to work without changes.
|