contensis-cli 1.0.0-beta.87 → 1.0.0-beta.89

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.
@@ -221,6 +221,8 @@ export const LogMessages = {
221
221
  `Assign your new key to a role with "set role assignments", or create a new role with "create role"`,
222
222
  failedCreate: (env: string, name: string) =>
223
223
  `[${env}] Unable to create API key ${Logger.highlightText(name)}`,
224
+ failedUpdate: (env: string, name: string) =>
225
+ `[${env}] Unable to update API key ${Logger.highlightText(name)}`,
224
226
  removed: (env: string, id: string) =>
225
227
  `[${env}] Deleted API key ${Logger.highlightText(id)}`,
226
228
  failedRemove: (env: string, id: string) =>
@@ -479,7 +481,7 @@ You could visit ${git.secretsUri} to check that you can see repository settings`
479
481
  )}`,
480
482
  addGitSecretsIntro: () =>
481
483
  `We have ceated an API key that allows you to deploy your app image to a Contensis Block but we need you to add these details to your GitLab repository.`,
482
- addGitSecretsHelp: (git: GitHelper, id: string, secret: string) =>
484
+ addGitSecretsHelp: (git: GitHelper, id?: string, secret?: string) =>
483
485
  `Add secrets or variables in your repository's settings page\n\nGo to ${Logger.highlightText(
484
486
  git.secretsUri
485
487
  )}\n\n${
@@ -0,0 +1,36 @@
1
+
2
+ export type OutputFormat = 'json' | 'csv' | 'xml';
3
+
4
+ export type OutputOptions = {
5
+ format?: OutputFormat;
6
+ output?: string;
7
+ };
8
+
9
+ export interface IConnectOptions extends IAuthOptions {
10
+ alias?: string;
11
+ projectId?: string;
12
+ }
13
+
14
+ export interface IAuthOptions {
15
+ user?: string;
16
+ password?: string;
17
+ clientId?: string;
18
+ sharedSecret?: string;
19
+ }
20
+
21
+ export interface IImportOptions {
22
+ sourceAlias?: string;
23
+ sourceProjectId?: string;
24
+ }
25
+
26
+ export type OutputOptionsConstructorArg = OutputOptions &
27
+ IConnectOptions &
28
+ IImportOptions;
29
+
30
+ export interface ContensisCliConstructor {
31
+ new (
32
+ args: string[],
33
+ outputOpts?: OutputOptionsConstructorArg,
34
+ contensisOpts?: Partial<MigrateRequest>
35
+ ): ContensisCli;
36
+ }
@@ -1,11 +1,12 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import fetch from 'node-fetch';
4
- import inquirer from 'inquirer';
5
1
  import to from 'await-to-js';
6
2
  import chalk from 'chalk';
3
+ import fs from 'fs';
4
+ import inquirer from 'inquirer';
5
+ import fetch from 'node-fetch';
6
+ import path from 'path';
7
7
 
8
8
  import { Component, ContentType, Project } from 'contensis-core-api';
9
+ import { Node } from 'contensis-delivery-api/lib/models';
9
10
  import { Entry, Role } from 'contensis-management-api/lib/models';
10
11
  import {
11
12
  ContensisMigrationService,
@@ -22,6 +23,7 @@ import {
22
23
  import ContensisAuthService from './ContensisAuthService';
23
24
 
24
25
  import { LogMessages } from '~/localisation/en-GB';
26
+ import { OutputFormat, OutputOptionsConstructorArg } from '~/models/CliService';
25
27
 
26
28
  import { readJsonFile } from '~/providers/file-provider';
27
29
  import SessionCacheProvider from '../providers/SessionCacheProvider';
@@ -47,42 +49,8 @@ import { jsonFormatter } from '~/util/json.formatter';
47
49
  import { diffLogStrings } from '~/util/diff';
48
50
  import { logError, Logger } from '~/util/logger';
49
51
  import { promiseDelay } from '~/util/timers';
52
+ import { findByIdOrName } from '~/util/find';
50
53
 
51
- type OutputFormat = 'json' | 'csv' | 'xml';
52
-
53
- type OutputOptions = {
54
- format?: OutputFormat;
55
- output?: string;
56
- };
57
-
58
- interface IConnectOptions extends IAuthOptions {
59
- alias?: string;
60
- projectId?: string;
61
- }
62
-
63
- interface IAuthOptions {
64
- user?: string;
65
- password?: string;
66
- clientId?: string;
67
- sharedSecret?: string;
68
- }
69
-
70
- interface IImportOptions {
71
- sourceAlias?: string;
72
- sourceProjectId?: string;
73
- }
74
-
75
- export type OutputOptionsConstructorArg = OutputOptions &
76
- IConnectOptions &
77
- IImportOptions;
78
-
79
- export interface ContensisCliConstructor {
80
- new (
81
- args: string[],
82
- outputOpts?: OutputOptionsConstructorArg,
83
- contensisOpts?: Partial<MigrateRequest>
84
- ): ContensisCli;
85
- }
86
54
  let insecurePasswordWarningShown = false;
87
55
 
88
56
  class ContensisCli {
@@ -937,15 +905,7 @@ class ContensisCli {
937
905
  if (Array.isArray(roles)) {
938
906
  log.success(messages.roles.list(currentEnv));
939
907
 
940
- const role =
941
- roles.find(
942
- r =>
943
- r.id === roleNameOrId ||
944
- r.name.toLowerCase() === roleNameOrId.toLowerCase()
945
- ) ||
946
- roles.find(r =>
947
- r.name.toLowerCase().includes(roleNameOrId.toLowerCase())
948
- );
908
+ const role = findByIdOrName(roles, roleNameOrId);
949
909
 
950
910
  if (role) this.HandleFormattingAndOutput(role, log.object);
951
911
  else log.error(messages.roles.failedGet(currentEnv, roleNameOrId));
@@ -996,11 +956,7 @@ class ContensisCli {
996
956
  if (Array.isArray(roles)) {
997
957
  log.success(messages.roles.list(currentEnv));
998
958
 
999
- const existingRole = roles.find(
1000
- r =>
1001
- r.id === roleNameOrId ||
1002
- r.name.toLowerCase() === roleNameOrId.toLowerCase()
1003
- );
959
+ const existingRole = findByIdOrName(roles, roleNameOrId, true);
1004
960
  if (existingRole) {
1005
961
  log.info(messages.roles.setPayload());
1006
962
  log.object(role);
@@ -1040,11 +996,8 @@ class ContensisCli {
1040
996
  if (Array.isArray(roles)) {
1041
997
  log.success(messages.roles.list(currentEnv));
1042
998
 
1043
- const existingRole = roles.find(
1044
- r =>
1045
- r.id === roleNameOrId ||
1046
- r.name.toLowerCase() === roleNameOrId.toLowerCase()
1047
- );
999
+ const existingRole = findByIdOrName(roles, roleNameOrId, true);
1000
+
1048
1001
  if (existingRole) {
1049
1002
  const [deleteErr] = await contensis.roles.RemoveRole(existingRole.id);
1050
1003
 
@@ -1737,12 +1690,45 @@ class ContensisCli {
1737
1690
  log.error(messages.nodes.failedGet(currentProject), err);
1738
1691
  return;
1739
1692
  }
1740
- const nodes = contensis.content.sourceRepo.nodes.tree;
1693
+ const root = contensis.content.sourceRepo.nodes.tree;
1741
1694
 
1742
1695
  log.success(messages.nodes.get(currentProject, rootPath, depth));
1743
- this.HandleFormattingAndOutput(nodes, () => {
1696
+
1697
+ const outputNode = (node: Node | any, spaces: string) =>
1698
+ `${node.entry ? log.highlightText('e') : log.infoText('-')}${
1699
+ node.isCanonical ? log.highlightText('c') : log.infoText('-')
1700
+ }${
1701
+ node.includeInMenu ? log.highlightText('m') : log.infoText('-')
1702
+ }${spaces}${
1703
+ node.isCanonical ? log.boldText(`/${node.slug}`) : `/${node.slug}`
1704
+ }${node.entry ? ` ${log.helpText(node.entry.sys.contentTypeId)}` : ''}${
1705
+ node.childCount ? ` +${node.childCount}` : ``
1706
+ } ${log.infoText(node.displayName)}`;
1707
+
1708
+ this.HandleFormattingAndOutput(root, () => {
1744
1709
  // print the nodes to console
1745
- log.object(nodes);
1710
+ log.object({ ...root, children: undefined });
1711
+ log.raw('');
1712
+ log.info(
1713
+ `${log.highlightText('e')} = has entry; ${log.highlightText(
1714
+ 'c'
1715
+ )} = canonical; ${log.highlightText('m')} = include in menu`
1716
+ );
1717
+ log.line();
1718
+ const outputChildren = (root: Node | undefined, depth = 2) => {
1719
+ let str = '';
1720
+ for (const node of (root as any)?.children as Node[]) {
1721
+ str += `${outputNode(node, Array(depth + 1).join(' '))}\n`;
1722
+ if ('children' in node) str += outputChildren(node, depth + 1);
1723
+ }
1724
+ return str;
1725
+ };
1726
+
1727
+ const children = outputChildren(root);
1728
+ log.limits(
1729
+ `${outputNode(root, ' ')}${children ? `\n${children}` : ''}`,
1730
+ 100
1731
+ );
1746
1732
  });
1747
1733
  } else {
1748
1734
  log.warning(messages.models.noList(currentProject));
@@ -2218,7 +2204,9 @@ class ContensisCli {
2218
2204
  const contensis = await this.ConnectContensis();
2219
2205
  if (contensis) {
2220
2206
  // Retrieve proxies list for env
2221
- const [err, proxies] = await contensis.proxies.GetProxies(proxyId);
2207
+ const [err, proxies] = await (contensis.proxies.GetProxies as any)(
2208
+ proxyId
2209
+ ); // TODO: resolve any cast;
2222
2210
 
2223
2211
  if (Array.isArray(proxies)) {
2224
2212
  this.HandleFormattingAndOutput(proxies, () => {
@@ -2230,7 +2218,9 @@ class ContensisCli {
2230
2218
  version.versionNo
2231
2219
  }] ${id} ${log.infoText`${description}`}`
2232
2220
  );
