@dotcms/client 0.0.1-alpha.9 → 0.0.1-beta.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.
Files changed (54) hide show
  1. package/README.md +166 -19
  2. package/index.cjs.d.ts +1 -0
  3. package/index.cjs.default.js +1 -0
  4. package/index.cjs.js +2050 -0
  5. package/index.cjs.mjs +2 -0
  6. package/index.esm.d.ts +1 -0
  7. package/index.esm.js +2038 -0
  8. package/package.json +36 -25
  9. package/src/index.d.ts +8 -0
  10. package/src/lib/client/content/builders/collection/collection.d.ts +226 -0
  11. package/src/lib/client/content/content-api.d.ts +129 -0
  12. package/src/lib/client/content/shared/const.d.ts +13 -0
  13. package/src/lib/client/content/shared/types.d.ts +138 -0
  14. package/src/lib/client/content/shared/utils.d.ts +20 -0
  15. package/src/lib/client/models/index.d.ts +12 -0
  16. package/src/lib/client/models/types.d.ts +13 -0
  17. package/src/lib/client/sdk-js-client.d.ts +276 -0
  18. package/src/lib/editor/listeners/listeners.d.ts +45 -0
  19. package/src/lib/editor/models/client.model.d.ts +98 -0
  20. package/src/lib/editor/models/editor.model.d.ts +62 -0
  21. package/src/lib/editor/models/inline-event.model.d.ts +9 -0
  22. package/src/lib/editor/models/{listeners.model.ts → listeners.model.d.ts} +17 -8
  23. package/src/lib/editor/sdk-editor-vtl.d.ts +1 -0
  24. package/src/lib/editor/sdk-editor.d.ts +92 -0
  25. package/src/lib/editor/utils/editor.utils.d.ts +159 -0
  26. package/src/lib/editor/utils/traditional-vtl.utils.d.ts +4 -0
  27. package/src/lib/query-builder/lucene-syntax/Equals.d.ts +114 -0
  28. package/src/lib/query-builder/lucene-syntax/Field.d.ts +32 -0
  29. package/src/lib/query-builder/lucene-syntax/NotOperand.d.ts +26 -0
  30. package/src/lib/query-builder/lucene-syntax/Operand.d.ts +44 -0
  31. package/src/lib/query-builder/lucene-syntax/index.d.ts +4 -0
  32. package/src/lib/query-builder/sdk-query-builder.d.ts +76 -0
  33. package/src/lib/query-builder/utils/index.d.ts +142 -0
  34. package/src/lib/utils/graphql/transforms.d.ts +24 -0
  35. package/src/lib/utils/index.d.ts +2 -0
  36. package/src/lib/utils/page/common-utils.d.ts +33 -0
  37. package/.eslintrc.json +0 -18
  38. package/jest.config.ts +0 -15
  39. package/project.json +0 -63
  40. package/src/index.ts +0 -4
  41. package/src/lib/client/sdk-js-client.spec.ts +0 -258
  42. package/src/lib/client/sdk-js-client.ts +0 -297
  43. package/src/lib/editor/listeners/listeners.spec.ts +0 -55
  44. package/src/lib/editor/listeners/listeners.ts +0 -200
  45. package/src/lib/editor/models/client.model.ts +0 -55
  46. package/src/lib/editor/models/editor.model.ts +0 -17
  47. package/src/lib/editor/sdk-editor-vtl.ts +0 -24
  48. package/src/lib/editor/sdk-editor.spec.ts +0 -95
  49. package/src/lib/editor/sdk-editor.ts +0 -70
  50. package/src/lib/editor/utils/editor.utils.spec.ts +0 -164
  51. package/src/lib/editor/utils/editor.utils.ts +0 -151
  52. package/tsconfig.json +0 -22
  53. package/tsconfig.lib.json +0 -10
  54. package/tsconfig.spec.json +0 -9
