@dotcms/client 0.0.1-beta.2 → 0.0.1-beta.21

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.
Files changed (47) hide show
  1. package/README.md +164 -36
  2. package/index.cjs.js +102 -1238
  3. package/index.esm.js +86 -1221
  4. package/next.cjs.d.ts +1 -0
  5. package/next.cjs.default.js +1 -0
  6. package/next.cjs.js +575 -0
  7. package/next.cjs.mjs +2 -0
  8. package/next.esm.d.ts +1 -0
  9. package/next.esm.js +573 -0
  10. package/package.json +32 -7
  11. package/src/index.d.ts +6 -6
  12. package/src/lib/client/client.d.ts +84 -0
  13. package/src/lib/client/content/builders/collection/collection.d.ts +1 -1
  14. package/src/lib/client/content/content-api.d.ts +1 -1
  15. package/src/lib/client/content/shared/types.d.ts +2 -2
  16. package/src/lib/client/models/types.d.ts +573 -10
  17. package/src/lib/client/navigation/navigation-api.d.ts +31 -0
  18. package/src/lib/client/page/page-api.d.ts +172 -0
  19. package/src/lib/client/page/utils.d.ts +41 -0
  20. package/src/lib/{editor → deprecated/editor}/models/client.model.d.ts +13 -0
  21. package/src/lib/{editor → deprecated/editor}/sdk-editor.d.ts +1 -1
  22. package/src/lib/{client → deprecated}/sdk-js-client.d.ts +1 -1
  23. package/src/lib/utils/page/common-utils.d.ts +1 -1
  24. package/src/next.d.ts +1 -0
  25. package/src/types.d.ts +2 -0
  26. package/transforms.cjs.js +1149 -0
  27. package/transforms.esm.js +1143 -0
  28. package/types.cjs.d.ts +1 -0
  29. package/types.cjs.default.js +1 -0
  30. package/types.cjs.js +2 -0
  31. package/types.cjs.mjs +2 -0
  32. package/types.esm.d.ts +1 -0
  33. package/types.esm.js +1 -0
  34. /package/src/lib/{query-builder → client/content/builders/query}/lucene-syntax/Equals.d.ts +0 -0
  35. /package/src/lib/{query-builder → client/content/builders/query}/lucene-syntax/Field.d.ts +0 -0
  36. /package/src/lib/{query-builder → client/content/builders/query}/lucene-syntax/NotOperand.d.ts +0 -0
  37. /package/src/lib/{query-builder → client/content/builders/query}/lucene-syntax/Operand.d.ts +0 -0
  38. /package/src/lib/{query-builder → client/content/builders/query}/lucene-syntax/index.d.ts +0 -0
  39. /package/src/lib/{query-builder/sdk-query-builder.d.ts → client/content/builders/query/query.d.ts} +0 -0
  40. /package/src/lib/{query-builder → client/content/builders/query}/utils/index.d.ts +0 -0
  41. /package/src/lib/{editor → deprecated/editor}/listeners/listeners.d.ts +0 -0
  42. /package/src/lib/{editor → deprecated/editor}/models/editor.model.d.ts +0 -0
  43. /package/src/lib/{editor → deprecated/editor}/models/inline-event.model.d.ts +0 -0
  44. /package/src/lib/{editor → deprecated/editor}/models/listeners.model.d.ts +0 -0
  45. /package/src/lib/{editor → deprecated/editor}/sdk-editor-vtl.d.ts +0 -0
  46. /package/src/lib/{editor → deprecated/editor}/utils/editor.utils.d.ts +0 -0
  47. /package/src/lib/{editor → deprecated/editor}/utils/traditional-vtl.utils.d.ts +0 -0
