@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.
- package/.babelrc +6 -6
- package/.vscode/launch.json +34 -34
- package/README.md +206 -206
- package/dist/agility-sync-sdk.node.js +4246 -1481
- package/package.json +46 -46
- package/src/methods/clearSync.js +7 -7
- package/src/methods/runSync.js +94 -94
- package/src/methods/syncContent.js +80 -80
- package/src/methods/syncPages.js +75 -75
- package/src/store-interface-console.js +72 -72
- package/src/store-interface-filesystem.js +201 -198
- package/src/store-interface.js +511 -511
- package/src/sync-client.js +74 -74
- package/src/util.js +45 -45
- package/test/01-getSyncClient.tests.js +37 -37
- package/test/02-runSync.tests.js +74 -74
- package/test/03-store.getContentItem.tests.js +25 -25
- package/test/04-store.getContentList.tests.js +67 -67
- package/test/05-store.getPage.tests.js +25 -25
- package/test/06-store.getRedirects.tests.js +26 -26
- package/test/99-clearSync.tests.js +29 -29
- package/test/_syncClients.config.js +57 -57
- package/webpack.config.js +32 -32
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The function to handle saving/updating an item to your storage. This could be a Content Item, Page, Url Redirections, Sync State (state), or Sitemap.
|
|
3
|
-
* @param {Object} params - The parameters object
|
|
4
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
5
|
-
* @param {Object} params.item - The object representing the Content Item, Page, Url Redirections, Sync State (state), or Sitemap that needs to be saved/updated
|
|
6
|
-
* @param {String} params.itemType - The type of item being saved/updated, expected values are `item`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
7
|
-
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
8
|
-
* @param {(String|Number)} params.itemID - The ID of the item being saved/updated - this could be a string or number depending on the itemType
|
|
9
|
-
* @returns {Void}
|
|
10
|
-
*/
|
|
11
|
-
const saveItem = async ({ options, item, itemType, languageCode, itemID }) => {
|
|
12
|
-
console.log(`Console Interface: saveItem has been called`);
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* The function to handle deleting an item to your storage. This could be a Content Item, Page, Url Redirections, Sync State (state), or Sitemap.
|
|
17
|
-
* @param {Object} params - The parameters object
|
|
18
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
19
|
-
* @param {String} params.itemType - The type of item being deleted, expected values are `item`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
20
|
-
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
21
|
-
* @param {(String|Number)} params.itemID - The ID of the item being deleted - this could be a string or number depending on the itemType
|
|
22
|
-
* @returns {Void}
|
|
23
|
-
*/
|
|
24
|
-
const deleteItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
25
|
-
console.log(`Console Interface: deleteItem has been called`);
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* The function to handle updating and placing a Content Item into a "list" so that you can handle querying a collection of items.
|
|
30
|
-
* @param {Object} params - The parameters object
|
|
31
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
32
|
-
* @param {Object} params.item - The object representing the Content Item
|
|
33
|
-
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
34
|
-
* @param {(String|Number)} params.itemID - The ID of the item being updated - this could be a string or number depending on the itemType
|
|
35
|
-
* @param {String} params.referenceName - The reference name of the Content List that this Content Item should be added to
|
|
36
|
-
* @param {String} params.definitionName - The Model name that the Content Item is based on
|
|
37
|
-
* @returns {Void}
|
|
38
|
-
*/
|
|
39
|
-
const mergeItemToList = async ({ options, item, languageCode, itemID, referenceName, definitionName }) => {
|
|
40
|
-
console.log(`Console Interface: mergeItemToList has been called`);
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* The function to handle retrieving a Content Item, Page, Url Redirections, Sync State (state), or Sitemap
|
|
45
|
-
* @param {Object} params - The parameters object
|
|
46
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
47
|
-
* @param {String} params.itemType - The type of item being accessed, expected values are `item`, `list`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
48
|
-
* @param {String} params.languageCode - The locale code associated to the item being accessed
|
|
49
|
-
* @param {(String|Number)} params.itemID - The ID of the item being accessed - this could be a string or number depending on the itemType
|
|
50
|
-
* @returns {Object}
|
|
51
|
-
*/
|
|
52
|
-
const getItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
53
|
-
console.log(`Console Interface: getItem has been called`)
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* The function to handle clearing the cache of synchronized data from the CMS
|
|
58
|
-
* @param {Object} params - The parameters object
|
|
59
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
60
|
-
* @returns {Void}
|
|
61
|
-
*/
|
|
62
|
-
const clearItems = async ({ options }) => {
|
|
63
|
-
console.log(`Console Interface: clearItem has been called`)
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
module.exports = {
|
|
68
|
-
saveItem,
|
|
69
|
-
deleteItem,
|
|
70
|
-
mergeItemToList,
|
|
71
|
-
getItem,
|
|
72
|
-
clearItems
|
|
1
|
+
/**
|
|
2
|
+
* The function to handle saving/updating an item to your storage. This could be a Content Item, Page, Url Redirections, Sync State (state), or Sitemap.
|
|
3
|
+
* @param {Object} params - The parameters object
|
|
4
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
5
|
+
* @param {Object} params.item - The object representing the Content Item, Page, Url Redirections, Sync State (state), or Sitemap that needs to be saved/updated
|
|
6
|
+
* @param {String} params.itemType - The type of item being saved/updated, expected values are `item`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
7
|
+
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
8
|
+
* @param {(String|Number)} params.itemID - The ID of the item being saved/updated - this could be a string or number depending on the itemType
|
|
9
|
+
* @returns {Void}
|
|
10
|
+
*/
|
|
11
|
+
const saveItem = async ({ options, item, itemType, languageCode, itemID }) => {
|
|
12
|
+
console.log(`Console Interface: saveItem has been called`);
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The function to handle deleting an item to your storage. This could be a Content Item, Page, Url Redirections, Sync State (state), or Sitemap.
|
|
17
|
+
* @param {Object} params - The parameters object
|
|
18
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
19
|
+
* @param {String} params.itemType - The type of item being deleted, expected values are `item`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
20
|
+
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
21
|
+
* @param {(String|Number)} params.itemID - The ID of the item being deleted - this could be a string or number depending on the itemType
|
|
22
|
+
* @returns {Void}
|
|
23
|
+
*/
|
|
24
|
+
const deleteItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
25
|
+
console.log(`Console Interface: deleteItem has been called`);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The function to handle updating and placing a Content Item into a "list" so that you can handle querying a collection of items.
|
|
30
|
+
* @param {Object} params - The parameters object
|
|
31
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
32
|
+
* @param {Object} params.item - The object representing the Content Item
|
|
33
|
+
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
34
|
+
* @param {(String|Number)} params.itemID - The ID of the item being updated - this could be a string or number depending on the itemType
|
|
35
|
+
* @param {String} params.referenceName - The reference name of the Content List that this Content Item should be added to
|
|
36
|
+
* @param {String} params.definitionName - The Model name that the Content Item is based on
|
|
37
|
+
* @returns {Void}
|
|
38
|
+
*/
|
|
39
|
+
const mergeItemToList = async ({ options, item, languageCode, itemID, referenceName, definitionName }) => {
|
|
40
|
+
console.log(`Console Interface: mergeItemToList has been called`);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The function to handle retrieving a Content Item, Page, Url Redirections, Sync State (state), or Sitemap
|
|
45
|
+
* @param {Object} params - The parameters object
|
|
46
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
47
|
+
* @param {String} params.itemType - The type of item being accessed, expected values are `item`, `list`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
48
|
+
* @param {String} params.languageCode - The locale code associated to the item being accessed
|
|
49
|
+
* @param {(String|Number)} params.itemID - The ID of the item being accessed - this could be a string or number depending on the itemType
|
|
50
|
+
* @returns {Object}
|
|
51
|
+
*/
|
|
52
|
+
const getItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
53
|
+
console.log(`Console Interface: getItem has been called`)
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The function to handle clearing the cache of synchronized data from the CMS
|
|
58
|
+
* @param {Object} params - The parameters object
|
|
59
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
60
|
+
* @returns {Void}
|
|
61
|
+
*/
|
|
62
|
+
const clearItems = async ({ options }) => {
|
|
63
|
+
console.log(`Console Interface: clearItem has been called`)
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
saveItem,
|
|
69
|
+
deleteItem,
|
|
70
|
+
mergeItemToList,
|
|
71
|
+
getItem,
|
|
72
|
+
clearItems
|
|
73
73
|
}
|
|
@@ -1,199 +1,202 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const os = require('os')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const {sleep} = require("./util")
|
|
5
|
-
const { lockSync, unlockSync, checkSync, check } = require("proper-lockfile")
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
require("dotenv").config({
|
|
9
|
-
path: `.env.${process.env.NODE_ENV}`,
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The function to handle saving/updating an item to your storage. This could be a Content Item, Page, Url Redirections, Sync State (state), or Sitemap.
|
|
14
|
-
* @param {Object} params - The parameters object
|
|
15
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
16
|
-
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
17
|
-
* @param {Object} params.item - The object representing the Content Item, Page, Url Redirections, Sync State (state), or Sitemap that needs to be saved/updated
|
|
18
|
-
* @param {String} params.itemType - The type of item being saved/updated, expected values are `item`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
19
|
-
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
20
|
-
* @param {(String|Number)} params.itemID - The ID of the item being saved/updated - this could be a string or number depending on the itemType
|
|
21
|
-
* @returns {Void}
|
|
22
|
-
*/
|
|
23
|
-
const saveItem = async ({ options, item, itemType, languageCode, itemID }) => {
|
|
24
|
-
|
|
25
|
-
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
26
|
-
|
|
27
|
-
let dirPath = path.dirname(filePath);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (!fs.existsSync(dirPath)) {
|
|
31
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
let json = JSON.stringify(item);
|
|
35
|
-
fs.writeFileSync(filePath, json);
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* The function to handle deleting an item to your storage. This could be a Content Item, Page, Url Redirections, Sync State (state), or Sitemap.
|
|
39
|
-
* @param {Object} params - The parameters object
|
|
40
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
41
|
-
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
42
|
-
* @param {String} params.itemType - The type of item being deleted, expected values are `item`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
43
|
-
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
44
|
-
* @param {(String|Number)} params.itemID - The ID of the item being deleted - this could be a string or number depending on the itemType
|
|
45
|
-
* @returns {Void}
|
|
46
|
-
*/
|
|
47
|
-
const deleteItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
48
|
-
|
|
49
|
-
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
50
|
-
|
|
51
|
-
if (fs.existsSync(filePath)) {
|
|
52
|
-
fs.unlinkSync(filePath);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* The function to handle updating and placing a Content Item into a "list" so that you can handle querying a collection of items.
|
|
58
|
-
* @param {Object} params - The parameters object
|
|
59
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
60
|
-
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
61
|
-
* @param {Object} params.item - The object representing the Content Item
|
|
62
|
-
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
63
|
-
* @param {(String|Number)} params.itemID - The ID of the item being updated - this could be a string or number depending on the itemType
|
|
64
|
-
* @param {String} params.referenceName - The reference name of the Content List that this Content Item should be added to
|
|
65
|
-
* @param {String} params.definitionName - The Model name that the Content Item is based on
|
|
66
|
-
* @returns {Void}
|
|
67
|
-
*/
|
|
68
|
-
const mergeItemToList = async ({ options, item, languageCode, itemID, referenceName, definitionName }) => {
|
|
69
|
-
|
|
70
|
-
let contentList = await getItem({ options, itemType: "list", languageCode, itemID: referenceName });
|
|
71
|
-
|
|
72
|
-
if (contentList == null) {
|
|
73
|
-
//initialize the list
|
|
74
|
-
contentList = [item];
|
|
75
|
-
} else {
|
|
76
|
-
//replace the item...
|
|
77
|
-
const cIndex = contentList.findIndex((ci) => {
|
|
78
|
-
return ci.contentID === itemID;
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
if (item.properties.state === 3) {
|
|
82
|
-
//*** deleted item (remove from the list) ***
|
|
83
|
-
if (cIndex >= 0) {
|
|
84
|
-
//remove the item
|
|
85
|
-
contentList.splice(cIndex, 1);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
} else {
|
|
89
|
-
//*** regular item (merge) ***
|
|
90
|
-
if (cIndex >= 0) {
|
|
91
|
-
//replace the existing item
|
|
92
|
-
contentList[cIndex] = item;
|
|
93
|
-
} else {
|
|
94
|
-
//and it to the end of the
|
|
95
|
-
contentList.push(item);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
await saveItem({ options, item: contentList, itemType: "list", languageCode, itemID: referenceName });
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* The function to handle retrieving a Content Item, Page, Url Redirections, Sync State (state), or Sitemap
|
|
104
|
-
* @param {Object} params - The parameters object
|
|
105
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
106
|
-
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
107
|
-
* @param {String} params.itemType - The type of item being accessed, expected values are `item`, `list`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
108
|
-
* @param {String} params.languageCode - The locale code associated to the item being accessed
|
|
109
|
-
* @param {(String|Number)} params.itemID - The ID of the item being accessed - this could be a string or number depending on the itemType
|
|
110
|
-
* @returns {Object}
|
|
111
|
-
*/
|
|
112
|
-
const getItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
113
|
-
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
114
|
-
|
|
115
|
-
if (!fs.existsSync(filePath)) return null;
|
|
116
|
-
|
|
117
|
-
let json = fs.readFileSync(filePath, 'utf8');
|
|
118
|
-
return JSON.parse(json);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* The function to handle clearing the cache of synchronized data from the CMS
|
|
123
|
-
* @param {Object} params - The parameters object
|
|
124
|
-
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
125
|
-
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
126
|
-
* @returns {Void}
|
|
127
|
-
*/
|
|
128
|
-
const clearItems = async ({ options }) => {
|
|
129
|
-
fs.rmdirSync(options.rootPath, { recursive: true })
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* The function to handle multi-threaded Syncs that may be happening at the same time. If you need to prevent a sync from happening and let it wait until another sync has finished use this.
|
|
136
|
-
* @returns {Promise}
|
|
137
|
-
*/
|
|
138
|
-
const mutexLock = async () => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const dir = os.tmpdir();
|
|
142
|
-
const lockFile = `${dir}/${"agility-sync"}.mutex`
|
|
143
|
-
if (! fs.existsSync(lockFile)) {
|
|
144
|
-
fs.writeFileSync(lockFile, "agility-sync");
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
//THE LOCK IS ALREADY HELD - WAIT UP!
|
|
148
|
-
await waitOnLock(lockFile)
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
return lockSync(lockFile)
|
|
152
|
-
} catch (err) {
|
|
153
|
-
if (`${err}`.indexOf("Lock file is already being held") !== -1) {
|
|
154
|
-
|
|
155
|
-
//this error happens when 2 processes try to get a lock at the EXACT same time (very rare)
|
|
156
|
-
await sleep(100)
|
|
157
|
-
await waitOnLock(lockFile)
|
|
158
|
-
|
|
159
|
-
try {
|
|
160
|
-
return lockSync(lockFile)
|
|
161
|
-
} catch (e2) {
|
|
162
|
-
if (`${err}`.indexOf("Lock file is already being held") !== -1) {
|
|
163
|
-
|
|
164
|
-
//this error happens when 2 processes try to get a lock at the EXACT same time (very rare)
|
|
165
|
-
await sleep(100)
|
|
166
|
-
await waitOnLock(lockFile)
|
|
167
|
-
return lockSync(lockFile)
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
throw Error("The mutex lock could not be obtained.")
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
//private function to get a wait on a lock file
|
|
179
|
-
const waitOnLock = async (lockFile) => {
|
|
180
|
-
while (await check(lockFile)) {
|
|
181
|
-
await sleep(100)
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
//private function to get path of an item
|
|
186
|
-
const getFilePath = ({ options, itemType, languageCode, itemID }) => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const os = require('os')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const {sleep} = require("./util")
|
|
5
|
+
const { lockSync, unlockSync, checkSync, check } = require("proper-lockfile")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require("dotenv").config({
|
|
9
|
+
path: `.env.${process.env.NODE_ENV}`,
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The function to handle saving/updating an item to your storage. This could be a Content Item, Page, Url Redirections, Sync State (state), or Sitemap.
|
|
14
|
+
* @param {Object} params - The parameters object
|
|
15
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
16
|
+
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
17
|
+
* @param {Object} params.item - The object representing the Content Item, Page, Url Redirections, Sync State (state), or Sitemap that needs to be saved/updated
|
|
18
|
+
* @param {String} params.itemType - The type of item being saved/updated, expected values are `item`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
19
|
+
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
20
|
+
* @param {(String|Number)} params.itemID - The ID of the item being saved/updated - this could be a string or number depending on the itemType
|
|
21
|
+
* @returns {Void}
|
|
22
|
+
*/
|
|
23
|
+
const saveItem = async ({ options, item, itemType, languageCode, itemID }) => {
|
|
24
|
+
|
|
25
|
+
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
26
|
+
|
|
27
|
+
let dirPath = path.dirname(filePath);
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if (!fs.existsSync(dirPath)) {
|
|
31
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let json = JSON.stringify(item);
|
|
35
|
+
fs.writeFileSync(filePath, json);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The function to handle deleting an item to your storage. This could be a Content Item, Page, Url Redirections, Sync State (state), or Sitemap.
|
|
39
|
+
* @param {Object} params - The parameters object
|
|
40
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
41
|
+
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
42
|
+
* @param {String} params.itemType - The type of item being deleted, expected values are `item`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
43
|
+
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
44
|
+
* @param {(String|Number)} params.itemID - The ID of the item being deleted - this could be a string or number depending on the itemType
|
|
45
|
+
* @returns {Void}
|
|
46
|
+
*/
|
|
47
|
+
const deleteItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
48
|
+
|
|
49
|
+
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
50
|
+
|
|
51
|
+
if (fs.existsSync(filePath)) {
|
|
52
|
+
fs.unlinkSync(filePath);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The function to handle updating and placing a Content Item into a "list" so that you can handle querying a collection of items.
|
|
58
|
+
* @param {Object} params - The parameters object
|
|
59
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
60
|
+
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
61
|
+
* @param {Object} params.item - The object representing the Content Item
|
|
62
|
+
* @param {String} params.languageCode - The locale code associated to the item being saved/updated
|
|
63
|
+
* @param {(String|Number)} params.itemID - The ID of the item being updated - this could be a string or number depending on the itemType
|
|
64
|
+
* @param {String} params.referenceName - The reference name of the Content List that this Content Item should be added to
|
|
65
|
+
* @param {String} params.definitionName - The Model name that the Content Item is based on
|
|
66
|
+
* @returns {Void}
|
|
67
|
+
*/
|
|
68
|
+
const mergeItemToList = async ({ options, item, languageCode, itemID, referenceName, definitionName }) => {
|
|
69
|
+
|
|
70
|
+
let contentList = await getItem({ options, itemType: "list", languageCode, itemID: referenceName });
|
|
71
|
+
|
|
72
|
+
if (contentList == null) {
|
|
73
|
+
//initialize the list
|
|
74
|
+
contentList = [item];
|
|
75
|
+
} else {
|
|
76
|
+
//replace the item...
|
|
77
|
+
const cIndex = contentList.findIndex((ci) => {
|
|
78
|
+
return ci.contentID === itemID;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (item.properties.state === 3) {
|
|
82
|
+
//*** deleted item (remove from the list) ***
|
|
83
|
+
if (cIndex >= 0) {
|
|
84
|
+
//remove the item
|
|
85
|
+
contentList.splice(cIndex, 1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
} else {
|
|
89
|
+
//*** regular item (merge) ***
|
|
90
|
+
if (cIndex >= 0) {
|
|
91
|
+
//replace the existing item
|
|
92
|
+
contentList[cIndex] = item;
|
|
93
|
+
} else {
|
|
94
|
+
//and it to the end of the
|
|
95
|
+
contentList.push(item);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
await saveItem({ options, item: contentList, itemType: "list", languageCode, itemID: referenceName });
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The function to handle retrieving a Content Item, Page, Url Redirections, Sync State (state), or Sitemap
|
|
104
|
+
* @param {Object} params - The parameters object
|
|
105
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
106
|
+
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
107
|
+
* @param {String} params.itemType - The type of item being accessed, expected values are `item`, `list`, `page`, `sitemap`, `nestedsitemap`, `state`, `urlredirections`
|
|
108
|
+
* @param {String} params.languageCode - The locale code associated to the item being accessed
|
|
109
|
+
* @param {(String|Number)} params.itemID - The ID of the item being accessed - this could be a string or number depending on the itemType
|
|
110
|
+
* @returns {Object}
|
|
111
|
+
*/
|
|
112
|
+
const getItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
113
|
+
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
114
|
+
|
|
115
|
+
if (!fs.existsSync(filePath)) return null;
|
|
116
|
+
|
|
117
|
+
let json = fs.readFileSync(filePath, 'utf8');
|
|
118
|
+
return JSON.parse(json);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The function to handle clearing the cache of synchronized data from the CMS
|
|
123
|
+
* @param {Object} params - The parameters object
|
|
124
|
+
* @param {Object} params.options - A flexible object that can contain any properties specifically related to this interface
|
|
125
|
+
* @param {String} params.options.rootPath - The path to store/access the content as JSON
|
|
126
|
+
* @returns {Void}
|
|
127
|
+
*/
|
|
128
|
+
const clearItems = async ({ options }) => {
|
|
129
|
+
fs.rmdirSync(options.rootPath, { recursive: true })
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The function to handle multi-threaded Syncs that may be happening at the same time. If you need to prevent a sync from happening and let it wait until another sync has finished use this.
|
|
136
|
+
* @returns {Promise}
|
|
137
|
+
*/
|
|
138
|
+
const mutexLock = async () => {
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
const dir = os.tmpdir();
|
|
142
|
+
const lockFile = `${dir}/${"agility-sync"}.mutex`
|
|
143
|
+
if (! fs.existsSync(lockFile)) {
|
|
144
|
+
fs.writeFileSync(lockFile, "agility-sync");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
//THE LOCK IS ALREADY HELD - WAIT UP!
|
|
148
|
+
await waitOnLock(lockFile)
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
return lockSync(lockFile)
|
|
152
|
+
} catch (err) {
|
|
153
|
+
if (`${err}`.indexOf("Lock file is already being held") !== -1) {
|
|
154
|
+
|
|
155
|
+
//this error happens when 2 processes try to get a lock at the EXACT same time (very rare)
|
|
156
|
+
await sleep(100)
|
|
157
|
+
await waitOnLock(lockFile)
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
return lockSync(lockFile)
|
|
161
|
+
} catch (e2) {
|
|
162
|
+
if (`${err}`.indexOf("Lock file is already being held") !== -1) {
|
|
163
|
+
|
|
164
|
+
//this error happens when 2 processes try to get a lock at the EXACT same time (very rare)
|
|
165
|
+
await sleep(100)
|
|
166
|
+
await waitOnLock(lockFile)
|
|
167
|
+
return lockSync(lockFile)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
throw Error("The mutex lock could not be obtained.")
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
//private function to get a wait on a lock file
|
|
179
|
+
const waitOnLock = async (lockFile) => {
|
|
180
|
+
while (await check(lockFile)) {
|
|
181
|
+
await sleep(100)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
//private function to get path of an item
|
|
186
|
+
const getFilePath = ({ options, itemType, languageCode, itemID }) => {
|
|
187
|
+
if(typeof itemID === 'string' || itemID instanceof String){
|
|
188
|
+
itemID = itemID.replace(/[^a-zA-Z ]/g, "");
|
|
189
|
+
}
|
|
190
|
+
const fileName = `${itemID}.json`;
|
|
191
|
+
return path.join(options.rootPath, languageCode, itemType, fileName);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
module.exports = {
|
|
196
|
+
saveItem,
|
|
197
|
+
deleteItem,
|
|
198
|
+
mergeItemToList,
|
|
199
|
+
getItem,
|
|
200
|
+
clearItems,
|
|
201
|
+
mutexLock
|
|
199
202
|
}
|