package/index.cjs.js ADDED
@@ -0,0 +1,2050 @@
1
+ 'use strict';
2
+
3
+ /******************************************************************************
4
+ Copyright (c) Microsoft Corporation.
5
+
6
+ Permission to use, copy, modify, and/or distribute this software for any
7
+ purpose with or without fee is hereby granted.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
16
+ ***************************************************************************** */
17
+ /* global Reflect, Promise, SuppressedError, Symbol */
18
+
19
+
20
+ function __classPrivateFieldGet(receiver, state, kind, f) {
21
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
22
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
23
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
24
+ }
25
+
26
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
27
+ if (kind === "m") throw new TypeError("Private method is not writable");
28
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
29
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
30
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
31
+ }
32
+
33
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
34
+ var e = new Error(message);
35
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
36
+ };
37
+
38
+ var _Field_query;
39
+ /**
40
+ * The `Field` class is used to build a query with a specific field.
41
+ * A Lucene Field is a key used to search for a specific value in a document.
42
+ *
43
+ * @export
44
+ * @class Field
45
+ */
46
+ class Field {
47
+ /**
48
+ * Creates an instance of the `Field` class.
49
+ *
50
+ * @param {string} query - The initial query string.
51
+ */
52
+ constructor(query) {
53
+ this.query = query;
54
+ _Field_query.set(this, '');
55
+ __classPrivateFieldSet(this, _Field_query, this.query, "f");
56
+ }
57
+ /**
58
+ * Appends a term to the query that should be included in the search.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const field = new Field("+myField");
63
+ * field.equals("myValue");
64
+ * ```
65
+ *
66
+ * @param {string} term - The term that should be included in the search.
67
+ * @return {Equals} - An instance of `Equals`.
68
+ * @memberof Field
69
+ */
70
+ equals(term) {
71
+ return buildEquals(__classPrivateFieldGet(this, _Field_query, "f"), term);
72
+ }
73
+ }
74
+ _Field_query = new WeakMap();
75
+
76
+ var _NotOperand_query;
77
+ /**
78
+ * 'NotOperand' Is a Typescript class that provides the ability to use the NOT operand in the lucene query string.
79
+ *
80
+ * @export
81
+ * @class NotOperand
82
+ */
83
+ class NotOperand {
84
+ constructor(query) {
85
+ this.query = query;
86
+ _NotOperand_query.set(this, '');
87
+ __classPrivateFieldSet(this, _NotOperand_query, this.query, "f");
88
+ }
89
+ /**
90
+ * This method appends to the query a term that should be included in the search.
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const notOperand = new NotOperand("+myField");
95
+ * notOperand.equals("myValue");
96
+ * ```
97
+ *
98
+ * @param {string} term - The term that should be included in the search.
99
+ * @return {*} {Equals} - An instance of Equals.
100
+ * @memberof NotOperand
101
+ */
102
+ equals(term) {
103
+ return buildEquals(__classPrivateFieldGet(this, _NotOperand_query, "f"), term);
104
+ }
105
+ }
106
+ _NotOperand_query = new WeakMap();
107
+
108
+ var _Operand_query;
109
+ /**
110
+ * 'Operand' Is a Typescript class that provides the ability to use operands in the lucene query string.}
111
+ * An operand is a logical operator used to join two or more conditions in a query.
112
+ *
113
+ * @export
114
+ * @class Operand
115
+ */
116
+ class Operand {
117
+ constructor(query) {
118
+ this.query = query;
119
+ _Operand_query.set(this, '');
120
+ __classPrivateFieldSet(this, _Operand_query, this.query, "f");
121
+ }
122
+ /**
123
+ * This method appends to the query a term that should be excluded in the search.
124
+ *
125
+ * Ex: "-myValue"
126
+ *
127
+ * @param {string} field - The field that should be excluded in the search.
128
+ * @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
129
+ * @memberof Operand
130
+ */
131
+ excludeField(field) {
132
+ return buildExcludeField(__classPrivateFieldGet(this, _Operand_query, "f"), field);
133
+ }
134
+ /**
135
+ * This method appends to the query a field that should be included in the search.
136
+ *
137
+ * Ex: "+myField:"
138
+ *
139
+ * @param {string} field - The field that should be included in the search.
140
+ * @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
141
+ * @memberof Operand
142
+ */
143
+ field(field) {
144
+ return buildField(__classPrivateFieldGet(this, _Operand_query, "f"), field);
145
+ }
146
+ /**
147
+ * This method appends to the query a term that should be included in the search.
148
+ *
149
+ * Ex: myValue or "My value"
150
+ *
151
+ * @param {string} term - The term that should be included in the search.
152
+ * @return {*} {Equals} - An instance of Equals.
153
+ * @memberof Operand
154
+ */
155
+ equals(term) {
156
+ return buildEquals(__classPrivateFieldGet(this, _Operand_query, "f"), term);
157
+ }
158
+ }
159
+ _Operand_query = new WeakMap();
160
+
161
+ /**
162
+ * Enum for common Operands
163
+ *
164
+ * @export
165
+ * @enum {number}
166
+ */
167
+ var OPERAND;
168
+ (function (OPERAND) {
169
+ OPERAND["OR"] = "OR";
170
+ OPERAND["AND"] = "AND";
171
+ OPERAND["NOT"] = "NOT";
172
+ })(OPERAND || (OPERAND = {}));
173
+ /**
174
+ * This function removes extra spaces from a string.
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * sanitizeQuery(" my query "); // Output: "my query"
179
+ * ```
180
+ *
181
+ * @export
182
+ * @param {string} str
183
+ * @return {*} {string}
184
+ */
185
+ function sanitizeQuery(str) {
186
+ return str.replace(/\s{2,}/g, ' ').trim();
187
+ }
188
+ /**
189
+ * This function sanitizes a term by adding quotes if it contains spaces.
190
+ * In lucene, a term with spaces should be enclosed in quotes.
191
+ *
192
+ * @example
193
+ * ```ts
194
+ * sanitizePhrases(`my term`); // Output: `"my term"`
195
+ * sanitizePhrases(`myterm`); // Output: `myterm`
196
+ * ```
197
+ *
198
+ * @export
199
+ * @param {string} term
200
+ * @return {*} {string}
201
+ */
202
+ function sanitizePhrases(term) {
203
+ return term.includes(' ') ? `'${term}'` : term;
204
+ }
205
+ /**
206
+ * This function builds a term to be used in a lucene query.
207
+ * We need to sanitize the term before adding it to the query.
208
+ *
209
+ * @example
210
+ * ```ts
211
+ * const equals = buildEquals("+myField: ", "myValue"); // Current query: "+myField: myValue"
212
+ * ```
213
+ *
214
+ * @export
215
+ * @param {string} query
216
+ * @param {string} term
217
+ * @return {*} {Equals}
218
+ */
219
+ function buildEquals(query, term) {
220
+ const newQuery = query + sanitizePhrases(term);
221
+ return new Equals(newQuery);
222
+ }
223
+ /**
224
+ * This function builds a term to be used in a lucene query.
225
+ * We need to sanitize the raw query before adding it to the query.
226
+ *
227
+ * @example
228
+ * ```ts
229
+ * const query = "+myField: myValue";
230
+ * const field = buildRawEquals(query, "-myField2: myValue2"); // Current query: "+myField: myValue -myField2: myValue"
231
+ * ```
232
+ *
233
+ * @export
234
+ * @param {string} query
235
+ * @param {string} raw
236
+ * @return {*} {Equals}
237
+ */
238
+ function buildRawEquals(query, raw) {
239
+ const newQuery = query + ` ${raw}`;
240
+ return new Equals(sanitizeQuery(newQuery));
241
+ }
242
+ /**
243
+ * This function builds a field to be used in a lucene query.
244
+ * We need to format the field before adding it to the query.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * const field = buildField("+myField: ", "myValue"); // Current query: "+myField: myValue"
249
+ * ```
250
+ *
251
+ * @export
252
+ * @param {string} query
253
+ * @param {string} field
254
+ * @return {*} {Field}
255
+ */
256
+ function buildField(query, field) {
257
+ const newQuery = query + ` +${field}:`;
258
+ return new Field(newQuery);
259
+ }
260
+ /**
261
+ * This function builds an exclude field to be used in a lucene query.
262
+ * We need to format the field before adding it to the query.
263
+ *
264
+ * @example
265
+ * ```ts
266
+ * const query = "+myField: myValue";
267
+ * const field = buildExcludeField(query, "myField2"); // Current query: "+myField: myValue -myField2:"
268
+ * ```
269
+ *
270
+ * @export
271
+ * @param {string} query
272
+ * @param {string} field
273
+ * @return {*} {Field}
274
+ */
275
+ function buildExcludeField(query, field) {
276
+ const newQuery = query + ` -${field}:`;
277
+ return new Field(newQuery);
278
+ }
279
+ /**
280
+ * This function builds an operand to be used in a lucene query.
281
+ * We need to format the operand before adding it to the query.
282
+ *
283
+ * @example
284
+ * <caption>E.g. Using the AND operand</caption>
285
+ * ```ts
286
+ * const query = "+myField: myValue";
287
+ * const field = buildOperand(query, OPERAND.AND); // Current query: "+myField: myValue AND"
288
+ * ```
289
+ * @example
290
+ * <caption>E.g. Using the OR operand</caption>
291
+ * ```ts
292
+ * const query = "+myField: myValue";
293
+ * const field = buildOperand(query, OPERAND.OR); // Current query: "+myField: myValue OR"
294
+ * ```
295
+ * @export
296
+ * @param {string} query
297
+ * @param {OPERAND} operand
298
+ * @return {*} {Operand}
299
+ */
300
+ function buildOperand(query, operand) {
301
+ const newQuery = query + ` ${operand} `;
302
+ return new Operand(newQuery);
303
+ }
304
+ /**
305
+ * This function builds a NOT operand to be used in a lucene query.
306
+ * We need to format the operand before adding it to the query.
307
+ *
308
+ * @example
309
+ * ```ts
310
+ * const query = "+myField: myValue";
311
+ * const field = buildNotOperand(query); // Current query: "+myField: myValue NOT"
312
+ * ```
313
+ *
314
+ * @export
315
+ * @param {string} query
316
+ * @return {*} {NotOperand}
317
+ */
318
+ function buildNotOperand(query) {
319
+ const newQuery = query + ` ${OPERAND.NOT} `;
320
+ return new NotOperand(newQuery);
321
+ }
322
+
323
+ var _Equals_query;
324
+ /**
325
+ * 'Equal' Is a Typescript class that provides the ability to use terms in the lucene query string.
326
+ * A term is a value used to search for a specific value in a document. It can be a word or a phrase.
327
+ *
328
+ * Ex: myValue or "My Value"
329
+ *
330
+ * @export
331
+ * @class Equal
332
+ */
333
+ class Equals {
334
+ constructor(query) {
335
+ this.query = query;
336
+ _Equals_query.set(this, '');
337
+ __classPrivateFieldSet(this, _Equals_query, this.query, "f");
338
+ }
339
+ /**
340
+ * This method appends to the query a term that should be excluded in the search.
341
+ *
342
+ * @example
343
+ * ```ts
344
+ * const equals = new Equals("+myField: myValue");
345
+ * equals.excludeField("myField2").equals("myValue2"); // Current query: "+myField: myValue -myField2: myValue2"
346
+ * ```
347
+ *
348
+ * @param {string} field - The field that should be excluded in the search.
349
+ * @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
350
+ * @memberof Equal
351
+ */
352
+ excludeField(field) {
353
+ return buildExcludeField(__classPrivateFieldGet(this, _Equals_query, "f"), field);
354
+ }
355
+ /**
356
+ * This method appends to the query a field that should be included in the search.
357
+ *
358
+ * @example
359
+ * ```ts
360
+ * const equals = new Equals("+myField: myValue");
361
+ * equals.field("myField2").equals("myValue2"); // Current query: "+myField: myValue +myField2: myValue2"
362
+ *```
363
+ * @param {string} field - The field that should be included in the search.
364
+ * @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
365
+ * @memberof Equal
366
+ */
367
+ field(field) {
368
+ return buildField(__classPrivateFieldGet(this, _Equals_query, "f"), field);
369
+ }
370
+ /**
371
+ * This method appends to the query an operand to use logic operators in the query.
372
+ *
373
+ * @example
374
+ * @example
375
+ * ```ts
376
+ * const equals = new Equals("+myField: myValue");
377
+ * equals.or().field("myField2").equals("myValue2"); // Current query: "+myField: myValue OR +myField2: myValue2"
378
+ * ```
379
+ *
380
+ * @return {*} {Operand} - An instance of a Lucene Operand. An operand is a logical operator used to combine terms or phrases in a query.
381
+ * @memberof Equal
382
+ */
383
+ or() {
384
+ return buildOperand(__classPrivateFieldGet(this, _Equals_query, "f"), OPERAND.OR);
385
+ }
386
+ /**
387
+ * This method appends to the query an operand to use logic operators in the query.
388
+ *
389
+ * @example
390
+ * ```ts
391
+ * const equals = new Equals("+myField: myValue");
392
+ * equals.and().field("myField2").equals("myValue2"); // Current query: "+myField: myValue AND +myField2: myValue2"
393
+ * ```
394
+ *
395
+ * @return {*} {Operand} - An instance of a Lucene Operand. An operand is a logical operator used to combine terms or phrases in a query.
396
+ * @memberof Equal
397
+ */
398
+ and() {
399
+ return buildOperand(__classPrivateFieldGet(this, _Equals_query, "f"), OPERAND.AND);
400
+ }
401
+ /**
402
+ * This method appends to the query an operand to use logic operators in the query.
403
+ *
404
+ * @example
405
+ * ```ts
406
+ * const equals = new Equals("+myField: myValue");
407
+ * equals.not().field("myField").equals("myValue2"); // Current query: "+myField: myValue NOT +myField: myValue2"
408
+ * ```
409
+ *
410
+ * @return {*} {NotOperand} - An instance of a Lucene Not Operand. A not operand is a logical operator used to exclude terms or phrases in a query.
411
+ * @memberof Equal
412
+ */
413
+ not() {
414
+ return buildNotOperand(__classPrivateFieldGet(this, _Equals_query, "f"));
415
+ }
416
+ /**
417
+ * This method allows to pass a raw query string to the query builder.
418
+ * This raw query should end in a Lucene Equal.
419
+ * This method is useful when you want to append a complex query or an already written query to the query builder.
420
+ *
421
+ * @example
422
+ * ```ts
423
+ * // This builds the follow raw query "+myField: value AND (someOtherValue OR anotherValue)"
424
+ * const equals = new Equals("+myField: value");
425
+ * equals.raw("+myField2: value2"); // Current query: "+myField: value +myField2: anotherValue"
426
+ * ```
427
+ *
428
+ * @param {string} query - A raw query string.
429
+ * @return {*} {Equal} - An instance of a Lucene Equal. A term is a value used to search for a specific value in a document.
430
+ * @memberof QueryBuilder
431
+ */
432
+ raw(query) {
433
+ return buildRawEquals(__classPrivateFieldGet(this, _Equals_query, "f"), query);
434
+ }
435
+ /**
436
+ * This method returns the final query string.
437
+ *
438
+ * @example
439
+ * ```ts
440
+ * const equals = new Equals("+myField: myValue");
441
+ * equals.field("myField2").equals("myValue2").build(); // Returns "+myField: myValue +myField2: myValue2"
442
+ * ```
443
+ *
444
+ * @return {*} {string} - The final query string.
445
+ * @memberof Equal
446
+ */
447
+ build() {
448
+ return sanitizeQuery(__classPrivateFieldGet(this, _Equals_query, "f"));
449
+ }
450
+ }
451
+ _Equals_query = new WeakMap();
452
+
453
+ var _QueryBuilder_query;
454
+ /**
455
+ * 'QueryBuilder' Is a Typescript class that provides the ability to build a query string using the Lucene syntax in a more readable way.
456
+ * @example
457
+ * ```ts
458
+ * const qb = new QueryBuilder();
459
+ * const query = qb
460
+ * .field('contentType')
461
+ * .equals('Blog')
462
+ * .field('conhost')
463
+ * .equals('my-super-cool-site')
464
+ * .build(); // Output: `+contentType:Blog +conhost:my-super-cool-site"`
465
+ * ```
466
+ *
467
+ * @example
468
+ * ```ts
469
+ * const qb = new QueryBuilder();
470
+ * const query = qb
471
+ * .field('contentType')
472
+ * .equals('Blog')
473
+ * .field('title')
474
+ * .equals('Football')
475
+ * .excludeField('summary')
476
+ * .equals('Lionel Messi')
477
+ * .build(); // Output: `+contentType:Blog +title:Football -summary:"Lionel Messi"`
478
+ * ```
479
+ * @export
480
+ * @class QueryBuilder
481
+ */
482
+ class QueryBuilder {
483
+ constructor() {
484
+ _QueryBuilder_query.set(this, '');
485
+ }
486
+ /**
487
+ * This method appends to the query a field that should be included in the search.
488
+ *
489
+ * @example
490
+ * ```ts
491
+ * const qb = new QueryBuilder();
492
+ * qb.field("+myField: ", "myValue"); // Current query: "+myField: myValue"
493
+ * ```
494
+ *
495
+ * @param {string} field - The field that should be included in the search.
496
+ * @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
497
+ * @memberof QueryBuilder
498
+ */
499
+ field(field) {
500
+ return buildField(__classPrivateFieldGet(this, _QueryBuilder_query, "f"), field);
501
+ }
502
+ /**
503
+ * This method appends to the query a field that should be excluded from the search.
504
+ *
505
+ * @example
506
+ * ```ts
507
+ * const qb = new QueryBuilder();
508
+ * qb.excludeField("myField").equals("myValue"); // Current query: "-myField: myValue"
509
+ * ```
510
+ *
511
+ * @param {string} field - The field that should be excluded from the search.
512
+ * @return {*} {Field} - An instance of a Lucene Exclude Field. An exclude field is a key used to exclude for a specific value in a document.
513
+ * @memberof QueryBuilder
514
+ */
515
+ excludeField(field) {
516
+ return buildExcludeField(__classPrivateFieldGet(this, _QueryBuilder_query, "f"), field);
517
+ }
518
+ /**
519
+ * This method allows to pass a raw query string to the query builder.
520
+ * This raw query should end in Equals.
521
+ * This method is useful when you want to append a complex query or an already written query to the query builder.
522
+ *
523
+ * @example
524
+ * ```ts
525
+ * const qb = new QueryBuilder();
526
+ * qb.raw("+myField: value AND (someOtherValue OR anotherValue)"); // Current query: "+myField: value AND (someOtherValue OR anotherValue)"
527
+ * ```
528
+ *
529
+ * @param {string} query - A raw query string.
530
+ * @return {*} {Equals} - An instance of Equals. A term is a value used to search for a specific value in a document.
531
+ * @memberof QueryBuilder
532
+ */
533
+ raw(query) {
534
+ return buildRawEquals(__classPrivateFieldGet(this, _QueryBuilder_query, "f"), query);
535
+ }
536
+ }
537
+ _QueryBuilder_query = new WeakMap();
538
+
539
+ /**
540
+ * Default variant identifier used in the application.
541
+ */
542
+ /**
543
+ * Fields that should not be formatted when sanitizing the query.
544
+ * These fields are essential for maintaining the integrity of the content type.
545
+ */
546
+ const CONTENT_TYPE_MAIN_FIELDS = ['live', 'variant', 'contentType', 'languageId'];
547
+ /**
548
+ * URL endpoint for the content API search functionality.
549
+ */
550
+ const CONTENT_API_URL = '/api/content/_search';
551
+
552
+ /**
553
+ * @description
554
+ * Sanitizes the query for the given content type.
555
+ * It replaces the fields that are not content type fields with the correct format.
556
+ * Example: +field: -> +contentTypeVar.field:
557
+ *
558
+ * @example
559
+ *
560
+ * ```ts
561
+ * const query = '+field: value';
562
+ * const contentType = 'contentTypeVar';
563
+ * const sanitizedQuery = sanitizeQueryForContentType(query, contentType); // Output: '+contentTypeVar.field: value'
564
+ * ```
565
+ *
566
+ * @export
567
+ * @param {string} query - The query string to be sanitized.
568
+ * @param {string} contentType - The content type to be used for formatting the fields.
569
+ * @returns {string} The sanitized query string.
570
+ */
571
+ function sanitizeQueryForContentType(query, contentType) {
572
+ return query.replace(/\+([^+:]*?):/g, (original, field) => {
573
+ return !CONTENT_TYPE_MAIN_FIELDS.includes(field) // Fields that are not content type fields
574
+ ? `+${contentType}.${field}:` // Should have this format: +contentTypeVar.field:
575
+ : original; // Return the field if it is a content type field
576
+ });
577
+ }
578
+
579
+ var _CollectionBuilder_page, _CollectionBuilder_limit, _CollectionBuilder_depth, _CollectionBuilder_render, _CollectionBuilder_sortBy, _CollectionBuilder_contentType, _CollectionBuilder_defaultQuery, _CollectionBuilder_query, _CollectionBuilder_rawQuery, _CollectionBuilder_languageId, _CollectionBuilder_draft, _CollectionBuilder_serverUrl, _CollectionBuilder_requestOptions;
580
+ /**
581
+ * Creates a Builder to filter and fetch content from the content API for a specific content type.
582
+ *
583
+ * @export
584
+ * @class CollectionBuilder
585
+ * @template T Represents the type of the content type to fetch. Defaults to unknown.
586
+ */
587
+ class CollectionBuilder {
588
+ /**
589
+ * Creates an instance of CollectionBuilder.
590
+ * @param {ClientOptions} requestOptions Options for the client request.
591
+ * @param {string} serverUrl The server URL.
592
+ * @param {string} contentType The content type to fetch.
593
+ * @memberof CollectionBuilder
594
+ */
595
+ constructor(requestOptions, serverUrl, contentType) {
596
+ _CollectionBuilder_page.set(this, 1);
597
+ _CollectionBuilder_limit.set(this, 10);
598
+ _CollectionBuilder_depth.set(this, 0);
599
+ _CollectionBuilder_render.set(this, false);
600
+ _CollectionBuilder_sortBy.set(this, void 0);
601
+ _CollectionBuilder_contentType.set(this, void 0);
602
+ _CollectionBuilder_defaultQuery.set(this, void 0);
603
+ _CollectionBuilder_query.set(this, void 0);
604
+ _CollectionBuilder_rawQuery.set(this, void 0);
605
+ _CollectionBuilder_languageId.set(this, 1);
606
+ _CollectionBuilder_draft.set(this, false);
607
+ _CollectionBuilder_serverUrl.set(this, void 0);
608
+ _CollectionBuilder_requestOptions.set(this, void 0);
609
+ __classPrivateFieldSet(this, _CollectionBuilder_requestOptions, requestOptions, "f");
610
+ __classPrivateFieldSet(this, _CollectionBuilder_serverUrl, serverUrl, "f");
611
+ __classPrivateFieldSet(this, _CollectionBuilder_contentType, contentType, "f");
612
+ // Build the default query with the contentType field
613
+ __classPrivateFieldSet(this, _CollectionBuilder_defaultQuery, new QueryBuilder().field('contentType').equals(__classPrivateFieldGet(this, _CollectionBuilder_contentType, "f")), "f");
614
+ }
615
+ /**
616
+ * Returns the sort query in the format: field order, field order, ...
617
+ *
618
+ * @readonly
619
+ * @private
620
+ * @memberof CollectionBuilder
621
+ */
622
+ get sort() {
623
+ return __classPrivateFieldGet(this, _CollectionBuilder_sortBy, "f")?.map((sort) => `${sort.field} ${sort.order}`).join(',');
624
+ }
625
+ /**
626
+ * Returns the offset for pagination.
627
+ *
628
+ * @readonly
629
+ * @private
630
+ * @memberof CollectionBuilder
631
+ */
632
+ get offset() {
633
+ return __classPrivateFieldGet(this, _CollectionBuilder_limit, "f") * (__classPrivateFieldGet(this, _CollectionBuilder_page, "f") - 1);
634
+ }
635
+ /**
636
+ * Returns the full URL for the content API.
637
+ *
638
+ * @readonly
639
+ * @private
640
+ * @memberof CollectionBuilder
641
+ */
642
+ get url() {
643
+ return `${__classPrivateFieldGet(this, _CollectionBuilder_serverUrl, "f")}${CONTENT_API_URL}`;
644
+ }
645
+ /**
646
+ * Returns the current query built.
647
+ *
648
+ * @readonly
649
+ * @private
650
+ * @memberof CollectionBuilder
651
+ */
652
+ get currentQuery() {
653
+ return __classPrivateFieldGet(this, _CollectionBuilder_query, "f") ?? __classPrivateFieldGet(this, _CollectionBuilder_defaultQuery, "f");
654
+ }
655
+ /**
656
+ * Filters the content by the specified language ID.
657
+ *
658
+ * @example
659
+ * ```typescript
660
+ * const client = new DotCMSClient(config);
661
+ * const collectionBuilder = client.content.getCollection("Blog");
662
+ * collectionBuilder.language(1);
663
+ * ```
664
+ *
665
+ * @param {number | string} languageId The language ID to filter the content by.
666
+ * @return {CollectionBuilder} A CollectionBuilder instance.
667
+ * @memberof CollectionBuilder
668
+ */
669
+ language(languageId) {
670
+ __classPrivateFieldSet(this, _CollectionBuilder_languageId, languageId, "f");
671
+ return this;
672
+ }
673
+ /**
674
+ * Setting this to true will server side render (using velocity) any widgets that are returned by the content query.
675
+ *
676
+ * More information here: {@link https://www.dotcms.com/docs/latest/content-api-retrieval-and-querying#ParamsOptional}
677
+ *
678
+ * @return {CollectionBuilder} A CollectionBuilder instance.
679
+ * @memberof CollectionBuilder
680
+ */
681
+ render() {
682
+ __classPrivateFieldSet(this, _CollectionBuilder_render, true, "f");
683
+ return this;
684
+ }
685
+ /**
686
+ * Sorts the content by the specified fields and orders.
687
+ *
688
+ * @example
689
+ * ```typescript
690
+ * const client = new DotCMSClient(config);
691
+ * const collectionBuilder = client.content.getCollection("Blog");
692
+ * const sortBy = [{ field: 'title', order: 'asc' }, { field: 'modDate', order: 'desc' }];
693
+ * collectionBuilder("Blog").sortBy(sortBy);
694
+ * ```
695
+ *
696
+ * @param {SortBy[]} sortBy Array of constraints to sort the content by.
697
+ * @return {CollectionBuilder} A CollectionBuilder instance.
698
+ * @memberof CollectionBuilder
699
+ */
700
+ sortBy(sortBy) {
701
+ __classPrivateFieldSet(this, _CollectionBuilder_sortBy, sortBy, "f");
702
+ return this;
703
+ }
704
+ /**
705
+ * Sets the maximum amount of content to fetch.
706
+ *
707
+ * @param {number} limit The maximum amount of content to fetch.
708
+ * @return {CollectionBuilder} A CollectionBuilder instance.
709
+ * @memberof CollectionBuilder
710
+ */
711
+ limit(limit) {
712
+ __classPrivateFieldSet(this, _CollectionBuilder_limit, limit, "f");
713
+ return this;
714
+ }
715
+ /**
716
+ * Sets the page number to fetch.
717
+ *
718
+ * @param {number} page The page number to fetch.
719
+ * @return {CollectionBuilder} A CollectionBuilder instance.
720
+ * @memberof CollectionBuilder
721
+ */
722
+ page(page) {
723
+ __classPrivateFieldSet(this, _CollectionBuilder_page, page, "f");
724
+ return this;
725
+ }
726
+ query(arg) {
727
+ if (typeof arg === 'string') {
728
+ __classPrivateFieldSet(this, _CollectionBuilder_rawQuery, arg, "f");
729
+ return this;
730
+ }
731
+ if (typeof arg !== 'function') {
732
+ throw new Error(`Parameter for query method should be a buildQuery function or a string.\nExample:\nclient.content.getCollection('Activity').query((queryBuilder) => queryBuilder.field('title').equals('Hello World'))\nor\nclient.content.getCollection('Activity').query('+Activity.title:"Hello World"') \nSee documentation for more information.`);
733
+ }
734
+ const builtQuery = arg(new QueryBuilder());
735
+ // This can be use in Javascript so we cannot rely on the type checking
736
+ if (builtQuery instanceof Equals) {
737
+ __classPrivateFieldSet(this, _CollectionBuilder_query, builtQuery.raw(this.currentQuery.build()), "f");
738
+ }
739
+ else {
740
+ throw new Error('Provided query is not valid. A query should end in an equals method call.\nExample:\n(queryBuilder) => queryBuilder.field("title").equals("Hello World")\nSee documentation for more information.');
741
+ }
742
+ return this;
743
+ }
744
+ /**
745
+ * Retrieves draft content.
746
+ * @example
747
+ * ```ts
748
+ * const client = new DotCMSClient(config);
749
+ * const collectionBuilder = client.content.getCollection("Blog");
750
+ * collectionBuilder
751
+ * .draft() // This will retrieve draft/working content
752
+ * .then((response) => // Your code here })
753
+ * .catch((error) => // Your code here })
754
+ * ```
755
+ *
756
+ * @return {CollectionBuilder} A CollectionBuilder instance.
757
+ * @memberof CollectionBuilder
758
+ */
759
+ draft() {
760
+ __classPrivateFieldSet(this, _CollectionBuilder_draft, true, "f");
761
+ return this;
762
+ }
763
+ /**
764
+ * Filters the content by a variant ID for [Experiments](https://www.dotcms.com/docs/latest/experiments-and-a-b-testing)
765
+ *
766
+ * More information here: {@link https://www.dotcms.com/docs/latest/content-api-retrieval-and-querying#ParamsOptional}
767
+ *
768
+ * @example
769
+ * ```ts
770
+ * const client = new DotCMSClient(config);
771
+ * const collectionBuilder = client.content.getCollection("Blog");
772
+ * collectionBuilder
773
+ * .variant("YOUR_VARIANT_ID")
774
+ * .then((response) => // Your code here })
775
+ * .catch((error) => // Your code here })
776
+ * ```
777
+ *
778
+ * @param {string} variantId A string that represents a variant ID.
779
+ * @return {CollectionBuilder} A CollectionBuilder instance.
780
+ * @memberof CollectionBuilder
781
+ */
782
+ variant(variantId) {
783
+ __classPrivateFieldSet(this, _CollectionBuilder_query, this.currentQuery.field('variant').equals(variantId), "f");
784
+ return this;
785
+ }
786
+ /**
787
+ * Sets the depth of the relationships of the content.
788
+ * Specifies the depth of related content to return in the results.
789
+ *
790
+ * More information here: {@link https://www.dotcms.com/docs/latest/content-api-retrieval-and-querying#ParamsOptional}
791
+ *
792
+ * @example
793
+ * ```ts
794
+ * const client = new DotCMSClient(config);
795
+ * const collectionBuilder = client.content.getCollection("Blog");
796
+ * collectionBuilder
797
+ * .depth(1)
798
+ * .then((response) => // Your code here })
799
+ * .catch((error) => // Your code here })
800
+ * ```
801
+ *
802
+ * @param {number} depth The depth of the relationships of the content.
803
+ * @return {CollectionBuilder} A CollectionBuilder instance.
804
+ * @memberof CollectionBuilder
805
+ */
806
+ depth(depth) {
807
+ if (depth < 0 || depth > 3) {
808
+ throw new Error('Depth value must be between 0 and 3');
809
+ }
810
+ __classPrivateFieldSet(this, _CollectionBuilder_depth, depth, "f");
811
+ return this;
812
+ }
813
+ /**
814
+ * Executes the fetch and returns a promise that resolves to the content or rejects with an error.
815
+ *
816
+ * @example
817
+ * ```ts
818
+ * const client = new DotCMSClient(config);
819
+ * const collectionBuilder = client.content.getCollection("Blog");
820
+ * collectionBuilder
821
+ * .limit(10)
822
+ * .then((response) => // Your code here })
823
+ * .catch((error) => // Your code here })
824
+ * ```
825
+ *
826
+ * @param {OnFullfilled} [onfulfilled] A callback that is called when the fetch is successful.
827
+ * @param {OnRejected} [onrejected] A callback that is called when the fetch fails.
828
+ * @return {Promise<GetCollectionResponse<T> | GetCollectionError>} A promise that resolves to the content or rejects with an error.
829
+ * @memberof CollectionBuilder
830
+ */
831
+ then(onfulfilled, onrejected) {
832
+ return this.fetch().then(async (response) => {
833
+ const data = await response.json();
834
+ if (response.ok) {
835
+ const formattedResponse = this.formatResponse(data);
836
+ const finalResponse = typeof onfulfilled === 'function'
837
+ ? onfulfilled(formattedResponse)
838
+ : formattedResponse;
839
+ return finalResponse;
840
+ }
841
+ else {
842
+ return {
843
+ status: response.status,
844
+ ...data
845
+ };
846
+ }
847
+ }, onrejected);
848
+ }
849
+ /**
850
+ * Formats the response to the desired format.
851
+ *
852
+ * @private
853
+ * @param {GetCollectionRawResponse<T>} data The raw response data.
854
+ * @return {GetCollectionResponse<T>} The formatted response.
855
+ * @memberof CollectionBuilder
856
+ */
857
+ formatResponse(data) {
858
+ const contentlets = data.entity.jsonObjectView.contentlets;
859
+ const total = data.entity.resultsSize;
860
+ const mappedResponse = {
861
+ contentlets,
862
+ total,
863
+ page: __classPrivateFieldGet(this, _CollectionBuilder_page, "f"),
864
+ size: contentlets.length
865
+ };
866
+ return __classPrivateFieldGet(this, _CollectionBuilder_sortBy, "f")
867
+ ? {
868
+ ...mappedResponse,
869
+ sortedBy: __classPrivateFieldGet(this, _CollectionBuilder_sortBy, "f")
870
+ }
871
+ : mappedResponse;
872
+ }
873
+ /**
874
+ * Calls the content API to fetch the content.
875
+ *
876
+ * @private
877
+ * @return {Promise<Response>} The fetch response.
878
+ * @memberof CollectionBuilder
879
+ */
880
+ fetch() {
881
+ const finalQuery = this.currentQuery
882
+ .field('languageId')
883
+ .equals(__classPrivateFieldGet(this, _CollectionBuilder_languageId, "f").toString())
884
+ .field('live')
885
+ .equals((!__classPrivateFieldGet(this, _CollectionBuilder_draft, "f")).toString())
886
+ .build();
887
+ const sanitizedQuery = sanitizeQueryForContentType(finalQuery, __classPrivateFieldGet(this, _CollectionBuilder_contentType, "f"));
888
+ const query = __classPrivateFieldGet(this, _CollectionBuilder_rawQuery, "f") ? `${sanitizedQuery} ${__classPrivateFieldGet(this, _CollectionBuilder_rawQuery, "f")}` : sanitizedQuery;
889
+ return fetch(this.url, {
890
+ ...__classPrivateFieldGet(this, _CollectionBuilder_requestOptions, "f"),
891
+ method: 'POST',
892
+ headers: {
893
+ ...__classPrivateFieldGet(this, _CollectionBuilder_requestOptions, "f").headers,
894
+ 'Content-Type': 'application/json'
895
+ },
896
+ body: JSON.stringify({
897
+ query,
898
+ render: __classPrivateFieldGet(this, _CollectionBuilder_render, "f"),
899
+ sort: this.sort,
900
+ limit: __classPrivateFieldGet(this, _CollectionBuilder_limit, "f"),
901
+ offset: this.offset,
902
+ depth: __classPrivateFieldGet(this, _CollectionBuilder_depth, "f")
903
+ //userId: This exist but we currently don't use it
904
+ //allCategoriesInfo: This exist but we currently don't use it
905
+ })
906
+ });
907
+ }
908
+ }
909
+ _CollectionBuilder_page = new WeakMap(), _CollectionBuilder_limit = new WeakMap(), _CollectionBuilder_depth = new WeakMap(), _CollectionBuilder_render = new WeakMap(), _CollectionBuilder_sortBy = new WeakMap(), _CollectionBuilder_contentType = new WeakMap(), _CollectionBuilder_defaultQuery = new WeakMap(), _CollectionBuilder_query = new WeakMap(), _CollectionBuilder_rawQuery = new WeakMap(), _CollectionBuilder_languageId = new WeakMap(), _CollectionBuilder_draft = new WeakMap(), _CollectionBuilder_serverUrl = new WeakMap(), _CollectionBuilder_requestOptions = new WeakMap();
910
+
911
+ var _Content_requestOptions, _Content_serverUrl;
912
+ /**
913
+ * Creates a builder to filter and fetch a collection of content items.
914
+ * @param contentType - The content type to retrieve.
915
+ * @returns A CollectionBuilder instance for chaining filters and executing the query.
916
+ * @template T - The type of the content items (defaults to unknown).
917
+ *
918
+ * @example Fetch blog posts with async/await
919
+ * ```typescript
920
+ * const response = await client.content
921
+ * .getCollection<BlogPost>('Blog')
922
+ * .limit(10)
923
+ * .page(2)
924
+ * .sortBy([{ field: 'title', order: 'asc' }])
925
+ * .query(q => q.field('author').equals('John Doe'))
926
+ * .depth(1)
927
+ * .fetch();
928
+ *
929
+ * console.log(response.contentlets);
930
+ * ```
931
+ *
932
+ * @example Fetch blog posts with Promise chain
933
+ * ```typescript
934
+ * client.content
935
+ * .getCollection<BlogPost>('Blog')
936
+ * .limit(10)
937
+ * .page(2)
938
+ * .sortBy([{ field: 'title', order: 'asc' }])
939
+ * .query(q => q.field('author').equals('John Doe'))
940
+ * .depth(1)
941
+ * .fetch()
942
+ * .then(response => console.log(response.contentlets))
943
+ * .catch(error => console.error(error));
944
+ * ```
945
+ *
946
+ * @example Using a custom type
947
+ * ```typescript
948
+ * interface BlogPost {
949
+ * summary: string;
950
+ * author: string;
951
+ * title: string;
952
+ * }
953
+ *
954
+ * const posts = await client.content
955
+ * .getCollection<BlogPost>('Blog')
956
+ * .limit(10)
957
+ * .fetch();
958
+ *
959
+ * posts.contentlets.forEach(post => {
960
+ * console.log(post.title, post.author, post.summary);
961
+ * });
962
+ * ```
963
+ */
964
+ class Content {
965
+ /**
966
+ * Creates an instance of Content.
967
+ * @param {ClientOptions} requestOptions - The options for the client request.
968
+ * @param {string} serverUrl - The server URL.
969
+ */
970
+ constructor(requestOptions, serverUrl) {
971
+ _Content_requestOptions.set(this, void 0);
972
+ _Content_serverUrl.set(this, void 0);
973
+ __classPrivateFieldSet(this, _Content_requestOptions, requestOptions, "f");
974
+ __classPrivateFieldSet(this, _Content_serverUrl, serverUrl, "f");
975
+ }
976
+ /**
977
+ * Takes a content type and returns a builder to filter and fetch the collection.
978
+ * @param {string} contentType - The content type to get the collection.
979
+ * @return {CollectionBuilder<T>} CollectionBuilder to filter and fetch the collection.
980
+ * @template T - Represents the type of the content type to fetch. Defaults to unknown.
981
+ * @memberof Content
982
+ *
983
+ * @example
984
+ * ```javascript
985
+ * // Using await and async
986
+ * const collectionResponse = await client.content
987
+ * .getCollection('Blog')
988
+ * .limit(10)
989
+ * .page(2)
990
+ * .sortBy([{ field: 'title', order: 'asc' }])
991
+ * .query((queryBuilder) => queryBuilder.field('author').equals('John Doe'))
992
+ * .depth(1);
993
+ * ```
994
+ * @example
995
+ * ```javascript
996
+ * // Using then and catch
997
+ * client.content
998
+ * .getCollection('Blog')
999
+ * .limit(10)
1000
+ * .page(2)
1001
+ * .sortBy([{ field: 'title', order: 'asc' }])
1002
+ * .query((queryBuilder) => queryBuilder.field('author').equals('John Doe'))
1003
+ * .depth(1)
1004
+ * .then((response) => {
1005
+ * console.log(response.contentlets);
1006
+ * })
1007
+ * .catch((error) => {
1008
+ * console.error(error);
1009
+ * });
1010
+ * ```
1011
+ * @example
1012
+ * ```typescript
1013
+ * // Using a specific type for your content
1014
+ *
1015
+ * type Blog = {
1016
+ * summary: string;
1017
+ * author: string;
1018
+ * title: string;
1019
+ * };
1020
+ *
1021
+ * client.content
1022
+ * .getCollection<Blog>('Blog')
1023
+ * .limit(10)
1024
+ * .page(2)
1025
+ * .sortBy([{ field: 'title', order: 'asc' }])
1026
+ * .query((queryBuilder) => queryBuilder.field('author').equals('John Doe'))
1027
+ * .depth(1)
1028
+ * .then((response) => {
1029
+ * response.contentlets.forEach((blog) => {
1030
+ * console.log(blog.title);
1031
+ * console.log(blog.author);
1032
+ * console.log(blog.summary);
1033
+ * });
1034
+ * })
1035
+ * .catch((error) => {
1036
+ * console.error(error);
1037
+ * });
1038
+ * ```
1039
+ *
1040
+ */
1041
+ getCollection(contentType) {
1042
+ return new CollectionBuilder(__classPrivateFieldGet(this, _Content_requestOptions, "f"), __classPrivateFieldGet(this, _Content_serverUrl, "f"), contentType);
1043
+ }
1044
+ }
1045
+ _Content_requestOptions = new WeakMap(), _Content_serverUrl = new WeakMap();
1046
+
1047
+ /**
1048
+ * A record of HTTP status codes and their corresponding error messages.
1049
+ *
1050
+ * @type {Record<number, string>}
1051
+ * @property {string} 401 - Unauthorized. Check the token and try again.
1052
+ * @property {string} 403 - Forbidden. Check the permissions and try again.
1053
+ * @property {string} 404 - Not Found. Check the URL and try again.
1054
+ * @property {string} 500 - Internal Server Error. Try again later.
1055
+ * @property {string} 502 - Bad Gateway. Try again later.
1056
+ * @property {string} 503 - Service Unavailable. Try again later.
1057
+ */
1058
+ const ErrorMessages = {
1059
+ 401: 'Unauthorized. Check the token and try again.',
1060
+ 403: 'Forbidden. Check the permissions and try again.',
1061
+ 404: 'Not Found. Check the URL and try again.',
1062
+ 500: 'Internal Server Error. Try again later.',
1063
+ 502: 'Bad Gateway. Try again later.',
1064
+ 503: 'Service Unavailable. Try again later.'
1065
+ };
1066
+
1067
+ /**
1068
+ * Actions received from the dotcms editor
1069
+ *
1070
+ * @export
1071
+ * @enum {number}
1072
+ */
1073
+ exports.NOTIFY_CLIENT = void 0;
1074
+ (function (NOTIFY_CLIENT) {
1075
+ /**
1076
+ * Request to page to reload
1077
+ */
1078
+ NOTIFY_CLIENT["UVE_RELOAD_PAGE"] = "uve-reload-page";
1079
+ /**
1080
+ * Request the bounds for the elements
1081
+ */
1082
+ NOTIFY_CLIENT["UVE_REQUEST_BOUNDS"] = "uve-request-bounds";
1083
+ /**
1084
+ * Received pong from the editor
1085
+ */
1086
+ NOTIFY_CLIENT["UVE_EDITOR_PONG"] = "uve-editor-pong";
1087
+ /**
1088
+ * Received scroll event trigger from the editor
1089
+ */
1090
+ NOTIFY_CLIENT["UVE_SCROLL_INSIDE_IFRAME"] = "uve-scroll-inside-iframe";
1091
+ /**
1092
+ * Set the page data
1093
+ */
1094
+ NOTIFY_CLIENT["UVE_SET_PAGE_DATA"] = "uve-set-page-data";
1095
+ /**
1096
+ * Copy contentlet inline editing success
1097
+ */
1098
+ NOTIFY_CLIENT["UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS"] = "uve-copy-contentlet-inline-editing-success";
1099
+ })(exports.NOTIFY_CLIENT || (exports.NOTIFY_CLIENT = {}));
1100
+
1101
+ const INITIAL_DOT_UVE = {
1102
+ editContentlet,
1103
+ initInlineEditing,
1104
+ reorderMenu,
1105
+ lastScrollYPosition: 0
1106
+ };
1107
+ /**
1108
+ * Actions send to the dotcms editor
1109
+ *
1110
+ * @export
1111
+ * @enum {number}
1112
+ */
1113
+ exports.CLIENT_ACTIONS = void 0;
1114
+ (function (CLIENT_ACTIONS) {
1115
+ /**
1116
+ * Tell the dotcms editor that page change
1117
+ */
1118
+ CLIENT_ACTIONS["NAVIGATION_UPDATE"] = "set-url";
1119
+ /**
1120
+ * Send the element position of the rows, columnsm containers and contentlets
1121
+ */
1122
+ CLIENT_ACTIONS["SET_BOUNDS"] = "set-bounds";
1123
+ /**
1124
+ * Send the information of the hovered contentlet
1125
+ */
1126
+ CLIENT_ACTIONS["SET_CONTENTLET"] = "set-contentlet";
1127
+ /**
1128
+ * Tell the editor that the page is being scrolled
1129
+ */
1130
+ CLIENT_ACTIONS["IFRAME_SCROLL"] = "scroll";
1131
+ /**
1132
+ * Tell the editor that the page has stopped scrolling
1133
+ */
1134
+ CLIENT_ACTIONS["IFRAME_SCROLL_END"] = "scroll-end";
1135
+ /**
1136
+ * Ping the editor to see if the page is inside the editor
1137
+ */
1138
+ CLIENT_ACTIONS["PING_EDITOR"] = "ping-editor";
1139
+ /**
1140
+ * Tell the editor to init the inline editing editor.
1141
+ */
1142
+ CLIENT_ACTIONS["INIT_INLINE_EDITING"] = "init-inline-editing";
1143
+ /**
1144
+ * Tell the editor to open the Copy-contentlet dialog
1145
+ * To copy a content and then edit it inline.
1146
+ */
1147
+ CLIENT_ACTIONS["COPY_CONTENTLET_INLINE_EDITING"] = "copy-contentlet-inline-editing";
1148
+ /**
1149
+ * Tell the editor to save inline edited contentlet
1150
+ */
1151
+ CLIENT_ACTIONS["UPDATE_CONTENTLET_INLINE_EDITING"] = "update-contentlet-inline-editing";
1152
+ /**
1153
+ * Tell the editor to trigger a menu reorder
1154
+ */
1155
+ CLIENT_ACTIONS["REORDER_MENU"] = "reorder-menu";
1156
+ /**
1157
+ * Tell the editor to send the page info to iframe
1158
+ */
1159
+ CLIENT_ACTIONS["GET_PAGE_DATA"] = "get-page-data";
1160
+ /**
1161
+ * Tell the editor an user send a graphql query
1162
+ */
1163
+ CLIENT_ACTIONS["CLIENT_READY"] = "client-ready";
1164
+ /**
1165
+ * Tell the editor to edit a contentlet
1166
+ */
1167
+ CLIENT_ACTIONS["EDIT_CONTENTLET"] = "edit-contentlet";
1168
+ /**
1169
+ * Tell the editor to do nothing
1170
+ */
1171
+ CLIENT_ACTIONS["NOOP"] = "noop";
1172
+ })(exports.CLIENT_ACTIONS || (exports.CLIENT_ACTIONS = {}));
1173
+ /**
1174
+ * Post message to dotcms page editor
1175
+ *
1176
+ * @export
1177
+ * @template T
1178
+ * @param {PostMessageProps<T>} message
1179
+ */
1180
+ function postMessageToEditor(message) {
1181
+ window.parent.postMessage(message, '*');
1182
+ }
1183
+
1184
+ /**
1185
+ * Calculates the bounding information for each page element within the given containers.
1186
+ *
1187
+ * @export
1188
+ * @param {HTMLDivElement[]} containers - An array of HTMLDivElement representing the containers.
1189
+ * @return {ContainerBound[]} An array of objects containing the bounding information for each page element.
1190
+ * @example
1191
+ * ```ts
1192
+ * const containers = document.querySelectorAll('.container');
1193
+ * const bounds = getPageElementBound(containers);
1194
+ * console.log(bounds);
1195
+ * ```
1196
+ */
1197
+ function getPageElementBound(containers) {
1198
+ return containers.map((container) => {
1199
+ const containerRect = container.getBoundingClientRect();
1200
+ const contentlets = Array.from(container.querySelectorAll('[data-dot-object="contentlet"]'));
1201
+ return {
1202
+ x: containerRect.x,
1203
+ y: containerRect.y,
1204
+ width: containerRect.width,
1205
+ height: containerRect.height,
1206
+ payload: JSON.stringify({
1207
+ container: getContainerData(container)
1208
+ }),
1209
+ contentlets: getContentletsBound(containerRect, contentlets)
1210
+ };
1211
+ });
1212
+ }
1213
+ /**
1214
+ * Calculates the bounding information for each contentlet inside a container.
1215
+ *
1216
+ * @export
1217
+ * @param {DOMRect} containerRect - The bounding rectangle of the container.
1218
+ * @param {HTMLDivElement[]} contentlets - An array of HTMLDivElement representing the contentlets.
1219
+ * @return {ContentletBound[]} An array of objects containing the bounding information for each contentlet.
1220
+ * @example
1221
+ * ```ts
1222
+ * const containerRect = container.getBoundingClientRect();
1223
+ * const contentlets = container.querySelectorAll('.contentlet');
1224
+ * const bounds = getContentletsBound(containerRect, contentlets);
1225
+ * console.log(bounds); // Element bounds within the container
1226
+ * ```
1227
+ */
1228
+ function getContentletsBound(containerRect, contentlets) {
1229
+ return contentlets.map((contentlet) => {
1230
+ const contentletRect = contentlet.getBoundingClientRect();
1231
+ return {
1232
+ x: 0,
1233
+ y: contentletRect.y - containerRect.y,
1234
+ width: contentletRect.width,
1235
+ height: contentletRect.height,
1236
+ payload: JSON.stringify({
1237
+ container: contentlet.dataset?.['dotContainer']
1238
+ ? JSON.parse(contentlet.dataset?.['dotContainer'])
1239
+ : getClosestContainerData(contentlet),
1240
+ contentlet: {
1241
+ identifier: contentlet.dataset?.['dotIdentifier'],
1242
+ title: contentlet.dataset?.['dotTitle'],
1243
+ inode: contentlet.dataset?.['dotInode'],
1244
+ contentType: contentlet.dataset?.['dotType']
1245
+ }
1246
+ })
1247
+ };
1248
+ });
1249
+ }
1250
+ /**
1251
+ * Get container data from VTLS.
1252
+ *
1253
+ * @export
1254
+ * @param {HTMLElement} container - The container element.
1255
+ * @return {object} An object containing the container data.
1256
+ * @example
1257
+ * ```ts
1258
+ * const container = document.querySelector('.container');
1259
+ * const data = getContainerData(container);
1260
+ * console.log(data);
1261
+ * ```
1262
+ */
1263
+ function getContainerData(container) {
1264
+ return {
1265
+ acceptTypes: container.dataset?.['dotAcceptTypes'] || '',
1266
+ identifier: container.dataset?.['dotIdentifier'] || '',
1267
+ maxContentlets: container.dataset?.['maxContentlets'] || '',
1268
+ uuid: container.dataset?.['dotUuid'] || ''
1269
+ };
1270
+ }
1271
+ /**
1272
+ * Get the closest container data from the contentlet.
1273
+ *
1274
+ * @export
1275
+ * @param {Element} element - The contentlet element.
1276
+ * @return {object | null} An object containing the closest container data or null if no container is found.
1277
+ * @example
1278
+ * ```ts
1279
+ * const contentlet = document.querySelector('.contentlet');
1280
+ * const data = getClosestContainerData(contentlet);
1281
+ * console.log(data);
1282
+ * ```
1283
+ */
1284
+ function getClosestContainerData(element) {
1285
+ // Find the closest ancestor element with data-dot-object="container" attribute
1286
+ const container = element.closest('[data-dot-object="container"]');
1287
+ // If a container element is found
1288
+ if (container) {
1289
+ // Return the dataset of the container element
1290
+ return getContainerData(container);
1291
+ }
1292
+ else {
1293
+ // If no container element is found, return null
1294
+ console.warn('No container found for the contentlet');
1295
+ return null;
1296
+ }
1297
+ }
1298
+ /**
1299
+ * Find the closest contentlet element based on HTMLElement.
1300
+ *
1301
+ * @export
1302
+ * @param {HTMLElement | null} element - The starting element.
1303
+ * @return {HTMLElement | null} The closest contentlet element or null if not found.
1304
+ * @example
1305
+ * const element = document.querySelector('.some-element');
1306
+ * const contentlet = findDotElement(element);
1307
+ * console.log(contentlet);
1308
+ */
1309
+ function findDotElement(element) {
1310
+ if (!element)
1311
+ return null;
1312
+ if (element?.dataset?.['dotObject'] === 'contentlet' ||
1313
+ (element?.dataset?.['dotObject'] === 'container' && element.children.length === 0)) {
1314
+ return element;
1315
+ }
1316
+ return findDotElement(element?.['parentElement']);
1317
+ }
1318
+ /**
1319
+ * Find VTL data within a target element.
1320
+ *
1321
+ * @export
1322
+ * @param {HTMLElement} target - The target element to search within.
1323
+ * @return {Array<{ inode: string, name: string }> | null} An array of objects containing VTL data or null if none found.
1324
+ * @example
1325
+ * ```ts
1326
+ * const target = document.querySelector('.target-element');
1327
+ * const vtlData = findVTLData(target);
1328
+ * console.log(vtlData);
1329
+ * ```
1330
+ */
1331
+ function findVTLData(target) {
1332
+ const vltElements = target.querySelectorAll('[data-dot-object="vtl-file"]');
1333
+ if (!vltElements.length) {
1334
+ return null;
1335
+ }
1336
+ return Array.from(vltElements).map((vltElement) => {
1337
+ return {
1338
+ inode: vltElement.dataset?.['dotInode'],
1339
+ name: vltElement.dataset?.['dotUrl']
1340
+ };
1341
+ });
1342
+ }
1343
+ /**
1344
+ * Check if the scroll position is at the bottom of the page.
1345
+ *
1346
+ * @export
1347
+ * @return {boolean} True if the scroll position is at the bottom, otherwise false.
1348
+ * @example
1349
+ * ```ts
1350
+ * if (scrollIsInBottom()) {
1351
+ * console.log('Scrolled to the bottom');
1352
+ * }
1353
+ * ```
1354
+ */
1355
+ function scrollIsInBottom() {
1356
+ const documentHeight = document.documentElement.scrollHeight;
1357
+ const viewportHeight = window.innerHeight;
1358
+ const scrollY = window.scrollY;
1359
+ return scrollY + viewportHeight >= documentHeight;
1360
+ }
1361
+
1362
+ /**
1363
+ * Represents an array of DotCMSPageEditorSubscription objects.
1364
+ * Used to store the subscriptions for the editor and unsubscribe later.
1365
+ */
1366
+ const subscriptions = [];
1367
+ /**
1368
+ * Sets the bounds of the containers in the editor.
1369
+ * Retrieves the containers from the DOM and sends their position data to the editor.
1370
+ * @private
1371
+ * @memberof DotCMSPageEditor
1372
+ */
1373
+ function setBounds() {
1374
+ const containers = Array.from(document.querySelectorAll('[data-dot-object="container"]'));
1375
+ const positionData = getPageElementBound(containers);
1376
+ postMessageToEditor({
1377
+ action: exports.CLIENT_ACTIONS.SET_BOUNDS,
1378
+ payload: positionData
1379
+ });
1380
+ }
1381
+ /**
1382
+ * Listens for editor messages and performs corresponding actions based on the received message.
1383
+ *
1384
+ * @private
1385
+ * @memberof DotCMSPageEditor
1386
+ */
1387
+ function listenEditorMessages() {
1388
+ const messageCallback = (event) => {
1389
+ const ACTIONS_NOTIFICATION = {
1390
+ [exports.NOTIFY_CLIENT.UVE_RELOAD_PAGE]: () => {
1391
+ window.location.reload();
1392
+ },
1393
+ [exports.NOTIFY_CLIENT.UVE_REQUEST_BOUNDS]: () => {
1394
+ setBounds();
1395
+ },
1396
+ [exports.NOTIFY_CLIENT.UVE_SCROLL_INSIDE_IFRAME]: () => {
1397
+ const direction = event.data.direction;
1398
+ if ((window.scrollY === 0 && direction === 'up') ||
1399
+ (scrollIsInBottom() && direction === 'down')) {
1400
+ // If the iframe scroll is at the top or bottom, do not send anything.
1401
+ // This avoids losing the scrollend event.
1402
+ return;
1403
+ }
1404
+ const scrollY = direction === 'up' ? -120 : 120;
1405
+ window.scrollBy({ left: 0, top: scrollY, behavior: 'smooth' });
1406
+ }
1407
+ };
1408
+ ACTIONS_NOTIFICATION[event.data.name]?.();
1409
+ };
1410
+ window.addEventListener('message', messageCallback);
1411
+ subscriptions.push({
1412
+ type: 'listener',
1413
+ event: 'message',
1414
+ callback: messageCallback
1415
+ });
1416
+ }
1417
+ /**
1418
+ * Listens for pointer move events and extracts information about the hovered contentlet.
1419
+ *
1420
+ * @private
1421
+ * @memberof DotCMSPageEditor
1422
+ */
1423
+ function listenHoveredContentlet() {
1424
+ const pointerMoveCallback = (event) => {
1425
+ const foundElement = findDotElement(event.target);
1426
+ if (!foundElement)
1427
+ return;
1428
+ const { x, y, width, height } = foundElement.getBoundingClientRect();
1429
+ const isContainer = foundElement.dataset?.['dotObject'] === 'container';
1430
+ const contentletForEmptyContainer = {
1431
+ identifier: 'TEMP_EMPTY_CONTENTLET',
1432
+ title: 'TEMP_EMPTY_CONTENTLET',
1433
+ contentType: 'TEMP_EMPTY_CONTENTLET_TYPE',
1434
+ inode: 'TEMPY_EMPTY_CONTENTLET_INODE',
1435
+ widgetTitle: 'TEMP_EMPTY_CONTENTLET',
1436
+ baseType: 'TEMP_EMPTY_CONTENTLET',
1437
+ onNumberOfPages: 1
1438
+ };
1439
+ const contentlet = {
1440
+ identifier: foundElement.dataset?.['dotIdentifier'],
1441
+ title: foundElement.dataset?.['dotTitle'],
1442
+ inode: foundElement.dataset?.['dotInode'],
1443
+ contentType: foundElement.dataset?.['dotType'],
1444
+ baseType: foundElement.dataset?.['dotBasetype'],
1445
+ widgetTitle: foundElement.dataset?.['dotWidgetTitle'],
1446
+ onNumberOfPages: foundElement.dataset?.['dotOnNumberOfPages']
1447
+ };
1448
+ const vtlFiles = findVTLData(foundElement);
1449
+ const contentletPayload = {
1450
+ container:
1451
+ // Here extract dot-container from contentlet if it is Headless
1452
+ // or search in parent container if it is VTL
1453
+ foundElement.dataset?.['dotContainer']
1454
+ ? JSON.parse(foundElement.dataset?.['dotContainer'])
1455
+ : getClosestContainerData(foundElement),
1456
+ contentlet: isContainer ? contentletForEmptyContainer : contentlet,
1457
+ vtlFiles
1458
+ };
1459
+ postMessageToEditor({
1460
+ action: exports.CLIENT_ACTIONS.SET_CONTENTLET,
1461
+ payload: {
1462
+ x,
1463
+ y,
1464
+ width,
1465
+ height,
1466
+ payload: contentletPayload
1467
+ }
1468
+ });
1469
+ };
1470
+ document.addEventListener('pointermove', pointerMoveCallback);
1471
+ subscriptions.push({
1472
+ type: 'listener',
1473
+ event: 'pointermove',
1474
+ callback: pointerMoveCallback
1475
+ });
1476
+ }
1477
+ /**
1478
+ * Attaches a scroll event listener to the window
1479
+ * and sends a message to the editor when the window is scrolled.
1480
+ *
1481
+ * @private
1482
+ * @memberof DotCMSPageEditor
1483
+ */
1484
+ function scrollHandler() {
1485
+ const scrollCallback = () => {
1486
+ postMessageToEditor({
1487
+ action: exports.CLIENT_ACTIONS.IFRAME_SCROLL
1488
+ });
1489
+ // In case it doesn't have a dotUVE object, we create it with the initial values.
1490
+ window.dotUVE = {
1491
+ ...(window.dotUVE ?? INITIAL_DOT_UVE),
1492
+ lastScrollYPosition: window.scrollY
1493
+ };
1494
+ };
1495
+ const scrollEndCallback = () => {
1496
+ postMessageToEditor({
1497
+ action: exports.CLIENT_ACTIONS.IFRAME_SCROLL_END
1498
+ });
1499
+ };
1500
+ window.addEventListener('scroll', scrollCallback);
1501
+ window.addEventListener('scrollend', scrollEndCallback);
1502
+ subscriptions.push({
1503
+ type: 'listener',
1504
+ event: 'scroll',
1505
+ callback: scrollEndCallback
1506
+ });
1507
+ subscriptions.push({
1508
+ type: 'listener',
1509
+ event: 'scroll',
1510
+ callback: scrollCallback
1511
+ });
1512
+ }
1513
+ /**
1514
+ * Sends a message to the editor to get the page data.
1515
+ * @param {string} pathname - The pathname of the page.
1516
+ * @private
1517
+ * @memberof DotCMSPageEditor
1518
+ */
1519
+ function fetchPageDataFromInsideUVE(pathname) {
1520
+ postMessageToEditor({
1521
+ action: exports.CLIENT_ACTIONS.GET_PAGE_DATA,
1522
+ payload: {
1523
+ pathname
1524
+ }
1525
+ });
1526
+ }
1527
+
1528
+ /**
1529
+ * Updates the navigation in the editor.
1530
+ *
1531
+ * @param {string} pathname - The pathname to update the navigation with.
1532
+ * @memberof DotCMSPageEditor
1533
+ * @example
1534
+ * updateNavigation('/home'); // Sends a message to the editor to update the navigation to '/home'
1535
+ */
1536
+ function updateNavigation(pathname) {
1537
+ postMessageToEditor({
1538
+ action: exports.CLIENT_ACTIONS.NAVIGATION_UPDATE,
1539
+ payload: {
1540
+ url: pathname || '/'
1541
+ }
1542
+ });
1543
+ }
1544
+ /**
1545
+ * You can use this function to edit a contentlet in the editor.
1546
+ *
1547
+ * Calling this function inside the editor, will prompt the UVE to open a dialog to edit the contentlet.
1548
+ *
1549
+ * @export
1550
+ * @template T
1551
+ * @param {Contentlet<T>} contentlet - The contentlet to edit.
1552
+ */
1553
+ function editContentlet(contentlet) {
1554
+ postMessageToEditor({
1555
+ action: exports.CLIENT_ACTIONS.EDIT_CONTENTLET,
1556
+ payload: contentlet
1557
+ });
1558
+ }
1559
+ /**
1560
+ * Initializes the inline editing in the editor.
1561
+ *
1562
+ * @export
1563
+ * @param {INLINE_EDITING_EVENT_KEY} type
1564
+ * @param {InlineEditEventData} eventData
1565
+ * @return {*}
1566
+ *
1567
+ * * @example
1568
+ * ```html
1569
+ * <div onclick="initInlineEditing('BLOCK_EDITOR', { inode, languageId, contentType, fieldName, content })">
1570
+ * ${My Content}
1571
+ * </div>
1572
+ * ```
1573
+ */
1574
+ function initInlineEditing(type, data) {
1575
+ postMessageToEditor({
1576
+ action: exports.CLIENT_ACTIONS.INIT_INLINE_EDITING,
1577
+ payload: {
1578
+ type,
1579
+ data
1580
+ }
1581
+ });
1582
+ }
1583
+ /*
1584
+ * Reorders the menu based on the provided configuration.
1585
+ *
1586
+ * @param {ReorderMenuConfig} [config] - Optional configuration for reordering the menu.
1587
+ * @param {number} [config.startLevel=1] - The starting level of the menu to reorder.
1588
+ * @param {number} [config.depth=2] - The depth of the menu to reorder.
1589
+ *
1590
+ * This function constructs a URL for the reorder menu page with the specified
1591
+ * start level and depth, and sends a message to the editor to perform the reorder action.
1592
+ */
1593
+ function reorderMenu(config) {
1594
+ const { startLevel = 1, depth = 2 } = config || {};
1595
+ postMessageToEditor({
1596
+ action: exports.CLIENT_ACTIONS.REORDER_MENU,
1597
+ payload: { startLevel, depth }
1598
+ });
1599
+ }
1600
+ /**
1601
+ * @deprecated Use `getUVEState` function on {@link https://npmjs.com/package/@dotcms/uve|@dotcms/uve} instead, this function will be removed on future versions.
1602
+ *
1603
+ * Checks if the code is running inside the DotCMS Universal Visual Editor (UVE).
1604
+ *
1605
+ * The function checks three conditions:
1606
+ * 1. If window is defined (for SSR environments)
1607
+ * 2. If the page is not in preview mode
1608
+ * 3. If the current window is embedded in a parent frame
1609
+ *
1610
+ * @returns {boolean} Returns true if running inside the UVE editor, false if running standalone or in preview mode
1611
+ * @example
1612
+ * ```ts
1613
+ * // Check if code is running in editor before initializing editor-specific features
1614
+ * if (isInsideEditor()) {
1615
+ * initEditor(config);
1616
+ * } else {
1617
+ * initStandaloneMode();
1618
+ * }
1619
+ * ```
1620
+ */
1621
+ function isInsideEditor() {
1622
+ if (typeof window === 'undefined') {
1623
+ return false;
1624
+ }
1625
+ return window.parent !== window;
1626
+ }
1627
+ function initDotUVE() {
1628
+ window.dotUVE = INITIAL_DOT_UVE;
1629
+ }
1630
+ /**
1631
+ * Initializes the DotCMS page editor.
1632
+ *
1633
+ * @param {DotCMSPageEditorConfig} config - Optional configuration for the editor.
1634
+ * @example
1635
+ * ```ts
1636
+ * const config = { pathname: '/home' };
1637
+ * initEditor(config); // Initializes the editor with the provided configuration
1638
+ * ```
1639
+ */
1640
+ function initEditor(config) {
1641
+ initDotUVE();
1642
+ fetchPageDataFromInsideUVE(config.pathname);
1643
+ listenEditorMessages();
1644
+ listenHoveredContentlet();
1645
+ scrollHandler();
1646
+ }
1647
+ /**
1648
+ * Destroys the editor by removing event listeners and disconnecting observers.
1649
+ *
1650
+ * @example
1651
+ * ```ts
1652
+ * destroyEditor(); // Cleans up the editor by removing all event listeners and disconnecting observers
1653
+ * ```
1654
+ */
1655
+ function destroyEditor() {
1656
+ subscriptions.forEach((subscription) => {
1657
+ if (subscription.type === 'listener') {
1658
+ window.removeEventListener(subscription.event, subscription.callback);
1659
+ }
1660
+ if (subscription.type === 'observer') {
1661
+ subscription.observer.disconnect();
1662
+ }
1663
+ });
1664
+ }
1665
+
1666
+ var _DotCmsClient_config, _DotCmsClient_requestOptions, _DotCmsClient_listeners;
1667
+ function getHostURL(url) {
1668
+ try {
1669
+ return new URL(url);
1670
+ }
1671
+ catch (error) {
1672
+ return undefined;
1673
+ }
1674
+ }
1675
+ /**
1676
+ * `DotCmsClient` is a TypeScript class that provides methods to interact with the DotCMS REST API.
1677
+ * DotCMS is a hybrid-headless CMS and digital experience platform.
1678
+ *
1679
+ * @class DotCmsClient
1680
+ * @property {ClientConfig} config - The configuration object for the DotCMS client.
1681
+ * @property {Content} content - Provides methods to interact with content in DotCMS.
1682
+ *
1683
+ * @method constructor(config: ClientConfig) - Constructs a new instance of the DotCmsClient class.
1684
+ *
1685
+ * @method page.get(options: PageApiOptions): Promise<PageApiResponse> - Retrieves all the elements of any Page in your dotCMS system in JSON format.
1686
+ * The Page API enables you to retrieve page information, layout, template, content blocks, and more.
1687
+ * @see {@link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas}
1688
+ *
1689
+ * @method nav.get(options: NavApiOptions = { depth: 0, path: '/', languageId: 1 }): Promise<NavApiResponse> - Retrieves information about the dotCMS file and folder tree.
1690
+ * The Navigation API allows you to fetch the site structure and menu items.
1691
+ * @see {@link https://www.dotcms.com/docs/latest/navigation-rest-api}
1692
+ *
1693
+ * @method content.get(options: ContentApiOptions): Promise<ContentApiResponse> - Retrieves content items based on specified criteria.
1694
+ * The Content API allows you to query and retrieve content by ID, inode, or using Lucene queries.
1695
+ * @see {@link https://www.dotcms.com/docs/latest/content-api-retrieval-and-querying}
1696
+ *
1697
+ * @method editor.on(action: string, callbackFn: (payload: unknown) => void) - Allows you to react to actions issued by the Universal Visual Editor (UVE).
1698
+ * @method editor.off(action: string) - Stops listening to an action issued by UVE.
1699
+ *
1700
+ * @static
1701
+ * @method init(config: ClientConfig): DotCmsClient - Initializes and returns a DotCmsClient instance.
1702
+ * @method dotcmsUrl: string - Retrieves the DotCMS URL from the instance configuration.
1703
+ *
1704
+ * @example <caption>Basic usage</caption>
1705
+ * ```javascript
1706
+ * const client = DotCmsClient.init({ dotcmsUrl: 'https://demo.dotcms.com', authToken: 'your-auth-token' });
1707
+ *
1708
+ * // Get a page
1709
+ * client.page.get({ path: '/about-us' }).then(response => console.log(response));
1710
+ *
1711
+ * // Get navigation
1712
+ * client.nav.get({ path: '/about-us', depth: 2 }).then(response => console.log(response));
1713
+ *
1714
+ * // Get content
1715
+ * client.content.get({ query: '+contentType:Blog +languageId:1', limit: 10 }).then(response => console.log(response));
1716
+ *
1717
+ * // Listen to editor changes
1718
+ * client.editor.on('changes', (payload) => console.log('Changes detected:', payload));
1719
+ * ```
1720
+ */
1721
+ class DotCmsClient {
1722
+ constructor(config = { dotcmsUrl: '', authToken: '', requestOptions: {}, siteId: '' }) {
1723
+ _DotCmsClient_config.set(this, void 0);
1724
+ _DotCmsClient_requestOptions.set(this, void 0);
1725
+ _DotCmsClient_listeners.set(this, []);
1726
+ this.page = {
1727
+ /**
1728
+ * `page.get` is an asynchronous method of the `DotCmsClient` class that retrieves all the elements of any Page in your dotCMS system in JSON format.
1729
+ * It takes a `PageApiOptions` object as a parameter and returns a Promise that resolves to the response from the DotCMS API.
1730
+ *
1731
+ * The Page API enables you to retrieve all the elements of any Page in your dotCMS system.
1732
+ * The elements may be retrieved in JSON format.
1733
+ *
1734
+ * @link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas
1735
+ * @async
1736
+ * @param {PageApiOptions} options - The options for the Page API call.
1737
+ * @returns {Promise<unknown>} - A Promise that resolves to the response from the DotCMS API.
1738
+ * @throws {Error} - Throws an error if the options are not valid.
1739
+ * @example
1740
+ * ```ts
1741
+ * const client = new DotCmsClient({ dotcmsUrl: 'https://your.dotcms.com', authToken: 'your-auth-token', siteId: 'your-site-id' });
1742
+ * client.page.get({ path: '/about-us' }).then(response => console.log(response));
1743
+ * ```
1744
+ */
1745
+ get: async (options) => {
1746
+ this.validatePageOptions(options);
1747
+ const queryParamsObj = {};
1748
+ for (const [key, value] of Object.entries(options)) {
1749
+ if (value === undefined || key === 'path' || key === 'siteId')
1750
+ continue;
1751
+ if (key === 'personaId') {
1752
+ queryParamsObj['com.dotmarketing.persona.id'] = String(value);
1753
+ }
1754
+ else if (key === 'mode' && value) {
1755
+ queryParamsObj['mode'] = String(value);
1756
+ }
1757
+ else {
1758
+ queryParamsObj[key] = String(value);
1759
+ }
1760
+ }
1761
+ const queryHostId = options.siteId ?? __classPrivateFieldGet(this, _DotCmsClient_config, "f").siteId ?? '';
1762
+ if (queryHostId) {
1763
+ queryParamsObj['host_id'] = queryHostId;
1764
+ }
1765
+ const queryParams = new URLSearchParams(queryParamsObj).toString();
1766
+ const formattedPath = options.path.startsWith('/') ? options.path : `/${options.path}`;
1767
+ const url = `${__classPrivateFieldGet(this, _DotCmsClient_config, "f").dotcmsUrl}/api/v1/page/json${formattedPath}${queryParams ? `?${queryParams}` : ''}`;
1768
+ const response = await fetch(url, __classPrivateFieldGet(this, _DotCmsClient_requestOptions, "f"));
1769
+ if (!response.ok) {
1770
+ const error = {
1771
+ status: response.status,
1772
+ message: ErrorMessages[response.status] || response.statusText
1773
+ };
1774
+ console.error(error);
1775
+ throw error;
1776
+ }
1777
+ return response.json().then((data) => data.entity);
1778
+ }
1779
+ };
1780
+ this.editor = {
1781
+ /**
1782
+ * `editor.on` is an asynchronous method of the `DotCmsClient` class that allows you to react to actions issued by the UVE.
1783
+ *
1784
+ * NOTE: This is being used by the development team - This logic is probably varied or moved to another function/object.
1785
+ * @param {string} action - The name of the action emitted by UVE.
1786
+ * @param {function} callbackFn - The function to execute when the UVE emits the action.
1787
+ * @example
1788
+ * ```ts
1789
+ * client.editor.on('changes', (payload) => {
1790
+ * console.log('Changes detected:', payload);
1791
+ * });
1792
+ * ```
1793
+ */
1794
+ on: (action, callbackFn) => {
1795
+ if (!isInsideEditor()) {
1796
+ return;
1797
+ }
1798
+ if (action === 'changes') {
1799
+ const messageCallback = (event) => {
1800
+ if (event.data.name === exports.NOTIFY_CLIENT.UVE_SET_PAGE_DATA) {
1801
+ callbackFn(event.data.payload);
1802
+ }
1803
+ };
1804
+ window.addEventListener('message', messageCallback);
1805
+ __classPrivateFieldGet(this, _DotCmsClient_listeners, "f").push({ event: 'message', callback: messageCallback, action });
1806
+ }
1807
+ },
1808
+ /**
1809
+ * `editor.off` is a synchronous method of the `DotCmsClient` class that allows you to stop listening and reacting to an action issued by UVE.
1810
+ *
1811
+ * NOTE: This is being used by the development team - This logic is probably varied or moved to another function/object.
1812
+ * @param {string} action - The name of the action to stop listening to.
1813
+ * @example
1814
+ * ```ts
1815
+ * client.editor.off('changes');
1816
+ * ```
1817
+ */
1818
+ off: (action) => {
1819
+ const listenerIndex = __classPrivateFieldGet(this, _DotCmsClient_listeners, "f").findIndex((listener) => listener.action === action);
1820
+ if (listenerIndex !== -1) {
1821
+ const listener = __classPrivateFieldGet(this, _DotCmsClient_listeners, "f")[listenerIndex];
1822
+ window.removeEventListener(listener.event, listener.callback);
1823
+ __classPrivateFieldGet(this, _DotCmsClient_listeners, "f").splice(listenerIndex, 1);
1824
+ }
1825
+ }
1826
+ };
1827
+ this.nav = {
1828
+ /**
1829
+ * `nav.get` is an asynchronous method of the `DotCmsClient` class that retrieves information about the dotCMS file and folder tree.
1830
+ * It takes a `NavApiOptions` object as a parameter (with default values) and returns a Promise that resolves to the response from the DotCMS API.
1831
+ *
1832
+ * The navigation REST API enables you to retrieve information about the dotCMS file and folder tree through REST API calls.
1833
+ * @link https://www.dotcms.com/docs/latest/navigation-rest-api
1834
+ * @async
1835
+ * @param {NavApiOptions} options - The options for the Nav API call. Defaults to `{ depth: 0, path: '/', languageId: 1 }`.
1836
+ * @returns {Promise<unknown>} - A Promise that resolves to the response from the DotCMS API.
1837
+ * @throws {Error} - Throws an error if the options are not valid.
1838
+ * @example
1839
+ * ```ts
1840
+ * const client = new DotCmsClient({ dotcmsUrl: 'https://your.dotcms.com', authToken: 'your-auth-token', siteId: 'your-site-id' }});
1841
+ * client.nav.get({ path: '/about-us', depth: 2 }).then(response => console.log(response));
1842
+ * ```
1843
+ */
1844
+ get: async (options = { depth: 0, path: '/', languageId: 1 }) => {
1845
+ this.validateNavOptions(options);
1846
+ // Extract the 'path' from the options and prepare the rest as query parameters
1847
+ const { path, ...queryParamsOptions } = options;
1848
+ const queryParamsObj = {};
1849
+ Object.entries(queryParamsOptions).forEach(([key, value]) => {
1850
+ if (value !== undefined) {
1851
+ queryParamsObj[key] = String(value);
1852
+ }
1853
+ });
1854
+ const queryParams = new URLSearchParams(queryParamsObj).toString();
1855
+ // Format the URL correctly depending on the 'path' value
1856
+ const formattedPath = path === '/' ? '/' : `/${path}`;
1857
+ const url = `${__classPrivateFieldGet(this, _DotCmsClient_config, "f").dotcmsUrl}/api/v1/nav${formattedPath}${queryParams ? `?${queryParams}` : ''}`;
1858
+ const response = await fetch(url, __classPrivateFieldGet(this, _DotCmsClient_requestOptions, "f"));
1859
+ return response.json();
1860
+ }
1861
+ };
1862
+ if (!config.dotcmsUrl) {
1863
+ throw new Error("Invalid configuration - 'dotcmsUrl' is required");
1864
+ }
1865
+ this.dotcmsUrl = getHostURL(config.dotcmsUrl)?.origin;
1866
+ if (!this.dotcmsUrl) {
1867
+ throw new Error("Invalid configuration - 'dotcmsUrl' must be a valid URL");
1868
+ }
1869
+ if (!config.authToken) {
1870
+ throw new Error("Invalid configuration - 'authToken' is required");
1871
+ }
1872
+ __classPrivateFieldSet(this, _DotCmsClient_config, {
1873
+ ...config,
1874
+ dotcmsUrl: this.dotcmsUrl
1875
+ }, "f");
1876
+ __classPrivateFieldSet(this, _DotCmsClient_requestOptions, {
1877
+ ...__classPrivateFieldGet(this, _DotCmsClient_config, "f").requestOptions,
1878
+ headers: {
1879
+ Authorization: `Bearer ${__classPrivateFieldGet(this, _DotCmsClient_config, "f").authToken}`,
1880
+ ...__classPrivateFieldGet(this, _DotCmsClient_config, "f").requestOptions?.headers
1881
+ }
1882
+ }, "f");
1883
+ this.content = new Content(__classPrivateFieldGet(this, _DotCmsClient_requestOptions, "f"), __classPrivateFieldGet(this, _DotCmsClient_config, "f").dotcmsUrl);
1884
+ }
1885
+ /**
1886
+ * Initializes the DotCmsClient instance with the provided configuration.
1887
+ * If an instance already exists, it returns the existing instance.
1888
+ *
1889
+ * @param {ClientConfig} config - The configuration object for the DotCMS client.
1890
+ * @returns {DotCmsClient} - The initialized DotCmsClient instance.
1891
+ * @example
1892
+ * ```ts
1893
+ * const client = DotCmsClient.init({ dotcmsUrl: 'https://demo.dotcms.com', authToken: 'your-auth-token' });
1894
+ * ```
1895
+ */
1896
+ static init(config) {
1897
+ if (this.instance) {
1898
+ console.warn('DotCmsClient has already been initialized. Please use the instance to interact with the DotCMS API.');
1899
+ }
1900
+ return this.instance ?? (this.instance = new DotCmsClient(config));
1901
+ }
1902
+ /**
1903
+ * Retrieves the DotCMS URL from the instance configuration.
1904
+ *
1905
+ * @returns {string} - The DotCMS URL.
1906
+ */
1907
+ static get dotcmsUrl() {
1908
+ return (this.instance && __classPrivateFieldGet(this.instance, _DotCmsClient_config, "f").dotcmsUrl) || '';
1909
+ }
1910
+ /**
1911
+ * Throws an error if the path is not valid.
1912
+ *
1913
+ * @returns {string} - The authentication token.
1914
+ */
1915
+ validatePageOptions(options) {
1916
+ if (!options.path) {
1917
+ throw new Error("The 'path' parameter is required for the Page API");
1918
+ }
1919
+ }
1920
+ /**
1921
+ * Throws an error if the path is not valid.
1922
+ *
1923
+ * @returns {string} - The authentication token.
1924
+ */
1925
+ validateNavOptions(options) {
1926
+ if (!options.path) {
1927
+ throw new Error("The 'path' parameter is required for the Nav API");
1928
+ }
1929
+ }
1930
+ }
1931
+ _DotCmsClient_config = new WeakMap(), _DotCmsClient_requestOptions = new WeakMap(), _DotCmsClient_listeners = new WeakMap();
1932
+
1933
+ /**
1934
+ * Transforms a GraphQL Page response to a Page Entity.
1935
+ *
1936
+ * @param {GraphQLPageResponse} graphQLPageResponse - The GraphQL Page response object.
1937
+ * @returns {object|null} The transformed Page Entity or null if the page is not present.
1938
+ *
1939
+ * @example
1940
+ * ```ts
1941
+ * const pageEntity = graphqlToPageEntity(graphQLPageResponse);
1942
+ * ```
1943
+ */
1944
+ const graphqlToPageEntity = (graphQLPageResponse) => {
1945
+ const { page } = graphQLPageResponse;
1946
+ // If there is no page, return null
1947
+ if (!page) {
1948
+ return null;
1949
+ }
1950
+ const { layout, template, containers, urlContentMap, viewAs, site, _map, ...pageAsset } = page;
1951
+ const data = (_map || {});
1952
+ return {
1953
+ layout,
1954
+ template,
1955
+ viewAs,
1956
+ urlContentMap,
1957
+ site,
1958
+ page: {
1959
+ ...data,
1960
+ ...pageAsset
1961
+ },
1962
+ containers: parseContainers(containers)
1963
+ };
1964
+ };
1965
+ /**
1966
+ * Parses the containers from the GraphQL response.
1967
+ *
1968
+ * @param {Array<Record<string, unknown>>} [containers=[]] - The containers array from the GraphQL response.
1969
+ * @returns {Record<string, unknown>} The parsed containers.
1970
+ */
1971
+ const parseContainers = (containers = []) => {
1972
+ return containers.reduce((acc, container) => {
1973
+ const { path, identifier, containerStructures, containerContentlets, ...rest } = container;
1974
+ const key = (path || identifier);
1975
+ acc[key] = {
1976
+ containerStructures,
1977
+ container: {
1978
+ path,
1979
+ identifier,
1980
+ ...rest
1981
+ },
1982
+ contentlets: parseContentletsToUuidMap(containerContentlets)
1983
+ };
1984
+ return acc;
1985
+ }, {});
1986
+ };
1987
+ /**
1988
+ * Parses the contentlets from the GraphQL response.
1989
+ *
1990
+ * @param {Array<Record<string, unknown>>} containerContentlets - The contentlets array from the GraphQL response.
1991
+ * @returns {Record<string, Array<Record<string, unknown>>>} The parsed contentlets mapped by UUID.
1992
+ */
1993
+ const parseContentletsToUuidMap = (containerContentlets = []) => {
1994
+ return containerContentlets.reduce((acc, containerContentlet) => {
1995
+ const { uuid, contentlets } = containerContentlet;
1996
+ // TODO: This is a temporary solution, we need to find a better way to handle this.
1997
+ acc[uuid] = contentlets.map(({ _map = {}, ...rest }) => {
1998
+ return {
1999
+ ..._map,
2000
+ ...rest
2001
+ };
2002
+ });
2003
+ return acc;
2004
+ }, {});
2005
+ };
2006
+
2007
+ /**
2008
+ * Generates the page request parameters to be used in the API call.
2009
+ *
2010
+ * @param {PageRequestParamsProps} PageRequestParamsProps - The properties for the page request.
2011
+ * @returns {PageApiOptions} The options for the page API.
2012
+ * @example
2013
+ * ```ts
2014
+ * const pageApiOptions = getPageRequestParams({ path: '/api/v1/page', params: queryParams });
2015
+ * ```
2016
+ */
2017
+ const getPageRequestParams = ({ path = '', params = {} }) => {
2018
+ const copiedParams = params instanceof URLSearchParams ? Object.fromEntries(params.entries()) : { ...params };
2019
+ const finalParams = {};
2020
+ const dotMarketingPersonaId = copiedParams['com.dotmarketing.persona.id'] || '';
2021
+ finalParams['mode'] = copiedParams['mode'] || 'LIVE';
2022
+ if (copiedParams['language_id']) {
2023
+ finalParams['language_id'] = copiedParams['language_id'];
2024
+ }
2025
+ if (copiedParams['variantName']) {
2026
+ finalParams['variantName'] = copiedParams['variantName'];
2027
+ }
2028
+ if (copiedParams['personaId'] || dotMarketingPersonaId) {
2029
+ finalParams['personaId'] = copiedParams['personaId'] || dotMarketingPersonaId;
2030
+ }
2031
+ if (copiedParams['publishDate']) {
2032
+ finalParams['publishDate'] = copiedParams['publishDate'];
2033
+ }
2034
+ return {
2035
+ path,
2036
+ ...finalParams
2037
+ };
2038
+ };
2039
+
2040
+ exports.DotCmsClient = DotCmsClient;
2041
+ exports.destroyEditor = destroyEditor;
2042
+ exports.editContentlet = editContentlet;
2043
+ exports.getPageRequestParams = getPageRequestParams;
2044
+ exports.graphqlToPageEntity = graphqlToPageEntity;
2045
+ exports.initEditor = initEditor;
2046
+ exports.initInlineEditing = initInlineEditing;
2047
+ exports.isInsideEditor = isInsideEditor;
2048
+ exports.postMessageToEditor = postMessageToEditor;
2049
+ exports.reorderMenu = reorderMenu;
2050
+ exports.updateNavigation = updateNavigation;