contensis-cli 1.0.0-beta.72 → 1.0.0-beta.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/util/index.ts"],
4
- "sourcesContent": ["import mergeWith from 'lodash/mergeWith';\nimport { Logger } from './logger';\nimport { LogMessages as enGB } from '../localisation/en-GB.js';\n\nexport const isSharedSecret = (str = '') =>\n str.length > 80 && str.split('-').length === 3 ? str : undefined;\n\nexport const isPassword = (str = '') =>\n !isSharedSecret(str) ? str : undefined;\n\nexport const tryParse = (str: string) => {\n try {\n return typeof str === 'object' ? str : JSON.parse(str);\n } catch (e) {\n return false;\n }\n};\n\nexport const isJson = (str: string) =>\n typeof str === 'object' || !!tryParse(str);\n\nexport const tryStringify = (obj: any) => {\n try {\n return typeof obj === 'object' ? JSON.stringify(obj) : obj;\n } catch (e) {\n return obj;\n }\n};\n\nexport const isSysError = (error: any): error is Error =>\n error?.message !== undefined && error.stack;\n\nexport const isUuid = (str: string) => {\n // Regular expression to check if string is a valid UUID\n const regexExp =\n /^[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}$/gi;\n\n return regexExp.test(str);\n};\n\nexport const url = (alias: string, project: string) => {\n const projectAndAlias =\n project && project.toLowerCase() !== 'website'\n ? `${project.toLowerCase()}-${alias}`\n : alias;\n return {\n api: `https://api-${alias}.cloud.contensis.com`,\n cms: `https://cms-${alias}.cloud.contensis.com`,\n liveWeb: `https://live-${projectAndAlias}.cloud.contensis.com`,\n previewWeb: `https://preview-${projectAndAlias}.cloud.contensis.com`,\n iisWeb: `https://iis-live-${projectAndAlias}.cloud.contensis.com`,\n iisPreviewWeb: `https://iis-preview-${projectAndAlias}.cloud.contensis.com`,\n };\n};\n\nexport const Logging = async (language = 'en-GB') => {\n const defaultMessages = enGB;\n // const { LogMessages: defaultMessages } = await import(\n // `../localisation/en-GB.js`\n // );\n let localisedMessages = defaultMessages;\n\n if (language === 'en-GB') {\n // Using a variable import e.g. `import(`../localisation/${language}.js`);`\n // does not play well with packaged executables\n // So we have to hard code the import for each language individually\n }\n return {\n messages: mergeWith(\n localisedMessages,\n defaultMessages,\n (v, s) => v || s\n ) as typeof defaultMessages,\n Log: Logger,\n };\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAsB;AACtB,oBAAuB;AACvB,mBAAoC;AAE7B,MAAM,iBAAiB,CAAC,MAAM,OACnC,IAAI,SAAS,MAAM,IAAI,MAAM,GAAG,EAAE,WAAW,IAAI,MAAM;AAElD,MAAM,aAAa,CAAC,MAAM,OAC/B,CAAC,eAAe,GAAG,IAAI,MAAM;AAExB,MAAM,WAAW,CAAC,QAAgB;AACvC,MAAI;AACF,WAAO,OAAO,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG;AAAA,EACvD,SAAS,GAAP;AACA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,SAAS,CAAC,QACrB,OAAO,QAAQ,YAAY,CAAC,CAAC,SAAS,GAAG;AAEpC,MAAM,eAAe,CAAC,QAAa;AACxC,MAAI;AACF,WAAO,OAAO,QAAQ,WAAW,KAAK,UAAU,GAAG,IAAI;AAAA,EACzD,SAAS,GAAP;AACA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,aAAa,CAAC,WACzB,+BAAO,aAAY,UAAa,MAAM;AAEjC,MAAM,SAAS,CAAC,QAAgB;AAErC,QAAM,WACJ;AAEF,SAAO,SAAS,KAAK,GAAG;AAC1B;AAEO,MAAM,MAAM,CAAC,OAAe,YAAoB;AACrD,QAAM,kBACJ,WAAW,QAAQ,YAAY,MAAM,YACjC,GAAG,QAAQ,YAAY,KAAK,UAC5B;AACN,SAAO;AAAA,IACL,KAAK,eAAe;AAAA,IACpB,KAAK,eAAe;AAAA,IACpB,SAAS,gBAAgB;AAAA,IACzB,YAAY,mBAAmB;AAAA,IAC/B,QAAQ,oBAAoB;AAAA,IAC5B,eAAe,uBAAuB;AAAA,EACxC;AACF;AAEO,MAAM,UAAU,OAAO,WAAW,YAAY;AACnD,QAAM,kBAAkB,aAAAA;AAIxB,MAAI,oBAAoB;AAExB,MAAI,aAAa,SAAS;AAAA,EAI1B;AACA,SAAO;AAAA,IACL,cAAU,iBAAAC;AAAA,MACR;AAAA,MACA;AAAA,MACA,CAAC,GAAG,MAAM,KAAK;AAAA,IACjB;AAAA,IACA,KAAK;AAAA,EACP;AACF;",
4
+ "sourcesContent": ["import mergeWith from 'lodash/mergeWith';\nimport { Logger } from './logger';\nimport { LogMessages as enGB } from '../localisation/en-GB.js';\n\nexport const isSharedSecret = (str = '') =>\n str.length > 80 && str.split('-').length === 3 ? str : undefined;\n\nexport const isPassword = (str = '') =>\n !isSharedSecret(str) ? str : undefined;\n\nexport const tryParse = (str: any) => {\n try {\n return typeof str === 'object' ? str : JSON.parse(str);\n } catch (e) {\n return false;\n }\n};\n\nexport const isJson = (str: string) =>\n typeof str === 'object' || !!tryParse(str);\n\nexport const tryStringify = (obj: any) => {\n try {\n return typeof obj === 'object' ? JSON.stringify(obj) : obj;\n } catch (e) {\n return obj;\n }\n};\n\nexport const isSysError = (error: any): error is Error =>\n error?.message !== undefined && error.stack;\n\nexport const isUuid = (str: string) => {\n // Regular expression to check if string is a valid UUID\n const regexExp =\n /^[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}$/gi;\n\n return regexExp.test(str);\n};\n\nexport const url = (alias: string, project: string) => {\n const projectAndAlias =\n project && project.toLowerCase() !== 'website'\n ? `${project.toLowerCase()}-${alias}`\n : alias;\n return {\n api: `https://api-${alias}.cloud.contensis.com`,\n cms: `https://cms-${alias}.cloud.contensis.com`,\n liveWeb: `https://live-${projectAndAlias}.cloud.contensis.com`,\n previewWeb: `https://preview-${projectAndAlias}.cloud.contensis.com`,\n iisWeb: `https://iis-live-${projectAndAlias}.cloud.contensis.com`,\n iisPreviewWeb: `https://iis-preview-${projectAndAlias}.cloud.contensis.com`,\n };\n};\n\nexport const Logging = async (language = 'en-GB') => {\n const defaultMessages = enGB;\n // const { LogMessages: defaultMessages } = await import(\n // `../localisation/en-GB.js`\n // );\n let localisedMessages = defaultMessages;\n\n if (language === 'en-GB') {\n // Using a variable import e.g. `import(`../localisation/${language}.js`);`\n // does not play well with packaged executables\n // So we have to hard code the import for each language individually\n }\n return {\n messages: mergeWith(\n localisedMessages,\n defaultMessages,\n (v, s) => v || s\n ) as typeof defaultMessages,\n Log: Logger,\n };\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAsB;AACtB,oBAAuB;AACvB,mBAAoC;AAE7B,MAAM,iBAAiB,CAAC,MAAM,OACnC,IAAI,SAAS,MAAM,IAAI,MAAM,GAAG,EAAE,WAAW,IAAI,MAAM;AAElD,MAAM,aAAa,CAAC,MAAM,OAC/B,CAAC,eAAe,GAAG,IAAI,MAAM;AAExB,MAAM,WAAW,CAAC,QAAa;AACpC,MAAI;AACF,WAAO,OAAO,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG;AAAA,EACvD,SAAS,GAAP;AACA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,SAAS,CAAC,QACrB,OAAO,QAAQ,YAAY,CAAC,CAAC,SAAS,GAAG;AAEpC,MAAM,eAAe,CAAC,QAAa;AACxC,MAAI;AACF,WAAO,OAAO,QAAQ,WAAW,KAAK,UAAU,GAAG,IAAI;AAAA,EACzD,SAAS,GAAP;AACA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,aAAa,CAAC,WACzB,+BAAO,aAAY,UAAa,MAAM;AAEjC,MAAM,SAAS,CAAC,QAAgB;AAErC,QAAM,WACJ;AAEF,SAAO,SAAS,KAAK,GAAG;AAC1B;AAEO,MAAM,MAAM,CAAC,OAAe,YAAoB;AACrD,QAAM,kBACJ,WAAW,QAAQ,YAAY,MAAM,YACjC,GAAG,QAAQ,YAAY,KAAK,UAC5B;AACN,SAAO;AAAA,IACL,KAAK,eAAe;AAAA,IACpB,KAAK,eAAe;AAAA,IACpB,SAAS,gBAAgB;AAAA,IACzB,YAAY,mBAAmB;AAAA,IAC/B,QAAQ,oBAAoB;AAAA,IAC5B,eAAe,uBAAuB;AAAA,EACxC;AACF;AAEO,MAAM,UAAU,OAAO,WAAW,YAAY;AACnD,QAAM,kBAAkB,aAAAA;AAIxB,MAAI,oBAAoB;AAExB,MAAI,aAAa,SAAS;AAAA,EAI1B;AACA,SAAO;AAAA,IACL,cAAU,iBAAAC;AAAA,MACR;AAAA,MACA;AAAA,MACA,CAAC,GAAG,MAAM,KAAK;AAAA,IACjB;AAAA,IACA,KAAK;AAAA,EACP;AACF;",
6
6
  "names": ["enGB", "mergeWith"]
7
7
  }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var timers_exports = {};
20
+ __export(timers_exports, {
21
+ promiseDelay: () => promiseDelay
22
+ });
23
+ module.exports = __toCommonJS(timers_exports);
24
+ const promiseDelay = (delay, value) => {
25
+ let timeout;
26
+ let _reject;
27
+ const wait = () => new Promise((resolve, reject) => {
28
+ _reject = reject;
29
+ timeout = setTimeout(resolve, delay, value);
30
+ });
31
+ const promise = wait();
32
+ return {
33
+ promise,
34
+ cancel() {
35
+ if (timeout) {
36
+ clearTimeout(timeout);
37
+ timeout = null;
38
+ _reject();
39
+ _reject = null;
40
+ }
41
+ },
42
+ wait
43
+ };
44
+ };
45
+ // Annotate the CommonJS export names for ESM import in node:
46
+ 0 && (module.exports = {
47
+ promiseDelay
48
+ });
49
+ //# sourceMappingURL=timers.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/util/timers.ts"],
4
+ "sourcesContent": ["export const promiseDelay = (delay: number, value: any) => {\n let timeout: NodeJS.Timeout | null;\n let _reject: PromiseRejectionEvent['reason'];\n\n const wait = () =>\n new Promise((resolve, reject) => {\n _reject = reject;\n timeout = setTimeout(resolve, delay, value);\n });\n\n const promise = wait();\n return {\n promise,\n cancel() {\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n _reject();\n _reject = null;\n }\n },\n wait,\n };\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,eAAe,CAAC,OAAe,UAAe;AACzD,MAAI;AACJ,MAAI;AAEJ,QAAM,OAAO,MACX,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC/B,cAAU;AACV,cAAU,WAAW,SAAS,OAAO,KAAK;AAAA,EAC5C,CAAC;AAEH,QAAM,UAAU,KAAK;AACrB,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AACP,UAAI,SAAS;AACX,qBAAa,OAAO;AACpB,kBAAU;AACV,gBAAQ;AACR,kBAAU;AAAA,MACZ;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
package/dist/version.js CHANGED
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  LIB_VERSION: () => LIB_VERSION
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const LIB_VERSION = "1.0.0-beta.72";
24
+ const LIB_VERSION = "1.0.0-beta.76";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  LIB_VERSION
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/version.ts"],
4
- "sourcesContent": ["export const LIB_VERSION = \"1.0.0-beta.72\";\n"],
4
+ "sourcesContent": ["export const LIB_VERSION = \"1.0.0-beta.76\";\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,cAAc;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contensis-cli",
3
- "version": "1.0.0-beta.72",
3
+ "version": "1.0.0-beta.76",
4
4
  "description": "A fully featured Contensis command line interface with a shell UI provides simple and intuitive ways to manage or profile your content in any NodeJS terminal.",
5
5
  "repository": "https://github.com/contensis/node-cli",
6
6
  "homepage": "https://github.com/contensis/node-cli/tree/main/packages/contensis-cli#readme",
@@ -1,4 +1,5 @@
1
1
  import { Argument, Command } from 'commander';
2
+ import { merge } from 'lodash';
2
3
  import { cliCommand } from '~/services/ContensisCliService';
3
4
  import { addGlobalOptions, mapContensisOpts } from './globalOptions';
4
5
 
@@ -175,7 +176,7 @@ Example call:
175
176
  .argument(
176
177
  '[branch]',
177
178
  'the branch of the block to get version details for',
178
- 'main'
179
+ 'default'
179
180
  )
180
181
  .argument(
181
182
  '[version]',
@@ -185,7 +186,8 @@ Example call:
185
186
  'after',
186
187
  `
187
188
  Example call:
188
- > get block contensis-website master latest
189
+ > get block contensis-website
190
+ > get block contensis-website develop latest
189
191
  `
190
192
  )
191
193
  .action(async (blockId: string, branch: string, version: string, opts) => {
@@ -210,7 +212,7 @@ Example call:
210
212
  .argument(
211
213
  '[branch]',
212
214
  'the branch of the block to get version details for',
213
- 'main'
215
+ 'default'
214
216
  )
215
217
  .argument(
216
218
  '[version]',
@@ -218,13 +220,14 @@ Example call:
218
220
  'latest'
219
221
  )
220
222
  .addArgument(dataCenter)
223
+ .option('-t, --follow', 'follow block logs in near realtime', false)
221
224
  .usage('get block logs [blockId] [branch] [version] [dataCenter]')
222
225
  .addHelpText(
223
226
  'after',
224
227
  `
225
228
  Example call:
226
- > get block logs contensis-website master
227
- > get block logs contensis-website master latest london
229
+ > get block logs contensis-website default
230
+ > get block logs contensis-website master latest london --follow
228
231
  `
229
232
  )
230
233
  .action(
@@ -235,11 +238,16 @@ Example call:
235
238
  dataCenter: 'hq' | 'manchester' | 'london',
236
239
  opts
237
240
  ) => {
238
- await cliCommand(['get', 'block', 'logs'], opts).PrintBlockLogs(
241
+ const parentOpts = block.opts() || {};
242
+ await cliCommand(
243
+ ['get', 'block', 'logs'],
244
+ merge(opts, parentOpts)
245
+ ).PrintBlockLogs(
239
246
  blockId,
240
247
  branch,
241
248
  version,
242
- dataCenter
249
+ dataCenter,
250
+ opts.follow as boolean
243
251
  );
244
252
  }
245
253
  );
@@ -385,6 +385,14 @@ export const LogMessages = {
385
385
  `[${env}] Unable to delete block ${Logger.highlightText(
386
386
  id
387
387
  )} in project ${projectId}`,
388
+ stopFollow: (id: string, env: string, projectId?: string) =>
389
+ `[${env}]\n\n 👌 stop fetching new ${Logger.highlightText(
390
+ id
391
+ )} logs in project ${projectId}`,
392
+ timeoutFollow: (id: string, env: string, projectId?: string) =>
393
+ `[${env}]\n\n 🤏 pausing fetching new ${Logger.highlightText(
394
+ id
395
+ )} logs in project ${projectId} due to too many requests`,
388
396
  },
389
397
  webhooks: {
390
398
  list: (env: string) => `[${env}] Webhook subscriptions:`,
@@ -5,7 +5,14 @@ import inquirer from 'inquirer';
5
5
  import to from 'await-to-js';
6
6
  import chalk from 'chalk';
7
7
  import { Component, ContentType, Project } from 'contensis-core-api';
8
- import { isPassword, isSharedSecret, isUuid, tryStringify, url } from '~/util';
8
+ import {
9
+ isPassword,
10
+ isSharedSecret,
11
+ isUuid,
12
+ tryParse,
13
+ tryStringify,
14
+ url,
15
+ } from '~/util';
9
16
  import SessionCacheProvider from '../providers/SessionCacheProvider';
10
17
  import ContensisAuthService from './ContensisAuthService';
11
18
  import CredentialProvider from '~/providers/CredentialProvider';
@@ -27,6 +34,8 @@ import { Entry, Role } from 'contensis-management-api/lib/models';
27
34
  import { csvFormatter } from '~/util/csv.formatter';
28
35
  import { xmlFormatter } from '~/util/xml.formatter';
29
36
  import { jsonFormatter } from '~/util/json.formatter';
37
+ import { diffLogStrings } from '~/util/diff';
38
+ import { promiseDelay } from '~/util/timers';
30
39
  import {
31
40
  printBlockVersion,
32
41
  printMigrateResult,
@@ -2009,7 +2018,8 @@ class ContensisCli {
2009
2018
  blockId: string,
2010
2019
  branch: string,
2011
2020
  version: string,
2012
- dataCenter: 'hq' | 'manchester' | 'london'
2021
+ dataCenter: 'hq' | 'manchester' | 'london',
2022
+ follow = false
2013
2023
  ) => {
2014
2024
  const { currentEnv, env, log, messages } = this;
2015
2025
  const contensis = await this.ConnectContensis();
@@ -2026,8 +2036,17 @@ class ContensisCli {
2026
2036
  dataCenter,
2027
2037
  });
2028
2038
 
2029
- if (blockLogs) {
2030
- this.HandleFormattingAndOutput(blockLogs, () => {
2039
+ if (err) {
2040
+ log.error(
2041
+ messages.blocks.failedGetLogs(blockId, currentEnv, env.currentProject)
2042
+ );
2043
+ log.error(jsonFormatter(err));
2044
+ } else if (blockLogs) {
2045
+ const removeTrailingNewline = (logs: string) =>
2046
+ logs.endsWith('\n') ? logs.slice(0, logs.length - 1) : logs;
2047
+ const renderLogs = removeTrailingNewline(blockLogs);
2048
+
2049
+ this.HandleFormattingAndOutput(renderLogs, () => {
2031
2050
  // print the logs to console
2032
2051
  console.log(
2033
2052
  ` - ${blockId} ${branch} ${
@@ -2035,16 +2054,91 @@ class ContensisCli {
2035
2054
  } [${dataCenter}]`
2036
2055
  );
2037
2056
  log.line();
2038
- console.log(log.infoText(blockLogs));
2039
- log.line();
2057
+ console.log(log.infoText(renderLogs));
2040
2058
  });
2041
- }
2042
2059
 
2043
- if (err) {
2044
- log.error(
2045
- messages.blocks.failedGetLogs(blockId, currentEnv, env.currentProject)
2046
- );
2047
- log.error(jsonFormatter(err));
2060
+ // Code for the `--follow` options
2061
+ let following = follow;
2062
+ let alreadyShown = blockLogs;
2063
+ let needsNewLine = false;
2064
+ let counter = 0;
2065
+
2066
+ // remove existing listeners and add them back afterwards
2067
+ const listeners = process.listeners('SIGINT');
2068
+
2069
+ process.removeAllListeners('SIGINT');
2070
+ // add listener to update following to false and break out
2071
+ process.on('SIGINT', () => {
2072
+ Logger.warning(
2073
+ `\n${messages.blocks.stopFollow(
2074
+ blockId,
2075
+ currentEnv,
2076
+ env.currentProject
2077
+ )}`
2078
+ );
2079
+ stopFollowing();
2080
+ });
2081
+
2082
+ let delay = promiseDelay(5 * 1000, null);
2083
+ const stopFollowing = () => {
2084
+ following = false;
2085
+ delay.cancel();
2086
+
2087
+ // Add back the listeners we removed previously
2088
+ process.removeAllListeners('SIGINT');
2089
+ for (const listener of listeners)
2090
+ process.addListener('SIGINT', listener);
2091
+ };
2092
+
2093
+ while (following) {
2094
+ if (counter++ > 300) {
2095
+ Logger.warning(
2096
+ `\n${messages.blocks.timeoutFollow(
2097
+ blockId,
2098
+ currentEnv,
2099
+ env.currentProject
2100
+ )}`
2101
+ );
2102
+ stopFollowing();
2103
+ }
2104
+
2105
+ // wait n. seconds then poll for logs again
2106
+ await delay.wait();
2107
+
2108
+ const [lastErr, lastLogs] = following
2109
+ ? await contensis.blocks.GetBlockLogs({
2110
+ blockId,
2111
+ branchId: branch,
2112
+ version,
2113
+ dataCenter,
2114
+ })
2115
+ : [null, null];
2116
+
2117
+ if (lastLogs) {
2118
+ // Find the difference and output it next
2119
+ const difference = diffLogStrings(lastLogs, alreadyShown);
2120
+ if (difference) {
2121
+ if (needsNewLine) {
2122
+ console.log('');
2123
+ }
2124
+ // Take the trailing newline off of the logged output to
2125
+ // avoid blank lines inbetween logs fetched sequentially
2126
+ const render = removeTrailingNewline(difference);
2127
+ console.log(log.infoText(render));
2128
+
2129
+ // Add what we've just rendered to already shown "cache"
2130
+ alreadyShown += render;
2131
+ needsNewLine = false;
2132
+ } else {
2133
+ // If no difference output a dot
2134
+ process.stdout.write('.');
2135
+ needsNewLine = true;
2136
+ }
2137
+ } else if (lastErr) {
2138
+ // If error output an x
2139
+ process.stdout.write('x');
2140
+ }
2141
+ }
2048
2142
  }
2049
2143
  }
2050
2144
  };
@@ -2149,15 +2243,16 @@ class ContensisCli {
2149
2243
 
2150
2244
  if (output) {
2151
2245
  let writeString = '';
2246
+ const isText = !tryParse(obj) && typeof obj === 'string';
2152
2247
  if (format === 'csv') {
2153
2248
  writeString = csvFormatter(obj as any);
2154
2249
  } else if (format === 'xml') {
2155
2250
  writeString = xmlFormatter(obj as any);
2156
- } else writeString = jsonFormatter(obj);
2251
+ } else writeString = isText ? (obj as string) : jsonFormatter(obj);
2157
2252
  // write output to file
2158
2253
  if (writeString) {
2159
2254
  fs.writeFileSync(output, writeString);
2160
- log.success(messages.app.fileOutput(format, output));
2255
+ log.success(messages.app.fileOutput(isText ? 'text' : format, output));
2161
2256
  } else {
2162
2257
  log.info(messages.app.noFileOutput());
2163
2258
  }
@@ -0,0 +1,21 @@
1
+ export const diffLogStrings = (updates: string, previous: string) => {
2
+ const lastFewLines = previous.split('\n').slice(-10);
3
+ const incomingLines = updates.split('\n');
4
+
5
+ // Find the line indices in the incoming lines
6
+ // of the last few lines previously rendered
7
+ const incomingLineIndices = [];
8
+ for (const lastRenderedLine of lastFewLines) {
9
+ if (lastRenderedLine.length > 20)
10
+ incomingLineIndices.push(
11
+ incomingLines.findIndex(
12
+ incomingLine => incomingLine === lastRenderedLine
13
+ )
14
+ );
15
+ }
16
+
17
+ // Get the new lines from the next position on from the last of the already shown lines
18
+ const differentFromPos = Math.max(...incomingLineIndices) + 1 || 0;
19
+ // Return just the incoming lines from the position we matched
20
+ return incomingLines.slice(differentFromPos).join('\n');
21
+ };
package/src/util/index.ts CHANGED
@@ -8,7 +8,7 @@ export const isSharedSecret = (str = '') =>
8
8
  export const isPassword = (str = '') =>
9
9
  !isSharedSecret(str) ? str : undefined;
10
10
 
11
- export const tryParse = (str: string) => {
11
+ export const tryParse = (str: any) => {
12
12
  try {
13
13
  return typeof str === 'object' ? str : JSON.parse(str);
14
14
  } catch (e) {
@@ -0,0 +1,24 @@
1
+ export const promiseDelay = (delay: number, value: any) => {
2
+ let timeout: NodeJS.Timeout | null;
3
+ let _reject: PromiseRejectionEvent['reason'];
4
+
5
+ const wait = () =>
6
+ new Promise((resolve, reject) => {
7
+ _reject = reject;
8
+ timeout = setTimeout(resolve, delay, value);
9
+ });
10
+
11
+ const promise = wait();
12
+ return {
13
+ promise,
14
+ cancel() {
15
+ if (timeout) {
16
+ clearTimeout(timeout);
17
+ timeout = null;
18
+ _reject();
19
+ _reject = null;
20
+ }
21
+ },
22
+ wait,
23
+ };
24
+ };
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const LIB_VERSION = "1.0.0-beta.72";
1
+ export const LIB_VERSION = "1.0.0-beta.76";