package/next.cjs.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/next";
@@ -0,0 +1 @@
1
+ exports._default = require('./next.cjs.js').default;
package/next.cjs.js ADDED
@@ -0,0 +1,575 @@
1
+ 'use strict';
2
+
3
+ var transforms = require('./transforms.cjs.js');
4
+
5
+ class NavigationClient {
6
+ constructor(config, requestOptions) {
7
+ this.requestOptions = requestOptions;
8
+ this.BASE_URL = `${config?.dotcmsUrl}/api/v1/nav`;
9
+ }
10
+ /**
11
+ * Retrieves information about the dotCMS file and folder tree.
12
+ * @param {NavigationApiOptions} options - The options for the Navigation API call. Defaults to `{ depth: 0, path: '/', languageId: 1 }`.
13
+ * @returns {Promise<unknown>} - A Promise that resolves to the response from the DotCMS API.
14
+ * @throws {Error} - Throws an error if the options are not valid.
15
+ */
16
+ async get(path, params) {
17
+ if (!path) {
18
+ throw new Error("The 'path' parameter is required for the Navigation API");
19
+ }
20
+ const navParams = params ? this.mapToBackendParams(params) : {};
21
+ const urlParams = new URLSearchParams(navParams).toString();
22
+ const parsedPath = path.replace(/^\/+/, '/').replace(/\/+$/, '/');
23
+ const url = `${this.BASE_URL}${parsedPath}${urlParams ? `?${urlParams}` : ''}`;
24
+ const response = await fetch(url, this.requestOptions);
25
+ if (!response.ok) {
26
+ throw new Error(`Failed to fetch navigation data: ${response.statusText} - ${response.status}`);
27
+ }
28
+ return response.json().then((data) => data.entity);
29
+ }
30
+ mapToBackendParams(params) {
31
+ const backendParams = {};
32
+ if (params.depth) {
33
+ backendParams['depth'] = String(params.depth);
34
+ }
35
+ if (params.languageId) {
36
+ backendParams['language_id'] = String(params.languageId);
37
+ }
38
+ return backendParams;
39
+ }
40
+ }
41
+
42
+ const DEFAULT_PAGE_CONTENTLETS_CONTENT = `
43
+ publishDate
44
+ inode
45
+ identifier
46
+ archived
47
+ urlMap
48
+ urlMap
49
+ locked
50
+ contentType
51
+ creationDate
52
+ modDate
53
+ title
54
+ baseType
55
+ working
56
+ live
57
+ publishUser {
58
+ firstName
59
+ lastName
60
+ }
61
+ owner {
62
+ lastName
63
+ }
64
+ conLanguage {
65
+ language
66
+ languageCode
67
+ }
68
+ modUser {
69
+ firstName
70
+ lastName
71
+ }
72
+ `;
73
+ /**
74
+ * Builds a GraphQL query for retrieving page content from DotCMS.
75
+ *
76
+ * @param {string} pageQuery - Custom fragment fields to include in the ClientPage fragment
77
+ * @param {string} additionalQueries - Additional GraphQL queries to include in the main query
78
+ * @returns {string} Complete GraphQL query string for page content
79
+ */
80
+ const buildPageQuery = ({ page, fragments, additionalQueries }) => {
81
+ if (!page) {
82
+ console.warn('No page query provided. The query will be used by fetching all content with _map. This may mean poor performance in the query. We suggest you provide a detailed query on page attribute.');
83
+ }
84
+ return `
85
+ fragment DotCMSPage on DotPage {
86
+ publishDate
87
+ type
88
+ httpsRequired
89
+ inode
90
+ path
91
+ identifier
92
+ hasTitleImage
93
+ sortOrder
94
+ extension
95
+ canRead
96
+ pageURI
97
+ canEdit
98
+ archived
99
+ friendlyName
100
+ workingInode
101
+ url
102
+ hasLiveVersion
103
+ deleted
104
+ pageUrl
105
+ shortyWorking
106
+ mimeType
107
+ locked
108
+ stInode
109
+ contentType
110
+ creationDate
111
+ liveInode
112
+ name
113
+ shortyLive
114
+ modDate
115
+ title
116
+ baseType
117
+ working
118
+ canLock
119
+ live
120
+ isContentlet
121
+ statusIcons
122
+ canEdit
123
+ canLock
124
+ canRead
125
+ canEdit
126
+ canLock
127
+ canRead
128
+ urlContentMap {
129
+ _map
130
+ }
131
+ conLanguage {
132
+ id
133
+ language
134
+ languageCode
135
+ }
136
+ template {
137
+ drawed
138
+ }
139
+ containers {
140
+ path
141
+ identifier
142
+ maxContentlets
143
+ containerStructures {
144
+ id
145
+ code
146
+ structureId
147
+ containerId
148
+ contentTypeVar
149
+ containerInode
150
+ }
151
+ containerContentlets {
152
+ uuid
153
+ contentlets {
154
+ ${page ? DEFAULT_PAGE_CONTENTLETS_CONTENT : '_map'}
155
+ }
156
+ }
157
+ }
158
+ layout {
159
+ header
160
+ footer
161
+ body {
162
+ rows {
163
+ columns {
164
+ leftOffset
165
+ styleClass
166
+ width
167
+ left
168
+ containers {
169
+ identifier
170
+ uuid
171
+ }
172
+ }
173
+ }
174
+ }
175
+ }
176
+ viewAs {
177
+ visitor {
178
+ persona {
179
+ name
180
+ }
181
+ }
182
+ language {
183
+ id
184
+ languageCode
185
+ countryCode
186
+ language
187
+ country
188
+ }
189
+ }
190
+ }
191
+
192
+ ${page ? ` fragment ClientPage on DotPage { ${page} } ` : ''}
193
+
194
+ ${fragments ? fragments.join('\n\n') : ''}
195
+
196
+ query PageContent($url: String!, $languageId: String, $mode: String, $personaId: String, $fireRules: Boolean, $publishDate: String, $siteId: String) {
197
+ page: page(url: $url, languageId: $languageId, pageMode: $mode, persona: $personaId, fireRules: $fireRules, publishDate: $publishDate, site: $siteId) {
198
+ ...DotCMSPage
199
+ ${page ? '...ClientPage' : ''}
200
+ }
201
+
202
+ ${additionalQueries}
203
+ }
204
+ `;
205
+ };
206
+ /**
207
+ * Converts a record of query strings into a single GraphQL query string.
208
+ *
209
+ * @param {Record<string, string>} queryData - Object containing named query strings
210
+ * @returns {string} Combined query string or empty string if no queryData provided
211
+ */
212
+ function buildQuery(queryData) {
213
+ if (!queryData)
214
+ return '';
215
+ return Object.entries(queryData)
216
+ .map(([key, query]) => `${key}: ${query}`)
217
+ .join(' ');
218
+ }
219
+ /**
220
+ * Filters response data to include only specified keys.
221
+ *
222
+ * @param {Record<string, string>} responseData - Original response data object
223
+ * @param {string[]} keys - Array of keys to extract from the response data
224
+ * @returns {Record<string, string>} New object containing only the specified keys
225
+ */
226
+ function mapResponseData(responseData, keys) {
227
+ return keys.reduce((accumulator, key) => {
228
+ if (responseData[key] !== undefined) {
229
+ accumulator[key] = responseData[key];
230
+ }
231
+ return accumulator;
232
+ }, {});
233
+ }
234
+ /**
235
+ * Executes a GraphQL query against the DotCMS API.
236
+ *
237
+ * @param {Object} options - Options for the fetch request
238
+ * @param {string} options.body - GraphQL query string
239
+ * @param {Record<string, string>} options.headers - HTTP headers for the request
240
+ * @returns {Promise<any>} Parsed JSON response from the GraphQL API
241
+ * @throws {Error} If the HTTP response is not successful
242
+ */
243
+ async function fetchGraphQL({ baseURL, body, headers }) {
244
+ const url = new URL(baseURL);
245
+ url.pathname = '/api/v1/graphql';
246
+ const response = await fetch(url.toString(), {
247
+ method: 'POST',
248
+ body,
249
+ headers
250
+ });
251
+ if (!response.ok) {
252
+ const error = {
253
+ status: response.status,
254
+ message: transforms.ErrorMessages[response.status] || response.statusText
255
+ };
256
+ throw error;
257
+ }
258
+ return await response.json();
259
+ }
260
+
261
+ var _PageClient_instances, _PageClient_isGraphQLRequest, _PageClient_getPageFromAPI, _PageClient_getPageFromGraphQL, _PageClient_mapToBackendParams;
262
+ /**
263
+ * Client for interacting with the DotCMS Page API.
264
+ * Provides methods to retrieve and manipulate pages.
265
+ */
266
+ class PageClient {
267
+ /**
268
+ * Creates a new PageClient instance.
269
+ *
270
+ * @param {DotCMSClientConfig} config - Configuration options for the DotCMS client
271
+ * @param {RequestOptions} requestOptions - Options for fetch requests including authorization headers
272
+ * @example
273
+ * ```typescript
274
+ * const pageClient = new PageClient(
275
+ * {
276
+ * dotcmsUrl: 'https://demo.dotcms.com',
277
+ * authToken: 'your-auth-token',
278
+ * siteId: 'demo.dotcms.com'
279
+ * },
280
+ * {
281
+ * headers: {
282
+ * Authorization: 'Bearer your-auth-token'
283
+ * }
284
+ * }
285
+ * );
286
+ * ```
287
+ */
288
+ constructor(config, requestOptions) {
289
+ _PageClient_instances.add(this);
290
+ this.requestOptions = requestOptions;
291
+ this.siteId = config.siteId || '';
292
+ this.dotcmsUrl = config.dotcmsUrl;
293
+ }
294
+ get(url, options) {
295
+ if (!options) {
296
+ return transforms.__classPrivateFieldGet(this, _PageClient_instances, "m", _PageClient_getPageFromAPI).call(this, url);
297
+ }
298
+ if (transforms.__classPrivateFieldGet(this, _PageClient_instances, "m", _PageClient_isGraphQLRequest).call(this, options)) {
299
+ return transforms.__classPrivateFieldGet(this, _PageClient_instances, "m", _PageClient_getPageFromGraphQL).call(this, url, options);
300
+ }
301
+ return transforms.__classPrivateFieldGet(this, _PageClient_instances, "m", _PageClient_getPageFromAPI).call(this, url, options);
302
+ }
303
+ }
304
+ _PageClient_instances = new WeakSet(), _PageClient_isGraphQLRequest = function _PageClient_isGraphQLRequest(options) {
305
+ return 'graphql' in options;
306
+ }, _PageClient_getPageFromAPI =
307
+ /**
308
+ * Retrieves all the elements of a Page in your dotCMS system in JSON format.
309
+ *
310
+ * @param {string} path - The path of the page to retrieve
311
+ * @param {PageRequestParams} params - The options for the Page API call
312
+ * @returns {Promise<unknown>} A Promise that resolves to the page data
313
+ * @throws {Error} Throws an error if the path parameter is missing or if the fetch request fails
314
+ * @example
315
+ * ```typescript
316
+ * // Get a page with default parameters
317
+ * const homePage = await pageClient.get('/');
318
+ *
319
+ * // Get a page with specific language and mode
320
+ * const aboutPage = await pageClient.get('/about-us', {
321
+ * languageId: 2,
322
+ * mode: 'PREVIEW_MODE'
323
+ * });
324
+ *
325
+ * // Get a page with persona targeting
326
+ * const productPage = await pageClient.get('/products', {
327
+ * personaId: 'persona-123',
328
+ * depth: 2
329
+ * });
330
+ * ```
331
+ */
332
+ async function _PageClient_getPageFromAPI(path, params) {
333
+ if (!path) {
334
+ throw new Error("The 'path' parameter is required for the Page API");
335
+ }
336
+ // If the siteId is not provided, use the one from the config
337
+ const completedParams = {
338
+ ...(params ?? {}),
339
+ siteId: params?.siteId || this.siteId
340
+ };
341
+ // Map the public parameters to the one used by the API
342
+ const normalizedParams = transforms.__classPrivateFieldGet(this, _PageClient_instances, "m", _PageClient_mapToBackendParams).call(this, completedParams || {});
343
+ // Build the query params
344
+ const queryParams = new URLSearchParams(normalizedParams).toString();
345
+ // If the path starts with a slash, remove it to avoid double slashes in the final URL
346
+ // Because the page path is part of api url path
347
+ const pagePath = path.startsWith('/') ? path.slice(1) : path;
348
+ const url = `${this.dotcmsUrl}/api/v1/page/json/${pagePath}?${queryParams}`;
349
+ const response = await fetch(url, this.requestOptions);
350
+ if (!response.ok) {
351
+ const error = {
352
+ status: response.status,
353
+ message: transforms.ErrorMessages[response.status] || response.statusText
354
+ };
355
+ throw error;
356
+ }
357
+ return response.json().then((data) => ({
358
+ ...data.entity,
359
+ params: completedParams // We retrieve the params from the API response, to make the same fetch on UVE
360
+ }));
361
+ }, _PageClient_getPageFromGraphQL =
362
+ /**
363
+ * Retrieves a personalized page with associated content and navigation.
364
+ *
365
+ * @param {Object} options - Options for the personalized page request
366
+ * @param {string} options.url - The URL of the page to retrieve
367
+ * @param {string} options.languageId - The language ID for the page content
368
+ * @param {string} options.mode - The rendering mode for the page
369
+ * @param {string} options.pageFragment - GraphQL fragment for page data
370
+ * @param {Record<string, string>} options.content - Content queries to include
371
+ * @param {Record<string, string>} options.nav - Navigation queries to include
372
+ * @returns {Promise<Object>} A Promise that resolves to the personalized page data with content and navigation
373
+ * @example
374
+ * ```typescript
375
+ * // Get a personalized page with content and navigation
376
+ * const personalizedPage = await pageClient.getPageFromGraphQL({
377
+ * url: '/about-us',
378
+ * languageId: '1',
379
+ * mode: 'LIVE',
380
+ * pageFragment: `
381
+ * fragment PageFields on Page {
382
+ * title
383
+ * description
384
+ * modDate
385
+ * }
386
+ * `,
387
+ * content: {
388
+ * blogs: `
389
+ * search(query: "+contentType: blog", limit: 3) {
390
+ * title
391
+ * ...on Blog {
392
+ * author {
393
+ * title
394
+ * }
395
+ * }
396
+ }
397
+ * nav: {
398
+ * mainNav: `
399
+ * query MainNav {
400
+ * Nav(identifier: "main-nav") {
401
+ * title
402
+ * items {
403
+ * label
404
+ * url
405
+ * }
406
+ * }
407
+ * }
408
+ * `
409
+ * }
410
+ * });
411
+ * ```
412
+ */
413
+ async function _PageClient_getPageFromGraphQL(url, options) {
414
+ const { languageId = '1', mode = 'LIVE', siteId = this.siteId, fireRules = false, personaId, publishDate, graphql = {} } = options || {};
415
+ const { page, content = {}, variables, fragments } = graphql;
416
+ const contentQuery = buildQuery(content);
417
+ const completeQuery = buildPageQuery({
418
+ page,
419
+ fragments,
420
+ additionalQueries: contentQuery
421
+ });
422
+ const requestVariables = {
423
+ url,
424
+ mode,
425
+ languageId,
426
+ personaId,
427
+ fireRules,
428
+ publishDate,
429
+ siteId,
430
+ ...variables
431
+ };
432
+ const requestHeaders = this.requestOptions.headers;
433
+ const requestBody = JSON.stringify({ query: completeQuery, variables: requestVariables });
434
+ try {
435
+ const { data, errors } = await fetchGraphQL({
436
+ baseURL: this.dotcmsUrl,
437
+ body: requestBody,
438
+ headers: requestHeaders
439
+ });
440
+ if (errors) {
441
+ errors.forEach((error) => {
442
+ throw new Error(error.message);
443
+ });
444
+ }
445
+ const pageResponse = transforms.graphqlToPageEntity(data);
446
+ if (!pageResponse) {
447
+ throw new Error('No page data found');
448
+ }
449
+ const contentResponse = mapResponseData(data, Object.keys(content));
450
+ return {
451
+ page: pageResponse,
452
+ content: contentResponse,
453
+ graphql: {
454
+ query: completeQuery,
455
+ variables: requestVariables
456
+ }
457
+ };
458
+ }
459
+ catch (error) {
460
+ const errorMessage = {
461
+ error,
462
+ message: 'Failed to retrieve page data',
463
+ graphql: {
464
+ query: completeQuery,
465
+ variables: requestVariables
466
+ }
467
+ };
468
+ throw errorMessage;
469
+ }
470
+ }, _PageClient_mapToBackendParams = function _PageClient_mapToBackendParams(params) {
471
+ const backendParams = {
472
+ hostId: params.siteId,
473
+ mode: params.mode,
474
+ language_id: params.languageId ? String(params.languageId) : undefined,
475
+ 'com.dotmarketing.persona.id': params.personaId,
476
+ fireRules: params.fireRules ? String(params.fireRules) : undefined,
477
+ depth: params.depth ? String(params.depth) : undefined,
478
+ publishDate: params.publishDate
479
+ };
480
+ // Remove undefined values
481
+ return Object.fromEntries(Object.entries(backendParams).filter(([_, value]) => value !== undefined));
482
+ };
483
+
484
+ /**
485
+ * Parses a string into a URL object.
486
+ *
487
+ * @param url - The URL string to parse
488
+ * @returns A URL object if parsing is successful, undefined otherwise
489
+ */
490
+ function parseURL(url) {
491
+ try {
492
+ return new URL(url);
493
+ }
494
+ catch {
495
+ console.error('Invalid URL:', url);
496
+ return undefined;
497
+ }
498
+ }
499
+ /**
500
+ * Default configuration for the DotCMS client.
501
+ */
502
+ const defaultConfig = {
503
+ dotcmsUrl: '',
504
+ authToken: '',
505
+ requestOptions: {}
506
+ };
507
+ /**
508
+ * Client for interacting with the DotCMS REST API.
509
+ * Provides access to content, page, and navigation functionality.
510
+ */
511
+ class DotCMSClient {
512
+ /**
513
+ * Creates a new DotCMS client instance.
514
+ *
515
+ * @param config - Configuration options for the client
516
+ * @throws Warning if dotcmsUrl is invalid or authToken is missing
517
+ */
518
+ constructor(config = defaultConfig) {
519
+ this.config = config;
520
+ this.requestOptions = this.createAuthenticatedRequestOptions(this.config);
521
+ // Initialize clients
522
+ this.page = new PageClient(this.config, this.requestOptions);
523
+ this.nav = new NavigationClient(this.config, this.requestOptions);
524
+ this.content = new transforms.Content(this.requestOptions, this.config.dotcmsUrl);
525
+ }
526
+ /**
527
+ * Creates request options with authentication headers.
528
+ *
529
+ * @param config - The client configuration
530
+ * @returns Request options with authorization headers
531
+ */
532
+ createAuthenticatedRequestOptions(config) {
533
+ return {
534
+ ...config.requestOptions,
535
+ headers: {
536
+ ...config.requestOptions?.headers,
537
+ Authorization: `Bearer ${config.authToken}`
538
+ }
539
+ };
540
+ }
541
+ }
542
+ /**
543
+ * Creates and returns a new DotCMS client instance.
544
+ *
545
+ * @param config - Configuration options for the client
546
+ * @returns A configured DotCMS client instance
547
+ * @example
548
+ * ```typescript
549
+ * const client = dotCMSCreateClient({
550
+ * dotcmsUrl: 'https://demo.dotcms.com',
551
+ * authToken: 'your-auth-token'
552
+ * });
553
+ *
554
+ * // Use the client to fetch content
555
+ * const pages = await client.page.get('/about-us');
556
+ * ```
557
+ */
558
+ const createDotCMSClient = (clientConfig) => {
559
+ const { dotcmsUrl, authToken } = clientConfig || {};
560
+ const instanceUrl = parseURL(dotcmsUrl)?.origin;
561
+ if (!instanceUrl) {
562
+ throw new TypeError("Invalid configuration - 'dotcmsUrl' must be a valid URL");
563
+ }
564
+ if (!authToken) {
565
+ throw new TypeError("Invalid configuration - 'authToken' is required");
566
+ }
567
+ const config = {
568
+ ...clientConfig,
569
+ authToken,
570
+ dotcmsUrl: instanceUrl
571
+ };
572
+ return new DotCMSClient(config);
573
+ };
574
+
575
+ exports.createDotCMSClient = createDotCMSClient;
package/next.cjs.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export * from './next.cjs.js';
2
+ export { _default as default } from './next.cjs.default.js';
package/next.esm.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/next";