contensis-cli 1.0.12-beta.2 → 1.0.12-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/commands/get.js +13 -1
- package/dist/commands/get.js.map +2 -2
- package/dist/commands/globalOptions.js +9 -10
- package/dist/commands/globalOptions.js.map +2 -2
- package/dist/commands/import.js +22 -12
- package/dist/commands/import.js.map +2 -2
- package/dist/commands/index.js +2 -2
- package/dist/commands/index.js.map +2 -2
- package/dist/commands/list.js +9 -0
- package/dist/commands/list.js.map +2 -2
- package/dist/commands/remove.js +13 -0
- package/dist/commands/remove.js.map +2 -2
- package/dist/localisation/en-GB.js +12 -4
- package/dist/localisation/en-GB.js.map +2 -2
- package/dist/mappers/DevInit-to-CIWorkflow.js +6 -8
- package/dist/mappers/DevInit-to-CIWorkflow.js.map +2 -2
- package/dist/mappers/DevInit-to-RolePermissions.js +4 -4
- package/dist/mappers/DevInit-to-RolePermissions.js.map +2 -2
- package/dist/providers/file-provider.js +5 -1
- package/dist/providers/file-provider.js.map +2 -2
- package/dist/services/ContensisAuthService.js.map +2 -2
- package/dist/services/ContensisCliService.js +158 -40
- package/dist/services/ContensisCliService.js.map +2 -2
- package/dist/services/ContensisDevService.js +51 -56
- package/dist/services/ContensisDevService.js.map +3 -3
- package/dist/shell.js +6 -0
- package/dist/shell.js.map +2 -2
- package/dist/util/console.printer.js +61 -52
- package/dist/util/console.printer.js.map +3 -3
- package/dist/util/csv.formatter.js +3 -11
- package/dist/util/csv.formatter.js.map +3 -3
- package/dist/util/diff.js +1 -1
- package/dist/util/diff.js.map +2 -2
- package/dist/util/error.js +36 -0
- package/dist/util/error.js.map +7 -0
- package/dist/util/find.js +10 -2
- package/dist/util/find.js.map +2 -2
- package/dist/util/git.js +1 -0
- package/dist/util/git.js.map +2 -2
- package/dist/util/json.formatter.js +35 -3
- package/dist/util/json.formatter.js.map +3 -3
- package/dist/util/logger.js +52 -9
- package/dist/util/logger.js.map +3 -3
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +4 -4
- package/src/commands/get.ts +19 -1
- package/src/commands/globalOptions.ts +9 -7
- package/src/commands/import.ts +35 -15
- package/src/commands/index.ts +2 -3
- package/src/commands/list.ts +15 -0
- package/src/commands/remove.ts +20 -0
- package/src/localisation/en-GB.ts +15 -5
- package/src/mappers/DevInit-to-CIWorkflow.ts +8 -8
- package/src/mappers/DevInit-to-RolePermissions.ts +5 -2
- package/src/models/Cache.d.ts +2 -1
- package/src/providers/file-provider.ts +5 -1
- package/src/services/ContensisAuthService.ts +1 -1
- package/src/services/ContensisCliService.ts +195 -55
- package/src/services/ContensisDevService.ts +76 -70
- package/src/shell.ts +8 -0
- package/src/util/console.printer.ts +151 -72
- package/src/util/csv.formatter.ts +1 -4
- package/src/util/diff.ts +1 -1
- package/src/util/error.ts +7 -0
- package/src/util/find.ts +13 -2
- package/src/util/git.ts +2 -1
- package/src/util/json.formatter.ts +32 -1
- package/src/util/logger.ts +90 -15
- package/src/version.ts +1 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import ansiEscapes from 'ansi-escapes';
|
|
1
2
|
import to from 'await-to-js';
|
|
2
3
|
import { spawn } from 'child_process';
|
|
3
4
|
import inquirer from 'inquirer';
|
|
5
|
+
import { createSpinner } from 'nanospinner';
|
|
4
6
|
import path from 'path';
|
|
5
7
|
|
|
6
8
|
import { Role } from 'contensis-management-api/lib/models';
|
|
@@ -20,15 +22,17 @@ import { GitHelper } from '~/util/git';
|
|
|
20
22
|
import { jsonFormatter } from '~/util/json.formatter';
|
|
21
23
|
import { winSlash } from '~/util/os';
|
|
22
24
|
import { stringifyYaml } from '~/util/yaml';
|
|
23
|
-
import { createSpinner } from 'nanospinner';
|
|
24
25
|
import { mergeContentsToAddWithGitignore } from '~/util/gitignore';
|
|
25
|
-
import ContensisAuthService from './ContensisAuthService';
|
|
26
|
-
import ansiEscapes from 'ansi-escapes';
|
|
27
26
|
|
|
28
27
|
class ContensisDev extends ContensisRole {
|
|
29
28
|
git!: GitHelper;
|
|
30
29
|
blockId!: string;
|
|
31
30
|
|
|
31
|
+
deployCredentials = {
|
|
32
|
+
clientId: '',
|
|
33
|
+
clientSecret: '',
|
|
34
|
+
};
|
|
35
|
+
|
|
32
36
|
constructor(
|
|
33
37
|
args: string[],
|
|
34
38
|
outputOpts?: OutputOptionsConstructorArg,
|
|
@@ -49,8 +53,6 @@ class ContensisDev extends ContensisRole {
|
|
|
49
53
|
const contensis = await this.ConnectContensis();
|
|
50
54
|
|
|
51
55
|
if (contensis) {
|
|
52
|
-
this.devinit = { ...this.devinit, invokedBy: this.invokedBy };
|
|
53
|
-
|
|
54
56
|
// First we need to get the block id from the user
|
|
55
57
|
const validateBlockId = (blockId: string) => {
|
|
56
58
|
const pattern = /^[0-9a-z](-?[0-9a-z])*$/;
|
|
@@ -64,6 +66,7 @@ class ContensisDev extends ContensisRole {
|
|
|
64
66
|
prefix: '🧱',
|
|
65
67
|
message: messages.devinit.blockIdQuestion,
|
|
66
68
|
validate: validateBlockId,
|
|
69
|
+
default: git.name,
|
|
67
70
|
});
|
|
68
71
|
// make sure block id is lowercase
|
|
69
72
|
this.blockId = blockId.toLowerCase();
|
|
@@ -93,65 +96,17 @@ class ContensisDev extends ContensisRole {
|
|
|
93
96
|
const devKeyDescription = `Created by Contensis to allow API access from the running block`;
|
|
94
97
|
let existingDevKey = apiKeyExists(devKeyName);
|
|
95
98
|
|
|
96
|
-
// if dev api key doesn't exisit go and create it (we need this for local development, we will store these details in the .env file).
|
|
97
|
-
if (!existingDevKey) {
|
|
98
|
-
existingDevKey = await this.CreateOrUpdateApiKey(
|
|
99
|
-
existingDevKey,
|
|
100
|
-
devKeyName,
|
|
101
|
-
devKeyDescription
|
|
102
|
-
);
|
|
103
|
-
log.success('Successfully created development key');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
99
|
const deployKeyName = `${apiKeyName}-ci`;
|
|
107
100
|
const deployKeyDescription = `Created by the Contensis CLI for use in continuous integration`;
|
|
108
101
|
|
|
109
102
|
let existingDeployKey = apiKeyExists(deployKeyName);
|
|
110
103
|
|
|
111
|
-
// if deploy api key doesn't exisit go and create it (we need this for yml file).
|
|
112
|
-
if (!existingDeployKey) {
|
|
113
|
-
existingDeployKey = await this.CreateOrUpdateApiKey(
|
|
114
|
-
existingDeployKey,
|
|
115
|
-
deployKeyName,
|
|
116
|
-
deployKeyDescription
|
|
117
|
-
);
|
|
118
|
-
log.success('Successfully created deploy key');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// check we have the deply key so we can assign them to this values
|
|
122
|
-
if (existingDeployKey) {
|
|
123
|
-
// Add client id and secret to global 'this'
|
|
124
|
-
this.devinit = {
|
|
125
|
-
...this.devinit,
|
|
126
|
-
credentials: {
|
|
127
|
-
clientId: existingDeployKey?.id,
|
|
128
|
-
clientSecret: existingDeployKey?.sharedSecret,
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// we need to credentials of the user so that we can create a auth service
|
|
134
|
-
const credentials = await this.GetCredentials(this.devinit.invokedBy);
|
|
135
|
-
|
|
136
|
-
// create new auth service using creds
|
|
137
|
-
let classicToken: string | undefined | null;
|
|
138
|
-
const auth = new ContensisAuthService({
|
|
139
|
-
username: credentials?.current?.account,
|
|
140
|
-
password: credentials?.current?.password,
|
|
141
|
-
projectId: currentProject,
|
|
142
|
-
rootUrl: `https://cms-${currentEnv}.cloud.contensis.com`,
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// once we have auth service, we can go and fetch out classic token
|
|
146
|
-
classicToken = await auth.ClassicToken();
|
|
147
|
-
|
|
148
104
|
// const blockId = git.name;
|
|
149
105
|
const errors = [] as AppError[];
|
|
150
106
|
|
|
151
107
|
// Start render console output
|
|
152
108
|
log.raw('');
|
|
153
109
|
log.success(messages.devinit.intro());
|
|
154
|
-
log.raw('');
|
|
155
110
|
log.raw(
|
|
156
111
|
log.infoText(
|
|
157
112
|
messages.devinit.projectDetails(
|
|
@@ -193,7 +148,6 @@ class ContensisDev extends ContensisRole {
|
|
|
193
148
|
|
|
194
149
|
log.raw(log.infoText(messages.devinit.ciDetails(ciFileName)));
|
|
195
150
|
|
|
196
|
-
let mappedWorkflow;
|
|
197
151
|
// Location for Client ID / Secret.
|
|
198
152
|
const { loc } = await inquirer.prompt({
|
|
199
153
|
name: 'loc',
|
|
@@ -213,9 +167,8 @@ class ContensisDev extends ContensisRole {
|
|
|
213
167
|
],
|
|
214
168
|
});
|
|
215
169
|
|
|
170
|
+
log.raw('');
|
|
216
171
|
log.help(messages.devinit.ciIntro(git, loc));
|
|
217
|
-
// Update CI Workflow
|
|
218
|
-
mappedWorkflow = await mapCIWorkflowContent(this, loc);
|
|
219
172
|
|
|
220
173
|
if (!dryRun) {
|
|
221
174
|
// Confirm prompt
|
|
@@ -233,7 +186,6 @@ class ContensisDev extends ContensisRole {
|
|
|
233
186
|
|
|
234
187
|
// Fetching access token
|
|
235
188
|
let accessToken: string | undefined = undefined;
|
|
236
|
-
log.raw('');
|
|
237
189
|
|
|
238
190
|
const spinner = createSpinner(messages.devinit.accessTokenFetch());
|
|
239
191
|
spinner.start();
|
|
@@ -241,9 +193,9 @@ class ContensisDev extends ContensisRole {
|
|
|
241
193
|
const token = await this.GetDeliveryApiKey();
|
|
242
194
|
|
|
243
195
|
if (token) {
|
|
244
|
-
spinner.success();
|
|
245
|
-
this.log.success(messages.devinit.accessTokenSuccess(token));
|
|
246
196
|
accessToken = token;
|
|
197
|
+
spinner.success({ text: messages.devinit.accessTokenSuccess(token) });
|
|
198
|
+
log.raw('');
|
|
247
199
|
} else {
|
|
248
200
|
spinner.error();
|
|
249
201
|
this.log.error(messages.devinit.accessTokenFailed());
|
|
@@ -261,9 +213,48 @@ class ContensisDev extends ContensisRole {
|
|
|
261
213
|
const [getRolesErr, roles] = await to(contensis.roles.GetRoles());
|
|
262
214
|
if (!roles && getRolesErr) errors.push(getRolesErr);
|
|
263
215
|
checkpoint(`fetched ${roles?.length} roles`);
|
|
216
|
+
|
|
264
217
|
if (dryRun) {
|
|
265
218
|
checkpoint(`skip api key creation (dry-run)`);
|
|
266
219
|
} else {
|
|
220
|
+
// if dev api key doesn't exist go and create it (we need this for local development, we will store these details in the .env file).
|
|
221
|
+
const devKeyExisted = !!existingDevKey;
|
|
222
|
+
if (!existingDevKey) {
|
|
223
|
+
existingDevKey = await this.CreateOrUpdateApiKey(
|
|
224
|
+
existingDevKey,
|
|
225
|
+
devKeyName,
|
|
226
|
+
devKeyDescription
|
|
227
|
+
);
|
|
228
|
+
log.success(messages.devinit.createDevKey(devKeyName, devKeyExisted));
|
|
229
|
+
}
|
|
230
|
+
// NF 24/11/23 Added this commented code back in as we are not assigning the dev key to any role here
|
|
231
|
+
// // Ensure dev API key is assigned to a role
|
|
232
|
+
// let existingDevRole = findByIdOrName(roles || [], devKeyName, true) as
|
|
233
|
+
// | Role
|
|
234
|
+
// | undefined;
|
|
235
|
+
// existingDevRole = await this.CreateOrUpdateRole(
|
|
236
|
+
// existingDevRole,
|
|
237
|
+
// devKeyRole(devKeyName, devKeyDescription)
|
|
238
|
+
// );
|
|
239
|
+
// checkpoint('dev key role assigned');
|
|
240
|
+
|
|
241
|
+
// if deploy api key doesn't exist go and create it (we need this for yml file).
|
|
242
|
+
const deployKeyExisted = !!existingDeployKey;
|
|
243
|
+
if (!existingDeployKey) {
|
|
244
|
+
existingDeployKey = await this.CreateOrUpdateApiKey(
|
|
245
|
+
existingDeployKey,
|
|
246
|
+
deployKeyName,
|
|
247
|
+
deployKeyDescription
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// check we have the deploy key so we can assign them to this values
|
|
252
|
+
if (existingDeployKey) {
|
|
253
|
+
// Add client id and secret to credentials
|
|
254
|
+
this.deployCredentials.clientId = existingDeployKey?.id;
|
|
255
|
+
this.deployCredentials.clientSecret = existingDeployKey?.sharedSecret;
|
|
256
|
+
}
|
|
257
|
+
|
|
267
258
|
// Ensure deploy API key is assigned to a role with the right permissions
|
|
268
259
|
const deployRoleName = `Role for CI push of block '${blockId}'`;
|
|
269
260
|
const deplyRoleDescription = `Created by the Contensis CLI for use in continuous integration`;
|
|
@@ -274,11 +265,13 @@ class ContensisDev extends ContensisRole {
|
|
|
274
265
|
) as Role | undefined;
|
|
275
266
|
existingDeployRole = await this.CreateOrUpdateRole(
|
|
276
267
|
existingDeployRole,
|
|
277
|
-
deployKeyRole(deployKeyName, deplyRoleDescription)
|
|
268
|
+
deployKeyRole(deployKeyName, deployRoleName, deplyRoleDescription)
|
|
278
269
|
);
|
|
279
270
|
|
|
280
271
|
checkpoint('deploy key role assigned');
|
|
281
|
-
log.success(
|
|
272
|
+
log.success(
|
|
273
|
+
messages.devinit.createDeployKey(deployRoleName, deployKeyExisted)
|
|
274
|
+
);
|
|
282
275
|
checkpoint('api keys done');
|
|
283
276
|
}
|
|
284
277
|
|
|
@@ -297,9 +290,11 @@ class ContensisDev extends ContensisRole {
|
|
|
297
290
|
if (accessToken) envContentsToAdd['ACCESS_TOKEN'] = accessToken;
|
|
298
291
|
// add client id and secret to the env file
|
|
299
292
|
if (loc === 'env') {
|
|
300
|
-
envContentsToAdd['CONTENSIS_CLIENT_ID'] =
|
|
293
|
+
envContentsToAdd['CONTENSIS_CLIENT_ID'] =
|
|
294
|
+
existingDevKey?.id || messages.devinit.dryRunKeyMessage(dryRun);
|
|
301
295
|
envContentsToAdd['CONTENSIS_CLIENT_SECRET'] =
|
|
302
|
-
existingDevKey?.sharedSecret
|
|
296
|
+
existingDevKey?.sharedSecret ||
|
|
297
|
+
messages.devinit.dryRunKeyMessage(dryRun);
|
|
303
298
|
}
|
|
304
299
|
|
|
305
300
|
// if we have client id / secret in our env remove it
|
|
@@ -339,7 +334,7 @@ class ContensisDev extends ContensisRole {
|
|
|
339
334
|
}
|
|
340
335
|
checkpoint('skip .env file update (dry-run)');
|
|
341
336
|
} else {
|
|
342
|
-
if (envDiff) log.info(`
|
|
337
|
+
if (envDiff) log.info(`Updating .env file ${winSlash(envFilePath)}`);
|
|
343
338
|
writeFile(envFilePath, envFileLines.join('\n'));
|
|
344
339
|
checkpoint('.env file updated');
|
|
345
340
|
log.success(messages.devinit.writeEnvFile());
|
|
@@ -347,9 +342,15 @@ class ContensisDev extends ContensisRole {
|
|
|
347
342
|
}
|
|
348
343
|
|
|
349
344
|
// Update git ignore
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
345
|
+
if (dryRun) {
|
|
346
|
+
checkpoint('skip .gitignore file update (dry-run)');
|
|
347
|
+
} else {
|
|
348
|
+
mergeContentsToAddWithGitignore(`${projectHome}/.gitignore`, ['.env']);
|
|
349
|
+
log.raw('');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Update CI Workflow
|
|
353
|
+
const mappedWorkflow = await mapCIWorkflowContent(this, loc);
|
|
353
354
|
|
|
354
355
|
// Update CI file -- different for GH/GL
|
|
355
356
|
if (mappedWorkflow?.diff) {
|
|
@@ -372,6 +373,7 @@ class ContensisDev extends ContensisRole {
|
|
|
372
373
|
} else {
|
|
373
374
|
log.info(messages.devinit.ciFileNoChanges(`./${ciFileName}`));
|
|
374
375
|
}
|
|
376
|
+
log.raw('');
|
|
375
377
|
checkpoint('CI file updated');
|
|
376
378
|
}
|
|
377
379
|
}
|
|
@@ -382,8 +384,9 @@ class ContensisDev extends ContensisRole {
|
|
|
382
384
|
log.help(
|
|
383
385
|
messages.devinit.addGitSecretsHelp(
|
|
384
386
|
git,
|
|
385
|
-
existingDeployKey?.id,
|
|
386
|
-
existingDeployKey?.sharedSecret
|
|
387
|
+
existingDeployKey?.id || messages.devinit.dryRunKeyMessage(dryRun),
|
|
388
|
+
existingDeployKey?.sharedSecret ||
|
|
389
|
+
messages.devinit.dryRunKeyMessage(dryRun)
|
|
387
390
|
)
|
|
388
391
|
);
|
|
389
392
|
}
|
|
@@ -395,10 +398,13 @@ class ContensisDev extends ContensisRole {
|
|
|
395
398
|
log.success(messages.devinit.success());
|
|
396
399
|
log.help(messages.devinit.startProjectTip());
|
|
397
400
|
// open the cms link -- if no classic token just return the cms url
|
|
401
|
+
|
|
402
|
+
// go and fetch the classic token from auth service
|
|
403
|
+
const classicToken = await this.auth?.ClassicToken();
|
|
398
404
|
log.help(
|
|
399
405
|
ansiEscapes.link(
|
|
400
406
|
`Open Contensis`,
|
|
401
|
-
|
|
407
|
+
`${this.urls?.cms}${
|
|
402
408
|
classicToken ? `?SecurityToken=${classicToken}` : ''
|
|
403
409
|
}`
|
|
404
410
|
)
|
package/src/shell.ts
CHANGED
|
@@ -143,6 +143,7 @@ class ContensisShell {
|
|
|
143
143
|
'execute block action makelive',
|
|
144
144
|
'execute block action rollback',
|
|
145
145
|
'execute block action markasbroken',
|
|
146
|
+
'get assets',
|
|
146
147
|
'get block',
|
|
147
148
|
'get block logs',
|
|
148
149
|
'get contenttype',
|
|
@@ -151,10 +152,13 @@ class ContensisShell {
|
|
|
151
152
|
'get nodes',
|
|
152
153
|
'get model',
|
|
153
154
|
'get project',
|
|
155
|
+
'get proxy',
|
|
156
|
+
'get renderer',
|
|
154
157
|
'get role',
|
|
155
158
|
'get token',
|
|
156
159
|
'get version',
|
|
157
160
|
'get webhook',
|
|
161
|
+
'get workflow',
|
|
158
162
|
'import contenttypes',
|
|
159
163
|
'import components',
|
|
160
164
|
'import entries',
|
|
@@ -169,11 +173,13 @@ class ContensisShell {
|
|
|
169
173
|
'list renderers',
|
|
170
174
|
'list roles',
|
|
171
175
|
'list webhooks',
|
|
176
|
+
'list workflows',
|
|
172
177
|
'push block',
|
|
173
178
|
'remove components',
|
|
174
179
|
'remove contenttypes',
|
|
175
180
|
'remove key',
|
|
176
181
|
'remove entries',
|
|
182
|
+
'remove nodes',
|
|
177
183
|
'remove role',
|
|
178
184
|
'set project name',
|
|
179
185
|
'set project description',
|
|
@@ -299,3 +305,5 @@ process.stdin.on('data', key => {
|
|
|
299
305
|
shell().quit();
|
|
300
306
|
}
|
|
301
307
|
});
|
|
308
|
+
|
|
309
|
+
// process.env.http_proxy = 'http://127.0.0.1:8888';
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { Node } from 'contensis-delivery-api/lib/models';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
|
+
import { deconstructApiError } from './error';
|
|
4
|
+
import { Logger, addNewLines } from './logger';
|
|
3
5
|
import {
|
|
4
6
|
BlockVersion,
|
|
5
7
|
EntriesResult,
|
|
6
8
|
MigrateModelsResult,
|
|
9
|
+
MigrateNodesTree,
|
|
7
10
|
MigrateStatus,
|
|
8
11
|
NodesResult,
|
|
12
|
+
ProjectNodesToMigrate,
|
|
9
13
|
} from 'migratortron';
|
|
10
14
|
import ContensisCli from '~/services/ContensisCliService';
|
|
11
|
-
import { Logger } from './logger';
|
|
12
15
|
|
|
13
16
|
const formatDate = (date: Date | string, format = 'DD/MM/YYYY HH:mm') =>
|
|
14
17
|
dayjs(date).format(format);
|
|
@@ -257,76 +260,57 @@ export const printEntriesMigrateResult = (
|
|
|
257
260
|
` - ${log.errorText(`errors: ${migrateResult.errors.length}`)}\n`
|
|
258
261
|
);
|
|
259
262
|
for (const error of migrateResult.errors)
|
|
260
|
-
log.error(error.message
|
|
263
|
+
log.error(error.message, null, '');
|
|
261
264
|
}
|
|
262
265
|
};
|
|
263
266
|
|
|
264
267
|
export const printNodesMigrateResult = (
|
|
265
|
-
{ log,
|
|
268
|
+
{ log, currentProject }: ContensisCli,
|
|
266
269
|
migrateResult: NodesResult,
|
|
267
270
|
{
|
|
268
271
|
action = 'import',
|
|
272
|
+
logLimit = 50,
|
|
269
273
|
showDiff = false,
|
|
270
274
|
showAll = false,
|
|
271
275
|
showChanged = false,
|
|
272
276
|
}: {
|
|
273
277
|
action?: 'import' | 'delete';
|
|
278
|
+
logLimit?: number;
|
|
274
279
|
showDiff?: boolean;
|
|
275
280
|
showAll?: boolean;
|
|
276
281
|
showChanged?: boolean;
|
|
277
282
|
} = {}
|
|
278
283
|
) => {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
migrateNodeId.id !== originalId ? `-> ${migrateNodeId.id}` : ''
|
|
291
|
-
}`}`
|
|
292
|
-
) + ` ${log.helpText(migrateNodeId.path)} ${migrateNodeId.displayName}`
|
|
293
|
-
);
|
|
284
|
+
log.raw(``);
|
|
285
|
+
for (const [projectId, counts] of Object.entries(migrateResult.nodes || {})) {
|
|
286
|
+
const importTitle =
|
|
287
|
+
action === 'delete'
|
|
288
|
+
? `Delete from project ${log.warningText(currentProject)}`
|
|
289
|
+
: `Import ${
|
|
290
|
+
projectId && projectId !== 'null'
|
|
291
|
+
? `from project ${log.highlightText(projectId)} `
|
|
292
|
+
: ''
|
|
293
|
+
}to ${log.boldText(log.warningText(currentProject))}`;
|
|
294
|
+
log.help(importTitle);
|
|
294
295
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
highlightDiffText(migrateNodeId.diff)
|
|
299
|
-
)}\n`
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
if (showAll || showChanged) console.log(``);
|
|
296
|
+
const migrateStatusAndCount = migrateResult.nodesToMigrate[
|
|
297
|
+
currentProject
|
|
298
|
+
] as ProjectNodesToMigrate;
|
|
304
299
|
|
|
305
|
-
for (const [projectId, counts] of Object.entries(migrateResult.nodes || {})) {
|
|
306
|
-
log.help(
|
|
307
|
-
`${action} from project ${
|
|
308
|
-
action === 'delete'
|
|
309
|
-
? log.warningText(currentProject)
|
|
310
|
-
: `${log.highlightText(projectId)} to ${log.boldText(
|
|
311
|
-
log.warningText(currentProject)
|
|
312
|
-
)}`
|
|
313
|
-
}`
|
|
314
|
-
);
|
|
315
|
-
counts.totalCount;
|
|
316
|
-
const migrateStatusAndCount = migrateResult.nodesToMigrate[currentProject];
|
|
317
300
|
const existingCount =
|
|
318
301
|
migrateResult.existing?.[currentProject]?.totalCount || 0;
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
100
|
|
329
|
-
|
|
302
|
+
|
|
303
|
+
const totalCount = Object.keys(migrateResult.nodesToMigrate.nodeIds).length;
|
|
304
|
+
const existingPercent = counts.totalCount
|
|
305
|
+
? ((existingCount / totalCount) * 100).toFixed(0)
|
|
306
|
+
: '0';
|
|
307
|
+
|
|
308
|
+
const noChangeCount = migrateStatusAndCount?.['no change'] || 0;
|
|
309
|
+
|
|
310
|
+
const changedPercentage = counts.totalCount
|
|
311
|
+
? ((noChangeCount / totalCount) * 100).toFixed(0)
|
|
312
|
+
: '0';
|
|
313
|
+
|
|
330
314
|
const existingColor =
|
|
331
315
|
existingPercent === '0' || action === 'delete'
|
|
332
316
|
? log.warningText
|
|
@@ -336,7 +320,9 @@ export const printNodesMigrateResult = (
|
|
|
336
320
|
changedPercentage === '100' ? log.successText : log.warningText;
|
|
337
321
|
|
|
338
322
|
console.log(
|
|
339
|
-
` - ${log.highlightText(
|
|
323
|
+
` - ${log.highlightText(
|
|
324
|
+
`totalCount: ${migrateStatusAndCount.totalCount}`
|
|
325
|
+
)}${
|
|
340
326
|
changedPercentage === '100'
|
|
341
327
|
? ''
|
|
342
328
|
: existingColor(` [existing: ${`${existingPercent}%`}]`)
|
|
@@ -357,10 +343,18 @@ export const printNodesMigrateResult = (
|
|
|
357
343
|
console.log(
|
|
358
344
|
` - ${log.errorText(`errors: ${migrateResult.errors.length}`)}\n`
|
|
359
345
|
);
|
|
360
|
-
|
|
361
|
-
|
|
346
|
+
|
|
347
|
+
log.limits(
|
|
348
|
+
migrateResult.errors
|
|
349
|
+
.map(error => {
|
|
350
|
+
return log.errorText(deconstructApiError(error));
|
|
351
|
+
})
|
|
352
|
+
.join('\n'),
|
|
353
|
+
logLimit
|
|
354
|
+
);
|
|
362
355
|
}
|
|
363
356
|
};
|
|
357
|
+
|
|
364
358
|
const highlightDiffText = (str: string) => {
|
|
365
359
|
const addedRegex = new RegExp(/<<\+>>(.*?)<<\/\+>>/, 'g');
|
|
366
360
|
const removedRegex = new RegExp(/<<->>(.*?)<<\/->>/, 'g');
|
|
@@ -472,41 +466,126 @@ export const printModelMigrationResult = (
|
|
|
472
466
|
};
|
|
473
467
|
|
|
474
468
|
export const printNodeTreeOutput = (
|
|
475
|
-
{ log }: ContensisCli,
|
|
476
|
-
root: Node | undefined
|
|
469
|
+
{ log, messages }: ContensisCli,
|
|
470
|
+
root: Node | MigrateNodesTree | undefined,
|
|
471
|
+
logDetail = 'errors',
|
|
472
|
+
logLimit = 1000
|
|
477
473
|
) => {
|
|
478
|
-
log.object({ ...root, children: undefined });
|
|
479
474
|
log.raw('');
|
|
475
|
+
const statusColour = messages.migrate.status;
|
|
476
|
+
|
|
477
|
+
if (root && 'status' in root)
|
|
478
|
+
log.info(
|
|
479
|
+
`Migrate status: ${statusColour('no change')(
|
|
480
|
+
'N'
|
|
481
|
+
)} [no change]; ${statusColour('create')('C')} [create]; ${statusColour(
|
|
482
|
+
'update'
|
|
483
|
+
)('U')} [update]; ${statusColour('delete')('D')} [delete]; ${statusColour(
|
|
484
|
+
'error'
|
|
485
|
+
)('E')} [error];`
|
|
486
|
+
);
|
|
480
487
|
log.info(
|
|
481
|
-
|
|
482
|
-
'
|
|
483
|
-
)} =
|
|
488
|
+
`Node properties: ${log.highlightText(
|
|
489
|
+
'e'
|
|
490
|
+
)} = has entry; ${log.highlightText('c')} = canonical; ${log.highlightText(
|
|
491
|
+
'm'
|
|
492
|
+
)} = include in menu`
|
|
484
493
|
);
|
|
494
|
+
|
|
485
495
|
log.line();
|
|
486
496
|
|
|
487
|
-
const outputNode = (
|
|
488
|
-
|
|
489
|
-
|
|
497
|
+
const outputNode = (
|
|
498
|
+
node: Node | MigrateNodesTree,
|
|
499
|
+
spaces: string,
|
|
500
|
+
isRoot = false
|
|
501
|
+
) => {
|
|
502
|
+
const errorOutput =
|
|
503
|
+
'error' in node && node.error && deconstructApiError(node.error);
|
|
504
|
+
const fullOutput = logDetail === 'all';
|
|
505
|
+
const changesOutput =
|
|
506
|
+
logDetail === 'changes' &&
|
|
507
|
+
'status' in node &&
|
|
508
|
+
['create', 'update'].includes(node.status);
|
|
509
|
+
|
|
510
|
+
const diffOutput =
|
|
511
|
+
(fullOutput || changesOutput || errorOutput) &&
|
|
512
|
+
'diff' in node &&
|
|
513
|
+
node.diff?.replaceAll('\n', '');
|
|
514
|
+
|
|
515
|
+
return `${
|
|
516
|
+
'status' in node
|
|
517
|
+
? `${statusColour(node.status)(
|
|
518
|
+
node.status.substring(0, 1).toUpperCase()
|
|
519
|
+
)} `
|
|
520
|
+
: ''
|
|
521
|
+
}${node.entry ? log.highlightText('e') : log.infoText('-')}${
|
|
522
|
+
'isCanonical' in node && node.isCanonical
|
|
523
|
+
? log.highlightText('c')
|
|
524
|
+
: log.infoText('-')
|
|
490
525
|
}${
|
|
491
526
|
node.includeInMenu ? log.highlightText('m') : log.infoText('-')
|
|
492
|
-
}${spaces}${
|
|
493
|
-
node
|
|
494
|
-
|
|
527
|
+
}${spaces}${log[
|
|
528
|
+
'status' in node && node.status === 'no change'
|
|
529
|
+
? 'infoText'
|
|
530
|
+
: 'standardText'
|
|
531
|
+
](
|
|
532
|
+
'isCanonical' in node && node.isCanonical
|
|
533
|
+
? log.boldText(fullOutput || isRoot ? node.path : `/${node.slug}`)
|
|
534
|
+
: fullOutput || isRoot
|
|
535
|
+
? node.path
|
|
536
|
+
: `/${node.slug}`
|
|
537
|
+
)}${node.entry ? ` ${log.helpText(node.entry.sys.contentTypeId)}` : ''}${
|
|
495
538
|
node.childCount ? ` +${node.childCount}` : ``
|
|
496
|
-
} ${log.infoText(node.displayName)}
|
|
539
|
+
} ${'displayName' in node ? log.infoText(node.displayName) : ''}${
|
|
540
|
+
fullOutput || (changesOutput && node.id !== node.originalId)
|
|
541
|
+
? `~n ${log.infoText(`id:`)} ${
|
|
542
|
+
node.id === node.originalId
|
|
543
|
+
? node.id
|
|
544
|
+
: `${node.id} ${log.infoText(`<= ${node.originalId}`)}`
|
|
545
|
+
}`
|
|
546
|
+
: ''
|
|
547
|
+
}${
|
|
548
|
+
(fullOutput ||
|
|
549
|
+
(changesOutput && node.parentId !== node.originalParentId)) &&
|
|
550
|
+
node.parentId
|
|
551
|
+
? `~n ${log.infoText(
|
|
552
|
+
`parentId: ${
|
|
553
|
+
node.parentId === node.originalParentId
|
|
554
|
+
? node.parentId
|
|
555
|
+
: `${node.parentId} <= ${node.originalParentId}`
|
|
556
|
+
}`
|
|
557
|
+
)}`
|
|
558
|
+
: ''
|
|
559
|
+
}${
|
|
560
|
+
fullOutput && node.entry?.sys.id
|
|
561
|
+
? `~n ${log.infoText(`entryId: ${node.entry.sys.id}`)}`
|
|
562
|
+
: ''
|
|
563
|
+
}${
|
|
564
|
+
errorOutput
|
|
565
|
+
? `~n${addNewLines(` ${log.errorText(errorOutput)}`, '~n')}`
|
|
566
|
+
: ''
|
|
567
|
+
}${
|
|
568
|
+
diffOutput
|
|
569
|
+
? `~n${addNewLines(
|
|
570
|
+
` ${log.infoText(`diff: ${highlightDiffText(diffOutput)}`)}`,
|
|
571
|
+
'~n'
|
|
572
|
+
)}`
|
|
573
|
+
: ''
|
|
574
|
+
}`;
|
|
575
|
+
};
|
|
497
576
|
|
|
498
|
-
const outputChildren = (
|
|
577
|
+
const outputChildren = (node: Node | undefined, depth = 2) => {
|
|
499
578
|
let str = '';
|
|
500
|
-
for (const
|
|
501
|
-
str += `${outputNode(
|
|
502
|
-
if ('children' in
|
|
579
|
+
for (const child of ((node as any)?.children || []) as Node[]) {
|
|
580
|
+
str += `${outputNode(child, Array(depth + 1).join(' '))}\n`;
|
|
581
|
+
if ('children' in child) str += outputChildren(child, depth + 1);
|
|
503
582
|
}
|
|
504
583
|
return str;
|
|
505
584
|
};
|
|
506
585
|
|
|
507
586
|
const children = outputChildren(root);
|
|
508
587
|
log.limits(
|
|
509
|
-
`${outputNode(root, '
|
|
510
|
-
|
|
588
|
+
`${outputNode(root || {}, ' ', true)}${children ? `\n${children}` : ''}`,
|
|
589
|
+
logLimit
|
|
511
590
|
);
|
|
512
591
|
};
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { flatten } from 'flat';
|
|
2
1
|
import { Parser } from 'json2csv';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
const flattenObject = (obj: any) => flatten(cleaner(obj, ['workflow']));
|
|
2
|
+
import { flattenObject } from './json.formatter';
|
|
6
3
|
|
|
7
4
|
export const csvFormatter = <T>(entries: T | T[]) => {
|
|
8
5
|
// Flatten the passed in object
|
package/src/util/diff.ts
CHANGED
package/src/util/find.ts
CHANGED
|
@@ -2,7 +2,18 @@ export const findByIdOrName = (arr: any[], idOrName: string, exact = false) =>
|
|
|
2
2
|
arr.find(
|
|
3
3
|
r =>
|
|
4
4
|
r.id === idOrName ||
|
|
5
|
-
r.name
|
|
5
|
+
(typeof r.name === 'string' &&
|
|
6
|
+
r.name.toLowerCase() === idOrName.toLowerCase()) ||
|
|
7
|
+
(typeof r.name === 'object' &&
|
|
8
|
+
Object.values<string>(r.name || {})?.[0].toLowerCase() ===
|
|
9
|
+
idOrName.toLowerCase())
|
|
6
10
|
) ||
|
|
7
11
|
(!exact &&
|
|
8
|
-
arr.find(
|
|
12
|
+
arr.find(
|
|
13
|
+
r =>
|
|
14
|
+
(typeof r.name === 'string' &&
|
|
15
|
+
r.name.toLowerCase().includes(idOrName.toLowerCase())) ||
|
|
16
|
+
(typeof r.name === 'object' &&
|
|
17
|
+
Object.values<string>(r.name || {})?.[0].toLowerCase() ===
|
|
18
|
+
idOrName.toLowerCase())
|
|
19
|
+
));
|