@dotcms/client 1.0.6 → 1.1.1

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/internal.cjs.js CHANGED
@@ -12,10 +12,9 @@
12
12
  * const pageEntity = graphqlToPageEntity(graphQLPageResponse);
13
13
  * ```
14
14
  */
15
- const graphqlToPageEntity = (graphQLPageResponse) => {
16
- const { page } = graphQLPageResponse;
15
+ const graphqlToPageEntity = (page) => {
17
16
  // If there is no page, return null
18
- if (!page) {
17
+ if (!page || (typeof page === 'object' && Object.keys(page).length === 0)) {
19
18
  return null;
20
19
  }
21
20
  const { layout, template, containers, urlContentMap, viewAs, host, vanityUrl, runningExperimentId, _map, ...pageAsset } = page;
@@ -55,7 +54,7 @@ const graphqlToPageEntity = (graphQLPageResponse) => {
55
54
  const parseContainers = (containers = []) => {
56
55
  return containers.reduce((acc, container) => {
57
56
  const { path, identifier, containerStructures, containerContentlets, ...rest } = container;
58
- const key = (path || identifier);
57
+ const key = path || identifier;
59
58
  acc[key] = {
60
59
  containerStructures,
61
60
  container: {
package/internal.esm.js CHANGED
@@ -10,10 +10,9 @@
10
10
  * const pageEntity = graphqlToPageEntity(graphQLPageResponse);
11
11
  * ```
12
12
  */
