@contentstack/datasync-manager 2.0.10 → 2.1.1
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/README.md +17 -0
- package/dist/config.js +5 -0
- package/dist/core/index.js +71 -6
- package/dist/core/plugins.js +43 -37
- package/dist/util/index.js +6 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -154,6 +154,23 @@ And here's an example to get you started:
|
|
|
154
154
|
}
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
+
### Environment Variables
|
|
158
|
+
|
|
159
|
+
The following environment variables can be used to customize the behavior of Contentstack DataSync Manager:
|
|
160
|
+
|
|
161
|
+
| Variable | Description | Default |
|
|
162
|
+
|--------------|-----------------------------------------------------------------------------|------------------------|
|
|
163
|
+
| `TOKEN_PATH` | Path to the directory where token/checkpoint/ledger files are stored. | Project root directory |
|
|
164
|
+
| `PLUGIN_PATH`| Path to the directory where plugins are loaded from. | Project root directory |
|
|
165
|
+
| `NODE_ENV` | Node.js environment (affects config/environment selection). | `development` |
|
|
166
|
+
| `SYNC_ENV` | Overrides the environment used for sync operations. | Value of `NODE_ENV` |
|
|
167
|
+
| `KILLDURATION`| Time (in ms) before the process is forcefully killed (overrides config). | Value from config |
|
|
168
|
+
|
|
169
|
+
**Note:**
|
|
170
|
+
- `TOKEN_PATH` is especially useful for storing token data in a custom directory (e.g., for selective re-syncing based on timestamps).
|
|
171
|
+
- If a relative path is provided, it is resolved from the project root.
|
|
172
|
+
- These variables can be set in your shell or in your process manager configuration.
|
|
173
|
+
|
|
157
174
|
### Further Reading
|
|
158
175
|
|
|
159
176
|
- [Getting started with Contentstack DataSync](https://www.contentstack.com/docs/guide/synchronization/contentstack-datasync)
|
package/dist/config.js
CHANGED
|
@@ -129,4 +129,9 @@ exports.config = {
|
|
|
129
129
|
saveFailedItems: true,
|
|
130
130
|
saveFilteredItems: true,
|
|
131
131
|
},
|
|
132
|
+
checkpoint: {
|
|
133
|
+
enabled: false,
|
|
134
|
+
filePath: ".checkpoint",
|
|
135
|
+
preserve: false // Set to true if you want to preserve the checkpoint file during clean operation
|
|
136
|
+
},
|
|
132
137
|
};
|
package/dist/core/index.js
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
7
25
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
26
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
27
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -18,6 +36,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
18
36
|
};
|
|
19
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
38
|
exports.unlock = exports.lock = exports.poke = exports.pop = exports.unshift = exports.push = exports.init = void 0;
|
|
39
|
+
/*!
|
|
40
|
+
* Contentstack DataSync Manager
|
|
41
|
+
* Copyright (c) 2019 Contentstack LLC
|
|
42
|
+
* MIT Licensed
|
|
43
|
+
*/
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
21
46
|
const debug_1 = __importDefault(require("debug"));
|
|
22
47
|
const events_1 = require("events");
|
|
23
48
|
const lodash_1 = require("lodash");
|
|
@@ -30,6 +55,7 @@ const promise_map_1 = require("../util/promise.map");
|
|
|
30
55
|
const inet_1 = require("./inet");
|
|
31
56
|
const q_1 = require("./q");
|
|
32
57
|
const token_management_1 = require("./token-management");
|
|
58
|
+
const helper_1 = require("../plugins/helper");
|
|
33
59
|
const debug = (0, debug_1.default)('sync-core');
|
|
34
60
|
const emitter = new events_1.EventEmitter();
|
|
35
61
|
const formattedAssetType = '_assets';
|
|
@@ -55,6 +81,7 @@ const init = (contentStore, assetStore) => {
|
|
|
55
81
|
return new Promise((resolve, reject) => {
|
|
56
82
|
try {
|
|
57
83
|
Contentstack = config.contentstack;
|
|
84
|
+
const checkPointConfig = config.checkpoint;
|
|
58
85
|
const paths = config.paths;
|
|
59
86
|
const environment = Contentstack.environment || process.env.NODE_ENV || 'development';
|
|
60
87
|
debug(`Environment: ${environment}`);
|
|
@@ -64,6 +91,7 @@ const init = (contentStore, assetStore) => {
|
|
|
64
91
|
limit: config.syncManager.limit,
|
|
65
92
|
},
|
|
66
93
|
};
|
|
94
|
+
loadCheckpoint(checkPointConfig, paths);
|
|
67
95
|
if (typeof Contentstack.sync_token === 'string' && Contentstack.sync_token.length !== 0) {
|
|
68
96
|
request.qs.sync_token = Contentstack.sync_token;
|
|
69
97
|
}
|
|
@@ -94,6 +122,37 @@ const init = (contentStore, assetStore) => {
|
|
|
94
122
|
});
|
|
95
123
|
};
|
|
96
124
|
exports.init = init;
|
|
125
|
+
const loadCheckpoint = (checkPointConfig, paths) => {
|
|
126
|
+
if (!(checkPointConfig === null || checkPointConfig === void 0 ? void 0 : checkPointConfig.enabled))
|
|
127
|
+
return;
|
|
128
|
+
// Try reading checkpoint from primary path
|
|
129
|
+
let checkpoint = readHiddenFile(paths.checkpoint);
|
|
130
|
+
// Fallback to filePath in config if not found
|
|
131
|
+
if (!checkpoint) {
|
|
132
|
+
const fallbackPath = path.join((0, helper_1.sanitizePath)(__dirname), (0, helper_1.sanitizePath)(checkPointConfig.filePath || ".checkpoint"));
|
|
133
|
+
checkpoint = readHiddenFile(fallbackPath);
|
|
134
|
+
}
|
|
135
|
+
// Set sync token if checkpoint is found
|
|
136
|
+
if (checkpoint) {
|
|
137
|
+
debug("Found sync token in checkpoint file:", checkpoint);
|
|
138
|
+
Contentstack.sync_token = checkpoint.token;
|
|
139
|
+
debug("Using sync token:", Contentstack.sync_token);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
function readHiddenFile(filePath) {
|
|
143
|
+
try {
|
|
144
|
+
if (!fs.existsSync(filePath)) {
|
|
145
|
+
logger_1.logger.error("File does not exist:", filePath);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const data = fs.readFileSync(filePath, "utf8");
|
|
149
|
+
return JSON.parse(data);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
logger_1.logger.error("Error reading file:", err);
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
97
156
|
const push = (data) => {
|
|
98
157
|
Q.emit('push', data);
|
|
99
158
|
};
|
|
@@ -251,6 +310,7 @@ const fire = (req) => {
|
|
|
251
310
|
});
|
|
252
311
|
return (0, promise_map_1.map)(contentTypeUids, (uid) => {
|
|
253
312
|
return new Promise((mapResolve, mapReject) => {
|
|
313
|
+
debug(`API called with for content type: ${uid}`);
|
|
254
314
|
return (0, api_1.get)({
|
|
255
315
|
path: `${Contentstack.apis.content_types}${uid}`,
|
|
256
316
|
qs: {
|
|
@@ -271,6 +331,7 @@ const fire = (req) => {
|
|
|
271
331
|
err.code = 'ICTC';
|
|
272
332
|
return mapReject(err);
|
|
273
333
|
}).catch((error) => {
|
|
334
|
+
debug('Error [map] fetching content type schema:', error);
|
|
274
335
|
if ((0, inet_1.netConnectivityIssues)(error)) {
|
|
275
336
|
flag.SQ = false;
|
|
276
337
|
}
|
|
@@ -286,14 +347,17 @@ const fire = (req) => {
|
|
|
286
347
|
flag.SQ = false;
|
|
287
348
|
}
|
|
288
349
|
// Errorred while fetching content type schema
|
|
350
|
+
debug('Error [mapResolve]:', error);
|
|
289
351
|
return reject(error);
|
|
290
352
|
});
|
|
291
353
|
}).catch((processError) => {
|
|
354
|
+
debug('Error [filterItems]:', processError);
|
|
292
355
|
return reject(processError);
|
|
293
356
|
});
|
|
294
357
|
}
|
|
295
358
|
return postProcess(req, syncResponse)
|
|
296
|
-
.then(resolve)
|
|
359
|
+
.then(resolve)
|
|
360
|
+
.catch(reject);
|
|
297
361
|
}).catch((error) => {
|
|
298
362
|
debug('Error [fire]', error);
|
|
299
363
|
if ((0, inet_1.netConnectivityIssues)(error)) {
|
|
@@ -335,6 +399,7 @@ const postProcess = (req, resp) => {
|
|
|
335
399
|
flag.SQ = false;
|
|
336
400
|
return resolve('');
|
|
337
401
|
}
|
|
402
|
+
debug(`Re-Fire called with: ${JSON.stringify(req)}`);
|
|
338
403
|
return fire(req)
|
|
339
404
|
.then(resolve)
|
|
340
405
|
.catch(reject);
|
package/dist/core/plugins.js
CHANGED
|
@@ -22,47 +22,53 @@ const pluginMethods = ['beforeSync', 'afterSync'];
|
|
|
22
22
|
*/
|
|
23
23
|
const load = (config) => {
|
|
24
24
|
debug('Plugins load called');
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
pluginInstances.external[pluginMethod] = pluginInstances[pluginMethod] || [];
|
|
32
|
-
pluginInstances.internal[pluginMethod] = pluginInstances[pluginMethod] || [];
|
|
33
|
-
});
|
|
34
|
-
plugins.forEach((plugin) => {
|
|
35
|
-
(0, validations_1.validatePlugin)(plugin);
|
|
36
|
-
const pluginName = plugin.name;
|
|
37
|
-
const slicedName = pluginName.slice(0, 13);
|
|
38
|
-
let isInternal = false;
|
|
39
|
-
if (slicedName === '_cs_internal_') {
|
|
40
|
-
isInternal = true;
|
|
41
|
-
}
|
|
42
|
-
const pluginPath = (0, index_1.normalizePluginPath)(config, plugin, isInternal);
|
|
43
|
-
const Plugin = require(pluginPath);
|
|
44
|
-
Plugin.options = plugin.options || {};
|
|
45
|
-
// execute/initiate plugin
|
|
46
|
-
Plugin();
|
|
25
|
+
try {
|
|
26
|
+
const pluginInstances = {
|
|
27
|
+
external: {},
|
|
28
|
+
internal: {},
|
|
29
|
+
};
|
|
30
|
+
const plugins = config.plugins || [];
|
|
47
31
|
pluginMethods.forEach((pluginMethod) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
32
|
+
pluginInstances.external[pluginMethod] = pluginInstances[pluginMethod] || [];
|
|
33
|
+
pluginInstances.internal[pluginMethod] = pluginInstances[pluginMethod] || [];
|
|
34
|
+
});
|
|
35
|
+
plugins.forEach((plugin) => {
|
|
36
|
+
(0, validations_1.validatePlugin)(plugin);
|
|
37
|
+
const pluginName = plugin.name;
|
|
38
|
+
const slicedName = pluginName.slice(0, 13);
|
|
39
|
+
let isInternal = false;
|
|
40
|
+
if (slicedName === '_cs_internal_') {
|
|
41
|
+
isInternal = true;
|
|
42
|
+
}
|
|
43
|
+
const pluginPath = (0, index_1.normalizePluginPath)(config, plugin, isInternal);
|
|
44
|
+
const Plugin = require(pluginPath);
|
|
45
|
+
Plugin.options = plugin.options || {};
|
|
46
|
+
// execute/initiate plugin
|
|
47
|
+
Plugin();
|
|
48
|
+
pluginMethods.forEach((pluginMethod) => {
|
|
49
|
+
if ((0, lodash_1.hasIn)(Plugin, pluginMethod)) {
|
|
50
|
+
if (plugin.disabled) {
|
|
51
|
+
// do nothing
|
|
52
|
+
}
|
|
53
|
+
else if (isInternal) {
|
|
54
|
+
pluginInstances.internal[pluginMethod].push(Plugin[pluginMethod]);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
pluginInstances.external[pluginMethod].push(Plugin[pluginMethod]);
|
|
58
|
+
}
|
|
59
|
+
debug(`${pluginMethod} loaded from ${pluginName} successfully!`);
|
|
54
60
|
}
|
|
55
61
|
else {
|
|
56
|
-
|
|
62
|
+
debug(`${pluginMethod} not found in ${pluginName}`);
|
|
57
63
|
}
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
debug(`${pluginMethod} not found in ${pluginName}`);
|
|
62
|
-
}
|
|
64
|
+
});
|
|
63
65
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
debug('Plugins loaded successfully!');
|
|
67
|
+
return pluginInstances;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
debug('Error while loading plugins:', error);
|
|
71
|
+
throw new Error(`Failed to load plugins: ${error === null || error === void 0 ? void 0 : error.message}`);
|
|
72
|
+
}
|
|
67
73
|
};
|
|
68
74
|
exports.load = load;
|
package/dist/util/index.js
CHANGED
|
@@ -131,8 +131,9 @@ const formatItems = (items, config) => {
|
|
|
131
131
|
items[i]._type = config.contentstack.actions.publish;
|
|
132
132
|
// extra keys
|
|
133
133
|
items[i]._synced_at = time;
|
|
134
|
-
|
|
135
|
-
items[i] = (0, lodash_1.merge)(items[i], items[i].data);
|
|
134
|
+
const assetLocale = items[i].data.publish_details.locale;
|
|
135
|
+
items[i] = (0, lodash_1.merge)((0, lodash_1.cloneDeep)(items[i]), items[i].data);
|
|
136
|
+
items[i].locale = assetLocale;
|
|
136
137
|
break;
|
|
137
138
|
case 'asset_unpublished':
|
|
138
139
|
delete items[i].type;
|
|
@@ -152,8 +153,9 @@ const formatItems = (items, config) => {
|
|
|
152
153
|
items[i]._content_type_uid = items[i].content_type_uid;
|
|
153
154
|
// extra keys
|
|
154
155
|
items[i]._synced_at = time;
|
|
155
|
-
|
|
156
|
-
items[i] = (0, lodash_1.merge)(items[i], items[i].data);
|
|
156
|
+
const entryLocale = items[i].data.publish_details.locale;
|
|
157
|
+
items[i] = (0, lodash_1.merge)((0, lodash_1.cloneDeep)(items[i]), items[i].data);
|
|
158
|
+
items[i].locale = entryLocale;
|
|
157
159
|
break;
|
|
158
160
|
case 'entry_unpublished':
|
|
159
161
|
delete items[i].type;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/datasync-manager",
|
|
3
3
|
"author": "Contentstack LLC <support@contentstack.com>",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.1.1",
|
|
5
5
|
"description": "The primary module of Contentstack DataSync. Syncs Contentstack data with your server using Contentstack Sync API",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"dependencies": {
|