@contentstack/datasync-manager 2.1.2 → 2.2.0

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/dist/api.js CHANGED
@@ -15,6 +15,7 @@ const path_1 = require("path");
15
15
  const querystring_1 = require("querystring");
16
16
  const sanitize_url_1 = require("@braintree/sanitize-url");
17
17
  const fs_1 = require("./util/fs");
18
+ const messages_1 = require("./util/messages");
18
19
  const debug = (0, debug_1.default)('api');
19
20
  let MAX_RETRY_LIMIT;
20
21
  let RETRY_DELAY_BASE = 200; // Default base delay in milliseconds
@@ -71,7 +72,7 @@ const get = (req, RETRY = 1) => {
71
72
  timeout: TIMEOUT, // Configurable timeout to prevent socket hang ups
72
73
  };
73
74
  try {
74
- debug(`${options.method.toUpperCase()}: ${options.path}`);
75
+ debug(messages_1.MESSAGES.API.REQUEST(options.method, options.path));
75
76
  let timeDelay;
76
77
  let body = '';
77
78
  const httpRequest = (0, https_1.request)(options, (response) => {
@@ -79,13 +80,13 @@ const get = (req, RETRY = 1) => {
79
80
  .setEncoding('utf-8')
80
81
  .on('data', (chunk) => body += chunk)
81
82
  .on('end', () => {
82
- debug(`status: ${response.statusCode}.`);
83
+ debug(messages_1.MESSAGES.API.STATUS(response.statusCode));
83
84
  if (response.statusCode >= 200 && response.statusCode <= 399) {
84
85
  return resolve(JSON.parse(body));
85
86
  }
86
87
  else if (response.statusCode === 429) {
87
88
  timeDelay = Math.pow(Math.SQRT2, RETRY) * RETRY_DELAY_BASE;
88
- debug(`API rate limit exceeded. Retrying ${options.path} with ${timeDelay} ms delay`);
89
+ debug(messages_1.MESSAGES.API.RATE_LIMIT(options.path, timeDelay));
89
90
  return setTimeout(() => {
90
91
  return (0, exports.get)(req, RETRY)
91
92
  .then(resolve)
@@ -95,7 +96,7 @@ const get = (req, RETRY = 1) => {
95
96
  else if (response.statusCode >= 500) {
96
97
  // retry, with delay
97
98
  timeDelay = Math.pow(Math.SQRT2, RETRY) * RETRY_DELAY_BASE;
98
- debug(`Retrying ${options.path} with ${timeDelay} ms delay`);
99
+ debug(messages_1.MESSAGES.API.RETRY(options.path, timeDelay));
99
100
  RETRY++;
100
101
  return setTimeout(() => {
101
102
  return (0, exports.get)(req, RETRY)
@@ -104,25 +105,25 @@ const get = (req, RETRY = 1) => {
104
105
  }, timeDelay);
105
106
  }
106
107
  else {
107
- debug(`Request failed\n${JSON.stringify(options)}`);
108
+ debug(messages_1.MESSAGES.API.REQUEST_FAILED(options));
108
109
  return reject(body);
109
110
  }
110
111
  });
111
112
  });
112
113
  // Set socket timeout to handle socket hang ups
113
114
  httpRequest.setTimeout(options.timeout, () => {
114
- debug(`Request timeout for ${options.path || 'unknown'}`);
115
+ debug(messages_1.MESSAGES.API.REQUEST_TIMEOUT(options.path));
115
116
  httpRequest.destroy();
116
117
  reject(new Error('Request timeout'));
117
118
  });
118
119
  // Enhanced error handling for socket hang ups and connection resets
119
120
  httpRequest.on('error', (error) => {
120
121
  var _a;
121
- debug(`Request error for ${options.path || 'unknown'}: ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'} (${(error === null || error === void 0 ? void 0 : error.code) || 'NO_CODE'})`);
122
+ debug(messages_1.MESSAGES.API.REQUEST_ERROR(options.path, error === null || error === void 0 ? void 0 : error.message, error === null || error === void 0 ? void 0 : error.code));
122
123
  // Handle socket hang up and connection reset errors with retry
123
124
  if (((error === null || error === void 0 ? void 0 : error.code) === 'ECONNRESET' || ((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('socket hang up'))) && RETRY <= MAX_RETRY_LIMIT) {
124
125
  timeDelay = Math.pow(Math.SQRT2, RETRY) * RETRY_DELAY_BASE;
125
- debug(`Socket hang up detected. Retrying ${options.path || 'unknown'} with ${timeDelay} ms delay (attempt ${RETRY}/${MAX_RETRY_LIMIT})`);
126
+ debug(messages_1.MESSAGES.API.SOCKET_HANGUP_RETRY(options.path, timeDelay, RETRY, MAX_RETRY_LIMIT));
126
127
  RETRY++;
127
128
  return setTimeout(() => {
128
129
  return (0, exports.get)(req, RETRY)
@@ -51,6 +51,7 @@ const api_1 = require("../api");
51
51
  const fs_1 = require("../util/fs");
52
52
  const index_1 = require("../util/index");
53
53
  const logger_1 = require("../util/logger");
54
+ const messages_1 = require("../util/messages");
54
55
  const promise_map_1 = require("../util/promise.map");
55
56
  const inet_1 = require("./inet");
56
57
  const q_1 = require("./q");
@@ -77,14 +78,14 @@ const init = (contentStore, assetStore) => {
77
78
  config = (0, __1.getConfig)();
78
79
  Q = new q_1.Q(contentStore, assetStore, config);
79
80
  (0, api_1.init)(config.contentstack);
80
- debug('Sync core:start invoked');
81
+ debug(messages_1.MESSAGES.SYNC_CORE.START);
81
82
  return new Promise((resolve, reject) => {
82
83
  try {
83
84
  Contentstack = config.contentstack;
84
85
  const checkPointConfig = config.checkpoint;
85
86
  const paths = config.paths;
86
87
  const environment = Contentstack.environment || process.env.NODE_ENV || 'development';
87
- debug(`Environment: ${environment}`);
88
+ debug(messages_1.MESSAGES.SYNC_CORE.ENVIRONMENT(environment));
88
89
  const request = {
89
90
  qs: {
90
91
  environment,
@@ -134,22 +135,22 @@ const loadCheckpoint = (checkPointConfig, paths) => {
134
135
  }
135
136
  // Set sync token if checkpoint is found
136
137
  if (checkpoint) {
137
- debug("Found sync token in checkpoint file:", checkpoint);
138
+ debug(messages_1.MESSAGES.SYNC_CORE.TOKEN_FOUND, checkpoint);
138
139
  Contentstack.sync_token = checkpoint.token;
139
- debug("Using sync token:", Contentstack.sync_token);
140
+ debug(messages_1.MESSAGES.SYNC_CORE.TOKEN_USING, Contentstack.sync_token);
140
141
  }
141
142
  };
142
143
  function readHiddenFile(filePath) {
143
144
  try {
144
145
  if (!fs.existsSync(filePath)) {
145
- logger_1.logger.error("File does not exist:", filePath);
146
+ logger_1.logger.error(messages_1.MESSAGES.SYNC_CORE.FILE_NOT_FOUND(filePath));
146
147
  return;
147
148
  }
148
149
  const data = fs.readFileSync(filePath, "utf8");
149
150
  return JSON.parse(data);
150
151
  }
151
152
  catch (err) {
152
- logger_1.logger.error("Error reading file:", err);
153
+ logger_1.logger.error(messages_1.MESSAGES.SYNC_CORE.FILE_READ_ERROR(err));
153
154
  return undefined;
154
155
  }
155
156
  }
@@ -170,8 +171,8 @@ exports.pop = pop;
170
171
  */
171
172
  const poke = () => __awaiter(void 0, void 0, void 0, function* () {
172
173
  try {
173
- debug('Invoked poke');
174
- logger_1.logger.info('Received \'contentstack sync\' notification');
174
+ debug(messages_1.MESSAGES.SYNC_CORE.POKE_INVOKED);
175
+ logger_1.logger.info(messages_1.MESSAGES.SYNC_CORE.POKE_NOTIFICATION);
175
176
  if (!flag.lockdown) {
176
177
  flag.WQ = true;
177
178
  return yield check();
@@ -179,7 +180,7 @@ const poke = () => __awaiter(void 0, void 0, void 0, function* () {
179
180
  return null;
180
181
  }
181
182
  catch (error) {
182
- debug('Error [poke]', error);
183
+ debug(messages_1.MESSAGES.SYNC_CORE.POKE_ERROR, error);
183
184
  throw error;
184
185
  }
185
186
  });
@@ -190,12 +191,12 @@ exports.poke = poke;
190
191
  */
191
192
  const check = () => __awaiter(void 0, void 0, void 0, function* () {
192
193
  try {
193
- debug(`Check called. SQ status is ${flag.SQ} and WQ status is ${flag.WQ}`);
194
+ debug(messages_1.MESSAGES.SYNC_CORE.CHECK_CALLED(flag.SQ, flag.WQ));
194
195
  if (!flag.SQ && flag.WQ) {
195
196
  flag.WQ = false;
196
197
  flag.SQ = true;
197
198
  yield sync();
198
- debug(`Sync completed and SQ flag updated. Cooloff duration is ${config.syncManager.cooloff}`);
199
+ debug(messages_1.MESSAGES.SYNC_CORE.CHECK_COMPLETE(config.syncManager.cooloff));
199
200
  setTimeout(() => {
200
201
  flag.SQ = false;
201
202
  emitter.emit('check');
@@ -204,11 +205,11 @@ const check = () => __awaiter(void 0, void 0, void 0, function* () {
204
205
  }
205
206
  catch (error) {
206
207
  logger_1.logger.error(error);
207
- debug('Error [check]', error);
208
+ debug(messages_1.MESSAGES.SYNC_CORE.CHECK_ERROR, error);
208
209
  check().then(() => {
209
- debug('passed [check] error');
210
+ debug(messages_1.MESSAGES.SYNC_CORE.CHECK_RECOVERED);
210
211
  }).catch((error) => {
211
- debug('failed [check] error', error);
212
+ debug(messages_1.MESSAGES.SYNC_CORE.CHECK_FAILED, error);
212
213
  });
213
214
  throw error;
214
215
  }
@@ -218,9 +219,9 @@ const check = () => __awaiter(void 0, void 0, void 0, function* () {
218
219
  */
219
220
  const sync = () => __awaiter(void 0, void 0, void 0, function* () {
220
221
  try {
221
- debug('started [sync]');
222
+ debug(messages_1.MESSAGES.SYNC_CORE.SYNC_STARTED);
222
223
  const tokenObject = yield (0, token_management_1.getToken)();
223
- debug('tokenObject [sync]', tokenObject);
224
+ debug(messages_1.MESSAGES.SYNC_CORE.SYNC_TOKEN_OBJECT, tokenObject);
224
225
  const token = tokenObject;
225
226
  const request = {
226
227
  qs: {
@@ -232,7 +233,7 @@ const sync = () => __awaiter(void 0, void 0, void 0, function* () {
232
233
  return yield fire(request);
233
234
  }
234
235
  catch (error) {
235
- debug('Error [sync]', error);
236
+ debug(messages_1.MESSAGES.SYNC_CORE.SYNC_ERROR, error);
236
237
  throw error;
237
238
  }
238
239
  });
@@ -240,7 +241,7 @@ const sync = () => __awaiter(void 0, void 0, void 0, function* () {
240
241
  * @description Used to lockdown the 'sync' process in case of exceptions
241
242
  */
242
243
  const lock = () => {
243
- debug('Contentstack sync locked..');
244
+ debug(messages_1.MESSAGES.SYNC_CORE.SYNC_LOCKED);
244
245
  flag.lockdown = true;
245
246
  };
246
247
  exports.lock = lock;
@@ -248,7 +249,7 @@ exports.lock = lock;
248
249
  * @description Used to unlock the 'sync' process in case of errors/exceptions
249
250
  */
250
251
  const unlock = (refire) => {
251
- debug('Contentstack sync unlocked..', refire);
252
+ debug(messages_1.MESSAGES.SYNC_CORE.SYNC_UNLOCKED, refire);
252
253
  flag.lockdown = false;
253
254
  if (typeof refire === 'boolean' && refire) {
254
255
  flag.WQ = true;
@@ -266,7 +267,7 @@ exports.unlock = unlock;
266
267
  * @param {Object} req - Contentstack sync API request object
267
268
  */
268
269
  const fire = (req) => {
269
- debug(`Fire called with: ${JSON.stringify(req)}`);
270
+ debug(messages_1.MESSAGES.SYNC_CORE.FIRE_CALLED(req));
270
271
  flag.SQ = true;
271
272
  return new Promise((resolve, reject) => {
272
273
  return (0, api_1.get)(req).then((response) => {
@@ -275,7 +276,7 @@ const fire = (req) => {
275
276
  delete req.qs.sync_token;
276
277
  delete req.path;
277
278
  const syncResponse = response;
278
- debug('Response [fire]', syncResponse.items.length);
279
+ debug(messages_1.MESSAGES.SYNC_CORE.FIRE_COMPLETE(syncResponse.items.length));
279
280
  if (syncResponse.items.length) {
280
281
  return (0, index_1.filterItems)(syncResponse, config).then(() => {
281
282
  if (syncResponse.items.length === 0) {
@@ -310,7 +311,7 @@ const fire = (req) => {
310
311
  });
311
312
  return (0, promise_map_1.map)(contentTypeUids, (uid) => {
312
313
  return new Promise((mapResolve, mapReject) => {
313
- debug(`API called with for content type: ${uid}`);
314
+ debug(messages_1.MESSAGES.SYNC_CORE.API_CALL_CT(uid));
314
315
  return (0, api_1.get)({
315
316
  path: `${Contentstack.apis.content_types}${uid}`,
316
317
  qs: {
@@ -331,7 +332,7 @@ const fire = (req) => {
331
332
  err.code = 'ICTC';
332
333
  return mapReject(err);
333
334
  }).catch((error) => {
334
- debug('Error [map] fetching content type schema:', error);
335
+ debug(messages_1.MESSAGES.SYNC_CORE.ERROR_MAP, error);
335
336
  if ((0, inet_1.netConnectivityIssues)(error)) {
336
337
  flag.SQ = false;
337
338
  }
@@ -347,11 +348,11 @@ const fire = (req) => {
347
348
  flag.SQ = false;
348
349
  }
349
350
  // Errorred while fetching content type schema
350
- debug('Error [mapResolve]:', error);
351
+ debug(messages_1.MESSAGES.SYNC_CORE.ERROR_MAP_RESOLVE, error);
351
352
  return reject(error);
352
353
  });
353
354
  }).catch((processError) => {
354
- debug('Error [filterItems]:', processError);
355
+ debug(messages_1.MESSAGES.SYNC_CORE.ERROR_FILTER_ITEMS, processError);
355
356
  return reject(processError);
356
357
  });
357
358
  }
@@ -359,7 +360,7 @@ const fire = (req) => {
359
360
  .then(resolve)
360
361
  .catch(reject);
361
362
  }).catch((error) => {
362
- debug('Error [fire]', error);
363
+ debug(messages_1.MESSAGES.SYNC_CORE.ERROR_FIRE, error);
363
364
  if ((0, inet_1.netConnectivityIssues)(error)) {
364
365
  flag.SQ = false;
365
366
  }
@@ -387,7 +388,7 @@ const postProcess = (req, resp) => {
387
388
  // re-fire!
388
389
  req.qs[name] = resp[name];
389
390
  if (flag.lockdown) {
390
- logger_1.logger.log('Checkpoint: lockdown has been invoked');
391
+ logger_1.logger.log(messages_1.MESSAGES.SYNC_CORE.CHECKPOINT_LOCKDOWN);
391
392
  flag.requestCache = {
392
393
  params: req,
393
394
  reject,
@@ -399,7 +400,7 @@ const postProcess = (req, resp) => {
399
400
  flag.SQ = false;
400
401
  return resolve('');
401
402
  }
402
- debug(`Re-Fire called with: ${JSON.stringify(req)}`);
403
+ debug(messages_1.MESSAGES.SYNC_CORE.REFIRE_CALLED(req));
403
404
  return fire(req)
404
405
  .then(resolve)
405
406
  .catch(reject);
package/dist/core/inet.js CHANGED
@@ -14,6 +14,7 @@ const dns_socket_1 = __importDefault(require("dns-socket"));
14
14
  const events_1 = require("events");
15
15
  const index_1 = require("../index");
16
16
  const logger_1 = require("../util/logger");
17
+ const messages_1 = require("../util/messages");
17
18
  const index_2 = require("./index");
18
19
  const emitter = new events_1.EventEmitter();
19
20
  const debug = (0, debug_1.default)('inet');
@@ -36,7 +37,7 @@ const init = () => {
36
37
  port = sm.inet.port;
37
38
  dns = sm.inet.dns;
38
39
  currentTimeout = sm.inet.retryTimeout;
39
- debug(`inet initiated - waiting ${currentTimeout} before checking connectivity.`);
40
+ debug(messages_1.MESSAGES.INET.INITIATED(currentTimeout));
40
41
  // start checking for net connectivity, 30 seconds after the app has started
41
42
  setTimeout(exports.checkNetConnectivity, currentTimeout);
42
43
  };
@@ -46,13 +47,13 @@ const checkNetConnectivity = () => {
46
47
  retries: sm.inet.retries,
47
48
  timeout: sm.inet.timeout,
48
49
  });
49
- debug('checking network connectivity');
50
+ debug(messages_1.MESSAGES.INET.CHECKING);
50
51
  socket.query(query, port, dns, (err) => {
51
52
  if (err) {
52
- debug(`errorred.. ${err}`);
53
+ debug(messages_1.MESSAGES.INET.CHECK_FAILED(err));
53
54
  disconnected = true;
54
55
  return socket.destroy(() => {
55
- debug('socket destroyed');
56
+ debug(messages_1.MESSAGES.INET.CLEANUP_ERROR);
56
57
  emitter.emit('disconnected', currentTimeout += sm.inet.retryIncrement);
57
58
  });
58
59
  }
@@ -61,7 +62,7 @@ const checkNetConnectivity = () => {
61
62
  }
62
63
  disconnected = false;
63
64
  return socket.destroy(() => {
64
- debug('socket destroyed');
65
+ debug(messages_1.MESSAGES.INET.CLEANUP_SUCCESS);
65
66
  emitter.emit('ok');
66
67
  });
67
68
  });
@@ -79,11 +80,11 @@ const netConnectivityIssues = (error) => {
79
80
  exports.netConnectivityIssues = netConnectivityIssues;
80
81
  emitter.on('ok', () => {
81
82
  currentTimeout = sm.inet.retryTimeout;
82
- debug(`pinging ${sm.inet.host} in ${sm.inet.timeout} ms`);
83
+ debug(messages_1.MESSAGES.INET.PINGING(sm.inet.host, sm.inet.timeout));
83
84
  setTimeout(exports.checkNetConnectivity, sm.inet.timeout);
84
85
  });
85
86
  emitter.on('disconnected', (timeout) => {
86
- logger_1.logger.warn('Network disconnected');
87
- debug(`pinging ${sm.inet.host} in ${timeout} ms`);
87
+ logger_1.logger.warn(messages_1.MESSAGES.INET.DISCONNECTED);
88
+ debug(messages_1.MESSAGES.INET.PINGING(sm.inet.host, timeout));
88
89
  setTimeout(exports.checkNetConnectivity, timeout);
89
90
  });
@@ -12,6 +12,7 @@ exports.load = void 0;
12
12
  const debug_1 = __importDefault(require("debug"));
13
13
  const lodash_1 = require("lodash");
14
14
  const index_1 = require("../util/index");
15
+ const messages_1 = require("../util/messages");
15
16
  const validations_1 = require("../util/validations");
16
17
  const debug = (0, debug_1.default)('plugins');
17
18
  const pluginMethods = ['beforeSync', 'afterSync'];
@@ -21,7 +22,7 @@ const pluginMethods = ['beforeSync', 'afterSync'];
21
22
  * @returns {Object} pluginInstance - An instance of plugins, with valid registered methods
22
23
  */
23
24
  const load = (config) => {
24
- debug('Plugins load called');
25
+ debug(messages_1.MESSAGES.PLUGINS.LOAD_CALLED);
25
26
  try {
26
27
  const pluginInstances = {
27
28
  external: {},
@@ -56,19 +57,19 @@ const load = (config) => {
56
57
  else {
57
58
  pluginInstances.external[pluginMethod].push(Plugin[pluginMethod]);
58
59
  }
59
- debug(`${pluginMethod} loaded from ${pluginName} successfully!`);
60
+ debug(messages_1.MESSAGES.PLUGINS.METHOD_LOADED(pluginMethod, pluginName));
60
61
  }
61
62
  else {
62
- debug(`${pluginMethod} not found in ${pluginName}`);
63
+ debug(messages_1.MESSAGES.PLUGINS.METHOD_NOT_FOUND(pluginMethod, pluginName));
63
64
  }
64
65
  });
65
66
  });
66
- debug('Plugins loaded successfully!');
67
+ debug(messages_1.MESSAGES.PLUGINS.LOAD_SUCCESS);
67
68
  return pluginInstances;
68
69
  }
69
70
  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}`);
71
+ debug(messages_1.MESSAGES.PLUGINS.LOAD_ERROR, error);
72
+ throw new Error(messages_1.MESSAGES.PLUGINS.LOAD_ERROR_DETAIL(error === null || error === void 0 ? void 0 : error.message));
72
73
  }
73
74
  };
74
75
  exports.load = load;
@@ -12,6 +12,7 @@ exports.configure = void 0;
12
12
  */
13
13
  const index_1 = require("../index");
14
14
  const logger_1 = require("../util/logger");
15
+ const messages_1 = require("../util/messages");
15
16
  const index_2 = require("./index");
16
17
  /**
17
18
  * @description Handles process exit. Stops the current application and manages a graceful shutdown
@@ -21,7 +22,7 @@ const handleExit = (signal) => {
21
22
  (0, index_2.lock)();
22
23
  const { syncManager } = (0, index_1.getConfig)();
23
24
  const killDuration = (process.env.KILLDURATION) ? calculateKillDuration() : syncManager.processTimeout;
24
- logger_1.logger.info(`Received ${signal}. This will shut down the process in ${killDuration}ms..`);
25
+ logger_1.logger.info(messages_1.MESSAGES.PROCESS.SHUTDOWN(signal, killDuration));
25
26
  setTimeout(abort, killDuration);
26
27
  };
27
28
  /**
@@ -32,7 +33,7 @@ const handleExit = (signal) => {
32
33
  * @param {Object} error - Unhandled error object
33
34
  */
34
35
  const unhandledErrors = (error) => {
35
- logger_1.logger.error('Unhandled exception caught. Locking down process for 10s to recover..');
36
+ logger_1.logger.error(messages_1.MESSAGES.PROCESS.UNHANDLED_ERROR);
36
37
  logger_1.logger.error(error);
37
38
  (0, index_2.lock)();
38
39
  setTimeout(() => {
package/dist/core/q.js CHANGED
@@ -24,6 +24,7 @@ const lodash_1 = require("lodash");
24
24
  const _1 = require(".");
25
25
  const index_1 = require("../util/index");
26
26
  const logger_1 = require("../util/logger");
27
+ const messages_1 = require("../util/messages");
27
28
  const series_1 = require("../util/series");
28
29
  const unprocessible_1 = require("../util/unprocessible");
29
30
  const plugins_1 = require("./plugins");
@@ -59,7 +60,7 @@ class Q extends events_1.EventEmitter {
59
60
  this.on('push', this.push);
60
61
  this.on('unshift', this.unshift);
61
62
  instance = this;
62
- debug('Core \'Q\' constructor initiated');
63
+ debug(messages_1.MESSAGES.QUEUE.CONSTRUCTOR);
63
64
  }
64
65
  return instance;
65
66
  }
@@ -69,7 +70,7 @@ class Q extends events_1.EventEmitter {
69
70
  this.iLock = true;
70
71
  (0, _1.lock)();
71
72
  }
72
- debug(`Content type '${data._content_type_uid}' received for '${data._type}'`);
73
+ debug(messages_1.MESSAGES.QUEUE.CONTENT_TYPE_RECEIVED(data._content_type_uid, data._type));
73
74
  this.emit('next');
74
75
  }
75
76
  /**
@@ -82,7 +83,7 @@ class Q extends events_1.EventEmitter {
82
83
  this.iLock = true;
83
84
  (0, _1.lock)();
84
85
  }
85
- debug(`Content type '${data._content_type_uid}' received for '${data._type}'`);
86
+ debug(messages_1.MESSAGES.QUEUE.CONTENT_TYPE_RECEIVED(data._content_type_uid, data._type));
86
87
  this.emit('next');
87
88
  }
88
89
  /**
@@ -95,7 +96,7 @@ class Q extends events_1.EventEmitter {
95
96
  try {
96
97
  notify('error', obj);
97
98
  logger_1.logger.error(obj);
98
- debug(`Error handler called with ${JSON.stringify(obj)}`);
99
+ debug(messages_1.MESSAGES.QUEUE.ERROR_HANDLER_CALLED(obj));
99
100
  if (typeof obj.checkpoint !== 'undefined') {
100
101
  yield (0, token_management_1.saveToken)(obj.checkpoint.name, obj.checkpoint.token);
101
102
  }
@@ -105,7 +106,7 @@ class Q extends events_1.EventEmitter {
105
106
  }
106
107
  catch (error) {
107
108
  // probably, the context could change
108
- logger_1.logger.error('Something went wrong in errorHandler!');
109
+ logger_1.logger.error(messages_1.MESSAGES.QUEUE.ERROR_IN_HANDLER);
109
110
  logger_1.logger.error(error);
110
111
  that.inProgress = false;
111
112
  that.emit('next');
@@ -125,7 +126,7 @@ class Q extends events_1.EventEmitter {
125
126
  (0, _1.unlock)(true);
126
127
  this.iLock = false;
127
128
  }
128
- debug(`Calling 'next'. In progress status is ${this.inProgress}, and Q length is ${this.q.length}`);
129
+ debug(messages_1.MESSAGES.QUEUE.NEXT_CALLED(this.inProgress, this.q.length));
129
130
  if (!this.inProgress && this.q.length) {
130
131
  this.inProgress = true;
131
132
  const item = this.q.shift();
@@ -170,7 +171,7 @@ class Q extends events_1.EventEmitter {
170
171
  checkpoint = data._checkpoint;
171
172
  delete data._checkpoint;
172
173
  }
173
- debug(`Executing: ${JSON.stringify(data)}`);
174
+ debug(messages_1.MESSAGES.QUEUE.EXECUTING(data));
174
175
  const beforeSyncInternalPlugins = [];
175
176
  // re-initializing everytime with const.. avoids memory leaks
176
177
  const beforeSyncPlugins = [];
@@ -208,15 +209,15 @@ class Q extends events_1.EventEmitter {
208
209
  });
209
210
  yield Promise.all(beforeSyncPlugins);
210
211
  }
211
- debug('Before action plugins executed successfully!');
212
+ debug(messages_1.MESSAGES.QUEUE.BEFORE_PLUGINS);
212
213
  yield this.contentStore[action](data);
213
- debug(`Completed '${action}' on connector successfully!`);
214
+ debug(messages_1.MESSAGES.QUEUE.ACTION_COMPLETE(action));
214
215
  if (typeof schema !== 'undefined') {
215
216
  if (branch)
216
217
  schema.branch = branch;
217
218
  yield this.contentStore.updateContentType(schema);
218
219
  }
219
- debug('Connector instance called successfully!');
220
+ debug(messages_1.MESSAGES.QUEUE.CONNECTOR_CALLED);
220
221
  if (this.syncManager.serializePlugins) {
221
222
  this.pluginInstances.external.afterSync.forEach((method) => {
222
223
  afterSyncPlugins.push(() => method(action, transformedData, transformedSchema));
@@ -232,7 +233,7 @@ class Q extends events_1.EventEmitter {
232
233
  if (typeof checkpoint !== 'undefined') {
233
234
  yield (0, token_management_1.saveToken)(checkpoint.name, checkpoint.token);
234
235
  }
235
- debug('After action plugins executed successfully!');
236
+ debug(messages_1.MESSAGES.QUEUE.AFTER_PLUGINS);
236
237
  logger_1.logger.log(`${type}: { content_type: '${contentType}', ${(locale) ? `locale: '${locale}',` : ''} uid: '${uid}'} was completed successfully!`);
237
238
  this.inProgress = false;
238
239
  this.emit('next', data);
@@ -22,6 +22,7 @@ const debug_1 = __importDefault(require("debug"));
22
22
  const index_1 = require("../index");
23
23
  const fs_1 = require("../util/fs");
24
24
  const index_2 = require("../util/index");
25
+ const messages_1 = require("../util/messages");
25
26
  const debug = (0, debug_1.default)('token-management');
26
27
  let counter = 0;
27
28
  /**
@@ -36,12 +37,12 @@ const getToken = () => {
36
37
  const token = config.paths.token;
37
38
  let data = {};
38
39
  if ((0, fs_1.existsSync)(checkpoint)) {
39
- debug(`Checkpoint read: ${checkpoint}`);
40
+ debug(messages_1.MESSAGES.TOKEN.CHECKPOINT_READ(checkpoint));
40
41
  const contents = yield (0, fs_1.readFile)(checkpoint);
41
42
  data = JSON.parse(contents);
42
43
  }
43
44
  else if ((0, fs_1.existsSync)(token)) {
44
- debug(`Token read: ${token}`);
45
+ debug(messages_1.MESSAGES.TOKEN.TOKEN_READ(token));
45
46
  const contents = yield (0, fs_1.readFile)(token);
46
47
  data = JSON.parse(contents);
47
48
  }
@@ -60,7 +61,7 @@ exports.getToken = getToken;
60
61
  * @param {String} type - Token type
61
62
  */
62
63
  const saveToken = (name, token) => {
63
- debug(`Save token invoked with name: ${name}, token: ${token}`);
64
+ debug(messages_1.MESSAGES.TOKEN.SAVE_TOKEN(name));
64
65
  return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
65
66
  try {
66
67
  const config = (0, index_1.getConfig)();
@@ -88,7 +89,7 @@ const saveToken = (name, token) => {
88
89
  counter++;
89
90
  return `${config.paths.ledger}-${counter}`;
90
91
  });
91
- debug(`ledger file: ${file} exists?(${(0, fs_1.existsSync)(file)})`);
92
+ debug(messages_1.MESSAGES.TOKEN.LEDGER_CHECK(file, (0, fs_1.existsSync)(file)));
92
93
  if (!(0, fs_1.existsSync)(file)) {
93
94
  yield (0, fs_1.writeFile)(file, JSON.stringify([obj]));
94
95
  }
@@ -113,7 +114,7 @@ exports.saveToken = saveToken;
113
114
  * @param {String} type - Token type
114
115
  */
115
116
  const saveCheckpoint = (name, token) => __awaiter(void 0, void 0, void 0, function* () {
116
- debug(`Save token invoked with name: ${name}, token: ${token}`);
117
+ debug(messages_1.MESSAGES.TOKEN.SAVE_CHECKPOINT(name));
117
118
  const config = (0, index_1.getConfig)();
118
119
  const path = config.paths.checkpoint;
119
120
  const data = {
package/dist/index.js CHANGED
@@ -29,6 +29,7 @@ Object.defineProperty(exports, "notifications", { enumerable: true, get: functio
29
29
  const build_paths_1 = require("./util/build-paths");
30
30
  const index_2 = require("./util/index");
31
31
  const logger_1 = require("./util/logger");
32
+ const messages_1 = require("./util/messages");
32
33
  const validations_1 = require("./util/validations");
33
34
  const debug = (0, debug_1.default)('sm:index');
34
35
  let assetStoreInstance;
@@ -146,23 +147,25 @@ const start = (config = {}) => {
146
147
  (0, logger_1.setLogger)();
147
148
  (0, process_1.configure)();
148
149
  return assetStore.start(appConfig).then((assetInstance) => {
149
- debug('Asset store instance has returned successfully!');
150
+ debug(messages_1.MESSAGES.INDEX.ASSET_STORE_INIT);
150
151
  (0, validations_1.validateAssetStoreInstance)(assetInstance);
151
152
  assetStoreInstance = assetInstance;
152
153
  return contentStore.start(assetInstance, appConfig);
153
154
  }).then((contentStoreInstance) => {
154
- debug('Content store instance has returned successfully!');
155
+ debug(messages_1.MESSAGES.INDEX.CONTENT_STORE_INIT);
155
156
  (0, validations_1.validateContentStoreInstance)(contentStoreInstance);
156
157
  appConfig = (0, index_2.formatSyncFilters)(appConfig);
157
158
  return (0, index_1.init)(contentStoreInstance, assetStoreInstance);
158
159
  }).then(() => {
159
- debug('Sync Manager initiated successfully!');
160
+ debug(messages_1.MESSAGES.INDEX.SYNC_MANAGER_INIT);
160
161
  listener.register(index_1.poke);
161
162
  // start checking for inet 10 secs after the app has started
162
163
  (0, inet_1.init)();
163
164
  return listener.start(appConfig);
164
- }).then(() => {
165
- logger_1.logger.info('Contentstack sync utility started successfully!');
165
+ }).then((webhookServer) => {
166
+ // Set up webhook listener monitoring and fallback mechanism
167
+ setupWebhookMonitoring(webhookServer);
168
+ logger_1.logger.info(messages_1.MESSAGES.INDEX.SYNC_UTILITY_STARTED);
166
169
  return resolve('');
167
170
  }).catch(reject);
168
171
  }
@@ -180,7 +183,7 @@ exports.start = start;
180
183
  */
181
184
  const debugNotifications = (action) => {
182
185
  return (item) => {
183
- debug(`Notifications: ${action} - ${JSON.stringify(item)}`);
186
+ debug(messages_1.MESSAGES.INDEX.NOTIFICATION(action, item));
184
187
  };
185
188
  };
186
189
  exports.debugNotifications = debugNotifications;
@@ -189,3 +192,63 @@ q_1.notifications
189
192
  .on('unpublish', (0, exports.debugNotifications)('unpublish'))
190
193
  .on('delete', (0, exports.debugNotifications)('delete'))
191
194
  .on('error', (0, exports.debugNotifications)('error'));
195
+ /**
196
+ * Set up webhook listener monitoring and fallback polling mechanism
197
+ * @param {object} webhookServer The webhook server instance
198
+ */
199
+ function setupWebhookMonitoring(webhookServer) {
200
+ const FALLBACK_POLL_INTERVAL = 60000; // 1 minute fallback polling
201
+ let fallbackTimer = null;
202
+ let webhookHealthy = true;
203
+ debug('Webhook monitoring initialized. Server:', !!webhookServer, 'Healthy:', webhookHealthy);
204
+ // Start fallback polling when webhook is unhealthy
205
+ const startFallbackPolling = () => {
206
+ if (fallbackTimer)
207
+ return; // Already running
208
+ logger_1.logger.info(`Starting fallback polling every ${FALLBACK_POLL_INTERVAL}ms`);
209
+ fallbackTimer = setInterval(() => {
210
+ debug('Fallback polling: triggering sync check');
211
+ try {
212
+ (0, index_1.poke)().catch((error) => {
213
+ debug('Fallback polling error:', error);
214
+ });
215
+ }
216
+ catch (error) {
217
+ debug('Fallback polling exception:', error);
218
+ }
219
+ }, FALLBACK_POLL_INTERVAL);
220
+ };
221
+ // Stop fallback polling when webhook is healthy
222
+ const stopFallbackPolling = () => {
223
+ if (fallbackTimer) {
224
+ clearInterval(fallbackTimer);
225
+ fallbackTimer = null;
226
+ logger_1.logger.info('Fallback polling stopped');
227
+ }
228
+ };
229
+ // Webhook activity is tracked via events, no need to wrap poke function
230
+ // Handle process cleanup
231
+ const cleanup = () => {
232
+ if (fallbackTimer) {
233
+ clearInterval(fallbackTimer);
234
+ fallbackTimer = null;
235
+ }
236
+ };
237
+ process.on('SIGINT', cleanup);
238
+ process.on('SIGTERM', cleanup);
239
+ process.on('exit', cleanup);
240
+ // Handle webhook server events if available
241
+ if (listener.getEventEmitter) {
242
+ const webhookEmitter = listener.getEventEmitter();
243
+ webhookEmitter.on('server-error', (error) => {
244
+ logger_1.logger.warn('Webhook server error detected:', error.message);
245
+ webhookHealthy = false;
246
+ startFallbackPolling();
247
+ });
248
+ webhookEmitter.on('reconnect-success', () => {
249
+ logger_1.logger.info('Webhook server reconnected successfully');
250
+ webhookHealthy = true;
251
+ stopFallbackPolling();
252
+ });
253
+ }
254
+ }
package/dist/util/fs.js CHANGED
@@ -16,6 +16,7 @@ Object.defineProperty(exports, "existsSync", { enumerable: true, get: function (
16
16
  const mkdirp_1 = require("mkdirp");
17
17
  const path_1 = require("path");
18
18
  const write_file_atomic_1 = __importDefault(require("write-file-atomic"));
19
+ const messages_1 = require("./messages");
19
20
  const debug = Debug('sm:util-fs');
20
21
  /**
21
22
  * @description A wrapper around nodejs fs module's 'writeFile()'
@@ -24,7 +25,7 @@ const debug = Debug('sm:util-fs');
24
25
  * @returns {Promise} Returns a promise
25
26
  */
26
27
  const writeFile = (filePath, data) => {
27
- debug(`Write file called on ${filePath}`);
28
+ debug(messages_1.MESSAGES.FS.WRITE_FILE(filePath));
28
29
  return new Promise((resolve, reject) => {
29
30
  try {
30
31
  const fileDirectory = (0, path_1.dirname)(filePath);
@@ -50,7 +51,7 @@ exports.writeFile = writeFile;
50
51
  * @returns {Promise} Returns a promise
51
52
  */
52
53
  const readFile = (filePath) => {
53
- debug(`Read file called on ${filePath}`);
54
+ debug(messages_1.MESSAGES.FS.READ_FILE(filePath));
54
55
  return new Promise((resolve, reject) => {
55
56
  try {
56
57
  return (0, fs_1.stat)(filePath, (error, stats) => {
@@ -65,7 +66,7 @@ const readFile = (filePath) => {
65
66
  return resolve(data);
66
67
  });
67
68
  }
68
- const err = new Error(`Invalid 'read' operation on file. Expected ${filePath} to be of type 'file'!`);
69
+ const err = new Error(messages_1.MESSAGES.FS.INVALID_READ(filePath));
69
70
  err.code = 'IOORF';
70
71
  return reject(err);
71
72
  });
@@ -82,11 +83,11 @@ exports.readFile = readFile;
82
83
  * @returns {String} Returns the data that's been read
83
84
  */
84
85
  const readFileSync = (filePath) => {
85
- debug(`Read file sync called on ${filePath}`);
86
+ debug(messages_1.MESSAGES.FS.READ_FILE_SYNC(filePath));
86
87
  if ((0, fs_1.existsSync)(filePath)) {
87
88
  return (0, fs_1.readFileSync)(filePath, { encoding: 'utf-8' });
88
89
  }
89
- const err = new Error(`Invalid 'read' operation on file. Expected ${filePath} to be of type 'file'!`);
90
+ const err = new Error(messages_1.MESSAGES.FS.INVALID_READ(filePath));
90
91
  err.code = 'IOORFS';
91
92
  throw err;
92
93
  };
@@ -97,7 +98,7 @@ exports.readFileSync = readFileSync;
97
98
  * @returns {String} Returns a promise
98
99
  */
99
100
  const mkdir = (path) => {
100
- debug(`mkdir called on ${path}`);
101
+ debug(messages_1.MESSAGES.FS.MKDIR(path));
101
102
  return (0, mkdirp_1.mkdirp)(path)
102
103
  .then(() => '')
103
104
  .catch(error => Promise.reject(error));
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.getSchema = exports.filterUnwantedKeys = exports.normalizePluginPath = exports.getOrSetRTEMarkdownAssets = exports.getFile = exports.markCheckpoint = exports.formatItems = exports.groupItems = exports.formatSyncFilters = exports.filterItems = void 0;
20
+ exports.getSchema = exports.filterUnwantedKeys = exports.normalizePluginPath = exports.getOrSetRTEMarkdownAssets = exports.getFile = exports.markCheckpoint = exports.formatItems = exports.groupItems = exports.formatSyncFilters = exports.filterItems = exports.MESSAGES = void 0;
21
21
  const debug_1 = __importDefault(require("debug"));
22
22
  const lodash_1 = require("lodash");
23
23
  const marked_1 = __importDefault(require("marked"));
@@ -25,10 +25,14 @@ const path_1 = require("path");
25
25
  const index_1 = require("../index");
26
26
  const fs_1 = require("./fs");
27
27
  const logger_1 = require("./logger");
28
+ const messages_1 = require("./messages");
28
29
  const unprocessible_1 = require("./unprocessible");
29
30
  const validations_1 = require("./validations");
30
31
  const helper_1 = require("./../plugins/helper");
31
32
  const debug = (0, debug_1.default)('util:index');
33
+ // Re-export messages for convenience
34
+ var messages_2 = require("./messages");
35
+ Object.defineProperty(exports, "MESSAGES", { enumerable: true, get: function () { return messages_2.MESSAGES; } });
32
36
  const formattedAssetType = '_assets';
33
37
  const formattedContentType = '_content_types';
34
38
  const assetType = 'sys_assets';
@@ -176,8 +180,8 @@ const formatItems = (items, config) => {
176
180
  items[i]._content_type_uid = formattedContentType;
177
181
  break;
178
182
  default:
179
- logger_1.logger.error('Item\'s type did not match any expected case!!');
180
- logger_1.logger.error(JSON.stringify(items[i]));
183
+ logger_1.logger.error(messages_1.MESSAGES.UTIL.ITEM_TYPE_MISMATCH);
184
+ logger_1.logger.error(messages_1.MESSAGES.UTIL.ITEM_SERIALIZED(items[i]));
181
185
  // remove the element from items[i]s
182
186
  items[i].splice(i, 1);
183
187
  i--;
@@ -197,7 +201,7 @@ const markCheckpoint = (groupedItems, syncResponse) => {
197
201
  const tokenValue = syncResponse[tokenName];
198
202
  const contentTypeUids = Object.keys(groupedItems);
199
203
  if (contentTypeUids.length === 1 && contentTypeUids[0] === '_assets') {
200
- debug(`Only assets found in SYNC API response. Last content type is ${contentTypeUids[0]}`);
204
+ debug(messages_1.MESSAGES.UTIL.ONLY_ASSETS(contentTypeUids[0]));
201
205
  const items = groupedItems[contentTypeUids[0]];
202
206
  // find the last item, add checkpoint to it
203
207
  items[items.length - 1]._checkpoint = {
@@ -206,7 +210,7 @@ const markCheckpoint = (groupedItems, syncResponse) => {
206
210
  };
207
211
  }
208
212
  else if (contentTypeUids.length === 1 && contentTypeUids[0] === '_content_types') {
209
- debug(`Only content type events found in SYNC API response. Last content type is ${contentTypeUids[0]}`);
213
+ debug(messages_1.MESSAGES.UTIL.ONLY_CT_EVENTS(contentTypeUids[0]));
210
214
  const items = groupedItems[contentTypeUids[0]];
211
215
  // find the last item, add checkpoint to it
212
216
  items[items.length - 1]._checkpoint = {
@@ -215,7 +219,7 @@ const markCheckpoint = (groupedItems, syncResponse) => {
215
219
  };
216
220
  }
217
221
  else if (contentTypeUids.length === 2 && (contentTypeUids.indexOf('_assets') !== -1 && contentTypeUids.indexOf('_content_types'))) {
218
- debug(`Assets & content types found found in SYNC API response. Last content type is ${contentTypeUids[1]}`);
222
+ debug(messages_1.MESSAGES.UTIL.ASSETS_AND_CT(contentTypeUids[1]));
219
223
  const items = groupedItems[contentTypeUids[1]];
220
224
  // find the last item, add checkpoint to it
221
225
  items[items.length - 1]._checkpoint = {
@@ -225,7 +229,7 @@ const markCheckpoint = (groupedItems, syncResponse) => {
225
229
  }
226
230
  else {
227
231
  const lastContentTypeUid = contentTypeUids[contentTypeUids.length - 1];
228
- debug(`Mixed content types found in SYNC API response. Last content type is ${lastContentTypeUid}`);
232
+ debug(messages_1.MESSAGES.UTIL.MIXED_CT(lastContentTypeUid));
229
233
  const entries = groupedItems[lastContentTypeUid];
230
234
  entries[entries.length - 1]._checkpoint = {
231
235
  name: tokenName,
@@ -257,7 +261,7 @@ const getFile = (file, rotate) => {
257
261
  return resolve(file);
258
262
  }
259
263
  else {
260
- return reject(new Error(`${file} is not of type file`));
264
+ return reject(new Error(messages_1.MESSAGES.UTIL.FILE_NOT_TYPE(file)));
261
265
  }
262
266
  });
263
267
  }
@@ -395,13 +399,13 @@ const normalizePluginPath = (config, plugin, isInternal) => {
395
399
  if (plugin.path && typeof plugin.path === 'string' && plugin.path.length > 0) {
396
400
  if ((0, path_1.isAbsolute)(plugin.path)) {
397
401
  if (!(0, fs_1.existsSync)(plugin.path)) {
398
- throw new Error(`${plugin.path} does not exist!`);
402
+ throw new Error(messages_1.MESSAGES.UTIL.PLUGIN_PATH_NOT_EXIST(plugin.path));
399
403
  }
400
404
  return plugin.path;
401
405
  }
402
406
  pluginPath = (0, path_1.resolve)((0, path_1.join)((0, helper_1.sanitizePath)(config.paths.baseDir), (0, helper_1.sanitizePath)(plugin.name), 'index.js'));
403
407
  if (!(0, fs_1.existsSync)(pluginPath)) {
404
- throw new Error(`${pluginPath} does not exist!`);
408
+ throw new Error(messages_1.MESSAGES.UTIL.PLUGIN_PATH_NOT_EXIST(pluginPath));
405
409
  }
406
410
  return pluginPath;
407
411
  }
@@ -413,7 +417,7 @@ const normalizePluginPath = (config, plugin, isInternal) => {
413
417
  }
414
418
  pluginPath = (0, path_1.resolve)((0, path_1.join)((0, helper_1.sanitizePath)(config.paths.plugin), (0, helper_1.sanitizePath)(plugin.name), 'index.js'));
415
419
  if (!(0, fs_1.existsSync)(pluginPath)) {
416
- throw new Error(`Unable to find plugin: ${JSON.stringify(plugin)}`);
420
+ throw new Error(messages_1.MESSAGES.UTIL.UNABLE_TO_FIND_PLUGIN(plugin));
417
421
  }
418
422
  return pluginPath;
419
423
  };
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /*!
3
+ * Contentstack DataSync Manager
4
+ * Centralized Messages and Logging Constants
5
+ * Copyright (c) 2025 Contentstack LLC
6
+ * MIT Licensed
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ERROR_CODES = exports.LOG_LEVELS = exports.MESSAGES = void 0;
10
+ /**
11
+ * @description Centralized messages for logging and error handling
12
+ * This file contains all user-facing messages, debug logs, and error messages
13
+ * for consistency and easier maintenance.
14
+ */
15
+ exports.MESSAGES = {
16
+ // Network connectivity messages (inet.ts)
17
+ INET: {
18
+ INITIATED: (timeout) => `inet initiated. Waiting ${timeout} ms before checking connectivity.`,
19
+ CHECKING: 'Checking network connectivity...',
20
+ CHECK_FAILED: (err) => `Network connectivity check failed: ${err}`,
21
+ CLEANUP_SUCCESS: 'Network check successful. Cleaning up connection.',
22
+ CLEANUP_ERROR: 'Network check failed. Cleaning up connection.',
23
+ PINGING: (host, timeout) => `Pinging ${host} in ${timeout} ms`,
24
+ DISCONNECTED: 'The network connection was lost.',
25
+ },
26
+ // Process management messages (process.ts)
27
+ PROCESS: {
28
+ SHUTDOWN: (signal, duration) => `Received ${signal}. Shutting down the process in ${duration} ms.`,
29
+ UNHANDLED_ERROR: 'An unexpected error occurred. Locking the process for 10 seconds to recover.',
30
+ },
31
+ // API messages (api.ts)
32
+ API: {
33
+ REQUEST: (method, path) => `${method.toUpperCase()}: ${path}`,
34
+ STATUS: (code) => `Status: ${code}.`,
35
+ RATE_LIMIT: (path, delay) => `API rate limit exceeded. Retrying ${path} after a ${delay} ms delay.`,
36
+ RETRY: (path, delay) => `Retrying ${path} after a ${delay} ms delay.`,
37
+ REQUEST_FAILED: (options) => `Request failed.\n${JSON.stringify(options)}`,
38
+ REQUEST_TIMEOUT: (path) => `Request timeout for ${path || 'unknown'}`,
39
+ REQUEST_ERROR: (path, message, code) => `Request error for ${path || 'unknown'}: ${message || 'Unknown error'} (${code || 'NO_CODE'})`,
40
+ SOCKET_HANGUP_RETRY: (path, delay, attempt, max) => `Socket hang up detected. Retrying ${path || 'unknown'} with ${delay} ms delay (attempt ${attempt}/${max})`,
41
+ },
42
+ // Plugin messages (plugins.ts)
43
+ PLUGINS: {
44
+ LOAD_CALLED: 'Initializing plugin load...',
45
+ METHOD_LOADED: (method, name) => `${method} loaded from ${name} successfully!`,
46
+ METHOD_NOT_FOUND: (method, name) => `${method} not found in ${name}.`,
47
+ LOAD_SUCCESS: 'All plugins loaded successfully.',
48
+ LOAD_ERROR: 'An error occurred while loading plugins.',
49
+ LOAD_ERROR_DETAIL: (message) => `Failed to load plugins: ${message}`,
50
+ },
51
+ // Sync core messages (core/index.ts)
52
+ SYNC_CORE: {
53
+ START: 'Sync core: Start invoked.',
54
+ ENVIRONMENT: (env) => `Current environment: ${env}`,
55
+ TOKEN_FOUND: 'Sync token found in the checkpoint file:',
56
+ TOKEN_USING: 'Using sync token:',
57
+ FILE_NOT_FOUND: (path) => `File not found: ${path}`,
58
+ FILE_READ_ERROR: (err) => `An error occurred while reading the file: ${err}`,
59
+ POKE_INVOKED: 'Poke command invoked.',
60
+ POKE_NOTIFICATION: 'Received "contentstack sync" notification.',
61
+ POKE_ERROR: 'Error during poke operation.',
62
+ CHECK_CALLED: (sqStatus, wqStatus) => `Check initiated. SQ status: ${sqStatus}, WQ status: ${wqStatus}.`,
63
+ CHECK_COMPLETE: (cooloff) => `Sync completed. SQ flag updated. Cooloff duration: ${cooloff}.`,
64
+ CHECK_ERROR: 'Error during check operation.',
65
+ CHECK_RECOVERED: 'Check recovered from errors.',
66
+ CHECK_FAILED: 'Check failed due to an error.',
67
+ SYNC_STARTED: 'Sync process started.',
68
+ SYNC_TOKEN_OBJECT: 'Token object received for sync.',
69
+ SYNC_ERROR: 'Error during sync operation.',
70
+ SYNC_LOCKED: 'Contentstack sync is locked.',
71
+ SYNC_UNLOCKED: 'Contentstack sync is unlocked.',
72
+ FIRE_CALLED: (req) => `Fire operation triggered with: ${JSON.stringify(req)}`,
73
+ FIRE_COMPLETE: (itemCount) => `Fire operation completed. Items received: ${itemCount}.`,
74
+ API_CALL_CT: (uid) => `API call initiated for content type: ${uid}.`,
75
+ ERROR_MAP: 'Error [map]: Failed to fetch content type schema.',
76
+ ERROR_MAP_RESOLVE: 'Error [mapResolve]: Unable to resolve mapping.',
77
+ ERROR_FILTER_ITEMS: 'Error [filterItems]: Unable to filter items.',
78
+ ERROR_FIRE: 'Error during fire operation.',
79
+ REFIRE_CALLED: (req) => `Re-fire operation triggered with: ${JSON.stringify(req)}`,
80
+ CHECKPOINT_LOCKDOWN: 'Checkpoint: lockdown has been invoked',
81
+ },
82
+ // Main index messages (index.ts)
83
+ INDEX: {
84
+ ASSET_STORE_INIT: 'Asset store instance initialized successfully.',
85
+ CONTENT_STORE_INIT: 'Content store instance initialized successfully.',
86
+ SYNC_MANAGER_INIT: 'Sync manager initialized successfully.',
87
+ SYNC_UTILITY_STARTED: 'Contentstack sync utility started successfully.',
88
+ NOTIFICATION: (action, item) => `Notification received: ${action} – ${JSON.stringify(item)}`,
89
+ },
90
+ // Token management messages (token-management.ts)
91
+ TOKEN: {
92
+ CHECKPOINT_READ: (path) => `Checkpoint read from file: ${path}`,
93
+ TOKEN_READ: (path) => `Token retrieved: ${path}`,
94
+ SAVE_TOKEN: (name) => `Saving token with name: ${name}`,
95
+ SAVE_CHECKPOINT: (name) => `Saving checkpoint token with name: ${name}`,
96
+ LEDGER_CHECK: (file, exists) => `Ledger file check: ${file} exists? → ${exists}`,
97
+ },
98
+ // Queue messages (q.ts)
99
+ QUEUE: {
100
+ CONSTRUCTOR: 'Core \'Q\' constructor initiated.',
101
+ CONTENT_TYPE_RECEIVED: (ctUid, type) => `Received content type '${ctUid}' for '${type}'`,
102
+ ERROR_HANDLER_CALLED: (obj) => `Error handler invoked with: ${JSON.stringify(obj)}`,
103
+ ERROR_IN_HANDLER: 'An error occurred in the error handler.',
104
+ NEXT_CALLED: (inProgress, qLength) => `Calling 'next'. Current progress status: ${inProgress}, Queue length: ${qLength}.`,
105
+ EXECUTING: (data) => `Executing queue item: ${JSON.stringify(data)}`,
106
+ BEFORE_PLUGINS: 'Before-action plugins executed successfully.',
107
+ ACTION_COMPLETE: (action) => `Completed '${action}' on connector successfully.`,
108
+ CONNECTOR_CALLED: 'Connector instance invoked successfully.',
109
+ AFTER_PLUGINS: 'After-action plugins executed successfully.',
110
+ },
111
+ // File system messages (fs.ts)
112
+ FS: {
113
+ WRITE_FILE: (path) => `Writing file to: ${path}`,
114
+ READ_FILE: (path) => `Reading file from: ${path}`,
115
+ READ_FILE_SYNC: (path) => `Reading file synchronously from: ${path}`,
116
+ MKDIR: (path) => `Creating directory: ${path}`,
117
+ INVALID_READ: (path) => `Invalid 'read' operation on file. Expected ${path} to be of type 'file'!`,
118
+ },
119
+ // Utility messages (util/index.ts)
120
+ UTIL: {
121
+ ITEM_TYPE_MISMATCH: 'The item\'s type did not match any expected case.',
122
+ ITEM_SERIALIZED: (item) => `Serialized item: ${JSON.stringify(item)}`,
123
+ ONLY_ASSETS: (lastCt) => `Only assets were found in the SYNC API response. Last content type: ${lastCt}.`,
124
+ ONLY_CT_EVENTS: (lastCt) => `Only content type events were found in the SYNC API response. Last content type: ${lastCt}.`,
125
+ ASSETS_AND_CT: (lastCt) => `Assets and content types were found in the SYNC API response. Last content type: ${lastCt}.`,
126
+ MIXED_CT: (lastCt) => `Mixed content types were found in the SYNC API response. Last content type: ${lastCt}.`,
127
+ FILE_NOT_TYPE: (file) => `${file} is not of type file`,
128
+ UNABLE_TO_FIND_PLUGIN: (plugin) => `Unable to find plugin: ${JSON.stringify(plugin)}`,
129
+ PLUGIN_PATH_NOT_EXIST: (path) => `${path} does not exist!`,
130
+ },
131
+ // Unprocessible items messages (unprocessible.ts)
132
+ UNPROCESSIBLE: {
133
+ WRITE_FAILED: (data, file, error) => `Failed to write data to ${file}: ${JSON.stringify(data)}. Error: ${error}`,
134
+ READ_FAILED: (path) => `Failed to read file from: ${path}`,
135
+ WRITE_OBJECT_FAILED: (file, data, error) => `Failed to write object to ${file}: ${JSON.stringify(data)}. Error: ${error}`,
136
+ },
137
+ };
138
+ /**
139
+ * @description Logger level constants
140
+ */
141
+ exports.LOG_LEVELS = {
142
+ DEBUG: 'debug',
143
+ INFO: 'info',
144
+ WARN: 'warn',
145
+ ERROR: 'error',
146
+ LOG: 'log',
147
+ };
148
+ /**
149
+ * @description Error codes
150
+ */
151
+ exports.ERROR_CODES = {
152
+ ILLEGAL_CONTENT_TYPE_CALL: 'ICTC',
153
+ INVALID_OPERATION_ON_READ_FILE: 'IOORF',
154
+ INVALID_OPERATION_ON_READ_FILE_SYNC: 'IOORFS',
155
+ MAX_RETRY_LIMIT_EXCEEDED: 'Max retry limit exceeded!',
156
+ REQUEST_TIMEOUT: 'Request timeout',
157
+ };
@@ -20,6 +20,7 @@ const index_1 = require("../index");
20
20
  const fs_1 = require("./fs");
21
21
  const index_2 = require("./index");
22
22
  const logger_1 = require("./logger");
23
+ const messages_1 = require("./messages");
23
24
  const counter = {
24
25
  failed: 0,
25
26
  filtered: 0,
@@ -75,18 +76,18 @@ const saveFilteredItems = (items, name, token) => {
75
76
  loggedItems.push(objDetails);
76
77
  return (0, fs_1.writeFile)(file, JSON.stringify(loggedItems)).then(resolve).catch((error) => {
77
78
  // failed to log failed items
78
- logger_1.logger.error(`Failed to write ${JSON.stringify(loggedItems)} at ${error}`);
79
+ logger_1.logger.error(messages_1.MESSAGES.UNPROCESSIBLE.WRITE_FAILED(loggedItems, file, error));
79
80
  logger_1.logger.error(error);
80
81
  return resolve('');
81
82
  });
82
83
  }).catch((error) => {
83
- logger_1.logger.error(`Failed to read file from path ${fail}`);
84
+ logger_1.logger.error(messages_1.MESSAGES.UNPROCESSIBLE.READ_FAILED(file));
84
85
  logger_1.logger.error(error);
85
86
  return resolve('');
86
87
  });
87
88
  }
88
89
  return (0, fs_1.writeFile)(file, JSON.stringify([objDetails])).then(resolve).catch((error) => {
89
- logger_1.logger.error(`Failed while writing ${JSON.stringify(objDetails)} at ${file}`);
90
+ logger_1.logger.error(messages_1.MESSAGES.UNPROCESSIBLE.WRITE_OBJECT_FAILED(file, objDetails, error));
90
91
  logger_1.logger.error(error);
91
92
  return resolve('');
92
93
  });
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.1.2",
4
+ "version": "2.2.0",
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": {