13
- const graphqlToPageEntity = (graphQLPageResponse) => {
14
- const { page } = graphQLPageResponse;
13
+ const graphqlToPageEntity = (page) => {
15
14
  // If there is no page, return null
16
- if (!page) {
15
+ if (!page || (typeof page === 'object' && Object.keys(page).length === 0)) {
17
16
  return null;
18
17
  }
19
18
  const { layout, template, containers, urlContentMap, viewAs, host, vanityUrl, runningExperimentId, _map, ...pageAsset } = page;
@@ -53,7 +52,7 @@ const graphqlToPageEntity = (graphQLPageResponse) => {
53
52
  const parseContainers = (containers = []) => {
54
53
  return containers.reduce((acc, container) => {
55
54
  const { path, identifier, containerStructures, containerContentlets, ...rest } = container;
56
- const key = (path || identifier);
55
+ const key = path || identifier;
57
56
  acc[key] = {
58
57
  containerStructures,
59
58
  container: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotcms/client",
3
- "version": "1.0.6",
3
+ "version": "1.1.1",
4
4
  "description": "Official JavaScript library for interacting with DotCMS REST APIs.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,66 @@
1
+ import { BaseHttpClient, DotRequestOptions } from '@dotcms/types';
2
+ /**
3
+ * HTTP client implementation using the Fetch API.
4
+ *
5
+ * Extends BaseHttpClient to provide a standard interface for making HTTP requests.
6
+ * This implementation uses the native Fetch API and handles:
7
+ * - JSON and non-JSON response parsing
8
+ * - HTTP error response parsing and conversion to DotHttpError
9
+ * - Network error handling and wrapping
10
+ * - Content-Type detection for proper response handling
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const client = new FetchHttpClient();
15
+ *
16
+ * // JSON request
17
+ * const data = await client.request<MyType>('/api/data', {
18
+ * method: 'GET',
19
+ * headers: { 'Authorization': 'Bearer token' }
20
+ * });
21
+ *
22
+ * // Non-JSON request (e.g., file download)
23
+ * const response = await client.request<Response>('/api/file.pdf', {
24
+ * method: 'GET'
25
+ * });
26
+ * ```
27
+ */
28
+ export declare class FetchHttpClient extends BaseHttpClient {
29
+ /**
30
+ * Sends an HTTP request using the Fetch API.
31
+ *
32
+ * Implements the abstract request method from BaseHttpClient using the native Fetch API.
33
+ * Automatically handles response parsing based on Content-Type headers and converts
34
+ * HTTP errors to standardized DotHttpError instances.
35
+ *
36
+ * @template T - The expected response type. For JSON responses, T should be the parsed object type.
37
+ * For non-JSON responses, T should be Response or the expected response type.
38
+ * @param url - The URL to send the request to.
39
+ * @param options - Optional fetch options including method, headers, body, etc.
40
+ * @returns Promise that resolves with the parsed response data or the Response object for non-JSON.
41
+ * @throws {DotHttpError} - Throws DotHttpError for HTTP errors (4xx/5xx status codes).
42
+ * @throws {DotHttpError} - Throws DotHttpError for network errors (connection issues, timeouts).
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * // JSON API request
47
+ * const user = await client.request<User>('/api/users/123', {
48
+ * method: 'GET',
49
+ * headers: { 'Accept': 'application/json' }
50
+ * });
51
+ *
52
+ * // POST request with JSON body
53
+ * const result = await client.request<CreateResult>('/api/users', {
54
+ * method: 'POST',
55
+ * headers: { 'Content-Type': 'application/json' },
56
+ * body: JSON.stringify({ name: 'John', email: 'john@example.com' })
57
+ * });
58
+ *
59
+ * // File download (non-JSON response)
60
+ * const response = await client.request<Response>('/api/files/document.pdf', {
61
+ * method: 'GET'
62
+ * });
63
+ * ```
64
+ */
65
+ request<T = unknown>(url: string, options?: DotRequestOptions): Promise<T>;
66
+ }
@@ -9,6 +9,7 @@ import { PageClient } from './page/page-api';
9
9
  declare class DotCMSClient {
10
10
  private config;
11
11
  private requestOptions;
12
+ private httpClient;
12
13
  /**
13
14
  * Client for content-related operations.
14
15
  */
@@ -1,5 +1,5 @@
1
- import { GetCollectionResponse, BuildQuery, SortBy, GetCollectionError, OnFullfilled, OnRejected } from '../../shared/types';
2
- export type ClientOptions = Omit<RequestInit, 'body' | 'method'>;
1
+ import { DotHttpClient, DotRequestOptions, DotCMSClientConfig, DotErrorContent } from '@dotcms/types';
2
+ import { GetCollectionResponse, BuildQuery, SortBy, OnFullfilled, OnRejected } from '../../shared/types';
3
3
  /**
4
4
  * Creates a Builder to filter and fetch content from the content API for a specific content type.
5
5
  *
@@ -12,11 +12,12 @@ export declare class CollectionBuilder<T = unknown> {
12
12
  /**
13
13
  * Creates an instance of CollectionBuilder.
14
14
  * @param {ClientOptions} requestOptions Options for the client request.
15
- * @param {string} serverUrl The server URL.
15
+ * @param {DotCMSClientConfig} config The client configuration.
16
16
  * @param {string} contentType The content type to fetch.
17
+ * @param {DotHttpClient} httpClient HTTP client for making requests.
17
18
  * @memberof CollectionBuilder
18
19
  */
19
- constructor(requestOptions: ClientOptions, serverUrl: string, contentType: string);
20
+ constructor(requestOptions: DotRequestOptions, config: DotCMSClientConfig, contentType: string, httpClient: DotHttpClient);
20
21
  /**
21
22
  * Returns the sort query in the format: field order, field order, ...
22
23
  *
@@ -41,6 +42,14 @@ export declare class CollectionBuilder<T = unknown> {
41
42
  * @memberof CollectionBuilder
42
43
  */
43
44
  private get url();
45
+ /**
46
+ * Returns the site ID from the configuration.
47
+ *
48
+ * @readonly
49
+ * @private
50
+ * @memberof CollectionBuilder
51
+ */
52
+ private get siteId();
44
53
  /**
45
54
  * Returns the current query built.
46
55
  *
@@ -202,10 +211,10 @@ export declare class CollectionBuilder<T = unknown> {
202
211
  *
203
212
  * @param {OnFullfilled} [onfulfilled] A callback that is called when the fetch is successful.
204
213
  * @param {OnRejected} [onrejected] A callback that is called when the fetch fails.
205
- * @return {Promise<GetCollectionResponse<T> | GetCollectionError>} A promise that resolves to the content or rejects with an error.
214
+ * @return {Promise<GetCollectionResponse<T> | DotErrorContent>} A promise that resolves to the content or rejects with an error.
206
215
  * @memberof CollectionBuilder
207
216
  */
208
- then(onfulfilled?: OnFullfilled<T>, onrejected?: OnRejected): Promise<GetCollectionResponse<T> | GetCollectionError>;
217
+ then(onfulfilled?: OnFullfilled<T>, onrejected?: OnRejected): Promise<GetCollectionResponse<T> | DotErrorContent>;
209
218
  /**
210
219
  * Formats the response to the desired format.
211
220
  *
@@ -219,8 +228,45 @@ export declare class CollectionBuilder<T = unknown> {
219
228
  * Calls the content API to fetch the content.
220
229
  *
221
230
  * @private
222
- * @return {Promise<Response>} The fetch response.
231
+ * @return {Promise<GetCollectionRawResponse<T>>} The fetch response data.
232
+ * @throws {DotHttpError} When the HTTP request fails.
223
233
  * @memberof CollectionBuilder
224
234
  */
225
235
  private fetch;
236
+ /**
237
+ * Builds the final Lucene query string by combining the base query with required system constraints.
238
+ *
239
+ * This method constructs the complete query by:
240
+ * 1. Adding language ID filter to ensure content matches the specified language
241
+ * 2. Adding live/draft status filter based on the draft flag
242
+ * 3. Optionally adding site ID constraint if conditions are met
243
+ *
244
+ * Site ID constraint is added only when:
245
+ * - Query doesn't already contain a positive site constraint (+conhost)
246
+ * - Query doesn't explicitly exclude the current site ID (-conhost:currentSiteId)
247
+ * - Site ID is configured in the system
248
+ *
249
+ * @private
250
+ * @returns {string} The complete Lucene query string ready for the Content API
251
+ * @memberof CollectionBuilder
252
+ *
253
+ * @example
254
+ * // For live content in language 1 with site ID 123:
255
+ * // Returns: "+contentType:Blog +languageId:1 +live:true +conhost:123"
256
+ *
257
+ * @example
258
+ * // For draft content without site constraint:
259
+ * // Returns: "+contentType:Blog +languageId:1 +live:false"
260
+ *
261
+ * @example
262
+ * // For content with explicit exclusion of current site (site ID 123):
263
+ * // Query: "+contentType:Blog -conhost:123"
264
+ * // Returns: "+contentType:Blog -conhost:123 +languageId:1 +live:true" (no site ID added)
265
+ *
266
+ * @example
267
+ * // For content with exclusion of different site (site ID 456, current is 123):
268
+ * // Query: "+contentType:Blog -conhost:456"
269
+ * // Returns: "+contentType:Blog -conhost:456 +languageId:1 +live:true +conhost:123" (site ID still added)
270
+ */
271
+ private getFinalQuery;
226
272
  }
@@ -1,4 +1,4 @@
1
- import { RequestOptions } from '@dotcms/types';
1
+ import { DotRequestOptions, DotHttpClient, DotCMSClientConfig } from '@dotcms/types';
2
2
  import { CollectionBuilder } from './builders/collection/collection';
3
3
  /**
4
4
  * Creates a builder to filter and fetch a collection of content items.
@@ -53,10 +53,11 @@ export declare class Content {
53
53
  #private;
54
54
  /**
55
55
  * Creates an instance of Content.
56
- * @param {RequestOptions} requestOptions - The options for the client request.
56
+ * @param {DotRequestOptions} requestOptions - The options for the client request.
57
57
  * @param {string} serverUrl - The server URL.
58
+ * @param {DotHttpClient} httpClient - HTTP client for making requests.
58
59
  */
59
- constructor(requestOptions: RequestOptions, serverUrl: string);
60
+ constructor(config: DotCMSClientConfig, requestOptions: DotRequestOptions, httpClient: DotHttpClient);
60
61
  /**
61
62
  * Takes a content type and returns a builder to filter and fetch the collection.
62
63
  * @param {string} contentType - The content type to get the collection.
@@ -1,4 +1,4 @@
1
- import { Contentlet } from '@dotcms/types';
1
+ import { Contentlet, DotErrorContent } from '@dotcms/types';
2
2
  import { Equals } from '../builders/query/lucene-syntax';
3
3
  import { QueryBuilder } from '../builders/query/query';
4
4
  /**
@@ -28,17 +28,17 @@ export type BuildQuery = (qb: QueryBuilder) => Equals;
28
28
  * @template T - The type of the response.
29
29
  * @callback OnFullfilled
30
30
  * @param {GetCollectionResponse<T>} value - The response value.
31
- * @returns {GetCollectionResponse<T> | PromiseLike<GetCollectionResponse<T>> | void} The processed response or a promise.
31
+ * @returns {GetCollectionResponse<T> | PromiseLike<GetCollectionResponse<T>>} The processed response or a promise.
32
32
  */
33
- export type OnFullfilled<T> = ((value: GetCollectionResponse<T>) => GetCollectionResponse<T> | PromiseLike<GetCollectionResponse<T>> | void) | undefined | null;
33
+ export type OnFullfilled<T> = ((value: GetCollectionResponse<T>) => GetCollectionResponse<T> | PromiseLike<GetCollectionResponse<T>>) | undefined | null;
34
34
  /**
35
35
  * Callback for a rejected promise.
36
36
  *
37
37
  * @callback OnRejected
38
- * @param {GetCollectionError} error - The error object.
39
- * @returns {GetCollectionError | PromiseLike<GetCollectionError> | void} The processed error or a promise.
38
+ * @param {DotErrorContent} error - The content error object.
39
+ * @returns {DotErrorContent | PromiseLike<DotErrorContent>} The processed error or a promise.
40
40
  */
41
- export type OnRejected = ((error: GetCollectionError) => GetCollectionError | PromiseLike<GetCollectionError> | void) | undefined | null;
41
+ export type OnRejected = ((error: DotErrorContent) => DotErrorContent | PromiseLike<DotErrorContent>) | undefined | null;
42
42
  /**
43
43
  * Response of the get collection method.
44
44
  *
@@ -85,13 +85,3 @@ export interface GetCollectionRawResponse<T> {
85
85
  resultsSize: number;
86
86
  };
87
87
  }
88
- /**
89
- * Error object for the get collection method.
90
- */
91
- export interface GetCollectionError {
92
- /**
93
- * The status code of the error.
94
- */
95
- status: number;
96
- [key: string]: unknown;
97
- }
@@ -18,3 +18,39 @@
18
18
  * @returns {string} The sanitized query string.
19
19
  */
20
20
  export declare function sanitizeQueryForContentType(query: string, contentType: string): string;
21
+ /**
22
+ * @description
23
+ * Determines whether a site ID constraint should be added to a query based on existing constraints.
24
+ *
25
+ * The site ID constraint is added only when:
26
+ * - Query doesn't already contain a positive site constraint (+conhost)
27
+ * - Query doesn't explicitly exclude the specified site ID (-conhost:siteId)
28
+ * - Site ID is provided and configured
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const query = '+contentType:Blog +languageId:1';
33
+ * const siteId = '123';
34
+ * const shouldAdd = shouldAddSiteIdConstraint(query, siteId); // true
35
+ * ```
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const query = '+contentType:Blog -conhost:123';
40
+ * const siteId = '123';
41
+ * const shouldAdd = shouldAddSiteIdConstraint(query, siteId); // false (explicitly excluded)
42
+ * ```
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const query = '+contentType:Blog +conhost:456';
47
+ * const siteId = '123';
48
+ * const shouldAdd = shouldAddSiteIdConstraint(query, siteId); // false (already has constraint)
49
+ * ```
50
+ *
51
+ * @export
52
+ * @param {string} query - The Lucene query string to analyze
53
+ * @param {string | number | null | undefined} siteId - The site ID to check for
54
+ * @returns {boolean} True if site ID constraint should be added, false otherwise
55
+ */
56
+ export declare function shouldAddSiteIdConstraint(query: string, siteId: string | number | null | undefined): boolean;
@@ -1,13 +1,15 @@
1
- import { DotCMSClientConfig, DotCMSNavigationRequestParams, RequestOptions, DotCMSNavigationItem } from '@dotcms/types';
1
+ import { DotCMSClientConfig, DotCMSNavigationRequestParams, DotRequestOptions, DotCMSNavigationItem, DotHttpClient } from '@dotcms/types';
2
2
  export declare class NavigationClient {
3
3
  private requestOptions;
4
4
  private BASE_URL;
5
- constructor(config: DotCMSClientConfig, requestOptions: RequestOptions);
5
+ private httpClient;
6
+ constructor(config: DotCMSClientConfig, requestOptions: DotRequestOptions, httpClient: DotHttpClient);
6
7
  /**
7
8
  * Retrieves information about the dotCMS file and folder tree.
8
- * @param {NavigationApiOptions} options - The options for the Navigation API call. Defaults to `{ depth: 0, path: '/', languageId: 1 }`.
9
+ * @param {string} path - The path to retrieve navigation for.
10
+ * @param {DotCMSNavigationRequestParams} params - The options for the Navigation API call.
9
11
  * @returns {Promise<DotCMSNavigationItem[]>} - A Promise that resolves to the response from the DotCMS API.
10
- * @throws {Error} - Throws an error if the options are not valid.
12
+ * @throws {DotErrorNavigation} - Throws a navigation-specific error if the request fails.
11
13
  */
12
14
  get(path: string, params?: DotCMSNavigationRequestParams): Promise<DotCMSNavigationItem[]>;
13
15
  private mapToBackendParams;
@@ -1,4 +1,4 @@
1
- import { DotCMSClientConfig, DotCMSComposedPageResponse, DotCMSExtendedPageResponse, DotCMSPageResponse, DotCMSPageRequestParams, RequestOptions } from '@dotcms/types';
1
+ import { DotCMSClientConfig, DotCMSPageRequestParams, DotCMSPageResponse, DotCMSExtendedPageResponse, DotCMSComposedPageResponse, DotHttpClient, DotRequestOptions } from '@dotcms/types';
2
2
  /**
3
3
  * Client for interacting with the DotCMS Page API.
4
4
  * Provides methods to retrieve and manipulate pages.
@@ -19,11 +19,17 @@ export declare class PageClient {
19
19
  * @private
20
20
  */
21
21
  private dotcmsUrl;
22
+ /**
23
+ * HTTP client for making requests.
24
+ * @private
25
+ */
26
+ private httpClient;
22
27
  /**
23
28
  * Creates a new PageClient instance.
24
29
  *
25
30
  * @param {DotCMSClientConfig} config - Configuration options for the DotCMS client
26
- * @param {RequestOptions} requestOptions - Options for fetch requests including authorization headers
31
+ * @param {DotRequestOptions} requestOptions - Options for fetch requests including authorization headers
32
+ * @param {DotHttpClient} httpClient - HTTP client for making requests
27
33
  * @example
28
34
  * ```typescript
29
35
  * const pageClient = new PageClient(
@@ -36,11 +42,12 @@ export declare class PageClient {
36
42
  * headers: {
37
43
  * Authorization: 'Bearer your-auth-token'
38
44
  * }
39
- * }
45
+ * },
46
+ * httpClient
40
47
  * );
41
48
  * ```
42
49
  */
43
- constructor(config: DotCMSClientConfig, requestOptions: RequestOptions);
50
+ constructor(config: DotCMSClientConfig, requestOptions: DotRequestOptions, httpClient: DotHttpClient);
44
51
  /**
45
52
  * Retrieves a page from DotCMS using GraphQL.
46
53
  *
@@ -48,6 +55,7 @@ export declare class PageClient {
48
55
  * @param {DotCMSPageRequestParams} [options] - Options for the request
49
56
  * @template T - The type of the page and content, defaults to DotCMSBasicPage and Record<string, unknown> | unknown
50
57
  * @returns {Promise<DotCMSComposedPageResponse<T>>} A Promise that resolves to the page data
58
+ * @throws {DotErrorPage} - Throws a page-specific error if the request fails or page is not found
51
59
  *
52
60
  * @example Using GraphQL
53
61
  * ```typescript
@@ -1,3 +1,4 @@
1
+ import { DotHttpClient, DotGraphQLApiResponse } from '@dotcms/types';
1
2
  /**
2
3
  * Builds a GraphQL query for retrieving page content from DotCMS.
3
4
  *
@@ -20,22 +21,24 @@ export declare function buildQuery(queryData: Record<string, string>): string;
20
21
  /**
21
22
  * Filters response data to include only specified keys.
22
23
  *
23
- * @param {Record<string, string>} responseData - Original response data object
24
+ * @param {Record<string, unknown> | undefined} responseData - Original response data object
24
25
  * @param {string[]} keys - Array of keys to extract from the response data
25
- * @returns {Record<string, string>} New object containing only the specified keys
26
+ * @returns {Record<string, unknown> | undefined} New object containing only the specified keys
26
27
  */
27
- export declare function mapResponseData(responseData: Record<string, string>, keys: string[]): Record<string, string>;
28
+ export declare function mapContentResponse(responseData: Record<string, unknown> | undefined, keys: string[]): Record<string, unknown> | undefined;
28
29
  /**
29
30
  * Executes a GraphQL query against the DotCMS API.
30
31
  *
31
32
  * @param {Object} options - Options for the fetch request
32
33
  * @param {string} options.body - GraphQL query string
33
34
  * @param {Record<string, string>} options.headers - HTTP headers for the request
34
- * @returns {Promise<any>} Parsed JSON response from the GraphQL API
35
- * @throws {Error} If the HTTP response is not successful
35
+ * @param {DotHttpClient} options.httpClient - HTTP client for making requests
36
+ * @returns {Promise<DotGraphQLApiResponse>} Parsed JSON response from the GraphQL API
37
+ * @throws {DotHttpError} If the HTTP request fails (non-2xx status or network error)
36
38
  */
37
- export declare function fetchGraphQL({ baseURL, body, headers }: {
39
+ export declare function fetchGraphQL({ baseURL, body, headers, httpClient }: {
38
40
  baseURL: string;
39
41
  body: string;
40
- headers: Record<string, string>;
41
- }): Promise<any>;
42
+ headers?: HeadersInit;
43
+ httpClient: DotHttpClient;
44
+ }): Promise<DotGraphQLApiResponse>;
@@ -1,4 +1,4 @@
1
- import { DotCMSGraphQLPageResponse, DotCMSPageAsset } from '@dotcms/types';
1
+ import { DotCMSGraphQLPage, DotCMSPageAsset } from '@dotcms/types';
2
2
  /**
3
3
  * Transforms a GraphQL Page response to a Page Entity.
4
4
  *
@@ -10,4 +10,4 @@ import { DotCMSGraphQLPageResponse, DotCMSPageAsset } from '@dotcms/types';
10
10
  * const pageEntity = graphqlToPageEntity(graphQLPageResponse);
11
11
  * ```
12
12
  */
13
- export declare const graphqlToPageEntity: (graphQLPageResponse: DotCMSGraphQLPageResponse) => DotCMSPageAsset | null;
13
+ export declare const graphqlToPageEntity: (page: DotCMSGraphQLPage) => DotCMSPageAsset | null;