@agility/content-sync 1.1.3 → 1.1.4

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.
@@ -1,511 +1,511 @@
1
- import {
2
- logDebug,
3
- logInfo,
4
- logError,
5
- logWarning,
6
- logSuccess,
7
- asyncForEach,
8
- } from "./util";
9
-
10
- let store = null;
11
- let options = null;
12
-
13
- const validateStoreInterface = (storeCandidate) => {
14
- if (!storeCandidate.clearItems) {
15
- throw new TypeError(
16
- "Your sync store interface must implement `clearItems`."
17
- );
18
- }
19
-
20
- if (!storeCandidate.deleteItem) {
21
- throw new TypeError(
22
- "Your sync store interface must implement `deleteItem`."
23
- );
24
- }
25
-
26
- if (!storeCandidate.getItem) {
27
- throw new TypeError("Your sync store interface must implement `getItem`.");
28
- }
29
-
30
- if (!storeCandidate.saveItem) {
31
- throw new TypeError("Your sync store interface must implement `saveItem`.");
32
- }
33
-
34
- if (!storeCandidate.mergeItemToList) {
35
- throw new TypeError(
36
- "Your sync store interface must implement `mergeItemToList`."
37
- );
38
- }
39
- };
40
-
41
- const setStore = (storeToUse, storeOptions) => {
42
- validateStoreInterface(storeToUse);
43
- store = storeToUse;
44
- options = storeOptions;
45
- };
46
-
47
- const getStore = () => {
48
- return store
49
- }
50
-
51
- // sanitize graphql node names
52
- const sanitizeName = (name) => {
53
-
54
- if (name !== undefined && name !== null) {
55
- return name.replace(/\W/g, "")
56
- } else {
57
- return null
58
- }
59
-
60
- };
61
-
62
- const saveContentItem = async ({ contentItem, languageCode }) => {
63
-
64
- if (
65
- !contentItem ||
66
- !contentItem.properties
67
- ) {
68
- logWarning("Null item or item with no properties cannot be saved");
69
- return;
70
- }
71
-
72
- let definitionName = sanitizeName(contentItem.properties.definitionName)
73
- let referenceName = contentItem.properties.referenceName
74
-
75
- if (contentItem.properties.state === 3) {
76
- //if the item is deleted
77
-
78
- //grab the reference name from the currently saved item...
79
- const currentItem = await store.getItem({
80
- options,
81
- itemType: "item",
82
- languageCode,
83
- itemID: contentItem.contentID,
84
- });
85
- if (currentItem) {
86
-
87
- //if the item is deleted, we need to grab the def and ref name from the current
88
- definitionName = sanitizeName(currentItem.properties.definitionName)
89
- referenceName = currentItem.properties.referenceName
90
-
91
- await store.deleteItem({
92
- options,
93
- itemType: "item",
94
- languageCode,
95
- itemID: contentItem.contentID,
96
- });
97
- }
98
- } else {
99
- //regular item
100
- if (!contentItem.properties.definitionName
101
- || !contentItem.properties.referenceName) {
102
- logWarning(`Content with id ${contentItem.contentID} does not have the neccessary properties to be saved.`)
103
- return
104
- }
105
-
106
-
107
-
108
- await store.saveItem({
109
- options,
110
- item: contentItem,
111
- itemType: "item",
112
- languageCode,
113
- itemID: contentItem.contentID,
114
- });
115
- }
116
-
117
- if (referenceName) {
118
- //merge the item by reference or definition name - it might need to be merged into a list
119
- await store.mergeItemToList({
120
- options,
121
- item: contentItem,
122
- languageCode,
123
- itemID: contentItem.contentID,
124
- referenceName,
125
- definitionName,
126
- });
127
- }
128
- };
129
-
130
- const savePageItem = async ({ pageItem, languageCode }) => {
131
- if (pageItem.properties.state === 3) {
132
- //item is deleted
133
- await store.deleteItem({
134
- options,
135
- itemType: "page",
136
- languageCode,
137
- itemID: pageItem.pageID,
138
- });
139
- } else {
140
- //regular item
141
- await store.saveItem({
142
- options,
143
- item: pageItem,
144
- itemType: "page",
145
- languageCode,
146
- itemID: pageItem.pageID,
147
- });
148
- }
149
- };
150
-
151
- const saveSitemap = async ({ sitemap, channelName, languageCode }) => {
152
- await store.saveItem({
153
- options,
154
- item: sitemap,
155
- itemType: "sitemap",
156
- languageCode,
157
- itemID: channelName,
158
- });
159
- };
160
-
161
- const saveSitemapNested = async ({
162
- sitemapNested,
163
- channelName,
164
- languageCode,
165
- }) => {
166
- await store.saveItem({
167
- options,
168
- item: sitemapNested,
169
- itemType: "nestedsitemap",
170
- languageCode,
171
- itemID: channelName,
172
- });
173
- };
174
-
175
- const saveUrlRedirections = async ({ urlRedirections, languageCode }) => {
176
- await store.saveItem({
177
- options,
178
- item: urlRedirections,
179
- itemType: "urlredirections",
180
- languageCode,
181
- itemID: "urlredirections",
182
- });
183
- };
184
-
185
- const getUrlRedirections = async ({ languageCode }) => {
186
- return await store.getItem({
187
- options,
188
- itemType: "urlredirections",
189
- languageCode,
190
- itemID: "urlredirections",
191
- });
192
- };
193
-
194
- const saveSyncState = async ({ syncState, languageCode }) => {
195
- await store.saveItem({
196
- options,
197
- item: syncState,
198
- itemType: "state",
199
- languageCode,
200
- itemID: "sync",
201
- });
202
- };
203
-
204
- const getSyncState = async (languageCode) => {
205
- return await store.getItem({
206
- options,
207
- itemType: "state",
208
- languageCode,
209
- itemID: "sync",
210
- });
211
- };
212
-
213
- /**
214
- * Gets the details of a content item by its Content ID.
215
- * @memberof AgilitySync.Client.Content
216
- * @param {Object} requestParams - The paramters for the SDK request.
217
- * @param {number} requestParams.contentID - The contentID of the requested item in this language.
218
- * @param {string} requestParams.languageCode - The language code of the content you want to retrieve.
219
- * @param {number} [requestParams.depth] - The depth, representing the levels in which you want linked content auto-resolved. Default is **1**.
220
- * @param {boolean} [requestParams.expandAllContentLinks] - Whether or not to expand entire linked content references, includings lists and items that are rendered in the CMS as Grid or Link. Default is **false**
221
- * @returns {Promise<Object>} - Returns a content item object.
222
- */
223
- const getContentItem = async ({ contentID, languageCode, depth, contentLinkDepth, expandAllContentLinks = false }) => {
224
-
225
- if (depth === undefined && contentLinkDepth !== undefined) {
226
- depth = contentLinkDepth
227
- } else if (depth === undefined && contentLinkDepth === undefined) {
228
- depth = 2
229
- }
230
-
231
- const contentItem = await store.getItem({
232
- options,
233
- itemType: "item",
234
- languageCode,
235
- itemID: contentID,
236
- });
237
- return await expandContentItem({ contentItem, languageCode, depth, expandAllContentLinks });
238
- };
239
-
240
- const expandContentItem = async ({ contentItem, languageCode, depth, expandAllContentLinks = false }) => {
241
- if (!contentItem) return null;
242
-
243
- if (depth > 0) {
244
- //make this work for the .fields or the .customFields property...
245
- let fields = contentItem.fields;
246
- if (!fields) fields = contentItem.customFields;
247
- for (const fieldName in fields) {
248
- const fieldValue = fields[fieldName];
249
- if (!fieldValue) {
250
- //do nothing...
251
- continue;
252
- } else if (fieldValue.contentid > 0) {
253
- //single linked item
254
- const childItem = await getContentItem({
255
- contentID: fieldValue.contentid,
256
- languageCode,
257
- depth: depth - 1,
258
- });
259
- if (childItem != null) fields[fieldName] = childItem;
260
- } else if (fieldValue.fulllist === true
261
- && fieldValue.referencename
262
- && expandAllContentLinks === true) {
263
-
264
- //LINK TO THE FULL LIST
265
- const referenceName = fieldValue.referencename
266
-
267
- const skip = 0
268
- const take = 50
269
-
270
- const list = await getContentList({
271
- referenceName,
272
- languageCode,
273
- depth: depth - 1,
274
- expandAllContentLinks,
275
- skip,
276
- take
277
- })
278
-
279
- let sortIDAry = []
280
-
281
- if (fieldValue.sortids && fieldValue.sortids.split) {
282
- sortIDAry = fieldValue.sortids.split(",");
283
- }
284
-
285
- let itemCount = 0
286
- const childItems = [];
287
- for (const childItemID of sortIDAry) {
288
- itemCount++
289
- const childItem = await getContentItem({
290
- contentID: childItemID,
291
- languageCode,
292
- depth: depth - 1,
293
- expandAllContentLinks,
294
- skip,
295
- take
296
- });
297
-
298
- if (childItem != null) {
299
- childItems.push(childItem);
300
- }
301
- }
302
-
303
- for (const listItem of list.items) {
304
- itemCount++
305
- if (itemCount > 50) break;
306
-
307
- const listItemContentID = listItem.contentID
308
- if (sortIDAry.includes(`${listItemContentID}`)) {
309
- continue;
310
- }
311
-
312
- const childItem = await getContentItem({
313
- contentID: listItemContentID,
314
- languageCode,
315
- depth: depth - 1,
316
- expandAllContentLinks
317
- });
318
- if (childItem != null) childItems.push(childItem);
319
- }
320
-
321
- fields[fieldName] = childItems;
322
-
323
- } else if (fieldValue.sortids && fieldValue.sortids.split && fieldValue.fulllist !== true) {
324
- //MULTI LINKED ITEM
325
- let sortIDAry = []
326
- if (fieldValue.sortids && fieldValue.sortids.split) {
327
- sortIDAry = fieldValue.sortids.split(",");
328
- }
329
-
330
- const skip = expandAllContentLinks ? 0 : undefined
331
- const take = expandAllContentLinks ? 50 : undefined
332
-
333
- const childItems = [];
334
- for (const childItemID of sortIDAry) {
335
- const childItem = await getContentItem({
336
- contentID: childItemID,
337
- languageCode,
338
- depth: depth - 1,
339
- expandAllContentLinks,
340
- skip,
341
- take
342
- });
343
- if (childItem != null) childItems.push(childItem);
344
- }
345
- fields[fieldName] = childItems;
346
-
347
- }
348
- }
349
- }
350
- return contentItem;
351
- };
352
-
353
-
354
-
355
- /**
356
- * Retrieves a list of content items by reference name. If skip or take has been specified, returns an object with an items array and totalCount property. Otherwise returns an array of items.
357
- * @memberof AgilitySync.Client.Content
358
- * @param {Object} requestParams - The parameters for this request.
359
- * @param {string} requestParams.referenceName - The unique reference name of the content list you wish to retrieve in the specified language.
360
- * @param {string} requestParams.languageCode - The language code of the content you want to retrieve.
361
- * @param {number} [requestParams.depth] - The depth, representing the levels in which you want linked content auto-resolved. Default is **1**.
362
- * @param {boolean} [requestParams.expandAllContentLinks] - Whether or not to expand entire linked content references, includings lists and items that are rendered in the CMS as Grid or Link. Default is **false**
363
- * @param {number} [requestParams.take] - The maximum number of items to retrieve in this request.
364
- * @param {number} [requestParams.skip] - The number of items to skip from the list. Used for implementing pagination.
365
- * @returns {Promise<[] | Object>} - Returns a list of content items, or, if skip or take has been specified, an object with an items array and totalCount property.
366
- */
367
- const getContentList = async ({ referenceName, languageCode, depth, contentLinkDepth, expandAllContentLinks = false, skip = -1, take = -1 }) => {
368
-
369
- if (depth === undefined && contentLinkDepth !== undefined) {
370
- depth = contentLinkDepth
371
- } else if (depth === undefined && contentLinkDepth === undefined) {
372
- depth = 0
373
- }
374
-
375
- let lst = await store.getItem({
376
- options,
377
- itemType: "list",
378
- languageCode,
379
- itemID: referenceName,
380
- }) || [];
381
-
382
- if (depth > 0 && take === -1) {
383
- throw new Error("If you specify depth > 0, you must also specify the take parameter.")
384
- }
385
-
386
- if (expandAllContentLinks && take === -1) {
387
- throw new Error("If you specify expandAllContentLinks=true, you must also specify the take parameter.")
388
- }
389
-
390
- const totalCount = lst.length
391
-
392
- if (skip > 0 && skip < lst.length) {
393
- lst = lst.slice(skip)
394
- }
395
-
396
- if (take > 0 && take < lst.length) {
397
- lst = lst.slice(0, take)
398
- }
399
-
400
- if (depth > 0) {
401
- for (let i=0; i<lst.length;i++) {
402
- lst[i] = await expandContentItem({
403
- contentItem: lst[i],
404
- depth: depth - 1,
405
- languageCode,
406
- expandAllContentLinks
407
- })
408
- }
409
- }
410
-
411
- if (skip > 0 || take > 0) {
412
- //if we have sliced this array, return an object with an items and totalCount property
413
- return {
414
- items: lst,
415
- totalCount
416
- }
417
- } else {
418
- //just return the full list
419
- return lst
420
- }
421
-
422
-
423
-
424
-
425
-
426
- };
427
- /**
428
- * Get a Page based on it's id and languageCode.
429
- * @param {*} { pageID, languageCode, depth = 3 }
430
- * @returns
431
- */
432
- const getPage = async ({ pageID, languageCode, depth, contentLinkDepth, expandAllContentLinks = false }) => {
433
-
434
- if (depth === undefined && contentLinkDepth !== undefined) {
435
- depth = contentLinkDepth
436
- } else if (depth === undefined && contentLinkDepth === undefined) {
437
- depth = 2
438
- }
439
-
440
- let pageItem = await store.getItem({
441
- options,
442
- itemType: "page",
443
- languageCode,
444
- itemID: pageID,
445
- });
446
-
447
- if (depth > 0) {
448
- //if a depth was specified, pull in the modules (content items) for this page
449
- for (const zoneName in pageItem.zones) {
450
- const zone = pageItem.zones[zoneName];
451
-
452
- for (const mod of zone) {
453
- const moduleItem = await getContentItem({
454
- options,
455
- contentID: mod.item.contentid,
456
- languageCode,
457
- depth: depth - 1,
458
- expandAllContentLinks
459
- });
460
- mod.item = moduleItem;
461
- }
462
- }
463
- }
464
-
465
- return pageItem;
466
- };
467
-
468
- const getSitemap = async ({ channelName, languageCode }) => {
469
- return await store.getItem({
470
- options,
471
- itemType: "sitemap",
472
- languageCode,
473
- itemID: channelName,
474
- });
475
- };
476
-
477
- const getSitemapNested = async ({ channelName, languageCode }) => {
478
- return await store.getItem({
479
- options,
480
- itemType: "nestedsitemap",
481
- languageCode,
482
- itemID: channelName,
483
- });
484
- };
485
-
486
- /**
487
- * Clear everything out.
488
- */
489
- const clear = async () => {
490
- await store.clearItems({ options });
491
- };
492
-
493
- export default {
494
- saveContentItem,
495
- savePageItem,
496
- getContentItem,
497
- getContentList,
498
- getPage,
499
- getSitemap,
500
- getSitemapFlat: getSitemap,
501
- getSitemapNested,
502
- saveSitemap,
503
- saveSitemapNested,
504
- saveUrlRedirections,
505
- getUrlRedirections,
506
- getSyncState,
507
- saveSyncState,
508
- clear,
509
- setStore,
510
- getStore
511
- };
1
+ import {
2
+ logDebug,
3
+ logInfo,
4
+ logError,
5
+ logWarning,
6
+ logSuccess,
7
+ asyncForEach,
8
+ } from "./util";
9
+
10
+ let store = null;
11
+ let options = null;
12
+
13
+ const validateStoreInterface = (storeCandidate) => {
14
+ if (!storeCandidate.clearItems) {
15
+ throw new TypeError(
16
+ "Your sync store interface must implement `clearItems`."
17
+ );
18
+ }
19
+
20
+ if (!storeCandidate.deleteItem) {
21
+ throw new TypeError(
22
+ "Your sync store interface must implement `deleteItem`."
23
+ );
24
+ }
25
+
26
+ if (!storeCandidate.getItem) {
27
+ throw new TypeError("Your sync store interface must implement `getItem`.");
28
+ }
29
+
30
+ if (!storeCandidate.saveItem) {
31
+ throw new TypeError("Your sync store interface must implement `saveItem`.");
32
+ }
33
+
34
+ if (!storeCandidate.mergeItemToList) {
35
+ throw new TypeError(
36
+ "Your sync store interface must implement `mergeItemToList`."
37
+ );
38
+ }
39
+ };
40
+
41
+ const setStore = (storeToUse, storeOptions) => {
42
+ validateStoreInterface(storeToUse);
43
+ store = storeToUse;
44
+ options = storeOptions;
45
+ };
46
+
47
+ const getStore = () => {
48
+ return store
49
+ }
50
+
51
+ // sanitize graphql node names
52
+ const sanitizeName = (name) => {
53
+
54
+ if (name !== undefined && name !== null) {
55
+ return name.replace(/\W/g, "")
56
+ } else {
57
+ return null
58
+ }
59
+
60
+ };
61
+
62
+ const saveContentItem = async ({ contentItem, languageCode }) => {
63
+
64
+ if (
65
+ !contentItem ||
66
+ !contentItem.properties
67
+ ) {
68
+ logWarning("Null item or item with no properties cannot be saved");
69
+ return;
70
+ }
71
+
72
+ let definitionName = sanitizeName(contentItem.properties.definitionName)
73
+ let referenceName = contentItem.properties.referenceName
74
+
75
+ if (contentItem.properties.state === 3) {
76
+ //if the item is deleted
77
+
78
+ //grab the reference name from the currently saved item...
79
+ const currentItem = await store.getItem({
80
+ options,
81
+ itemType: "item",
82
+ languageCode,
83
+ itemID: contentItem.contentID,
84
+ });
85
+ if (currentItem) {
86
+
87
+ //if the item is deleted, we need to grab the def and ref name from the current
88
+ definitionName = sanitizeName(currentItem.properties.definitionName)
89
+ referenceName = currentItem.properties.referenceName
90
+
91
+ await store.deleteItem({
92
+ options,
93
+ itemType: "item",
94
+ languageCode,
95
+ itemID: contentItem.contentID,
96
+ });
97
+ }
98
+ } else {
99
+ //regular item
100
+ if (!contentItem.properties.definitionName
101
+ || !contentItem.properties.referenceName) {
102
+ logWarning(`Content with id ${contentItem.contentID} does not have the neccessary properties to be saved.`)
103
+ return
104
+ }
105
+
106
+
107
+
108
+ await store.saveItem({
109
+ options,
110
+ item: contentItem,
111
+ itemType: "item",
112
+ languageCode,
113
+ itemID: contentItem.contentID,
114
+ });
115
+ }
116
+
117
+ if (referenceName) {
118
+ //merge the item by reference or definition name - it might need to be merged into a list
119
+ await store.mergeItemToList({
120
+ options,
121
+ item: contentItem,
122
+ languageCode,
123
+ itemID: contentItem.contentID,
124
+ referenceName,
125
+ definitionName,
126
+ });
127
+ }
128
+ };
129
+
130
+ const savePageItem = async ({ pageItem, languageCode }) => {
131
+ if (pageItem.properties.state === 3) {
132
+ //item is deleted
133
+ await store.deleteItem({
134
+ options,
135
+ itemType: "page",
136
+ languageCode,
137
+ itemID: pageItem.pageID,
138
+ });
139
+ } else {
140
+ //regular item
141
+ await store.saveItem({
142
+ options,
143
+ item: pageItem,
144
+ itemType: "page",
145
+ languageCode,
146
+ itemID: pageItem.pageID,
147
+ });
148
+ }
149
+ };
150
+
151
+ const saveSitemap = async ({ sitemap, channelName, languageCode }) => {
152
+ await store.saveItem({
153
+ options,
154
+ item: sitemap,
155
+ itemType: "sitemap",
156
+ languageCode,
157
+ itemID: channelName,
158
+ });
159
+ };
160
+
161
+ const saveSitemapNested = async ({
162
+ sitemapNested,
163
+ channelName,
164
+ languageCode,
165
+ }) => {
166
+ await store.saveItem({
167
+ options,
168
+ item: sitemapNested,
169
+ itemType: "nestedsitemap",
170
+ languageCode,
171
+ itemID: channelName,
172
+ });
173
+ };
174
+
175
+ const saveUrlRedirections = async ({ urlRedirections, languageCode }) => {
176
+ await store.saveItem({
177
+ options,
178
+ item: urlRedirections,
179
+ itemType: "urlredirections",
180
+ languageCode,
181
+ itemID: "urlredirections",
182
+ });
183
+ };
184
+
185
+ const getUrlRedirections = async ({ languageCode }) => {
186
+ return await store.getItem({
187
+ options,
188
+ itemType: "urlredirections",
189
+ languageCode,
190
+ itemID: "urlredirections",
191
+ });
192
+ };
193
+
194
+ const saveSyncState = async ({ syncState, languageCode }) => {
195
+ await store.saveItem({
196
+ options,
197
+ item: syncState,
198
+ itemType: "state",
199
+ languageCode,
200
+ itemID: "sync",
201
+ });
202
+ };
203
+
204
+ const getSyncState = async (languageCode) => {
205
+ return await store.getItem({
206
+ options,
207
+ itemType: "state",
208
+ languageCode,
209
+ itemID: "sync",
210
+ });
211
+ };
212
+
213
+ /**
214
+ * Gets the details of a content item by its Content ID.
215
+ * @memberof AgilitySync.Client.Content
216
+ * @param {Object} requestParams - The paramters for the SDK request.
217
+ * @param {number} requestParams.contentID - The contentID of the requested item in this language.
218
+ * @param {string} requestParams.languageCode - The language code of the content you want to retrieve.
219
+ * @param {number} [requestParams.depth] - The depth, representing the levels in which you want linked content auto-resolved. Default is **1**.
220
+ * @param {boolean} [requestParams.expandAllContentLinks] - Whether or not to expand entire linked content references, includings lists and items that are rendered in the CMS as Grid or Link. Default is **false**
221
+ * @returns {Promise<Object>} - Returns a content item object.
222
+ */
223
+ const getContentItem = async ({ contentID, languageCode, depth, contentLinkDepth, expandAllContentLinks = false }) => {
224
+
225
+ if (depth === undefined && contentLinkDepth !== undefined) {
226
+ depth = contentLinkDepth
227
+ } else if (depth === undefined && contentLinkDepth === undefined) {
228
+ depth = 2
229
+ }
230
+
231
+ const contentItem = await store.getItem({
232
+ options,
233
+ itemType: "item",
234
+ languageCode,
235
+ itemID: contentID,
236
+ });
237
+ return await expandContentItem({ contentItem, languageCode, depth, expandAllContentLinks });
238
+ };
239
+
240
+ const expandContentItem = async ({ contentItem, languageCode, depth, expandAllContentLinks = false }) => {
241
+ if (!contentItem) return null;
242
+
243
+ if (depth > 0) {
244
+ //make this work for the .fields or the .customFields property...
245
+ let fields = contentItem.fields;
246
+ if (!fields) fields = contentItem.customFields;
247
+ for (const fieldName in fields) {
248
+ const fieldValue = fields[fieldName];
249
+ if (!fieldValue) {
250
+ //do nothing...
251
+ continue;
252
+ } else if (fieldValue.contentid > 0) {
253
+ //single linked item
254
+ const childItem = await getContentItem({
255
+ contentID: fieldValue.contentid,
256
+ languageCode,
257
+ depth: depth - 1,
258
+ });
259
+ if (childItem != null) fields[fieldName] = childItem;
260
+ } else if (fieldValue.fulllist === true
261
+ && fieldValue.referencename
262
+ && expandAllContentLinks === true) {
263
+
264
+ //LINK TO THE FULL LIST
265
+ const referenceName = fieldValue.referencename
266
+
267
+ const skip = 0
268
+ const take = 50
269
+
270
+ const list = await getContentList({
271
+ referenceName,
272
+ languageCode,
273
+ depth: depth - 1,
274
+ expandAllContentLinks,
275
+ skip,
276
+ take
277
+ })
278
+
279
+ let sortIDAry = []
280
+
281
+ if (fieldValue.sortids && fieldValue.sortids.split) {
282
+ sortIDAry = fieldValue.sortids.split(",");
283
+ }
284
+
285
+ let itemCount = 0
286
+ const childItems = [];
287
+ for (const childItemID of sortIDAry) {
288
+ itemCount++
289
+ const childItem = await getContentItem({
290
+ contentID: childItemID,
291
+ languageCode,
292
+ depth: depth - 1,
293
+ expandAllContentLinks,
294
+ skip,
295
+ take
296
+ });
297
+
298
+ if (childItem != null) {
299
+ childItems.push(childItem);
300
+ }
301
+ }
302
+
303
+ for (const listItem of list.items) {
304
+ itemCount++
305
+ if (itemCount > 50) break;
306
+
307
+ const listItemContentID = listItem.contentID
308
+ if (sortIDAry.includes(`${listItemContentID}`)) {
309
+ continue;
310
+ }
311
+
312
+ const childItem = await getContentItem({
313
+ contentID: listItemContentID,
314
+ languageCode,
315
+ depth: depth - 1,
316
+ expandAllContentLinks
317
+ });
318
+ if (childItem != null) childItems.push(childItem);
319
+ }
320
+
321
+ fields[fieldName] = childItems;
322
+
323
+ } else if (fieldValue.sortids && fieldValue.sortids.split && fieldValue.fulllist !== true) {
324
+ //MULTI LINKED ITEM
325
+ let sortIDAry = []
326
+ if (fieldValue.sortids && fieldValue.sortids.split) {
327
+ sortIDAry = fieldValue.sortids.split(",");
328
+ }
329
+
330
+ const skip = expandAllContentLinks ? 0 : undefined
331
+ const take = expandAllContentLinks ? 50 : undefined
332
+
333
+ const childItems = [];
334
+ for (const childItemID of sortIDAry) {
335
+ const childItem = await getContentItem({
336
+ contentID: childItemID,
337
+ languageCode,
338
+ depth: depth - 1,
339
+ expandAllContentLinks,
340
+ skip,
341
+ take
342
+ });
343
+ if (childItem != null) childItems.push(childItem);
344
+ }
345
+ fields[fieldName] = childItems;
346
+
347
+ }
348
+ }
349
+ }
350
+ return contentItem;
351
+ };
352
+
353
+
354
+
355
+ /**
356
+ * Retrieves a list of content items by reference name. If skip or take has been specified, returns an object with an items array and totalCount property. Otherwise returns an array of items.
357
+ * @memberof AgilitySync.Client.Content
358
+ * @param {Object} requestParams - The parameters for this request.
359
+ * @param {string} requestParams.referenceName - The unique reference name of the content list you wish to retrieve in the specified language.
360
+ * @param {string} requestParams.languageCode - The language code of the content you want to retrieve.
361
+ * @param {number} [requestParams.depth] - The depth, representing the levels in which you want linked content auto-resolved. Default is **1**.
362
+ * @param {boolean} [requestParams.expandAllContentLinks] - Whether or not to expand entire linked content references, includings lists and items that are rendered in the CMS as Grid or Link. Default is **false**
363
+ * @param {number} [requestParams.take] - The maximum number of items to retrieve in this request.
364
+ * @param {number} [requestParams.skip] - The number of items to skip from the list. Used for implementing pagination.
365
+ * @returns {Promise<[] | Object>} - Returns a list of content items, or, if skip or take has been specified, an object with an items array and totalCount property.
366
+ */
367
+ const getContentList = async ({ referenceName, languageCode, depth, contentLinkDepth, expandAllContentLinks = false, skip = -1, take = -1 }) => {
368
+
369
+ if (depth === undefined && contentLinkDepth !== undefined) {
370
+ depth = contentLinkDepth
371
+ } else if (depth === undefined && contentLinkDepth === undefined) {
372
+ depth = 0
373
+ }
374
+
375
+ let lst = await store.getItem({
376
+ options,
377
+ itemType: "list",
378
+ languageCode,
379
+ itemID: referenceName,
380
+ }) || [];
381
+
382
+ if (depth > 0 && take === -1) {
383
+ throw new Error("If you specify depth > 0, you must also specify the take parameter.")
384
+ }
385
+
386
+ if (expandAllContentLinks && take === -1) {
387
+ throw new Error("If you specify expandAllContentLinks=true, you must also specify the take parameter.")
388
+ }
389
+
390
+ const totalCount = lst.length
391
+
392
+ if (skip > 0 && skip < lst.length) {
393
+ lst = lst.slice(skip)
394
+ }
395
+
396
+ if (take > 0 && take < lst.length) {
397
+ lst = lst.slice(0, take)
398
+ }
399
+
400
+ if (depth > 0) {
401
+ for (let i=0; i<lst.length;i++) {
402
+ lst[i] = await expandContentItem({
403
+ contentItem: lst[i],
404
+ depth: depth - 1,
405
+ languageCode,
406
+ expandAllContentLinks
407
+ })
408
+ }
409
+ }
410
+
411
+ if (skip > 0 || take > 0) {
412
+ //if we have sliced this array, return an object with an items and totalCount property
413
+ return {
414
+ items: lst,
415
+ totalCount
416
+ }
417
+ } else {
418
+ //just return the full list
419
+ return lst
420
+ }
421
+
422
+
423
+
424
+
425
+
426
+ };
427
+ /**
428
+ * Get a Page based on it's id and languageCode.
429
+ * @param {*} { pageID, languageCode, depth = 3 }
430
+ * @returns
431
+ */
432
+ const getPage = async ({ pageID, languageCode, depth, contentLinkDepth, expandAllContentLinks = false }) => {
433
+
434
+ if (depth === undefined && contentLinkDepth !== undefined) {
435
+ depth = contentLinkDepth
436
+ } else if (depth === undefined && contentLinkDepth === undefined) {
437
+ depth = 2
438
+ }
439
+
440
+ let pageItem = await store.getItem({
441
+ options,
442
+ itemType: "page",
443
+ languageCode,
444
+ itemID: pageID,
445
+ });
446
+
447
+ if (depth > 0) {
448
+ //if a depth was specified, pull in the modules (content items) for this page
449
+ for (const zoneName in pageItem.zones) {
450
+ const zone = pageItem.zones[zoneName];
451
+
452
+ for (const mod of zone) {
453
+ const moduleItem = await getContentItem({
454
+ options,
455
+ contentID: mod.item.contentid,
456
+ languageCode,
457
+ depth: depth - 1,
458
+ expandAllContentLinks
459
+ });
460
+ mod.item = moduleItem;
461
+ }
462
+ }
463
+ }
464
+
465
+ return pageItem;
466
+ };
467
+
468
+ const getSitemap = async ({ channelName, languageCode }) => {
469
+ return await store.getItem({
470
+ options,
471
+ itemType: "sitemap",
472
+ languageCode,
473
+ itemID: channelName,
474
+ });
475
+ };
476
+
477
+ const getSitemapNested = async ({ channelName, languageCode }) => {
478
+ return await store.getItem({
479
+ options,
480
+ itemType: "nestedsitemap",
481
+ languageCode,
482
+ itemID: channelName,
483
+ });
484
+ };
485
+
486
+ /**
487
+ * Clear everything out.
488
+ */
489
+ const clear = async () => {
490
+ await store.clearItems({ options });
491
+ };
492
+
493
+ export default {
494
+ saveContentItem,
495
+ savePageItem,
496
+ getContentItem,
497
+ getContentList,
498
+ getPage,
499
+ getSitemap,
500
+ getSitemapFlat: getSitemap,
501
+ getSitemapNested,
502
+ saveSitemap,
503
+ saveSitemapNested,
504
+ saveUrlRedirections,
505
+ getUrlRedirections,
506
+ getSyncState,
507
+ saveSyncState,
508
+ clear,
509
+ setStore,
510
+ getStore
511
+ };