@dotcms/client 0.0.1-alpha.37 → 0.0.1-alpha.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +18 -0
- package/README.md +4 -4
- package/jest.config.ts +15 -0
- package/package.json +3 -15
- package/project.json +72 -0
- package/src/index.ts +30 -0
- package/src/lib/client/content/builders/collection/collection.spec.ts +515 -0
- package/src/lib/client/content/builders/collection/collection.ts +416 -0
- package/src/lib/client/content/content-api.ts +139 -0
- package/src/lib/client/content/shared/const.ts +15 -0
- package/src/lib/client/content/shared/types.ts +155 -0
- package/src/lib/client/content/shared/utils.ts +28 -0
- package/src/lib/client/models/index.ts +19 -0
- package/src/lib/client/models/types.ts +14 -0
- package/src/lib/client/sdk-js-client.spec.ts +483 -0
- package/src/lib/client/sdk-js-client.ts +442 -0
- package/src/lib/editor/listeners/listeners.spec.ts +119 -0
- package/src/lib/editor/listeners/listeners.ts +223 -0
- package/src/lib/editor/models/{client.model.d.ts → client.model.ts} +19 -16
- package/src/lib/editor/models/{editor.model.d.ts → editor.model.ts} +9 -5
- package/src/lib/editor/models/{listeners.model.d.ts → listeners.model.ts} +9 -6
- package/src/lib/editor/sdk-editor-vtl.ts +31 -0
- package/src/lib/editor/sdk-editor.spec.ts +116 -0
- package/src/lib/editor/sdk-editor.ts +105 -0
- package/src/lib/editor/utils/editor.utils.spec.ts +206 -0
- package/src/lib/editor/utils/editor.utils.ts +258 -0
- package/src/lib/query-builder/lucene-syntax/{Equals.d.ts → Equals.ts} +83 -18
- package/src/lib/query-builder/lucene-syntax/Field.ts +40 -0
- package/src/lib/query-builder/lucene-syntax/{NotOperand.d.ts → NotOperand.ts} +18 -6
- package/src/lib/query-builder/lucene-syntax/{Operand.d.ts → Operand.ts} +21 -7
- package/src/lib/query-builder/sdk-query-builder.spec.ts +159 -0
- package/src/lib/query-builder/sdk-query-builder.ts +87 -0
- package/src/lib/query-builder/utils/index.ts +179 -0
- package/src/lib/utils/graphql/transforms.spec.ts +150 -0
- package/src/lib/utils/graphql/transforms.ts +99 -0
- package/src/lib/utils/page/common-utils.spec.ts +37 -0
- package/src/lib/utils/page/common-utils.ts +64 -0
- package/tsconfig.json +22 -0
- package/tsconfig.lib.json +13 -0
- package/tsconfig.spec.json +9 -0
- package/index.cjs.d.ts +0 -1
- package/index.cjs.default.js +0 -1
- package/index.cjs.js +0 -1490
- package/index.cjs.mjs +0 -2
- package/index.esm.d.ts +0 -1
- package/index.esm.js +0 -1481
- package/src/index.d.ts +0 -6
- package/src/lib/client/content/builders/collection/collection.d.ts +0 -148
- package/src/lib/client/content/content-api.d.ts +0 -78
- package/src/lib/client/content/shared/const.d.ts +0 -3
- package/src/lib/client/content/shared/types.d.ts +0 -62
- package/src/lib/client/content/shared/utils.d.ts +0 -12
- package/src/lib/client/models/index.d.ts +0 -1
- package/src/lib/client/models/types.d.ts +0 -5
- package/src/lib/client/sdk-js-client.d.ts +0 -193
- package/src/lib/editor/listeners/listeners.d.ts +0 -46
- package/src/lib/editor/sdk-editor-vtl.d.ts +0 -6
- package/src/lib/editor/sdk-editor.d.ts +0 -29
- package/src/lib/editor/utils/editor.utils.d.ts +0 -83
- package/src/lib/query-builder/lucene-syntax/Field.d.ts +0 -23
- package/src/lib/query-builder/sdk-query-builder.d.ts +0 -42
- package/src/lib/query-builder/utils/index.d.ts +0 -91
- package/src/lib/utils/graphql/transforms.d.ts +0 -11
- package/src/lib/utils/page/common-utils.d.ts +0 -11
- /package/src/lib/query-builder/lucene-syntax/{index.d.ts → index.ts} +0 -0
- /package/src/lib/utils/{index.d.ts → index.ts} +0 -0
package/index.cjs.js
DELETED
|
@@ -1,1490 +0,0 @@
|
|
|
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
|
-
* 'Field' class is used to build a query with a 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
|
-
constructor(query) {
|
|
48
|
-
this.query = query;
|
|
49
|
-
_Field_query.set(this, '');
|
|
50
|
-
__classPrivateFieldSet(this, _Field_query, this.query, "f");
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* This method appends to the query a term that should be included in the search..
|
|
54
|
-
*
|
|
55
|
-
* Ex: myValue or "My value"
|
|
56
|
-
*
|
|
57
|
-
* @param {string} term - The term that should be included in the search.
|
|
58
|
-
* @return {*} {Equals} - An instance of Equals.
|
|
59
|
-
* @memberof Field
|
|
60
|
-
*/
|
|
61
|
-
equals(term) {
|
|
62
|
-
return buildEquals(__classPrivateFieldGet(this, _Field_query, "f"), term);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
_Field_query = new WeakMap();
|
|
66
|
-
|
|
67
|
-
var _NotOperand_query;
|
|
68
|
-
/**
|
|
69
|
-
* 'NotOperand' Is a Typescript class that provides the ability to use the NOT operand in the lucene query string.
|
|
70
|
-
*
|
|
71
|
-
* @export
|
|
72
|
-
* @class NotOperand
|
|
73
|
-
*/
|
|
74
|
-
class NotOperand {
|
|
75
|
-
constructor(query) {
|
|
76
|
-
this.query = query;
|
|
77
|
-
_NotOperand_query.set(this, '');
|
|
78
|
-
__classPrivateFieldSet(this, _NotOperand_query, this.query, "f");
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* This method appends to the query a term that should be included in the search.
|
|
82
|
-
*
|
|
83
|
-
* Ex: myValue or "My value"
|
|
84
|
-
*
|
|
85
|
-
* @param {string} term - The term that should be included in the search.
|
|
86
|
-
* @return {*} {Equals} - An instance of Equals.
|
|
87
|
-
* @memberof NotOperand
|
|
88
|
-
*/
|
|
89
|
-
equals(term) {
|
|
90
|
-
return buildEquals(__classPrivateFieldGet(this, _NotOperand_query, "f"), term);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
_NotOperand_query = new WeakMap();
|
|
94
|
-
|
|
95
|
-
var _Operand_query;
|
|
96
|
-
/**
|
|
97
|
-
* 'Operand' Is a Typescript class that provides the ability to use operands in the lucene query string.}
|
|
98
|
-
* An operand is a logical operator used to join two or more conditions in a query.
|
|
99
|
-
*
|
|
100
|
-
* @export
|
|
101
|
-
* @class Operand
|
|
102
|
-
*/
|
|
103
|
-
class Operand {
|
|
104
|
-
constructor(query) {
|
|
105
|
-
this.query = query;
|
|
106
|
-
_Operand_query.set(this, '');
|
|
107
|
-
__classPrivateFieldSet(this, _Operand_query, this.query, "f");
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* This method appends to the query a term that should be excluded in the search.
|
|
111
|
-
*
|
|
112
|
-
* Ex: "-myValue"
|
|
113
|
-
*
|
|
114
|
-
* @param {string} field - The field that should be excluded in the search.
|
|
115
|
-
* @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
|
|
116
|
-
* @memberof Operand
|
|
117
|
-
*/
|
|
118
|
-
excludeField(field) {
|
|
119
|
-
return buildExcludeField(__classPrivateFieldGet(this, _Operand_query, "f"), field);
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* This method appends to the query a field that should be included in the search.
|
|
123
|
-
*
|
|
124
|
-
* Ex: "+myField:"
|
|
125
|
-
*
|
|
126
|
-
* @param {string} field - The field that should be included in the search.
|
|
127
|
-
* @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
|
|
128
|
-
* @memberof Operand
|
|
129
|
-
*/
|
|
130
|
-
field(field) {
|
|
131
|
-
return buildField(__classPrivateFieldGet(this, _Operand_query, "f"), field);
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* This method appends to the query a term that should be included in the search.
|
|
135
|
-
*
|
|
136
|
-
* Ex: myValue or "My value"
|
|
137
|
-
*
|
|
138
|
-
* @param {string} term - The term that should be included in the search.
|
|
139
|
-
* @return {*} {Equals} - An instance of Equals.
|
|
140
|
-
* @memberof Operand
|
|
141
|
-
*/
|
|
142
|
-
equals(term) {
|
|
143
|
-
return buildEquals(__classPrivateFieldGet(this, _Operand_query, "f"), term);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
_Operand_query = new WeakMap();
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Enum for common Operands
|
|
150
|
-
*
|
|
151
|
-
* @export
|
|
152
|
-
* @enum {number}
|
|
153
|
-
*/
|
|
154
|
-
var OPERAND;
|
|
155
|
-
(function (OPERAND) {
|
|
156
|
-
OPERAND["OR"] = "OR";
|
|
157
|
-
OPERAND["AND"] = "AND";
|
|
158
|
-
OPERAND["NOT"] = "NOT";
|
|
159
|
-
})(OPERAND || (OPERAND = {}));
|
|
160
|
-
/**
|
|
161
|
-
* This function removes extra spaces from a string.
|
|
162
|
-
*
|
|
163
|
-
* @export
|
|
164
|
-
* @param {string} str
|
|
165
|
-
* @return {*} {string}
|
|
166
|
-
*/
|
|
167
|
-
function sanitizeQuery(str) {
|
|
168
|
-
return str.replace(/\s{2,}/g, ' ').trim();
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* This function sanitizes a term by adding quotes if it contains spaces.
|
|
172
|
-
* In lucene, a term with spaces should be enclosed in quotes.
|
|
173
|
-
*
|
|
174
|
-
* @export
|
|
175
|
-
* @param {string} term
|
|
176
|
-
* @return {*} {string}
|
|
177
|
-
*/
|
|
178
|
-
function sanitizePhrases(term) {
|
|
179
|
-
return term.includes(' ') ? `"${term}"` : term;
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* This function builds a term to be used in a lucene query.
|
|
183
|
-
* We need to sanitize the term before adding it to the query.
|
|
184
|
-
*
|
|
185
|
-
* @export
|
|
186
|
-
* @param {string} query
|
|
187
|
-
* @param {string} term
|
|
188
|
-
* @return {*} {Equals}
|
|
189
|
-
*/
|
|
190
|
-
function buildEquals(query, term) {
|
|
191
|
-
const newQuery = query + sanitizePhrases(term);
|
|
192
|
-
return new Equals(newQuery);
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* This function builds a term to be used in a lucene query.
|
|
196
|
-
* We need to sanitize the raw query before adding it to the query.
|
|
197
|
-
*
|
|
198
|
-
* @export
|
|
199
|
-
* @param {string} query
|
|
200
|
-
* @param {string} raw
|
|
201
|
-
* @return {*} {Equals}
|
|
202
|
-
*/
|
|
203
|
-
function buildRawEquals(query, raw) {
|
|
204
|
-
const newQuery = query + ` ${raw}`;
|
|
205
|
-
return new Equals(sanitizeQuery(newQuery));
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* This function builds a field to be used in a lucene query.
|
|
209
|
-
* We need to format the field before adding it to the query.
|
|
210
|
-
*
|
|
211
|
-
* @export
|
|
212
|
-
* @param {string} query
|
|
213
|
-
* @param {string} field
|
|
214
|
-
* @return {*} {Field}
|
|
215
|
-
*/
|
|
216
|
-
function buildField(query, field) {
|
|
217
|
-
const newQuery = query + ` +${field}:`;
|
|
218
|
-
return new Field(newQuery);
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* This function builds an exclude field to be used in a lucene query.
|
|
222
|
-
* We need to format the field before adding it to the query.
|
|
223
|
-
*
|
|
224
|
-
* @export
|
|
225
|
-
* @param {string} query
|
|
226
|
-
* @param {string} field
|
|
227
|
-
* @return {*} {Field}
|
|
228
|
-
*/
|
|
229
|
-
function buildExcludeField(query, field) {
|
|
230
|
-
const newQuery = query + ` -${field}:`;
|
|
231
|
-
return new Field(newQuery);
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* This function builds an operand to be used in a lucene query.
|
|
235
|
-
* We need to format the operand before adding it to the query.
|
|
236
|
-
*
|
|
237
|
-
* @export
|
|
238
|
-
* @param {string} query
|
|
239
|
-
* @param {OPERAND} operand
|
|
240
|
-
* @return {*} {Operand}
|
|
241
|
-
*/
|
|
242
|
-
function buildOperand(query, operand) {
|
|
243
|
-
const newQuery = query + ` ${operand} `;
|
|
244
|
-
return new Operand(newQuery);
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* This function builds a NOT operand to be used in a lucene query.
|
|
248
|
-
* We need to format the operand before adding it to the query.
|
|
249
|
-
*
|
|
250
|
-
* @export
|
|
251
|
-
* @param {string} query
|
|
252
|
-
* @return {*} {NotOperand}
|
|
253
|
-
*/
|
|
254
|
-
function buildNotOperand(query) {
|
|
255
|
-
const newQuery = query + ` ${OPERAND.NOT} `;
|
|
256
|
-
return new NotOperand(newQuery);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
var _Equals_query;
|
|
260
|
-
/**
|
|
261
|
-
* 'Equal' Is a Typescript class that provides the ability to use terms in the lucene query string.
|
|
262
|
-
* A term is a value used to search for a specific value in a document. It can be a word or a phrase.
|
|
263
|
-
*
|
|
264
|
-
* Ex: myValue or "My Value"
|
|
265
|
-
*
|
|
266
|
-
* @export
|
|
267
|
-
* @class Equal
|
|
268
|
-
*/
|
|
269
|
-
class Equals {
|
|
270
|
-
constructor(query) {
|
|
271
|
-
this.query = query;
|
|
272
|
-
_Equals_query.set(this, '');
|
|
273
|
-
__classPrivateFieldSet(this, _Equals_query, this.query, "f");
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* This method appends to the query a term that should be excluded in the search.
|
|
277
|
-
*
|
|
278
|
-
* Ex: "-myValue"
|
|
279
|
-
*
|
|
280
|
-
* @param {string} field - The field that should be excluded in the search.
|
|
281
|
-
* @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
|
|
282
|
-
* @memberof Equal
|
|
283
|
-
*/
|
|
284
|
-
excludeField(field) {
|
|
285
|
-
return buildExcludeField(__classPrivateFieldGet(this, _Equals_query, "f"), field);
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* This method appends to the query a field that should be included in the search.
|
|
289
|
-
*
|
|
290
|
-
* Ex: "+myField:"
|
|
291
|
-
*
|
|
292
|
-
* @param {string} field - The field that should be included in the search.
|
|
293
|
-
* @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
|
|
294
|
-
* @memberof Equal
|
|
295
|
-
*/
|
|
296
|
-
field(field) {
|
|
297
|
-
return buildField(__classPrivateFieldGet(this, _Equals_query, "f"), field);
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* This method appends to the query an operand to use logic operators in the query.
|
|
301
|
-
*
|
|
302
|
-
* Ex: "OR"
|
|
303
|
-
*
|
|
304
|
-
* @return {*} {Operand} - An instance of a Lucene Operand. An operand is a logical operator used to combine terms or phrases in a query.
|
|
305
|
-
* @memberof Equal
|
|
306
|
-
*/
|
|
307
|
-
or() {
|
|
308
|
-
return buildOperand(__classPrivateFieldGet(this, _Equals_query, "f"), OPERAND.OR);
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* This method appends to the query an operand to use logic operators in the query.
|
|
312
|
-
*
|
|
313
|
-
* Ex: "AND"
|
|
314
|
-
*
|
|
315
|
-
* @return {*} {Operand} - An instance of a Lucene Operand. An operand is a logical operator used to combine terms or phrases in a query.
|
|
316
|
-
* @memberof Equal
|
|
317
|
-
*/
|
|
318
|
-
and() {
|
|
319
|
-
return buildOperand(__classPrivateFieldGet(this, _Equals_query, "f"), OPERAND.AND);
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* This method appends to the query an operand to use logic operators in the query.
|
|
323
|
-
*
|
|
324
|
-
* Ex: "NOT"
|
|
325
|
-
*
|
|
326
|
-
* @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.
|
|
327
|
-
* @memberof Equal
|
|
328
|
-
*/
|
|
329
|
-
not() {
|
|
330
|
-
return buildNotOperand(__classPrivateFieldGet(this, _Equals_query, "f"));
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* This method allows to pass a raw query string to the query builder.
|
|
334
|
-
* This raw query should end in a Lucene Equal.
|
|
335
|
-
* This method is useful when you want to append a complex query or an already written query to the query builder.
|
|
336
|
-
*
|
|
337
|
-
* Ex: "+myField: value AND (someOtherValue OR anotherValue)"
|
|
338
|
-
*
|
|
339
|
-
* @param {string} query - A raw query string.
|
|
340
|
-
* @return {*} {Equal} - An instance of a Lucene Equal. A term is a value used to search for a specific value in a document.
|
|
341
|
-
* @memberof QueryBuilder
|
|
342
|
-
*/
|
|
343
|
-
raw(query) {
|
|
344
|
-
return buildRawEquals(__classPrivateFieldGet(this, _Equals_query, "f"), query);
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* This method returns the final query string.
|
|
348
|
-
*
|
|
349
|
-
* @return {*} {string} - The final query string.
|
|
350
|
-
* @memberof Equal
|
|
351
|
-
*/
|
|
352
|
-
build() {
|
|
353
|
-
return sanitizeQuery(__classPrivateFieldGet(this, _Equals_query, "f"));
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
_Equals_query = new WeakMap();
|
|
357
|
-
|
|
358
|
-
var _QueryBuilder_query;
|
|
359
|
-
/**
|
|
360
|
-
* 'QueryBuilder' Is a Typescript class that provides the ability to build a query string using the Lucene syntax in a more readable way.
|
|
361
|
-
*
|
|
362
|
-
* @export
|
|
363
|
-
* @class QueryBuilder
|
|
364
|
-
*/
|
|
365
|
-
class QueryBuilder {
|
|
366
|
-
constructor() {
|
|
367
|
-
_QueryBuilder_query.set(this, '');
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* This method appends to the query a field that should be included in the search.
|
|
371
|
-
*
|
|
372
|
-
* Ex: "+myField:"
|
|
373
|
-
*
|
|
374
|
-
* @param {string} field - The field that should be included in the search.
|
|
375
|
-
* @return {*} {Field} - An instance of a Lucene Field. A field is a key used to search for a specific value in a document.
|
|
376
|
-
* @memberof QueryBuilder
|
|
377
|
-
*/
|
|
378
|
-
field(field) {
|
|
379
|
-
return buildField(__classPrivateFieldGet(this, _QueryBuilder_query, "f"), field);
|
|
380
|
-
}
|
|
381
|
-
/**
|
|
382
|
-
* This method appends to the query a field that should be excluded from the search.
|
|
383
|
-
*
|
|
384
|
-
* Ex: "-myField:"
|
|
385
|
-
*
|
|
386
|
-
* @param {string} field - The field that should be excluded from the search.
|
|
387
|
-
* @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.
|
|
388
|
-
* @memberof QueryBuilder
|
|
389
|
-
*/
|
|
390
|
-
excludeField(field) {
|
|
391
|
-
return buildExcludeField(__classPrivateFieldGet(this, _QueryBuilder_query, "f"), field);
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* This method allows to pass a raw query string to the query builder.
|
|
395
|
-
* This raw query should end in Equals.
|
|
396
|
-
* This method is useful when you want to append a complex query or an already written query to the query builder.
|
|
397
|
-
*
|
|
398
|
-
* Ex: "+myField: value AND (someOtherValue OR anotherValue)"
|
|
399
|
-
*
|
|
400
|
-
* @param {string} query - A raw query string.
|
|
401
|
-
* @return {*} {Equals} - An instance of Equals. A term is a value used to search for a specific value in a document.
|
|
402
|
-
* @memberof QueryBuilder
|
|
403
|
-
*/
|
|
404
|
-
raw(query) {
|
|
405
|
-
return buildRawEquals(__classPrivateFieldGet(this, _QueryBuilder_query, "f"), query);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
_QueryBuilder_query = new WeakMap();
|
|
409
|
-
|
|
410
|
-
// Fields that we don't want to format when sanitizing the query
|
|
411
|
-
const CONTENT_TYPE_MAIN_FIELDS = ['live', 'variant', 'contentType', 'languageId'];
|
|
412
|
-
const CONTENT_API_URL = '/api/content/_search';
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* Sanitizes the query for the given content type.
|
|
416
|
-
* It replaces the fields that are not contentType fields with the correct format.
|
|
417
|
-
* Example: +field: -> +contentTypeVar.field:
|
|
418
|
-
*
|
|
419
|
-
*
|
|
420
|
-
* @export
|
|
421
|
-
* @param {string} query
|
|
422
|
-
* @param {string} contentType
|
|
423
|
-
* @return {*} {string}
|
|
424
|
-
*/
|
|
425
|
-
function sanitizeQueryForContentType(query, contentType) {
|
|
426
|
-
return query.replace(/\+([^+:]*?):/g, (original, field) => {
|
|
427
|
-
return !CONTENT_TYPE_MAIN_FIELDS.includes(field) // Fields that are not contentType fields
|
|
428
|
-
? `+${contentType}.${field}:` // Should have this format: +contentTypeVar.field:
|
|
429
|
-
: original; // Return the field if it is a contentType field
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
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;
|
|
434
|
-
/**
|
|
435
|
-
* Creates a Builder to filter and fetch content from the content API for an specific content type
|
|
436
|
-
*
|
|
437
|
-
* @export
|
|
438
|
-
* @class CollectionBuilder
|
|
439
|
-
* @template T Represents the type of the content type to fetch. Defaults to unknown
|
|
440
|
-
*/
|
|
441
|
-
class CollectionBuilder {
|
|
442
|
-
constructor(requestOptions, serverUrl, contentType) {
|
|
443
|
-
_CollectionBuilder_page.set(this, 1);
|
|
444
|
-
_CollectionBuilder_limit.set(this, 10);
|
|
445
|
-
_CollectionBuilder_depth.set(this, 0);
|
|
446
|
-
_CollectionBuilder_render.set(this, false);
|
|
447
|
-
_CollectionBuilder_sortBy.set(this, void 0);
|
|
448
|
-
_CollectionBuilder_contentType.set(this, void 0);
|
|
449
|
-
_CollectionBuilder_defaultQuery.set(this, void 0);
|
|
450
|
-
_CollectionBuilder_query.set(this, void 0);
|
|
451
|
-
_CollectionBuilder_rawQuery.set(this, void 0);
|
|
452
|
-
_CollectionBuilder_languageId.set(this, 1);
|
|
453
|
-
_CollectionBuilder_draft.set(this, false);
|
|
454
|
-
_CollectionBuilder_serverUrl.set(this, void 0);
|
|
455
|
-
_CollectionBuilder_requestOptions.set(this, void 0);
|
|
456
|
-
__classPrivateFieldSet(this, _CollectionBuilder_requestOptions, requestOptions, "f");
|
|
457
|
-
__classPrivateFieldSet(this, _CollectionBuilder_serverUrl, serverUrl, "f");
|
|
458
|
-
__classPrivateFieldSet(this, _CollectionBuilder_contentType, contentType, "f");
|
|
459
|
-
// We need to build the default query with the contentType field
|
|
460
|
-
__classPrivateFieldSet(this, _CollectionBuilder_defaultQuery, new QueryBuilder().field('contentType').equals(__classPrivateFieldGet(this, _CollectionBuilder_contentType, "f")), "f");
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* This method returns the sort query in this format: field order, field order, ...
|
|
464
|
-
*
|
|
465
|
-
* @readonly
|
|
466
|
-
* @private
|
|
467
|
-
* @memberof CollectionBuilder
|
|
468
|
-
*/
|
|
469
|
-
get sort() {
|
|
470
|
-
return __classPrivateFieldGet(this, _CollectionBuilder_sortBy, "f")?.map((sort) => `${sort.field} ${sort.order}`).join(',');
|
|
471
|
-
}
|
|
472
|
-
get offset() {
|
|
473
|
-
// This could end in an empty response
|
|
474
|
-
return __classPrivateFieldGet(this, _CollectionBuilder_limit, "f") * (__classPrivateFieldGet(this, _CollectionBuilder_page, "f") - 1);
|
|
475
|
-
}
|
|
476
|
-
get url() {
|
|
477
|
-
return `${__classPrivateFieldGet(this, _CollectionBuilder_serverUrl, "f")}${CONTENT_API_URL}`;
|
|
478
|
-
}
|
|
479
|
-
/**
|
|
480
|
-
* This method returns the current query built
|
|
481
|
-
*
|
|
482
|
-
* @readonly
|
|
483
|
-
* @private
|
|
484
|
-
* @memberof CollectionBuilder
|
|
485
|
-
*/
|
|
486
|
-
get currentQuery() {
|
|
487
|
-
return __classPrivateFieldGet(this, _CollectionBuilder_query, "f") ?? __classPrivateFieldGet(this, _CollectionBuilder_defaultQuery, "f");
|
|
488
|
-
}
|
|
489
|
-
/**
|
|
490
|
-
* Takes a language id and filters the content by that language.
|
|
491
|
-
*
|
|
492
|
-
* The language id defaults to 1
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
* @param {number | string} languageId The language id to filter the content by
|
|
496
|
-
* @return {CollectionBuilder} CollectionBuilder - A CollectionBuilder instance
|
|
497
|
-
* @memberof CollectionBuilder
|
|
498
|
-
*/
|
|
499
|
-
language(languageId) {
|
|
500
|
-
__classPrivateFieldSet(this, _CollectionBuilder_languageId, languageId, "f");
|
|
501
|
-
return this;
|
|
502
|
-
}
|
|
503
|
-
/**
|
|
504
|
-
* The retrieved content will have the rendered HTML
|
|
505
|
-
*
|
|
506
|
-
* @return {CollectionBuilder} CollectionBuilder - A CollectionBuilder instance
|
|
507
|
-
* @memberof CollectionBuilder
|
|
508
|
-
*/
|
|
509
|
-
render() {
|
|
510
|
-
__classPrivateFieldSet(this, _CollectionBuilder_render, true, "f");
|
|
511
|
-
return this;
|
|
512
|
-
}
|
|
513
|
-
/**
|
|
514
|
-
* Takes an array of constrains to sort the content by field an specific order
|
|
515
|
-
*
|
|
516
|
-
* @example
|
|
517
|
-
* ```javascript
|
|
518
|
-
* // This will sort the content by title in ascending order
|
|
519
|
-
* // and by modDate in descending order
|
|
520
|
-
* const sortBy = [{ field: 'title', order: 'asc' }, { field: 'modDate', order: 'desc' }]
|
|
521
|
-
*
|
|
522
|
-
* client.content.getCollection("Blog").sortBy(sortBy)
|
|
523
|
-
*```
|
|
524
|
-
*
|
|
525
|
-
* @param {SortBy[]} sortBy Array of constrains to sort the content by
|
|
526
|
-
* @return {CollectionBuilder} CollectionBuilder - A CollectionBuilder instance
|
|
527
|
-
* @memberof CollectionBuilder
|
|
528
|
-
*/
|
|
529
|
-
sortBy(sortBy) {
|
|
530
|
-
__classPrivateFieldSet(this, _CollectionBuilder_sortBy, sortBy, "f");
|
|
531
|
-
return this;
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Takes a number that represents the max amount of content to fetch
|
|
535
|
-
*
|
|
536
|
-
* `limit` is set to 10 by default
|
|
537
|
-
*
|
|
538
|
-
* @param {number} limit The max amount of content to fetch
|
|
539
|
-
* @return {CollectionBuilder} CollectionBuilder - A CollectionBuilder instance
|
|
540
|
-
* @memberof CollectionBuilder
|
|
541
|
-
*/
|
|
542
|
-
limit(limit) {
|
|
543
|
-
__classPrivateFieldSet(this, _CollectionBuilder_limit, limit, "f");
|
|
544
|
-
return this;
|
|
545
|
-
}
|
|
546
|
-
/**
|
|
547
|
-
* Takes a number that represents the page to fetch
|
|
548
|
-
*
|
|
549
|
-
* @param {number} page The page to fetch
|
|
550
|
-
* @return {CollectionBuilder} CollectionBuilder - A CollectionBuilder instance
|
|
551
|
-
* @memberof CollectionBuilder
|
|
552
|
-
*/
|
|
553
|
-
page(page) {
|
|
554
|
-
__classPrivateFieldSet(this, _CollectionBuilder_page, page, "f");
|
|
555
|
-
return this;
|
|
556
|
-
}
|
|
557
|
-
query(arg) {
|
|
558
|
-
if (typeof arg === 'string') {
|
|
559
|
-
__classPrivateFieldSet(this, _CollectionBuilder_rawQuery, arg, "f");
|
|
560
|
-
return this;
|
|
561
|
-
}
|
|
562
|
-
if (typeof arg !== 'function') {
|
|
563
|
-
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.`);
|
|
564
|
-
}
|
|
565
|
-
const builtQuery = arg(new QueryBuilder());
|
|
566
|
-
// This can be use in Javascript so we cannot rely on the type checking
|
|
567
|
-
if (builtQuery instanceof Equals) {
|
|
568
|
-
__classPrivateFieldSet(this, _CollectionBuilder_query, builtQuery.raw(this.currentQuery.build()), "f");
|
|
569
|
-
}
|
|
570
|
-
else {
|
|
571
|
-
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.');
|
|
572
|
-
}
|
|
573
|
-
return this;
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* The retrieved content will be draft content
|
|
577
|
-
*
|
|
578
|
-
* The default value is false to fetch content that is not on draft
|
|
579
|
-
*
|
|
580
|
-
* @return {CollectionBuilder} CollectionBuilder - A CollectionBuilder instance
|
|
581
|
-
* @memberof CollectionBuilder
|
|
582
|
-
*/
|
|
583
|
-
draft() {
|
|
584
|
-
__classPrivateFieldSet(this, _CollectionBuilder_draft, true, "f");
|
|
585
|
-
return this;
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* Takes a string that represents a variant ID of content created with the {@link https://www.dotcms.com/docs/latest/experiments-and-a-b-testing A/B Testing} feature
|
|
589
|
-
*
|
|
590
|
-
* `variantId` defaults to "DEFAULT" to fetch content that is not part of an A/B test
|
|
591
|
-
*
|
|
592
|
-
* @param {string} variantId A string that represents a variant ID
|
|
593
|
-
* @return {CollectionBuilder} CollectionBuilder - A CollectionBuilder instance
|
|
594
|
-
* @memberof CollectionBuilder
|
|
595
|
-
*/
|
|
596
|
-
variant(variantId) {
|
|
597
|
-
__classPrivateFieldSet(this, _CollectionBuilder_query, this.currentQuery.field('variant').equals(variantId), "f");
|
|
598
|
-
return this;
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Takes a number that represents the depth of the relationships of a content
|
|
602
|
-
*
|
|
603
|
-
* The `depth` is set to 0 by default and the max supported value is 3.
|
|
604
|
-
*
|
|
605
|
-
* @param {number} depth The depth of the relationships of a content
|
|
606
|
-
* @return {CollectionBuilder} CollectionBuilder - A CollectionBuilder instance
|
|
607
|
-
* @memberof CollectionBuilder
|
|
608
|
-
*/
|
|
609
|
-
depth(depth) {
|
|
610
|
-
if (depth < 0 || depth > 3) {
|
|
611
|
-
throw new Error('Depth value must be between 0 and 3');
|
|
612
|
-
}
|
|
613
|
-
__classPrivateFieldSet(this, _CollectionBuilder_depth, depth, "f");
|
|
614
|
-
return this;
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* Executes the fetch and returns a promise that resolves to the content or rejects to an error
|
|
618
|
-
*
|
|
619
|
-
* @param {OnFullfilled} [onfulfilled] A callback that is called when the fetch is successful
|
|
620
|
-
* @param {OnRejected} [onrejected] A callback that is called when the fetch fails
|
|
621
|
-
* @return {Promise<GetCollectionResponse<T> | GetCollectionError>} A promise that resolves to the content or rejects to an error
|
|
622
|
-
* @memberof CollectionBuilder
|
|
623
|
-
*/
|
|
624
|
-
then(onfulfilled, onrejected) {
|
|
625
|
-
return this.fetch().then(async (response) => {
|
|
626
|
-
const data = await response.json();
|
|
627
|
-
if (response.ok) {
|
|
628
|
-
const formattedResponse = this.formatResponse(data);
|
|
629
|
-
const finalResponse = typeof onfulfilled === 'function'
|
|
630
|
-
? onfulfilled(formattedResponse)
|
|
631
|
-
: formattedResponse;
|
|
632
|
-
return finalResponse;
|
|
633
|
-
}
|
|
634
|
-
else {
|
|
635
|
-
// Fetch does not reject on server errors, so we only have to bubble up the error as a normal fetch
|
|
636
|
-
return {
|
|
637
|
-
status: response.status,
|
|
638
|
-
...data
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
}, onrejected);
|
|
642
|
-
}
|
|
643
|
-
// Formats the response to the desired format
|
|
644
|
-
formatResponse(data) {
|
|
645
|
-
const contentlets = data.entity.jsonObjectView.contentlets;
|
|
646
|
-
const total = data.entity.resultsSize;
|
|
647
|
-
const mappedResponse = {
|
|
648
|
-
contentlets,
|
|
649
|
-
total,
|
|
650
|
-
page: __classPrivateFieldGet(this, _CollectionBuilder_page, "f"),
|
|
651
|
-
size: contentlets.length
|
|
652
|
-
};
|
|
653
|
-
return __classPrivateFieldGet(this, _CollectionBuilder_sortBy, "f")
|
|
654
|
-
? {
|
|
655
|
-
...mappedResponse,
|
|
656
|
-
sortedBy: __classPrivateFieldGet(this, _CollectionBuilder_sortBy, "f")
|
|
657
|
-
}
|
|
658
|
-
: mappedResponse;
|
|
659
|
-
}
|
|
660
|
-
// Calls the content API to fetch the content
|
|
661
|
-
fetch() {
|
|
662
|
-
const finalQuery = this.currentQuery
|
|
663
|
-
.field('languageId')
|
|
664
|
-
.equals(__classPrivateFieldGet(this, _CollectionBuilder_languageId, "f").toString())
|
|
665
|
-
.field('live')
|
|
666
|
-
.equals((!__classPrivateFieldGet(this, _CollectionBuilder_draft, "f")).toString())
|
|
667
|
-
.build();
|
|
668
|
-
const sanitizedQuery = sanitizeQueryForContentType(finalQuery, __classPrivateFieldGet(this, _CollectionBuilder_contentType, "f"));
|
|
669
|
-
const query = __classPrivateFieldGet(this, _CollectionBuilder_rawQuery, "f") ? `${sanitizedQuery} ${__classPrivateFieldGet(this, _CollectionBuilder_rawQuery, "f")}` : sanitizedQuery;
|
|
670
|
-
return fetch(this.url, {
|
|
671
|
-
...__classPrivateFieldGet(this, _CollectionBuilder_requestOptions, "f"),
|
|
672
|
-
method: 'POST',
|
|
673
|
-
headers: {
|
|
674
|
-
...__classPrivateFieldGet(this, _CollectionBuilder_requestOptions, "f").headers,
|
|
675
|
-
'Content-Type': 'application/json'
|
|
676
|
-
},
|
|
677
|
-
body: JSON.stringify({
|
|
678
|
-
query,
|
|
679
|
-
render: __classPrivateFieldGet(this, _CollectionBuilder_render, "f"),
|
|
680
|
-
sort: this.sort,
|
|
681
|
-
limit: __classPrivateFieldGet(this, _CollectionBuilder_limit, "f"),
|
|
682
|
-
offset: this.offset,
|
|
683
|
-
depth: __classPrivateFieldGet(this, _CollectionBuilder_depth, "f")
|
|
684
|
-
//userId: This exist but we currently don't use it
|
|
685
|
-
//allCategoriesInfo: This exist but we currently don't use it
|
|
686
|
-
})
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
_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();
|
|
691
|
-
|
|
692
|
-
var _Content_requestOptions, _Content_serverUrl;
|
|
693
|
-
/**
|
|
694
|
-
* Content classs exposes the content api methods
|
|
695
|
-
*
|
|
696
|
-
* @export
|
|
697
|
-
* @class Content
|
|
698
|
-
*/
|
|
699
|
-
class Content {
|
|
700
|
-
constructor(requestOptions, serverUrl) {
|
|
701
|
-
_Content_requestOptions.set(this, void 0);
|
|
702
|
-
_Content_serverUrl.set(this, void 0);
|
|
703
|
-
__classPrivateFieldSet(this, _Content_requestOptions, requestOptions, "f");
|
|
704
|
-
__classPrivateFieldSet(this, _Content_serverUrl, serverUrl, "f");
|
|
705
|
-
}
|
|
706
|
-
/**
|
|
707
|
-
* Takes a content type and returns a builder to filter and fetch the collection
|
|
708
|
-
*
|
|
709
|
-
* @example
|
|
710
|
-
* ```javascript
|
|
711
|
-
* // Using await and async
|
|
712
|
-
* const collectionResponse = await client.content
|
|
713
|
-
* .getCollection('Blog')
|
|
714
|
-
* .limit(10)
|
|
715
|
-
* .page(2)
|
|
716
|
-
* .sortBy([{ field: 'title', order: 'asc' }])
|
|
717
|
-
* .query((queryBuilder) => queryBuilder.field('author').equals('John Doe'))
|
|
718
|
-
* .depth(1);
|
|
719
|
-
* ```
|
|
720
|
-
* @example
|
|
721
|
-
* ```javascript
|
|
722
|
-
* // Using then and catch
|
|
723
|
-
* client.content
|
|
724
|
-
* .getCollection('Blog')
|
|
725
|
-
* .limit(10)
|
|
726
|
-
* .page(2)
|
|
727
|
-
* .sortBy([{ field: 'title', order: 'asc' }])
|
|
728
|
-
* .query((queryBuilder) => queryBuilder.field('author').equals('John Doe'))
|
|
729
|
-
* .depth(1)
|
|
730
|
-
* .then((response) => {
|
|
731
|
-
* console.log(response.contentlets);
|
|
732
|
-
* })
|
|
733
|
-
* .catch((error) => {
|
|
734
|
-
* console.error(error);
|
|
735
|
-
* });
|
|
736
|
-
* ```
|
|
737
|
-
* @example
|
|
738
|
-
* ```typescript
|
|
739
|
-
* // Using an specific type for your content
|
|
740
|
-
*
|
|
741
|
-
* type Blog = {
|
|
742
|
-
* summary: string;
|
|
743
|
-
* author: string;
|
|
744
|
-
* title: string;
|
|
745
|
-
* };
|
|
746
|
-
*
|
|
747
|
-
* client.content
|
|
748
|
-
* .getCollection<Blog>('Blog')
|
|
749
|
-
* .limit(10)
|
|
750
|
-
* .page(2)
|
|
751
|
-
* .sortBy([{ field: 'title', order: 'asc' }])
|
|
752
|
-
* .query((queryBuilder) => queryBuilder.field('author').equals('John Doe'))
|
|
753
|
-
* .depth(1)
|
|
754
|
-
* .then((response) => {
|
|
755
|
-
* response.contentlets.forEach((blog) => {
|
|
756
|
-
* console.log(blog.title);
|
|
757
|
-
* console.log(blog.author);
|
|
758
|
-
* console.log(blog.summary);
|
|
759
|
-
* });
|
|
760
|
-
* })
|
|
761
|
-
* .catch((error) => {
|
|
762
|
-
* console.error(error);
|
|
763
|
-
* });
|
|
764
|
-
* ```
|
|
765
|
-
*
|
|
766
|
-
* @param {string} contentType The content type to get the collection
|
|
767
|
-
* @return {CollectionBuilder} CollectionBuilder to filter and fetch the collection
|
|
768
|
-
* @template T Represents the type of the content type to fetch. Defaults to unknown
|
|
769
|
-
* @memberof Content
|
|
770
|
-
*/
|
|
771
|
-
getCollection(contentType) {
|
|
772
|
-
return new CollectionBuilder(__classPrivateFieldGet(this, _Content_requestOptions, "f"), __classPrivateFieldGet(this, _Content_serverUrl, "f"), contentType);
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
_Content_requestOptions = new WeakMap(), _Content_serverUrl = new WeakMap();
|
|
776
|
-
|
|
777
|
-
const ErrorMessages = {
|
|
778
|
-
401: 'Unauthorized. Check the token and try again.',
|
|
779
|
-
403: 'Forbidden. Check the permissions and try again.',
|
|
780
|
-
404: 'Not Found. Check the URL and try again.',
|
|
781
|
-
500: 'Internal Server Error. Try again later.',
|
|
782
|
-
502: 'Bad Gateway. Try again later.',
|
|
783
|
-
503: 'Service Unavailable. Try again later.'
|
|
784
|
-
};
|
|
785
|
-
|
|
786
|
-
/**
|
|
787
|
-
* Actions send to the dotcms editor
|
|
788
|
-
*
|
|
789
|
-
* @export
|
|
790
|
-
* @enum {number}
|
|
791
|
-
*/
|
|
792
|
-
exports.CUSTOMER_ACTIONS = void 0;
|
|
793
|
-
(function (CUSTOMER_ACTIONS) {
|
|
794
|
-
/**
|
|
795
|
-
* Tell the dotcms editor that page change
|
|
796
|
-
*/
|
|
797
|
-
CUSTOMER_ACTIONS["NAVIGATION_UPDATE"] = "set-url";
|
|
798
|
-
/**
|
|
799
|
-
* Send the element position of the rows, columnsm containers and contentlets
|
|
800
|
-
*/
|
|
801
|
-
CUSTOMER_ACTIONS["SET_BOUNDS"] = "set-bounds";
|
|
802
|
-
/**
|
|
803
|
-
* Send the information of the hovered contentlet
|
|
804
|
-
*/
|
|
805
|
-
CUSTOMER_ACTIONS["SET_CONTENTLET"] = "set-contentlet";
|
|
806
|
-
/**
|
|
807
|
-
* Tell the editor that the page is being scrolled
|
|
808
|
-
*/
|
|
809
|
-
CUSTOMER_ACTIONS["IFRAME_SCROLL"] = "scroll";
|
|
810
|
-
/**
|
|
811
|
-
* Tell the editor that the page has stopped scrolling
|
|
812
|
-
*/
|
|
813
|
-
CUSTOMER_ACTIONS["IFRAME_SCROLL_END"] = "scroll-end";
|
|
814
|
-
/**
|
|
815
|
-
* Ping the editor to see if the page is inside the editor
|
|
816
|
-
*/
|
|
817
|
-
CUSTOMER_ACTIONS["PING_EDITOR"] = "ping-editor";
|
|
818
|
-
/**
|
|
819
|
-
* Tell the editor to init the inline editing editor.
|
|
820
|
-
*/
|
|
821
|
-
CUSTOMER_ACTIONS["INIT_INLINE_EDITING"] = "init-inline-editing";
|
|
822
|
-
/**
|
|
823
|
-
* Tell the editor to open the Copy-contentlet dialog
|
|
824
|
-
* To copy a content and then edit it inline.
|
|
825
|
-
*/
|
|
826
|
-
CUSTOMER_ACTIONS["COPY_CONTENTLET_INLINE_EDITING"] = "copy-contentlet-inline-editing";
|
|
827
|
-
/**
|
|
828
|
-
* Tell the editor to save inline edited contentlet
|
|
829
|
-
*/
|
|
830
|
-
CUSTOMER_ACTIONS["UPDATE_CONTENTLET_INLINE_EDITING"] = "update-contentlet-inline-editing";
|
|
831
|
-
/**
|
|
832
|
-
* Tell the editor to trigger a menu reorder
|
|
833
|
-
*/
|
|
834
|
-
CUSTOMER_ACTIONS["REORDER_MENU"] = "reorder-menu";
|
|
835
|
-
/**
|
|
836
|
-
* Tell the editor to send the page info to iframe
|
|
837
|
-
*/
|
|
838
|
-
CUSTOMER_ACTIONS["GET_PAGE_DATA"] = "get-page-data";
|
|
839
|
-
/**
|
|
840
|
-
* Tell the editor an user send a graphql query
|
|
841
|
-
*/
|
|
842
|
-
CUSTOMER_ACTIONS["CLIENT_READY"] = "client-ready";
|
|
843
|
-
/**
|
|
844
|
-
* Tell the editor to do nothing
|
|
845
|
-
*/
|
|
846
|
-
CUSTOMER_ACTIONS["NOOP"] = "noop";
|
|
847
|
-
})(exports.CUSTOMER_ACTIONS || (exports.CUSTOMER_ACTIONS = {}));
|
|
848
|
-
/**
|
|
849
|
-
* Post message to dotcms page editor
|
|
850
|
-
*
|
|
851
|
-
* @export
|
|
852
|
-
* @template T
|
|
853
|
-
* @param {PostMessageProps<T>} message
|
|
854
|
-
*/
|
|
855
|
-
function postMessageToEditor(message) {
|
|
856
|
-
window.parent.postMessage(message, '*');
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
/**
|
|
860
|
-
* Actions received from the dotcms editor
|
|
861
|
-
*
|
|
862
|
-
* @export
|
|
863
|
-
* @enum {number}
|
|
864
|
-
*/
|
|
865
|
-
var NOTIFY_CUSTOMER;
|
|
866
|
-
(function (NOTIFY_CUSTOMER) {
|
|
867
|
-
/**
|
|
868
|
-
* Request to page to reload
|
|
869
|
-
*/
|
|
870
|
-
NOTIFY_CUSTOMER["EMA_RELOAD_PAGE"] = "ema-reload-page";
|
|
871
|
-
/**
|
|
872
|
-
* Request the bounds for the elements
|
|
873
|
-
*/
|
|
874
|
-
NOTIFY_CUSTOMER["EMA_REQUEST_BOUNDS"] = "ema-request-bounds";
|
|
875
|
-
/**
|
|
876
|
-
* Received pong from the editor
|
|
877
|
-
*/
|
|
878
|
-
NOTIFY_CUSTOMER["EMA_EDITOR_PONG"] = "ema-editor-pong";
|
|
879
|
-
/**
|
|
880
|
-
* Received scroll event trigger from the editor
|
|
881
|
-
*/
|
|
882
|
-
NOTIFY_CUSTOMER["EMA_SCROLL_INSIDE_IFRAME"] = "scroll-inside-iframe";
|
|
883
|
-
})(NOTIFY_CUSTOMER || (NOTIFY_CUSTOMER = {}));
|
|
884
|
-
|
|
885
|
-
/**
|
|
886
|
-
* Calculates the bounding information for each page element within the given containers.
|
|
887
|
-
*
|
|
888
|
-
* @export
|
|
889
|
-
* @param {HTMLDivElement[]} containers
|
|
890
|
-
* @return {*} An array of objects containing the bounding information for each page element.
|
|
891
|
-
*/
|
|
892
|
-
function getPageElementBound(containers) {
|
|
893
|
-
return containers.map((container) => {
|
|
894
|
-
const containerRect = container.getBoundingClientRect();
|
|
895
|
-
const contentlets = Array.from(container.querySelectorAll('[data-dot-object="contentlet"]'));
|
|
896
|
-
return {
|
|
897
|
-
x: containerRect.x,
|
|
898
|
-
y: containerRect.y,
|
|
899
|
-
width: containerRect.width,
|
|
900
|
-
height: containerRect.height,
|
|
901
|
-
payload: JSON.stringify({
|
|
902
|
-
container: getContainerData(container)
|
|
903
|
-
}),
|
|
904
|
-
contentlets: getContentletsBound(containerRect, contentlets)
|
|
905
|
-
};
|
|
906
|
-
});
|
|
907
|
-
}
|
|
908
|
-
/**
|
|
909
|
-
* An array of objects containing the bounding information for each contentlet inside a container.
|
|
910
|
-
*
|
|
911
|
-
* @export
|
|
912
|
-
* @param {DOMRect} containerRect
|
|
913
|
-
* @param {HTMLDivElement[]} contentlets
|
|
914
|
-
* @return {*}
|
|
915
|
-
*/
|
|
916
|
-
function getContentletsBound(containerRect, contentlets) {
|
|
917
|
-
return contentlets.map((contentlet) => {
|
|
918
|
-
const contentletRect = contentlet.getBoundingClientRect();
|
|
919
|
-
return {
|
|
920
|
-
x: 0,
|
|
921
|
-
y: contentletRect.y - containerRect.y,
|
|
922
|
-
width: contentletRect.width,
|
|
923
|
-
height: contentletRect.height,
|
|
924
|
-
payload: JSON.stringify({
|
|
925
|
-
container: contentlet.dataset?.['dotContainer']
|
|
926
|
-
? JSON.parse(contentlet.dataset?.['dotContainer'])
|
|
927
|
-
: getClosestContainerData(contentlet),
|
|
928
|
-
contentlet: {
|
|
929
|
-
identifier: contentlet.dataset?.['dotIdentifier'],
|
|
930
|
-
title: contentlet.dataset?.['dotTitle'],
|
|
931
|
-
inode: contentlet.dataset?.['dotInode'],
|
|
932
|
-
contentType: contentlet.dataset?.['dotType']
|
|
933
|
-
}
|
|
934
|
-
})
|
|
935
|
-
};
|
|
936
|
-
});
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Get container data from VTLS.
|
|
940
|
-
*
|
|
941
|
-
* @export
|
|
942
|
-
* @param {HTMLElement} container
|
|
943
|
-
* @return {*}
|
|
944
|
-
*/
|
|
945
|
-
function getContainerData(container) {
|
|
946
|
-
return {
|
|
947
|
-
acceptTypes: container.dataset?.['dotAcceptTypes'] || '',
|
|
948
|
-
identifier: container.dataset?.['dotIdentifier'] || '',
|
|
949
|
-
maxContentlets: container.dataset?.['maxContentlets'] || '',
|
|
950
|
-
uuid: container.dataset?.['dotUuid'] || ''
|
|
951
|
-
};
|
|
952
|
-
}
|
|
953
|
-
/**
|
|
954
|
-
* Get the closest container data from the contentlet.
|
|
955
|
-
*
|
|
956
|
-
* @export
|
|
957
|
-
* @param {Element} element
|
|
958
|
-
* @return {*}
|
|
959
|
-
*/
|
|
960
|
-
function getClosestContainerData(element) {
|
|
961
|
-
// Find the closest ancestor element with data-dot-object="container" attribute
|
|
962
|
-
const container = element.closest('[data-dot-object="container"]');
|
|
963
|
-
// If a container element is found
|
|
964
|
-
if (container) {
|
|
965
|
-
// Return the dataset of the container element
|
|
966
|
-
return getContainerData(container);
|
|
967
|
-
}
|
|
968
|
-
else {
|
|
969
|
-
// If no container element is found, return null
|
|
970
|
-
console.warn('No container found for the contentlet');
|
|
971
|
-
return null;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
/**
|
|
975
|
-
* Find the closest contentlet element based on HTMLElement.
|
|
976
|
-
*
|
|
977
|
-
* @export
|
|
978
|
-
* @param {(HTMLElement | null)} element
|
|
979
|
-
* @return {*}
|
|
980
|
-
*/
|
|
981
|
-
function findDotElement(element) {
|
|
982
|
-
if (!element)
|
|
983
|
-
return null;
|
|
984
|
-
if (element?.dataset?.['dotObject'] === 'contentlet' ||
|
|
985
|
-
(element?.dataset?.['dotObject'] === 'container' && element.children.length === 0)) {
|
|
986
|
-
return element;
|
|
987
|
-
}
|
|
988
|
-
return findDotElement(element?.['parentElement']);
|
|
989
|
-
}
|
|
990
|
-
function findVTLData(target) {
|
|
991
|
-
const vltElements = target.querySelectorAll('[data-dot-object="vtl-file"]');
|
|
992
|
-
if (!vltElements.length) {
|
|
993
|
-
return null;
|
|
994
|
-
}
|
|
995
|
-
return Array.from(vltElements).map((vltElement) => {
|
|
996
|
-
return {
|
|
997
|
-
inode: vltElement.dataset?.['dotInode'],
|
|
998
|
-
name: vltElement.dataset?.['dotUrl']
|
|
999
|
-
};
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
|
-
function scrollIsInBottom() {
|
|
1003
|
-
const documentHeight = document.documentElement.scrollHeight;
|
|
1004
|
-
const viewportHeight = window.innerHeight;
|
|
1005
|
-
const scrollY = window.scrollY;
|
|
1006
|
-
return scrollY + viewportHeight >= documentHeight;
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
/**
|
|
1010
|
-
* Represents an array of DotCMSPageEditorSubscription objects.
|
|
1011
|
-
* Used to store the subscriptions for the editor and unsubscribe later.
|
|
1012
|
-
*/
|
|
1013
|
-
const subscriptions = [];
|
|
1014
|
-
/**
|
|
1015
|
-
* Sets the bounds of the containers in the editor.
|
|
1016
|
-
* Retrieves the containers from the DOM and sends their position data to the editor.
|
|
1017
|
-
* @private
|
|
1018
|
-
* @memberof DotCMSPageEditor
|
|
1019
|
-
*/
|
|
1020
|
-
function setBounds() {
|
|
1021
|
-
const containers = Array.from(document.querySelectorAll('[data-dot-object="container"]'));
|
|
1022
|
-
const positionData = getPageElementBound(containers);
|
|
1023
|
-
postMessageToEditor({
|
|
1024
|
-
action: exports.CUSTOMER_ACTIONS.SET_BOUNDS,
|
|
1025
|
-
payload: positionData
|
|
1026
|
-
});
|
|
1027
|
-
}
|
|
1028
|
-
/**
|
|
1029
|
-
* Listens for editor messages and performs corresding actions based on the received message.
|
|
1030
|
-
*
|
|
1031
|
-
* @private
|
|
1032
|
-
* @memberof DotCMSPageEditor
|
|
1033
|
-
*/
|
|
1034
|
-
function listenEditorMessages() {
|
|
1035
|
-
const messageCallback = (event) => {
|
|
1036
|
-
switch (event.data) {
|
|
1037
|
-
case NOTIFY_CUSTOMER.EMA_REQUEST_BOUNDS: {
|
|
1038
|
-
setBounds();
|
|
1039
|
-
break;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
if (event.data.name === NOTIFY_CUSTOMER.EMA_SCROLL_INSIDE_IFRAME) {
|
|
1043
|
-
const direction = event.data.direction;
|
|
1044
|
-
if ((window.scrollY === 0 && direction === 'up') ||
|
|
1045
|
-
(scrollIsInBottom() && direction === 'down')) {
|
|
1046
|
-
/**
|
|
1047
|
-
* If the iframe scroll is in the top of bottom, we dont send anything.
|
|
1048
|
-
* This to avoid the lost of scrollend event
|
|
1049
|
-
**/
|
|
1050
|
-
return;
|
|
1051
|
-
}
|
|
1052
|
-
const scrollY = direction === 'up' ? -120 : 120;
|
|
1053
|
-
window.scrollBy({ left: 0, top: scrollY, behavior: 'smooth' });
|
|
1054
|
-
}
|
|
1055
|
-
};
|
|
1056
|
-
window.addEventListener('message', messageCallback);
|
|
1057
|
-
subscriptions.push({
|
|
1058
|
-
type: 'listener',
|
|
1059
|
-
event: 'message',
|
|
1060
|
-
callback: messageCallback
|
|
1061
|
-
});
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* Listens for pointer move events and extracts information about the hovered contentlet.
|
|
1065
|
-
*
|
|
1066
|
-
* @private
|
|
1067
|
-
* @memberof DotCMSPageEditor
|
|
1068
|
-
*/
|
|
1069
|
-
function listenHoveredContentlet() {
|
|
1070
|
-
const pointerMoveCallback = (event) => {
|
|
1071
|
-
const foundElement = findDotElement(event.target);
|
|
1072
|
-
if (!foundElement)
|
|
1073
|
-
return;
|
|
1074
|
-
const { x, y, width, height } = foundElement.getBoundingClientRect();
|
|
1075
|
-
const isContainer = foundElement.dataset?.['dotObject'] === 'container';
|
|
1076
|
-
const contentletForEmptyContainer = {
|
|
1077
|
-
identifier: 'TEMP_EMPTY_CONTENTLET',
|
|
1078
|
-
title: 'TEMP_EMPTY_CONTENTLET',
|
|
1079
|
-
contentType: 'TEMP_EMPTY_CONTENTLET_TYPE',
|
|
1080
|
-
inode: 'TEMPY_EMPTY_CONTENTLET_INODE',
|
|
1081
|
-
widgetTitle: 'TEMP_EMPTY_CONTENTLET',
|
|
1082
|
-
baseType: 'TEMP_EMPTY_CONTENTLET',
|
|
1083
|
-
onNumberOfPages: 1
|
|
1084
|
-
};
|
|
1085
|
-
const contentlet = {
|
|
1086
|
-
identifier: foundElement.dataset?.['dotIdentifier'],
|
|
1087
|
-
title: foundElement.dataset?.['dotTitle'],
|
|
1088
|
-
inode: foundElement.dataset?.['dotInode'],
|
|
1089
|
-
contentType: foundElement.dataset?.['dotType'],
|
|
1090
|
-
baseType: foundElement.dataset?.['dotBasetype'],
|
|
1091
|
-
widgetTitle: foundElement.dataset?.['dotWidgetTitle'],
|
|
1092
|
-
onNumberOfPages: foundElement.dataset?.['dotOnNumberOfPages']
|
|
1093
|
-
};
|
|
1094
|
-
const vtlFiles = findVTLData(foundElement);
|
|
1095
|
-
const contentletPayload = {
|
|
1096
|
-
container:
|
|
1097
|
-
// Here extract dot-container from contentlet if is Headless
|
|
1098
|
-
// or search in parent container if is VTL
|
|
1099
|
-
foundElement.dataset?.['dotContainer']
|
|
1100
|
-
? JSON.parse(foundElement.dataset?.['dotContainer'])
|
|
1101
|
-
: getClosestContainerData(foundElement),
|
|
1102
|
-
contentlet: isContainer ? contentletForEmptyContainer : contentlet,
|
|
1103
|
-
vtlFiles
|
|
1104
|
-
};
|
|
1105
|
-
postMessageToEditor({
|
|
1106
|
-
action: exports.CUSTOMER_ACTIONS.SET_CONTENTLET,
|
|
1107
|
-
payload: {
|
|
1108
|
-
x,
|
|
1109
|
-
y,
|
|
1110
|
-
width,
|
|
1111
|
-
height,
|
|
1112
|
-
payload: contentletPayload
|
|
1113
|
-
}
|
|
1114
|
-
});
|
|
1115
|
-
};
|
|
1116
|
-
document.addEventListener('pointermove', pointerMoveCallback);
|
|
1117
|
-
subscriptions.push({
|
|
1118
|
-
type: 'listener',
|
|
1119
|
-
event: 'pointermove',
|
|
1120
|
-
callback: pointerMoveCallback
|
|
1121
|
-
});
|
|
1122
|
-
}
|
|
1123
|
-
/**
|
|
1124
|
-
* Attaches a scroll event listener to the window
|
|
1125
|
-
* and sends a message to the editor when the window is scrolled.
|
|
1126
|
-
*
|
|
1127
|
-
* @private
|
|
1128
|
-
* @memberof DotCMSPageEditor
|
|
1129
|
-
*/
|
|
1130
|
-
function scrollHandler() {
|
|
1131
|
-
const scrollCallback = () => {
|
|
1132
|
-
postMessageToEditor({
|
|
1133
|
-
action: exports.CUSTOMER_ACTIONS.IFRAME_SCROLL
|
|
1134
|
-
});
|
|
1135
|
-
window.lastScrollYPosition = window.scrollY;
|
|
1136
|
-
};
|
|
1137
|
-
const scrollEndCallback = () => {
|
|
1138
|
-
postMessageToEditor({
|
|
1139
|
-
action: exports.CUSTOMER_ACTIONS.IFRAME_SCROLL_END
|
|
1140
|
-
});
|
|
1141
|
-
};
|
|
1142
|
-
window.addEventListener('scroll', scrollCallback);
|
|
1143
|
-
window.addEventListener('scrollend', scrollEndCallback);
|
|
1144
|
-
subscriptions.push({
|
|
1145
|
-
type: 'listener',
|
|
1146
|
-
event: 'scroll',
|
|
1147
|
-
callback: scrollEndCallback
|
|
1148
|
-
});
|
|
1149
|
-
subscriptions.push({
|
|
1150
|
-
type: 'listener',
|
|
1151
|
-
event: 'scroll',
|
|
1152
|
-
callback: scrollCallback
|
|
1153
|
-
});
|
|
1154
|
-
}
|
|
1155
|
-
/**
|
|
1156
|
-
* Sends a message to the editor to get the page data.
|
|
1157
|
-
* @param {string} pathname - The pathname of the page.
|
|
1158
|
-
* @private
|
|
1159
|
-
* @memberof DotCMSPageEditor
|
|
1160
|
-
*/
|
|
1161
|
-
function fetchPageDataFromInsideUVE(pathname) {
|
|
1162
|
-
postMessageToEditor({
|
|
1163
|
-
action: exports.CUSTOMER_ACTIONS.GET_PAGE_DATA,
|
|
1164
|
-
payload: {
|
|
1165
|
-
pathname
|
|
1166
|
-
}
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
/**
|
|
1171
|
-
*
|
|
1172
|
-
* Updates the navigation in the editor.
|
|
1173
|
-
* @param {string} pathname - The pathname to update the navigation with.
|
|
1174
|
-
* @memberof DotCMSPageEditor
|
|
1175
|
-
*/
|
|
1176
|
-
function updateNavigation(pathname) {
|
|
1177
|
-
postMessageToEditor({
|
|
1178
|
-
action: exports.CUSTOMER_ACTIONS.NAVIGATION_UPDATE,
|
|
1179
|
-
payload: {
|
|
1180
|
-
url: pathname === '/' ? 'index' : pathname?.replace('/', '')
|
|
1181
|
-
}
|
|
1182
|
-
});
|
|
1183
|
-
}
|
|
1184
|
-
/**
|
|
1185
|
-
* Checks if the code is running inside an editor.
|
|
1186
|
-
* @returns {boolean} Returns true if the code is running inside an editor, otherwise false.
|
|
1187
|
-
*/
|
|
1188
|
-
function isInsideEditor() {
|
|
1189
|
-
if (typeof window === 'undefined') {
|
|
1190
|
-
return false;
|
|
1191
|
-
}
|
|
1192
|
-
return window.parent !== window;
|
|
1193
|
-
}
|
|
1194
|
-
/**
|
|
1195
|
-
* Initializes the DotCMS page editor.
|
|
1196
|
-
*
|
|
1197
|
-
* @param conf - Optional configuration for the editor.
|
|
1198
|
-
*/
|
|
1199
|
-
function initEditor(config) {
|
|
1200
|
-
fetchPageDataFromInsideUVE(config.pathname);
|
|
1201
|
-
listenEditorMessages();
|
|
1202
|
-
listenHoveredContentlet();
|
|
1203
|
-
scrollHandler();
|
|
1204
|
-
}
|
|
1205
|
-
/**
|
|
1206
|
-
* Destroys the editor by removing event listeners and disconnecting observers.
|
|
1207
|
-
*/
|
|
1208
|
-
function destroyEditor() {
|
|
1209
|
-
subscriptions.forEach((subscription) => {
|
|
1210
|
-
if (subscription.type === 'listener') {
|
|
1211
|
-
window.removeEventListener(subscription.event, subscription.callback);
|
|
1212
|
-
}
|
|
1213
|
-
if (subscription.type === 'observer') {
|
|
1214
|
-
subscription.observer.disconnect();
|
|
1215
|
-
}
|
|
1216
|
-
});
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
var _DotCmsClient_config, _DotCmsClient_requestOptions, _DotCmsClient_listeners;
|
|
1220
|
-
function getHostURL(url) {
|
|
1221
|
-
try {
|
|
1222
|
-
return new URL(url);
|
|
1223
|
-
}
|
|
1224
|
-
catch (error) {
|
|
1225
|
-
return undefined;
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
/**
|
|
1229
|
-
* `DotCmsClient` is a TypeScript class that provides methods to interact with the DotCMS REST API.
|
|
1230
|
-
* It requires a configuration object on instantiation, which includes the DotCMS URL, site ID, and authentication token.
|
|
1231
|
-
*
|
|
1232
|
-
* @class DotCmsClient
|
|
1233
|
-
*
|
|
1234
|
-
* @property {ClientConfig} config - The configuration object for the DotCMS client.
|
|
1235
|
-
*
|
|
1236
|
-
* @method constructor(config: ClientConfig) - Constructs a new instance of the DotCmsClient class.
|
|
1237
|
-
*
|
|
1238
|
-
* @method page.get(options: PageApiOptions): Promise<unknown> - Retrieves all the elements of any Page in your dotCMS system in JSON format.
|
|
1239
|
-
*
|
|
1240
|
-
* @method nav.get(options: NavApiOptions = { depth: 0, path: '/', languageId: 1 }): Promise<unknown> - Retrieves information about the dotCMS file and folder tree.
|
|
1241
|
-
*
|
|
1242
|
-
*/
|
|
1243
|
-
class DotCmsClient {
|
|
1244
|
-
constructor(config = { dotcmsUrl: '', authToken: '', requestOptions: {}, siteId: '' }) {
|
|
1245
|
-
_DotCmsClient_config.set(this, void 0);
|
|
1246
|
-
_DotCmsClient_requestOptions.set(this, void 0);
|
|
1247
|
-
_DotCmsClient_listeners.set(this, []);
|
|
1248
|
-
this.page = {
|
|
1249
|
-
/**
|
|
1250
|
-
* `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.
|
|
1251
|
-
* It takes a `PageApiOptions` object as a parameter and returns a Promise that resolves to the response from the DotCMS API.
|
|
1252
|
-
*
|
|
1253
|
-
* The Page API enables you to retrieve all the elements of any Page in your dotCMS system.
|
|
1254
|
-
* The elements may be retrieved in JSON format.
|
|
1255
|
-
*
|
|
1256
|
-
* @link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas
|
|
1257
|
-
* @async
|
|
1258
|
-
* @param {PageApiOptions} options - The options for the Page API call.
|
|
1259
|
-
* @returns {Promise<unknown>} - A Promise that resolves to the response from the DotCMS API.
|
|
1260
|
-
* @throws {Error} - Throws an error if the options are not valid.
|
|
1261
|
-
*/
|
|
1262
|
-
get: async (options) => {
|
|
1263
|
-
this.validatePageOptions(options);
|
|
1264
|
-
const queryParamsObj = {};
|
|
1265
|
-
for (const [key, value] of Object.entries(options)) {
|
|
1266
|
-
if (value === undefined || key === 'path' || key === 'siteId')
|
|
1267
|
-
continue;
|
|
1268
|
-
if (key === 'personaId') {
|
|
1269
|
-
queryParamsObj['com.dotmarketing.persona.id'] = String(value);
|
|
1270
|
-
}
|
|
1271
|
-
else if (key === 'mode' && value) {
|
|
1272
|
-
queryParamsObj['mode'] = String(value);
|
|
1273
|
-
}
|
|
1274
|
-
else {
|
|
1275
|
-
queryParamsObj[key] = String(value);
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
const queryHostId = options.siteId ?? __classPrivateFieldGet(this, _DotCmsClient_config, "f").siteId ?? '';
|
|
1279
|
-
if (queryHostId) {
|
|
1280
|
-
queryParamsObj['host_id'] = queryHostId;
|
|
1281
|
-
}
|
|
1282
|
-
const queryParams = new URLSearchParams(queryParamsObj).toString();
|
|
1283
|
-
const formattedPath = options.path.startsWith('/') ? options.path : `/${options.path}`;
|
|
1284
|
-
const url = `${__classPrivateFieldGet(this, _DotCmsClient_config, "f").dotcmsUrl}/api/v1/page/json${formattedPath}${queryParams ? `?${queryParams}` : ''}`;
|
|
1285
|
-
const response = await fetch(url, __classPrivateFieldGet(this, _DotCmsClient_requestOptions, "f"));
|
|
1286
|
-
if (!response.ok) {
|
|
1287
|
-
const error = {
|
|
1288
|
-
status: response.status,
|
|
1289
|
-
message: ErrorMessages[response.status] || response.statusText
|
|
1290
|
-
};
|
|
1291
|
-
console.error(error);
|
|
1292
|
-
throw error;
|
|
1293
|
-
}
|
|
1294
|
-
return response.json().then((data) => data.entity);
|
|
1295
|
-
}
|
|
1296
|
-
};
|
|
1297
|
-
this.editor = {
|
|
1298
|
-
/**
|
|
1299
|
-
* `editor.on` is an asynchronous method of the `DotCmsClient` class that allows you to react to actions issued by the UVE.
|
|
1300
|
-
*
|
|
1301
|
-
* NOTE: This is being used by the development team - This logic is probably varied or moved to another function/object.
|
|
1302
|
-
* @param action - The name of the name emitted by UVE
|
|
1303
|
-
* @param callbackFn - The function to execute when the UVE emits the action
|
|
1304
|
-
*/
|
|
1305
|
-
on: (action, callbackFn) => {
|
|
1306
|
-
if (!isInsideEditor()) {
|
|
1307
|
-
return;
|
|
1308
|
-
}
|
|
1309
|
-
if (action === 'changes') {
|
|
1310
|
-
const messageCallback = (event) => {
|
|
1311
|
-
if (event.data.name === 'SET_PAGE_DATA') {
|
|
1312
|
-
callbackFn(event.data.payload);
|
|
1313
|
-
}
|
|
1314
|
-
};
|
|
1315
|
-
window.addEventListener('message', messageCallback);
|
|
1316
|
-
__classPrivateFieldGet(this, _DotCmsClient_listeners, "f").push({ event: 'message', callback: messageCallback, action });
|
|
1317
|
-
}
|
|
1318
|
-
},
|
|
1319
|
-
/**
|
|
1320
|
-
* `editor.off` is an synchronous method of the `DotCmsClient` class that allows you to stop listening and reacting to an action issued by UVE.
|
|
1321
|
-
*
|
|
1322
|
-
* NOTE: This is being used by the development team - This logic is probably varied or moved to another function/object.
|
|
1323
|
-
* @param action
|
|
1324
|
-
*/
|
|
1325
|
-
off: (action) => {
|
|
1326
|
-
const listenerIndex = __classPrivateFieldGet(this, _DotCmsClient_listeners, "f").findIndex((listener) => listener.action === action);
|
|
1327
|
-
if (listenerIndex !== -1) {
|
|
1328
|
-
const listener = __classPrivateFieldGet(this, _DotCmsClient_listeners, "f")[listenerIndex];
|
|
1329
|
-
window.removeEventListener(listener.event, listener.callback);
|
|
1330
|
-
__classPrivateFieldGet(this, _DotCmsClient_listeners, "f").splice(listenerIndex, 1);
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
};
|
|
1334
|
-
this.nav = {
|
|
1335
|
-
/**
|
|
1336
|
-
* `nav.get` is an asynchronous method of the `DotCmsClient` class that retrieves information about the dotCMS file and folder tree.
|
|
1337
|
-
* It takes a `NavApiOptions` object as a parameter (with default values) and returns a Promise that resolves to the response from the DotCMS API.
|
|
1338
|
-
*
|
|
1339
|
-
* The navigation REST API enables you to retrieve information about the dotCMS file and folder tree through REST API calls.
|
|
1340
|
-
* @link https://www.dotcms.com/docs/latest/navigation-rest-api
|
|
1341
|
-
* @async
|
|
1342
|
-
* @param {NavApiOptions} options - The options for the Nav API call. Defaults to `{ depth: 0, path: '/', languageId: 1 }`.
|
|
1343
|
-
* @returns {Promise<unknown>} - A Promise that resolves to the response from the DotCMS API.
|
|
1344
|
-
* @throws {Error} - Throws an error if the options are not valid.
|
|
1345
|
-
*/
|
|
1346
|
-
get: async (options = { depth: 0, path: '/', languageId: 1 }) => {
|
|
1347
|
-
this.validateNavOptions(options);
|
|
1348
|
-
// Extract the 'path' from the options and prepare the rest as query parameters
|
|
1349
|
-
const { path, ...queryParamsOptions } = options;
|
|
1350
|
-
const queryParamsObj = {};
|
|
1351
|
-
Object.entries(queryParamsOptions).forEach(([key, value]) => {
|
|
1352
|
-
if (value !== undefined) {
|
|
1353
|
-
queryParamsObj[key] = String(value);
|
|
1354
|
-
}
|
|
1355
|
-
});
|
|
1356
|
-
const queryParams = new URLSearchParams(queryParamsObj).toString();
|
|
1357
|
-
// Format the URL correctly depending on the 'path' value
|
|
1358
|
-
const formattedPath = path === '/' ? '/' : `/${path}`;
|
|
1359
|
-
const url = `${__classPrivateFieldGet(this, _DotCmsClient_config, "f").dotcmsUrl}/api/v1/nav${formattedPath}${queryParams ? `?${queryParams}` : ''}`;
|
|
1360
|
-
const response = await fetch(url, __classPrivateFieldGet(this, _DotCmsClient_requestOptions, "f"));
|
|
1361
|
-
return response.json();
|
|
1362
|
-
}
|
|
1363
|
-
};
|
|
1364
|
-
if (!config.dotcmsUrl) {
|
|
1365
|
-
throw new Error("Invalid configuration - 'dotcmsUrl' is required");
|
|
1366
|
-
}
|
|
1367
|
-
this.dotcmsUrl = getHostURL(config.dotcmsUrl)?.origin;
|
|
1368
|
-
if (!this.dotcmsUrl) {
|
|
1369
|
-
throw new Error("Invalid configuration - 'dotcmsUrl' must be a valid URL");
|
|
1370
|
-
}
|
|
1371
|
-
if (!config.authToken) {
|
|
1372
|
-
throw new Error("Invalid configuration - 'authToken' is required");
|
|
1373
|
-
}
|
|
1374
|
-
__classPrivateFieldSet(this, _DotCmsClient_config, {
|
|
1375
|
-
...config,
|
|
1376
|
-
dotcmsUrl: this.dotcmsUrl
|
|
1377
|
-
}, "f");
|
|
1378
|
-
__classPrivateFieldSet(this, _DotCmsClient_requestOptions, {
|
|
1379
|
-
...__classPrivateFieldGet(this, _DotCmsClient_config, "f").requestOptions,
|
|
1380
|
-
headers: {
|
|
1381
|
-
Authorization: `Bearer ${__classPrivateFieldGet(this, _DotCmsClient_config, "f").authToken}`,
|
|
1382
|
-
...__classPrivateFieldGet(this, _DotCmsClient_config, "f").requestOptions?.headers
|
|
1383
|
-
}
|
|
1384
|
-
}, "f");
|
|
1385
|
-
this.content = new Content(__classPrivateFieldGet(this, _DotCmsClient_requestOptions, "f"), __classPrivateFieldGet(this, _DotCmsClient_config, "f").dotcmsUrl);
|
|
1386
|
-
}
|
|
1387
|
-
static init(config) {
|
|
1388
|
-
if (this.instance) {
|
|
1389
|
-
console.warn('DotCmsClient has already been initialized. Please use the instance to interact with the DotCMS API.');
|
|
1390
|
-
}
|
|
1391
|
-
return this.instance ?? (this.instance = new DotCmsClient(config));
|
|
1392
|
-
}
|
|
1393
|
-
static get dotcmsUrl() {
|
|
1394
|
-
return (this.instance && __classPrivateFieldGet(this.instance, _DotCmsClient_config, "f").dotcmsUrl) || '';
|
|
1395
|
-
}
|
|
1396
|
-
validatePageOptions(options) {
|
|
1397
|
-
if (!options.path) {
|
|
1398
|
-
throw new Error("The 'path' parameter is required for the Page API");
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
validateNavOptions(options) {
|
|
1402
|
-
if (!options.path) {
|
|
1403
|
-
throw new Error("The 'path' parameter is required for the Nav API");
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
_DotCmsClient_config = new WeakMap(), _DotCmsClient_requestOptions = new WeakMap(), _DotCmsClient_listeners = new WeakMap();
|
|
1408
|
-
|
|
1409
|
-
// For now, we are not typing the functions in this file
|
|
1410
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1411
|
-
const graphqlToPageEntity = ({ page }) => {
|
|
1412
|
-
// If there is no page, return null
|
|
1413
|
-
if (!page) {
|
|
1414
|
-
return null;
|
|
1415
|
-
}
|
|
1416
|
-
const { layout, template, containers, urlContentMap, viewAs, site, _map, ...pageAsset } = page;
|
|
1417
|
-
const data = _map || {};
|
|
1418
|
-
return {
|
|
1419
|
-
layout,
|
|
1420
|
-
template,
|
|
1421
|
-
viewAs,
|
|
1422
|
-
urlContentMap,
|
|
1423
|
-
site,
|
|
1424
|
-
page: {
|
|
1425
|
-
...data,
|
|
1426
|
-
...pageAsset
|
|
1427
|
-
},
|
|
1428
|
-
containers: parseContainers(containers)
|
|
1429
|
-
};
|
|
1430
|
-
};
|
|
1431
|
-
const parseContainers = (containers = []) => {
|
|
1432
|
-
return containers.reduce((acc, container) => {
|
|
1433
|
-
const { path, identifier, containerStructures, containerContentlets, ...rest } = container;
|
|
1434
|
-
const key = (path || identifier);
|
|
1435
|
-
acc[key] = {
|
|
1436
|
-
containerStructures,
|
|
1437
|
-
container: {
|
|
1438
|
-
path,
|
|
1439
|
-
identifier,
|
|
1440
|
-
...rest
|
|
1441
|
-
},
|
|
1442
|
-
contentlets: parseContentletsToUuidMap(containerContentlets)
|
|
1443
|
-
};
|
|
1444
|
-
return acc;
|
|
1445
|
-
}, {});
|
|
1446
|
-
};
|
|
1447
|
-
const parseContentletsToUuidMap = (containerContentlets) => {
|
|
1448
|
-
return containerContentlets.reduce((acc, containerContentlet) => {
|
|
1449
|
-
const { uuid, contentlets } = containerContentlet;
|
|
1450
|
-
// TODO: This is a temporary solution, we need to find a better way to handle this.
|
|
1451
|
-
acc[uuid] = contentlets.map(({ _map = {}, ...rest }) => {
|
|
1452
|
-
return {
|
|
1453
|
-
..._map,
|
|
1454
|
-
...rest
|
|
1455
|
-
};
|
|
1456
|
-
});
|
|
1457
|
-
return acc;
|
|
1458
|
-
}, {});
|
|
1459
|
-
};
|
|
1460
|
-
|
|
1461
|
-
const getPageRequestParams = ({ path = '', params = {} }) => {
|
|
1462
|
-
const copiedParams = params instanceof URLSearchParams ? Object.fromEntries(params.entries()) : { ...params };
|
|
1463
|
-
const finalParams = {};
|
|
1464
|
-
const dotMarketingPersonaId = copiedParams['com.dotmarketing.persona.id'] || '';
|
|
1465
|
-
if (copiedParams['mode']) {
|
|
1466
|
-
finalParams['mode'] = copiedParams['mode'];
|
|
1467
|
-
}
|
|
1468
|
-
if (copiedParams['language_id']) {
|
|
1469
|
-
finalParams['language_id'] = copiedParams['language_id'];
|
|
1470
|
-
}
|
|
1471
|
-
if (copiedParams['variantName']) {
|
|
1472
|
-
finalParams['variantName'] = copiedParams['variantName'];
|
|
1473
|
-
}
|
|
1474
|
-
if (copiedParams['personaId'] || dotMarketingPersonaId) {
|
|
1475
|
-
finalParams['personaId'] = copiedParams['personaId'] || dotMarketingPersonaId;
|
|
1476
|
-
}
|
|
1477
|
-
return {
|
|
1478
|
-
path,
|
|
1479
|
-
...finalParams
|
|
1480
|
-
};
|
|
1481
|
-
};
|
|
1482
|
-
|
|
1483
|
-
exports.DotCmsClient = DotCmsClient;
|
|
1484
|
-
exports.destroyEditor = destroyEditor;
|
|
1485
|
-
exports.getPageRequestParams = getPageRequestParams;
|
|
1486
|
-
exports.graphqlToPageEntity = graphqlToPageEntity;
|
|
1487
|
-
exports.initEditor = initEditor;
|
|
1488
|
-
exports.isInsideEditor = isInsideEditor;
|
|
1489
|
-
exports.postMessageToEditor = postMessageToEditor;
|
|
1490
|
-
exports.updateNavigation = updateNavigation;
|