contensis-cli 1.0.12-beta.1 → 1.0.12-beta.11
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 +25 -10
- 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 +8 -2
- 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.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 +164 -75
- package/dist/services/ContensisCliService.js.map +3 -3
- package/dist/services/ContensisDevService.js +48 -53
- package/dist/services/ContensisDevService.js.map +3 -3
- package/dist/shell.js +5 -0
- package/dist/shell.js.map +2 -2
- package/dist/util/console.printer.js +111 -10
- package/dist/util/console.printer.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/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 +41 -13
- 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 +10 -3
- package/src/mappers/DevInit-to-CIWorkflow.ts +6 -8
- package/src/mappers/DevInit-to-RolePermissions.ts +1 -0
- package/src/models/Cache.d.ts +1 -1
- package/src/providers/file-provider.ts +5 -1
- package/src/services/ContensisAuthService.ts +1 -1
- package/src/services/ContensisCliService.ts +206 -101
- package/src/services/ContensisDevService.ts +70 -66
- package/src/shell.ts +5 -0
- package/src/util/console.printer.ts +238 -12
- package/src/util/error.ts +7 -0
- package/src/util/find.ts +13 -2
- package/src/util/git.ts +2 -1
- package/src/util/logger.ts +90 -15
- package/src/version.ts +1 -1
|
@@ -29,6 +29,11 @@ class ContensisDev extends ContensisRole {
|
|
|
29
29
|
git!: GitHelper;
|
|
30
30
|
blockId!: string;
|
|
31
31
|
|
|
32
|
+
deployCredentials = {
|
|
33
|
+
clientId: '',
|
|
34
|
+
clientSecret: '',
|
|
35
|
+
};
|
|
36
|
+
|
|
32
37
|
constructor(
|
|
33
38
|
args: string[],
|
|
34
39
|
outputOpts?: OutputOptionsConstructorArg,
|
|
@@ -49,8 +54,6 @@ class ContensisDev extends ContensisRole {
|
|
|
49
54
|
const contensis = await this.ConnectContensis();
|
|
50
55
|
|
|
51
56
|
if (contensis) {
|
|
52
|
-
this.devinit = { ...this.devinit, invokedBy: this.invokedBy };
|
|
53
|
-
|
|
54
57
|
// First we need to get the block id from the user
|
|
55
58
|
const validateBlockId = (blockId: string) => {
|
|
56
59
|
const pattern = /^[0-9a-z](-?[0-9a-z])*$/;
|
|
@@ -64,6 +67,7 @@ class ContensisDev extends ContensisRole {
|
|
|
64
67
|
prefix: '🧱',
|
|
65
68
|
message: messages.devinit.blockIdQuestion,
|
|
66
69
|
validate: validateBlockId,
|
|
70
|
+
default: git.name,
|
|
67
71
|
});
|
|
68
72
|
// make sure block id is lowercase
|
|
69
73
|
this.blockId = blockId.toLowerCase();
|
|
@@ -93,65 +97,17 @@ class ContensisDev extends ContensisRole {
|
|
|
93
97
|
const devKeyDescription = `Created by Contensis to allow API access from the running block`;
|
|
94
98
|
let existingDevKey = apiKeyExists(devKeyName);
|
|
95
99
|
|
|
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
100
|
const deployKeyName = `${apiKeyName}-ci`;
|
|
107
101
|
const deployKeyDescription = `Created by the Contensis CLI for use in continuous integration`;
|
|
108
102
|
|
|
109
103
|
let existingDeployKey = apiKeyExists(deployKeyName);
|
|
110
104
|
|
|
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
105
|
// const blockId = git.name;
|
|
149
106
|
const errors = [] as AppError[];
|
|
150
107
|
|
|
151
108
|
// Start render console output
|
|
152
109
|
log.raw('');
|
|
153
110
|
log.success(messages.devinit.intro());
|
|
154
|
-
log.raw('');
|
|
155
111
|
log.raw(
|
|
156
112
|
log.infoText(
|
|
157
113
|
messages.devinit.projectDetails(
|
|
@@ -193,7 +149,6 @@ class ContensisDev extends ContensisRole {
|
|
|
193
149
|
|
|
194
150
|
log.raw(log.infoText(messages.devinit.ciDetails(ciFileName)));
|
|
195
151
|
|
|
196
|
-
let mappedWorkflow;
|
|
197
152
|
// Location for Client ID / Secret.
|
|
198
153
|
const { loc } = await inquirer.prompt({
|
|
199
154
|
name: 'loc',
|
|
@@ -213,9 +168,8 @@ class ContensisDev extends ContensisRole {
|
|
|
213
168
|
],
|
|
214
169
|
});
|
|
215
170
|
|
|
171
|
+
log.raw('');
|
|
216
172
|
log.help(messages.devinit.ciIntro(git, loc));
|
|
217
|
-
// Update CI Workflow
|
|
218
|
-
mappedWorkflow = await mapCIWorkflowContent(this, loc);
|
|
219
173
|
|
|
220
174
|
if (!dryRun) {
|
|
221
175
|
// Confirm prompt
|
|
@@ -233,7 +187,6 @@ class ContensisDev extends ContensisRole {
|
|
|
233
187
|
|
|
234
188
|
// Fetching access token
|
|
235
189
|
let accessToken: string | undefined = undefined;
|
|
236
|
-
log.raw('');
|
|
237
190
|
|
|
238
191
|
const spinner = createSpinner(messages.devinit.accessTokenFetch());
|
|
239
192
|
spinner.start();
|
|
@@ -241,9 +194,9 @@ class ContensisDev extends ContensisRole {
|
|
|
241
194
|
const token = await this.GetDeliveryApiKey();
|
|
242
195
|
|
|
243
196
|
if (token) {
|
|
244
|
-
spinner.success();
|
|
245
|
-
this.log.success(messages.devinit.accessTokenSuccess(token));
|
|
246
197
|
accessToken = token;
|
|
198
|
+
spinner.success({ text: messages.devinit.accessTokenSuccess(token) });
|
|
199
|
+
log.raw('');
|
|
247
200
|
} else {
|
|
248
201
|
spinner.error();
|
|
249
202
|
this.log.error(messages.devinit.accessTokenFailed());
|
|
@@ -261,9 +214,48 @@ class ContensisDev extends ContensisRole {
|
|
|
261
214
|
const [getRolesErr, roles] = await to(contensis.roles.GetRoles());
|
|
262
215
|
if (!roles && getRolesErr) errors.push(getRolesErr);
|
|
263
216
|
checkpoint(`fetched ${roles?.length} roles`);
|
|
217
|
+
|
|
264
218
|
if (dryRun) {
|
|
265
219
|
checkpoint(`skip api key creation (dry-run)`);
|
|
266
220
|
} else {
|
|
221
|
+
// 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).
|
|
222
|
+
const devKeyExisted = !!existingDevKey;
|
|
223
|
+
if (!existingDevKey) {
|
|
224
|
+
existingDevKey = await this.CreateOrUpdateApiKey(
|
|
225
|
+
existingDevKey,
|
|
226
|
+
devKeyName,
|
|
227
|
+
devKeyDescription
|
|
228
|
+
);
|
|
229
|
+
log.success(messages.devinit.createDevKey(devKeyName, devKeyExisted));
|
|
230
|
+
}
|
|
231
|
+
// NF 24/11/23 Added this commented code back in as we are not assigning the dev key to any role here
|
|
232
|
+
// // Ensure dev API key is assigned to a role
|
|
233
|
+
// let existingDevRole = findByIdOrName(roles || [], devKeyName, true) as
|
|
234
|
+
// | Role
|
|
235
|
+
// | undefined;
|
|
236
|
+
// existingDevRole = await this.CreateOrUpdateRole(
|
|
237
|
+
// existingDevRole,
|
|
238
|
+
// devKeyRole(devKeyName, devKeyDescription)
|
|
239
|
+
// );
|
|
240
|
+
// checkpoint('dev key role assigned');
|
|
241
|
+
|
|
242
|
+
// if deploy api key doesn't exist go and create it (we need this for yml file).
|
|
243
|
+
const deployKeyExisted = !!existingDeployKey;
|
|
244
|
+
if (!existingDeployKey) {
|
|
245
|
+
existingDeployKey = await this.CreateOrUpdateApiKey(
|
|
246
|
+
existingDeployKey,
|
|
247
|
+
deployKeyName,
|
|
248
|
+
deployKeyDescription
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// check we have the deploy key so we can assign them to this values
|
|
253
|
+
if (existingDeployKey) {
|
|
254
|
+
// Add client id and secret to credentials
|
|
255
|
+
this.deployCredentials.clientId = existingDeployKey?.id;
|
|
256
|
+
this.deployCredentials.clientSecret = existingDeployKey?.sharedSecret;
|
|
257
|
+
}
|
|
258
|
+
|
|
267
259
|
// Ensure deploy API key is assigned to a role with the right permissions
|
|
268
260
|
const deployRoleName = `Role for CI push of block '${blockId}'`;
|
|
269
261
|
const deplyRoleDescription = `Created by the Contensis CLI for use in continuous integration`;
|
|
@@ -274,11 +266,13 @@ class ContensisDev extends ContensisRole {
|
|
|
274
266
|
) as Role | undefined;
|
|
275
267
|
existingDeployRole = await this.CreateOrUpdateRole(
|
|
276
268
|
existingDeployRole,
|
|
277
|
-
deployKeyRole(
|
|
269
|
+
deployKeyRole(deployRoleName, deplyRoleDescription)
|
|
278
270
|
);
|
|
279
271
|
|
|
280
272
|
checkpoint('deploy key role assigned');
|
|
281
|
-
log.success(
|
|
273
|
+
log.success(
|
|
274
|
+
messages.devinit.createDeployKey(deployRoleName, deployKeyExisted)
|
|
275
|
+
);
|
|
282
276
|
checkpoint('api keys done');
|
|
283
277
|
}
|
|
284
278
|
|
|
@@ -339,7 +333,7 @@ class ContensisDev extends ContensisRole {
|
|
|
339
333
|
}
|
|
340
334
|
checkpoint('skip .env file update (dry-run)');
|
|
341
335
|
} else {
|
|
342
|
-
if (envDiff) log.info(`
|
|
336
|
+
if (envDiff) log.info(`Updating .env file ${winSlash(envFilePath)}`);
|
|
343
337
|
writeFile(envFilePath, envFileLines.join('\n'));
|
|
344
338
|
checkpoint('.env file updated');
|
|
345
339
|
log.success(messages.devinit.writeEnvFile());
|
|
@@ -347,16 +341,21 @@ class ContensisDev extends ContensisRole {
|
|
|
347
341
|
}
|
|
348
342
|
|
|
349
343
|
// Update git ignore
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
344
|
+
if (dryRun) {
|
|
345
|
+
checkpoint('skip .gitignore file update (dry-run)');
|
|
346
|
+
} else {
|
|
347
|
+
mergeContentsToAddWithGitignore(`${projectHome}/.gitignore`, ['.env']);
|
|
348
|
+
log.raw('');
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Update CI Workflow
|
|
352
|
+
const mappedWorkflow = await mapCIWorkflowContent(this, loc);
|
|
353
353
|
|
|
354
354
|
// Update CI file -- different for GH/GL
|
|
355
355
|
if (mappedWorkflow?.diff) {
|
|
356
356
|
log.info(
|
|
357
357
|
`Updating ${winSlash(ciFileName)} file:\n${mappedWorkflow.diff}`
|
|
358
358
|
);
|
|
359
|
-
log.raw('');
|
|
360
359
|
}
|
|
361
360
|
if (dryRun) {
|
|
362
361
|
checkpoint('skip CI file update (dry-run)');
|
|
@@ -372,18 +371,20 @@ class ContensisDev extends ContensisRole {
|
|
|
372
371
|
} else {
|
|
373
372
|
log.info(messages.devinit.ciFileNoChanges(`./${ciFileName}`));
|
|
374
373
|
}
|
|
374
|
+
log.raw('');
|
|
375
375
|
checkpoint('CI file updated');
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
if (loc === 'git') {
|
|
380
380
|
// Echo Deployment API key to console, ask user to add secrets to repo
|
|
381
|
+
const dryRunKeyMessage = dryRun ? 'not created in dry-run' : undefined;
|
|
381
382
|
log.warning(messages.devinit.addGitSecretsIntro());
|
|
382
383
|
log.help(
|
|
383
384
|
messages.devinit.addGitSecretsHelp(
|
|
384
385
|
git,
|
|
385
|
-
existingDeployKey?.id,
|
|
386
|
-
existingDeployKey?.sharedSecret
|
|
386
|
+
existingDeployKey?.id || dryRunKeyMessage,
|
|
387
|
+
existingDeployKey?.sharedSecret || dryRunKeyMessage
|
|
387
388
|
)
|
|
388
389
|
);
|
|
389
390
|
}
|
|
@@ -395,10 +396,13 @@ class ContensisDev extends ContensisRole {
|
|
|
395
396
|
log.success(messages.devinit.success());
|
|
396
397
|
log.help(messages.devinit.startProjectTip());
|
|
397
398
|
// open the cms link -- if no classic token just return the cms url
|
|
399
|
+
|
|
400
|
+
// go and fetch the classic token from auth service
|
|
401
|
+
const classicToken = await this.auth?.ClassicToken();
|
|
398
402
|
log.help(
|
|
399
403
|
ansiEscapes.link(
|
|
400
404
|
`Open Contensis`,
|
|
401
|
-
|
|
405
|
+
`${this.urls?.cms}${
|
|
402
406
|
classicToken ? `?SecurityToken=${classicToken}` : ''
|
|
403
407
|
}`
|
|
404
408
|
)
|
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',
|
|
@@ -155,10 +156,12 @@ class ContensisShell {
|
|
|
155
156
|
'get token',
|
|
156
157
|
'get version',
|
|
157
158
|
'get webhook',
|
|
159
|
+
'get workflow',
|
|
158
160
|
'import contenttypes',
|
|
159
161
|
'import components',
|
|
160
162
|
'import entries',
|
|
161
163
|
'import models',
|
|
164
|
+
'import nodes',
|
|
162
165
|
'list blocks',
|
|
163
166
|
'list contenttypes',
|
|
164
167
|
'list components',
|
|
@@ -168,11 +171,13 @@ class ContensisShell {
|
|
|
168
171
|
'list renderers',
|
|
169
172
|
'list roles',
|
|
170
173
|
'list webhooks',
|
|
174
|
+
'list workflows',
|
|
171
175
|
'push block',
|
|
172
176
|
'remove components',
|
|
173
177
|
'remove contenttypes',
|
|
174
178
|
'remove key',
|
|
175
179
|
'remove entries',
|
|
180
|
+
'remove nodes',
|
|
176
181
|
'remove role',
|
|
177
182
|
'set project name',
|
|
178
183
|
'set project description',
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { Node } from 'contensis-delivery-api/lib/models';
|
|
1
2
|
import dayjs from 'dayjs';
|
|
2
|
-
import {
|
|
3
|
+
import { deconstructApiError } from './error';
|
|
4
|
+
import { Logger, addNewLines } from './logger';
|
|
5
|
+
import {
|
|
6
|
+
BlockVersion,
|
|
7
|
+
EntriesResult,
|
|
8
|
+
MigrateModelsResult,
|
|
9
|
+
MigrateNodesTree,
|
|
10
|
+
MigrateStatus,
|
|
11
|
+
NodesResult,
|
|
12
|
+
ProjectNodesToMigrate,
|
|
13
|
+
} from 'migratortron';
|
|
3
14
|
import ContensisCli from '~/services/ContensisCliService';
|
|
4
|
-
import { Logger } from './logger';
|
|
5
15
|
|
|
6
16
|
const formatDate = (date: Date | string, format = 'DD/MM/YYYY HH:mm') =>
|
|
7
17
|
dayjs(date).format(format);
|
|
@@ -104,19 +114,19 @@ export const printBlockVersion = (
|
|
|
104
114
|
console.log('');
|
|
105
115
|
};
|
|
106
116
|
|
|
107
|
-
export const
|
|
117
|
+
export const printEntriesMigrateResult = (
|
|
108
118
|
{ log, messages, currentProject }: ContensisCli,
|
|
109
|
-
migrateResult:
|
|
119
|
+
migrateResult: EntriesResult,
|
|
110
120
|
{
|
|
111
121
|
action = 'import',
|
|
112
122
|
showDiff = false,
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
showAll = false,
|
|
124
|
+
showChanged = false,
|
|
115
125
|
}: {
|
|
116
126
|
action?: 'import' | 'delete';
|
|
117
127
|
showDiff?: boolean;
|
|
118
|
-
|
|
119
|
-
|
|
128
|
+
showAll?: boolean;
|
|
129
|
+
showChanged?: boolean;
|
|
120
130
|
} = {}
|
|
121
131
|
) => {
|
|
122
132
|
console.log(``);
|
|
@@ -129,8 +139,8 @@ export const printMigrateResult = (
|
|
|
129
139
|
any
|
|
130
140
|
][]) {
|
|
131
141
|
if (
|
|
132
|
-
|
|
133
|
-
(
|
|
142
|
+
showAll ||
|
|
143
|
+
(showChanged &&
|
|
134
144
|
(
|
|
135
145
|
Object.entries(
|
|
136
146
|
Object.entries(entryStatus[currentProject])[0]
|
|
@@ -173,7 +183,7 @@ export const printMigrateResult = (
|
|
|
173
183
|
}
|
|
174
184
|
}
|
|
175
185
|
}
|
|
176
|
-
if (
|
|
186
|
+
if (showAll || showChanged) console.log(``);
|
|
177
187
|
|
|
178
188
|
for (const [projectId, contentTypeCounts] of Object.entries(
|
|
179
189
|
migrateResult.entries || {}
|
|
@@ -250,7 +260,98 @@ export const printMigrateResult = (
|
|
|
250
260
|
` - ${log.errorText(`errors: ${migrateResult.errors.length}`)}\n`
|
|
251
261
|
);
|
|
252
262
|
for (const error of migrateResult.errors)
|
|
253
|
-
log.error(error.message
|
|
263
|
+
log.error(error.message, null, '');
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
export const printNodesMigrateResult = (
|
|
268
|
+
{ log, currentProject }: ContensisCli,
|
|
269
|
+
migrateResult: NodesResult,
|
|
270
|
+
{
|
|
271
|
+
action = 'import',
|
|
272
|
+
logLimit = 50,
|
|
273
|
+
showDiff = false,
|
|
274
|
+
showAll = false,
|
|
275
|
+
showChanged = false,
|
|
276
|
+
}: {
|
|
277
|
+
action?: 'import' | 'delete';
|
|
278
|
+
logLimit?: number;
|
|
279
|
+
showDiff?: boolean;
|
|
280
|
+
showAll?: boolean;
|
|
281
|
+
showChanged?: boolean;
|
|
282
|
+
} = {}
|
|
283
|
+
) => {
|
|
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);
|
|
295
|
+
|
|
296
|
+
const migrateStatusAndCount = migrateResult.nodesToMigrate[
|
|
297
|
+
currentProject
|
|
298
|
+
] as ProjectNodesToMigrate;
|
|
299
|
+
|
|
300
|
+
const existingCount =
|
|
301
|
+
migrateResult.existing?.[currentProject]?.totalCount || 0;
|
|
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
|
+
|
|
314
|
+
const existingColor =
|
|
315
|
+
existingPercent === '0' || action === 'delete'
|
|
316
|
+
? log.warningText
|
|
317
|
+
: log.infoText;
|
|
318
|
+
|
|
319
|
+
const changedColor =
|
|
320
|
+
changedPercentage === '100' ? log.successText : log.warningText;
|
|
321
|
+
|
|
322
|
+
console.log(
|
|
323
|
+
` - ${log.highlightText(
|
|
324
|
+
`totalCount: ${migrateStatusAndCount.totalCount}`
|
|
325
|
+
)}${
|
|
326
|
+
changedPercentage === '100'
|
|
327
|
+
? ''
|
|
328
|
+
: existingColor(` [existing: ${`${existingPercent}%`}]`)
|
|
329
|
+
}${
|
|
330
|
+
existingPercent === '0'
|
|
331
|
+
? ''
|
|
332
|
+
: changedColor(
|
|
333
|
+
` ${
|
|
334
|
+
changedPercentage === '100'
|
|
335
|
+
? 'up to date'
|
|
336
|
+
: `[needs update: ${100 - Number(changedPercentage)}%]`
|
|
337
|
+
}`
|
|
338
|
+
)
|
|
339
|
+
}`
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
if (migrateResult.errors?.length) {
|
|
343
|
+
console.log(
|
|
344
|
+
` - ${log.errorText(`errors: ${migrateResult.errors.length}`)}\n`
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
log.limits(
|
|
348
|
+
migrateResult.errors
|
|
349
|
+
.map(error => {
|
|
350
|
+
return log.errorText(deconstructApiError(error));
|
|
351
|
+
})
|
|
352
|
+
.join('\n'),
|
|
353
|
+
logLimit
|
|
354
|
+
);
|
|
254
355
|
}
|
|
255
356
|
};
|
|
256
357
|
|
|
@@ -363,3 +464,128 @@ export const printModelMigrationResult = (
|
|
|
363
464
|
}
|
|
364
465
|
}
|
|
365
466
|
};
|
|
467
|
+
|
|
468
|
+
export const printNodeTreeOutput = (
|
|
469
|
+
{ log, messages }: ContensisCli,
|
|
470
|
+
root: Node | MigrateNodesTree | undefined,
|
|
471
|
+
logDetail = 'errors',
|
|
472
|
+
logLimit = 1000
|
|
473
|
+
) => {
|
|
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
|
+
);
|
|
487
|
+
log.info(
|
|
488
|
+
`Node properties: ${log.highlightText(
|
|
489
|
+
'e'
|
|
490
|
+
)} = has entry; ${log.highlightText('c')} = canonical; ${log.highlightText(
|
|
491
|
+
'm'
|
|
492
|
+
)} = include in menu`
|
|
493
|
+
);
|
|
494
|
+
|
|
495
|
+
log.line();
|
|
496
|
+
|
|
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('-')
|
|
525
|
+
}${
|
|
526
|
+
node.includeInMenu ? log.highlightText('m') : log.infoText('-')
|
|
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)}` : ''}${
|
|
538
|
+
node.childCount ? ` +${node.childCount}` : ``
|
|
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
|
+
};
|
|
576
|
+
|
|
577
|
+
const outputChildren = (node: Node | undefined, depth = 2) => {
|
|
578
|
+
let str = '';
|
|
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);
|
|
582
|
+
}
|
|
583
|
+
return str;
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
const children = outputChildren(root);
|
|
587
|
+
log.limits(
|
|
588
|
+
`${outputNode(root || {}, ' ', true)}${children ? `\n${children}` : ''}`,
|
|
589
|
+
logLimit
|
|
590
|
+
);
|
|
591
|
+
};
|
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
|
+
));
|
package/src/util/git.ts
CHANGED
|
@@ -75,7 +75,7 @@ export class GitHelper {
|
|
|
75
75
|
}
|
|
76
76
|
gitcwd = () => path.join(this.gitRepoPath);
|
|
77
77
|
gitInfo = (url: string = this.originUrl) => hostedGitInfo.fromUrl(url);
|
|
78
|
-
hostType = (url: string = this.originUrl): GitTypes => {
|
|
78
|
+
hostType = (url: string = this.originUrl): GitTypes | undefined => {
|
|
79
79
|
if (url) {
|
|
80
80
|
if (url.includes('github.com')) return 'github';
|
|
81
81
|
else return 'gitlab';
|
|
@@ -87,6 +87,7 @@ export class GitHelper {
|
|
|
87
87
|
gitConfig = (cwd = this.gitRepoPath) => {
|
|
88
88
|
// Find .git/config in project cwd
|
|
89
89
|
const config = parseGitConfig.sync({
|
|
90
|
+
cwd,
|
|
90
91
|
path: '.git/config',
|
|
91
92
|
expandKeys: true,
|
|
92
93
|
});
|