2233
- for (const [language, endpoint] of Object.entries(endpoints))
2221
+ for (const [language, endpoint] of Object.entries(
2222
+ endpoints as { [k: string]: any }
2223
+ )) // TODO: resolve any cast
2234
2224
  console.log(
2235
2225
  ` - ${log.infoText`language: ${language}
2236
2226
  server: ${endpoint.server}
@@ -2253,9 +2243,9 @@ class ContensisCli {
2253
2243
  const contensis = await this.ConnectContensis();
2254
2244
  if (contensis) {
2255
2245
  // Retrieve renderers list for env
2256
- const [err, renderers] = await contensis.renderers.GetRenderers(
2246
+ const [err, renderers] = await (contensis.renderers.GetRenderers as any)(
2257
2247
  rendererId
2258
- );
2248
+ ); // TODO: resolve any cast
2259
2249
 
2260
2250
  if (Array.isArray(renderers)) {
2261
2251
  this.HandleFormattingAndOutput(renderers, () => {
@@ -1,19 +1,21 @@
1
+ import to from 'await-to-js';
1
2
  import { execFile, spawn } from 'child_process';
2
3
  import inquirer from 'inquirer';
3
4
  import path from 'path';
5
+ import { Entry, Role } from 'contensis-management-api/lib/models';
4
6
 
5
7
  import { MigrateRequest } from 'migratortron';
6
8
  import { stringify } from 'yaml';
7
-
8
- import ContensisCli, {
9
- OutputOptionsConstructorArg,
10
- } from './ContensisCliService';
9
+ import ContensisCli from './ContensisCliService';
10
+ import ContensisRole from './ContensisRoleService';
11
+ import { OutputOptionsConstructorArg } from '~/models/CliService';
11
12
  import { mapSiteConfigYaml } from '~/mappers/ContensisCliService-to-RequestHanderSiteConfigYaml';
12
- import { appRootDir, writeFile } from '~/providers/file-provider';
13
+ import { appRootDir, readFile, writeFile } from '~/providers/file-provider';
13
14
  import { jsonFormatter } from '~/util/json.formatter';
14
15
  import { GitHelper } from '~/util/git';
16
+ import { findByIdOrName } from '~/util/find';
15
17
 
16
- class ContensisDev extends ContensisCli {
18
+ class ContensisDev extends ContensisRole {
17
19
  constructor(
18
20
  args: string[],
19
21
  outputOpts?: OutputOptionsConstructorArg,
@@ -23,6 +25,7 @@ class ContensisDev extends ContensisCli {
23
25
  }
24
26
 
25
27
  DevelopmentInit = async (projectHome: string, opts: any) => {
28
+ const { dryRun = false } = opts || {};
26
29
  const { currentEnv, currentProject, log, messages } = this;
27
30
  const contensis = await this.ConnectContensis();
28
31
 
@@ -45,12 +48,23 @@ class ContensisDev extends ContensisCli {
45
48
  // Retrieve ci workflow info
46
49
  const workflowFiles = git.workflows;
47
50
 
48
- // Set variables for logging etc.
51
+ // Set variables for performing operations and logging etc.
49
52
  let ciFileName = git.ciFileName;
50
53
 
51
- const devKey = `${git.name} development`;
52
- const deployKey = `${git.name} deployment`;
54
+ const devKeyName = `${git.name} development`;
55
+ const devKeyDescription = `${git.name} [contensis-cli]`;
56
+ const devKeyPermissions = { blocks: [] } as Partial<Role['permissions']>;
57
+ let existingDevKey = apiKeyExists(devKeyName);
58
+
59
+ const deployKeyName = `${git.name} deployment`;
60
+ const deployKeyDescription = `${git.name} deploy [contensis-cli]`;
61
+ const deployKeyPermissions = { blocks: ['push', 'release'] } as Partial<
62
+ Role['permissions']
63
+ >;
64
+ let existingDeployKey = apiKeyExists(deployKeyName);
65
+
53
66
  const blockId = git.name;
67
+ const errors = [] as AppError[];
54
68
 
55
69
  // Start render console output
56
70
  log.raw('');
@@ -68,12 +82,12 @@ class ContensisDev extends ContensisCli {
68
82
  );
69
83
  log.raw(
70
84
  log.infoText(
71
- messages.devinit.developmentKey(devKey, !!apiKeyExists(devKey))
85
+ messages.devinit.developmentKey(devKeyName, !!existingDevKey)
72
86
  )
73
87
  );
74
88
  log.raw(
75
89
  log.infoText(
76
- messages.devinit.deploymentKey(deployKey, !!apiKeyExists(deployKey))
90
+ messages.devinit.deploymentKey(deployKeyName, !!existingDeployKey)
77
91
  )
78
92
  );
79
93
  log.raw('');
@@ -95,7 +109,7 @@ class ContensisDev extends ContensisCli {
95
109
  }
96
110
 
97
111
  log.raw(log.infoText(messages.devinit.ciDetails(ciFileName)));
98
- log.help(messages.devinit.ciIntro(git));
112
+ ylog.help(messages.devinit.ciIntro(git));
99
113
 
100
114
  // Confirm prompt
101
115
  const { confirm } = await inquirer.prompt([
@@ -120,25 +134,131 @@ class ContensisDev extends ContensisCli {
120
134
  log.raw('');
121
135
 
122
136
  // Magic happens...
137
+ const checkpoint = (op: string) => {
138
+ if (errors.length) throw errors[0];
139
+ else log.debug(`${op} completed ok`);
140
+ return true;
141
+ };
123
142
 
124
143
  // Arrange API keys for development and deployment
125
- log.success(messages.devinit.createDevKey(devKey, false));
126
- log.success(messages.devinit.createDeployKey(deployKey, true));
144
+ const [getRolesErr, roles] = await to(contensis.roles.GetRoles());
145
+ if (!roles && getRolesErr) errors.push(getRolesErr);
146
+ checkpoint(`fetched ${roles?.length} roles`);
147
+ if (dryRun) {
148
+ checkpoint(`skip api key creation (dry-run)`);
149
+ } else {
150
+ existingDevKey = await this.CreateOrUpdateApiKey(
151
+ existingDevKey,
152
+ devKeyName,
153
+ devKeyDescription
154
+ );
155
+ checkpoint('dev key created');
156
+
157
+ existingDeployKey = await this.CreateOrUpdateApiKey(
158
+ existingDeployKey,
159
+ deployKeyName,
160
+ deployKeyDescription
161
+ );
162
+ checkpoint('deploy key created');
163
+
164
+ // Ensure dev API key is assigned to a role
165
+ let existingDevRole = findByIdOrName(roles || [], devKeyName, true) as
166
+ | Role
167
+ | undefined;
168
+ existingDevRole = await this.CreateOrUpdateRole(
169
+ existingDevRole,
170
+ devKeyName,
171
+ devKeyDescription,
172
+ { apiKeys: [devKeyName] },
173
+ devKeyPermissions
174
+ );
175
+ checkpoint('dev key role assigned');
176
+ log.success(messages.devinit.createDevKey(devKeyName, true));
177
+
178
+ // Ensure deploy API key is assigned to a role with the right permissions
179
+ let existingDeployRole = findByIdOrName(
180
+ roles || [],
181
+ deployKeyName,
182
+ true
183
+ ) as Role | undefined;
184
+ existingDeployRole = await this.CreateOrUpdateRole(
185
+ existingDeployRole,
186
+ deployKeyName,
187
+ deployKeyDescription,
188
+ { apiKeys: [deployKeyName] },
189
+ deployKeyPermissions
190
+ );
191
+
192
+ checkpoint('deploy key role assigned');
193
+ log.success(messages.devinit.createDeployKey(deployKeyName, true));
194
+ checkpoint('api keys done');
195
+ }
127
196
 
128
197
  // Update or create a file called .env in project home
129
- log.success(messages.devinit.writeEnvFile());
130
- // log.help(messages.devinit.useEnvFileTip());
198
+ const envContents = {
199
+ ALIAS: currentEnv,
200
+ PROJECT: currentProject,
201
+ ACCESS_TOKEN: accessToken,
202
+ };
203
+ const envFilePath = `${projectHome}/.env`;
204
+ const existingEnvFile = readFile(envFilePath);
205
+ const existingFileLines = (existingEnvFile || '').split('\n');
206
+ const envFileLines: string[] = [];
207
+
208
+ const updatedEnvKeys: string[] = [];
209
+ for (const ln of existingFileLines) {
210
+ let newline = '';
211
+ for (const [k, v] of Object.entries(envContents))
212
+ if (ln.startsWith(`${k}=`)) {
213
+ newline = `${k}=${v}`;
214
+ updatedEnvKeys.push(k);
215
+ }
216
+ envFileLines.push(newline || ln);
217
+ }
218
+ for (const addKey of existingFileLines
219
+ .filter(
220
+ efl =>
221
+ !updatedEnvKeys.find(uek =>
222
+ uek.startsWith(`${efl.split('=')?.[0]}=`)
223
+ ) && Object.keys(envContents).find(ck => ck === efl.split('=')?.[0])
224
+ )
225
+ .map(fl => fl.split('=')?.[0]) as (keyof typeof envContents)[]) {
226
+ envFileLines.push(`${addKey}=${envContents[addKey]}`);
227
+ }
228
+
229
+ if (dryRun) {
230
+ checkpoint('skip .env file update (dry-run)');
231
+ log.info(`.env file`);
232
+ log.object(envFileLines);
233
+ } else {
234
+ writeFile(envFilePath, envFileLines.join('\n'));
235
+ checkpoint('.env file updated');
236
+ log.success(messages.devinit.writeEnvFile());
237
+ // log.help(messages.devinit.useEnvFileTip());
238
+ }
131
239
 
132
240
  // Update CI file -- different for GH/GL -- create a sample one with build?
133
- log.success(messages.devinit.writeCiFile(`./${ciFileName}`));
134
- log.info(
135
- messages.devinit.ciBlockTip(blockId, currentEnv, currentProject)
136
- );
241
+ if (dryRun) {
242
+ checkpoint('skip CI file update (dry-run)');
243
+ log.info(`${ciFileName} file`);
244
+ // TODO: log what we might add to the file
245
+ //log.object(envFileLines);
246
+ } else {
247
+ log.success(messages.devinit.writeCiFile(`./${ciFileName}`));
248
+ log.info(
249
+ messages.devinit.ciBlockTip(blockId, currentEnv, currentProject)
250
+ );
251
+ checkpoint('CI file updated');
252
+ }
137
253
 
138
254
  // Echo Deployment API key to console, ask user to add secrets to repo
139
255
  log.warning(messages.devinit.addGitSecretsIntro());
140
256
  log.help(
141
- messages.devinit.addGitSecretsHelp(git, '123-456', '789-012-345')
257
+ messages.devinit.addGitSecretsHelp(
258
+ git,
259
+ existingDeployKey?.id,
260
+ existingDeployKey?.sharedSecret
261
+ )
142
262
  );
143
263
 
144
264
  log.success(messages.devinit.success());
@@ -0,0 +1,84 @@
1
+ import { Role } from 'contensis-management-api/lib/models';
2
+ import { ApiKey, MigrateRequest } from 'migratortron';
3
+
4
+ import ContensisCli from './ContensisCliService';
5
+ import { OutputOptionsConstructorArg } from '~/models/CliService';
6
+
7
+ class ContensisRole extends ContensisCli {
8
+ constructor(
9
+ args: string[],
10
+ outputOpts?: OutputOptionsConstructorArg,
11
+ contensisOpts: Partial<MigrateRequest> = {}
12
+ ) {
13
+ super(args, outputOpts, contensisOpts);
14
+ }
15
+
16
+ CreateOrUpdateApiKey = async (
17
+ existingKey: ApiKey | undefined,
18
+ name: string,
19
+ description: string
20
+ ) => {
21
+ const { contensis, currentEnv, messages } = this;
22
+ if (!contensis) throw new Error('shouldnt be here');
23
+ if (existingKey) {
24
+ const [err, key] = await contensis.apiKeys.UpdateKey(existingKey.id, {
25
+ name,
26
+ description,
27
+ });
28
+
29
+ if (err)
30
+ throw new Error(messages.keys.failedUpdate(currentEnv, name), {
31
+ cause: err,
32
+ });
33
+ return key;
34
+ } else {
35
+ const [err, key] = await contensis.apiKeys.CreateKey(name, description);
36
+ if (err)
37
+ throw new Error(messages.keys.failedCreate(currentEnv, name), {
38
+ cause: err,
39
+ });
40
+
41
+ return key;
42
+ }
43
+ };
44
+
45
+ CreateOrUpdateRole = async (
46
+ existingRole: Role | undefined,
47
+ name: string,
48
+ description: string,
49
+ assignments: Role['assignments'],
50
+ permissions: Role['permissions']
51
+ ) => {
52
+ const { contensis, currentEnv, messages } = this;
53
+ if (!contensis) throw new Error('shouldnt be here');
54
+
55
+ if (existingRole) {
56
+ // TODO: check is update needed?
57
+ const [err, updated] = await contensis.roles.UpdateRole(existingRole.id, {
58
+ ...existingRole,
59
+ assignments,
60
+ permissions,
61
+ });
62
+ if (err)
63
+ throw new Error(messages.roles.failedSet(currentEnv, name), {
64
+ cause: err,
65
+ });
66
+ return updated;
67
+ } else {
68
+ const [err, created] = await contensis.roles.CreateRole({
69
+ name,
70
+ description,
71
+ enabled: true,
72
+ assignments,
73
+ permissions,
74
+ } as Role);
75
+ if (err)
76
+ throw new Error(messages.roles.failedCreate(currentEnv, name), {
77
+ cause: err,
78
+ });
79
+
80
+ return created;
81
+ }
82
+ };
83
+ }
84
+ export default ContensisRole;
@@ -0,0 +1,8 @@
1
+ export const findByIdOrName = (arr: any[], idOrName: string, exact = false) =>
2
+ arr.find(
3
+ r =>
4
+ r.id === idOrName ||
5
+ r.name.toLowerCase() === idOrName.toLowerCase()
6
+ ) ||
7
+ (!exact &&
8
+ arr.find(r => r.name.toLowerCase().includes(idOrName.toLowerCase())));
@@ -2,6 +2,7 @@
2
2
  import chalk from 'chalk';
3
3
  import dateFormat from 'dateformat';
4
4
  import deepCleaner from 'deep-cleaner';
5
+ import { ansiEscapeCodes, first, strlen } from 'printable-characters';
5
6
  // import ProgressBar from 'progress';
6
7
  import { isSysError, tryStringify } from '.';
7
8
 
@@ -88,6 +89,13 @@ export class Logger {
88
89
  else console.log(message);
89
90
  progress.current.interrupt(message);
90
91
  };
92
+ static debug: LogMethod = content => {
93
+ const message = `${Logger.getPrefix()} ${
94
+ Logger.isUserTerminal ? chalk.bgGrey(' ⚙ ') : '[DEBUG]'
95
+ } ${Logger.infoText(content)}`;
96
+ if (progress.active) progress.current.interrupt(message);
97
+ else console.log(message);
98
+ };
91
99
  static json: LogJsonDepthMethod = (content, depth = 9) =>
92
100
  console.dir(deepCleaner(content), { colors: true, depth });
93
101
  static mixed: LogArrayMethod = contentArray =>
@@ -214,6 +222,26 @@ export class Logger {
214
222
  if (progress.active) progress.current.interrupt(content);
215
223
  else console.log(content);
216
224
  };
225
+
226
+ static limits = (content: string, displayLength = 30) => {
227
+ const consoleWidth = process.stdout.columns;
228
+ console.info(
229
+ consoleWidth
230
+ ? content
231
+ .split('\n')
232
+ .slice(0, consoleWidth ? displayLength : undefined)
233
+ .map((line: string) =>
234
+ consoleWidth && strlen(line) > consoleWidth
235
+ ? first(line, consoleWidth)
236
+ : line
237
+ )
238
+ .join('\n')
239
+ : content.replace(ansiEscapeCodes, '')
240
+ );
241
+ const tableArray = content.split('\n');
242
+ if (consoleWidth && tableArray.length > displayLength)
243
+ console.info(`\n`, `- and ${tableArray.length - displayLength} more...`);
244
+ };
217
245
  }
218
246
 
219
247
  export const logError: LogErrorFunc = (
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const LIB_VERSION = "1.0.0-beta.87";
1
+ export const LIB_VERSION = "1.0.0-beta.89";