contensis-cli 1.0.0-beta.8 → 1.0.0-beta.80
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 +1146 -78
- package/dist/commands/connect.js +3 -3
- package/dist/commands/connect.js.map +2 -2
- package/dist/commands/create.js +45 -10
- package/dist/commands/create.js.map +2 -2
- package/dist/commands/diff.js +57 -0
- package/dist/commands/diff.js.map +7 -0
- package/dist/commands/execute.js +103 -0
- package/dist/commands/execute.js.map +7 -0
- package/dist/commands/get.js +107 -18
- package/dist/commands/get.js.map +2 -2
- package/dist/commands/globalOptions.js +22 -17
- package/dist/commands/globalOptions.js.map +2 -2
- package/dist/commands/import.js +46 -11
- package/dist/commands/import.js.map +2 -2
- package/dist/commands/index.js +16 -2
- package/dist/commands/index.js.map +2 -2
- package/dist/commands/list.js +53 -10
- package/dist/commands/list.js.map +2 -2
- package/dist/commands/login.js +3 -3
- package/dist/commands/login.js.map +2 -2
- package/dist/commands/push.js +9 -5
- package/dist/commands/push.js.map +2 -2
- package/dist/commands/remove.js +51 -8
- package/dist/commands/remove.js.map +2 -2
- package/dist/commands/set.js +139 -12
- package/dist/commands/set.js.map +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/localisation/en-GB.js +193 -49
- package/dist/localisation/en-GB.js.map +2 -2
- package/dist/providers/CredentialProvider.js +36 -7
- package/dist/providers/CredentialProvider.js.map +3 -3
- package/dist/providers/SessionCacheProvider.js +21 -1
- package/dist/providers/SessionCacheProvider.js.map +2 -2
- package/dist/providers/file-provider.js +8 -4
- package/dist/providers/file-provider.js.map +3 -3
- package/dist/services/ContensisCliService.js +1092 -410
- package/dist/services/ContensisCliService.js.map +3 -3
- package/dist/shell.js +48 -14
- package/dist/shell.js.map +3 -3
- package/dist/util/console.printer.js +171 -55
- package/dist/util/console.printer.js.map +2 -2
- package/dist/util/diff.js +39 -0
- package/dist/util/diff.js.map +7 -0
- package/dist/util/index.js +8 -2
- package/dist/util/index.js.map +3 -3
- package/dist/util/logger.js +61 -29
- package/dist/util/logger.js.map +3 -3
- package/dist/util/timers.js +49 -0
- package/dist/util/timers.js.map +7 -0
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/esbuild.config.js +3 -1
- package/package.json +2 -2
- package/src/commands/connect.ts +3 -2
- package/src/commands/create.ts +61 -8
- package/src/commands/diff.ts +41 -0
- package/src/commands/execute.ts +117 -0
- package/src/commands/get.ts +150 -14
- package/src/commands/globalOptions.ts +18 -17
- package/src/commands/import.ts +57 -7
- package/src/commands/index.ts +16 -1
- package/src/commands/list.ts +85 -11
- package/src/commands/login.ts +3 -2
- package/src/commands/push.ts +10 -3
- package/src/commands/remove.ts +66 -4
- package/src/commands/set.ts +189 -9
- package/src/index.ts +1 -4
- package/src/localisation/en-GB.ts +269 -66
- package/src/providers/CredentialProvider.ts +39 -6
- package/src/providers/SessionCacheProvider.ts +29 -2
- package/src/providers/file-provider.ts +12 -4
- package/src/services/ContensisCliService.ts +1384 -484
- package/src/shell.ts +52 -15
- package/src/util/console.printer.ts +240 -78
- package/src/util/diff.ts +17 -0
- package/src/util/index.ts +16 -7
- package/src/util/logger.ts +111 -31
- package/src/util/timers.ts +24 -0
- package/src/version.ts +1 -1
|
@@ -3,8 +3,16 @@ import path from 'path';
|
|
|
3
3
|
import fetch from 'node-fetch';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
5
|
import to from 'await-to-js';
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { Component, ContentType, Project } from 'contensis-core-api';
|
|
8
|
+
import {
|
|
9
|
+
isPassword,
|
|
10
|
+
isSharedSecret,
|
|
11
|
+
isUuid,
|
|
12
|
+
tryParse,
|
|
13
|
+
tryStringify,
|
|
14
|
+
url,
|
|
15
|
+
} from '~/util';
|
|
8
16
|
import SessionCacheProvider from '../providers/SessionCacheProvider';
|
|
9
17
|
import ContensisAuthService from './ContensisAuthService';
|
|
10
18
|
import CredentialProvider from '~/providers/CredentialProvider';
|
|
@@ -16,13 +24,24 @@ import {
|
|
|
16
24
|
PushBlockParams,
|
|
17
25
|
SourceCms,
|
|
18
26
|
logEntriesTable,
|
|
27
|
+
ContentTypesResult,
|
|
28
|
+
Model,
|
|
29
|
+
MigrateModelsResult,
|
|
30
|
+
BlockActionType,
|
|
19
31
|
} from 'migratortron';
|
|
20
|
-
import { Entry } from 'contensis-management-api/lib/models';
|
|
32
|
+
import { Entry, Role } from 'contensis-management-api/lib/models';
|
|
21
33
|
|
|
22
34
|
import { csvFormatter } from '~/util/csv.formatter';
|
|
23
35
|
import { xmlFormatter } from '~/util/xml.formatter';
|
|
24
36
|
import { jsonFormatter } from '~/util/json.formatter';
|
|
25
|
-
import {
|
|
37
|
+
import { diffLogStrings } from '~/util/diff';
|
|
38
|
+
import { promiseDelay } from '~/util/timers';
|
|
39
|
+
import {
|
|
40
|
+
printBlockVersion,
|
|
41
|
+
printMigrateResult,
|
|
42
|
+
printModelMigrationAnalysis,
|
|
43
|
+
printModelMigrationResult,
|
|
44
|
+
} from '~/util/console.printer';
|
|
26
45
|
import { readJsonFile } from '~/providers/file-provider';
|
|
27
46
|
|
|
28
47
|
type OutputFormat = 'json' | 'csv' | 'xml';
|
|
@@ -45,28 +64,31 @@ interface IAuthOptions {
|
|
|
45
64
|
}
|
|
46
65
|
|
|
47
66
|
interface IImportOptions {
|
|
48
|
-
|
|
67
|
+
sourceAlias?: string;
|
|
49
68
|
sourceProjectId?: string;
|
|
50
69
|
}
|
|
51
70
|
|
|
71
|
+
let insecurePasswordWarningShown = false;
|
|
72
|
+
|
|
52
73
|
class ContensisCli {
|
|
53
74
|
static quit = (error?: Error) => {
|
|
54
75
|
process.removeAllListeners('exit');
|
|
55
76
|
const exitCode = error ? 1 : 0;
|
|
56
77
|
|
|
57
|
-
console.info(`\nExiting contensis-cli with exit code: ${exitCode}\n`);
|
|
78
|
+
// console.info(`\nExiting contensis-cli with exit code: ${exitCode}\n`);
|
|
58
79
|
process.exit(exitCode);
|
|
59
80
|
};
|
|
60
81
|
|
|
61
|
-
|
|
82
|
+
private command: CliCommand;
|
|
83
|
+
private format?: OutputFormat;
|
|
84
|
+
private output?: string;
|
|
85
|
+
private session: SessionCacheProvider;
|
|
86
|
+
|
|
62
87
|
contensis?: ContensisMigrationService;
|
|
63
88
|
contensisOpts: Partial<MigrateRequest>;
|
|
64
|
-
contentTypes?: ContentType[];
|
|
65
|
-
components?: Component[];
|
|
66
|
-
currentEnv: string;
|
|
67
89
|
currentProject: string;
|
|
68
|
-
|
|
69
|
-
|
|
90
|
+
|
|
91
|
+
sourceAlias?: string;
|
|
70
92
|
targetEnv?: string;
|
|
71
93
|
urls:
|
|
72
94
|
| {
|
|
@@ -78,17 +100,42 @@ class ContensisCli {
|
|
|
78
100
|
iisPreviewWeb: string;
|
|
79
101
|
}
|
|
80
102
|
| undefined;
|
|
81
|
-
private command: CliCommand;
|
|
82
|
-
private format?: OutputFormat;
|
|
83
|
-
private output?: string;
|
|
84
103
|
log = Logger;
|
|
85
104
|
messages = LogMessages;
|
|
86
|
-
private session: SessionCacheProvider;
|
|
87
105
|
|
|
88
106
|
verb: string;
|
|
89
107
|
noun: string;
|
|
90
108
|
thirdArg: string;
|
|
91
109
|
|
|
110
|
+
get cache() {
|
|
111
|
+
return this.session.Get();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get currentEnv() {
|
|
115
|
+
return this.cache.currentEnvironment || '';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
set currentEnv(currentEnvironment: string) {
|
|
119
|
+
this.session.Update({ currentEnvironment });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
get env() {
|
|
123
|
+
const currentEnvironment = this.currentEnv;
|
|
124
|
+
const environments = this.cache.environments || {};
|
|
125
|
+
|
|
126
|
+
if (!currentEnvironment) return {} as EnvironmentCache;
|
|
127
|
+
else if (!!environments[currentEnvironment])
|
|
128
|
+
return environments[currentEnvironment];
|
|
129
|
+
else {
|
|
130
|
+
return {
|
|
131
|
+
history: [],
|
|
132
|
+
lastUserId: '',
|
|
133
|
+
projects: [],
|
|
134
|
+
versionStatus: 'latest',
|
|
135
|
+
} as EnvironmentCache;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
92
139
|
constructor(
|
|
93
140
|
args: string[],
|
|
94
141
|
outputOpts?: OutputOptions & IConnectOptions & IImportOptions,
|
|
@@ -106,40 +153,28 @@ class ContensisCli {
|
|
|
106
153
|
}`.trim();
|
|
107
154
|
|
|
108
155
|
this.session = new SessionCacheProvider();
|
|
109
|
-
|
|
156
|
+
|
|
110
157
|
this.contensisOpts = contensisOpts;
|
|
111
158
|
this.format = outputOpts?.format;
|
|
112
159
|
this.output =
|
|
113
160
|
outputOpts?.output && path.join(process.cwd(), outputOpts.output);
|
|
114
161
|
|
|
115
|
-
const currentEnvironment =
|
|
116
|
-
outputOpts?.alias || this.cache.currentEnvironment || '';
|
|
162
|
+
const currentEnvironment = outputOpts?.alias || this.currentEnv;
|
|
117
163
|
const environments = this.cache.environments || {};
|
|
118
|
-
|
|
119
|
-
if (!currentEnvironment) this.env = {} as EnvironmentCache;
|
|
120
|
-
else if (!!environments[currentEnvironment])
|
|
121
|
-
this.env = environments[currentEnvironment];
|
|
122
|
-
else {
|
|
123
|
-
this.env = {
|
|
124
|
-
history: [],
|
|
125
|
-
lastUserId: '',
|
|
126
|
-
projects: [],
|
|
127
|
-
versionStatus: 'latest',
|
|
128
|
-
};
|
|
129
|
-
}
|
|
164
|
+
this.currentEnv = currentEnvironment;
|
|
130
165
|
|
|
131
166
|
const env = this.env;
|
|
132
167
|
|
|
133
168
|
if (outputOpts?.projectId) env.currentProject = outputOpts.projectId;
|
|
134
169
|
if (outputOpts?.user) env.lastUserId = outputOpts.user;
|
|
170
|
+
// setting this in env means passwordFallback is written to environments.json
|
|
135
171
|
if (outputOpts?.password) env.passwordFallback = outputOpts.password;
|
|
136
172
|
if (outputOpts?.clientId) env.lastUserId = outputOpts.clientId;
|
|
137
173
|
if (outputOpts?.sharedSecret)
|
|
138
174
|
env.passwordFallback = outputOpts.sharedSecret;
|
|
139
175
|
|
|
140
|
-
this.currentEnv = currentEnvironment;
|
|
141
176
|
this.currentProject = env?.currentProject || 'null';
|
|
142
|
-
this.
|
|
177
|
+
this.sourceAlias = outputOpts?.sourceAlias || currentEnvironment;
|
|
143
178
|
|
|
144
179
|
if (currentEnvironment) {
|
|
145
180
|
this.urls = url(currentEnvironment, env?.currentProject || 'website');
|
|
@@ -154,7 +189,7 @@ class ContensisCli {
|
|
|
154
189
|
if (currentEnvironment) {
|
|
155
190
|
env.history = [this.command];
|
|
156
191
|
if (commandText) {
|
|
157
|
-
environments[currentEnvironment] =
|
|
192
|
+
environments[currentEnvironment] = env;
|
|
158
193
|
this.session.Update({
|
|
159
194
|
currentEnvironment,
|
|
160
195
|
environments,
|
|
@@ -181,45 +216,24 @@ class ContensisCli {
|
|
|
181
216
|
};
|
|
182
217
|
|
|
183
218
|
Connect = async (environment: string) => {
|
|
184
|
-
const {
|
|
219
|
+
const { log, messages, session } = this;
|
|
185
220
|
|
|
186
221
|
if (environment) {
|
|
187
|
-
const envCache = cache.environments[environment];
|
|
188
|
-
if (!envCache)
|
|
189
|
-
cache.environments[environment] = {
|
|
190
|
-
versionStatus: 'published',
|
|
191
|
-
history: [],
|
|
192
|
-
lastUserId: '',
|
|
193
|
-
projects: [],
|
|
194
|
-
...(!this.currentEnv ? this.env : {}),
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
this.env = cache.environments[environment];
|
|
198
222
|
this.currentEnv = environment;
|
|
199
223
|
this.urls = url(environment, 'website');
|
|
200
224
|
|
|
201
225
|
const [fetchErr, response] = await to(fetch(this.urls.cms));
|
|
202
226
|
if (response && response?.status < 400) {
|
|
203
227
|
log.success(messages.connect.connected(environment));
|
|
228
|
+
session.UpdateEnv(this.env, environment);
|
|
204
229
|
|
|
205
230
|
if (this.env?.lastUserId) {
|
|
206
|
-
await this.ConnectContensis();
|
|
231
|
+
// await this.ConnectContensis();
|
|
207
232
|
await this.PrintProjects();
|
|
208
233
|
} else {
|
|
209
234
|
log.warning(messages.projects.noList());
|
|
210
235
|
log.help(messages.connect.tip());
|
|
211
|
-
// cache.environments[environment] = {
|
|
212
|
-
// versionStatus: 'published',
|
|
213
|
-
// history: [],
|
|
214
|
-
// lastUserId: '',
|
|
215
|
-
// projects: [],
|
|
216
|
-
// };
|
|
217
236
|
}
|
|
218
|
-
|
|
219
|
-
session.Update({
|
|
220
|
-
currentEnvironment: environment,
|
|
221
|
-
environments: cache.environments,
|
|
222
|
-
});
|
|
223
237
|
} else {
|
|
224
238
|
// Cannot reach environment - status X
|
|
225
239
|
log.error(
|
|
@@ -233,68 +247,75 @@ class ContensisCli {
|
|
|
233
247
|
};
|
|
234
248
|
|
|
235
249
|
ConnectContensis = async ({ commit = false } = {}) => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
250
|
+
if (!this.contensis) {
|
|
251
|
+
const { contensisOpts, currentEnv, env, log, messages } = this;
|
|
252
|
+
const userId = env?.lastUserId;
|
|
253
|
+
const isGuidId = userId && isUuid(userId);
|
|
239
254
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
{
|
|
255
|
+
if (currentEnv && userId) {
|
|
256
|
+
const credentials = await this.GetCredentials(
|
|
243
257
|
userId,
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
env.passwordFallback
|
|
247
|
-
).Init();
|
|
258
|
+
env.passwordFallback
|
|
259
|
+
);
|
|
248
260
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
261
|
+
const cachedPassword = credentials?.current?.password;
|
|
262
|
+
|
|
263
|
+
if (cachedPassword) {
|
|
264
|
+
this.contensis = new ContensisMigrationService(
|
|
265
|
+
{
|
|
266
|
+
...contensisOpts,
|
|
267
|
+
source: {
|
|
268
|
+
url: this.urls?.cms || '',
|
|
269
|
+
username: !isGuidId ? userId : undefined,
|
|
270
|
+
password: !isGuidId ? cachedPassword : undefined,
|
|
271
|
+
clientId: isGuidId ? userId : undefined,
|
|
272
|
+
sharedSecret: isGuidId ? cachedPassword : undefined,
|
|
273
|
+
project: env?.currentProject || '',
|
|
274
|
+
assetHostname: this.urls?.previewWeb,
|
|
275
|
+
},
|
|
276
|
+
concurrency:
|
|
277
|
+
typeof contensisOpts.concurrency !== 'undefined'
|
|
278
|
+
? contensisOpts.concurrency
|
|
279
|
+
: 3,
|
|
280
|
+
outputProgress: true,
|
|
268
281
|
},
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
!commit
|
|
276
|
-
);
|
|
282
|
+
!commit
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
} else {
|
|
286
|
+
if (!currentEnv) log.help(messages.connect.help());
|
|
287
|
+
if (!userId) log.help(messages.connect.tip());
|
|
277
288
|
}
|
|
278
|
-
} else {
|
|
279
|
-
if (!currentEnv) log.help(messages.connect.help());
|
|
280
|
-
if (!userId) log.help(messages.connect.tip());
|
|
281
289
|
}
|
|
290
|
+
return this.contensis;
|
|
282
291
|
};
|
|
283
292
|
|
|
284
293
|
ConnectContensisImport = async ({
|
|
285
|
-
commit,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
fileDataType,
|
|
294
|
+
commit = false,
|
|
295
|
+
fromFile,
|
|
296
|
+
importDataType,
|
|
289
297
|
}: {
|
|
290
|
-
commit
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
298
|
+
commit?: boolean;
|
|
299
|
+
fromFile?: string;
|
|
300
|
+
importDataType?:
|
|
301
|
+
| 'entries'
|
|
302
|
+
| 'contentTypes'
|
|
303
|
+
| 'components'
|
|
304
|
+
| 'models'
|
|
305
|
+
| 'user-input';
|
|
294
306
|
}) => {
|
|
295
|
-
const
|
|
307
|
+
const source: 'contensis' | 'file' = fromFile ? 'file' : 'contensis';
|
|
308
|
+
|
|
309
|
+
const fileData = fromFile
|
|
310
|
+
? readJsonFile<(Entry | ContentType | Component)[]>(fromFile) || []
|
|
311
|
+
: [];
|
|
312
|
+
|
|
313
|
+
if (typeof fileData === 'string')
|
|
314
|
+
throw new Error(`Import file format must be of type JSON`);
|
|
315
|
+
|
|
316
|
+
const { contensisOpts, currentEnv, env, log, messages, sourceAlias } = this;
|
|
296
317
|
const environments = this.cache.environments || {};
|
|
297
|
-
const sourceEnvironment = environments[
|
|
318
|
+
const sourceEnvironment = environments[sourceAlias || ''] || {};
|
|
298
319
|
const sourceCms =
|
|
299
320
|
('source' in contensisOpts && contensisOpts.source) ||
|
|
300
321
|
({} as Partial<SourceCms>);
|
|
@@ -303,7 +324,7 @@ class ContensisCli {
|
|
|
303
324
|
const sourceProjectId =
|
|
304
325
|
sourceCms.project || sourceEnvironment.currentProject || 'website';
|
|
305
326
|
const isSourceGuidId = sourceUserId && isUuid(sourceUserId);
|
|
306
|
-
const sourceUrls = url(
|
|
327
|
+
const sourceUrls = url(sourceAlias || '', sourceProjectId);
|
|
307
328
|
|
|
308
329
|
const sourcePassword =
|
|
309
330
|
sourceCms.sharedSecret ||
|
|
@@ -314,40 +335,24 @@ class ContensisCli {
|
|
|
314
335
|
const isTargetGuidId = targetUserId && isUuid(targetUserId);
|
|
315
336
|
|
|
316
337
|
if (sourceUserId && currentEnv && targetUserId) {
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
).Init();
|
|
325
|
-
|
|
326
|
-
if (sourceCredentialError && !sourceCredentials.current) {
|
|
327
|
-
// Log problem with Credential Provider
|
|
328
|
-
logError(sourceCredentialError);
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
338
|
+
const sourceCredentials = await this.GetCredentials(
|
|
339
|
+
sourceUserId,
|
|
340
|
+
sourcePassword,
|
|
341
|
+
sourceAlias,
|
|
342
|
+
false
|
|
343
|
+
);
|
|
344
|
+
|
|
331
345
|
const cachedSourcePassword = sourceCredentials?.current?.password;
|
|
332
346
|
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
alias: currentEnv,
|
|
338
|
-
},
|
|
339
|
-
env.passwordFallback
|
|
340
|
-
).Init();
|
|
347
|
+
const targetCredentials = await this.GetCredentials(
|
|
348
|
+
targetUserId,
|
|
349
|
+
env.passwordFallback
|
|
350
|
+
);
|
|
341
351
|
|
|
342
|
-
if (targetCredentialError && !targetCredentials.current) {
|
|
343
|
-
// Log problem with Credential Provider
|
|
344
|
-
log.error(targetCredentialError as any);
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
352
|
const cachedTargetPassword = targetCredentials?.current?.password;
|
|
348
353
|
|
|
349
354
|
if (cachedSourcePassword && cachedTargetPassword) {
|
|
350
|
-
if (source === 'file' ||
|
|
355
|
+
if (source === 'file' || importDataType === 'user-input') {
|
|
351
356
|
this.contensis = new ContensisMigrationService(
|
|
352
357
|
{
|
|
353
358
|
concurrency: 3,
|
|
@@ -362,12 +367,11 @@ class ContensisCli {
|
|
|
362
367
|
targetProjects: [env.currentProject || ''],
|
|
363
368
|
assetHostname: this.urls?.previewWeb,
|
|
364
369
|
},
|
|
365
|
-
...(
|
|
370
|
+
...(importDataType ? { [importDataType]: fileData } : {}),
|
|
366
371
|
},
|
|
367
372
|
!commit
|
|
368
373
|
);
|
|
369
|
-
}
|
|
370
|
-
if (source === 'contensis') {
|
|
374
|
+
} else if (source === 'contensis') {
|
|
371
375
|
this.contensis = new ContensisMigrationService(
|
|
372
376
|
{
|
|
373
377
|
concurrency: 3,
|
|
@@ -400,6 +404,40 @@ class ContensisCli {
|
|
|
400
404
|
if (!currentEnv) log.help(messages.connect.help());
|
|
401
405
|
if (!targetUserId) log.help(messages.connect.tip());
|
|
402
406
|
}
|
|
407
|
+
return this.contensis;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
GetCredentials = async (
|
|
411
|
+
userId: string,
|
|
412
|
+
password?: string,
|
|
413
|
+
currentEnv = this.currentEnv,
|
|
414
|
+
saveCurrentEnv = true
|
|
415
|
+
): Promise<CredentialProvider | undefined> => {
|
|
416
|
+
const { log, messages } = this;
|
|
417
|
+
if (userId) {
|
|
418
|
+
const [credentialError, credentials] = await new CredentialProvider(
|
|
419
|
+
{ userId, alias: currentEnv },
|
|
420
|
+
password
|
|
421
|
+
).Init();
|
|
422
|
+
|
|
423
|
+
if (credentialError && !credentials.current) {
|
|
424
|
+
// Log problem with Credential Provider
|
|
425
|
+
log.error(credentialError as any);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (credentials.remarks.secure !== true) {
|
|
430
|
+
if (!insecurePasswordWarningShown) {
|
|
431
|
+
log.warning(messages.login.insecurePassword());
|
|
432
|
+
insecurePasswordWarningShown = true;
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
const env = this.cache.environments[currentEnv];
|
|
436
|
+
env.passwordFallback = undefined;
|
|
437
|
+
this.session.UpdateEnv(env, currentEnv, saveCurrentEnv);
|
|
438
|
+
}
|
|
439
|
+
return credentials;
|
|
440
|
+
}
|
|
403
441
|
};
|
|
404
442
|
|
|
405
443
|
Login = async (
|
|
@@ -409,111 +447,102 @@ class ContensisCli {
|
|
|
409
447
|
promptPassword = true,
|
|
410
448
|
sharedSecret = isSharedSecret(this.env.passwordFallback),
|
|
411
449
|
silent = false,
|
|
450
|
+
attempt = 1,
|
|
412
451
|
}: {
|
|
413
452
|
password?: string;
|
|
414
453
|
promptPassword?: boolean;
|
|
415
454
|
sharedSecret?: string;
|
|
416
455
|
silent?: boolean;
|
|
417
|
-
|
|
456
|
+
attempt?: number;
|
|
457
|
+
} = {}
|
|
418
458
|
): Promise<string | undefined> => {
|
|
419
|
-
let inputPassword = password;
|
|
459
|
+
let inputPassword = password || sharedSecret;
|
|
420
460
|
const { log, messages } = this;
|
|
421
461
|
|
|
422
462
|
if (userId) {
|
|
423
|
-
const {
|
|
463
|
+
const { currentEnv, env } = this;
|
|
424
464
|
|
|
425
465
|
if (currentEnv) {
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
!sharedSecret &&
|
|
445
|
-
!inputPassword &&
|
|
446
|
-
!cachedPassword &&
|
|
447
|
-
!cachedSecret &&
|
|
448
|
-
promptPassword
|
|
449
|
-
) {
|
|
450
|
-
// Password prompt
|
|
451
|
-
({ inputPassword } = await inquirer.prompt([
|
|
452
|
-
{
|
|
453
|
-
type: 'password',
|
|
454
|
-
message: messages.login.passwordPrompt(currentEnv, userId),
|
|
455
|
-
name: 'inputPassword',
|
|
456
|
-
mask: '*',
|
|
457
|
-
prefix: undefined,
|
|
458
|
-
},
|
|
459
|
-
]));
|
|
460
|
-
}
|
|
466
|
+
const credentials = await this.GetCredentials(userId, inputPassword);
|
|
467
|
+
|
|
468
|
+
if (credentials) {
|
|
469
|
+
const cachedPassword = isPassword(credentials.current?.password);
|
|
470
|
+
const cachedSecret = isSharedSecret(credentials.current?.password);
|
|
471
|
+
|
|
472
|
+
if (!cachedPassword && !cachedSecret && promptPassword) {
|
|
473
|
+
// Password prompt
|
|
474
|
+
({ inputPassword } = await inquirer.prompt([
|
|
475
|
+
{
|
|
476
|
+
type: 'password',
|
|
477
|
+
message: messages.login.passwordPrompt(currentEnv, userId),
|
|
478
|
+
name: 'inputPassword',
|
|
479
|
+
mask: '*',
|
|
480
|
+
prefix: undefined,
|
|
481
|
+
},
|
|
482
|
+
]));
|
|
483
|
+
}
|
|
461
484
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
485
|
+
if (inputPassword || cachedPassword || cachedSecret) {
|
|
486
|
+
const authService = new ContensisAuthService({
|
|
487
|
+
username: userId,
|
|
488
|
+
password: inputPassword || cachedPassword,
|
|
489
|
+
projectId: env?.currentProject || 'website',
|
|
490
|
+
rootUrl: this.urls?.cms || '',
|
|
491
|
+
clientId: userId,
|
|
492
|
+
clientSecret: sharedSecret || cachedSecret,
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
const [authError, bearerToken] = await to(
|
|
496
|
+
authService.BearerToken()
|
|
497
|
+
);
|
|
471
498
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
499
|
+
// Login successful
|
|
500
|
+
if (bearerToken) {
|
|
501
|
+
// Set env vars
|
|
502
|
+
env.authToken = bearerToken;
|
|
503
|
+
env.lastUserId = userId;
|
|
504
|
+
env.passwordFallback =
|
|
505
|
+
credentials.remarks.secure !== true
|
|
506
|
+
? credentials.current?.password
|
|
507
|
+
: undefined;
|
|
508
|
+
|
|
509
|
+
// Persist env before finding projects or doing anything else
|
|
510
|
+
this.session.UpdateEnv(env);
|
|
511
|
+
if (inputPassword) await credentials.Save(inputPassword);
|
|
512
|
+
if (sharedSecret) await credentials.Save(sharedSecret);
|
|
513
|
+
|
|
514
|
+
if (!silent) {
|
|
515
|
+
Logger.success(messages.login.success(currentEnv, userId));
|
|
516
|
+
await this.PrintProjects();
|
|
517
|
+
}
|
|
518
|
+
} else if (authError) {
|
|
519
|
+
Logger.error(authError.toString());
|
|
520
|
+
// Clear env vars
|
|
521
|
+
env.authToken = '';
|
|
522
|
+
env.lastUserId = '';
|
|
523
|
+
env.passwordFallback = undefined;
|
|
524
|
+
// Persist env to remove cleared values
|
|
525
|
+
this.session.UpdateEnv(env);
|
|
526
|
+
|
|
527
|
+
// If the auth error was raised using a cached password
|
|
528
|
+
if (
|
|
529
|
+
(cachedPassword || cachedSecret) &&
|
|
530
|
+
credentials.remarks.secure
|
|
531
|
+
) {
|
|
532
|
+
// Remove any bad stored credential and trigger login prompt again
|
|
533
|
+
await credentials.Delete();
|
|
534
|
+
return await this.Login(userId, { password, sharedSecret });
|
|
535
|
+
} else {
|
|
536
|
+
throw new Error(messages.login.failed(currentEnv, userId));
|
|
537
|
+
}
|
|
507
538
|
}
|
|
508
|
-
}
|
|
509
539
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
Logger.error(messages.login.passwordPrompt(currentEnv, userId));
|
|
540
|
+
return env.authToken;
|
|
541
|
+
} else {
|
|
542
|
+
Logger.error(messages.login.passwordPrompt());
|
|
543
|
+
if (attempt < 2)
|
|
544
|
+
return await this.Login(userId, { attempt: attempt + 1 });
|
|
545
|
+
}
|
|
517
546
|
}
|
|
518
547
|
} else {
|
|
519
548
|
// No environment set, use `contensis connect {alias}` first
|
|
@@ -525,19 +554,65 @@ class ContensisCli {
|
|
|
525
554
|
}
|
|
526
555
|
};
|
|
527
556
|
|
|
557
|
+
PrintContensisVersion = async () => {
|
|
558
|
+
const { log, messages } = this;
|
|
559
|
+
const contensis = await this.ConnectContensis();
|
|
560
|
+
|
|
561
|
+
if (contensis) {
|
|
562
|
+
// Retrieve projects list for env
|
|
563
|
+
const [projectsErr, projects] = await to(
|
|
564
|
+
contensis.projects.GetSourceProjects()
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
if (Array.isArray(projects)) {
|
|
568
|
+
// Print contensis version to console
|
|
569
|
+
this.HandleFormattingAndOutput(contensis.contensisVersion, () =>
|
|
570
|
+
log.raw(log.highlightText(contensis.contensisVersion))
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (projectsErr) {
|
|
575
|
+
log.error(messages.projects.noList());
|
|
576
|
+
log.error(projectsErr.message);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
PrintBearerToken = async () => {
|
|
582
|
+
const { log, messages } = this;
|
|
583
|
+
const contensis = await this.ConnectContensis();
|
|
584
|
+
|
|
585
|
+
if (contensis) {
|
|
586
|
+
// Retrieve token for env
|
|
587
|
+
const [error, token] = await to(
|
|
588
|
+
contensis.content.sourceRepo.repo.BearerToken()
|
|
589
|
+
);
|
|
590
|
+
if (token) {
|
|
591
|
+
// Print bearer token to console
|
|
592
|
+
this.HandleFormattingAndOutput(token, () =>
|
|
593
|
+
log.raw(log.highlightText(token))
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (error) {
|
|
598
|
+
log.error(messages.projects.noList());
|
|
599
|
+
log.error(error.message);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
|
|
528
604
|
PrintProjects = async () => {
|
|
529
|
-
const {
|
|
530
|
-
|
|
605
|
+
const { currentProject, log, messages, session } = this;
|
|
606
|
+
const contensis = await this.ConnectContensis();
|
|
531
607
|
|
|
532
|
-
if (
|
|
608
|
+
if (contensis) {
|
|
533
609
|
// Retrieve projects list for env
|
|
534
610
|
const [projectsErr, projects] = await to(
|
|
535
|
-
|
|
611
|
+
contensis.projects.GetSourceProjects()
|
|
536
612
|
);
|
|
537
613
|
|
|
538
614
|
if (Array.isArray(projects)) {
|
|
539
615
|
// save these projects in cache
|
|
540
|
-
const currentVals = cache.environments[currentEnv] || {};
|
|
541
616
|
const nextCurrentProject =
|
|
542
617
|
currentProject && currentProject !== 'null'
|
|
543
618
|
? currentProject
|
|
@@ -545,46 +620,80 @@ class ContensisCli {
|
|
|
545
620
|
? 'website'
|
|
546
621
|
: undefined;
|
|
547
622
|
|
|
548
|
-
|
|
549
|
-
...currentVals,
|
|
623
|
+
session.UpdateEnv({
|
|
550
624
|
projects: projects.map(p => p.id),
|
|
551
625
|
currentProject: nextCurrentProject,
|
|
552
|
-
};
|
|
626
|
+
});
|
|
553
627
|
|
|
554
628
|
log.success(messages.projects.list());
|
|
629
|
+
log.raw('');
|
|
630
|
+
|
|
555
631
|
this.HandleFormattingAndOutput(projects, () => {
|
|
556
632
|
// print the projects to console
|
|
557
|
-
for (const project of projects)
|
|
633
|
+
for (const project of projects.sort((a, b) =>
|
|
634
|
+
a.id.localeCompare(b.id)
|
|
635
|
+
)) {
|
|
636
|
+
let color;
|
|
637
|
+
try {
|
|
638
|
+
color = chalk.keyword((project as any).color);
|
|
639
|
+
} catch (ex) {
|
|
640
|
+
color = chalk.white;
|
|
641
|
+
}
|
|
558
642
|
console.log(
|
|
559
|
-
|
|
560
|
-
project.
|
|
561
|
-
|
|
643
|
+
`${
|
|
644
|
+
nextCurrentProject === project.id
|
|
645
|
+
? `>> ${log.boldText(color(project.id))}`
|
|
646
|
+
: ` ${color(project.id)}`
|
|
647
|
+
} ${log.infoText(
|
|
648
|
+
`[${project.supportedLanguages
|
|
649
|
+
.map(l =>
|
|
650
|
+
l === project.primaryLanguage ? `*${log.boldText(l)}` : l
|
|
651
|
+
)
|
|
652
|
+
.join(' ')}]`
|
|
653
|
+
)}`
|
|
562
654
|
);
|
|
563
655
|
}
|
|
564
656
|
});
|
|
565
657
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
658
|
+
if (!this.SetProject(nextCurrentProject))
|
|
659
|
+
log.warning(messages.projects.tip());
|
|
660
|
+
}
|
|
569
661
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
662
|
+
if (projectsErr) {
|
|
663
|
+
log.error(messages.projects.noList());
|
|
664
|
+
log.error(projectsErr.message);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
PrintProject = async (projectId = this.currentProject) => {
|
|
670
|
+
const { log, messages, session } = this;
|
|
671
|
+
const contensis = await this.ConnectContensis();
|
|
672
|
+
|
|
673
|
+
if (contensis) {
|
|
674
|
+
// Retrieve projects list for env
|
|
675
|
+
const [projectsErr, projects] = await to(
|
|
676
|
+
contensis.projects.GetSourceProjects()
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
const foundProject = projects?.find(
|
|
680
|
+
p => p.id.toLowerCase() === projectId.toLowerCase()
|
|
681
|
+
);
|
|
682
|
+
|
|
683
|
+
if (foundProject) {
|
|
684
|
+
log.raw('');
|
|
685
|
+
this.HandleFormattingAndOutput(foundProject, log.object);
|
|
574
686
|
}
|
|
575
687
|
|
|
576
688
|
if (projectsErr) {
|
|
577
689
|
log.error(messages.projects.noList());
|
|
578
690
|
log.error(projectsErr.message);
|
|
579
691
|
}
|
|
580
|
-
// } else {
|
|
581
|
-
// log.warning(messages.projects.noList());
|
|
582
|
-
// log.help(messages.connect.tip());
|
|
583
692
|
}
|
|
584
693
|
};
|
|
585
694
|
|
|
586
|
-
SetProject =
|
|
587
|
-
const {
|
|
695
|
+
SetProject = (projectId = 'website') => {
|
|
696
|
+
const { env, log, messages, session } = this;
|
|
588
697
|
let nextProjectId: string | undefined;
|
|
589
698
|
if (env?.projects.length > 0 && env?.lastUserId) {
|
|
590
699
|
nextProjectId = env.projects.find(
|
|
@@ -592,10 +701,9 @@ class ContensisCli {
|
|
|
592
701
|
);
|
|
593
702
|
if (nextProjectId) {
|
|
594
703
|
env.currentProject = nextProjectId;
|
|
595
|
-
session.
|
|
596
|
-
environments: cache.environments,
|
|
597
|
-
});
|
|
704
|
+
session.UpdateEnv(env);
|
|
598
705
|
log.success(messages.projects.set(projectId));
|
|
706
|
+
log.raw('');
|
|
599
707
|
} else {
|
|
600
708
|
log.error(messages.projects.failedSet(projectId));
|
|
601
709
|
}
|
|
@@ -607,8 +715,8 @@ class ContensisCli {
|
|
|
607
715
|
return nextProjectId;
|
|
608
716
|
};
|
|
609
717
|
|
|
610
|
-
SetVersion =
|
|
611
|
-
const {
|
|
718
|
+
SetVersion = (versionStatus: 'latest' | 'published') => {
|
|
719
|
+
const { env, log, messages, session } = this;
|
|
612
720
|
if (!['latest', 'published'].includes(versionStatus)) {
|
|
613
721
|
log.error(messages.version.invalid(versionStatus));
|
|
614
722
|
return false;
|
|
@@ -618,10 +726,7 @@ class ContensisCli {
|
|
|
618
726
|
return false;
|
|
619
727
|
}
|
|
620
728
|
if (env?.projects.length > 0 && env?.lastUserId) {
|
|
621
|
-
|
|
622
|
-
session.Update({
|
|
623
|
-
environments: cache.environments,
|
|
624
|
-
});
|
|
729
|
+
session.UpdateEnv({ versionStatus });
|
|
625
730
|
log.success(messages.version.set(this.currentEnv, versionStatus));
|
|
626
731
|
return true;
|
|
627
732
|
} else {
|
|
@@ -632,30 +737,13 @@ class ContensisCli {
|
|
|
632
737
|
}
|
|
633
738
|
};
|
|
634
739
|
|
|
635
|
-
HydrateContensis = async () => {
|
|
636
|
-
const { log } = this;
|
|
637
|
-
if (!this.contensis) await this.ConnectContensis();
|
|
638
|
-
|
|
639
|
-
if (this.contensis) {
|
|
640
|
-
// Retrieve content types list for env
|
|
641
|
-
const [contensisErr, models] = await to(
|
|
642
|
-
this.contensis.models.HydrateContensisRepositories()
|
|
643
|
-
);
|
|
644
|
-
|
|
645
|
-
if (contensisErr) {
|
|
646
|
-
log.error(contensisErr.message);
|
|
647
|
-
return contensisErr;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
|
|
652
740
|
PrintApiKeys = async () => {
|
|
653
741
|
const { currentEnv, log, messages } = this;
|
|
654
|
-
|
|
742
|
+
const contensis = await this.ConnectContensis();
|
|
655
743
|
|
|
656
|
-
if (
|
|
744
|
+
if (contensis) {
|
|
657
745
|
// Retrieve keys list for env
|
|
658
|
-
const [keysErr, apiKeys] = await
|
|
746
|
+
const [keysErr, apiKeys] = await contensis.apiKeys.GetKeys();
|
|
659
747
|
|
|
660
748
|
if (Array.isArray(apiKeys)) {
|
|
661
749
|
log.success(messages.keys.list(currentEnv));
|
|
@@ -689,70 +777,492 @@ class ContensisCli {
|
|
|
689
777
|
|
|
690
778
|
CreateApiKey = async (name: string, description?: string) => {
|
|
691
779
|
const { currentEnv, log, messages } = this;
|
|
692
|
-
|
|
780
|
+
const contensis = await this.ConnectContensis();
|
|
693
781
|
|
|
694
|
-
if (
|
|
695
|
-
const [err, key] = await
|
|
696
|
-
name,
|
|
697
|
-
description
|
|
698
|
-
);
|
|
782
|
+
if (contensis) {
|
|
783
|
+
const [err, key] = await contensis.apiKeys.CreateKey(name, description);
|
|
699
784
|
|
|
700
785
|
if (key) {
|
|
701
786
|
log.success(messages.keys.created(currentEnv, name));
|
|
702
787
|
|
|
703
788
|
// print the key details to console
|
|
704
789
|
console.log(
|
|
705
|
-
` - ${key.name}${
|
|
706
|
-
|
|
707
|
-
|
|
790
|
+
` - ${chalk.bold(key.name)} [${key.dateModified
|
|
791
|
+
.toString()
|
|
792
|
+
.substring(0, 10)} ${key.modifiedBy}]`
|
|
793
|
+
);
|
|
794
|
+
if (key.description)
|
|
795
|
+
console.log(` ${log.infoText(key.description)}`);
|
|
796
|
+
console.log(` ${chalk.bold.grey`id`}: ${key.id}`);
|
|
797
|
+
console.log(
|
|
798
|
+
` ${chalk.bold.grey`sharedSecret`}: ${key.sharedSecret}`
|
|
708
799
|
);
|
|
709
|
-
console.log(
|
|
710
|
-
|
|
800
|
+
console.log('');
|
|
801
|
+
log.help(messages.keys.tip());
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
if (err) {
|
|
805
|
+
log.error(messages.keys.failedCreate(currentEnv, name), err);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
RemoveApiKey = async (id: string) => {
|
|
811
|
+
const { currentEnv, log, messages } = this;
|
|
812
|
+
const contensis = await this.ConnectContensis({ commit: true });
|
|
813
|
+
|
|
814
|
+
if (contensis) {
|
|
815
|
+
const [err, key] = await contensis.apiKeys.RemoveKey(id);
|
|
816
|
+
|
|
817
|
+
if (!err) {
|
|
818
|
+
log.success(messages.keys.removed(currentEnv, id));
|
|
819
|
+
console.log('');
|
|
820
|
+
} else {
|
|
821
|
+
log.error(messages.keys.failedRemove(currentEnv, id), err);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
PrintRoles = async () => {
|
|
827
|
+
const { currentEnv, log, messages } = this;
|
|
828
|
+
const contensis = await this.ConnectContensis();
|
|
829
|
+
|
|
830
|
+
if (contensis) {
|
|
831
|
+
// Retrieve roles list for env
|
|
832
|
+
const [rolesErr, roles] = await to(contensis.roles.GetRoles());
|
|
833
|
+
|
|
834
|
+
if (Array.isArray(roles)) {
|
|
835
|
+
log.success(messages.roles.list(currentEnv));
|
|
836
|
+
|
|
837
|
+
if (!roles.length) log.help(messages.roles.noneExist());
|
|
838
|
+
|
|
839
|
+
this.HandleFormattingAndOutput(roles, () => {
|
|
840
|
+
// print the roles to console
|
|
841
|
+
for (const {
|
|
842
|
+
id,
|
|
843
|
+
name,
|
|
844
|
+
description,
|
|
845
|
+
enabled,
|
|
846
|
+
assignments,
|
|
847
|
+
permissions,
|
|
848
|
+
} of roles) {
|
|
849
|
+
const color = enabled ? (s: string) => s : log.infoText;
|
|
850
|
+
|
|
851
|
+
console.log(color(` - ${chalk.bold(name)} ${log.infoText(id)}`));
|
|
852
|
+
if (description) console.log(log.infoText(` ${description}`));
|
|
853
|
+
if (enabled === false)
|
|
854
|
+
console.log(` ${chalk.bold.grey('enabled')}: false`);
|
|
855
|
+
if (assignments.groups?.length)
|
|
856
|
+
console.log(
|
|
857
|
+
` ${chalk.bold.grey('groups')}: ${assignments.groups.join(
|
|
858
|
+
', '
|
|
859
|
+
)}`
|
|
860
|
+
);
|
|
861
|
+
if (assignments.users?.length)
|
|
862
|
+
console.log(
|
|
863
|
+
` ${chalk.bold.grey('users')}: ${assignments.users.join(
|
|
864
|
+
', '
|
|
865
|
+
)}`
|
|
866
|
+
);
|
|
867
|
+
if (assignments.apiKeys?.length)
|
|
868
|
+
console.log(
|
|
869
|
+
` ${chalk.bold.grey('keys')}: ${assignments.apiKeys.join(
|
|
870
|
+
', '
|
|
871
|
+
)}`
|
|
872
|
+
);
|
|
873
|
+
|
|
874
|
+
if (permissions.entries?.length) {
|
|
875
|
+
console.log(` ${chalk.bold.grey('entries')}:`);
|
|
876
|
+
for (const p of permissions.entries)
|
|
877
|
+
console.log(
|
|
878
|
+
` ${p.id}: ${log.infoText(
|
|
879
|
+
p.actions.length > 2
|
|
880
|
+
? p.actions.length
|
|
881
|
+
: p.actions.join(', ')
|
|
882
|
+
)}`
|
|
883
|
+
);
|
|
884
|
+
}
|
|
885
|
+
if (permissions.contentTypes?.length)
|
|
886
|
+
console.log(
|
|
887
|
+
` ${chalk.bold.grey(
|
|
888
|
+
'contentTypes'
|
|
889
|
+
)}: ${permissions.contentTypes
|
|
890
|
+
.map(
|
|
891
|
+
p =>
|
|
892
|
+
`${p.id} [${p.actions.join(',')}] ${p.languages.join(
|
|
893
|
+
' '
|
|
894
|
+
)}`
|
|
895
|
+
)
|
|
896
|
+
.join(', ')}`
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (rolesErr) {
|
|
903
|
+
log.error(messages.roles.noList(currentEnv));
|
|
904
|
+
log.error(jsonFormatter(rolesErr));
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
|
|
909
|
+
PrintRole = async (roleNameOrId: string) => {
|
|
910
|
+
const { currentEnv, log, messages } = this;
|
|
911
|
+
const contensis = await this.ConnectContensis();
|
|
912
|
+
|
|
913
|
+
if (contensis) {
|
|
914
|
+
// Retrieve roles list for env
|
|
915
|
+
const [rolesErr, roles] = await to(contensis.roles.GetRoles());
|
|
916
|
+
|
|
917
|
+
if (Array.isArray(roles)) {
|
|
918
|
+
log.success(messages.roles.list(currentEnv));
|
|
919
|
+
|
|
920
|
+
const role =
|
|
921
|
+
roles.find(
|
|
922
|
+
r =>
|
|
923
|
+
r.id === roleNameOrId ||
|
|
924
|
+
r.name.toLowerCase() === roleNameOrId.toLowerCase()
|
|
925
|
+
) ||
|
|
926
|
+
roles.find(r =>
|
|
927
|
+
r.name.toLowerCase().includes(roleNameOrId.toLowerCase())
|
|
928
|
+
);
|
|
929
|
+
|
|
930
|
+
if (role) this.HandleFormattingAndOutput(role, log.object);
|
|
931
|
+
else log.error(messages.roles.failedGet(currentEnv, roleNameOrId));
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
if (rolesErr) {
|
|
935
|
+
log.error(messages.roles.noList(currentEnv));
|
|
936
|
+
log.error(jsonFormatter(rolesErr));
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
CreateRole = async (role: Partial<Role>) => {
|
|
942
|
+
const { currentEnv, log, messages } = this;
|
|
943
|
+
const contensis = await this.ConnectContensis();
|
|
944
|
+
|
|
945
|
+
if (contensis) {
|
|
946
|
+
const [err, created] = await contensis.roles.CreateRole(role as Role);
|
|
947
|
+
|
|
948
|
+
if (created) {
|
|
949
|
+
log.success(
|
|
950
|
+
messages.roles.created(currentEnv, role.id || role.name || '')
|
|
951
|
+
);
|
|
952
|
+
|
|
953
|
+
this.HandleFormattingAndOutput(created, log.object);
|
|
954
|
+
|
|
955
|
+
log.help(messages.roles.tip());
|
|
956
|
+
return role.id;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
if (err) {
|
|
960
|
+
log.error(
|
|
961
|
+
messages.roles.failedCreate(currentEnv, role.id || role.name || ''),
|
|
962
|
+
err
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
UpdateRole = async (roleNameOrId: string, role: Partial<Role>) => {
|
|
969
|
+
const { currentEnv, log, messages } = this;
|
|
970
|
+
const contensis = await this.ConnectContensis();
|
|
971
|
+
|
|
972
|
+
if (contensis) {
|
|
973
|
+
// Retrieve roles list for env
|
|
974
|
+
const [rolesErr, roles] = await to(contensis.roles.GetRoles());
|
|
975
|
+
|
|
976
|
+
if (Array.isArray(roles)) {
|
|
977
|
+
log.success(messages.roles.list(currentEnv));
|
|
978
|
+
|
|
979
|
+
const existingRole = roles.find(
|
|
980
|
+
r =>
|
|
981
|
+
r.id === roleNameOrId ||
|
|
982
|
+
r.name.toLowerCase() === roleNameOrId.toLowerCase()
|
|
983
|
+
);
|
|
984
|
+
if (existingRole) {
|
|
985
|
+
log.info(messages.roles.setPayload());
|
|
986
|
+
log.object(role);
|
|
987
|
+
log.raw(``);
|
|
988
|
+
const [updateErr, updated] = await contensis.roles.UpdateRole(
|
|
989
|
+
existingRole.id,
|
|
990
|
+
role
|
|
991
|
+
);
|
|
992
|
+
if (updateErr)
|
|
993
|
+
log.error(messages.roles.failedSet(currentEnv, roleNameOrId));
|
|
994
|
+
else {
|
|
995
|
+
log.success(messages.roles.set());
|
|
996
|
+
|
|
997
|
+
this.HandleFormattingAndOutput(updated, log.object);
|
|
998
|
+
}
|
|
999
|
+
} else {
|
|
1000
|
+
// Role does not exist
|
|
1001
|
+
log.error(messages.roles.failedGet(currentEnv, roleNameOrId));
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
if (rolesErr) {
|
|
1006
|
+
log.error(messages.roles.noList(currentEnv));
|
|
1007
|
+
log.error(jsonFormatter(rolesErr));
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
RemoveRole = async (roleNameOrId: string) => {
|
|
1013
|
+
const { currentEnv, log, messages } = this;
|
|
1014
|
+
const contensis = await this.ConnectContensis();
|
|
1015
|
+
|
|
1016
|
+
if (contensis) {
|
|
1017
|
+
// Retrieve roles list for env
|
|
1018
|
+
const [rolesErr, roles] = await to(contensis.roles.GetRoles());
|
|
1019
|
+
|
|
1020
|
+
if (Array.isArray(roles)) {
|
|
1021
|
+
log.success(messages.roles.list(currentEnv));
|
|
1022
|
+
|
|
1023
|
+
const existingRole = roles.find(
|
|
1024
|
+
r =>
|
|
1025
|
+
r.id === roleNameOrId ||
|
|
1026
|
+
r.name.toLowerCase() === roleNameOrId.toLowerCase()
|
|
1027
|
+
);
|
|
1028
|
+
if (existingRole) {
|
|
1029
|
+
const [deleteErr] = await contensis.roles.RemoveRole(existingRole.id);
|
|
1030
|
+
|
|
1031
|
+
if (deleteErr)
|
|
1032
|
+
log.error(messages.roles.failedRemove(currentEnv, roleNameOrId));
|
|
1033
|
+
else log.success(messages.roles.removed(currentEnv, roleNameOrId));
|
|
1034
|
+
} else {
|
|
1035
|
+
// Role does not exist
|
|
1036
|
+
log.error(messages.roles.failedGet(currentEnv, roleNameOrId));
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
if (rolesErr) {
|
|
1041
|
+
log.error(messages.roles.noList(currentEnv));
|
|
1042
|
+
log.error(jsonFormatter(rolesErr));
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
|
|
1047
|
+
CreateProject = async (project: Project) => {
|
|
1048
|
+
const { currentEnv, log, messages } = this;
|
|
1049
|
+
const contensis = await this.ConnectContensis();
|
|
1050
|
+
|
|
1051
|
+
if (contensis) {
|
|
1052
|
+
const [err, created] = await contensis.projects.CreateProject(project);
|
|
1053
|
+
|
|
1054
|
+
if (created) {
|
|
1055
|
+
log.success(messages.projects.created(currentEnv, project.id));
|
|
1056
|
+
|
|
1057
|
+
this.HandleFormattingAndOutput(created, () => {
|
|
1058
|
+
// set the CLI project to the newly created project
|
|
1059
|
+
this.SetProject(project.id);
|
|
1060
|
+
// print all the projects to console
|
|
1061
|
+
this.PrintProjects();
|
|
1062
|
+
});
|
|
1063
|
+
return project.id;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
if (err) {
|
|
1067
|
+
log.error(messages.projects.failedCreate(currentEnv, project.id), err);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
|
|
1072
|
+
UpdateProject = async (project: Partial<Project>) => {
|
|
1073
|
+
const { currentEnv, currentProject, log, messages } = this;
|
|
1074
|
+
const contensis = await this.ConnectContensis();
|
|
1075
|
+
|
|
1076
|
+
if (contensis) {
|
|
1077
|
+
const [err, updated] = await contensis.projects.UpdateProject({
|
|
1078
|
+
id: currentProject,
|
|
1079
|
+
...project,
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
if (updated) {
|
|
1083
|
+
log.success(messages.projects.updated(currentEnv, currentProject));
|
|
1084
|
+
|
|
1085
|
+
this.HandleFormattingAndOutput(updated, log.object);
|
|
1086
|
+
return updated.id;
|
|
711
1087
|
}
|
|
712
|
-
console.log('');
|
|
713
1088
|
|
|
714
1089
|
if (err) {
|
|
715
|
-
log.error(
|
|
1090
|
+
log.error(
|
|
1091
|
+
messages.projects.failedUpdate(currentEnv, currentProject),
|
|
1092
|
+
err
|
|
1093
|
+
);
|
|
716
1094
|
}
|
|
717
1095
|
}
|
|
718
1096
|
};
|
|
719
1097
|
|
|
720
|
-
|
|
721
|
-
const {
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
const
|
|
1098
|
+
PrintContentModels = async (modelIds: string[] = []) => {
|
|
1099
|
+
const { currentProject, log, messages } = this;
|
|
1100
|
+
const contensis = await this.ConnectContensis();
|
|
1101
|
+
if (contensis) {
|
|
1102
|
+
// Retrieve models list for env
|
|
1103
|
+
const models = await contensis.models.contentModels();
|
|
1104
|
+
const contentTypes = await contensis.models.contentTypes();
|
|
1105
|
+
const components = await contensis.models.components();
|
|
1106
|
+
|
|
1107
|
+
// Models to output to console
|
|
1108
|
+
const returnModels = modelIds?.length
|
|
1109
|
+
? models?.filter((m: Model) =>
|
|
1110
|
+
modelIds.some(id => id.toLowerCase() === m.id.toLowerCase())
|
|
1111
|
+
)
|
|
1112
|
+
: undefined;
|
|
1113
|
+
|
|
1114
|
+
// Generate a list of contentTypeIds and componentIds from all models
|
|
1115
|
+
// and dependencies
|
|
1116
|
+
const contentTypeIds = Array.from(
|
|
1117
|
+
new Set([
|
|
1118
|
+
...(returnModels || models || []).map(m => m.id),
|
|
1119
|
+
...(returnModels || models || [])
|
|
1120
|
+
.map(m => m.dependencies?.contentTypes?.map(c => c[0]) || [])
|
|
1121
|
+
.flat(),
|
|
1122
|
+
])
|
|
1123
|
+
);
|
|
1124
|
+
const componentIds = Array.from(
|
|
1125
|
+
new Set(
|
|
1126
|
+
(returnModels || models || [])
|
|
1127
|
+
.map(m => m.dependencies?.components?.map(c => c[0]) || [])
|
|
1128
|
+
.flat()
|
|
1129
|
+
)
|
|
1130
|
+
);
|
|
726
1131
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
1132
|
+
// Create an array of all the content types and component definitions
|
|
1133
|
+
// we will use this when outputting to a file
|
|
1134
|
+
const contentModelBackup = [
|
|
1135
|
+
...contentTypes.filter(c =>
|
|
1136
|
+
contentTypeIds.map(i => i.toLowerCase()).includes(c.id.toLowerCase())
|
|
1137
|
+
),
|
|
1138
|
+
...components.filter(c =>
|
|
1139
|
+
componentIds.map(i => i.toLowerCase()).includes(c.id.toLowerCase())
|
|
1140
|
+
),
|
|
1141
|
+
];
|
|
1142
|
+
|
|
1143
|
+
if (Array.isArray(returnModels)) {
|
|
1144
|
+
log.success(messages.models.list(currentProject));
|
|
1145
|
+
this.HandleFormattingAndOutput(contentModelBackup, () => {
|
|
1146
|
+
// print the content models to console
|
|
1147
|
+
for (const model of returnModels) {
|
|
1148
|
+
log.raw('');
|
|
1149
|
+
log.object(model);
|
|
1150
|
+
}
|
|
1151
|
+
log.raw('');
|
|
1152
|
+
});
|
|
730
1153
|
} else {
|
|
731
|
-
log.
|
|
1154
|
+
log.success(
|
|
1155
|
+
messages.models.get(currentProject, models?.length.toString() || '0')
|
|
1156
|
+
);
|
|
1157
|
+
log.raw('');
|
|
1158
|
+
if (models?.length) {
|
|
1159
|
+
this.HandleFormattingAndOutput(contentModelBackup, () => {
|
|
1160
|
+
// print the content models to console
|
|
1161
|
+
for (const model of models) {
|
|
1162
|
+
const components = model.components?.length || 0;
|
|
1163
|
+
const contentTypes = model.contentTypes?.length || 0;
|
|
1164
|
+
const dependencies =
|
|
1165
|
+
(model.dependencies?.components?.length || 0) +
|
|
1166
|
+
(model.dependencies?.contentTypes?.length || 0);
|
|
1167
|
+
const dependencyOf =
|
|
1168
|
+
(model.dependencyOf?.components?.length || 0) +
|
|
1169
|
+
(model.dependencyOf?.contentTypes?.length || 0);
|
|
1170
|
+
|
|
1171
|
+
const hasAny =
|
|
1172
|
+
components + contentTypes + dependencies + dependencyOf;
|
|
1173
|
+
log.raw(
|
|
1174
|
+
` - ${log.highlightText(log.boldText(model.id))} ${
|
|
1175
|
+
hasAny
|
|
1176
|
+
? log.infoText(
|
|
1177
|
+
`{ ${components ? `components: ${components}, ` : ''}${
|
|
1178
|
+
contentTypes ? `contentTypes: ${contentTypes}, ` : ''
|
|
1179
|
+
}${
|
|
1180
|
+
dependencies ? `references: ${dependencies}, ` : ''
|
|
1181
|
+
}${
|
|
1182
|
+
dependencyOf ? `required by: ${dependencyOf}` : ''
|
|
1183
|
+
} }`
|
|
1184
|
+
)
|
|
1185
|
+
: ''
|
|
1186
|
+
}`
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
log.raw('');
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
732
1192
|
}
|
|
733
1193
|
}
|
|
734
1194
|
};
|
|
735
1195
|
|
|
736
|
-
|
|
1196
|
+
ImportContentModels = async ({
|
|
1197
|
+
commit,
|
|
1198
|
+
fromFile,
|
|
1199
|
+
}: {
|
|
1200
|
+
commit: boolean;
|
|
1201
|
+
fromFile: string;
|
|
1202
|
+
}) => {
|
|
737
1203
|
const { currentProject, log, messages } = this;
|
|
738
|
-
let err;
|
|
739
|
-
if (!this.contensis) err = await this.HydrateContensis();
|
|
740
1204
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1205
|
+
const fileData = fromFile
|
|
1206
|
+
? readJsonFile<(ContentType | Component)[]>(fromFile) || []
|
|
1207
|
+
: [];
|
|
1208
|
+
if (typeof fileData === 'string')
|
|
1209
|
+
throw new Error(`Import file format must be of type JSON`);
|
|
1210
|
+
|
|
1211
|
+
const contensis = await this.ConnectContensisImport({
|
|
1212
|
+
commit,
|
|
1213
|
+
fromFile,
|
|
1214
|
+
importDataType: 'models',
|
|
1215
|
+
});
|
|
1216
|
+
|
|
1217
|
+
if (contensis) {
|
|
1218
|
+
log.line();
|
|
1219
|
+
if (contensis.isPreview) {
|
|
1220
|
+
console.log(log.successText(` -- IMPORT PREVIEW -- `));
|
|
1221
|
+
} else {
|
|
1222
|
+
console.log(log.warningText(` *** COMMITTING IMPORT *** `));
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
const [migrateErr, result] = await contensis.MigrateContentModels();
|
|
1226
|
+
|
|
1227
|
+
if (migrateErr) logError(migrateErr);
|
|
1228
|
+
else
|
|
1229
|
+
this.HandleFormattingAndOutput(result, () => {
|
|
1230
|
+
// print the results to console
|
|
1231
|
+
if (!commit) {
|
|
1232
|
+
log.raw(log.boldText(`\nContent types:`));
|
|
1233
|
+
if (!result.contentTypes) log.info(`- None returned\n`);
|
|
1234
|
+
else printModelMigrationAnalysis(this, result.contentTypes);
|
|
1235
|
+
|
|
1236
|
+
log.raw(log.boldText(`\nComponents:`));
|
|
1237
|
+
if (!result.components) log.info(`- None returned\n`);
|
|
1238
|
+
else printModelMigrationAnalysis(this, result.components);
|
|
1239
|
+
} else {
|
|
1240
|
+
const migrateResult = result as MigrateModelsResult;
|
|
1241
|
+
log.raw(log.boldText(`\nContent types:`));
|
|
1242
|
+
printModelMigrationResult(
|
|
1243
|
+
this,
|
|
1244
|
+
migrateResult[currentProject].contentTypes
|
|
1245
|
+
);
|
|
1246
|
+
|
|
1247
|
+
log.raw(log.boldText(`\nComponents:`));
|
|
1248
|
+
printModelMigrationResult(
|
|
1249
|
+
this,
|
|
1250
|
+
migrateResult[currentProject].components
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
745
1254
|
} else {
|
|
746
|
-
log.warning(messages.
|
|
1255
|
+
log.warning(messages.models.noList(currentProject));
|
|
1256
|
+
log.help(messages.connect.tip());
|
|
747
1257
|
}
|
|
748
1258
|
};
|
|
749
1259
|
|
|
750
1260
|
PrintContentTypes = async () => {
|
|
751
1261
|
const { currentProject, log, messages } = this;
|
|
752
|
-
await this.
|
|
753
|
-
if (
|
|
1262
|
+
const contensis = await this.ConnectContensis();
|
|
1263
|
+
if (contensis) {
|
|
754
1264
|
// Retrieve content types list for env
|
|
755
|
-
const
|
|
1265
|
+
const contentTypes = await contensis.models.contentTypes();
|
|
756
1266
|
|
|
757
1267
|
if (Array.isArray(contentTypes)) {
|
|
758
1268
|
log.success(messages.contenttypes.list(currentProject));
|
|
@@ -773,10 +1283,10 @@ class ContensisCli {
|
|
|
773
1283
|
|
|
774
1284
|
PrintContentType = async (contentTypeId: string) => {
|
|
775
1285
|
const { currentProject, log, messages } = this;
|
|
776
|
-
await this.
|
|
777
|
-
if (
|
|
1286
|
+
const contensis = await this.ConnectContensis();
|
|
1287
|
+
if (contensis) {
|
|
778
1288
|
// Retrieve content types list for env
|
|
779
|
-
const
|
|
1289
|
+
const contentTypes = await contensis.models.contentTypes();
|
|
780
1290
|
|
|
781
1291
|
if (Array.isArray(contentTypes)) {
|
|
782
1292
|
const contentType = contentTypes.find(
|
|
@@ -799,15 +1309,12 @@ class ContensisCli {
|
|
|
799
1309
|
|
|
800
1310
|
RemoveContentTypes = async (contentTypeIds: string[], commit = false) => {
|
|
801
1311
|
const { currentProject, log, messages } = this;
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
const [err, result] = await this.contensis.DeleteContentTypes(
|
|
809
|
-
contentTypeIds
|
|
810
|
-
);
|
|
1312
|
+
const contensis = await this.ConnectContensisImport({
|
|
1313
|
+
commit,
|
|
1314
|
+
importDataType: 'user-input',
|
|
1315
|
+
});
|
|
1316
|
+
if (contensis) {
|
|
1317
|
+
const [err, result] = await contensis.DeleteContentTypes(contentTypeIds);
|
|
811
1318
|
|
|
812
1319
|
if (err) {
|
|
813
1320
|
log.error(
|
|
@@ -822,7 +1329,7 @@ class ContensisCli {
|
|
|
822
1329
|
messages.contenttypes.removed(
|
|
823
1330
|
currentProject,
|
|
824
1331
|
contentTypeIds.join('", "'),
|
|
825
|
-
!
|
|
1332
|
+
!contensis.isPreview
|
|
826
1333
|
)
|
|
827
1334
|
);
|
|
828
1335
|
// print the results to console
|
|
@@ -851,22 +1358,21 @@ class ContensisCli {
|
|
|
851
1358
|
|
|
852
1359
|
if (!Array.isArray(fileData)) fileData = [fileData];
|
|
853
1360
|
|
|
854
|
-
await this.ConnectContensisImport({
|
|
1361
|
+
const contensis = await this.ConnectContensisImport({
|
|
855
1362
|
commit,
|
|
856
|
-
|
|
1363
|
+
importDataType: fromFile ? 'user-input' : undefined,
|
|
857
1364
|
});
|
|
858
1365
|
|
|
859
|
-
if (
|
|
1366
|
+
if (contensis) {
|
|
860
1367
|
// Pass each content type to the target repo
|
|
861
1368
|
for (const contentType of fileData) {
|
|
862
1369
|
// Fix invalid data
|
|
863
1370
|
contentType.projectId = currentProject;
|
|
864
1371
|
delete contentType.uuid;
|
|
865
1372
|
|
|
866
|
-
const [err, created, createStatus] =
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
].repo.UpsertContentType(false, contentType);
|
|
1373
|
+
const [err, created, createStatus] = await contensis.models.targetRepos[
|
|
1374
|
+
currentProject
|
|
1375
|
+
].repo.UpsertContentType(false, contentType);
|
|
870
1376
|
|
|
871
1377
|
if (err) log.error(err.message, err);
|
|
872
1378
|
if (createStatus) {
|
|
@@ -884,12 +1390,59 @@ class ContensisCli {
|
|
|
884
1390
|
}
|
|
885
1391
|
};
|
|
886
1392
|
|
|
1393
|
+
DiffModels = async (
|
|
1394
|
+
{
|
|
1395
|
+
fromFile,
|
|
1396
|
+
}: {
|
|
1397
|
+
fromFile: string;
|
|
1398
|
+
},
|
|
1399
|
+
modelIds: string[] = []
|
|
1400
|
+
) => {
|
|
1401
|
+
const { log } = this;
|
|
1402
|
+
|
|
1403
|
+
let fileData = fromFile ? readJsonFile<ContentType[]>(fromFile) || [] : [];
|
|
1404
|
+
if (typeof fileData === 'string')
|
|
1405
|
+
throw new Error(`Import file format must be of type JSON`);
|
|
1406
|
+
|
|
1407
|
+
if (!Array.isArray(fileData)) fileData = [fileData];
|
|
1408
|
+
|
|
1409
|
+
const contensis = await this.ConnectContensisImport({
|
|
1410
|
+
fromFile,
|
|
1411
|
+
importDataType: 'models',
|
|
1412
|
+
});
|
|
1413
|
+
|
|
1414
|
+
if (contensis) {
|
|
1415
|
+
const [err, result] = (await to(
|
|
1416
|
+
contensis.models.Diff(fileData.length ? fileData : modelIds)
|
|
1417
|
+
)) as [Error | null, ContentTypesResult | undefined];
|
|
1418
|
+
|
|
1419
|
+
if (err) log.error(err.message, err);
|
|
1420
|
+
if (result)
|
|
1421
|
+
// print the content type to console
|
|
1422
|
+
this.HandleFormattingAndOutput(result, () => {
|
|
1423
|
+
log.success(
|
|
1424
|
+
`Queried models ${log.infoText(
|
|
1425
|
+
`"${result.query.modelIds?.join(', ')}"`
|
|
1426
|
+
)}\n`
|
|
1427
|
+
);
|
|
1428
|
+
|
|
1429
|
+
log.raw(log.boldText(`Content types:`));
|
|
1430
|
+
if (!result.contentTypes) log.info(`- None returned\n`);
|
|
1431
|
+
else printModelMigrationAnalysis(this, result.contentTypes);
|
|
1432
|
+
|
|
1433
|
+
log.raw(log.boldText(`Components:`));
|
|
1434
|
+
if (!result.components) log.info(`- None returned\n`);
|
|
1435
|
+
else printModelMigrationAnalysis(this, result.components);
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
|
|
887
1440
|
PrintComponents = async () => {
|
|
888
1441
|
const { currentProject, log, messages } = this;
|
|
889
|
-
await this.
|
|
890
|
-
if (
|
|
1442
|
+
const contensis = await this.ConnectContensis();
|
|
1443
|
+
if (contensis) {
|
|
891
1444
|
// Retrieve components list for env
|
|
892
|
-
const
|
|
1445
|
+
const components = await contensis.models.components();
|
|
893
1446
|
|
|
894
1447
|
if (Array.isArray(components)) {
|
|
895
1448
|
log.success(messages.components.list(currentProject));
|
|
@@ -911,10 +1464,10 @@ class ContensisCli {
|
|
|
911
1464
|
|
|
912
1465
|
PrintComponent = async (componentId: string) => {
|
|
913
1466
|
const { currentProject, log, messages } = this;
|
|
914
|
-
await this.
|
|
915
|
-
if (
|
|
1467
|
+
const contensis = await this.ConnectContensis();
|
|
1468
|
+
if (contensis) {
|
|
916
1469
|
// Retrieve content types list for env
|
|
917
|
-
const
|
|
1470
|
+
const components = await contensis.models.components();
|
|
918
1471
|
|
|
919
1472
|
if (Array.isArray(components)) {
|
|
920
1473
|
const component = components.find(
|
|
@@ -933,13 +1486,12 @@ class ContensisCli {
|
|
|
933
1486
|
|
|
934
1487
|
RemoveComponents = async (componentIds: string[], commit = false) => {
|
|
935
1488
|
const { currentProject, log, messages } = this;
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
const [err, result] = await this.contensis.DeleteContentTypes(
|
|
1489
|
+
const contensis = await this.ConnectContensisImport({
|
|
1490
|
+
commit,
|
|
1491
|
+
importDataType: 'user-input',
|
|
1492
|
+
});
|
|
1493
|
+
if (contensis) {
|
|
1494
|
+
const [err, result] = await contensis.DeleteContentTypes(
|
|
943
1495
|
undefined,
|
|
944
1496
|
componentIds
|
|
945
1497
|
);
|
|
@@ -957,7 +1509,7 @@ class ContensisCli {
|
|
|
957
1509
|
messages.components.removed(
|
|
958
1510
|
currentProject,
|
|
959
1511
|
componentIds.join('", "'),
|
|
960
|
-
!
|
|
1512
|
+
!contensis.isPreview
|
|
961
1513
|
)
|
|
962
1514
|
);
|
|
963
1515
|
// print the results to console
|
|
@@ -986,22 +1538,21 @@ class ContensisCli {
|
|
|
986
1538
|
|
|
987
1539
|
if (!Array.isArray(fileData)) fileData = [fileData];
|
|
988
1540
|
|
|
989
|
-
await this.ConnectContensisImport({
|
|
1541
|
+
const contensis = await this.ConnectContensisImport({
|
|
990
1542
|
commit,
|
|
991
|
-
|
|
1543
|
+
importDataType: fromFile ? 'user-input' : undefined,
|
|
992
1544
|
});
|
|
993
1545
|
|
|
994
|
-
if (
|
|
1546
|
+
if (contensis) {
|
|
995
1547
|
// Pass each component to the target repo
|
|
996
1548
|
for (const component of fileData) {
|
|
997
1549
|
// Fix invalid data
|
|
998
1550
|
component.projectId = currentProject;
|
|
999
1551
|
delete component.uuid;
|
|
1000
1552
|
|
|
1001
|
-
const [err, created, createStatus] =
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
].repo.UpsertComponent(false, component);
|
|
1553
|
+
const [err, created, createStatus] = await contensis.models.targetRepos[
|
|
1554
|
+
currentProject
|
|
1555
|
+
].repo.UpsertComponent(false, component);
|
|
1005
1556
|
|
|
1006
1557
|
if (err) log.error(err.message, err);
|
|
1007
1558
|
if (createStatus) {
|
|
@@ -1019,38 +1570,42 @@ class ContensisCli {
|
|
|
1019
1570
|
}
|
|
1020
1571
|
};
|
|
1021
1572
|
|
|
1022
|
-
|
|
1023
|
-
const { currentEnv, log, messages } = this;
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
});
|
|
1573
|
+
RemoveEntries = async (commit = false) => {
|
|
1574
|
+
const { currentEnv, currentProject, log, messages } = this;
|
|
1575
|
+
const contensis = await this.ConnectContensisImport({
|
|
1576
|
+
commit,
|
|
1577
|
+
importDataType: 'user-input',
|
|
1578
|
+
});
|
|
1029
1579
|
|
|
1030
|
-
if (
|
|
1031
|
-
if (
|
|
1580
|
+
if (contensis) {
|
|
1581
|
+
if (contensis.isPreview) {
|
|
1032
1582
|
console.log(log.successText(` -- PREVIEW -- `));
|
|
1033
1583
|
} else {
|
|
1034
1584
|
console.log(log.warningText(` *** COMMITTING DELETE *** `));
|
|
1035
1585
|
}
|
|
1036
|
-
const [err, result] = await
|
|
1586
|
+
const [err, result] = await contensis.DeleteEntries();
|
|
1037
1587
|
if (result)
|
|
1038
1588
|
this.HandleFormattingAndOutput(result, () => {
|
|
1039
1589
|
// print the migrateResult to console
|
|
1040
|
-
printMigrateResult(this, result, {
|
|
1590
|
+
printMigrateResult(this, result, {
|
|
1591
|
+
action: 'delete',
|
|
1592
|
+
showAllEntries: true,
|
|
1593
|
+
});
|
|
1041
1594
|
});
|
|
1042
1595
|
if (
|
|
1043
1596
|
!err &&
|
|
1044
|
-
((!commit &&
|
|
1045
|
-
Object.values(result.entriesToMigrate)?.[0].totalCount > 0) ||
|
|
1597
|
+
((!commit && result.entriesToMigrate[currentProject].totalCount) ||
|
|
1046
1598
|
(commit && result.migrateResult?.deleted))
|
|
1047
1599
|
) {
|
|
1048
|
-
log.success(messages.entries.removed(currentEnv,
|
|
1049
|
-
if (!commit)
|
|
1600
|
+
log.success(messages.entries.removed(currentEnv, commit));
|
|
1601
|
+
if (!commit) {
|
|
1602
|
+
log.raw(``);
|
|
1603
|
+
log.help(messages.entries.commitTip());
|
|
1604
|
+
}
|
|
1050
1605
|
} else {
|
|
1051
|
-
log.error(messages.entries.failedRemove(currentEnv
|
|
1052
|
-
if (!
|
|
1053
|
-
log.help(messages.entries.notFound(
|
|
1606
|
+
log.error(messages.entries.failedRemove(currentEnv), err);
|
|
1607
|
+
if (!result.entriesToMigrate[currentProject].totalCount)
|
|
1608
|
+
log.help(messages.entries.notFound(currentEnv));
|
|
1054
1609
|
}
|
|
1055
1610
|
}
|
|
1056
1611
|
};
|
|
@@ -1061,21 +1616,21 @@ class ContensisCli {
|
|
|
1061
1616
|
withDependents?: boolean;
|
|
1062
1617
|
}) => {
|
|
1063
1618
|
const { currentProject, log, messages } = this;
|
|
1064
|
-
await this.ConnectContensis();
|
|
1619
|
+
const contensis = await this.ConnectContensis();
|
|
1065
1620
|
|
|
1066
|
-
if (
|
|
1621
|
+
if (contensis) {
|
|
1067
1622
|
log.line();
|
|
1068
|
-
const entries = await
|
|
1623
|
+
const entries = await contensis.GetEntries({ withDependents });
|
|
1069
1624
|
this.HandleFormattingAndOutput(entries, () =>
|
|
1070
1625
|
// print the entries to console
|
|
1071
1626
|
logEntriesTable(
|
|
1072
1627
|
entries,
|
|
1073
1628
|
currentProject,
|
|
1074
|
-
|
|
1629
|
+
contensis.payload.query?.fields
|
|
1075
1630
|
)
|
|
1076
1631
|
);
|
|
1077
1632
|
} else {
|
|
1078
|
-
log.warning(messages.
|
|
1633
|
+
log.warning(messages.models.noList(currentProject));
|
|
1079
1634
|
log.help(messages.connect.tip());
|
|
1080
1635
|
}
|
|
1081
1636
|
};
|
|
@@ -1083,89 +1638,157 @@ class ContensisCli {
|
|
|
1083
1638
|
ImportEntries = async ({
|
|
1084
1639
|
commit,
|
|
1085
1640
|
fromFile,
|
|
1641
|
+
logOutput,
|
|
1086
1642
|
}: {
|
|
1087
1643
|
commit: boolean;
|
|
1088
1644
|
fromFile: string;
|
|
1645
|
+
logOutput: string;
|
|
1089
1646
|
}) => {
|
|
1090
|
-
const { currentProject, log, messages } = this;
|
|
1091
|
-
|
|
1092
|
-
const fileData = fromFile ? readJsonFile<Entry[]>(fromFile) || [] : [];
|
|
1093
|
-
if (typeof fileData === 'string')
|
|
1094
|
-
throw new Error(`Import file format must be of type JSON`);
|
|
1647
|
+
const { currentEnv, currentProject, log, messages } = this;
|
|
1095
1648
|
|
|
1096
|
-
await this.ConnectContensisImport({
|
|
1649
|
+
const contensis = await this.ConnectContensisImport({
|
|
1097
1650
|
commit,
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
fileDataType: 'entries',
|
|
1651
|
+
fromFile,
|
|
1652
|
+
importDataType: 'entries',
|
|
1101
1653
|
});
|
|
1102
1654
|
|
|
1103
|
-
if (
|
|
1655
|
+
if (contensis) {
|
|
1104
1656
|
log.line();
|
|
1105
|
-
if (
|
|
1657
|
+
if (contensis.isPreview) {
|
|
1106
1658
|
console.log(log.successText(` -- IMPORT PREVIEW -- `));
|
|
1107
1659
|
} else {
|
|
1108
1660
|
console.log(log.warningText(` *** COMMITTING IMPORT *** `));
|
|
1109
1661
|
}
|
|
1110
1662
|
|
|
1111
|
-
const [
|
|
1663
|
+
const [err, result] = await contensis.MigrateEntries();
|
|
1112
1664
|
|
|
1113
|
-
if (
|
|
1665
|
+
if (err) logError(err);
|
|
1114
1666
|
else
|
|
1115
|
-
this.HandleFormattingAndOutput(
|
|
1667
|
+
this.HandleFormattingAndOutput(result, () => {
|
|
1116
1668
|
// print the migrateResult to console
|
|
1117
|
-
printMigrateResult(this,
|
|
1669
|
+
printMigrateResult(this, result, {
|
|
1670
|
+
showAllEntries: logOutput === 'all',
|
|
1671
|
+
showChangedEntries: logOutput === 'changes',
|
|
1672
|
+
});
|
|
1118
1673
|
});
|
|
1674
|
+
|
|
1675
|
+
if (
|
|
1676
|
+
!err &&
|
|
1677
|
+
!result.errors?.length &&
|
|
1678
|
+
((!commit && result.entriesToMigrate[currentProject].totalCount) ||
|
|
1679
|
+
(commit &&
|
|
1680
|
+
(result.migrateResult?.created || result.migrateResult?.updated)))
|
|
1681
|
+
) {
|
|
1682
|
+
log.success(
|
|
1683
|
+
messages.entries.imported(
|
|
1684
|
+
currentEnv,
|
|
1685
|
+
commit,
|
|
1686
|
+
commit
|
|
1687
|
+
? (result.migrateResult?.created || 0) +
|
|
1688
|
+
(result.migrateResult?.updated || 0)
|
|
1689
|
+
: result.entriesToMigrate[currentProject].totalCount
|
|
1690
|
+
)
|
|
1691
|
+
);
|
|
1692
|
+
if (!commit) {
|
|
1693
|
+
log.raw(``);
|
|
1694
|
+
log.help(messages.entries.commitTip());
|
|
1695
|
+
}
|
|
1696
|
+
} else {
|
|
1697
|
+
log.error(messages.entries.failedImport(currentEnv), err);
|
|
1698
|
+
if (!result.entriesToMigrate[currentProject].totalCount)
|
|
1699
|
+
log.help(messages.entries.notFound(currentEnv));
|
|
1700
|
+
}
|
|
1119
1701
|
} else {
|
|
1120
|
-
log.warning(messages.
|
|
1702
|
+
log.warning(messages.models.noList(currentProject));
|
|
1121
1703
|
log.help(messages.connect.tip());
|
|
1122
1704
|
}
|
|
1123
1705
|
};
|
|
1124
1706
|
|
|
1125
|
-
PrintWebhookSubscriptions = async (
|
|
1126
|
-
subscriptionIds?: string[],
|
|
1127
|
-
name?: string
|
|
1128
|
-
) => {
|
|
1707
|
+
PrintWebhookSubscriptions = async (subscriptionIdsOrNames?: string[]) => {
|
|
1129
1708
|
const { currentEnv, log, messages } = this;
|
|
1130
|
-
|
|
1131
|
-
if (
|
|
1709
|
+
const contensis = await this.ConnectContensis();
|
|
1710
|
+
if (contensis) {
|
|
1132
1711
|
// Retrieve webhooks list for env
|
|
1133
1712
|
const [webhooksErr, webhooks] =
|
|
1134
|
-
await
|
|
1135
|
-
|
|
1136
|
-
const filteredResults =
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1713
|
+
await contensis.subscriptions.webhooks.GetSubscriptions();
|
|
1714
|
+
|
|
1715
|
+
const filteredResults = subscriptionIdsOrNames?.length
|
|
1716
|
+
? webhooks?.filter(
|
|
1717
|
+
w =>
|
|
1718
|
+
subscriptionIdsOrNames?.some(idname =>
|
|
1719
|
+
w.name?.toLowerCase().includes(idname.toLowerCase())
|
|
1720
|
+
) ||
|
|
1721
|
+
subscriptionIdsOrNames?.some(
|
|
1722
|
+
id => id.toLowerCase() === w.id.toLowerCase()
|
|
1723
|
+
)
|
|
1724
|
+
)
|
|
1725
|
+
: webhooks;
|
|
1144
1726
|
|
|
1145
1727
|
if (Array.isArray(filteredResults)) {
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1728
|
+
log.success(messages.webhooks.list(currentEnv));
|
|
1729
|
+
if (!webhooks?.length) log.warning(messages.webhooks.noneExist());
|
|
1730
|
+
else {
|
|
1731
|
+
this.HandleFormattingAndOutput(filteredResults, () => {
|
|
1732
|
+
// print the keys to console
|
|
1733
|
+
for (const {
|
|
1734
|
+
id,
|
|
1735
|
+
description,
|
|
1736
|
+
method,
|
|
1737
|
+
name,
|
|
1738
|
+
version,
|
|
1739
|
+
url,
|
|
1740
|
+
enabled,
|
|
1741
|
+
topics,
|
|
1742
|
+
templates,
|
|
1743
|
+
headers,
|
|
1744
|
+
} of filteredResults) {
|
|
1745
|
+
console.log(
|
|
1746
|
+
log.infoText(
|
|
1747
|
+
` ${chalk.bold.white`- ${name}`} ${id} [${(
|
|
1748
|
+
version.modified || version.created
|
|
1749
|
+
)
|
|
1750
|
+
.toString()
|
|
1751
|
+
.substring(0, 10)} ${
|
|
1752
|
+
version.modifiedBy || version.createdBy
|
|
1753
|
+
}]`
|
|
1754
|
+
)
|
|
1755
|
+
);
|
|
1756
|
+
if (description) console.log(log.infoText` ${description}`);
|
|
1757
|
+
console.log(` ${log.infoText`[${method}]`} ${url}`);
|
|
1758
|
+
if (headers && Object.keys(headers).length) {
|
|
1759
|
+
console.log(` ${log.infoText`headers`}:`);
|
|
1760
|
+
|
|
1761
|
+
for (const [key, { value, secret }] of Object.entries(headers))
|
|
1762
|
+
console.log(
|
|
1763
|
+
` ${chalk.bold.gray(key)}: ${secret ? '🤐' : value}`
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
if (topics?.length)
|
|
1767
|
+
if (topics?.length === 1)
|
|
1768
|
+
console.log(
|
|
1769
|
+
` ${log.infoText`topics`}: ${topics
|
|
1770
|
+
.map(t => JSON.stringify(t))
|
|
1771
|
+
.join(' ')
|
|
1772
|
+
.replaceAll('"', '')
|
|
1773
|
+
.replaceAll(',', ' ')
|
|
1774
|
+
.replaceAll('{', '')
|
|
1775
|
+
.replaceAll('}', '')}`
|
|
1776
|
+
);
|
|
1777
|
+
else {
|
|
1778
|
+
console.log(` ${log.infoText`topics`}:`);
|
|
1779
|
+
log.objectRecurse(topics, 1, ' ');
|
|
1780
|
+
}
|
|
1781
|
+
if (templates && Object.keys(templates).length)
|
|
1782
|
+
console.log(
|
|
1783
|
+
` ${log.infoText`templates`}: ${Object.keys(
|
|
1784
|
+
templates
|
|
1785
|
+
).join(' ')}`
|
|
1786
|
+
);
|
|
1787
|
+
if (enabled === false)
|
|
1788
|
+
console.log(` ${log.infoText`enabled`}: ${enabled}`);
|
|
1789
|
+
}
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1169
1792
|
}
|
|
1170
1793
|
|
|
1171
1794
|
if (webhooksErr) {
|
|
@@ -1176,16 +1799,16 @@ class ContensisCli {
|
|
|
1176
1799
|
};
|
|
1177
1800
|
|
|
1178
1801
|
PrintBlocks = async () => {
|
|
1179
|
-
const { currentEnv, log, messages } = this;
|
|
1180
|
-
|
|
1181
|
-
if (
|
|
1802
|
+
const { currentEnv, env, log, messages } = this;
|
|
1803
|
+
const contensis = await this.ConnectContensis();
|
|
1804
|
+
if (contensis) {
|
|
1182
1805
|
// Retrieve blocks list for env
|
|
1183
|
-
const [err, blocks] = await
|
|
1806
|
+
const [err, blocks] = await contensis.blocks.GetBlocks();
|
|
1184
1807
|
|
|
1185
1808
|
if (Array.isArray(blocks)) {
|
|
1186
1809
|
this.HandleFormattingAndOutput(blocks, () => {
|
|
1187
1810
|
// print the blocks to console
|
|
1188
|
-
log.success(messages.blocks.list(currentEnv));
|
|
1811
|
+
log.success(messages.blocks.list(currentEnv, env.currentProject));
|
|
1189
1812
|
for (const {
|
|
1190
1813
|
id,
|
|
1191
1814
|
description,
|
|
@@ -1226,10 +1849,10 @@ class ContensisCli {
|
|
|
1226
1849
|
version: string
|
|
1227
1850
|
) => {
|
|
1228
1851
|
const { currentEnv, env, log, messages } = this;
|
|
1229
|
-
|
|
1230
|
-
if (
|
|
1852
|
+
const contensis = await this.ConnectContensis();
|
|
1853
|
+
if (contensis) {
|
|
1231
1854
|
// Retrieve block version
|
|
1232
|
-
const [err, blocks] = await
|
|
1855
|
+
const [err, blocks] = await contensis.blocks.GetBlockVersions(
|
|
1233
1856
|
blockId,
|
|
1234
1857
|
branch,
|
|
1235
1858
|
version
|
|
@@ -1239,7 +1862,7 @@ class ContensisCli {
|
|
|
1239
1862
|
this.HandleFormattingAndOutput(blocks, () => {
|
|
1240
1863
|
// print the version detail to console
|
|
1241
1864
|
log.success(
|
|
1242
|
-
messages.blocks.get(
|
|
1865
|
+
messages.blocks.get(blockId, currentEnv, env.currentProject)
|
|
1243
1866
|
);
|
|
1244
1867
|
for (const block of blocks)
|
|
1245
1868
|
printBlockVersion(
|
|
@@ -1268,18 +1891,20 @@ class ContensisCli {
|
|
|
1268
1891
|
const { currentEnv, env, log, messages } = this;
|
|
1269
1892
|
|
|
1270
1893
|
// Output request to console
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1894
|
+
log.info(
|
|
1895
|
+
messages.blocks.tryPush(
|
|
1896
|
+
block.id,
|
|
1897
|
+
block.source.branch,
|
|
1898
|
+
currentEnv,
|
|
1899
|
+
env.currentProject
|
|
1900
|
+
)
|
|
1276
1901
|
);
|
|
1277
1902
|
console.log(jsonFormatter(block));
|
|
1278
1903
|
|
|
1279
|
-
|
|
1280
|
-
if (
|
|
1904
|
+
const contensis = await this.ConnectContensis();
|
|
1905
|
+
if (contensis) {
|
|
1281
1906
|
// Push new block version
|
|
1282
|
-
const [err, blockVersion] = await
|
|
1907
|
+
const [err, blockVersion] = await contensis.blocks.PushBlockVersion(
|
|
1283
1908
|
block
|
|
1284
1909
|
);
|
|
1285
1910
|
if (!err) {
|
|
@@ -1291,7 +1916,6 @@ class ContensisCli {
|
|
|
1291
1916
|
env.currentProject
|
|
1292
1917
|
)
|
|
1293
1918
|
);
|
|
1294
|
-
console.log(jsonFormatter(blockVersion));
|
|
1295
1919
|
}
|
|
1296
1920
|
if (blockVersion) {
|
|
1297
1921
|
this.HandleFormattingAndOutput(blockVersion, () => {
|
|
@@ -1303,6 +1927,113 @@ class ContensisCli {
|
|
|
1303
1927
|
throw new Error(
|
|
1304
1928
|
messages.blocks.failedPush(block.id, currentEnv, env.currentProject)
|
|
1305
1929
|
);
|
|
1930
|
+
} else {
|
|
1931
|
+
throw new Error(
|
|
1932
|
+
messages.blocks.failedPush(block.id, currentEnv, env.currentProject)
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
|
|
1937
|
+
GetLatestBlockVersion = async (
|
|
1938
|
+
blockId: string,
|
|
1939
|
+
branch = 'default'
|
|
1940
|
+
): Promise<[AppError | null, string | undefined]> => {
|
|
1941
|
+
const { contensis, log, messages } = this;
|
|
1942
|
+
|
|
1943
|
+
// Look for block versions pushed to "default" branch
|
|
1944
|
+
const [getErr, blockVersions] =
|
|
1945
|
+
(await contensis?.blocks.GetBlockVersions(blockId, branch)) || [];
|
|
1946
|
+
|
|
1947
|
+
if (getErr) {
|
|
1948
|
+
return [getErr, undefined];
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
// Parse versionNo from response
|
|
1952
|
+
let blockVersionNo = 'latest';
|
|
1953
|
+
// The first blockVersion should be the latest one
|
|
1954
|
+
try {
|
|
1955
|
+
blockVersionNo = `${blockVersions?.[0]?.version.versionNo}`;
|
|
1956
|
+
|
|
1957
|
+
if (!Number.isNaN(blockVersionNo) && Number(blockVersionNo) > 0)
|
|
1958
|
+
// Is a valid versionNo
|
|
1959
|
+
return [null, blockVersionNo];
|
|
1960
|
+
else throw new Error(`'${blockVersionNo}' is not a valid version number`);
|
|
1961
|
+
} catch (parseVersionEx: any) {
|
|
1962
|
+
// Catch parsing errors in case of an unexpected response
|
|
1963
|
+
log.info(
|
|
1964
|
+
`Request for blockId: ${blockId}, branch: ${branch}, version: latest`
|
|
1965
|
+
);
|
|
1966
|
+
log.info(
|
|
1967
|
+
`Get block versions response was: ${tryStringify(blockVersions)}`
|
|
1968
|
+
);
|
|
1969
|
+
log.error(messages.blocks.failedParsingVersion());
|
|
1970
|
+
return [parseVersionEx, undefined];
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
|
|
1974
|
+
ExecuteBlockAction = async (
|
|
1975
|
+
action: BlockActionType,
|
|
1976
|
+
blockId: string,
|
|
1977
|
+
version = 'latest'
|
|
1978
|
+
) => {
|
|
1979
|
+
const { currentEnv, env, log, messages } = this;
|
|
1980
|
+
const contensis = await this.ConnectContensis();
|
|
1981
|
+
if (contensis) {
|
|
1982
|
+
let actionOnBlockVersion = version;
|
|
1983
|
+
|
|
1984
|
+
// If action is release and version is latest, find the latest version number
|
|
1985
|
+
if (action === 'release' && version === 'latest') {
|
|
1986
|
+
const [getErr, blockVersion] = await this.GetLatestBlockVersion(
|
|
1987
|
+
blockId
|
|
1988
|
+
);
|
|
1989
|
+
|
|
1990
|
+
if (getErr) {
|
|
1991
|
+
// Log error getting latest block version no
|
|
1992
|
+
// and throw the error message so the process can exit with a failure
|
|
1993
|
+
throw new Error(
|
|
1994
|
+
`${messages.blocks.noList(
|
|
1995
|
+
currentEnv,
|
|
1996
|
+
env.currentProject
|
|
1997
|
+
)} (${getErr})`
|
|
1998
|
+
);
|
|
1999
|
+
} else if (blockVersion) {
|
|
2000
|
+
actionOnBlockVersion = blockVersion;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
// Execute block action
|
|
2005
|
+
const [err, blockVersion] = await contensis.blocks.BlockAction(
|
|
2006
|
+
blockId,
|
|
2007
|
+
action,
|
|
2008
|
+
actionOnBlockVersion
|
|
2009
|
+
);
|
|
2010
|
+
|
|
2011
|
+
if (blockVersion) {
|
|
2012
|
+
this.HandleFormattingAndOutput(blockVersion, () => {
|
|
2013
|
+
// print the version detail to console
|
|
2014
|
+
log.success(
|
|
2015
|
+
messages.blocks.actionComplete(
|
|
2016
|
+
action,
|
|
2017
|
+
blockId,
|
|
2018
|
+
currentEnv,
|
|
2019
|
+
env.currentProject
|
|
2020
|
+
)
|
|
2021
|
+
);
|
|
2022
|
+
printBlockVersion(this, blockVersion);
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
if (err) {
|
|
2027
|
+
log.error(jsonFormatter(err));
|
|
2028
|
+
throw new Error(
|
|
2029
|
+
messages.blocks.actionFailed(
|
|
2030
|
+
action,
|
|
2031
|
+
blockId,
|
|
2032
|
+
currentEnv,
|
|
2033
|
+
env.currentProject
|
|
2034
|
+
)
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
1306
2037
|
}
|
|
1307
2038
|
};
|
|
1308
2039
|
|
|
@@ -1310,72 +2041,241 @@ class ContensisCli {
|
|
|
1310
2041
|
blockId: string,
|
|
1311
2042
|
branch: string,
|
|
1312
2043
|
version: string,
|
|
1313
|
-
dataCenter: 'hq' | 'manchester' | 'london'
|
|
2044
|
+
dataCenter: 'hq' | 'manchester' | 'london' | undefined,
|
|
2045
|
+
follow = false
|
|
1314
2046
|
) => {
|
|
1315
|
-
const { currentEnv, log, messages } = this;
|
|
1316
|
-
|
|
1317
|
-
if (
|
|
2047
|
+
const { currentEnv, env, log, messages } = this;
|
|
2048
|
+
const contensis = await this.ConnectContensis();
|
|
2049
|
+
if (contensis) {
|
|
1318
2050
|
// Retrieve block logs
|
|
1319
|
-
|
|
2051
|
+
log.success(
|
|
2052
|
+
messages.blocks.getLogs(blockId, branch, currentEnv, env.currentProject)
|
|
2053
|
+
);
|
|
2054
|
+
|
|
2055
|
+
const [err, blockLogs] = await contensis.blocks.GetBlockLogs({
|
|
1320
2056
|
blockId,
|
|
1321
2057
|
branchId: branch,
|
|
1322
2058
|
version,
|
|
1323
2059
|
dataCenter,
|
|
1324
2060
|
});
|
|
1325
2061
|
|
|
1326
|
-
if (
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
2062
|
+
if (err) {
|
|
2063
|
+
log.error(
|
|
2064
|
+
messages.blocks.failedGetLogs(blockId, currentEnv, env.currentProject)
|
|
2065
|
+
);
|
|
2066
|
+
log.error(jsonFormatter(err));
|
|
2067
|
+
} else if (blockLogs) {
|
|
2068
|
+
const removeTrailingNewline = (logs: string) =>
|
|
2069
|
+
logs.endsWith('\n') ? logs.slice(0, logs.length - 1) : logs;
|
|
2070
|
+
const renderLogs = removeTrailingNewline(blockLogs);
|
|
2071
|
+
|
|
2072
|
+
this.HandleFormattingAndOutput(renderLogs, () => {
|
|
2073
|
+
// print the logs to console
|
|
1330
2074
|
console.log(
|
|
1331
2075
|
` - ${blockId} ${branch} ${
|
|
1332
2076
|
Number(version) ? `v${version}` : version
|
|
1333
|
-
} [${dataCenter}]`
|
|
2077
|
+
} ${dataCenter ? `[${dataCenter}]` : ''}`
|
|
1334
2078
|
);
|
|
1335
2079
|
log.line();
|
|
1336
|
-
console.log(log.infoText(
|
|
1337
|
-
|
|
2080
|
+
console.log(log.infoText(renderLogs));
|
|
2081
|
+
});
|
|
2082
|
+
|
|
2083
|
+
// Code for the `--follow` options
|
|
2084
|
+
let following = follow;
|
|
2085
|
+
let alreadyShown = blockLogs;
|
|
2086
|
+
let needsNewLine = false;
|
|
2087
|
+
let counter = 0;
|
|
2088
|
+
|
|
2089
|
+
// remove existing listeners and add them back afterwards
|
|
2090
|
+
const listeners = process.listeners('SIGINT');
|
|
2091
|
+
|
|
2092
|
+
process.removeAllListeners('SIGINT');
|
|
2093
|
+
// add listener to update following to false and break out
|
|
2094
|
+
process.on('SIGINT', () => {
|
|
2095
|
+
Logger.warning(
|
|
2096
|
+
messages.blocks.stopFollow(blockId, currentEnv, env.currentProject)
|
|
2097
|
+
);
|
|
2098
|
+
stopFollowing();
|
|
2099
|
+
});
|
|
2100
|
+
|
|
2101
|
+
let delay = promiseDelay(5 * 1000, null);
|
|
2102
|
+
const stopFollowing = () => {
|
|
2103
|
+
following = false;
|
|
2104
|
+
delay.cancel();
|
|
2105
|
+
|
|
2106
|
+
// Add back the listeners we removed previously
|
|
2107
|
+
process.removeAllListeners('SIGINT');
|
|
2108
|
+
for (const listener of listeners)
|
|
2109
|
+
process.addListener('SIGINT', listener);
|
|
2110
|
+
};
|
|
2111
|
+
|
|
2112
|
+
while (following) {
|
|
2113
|
+
if (counter++ > 300) {
|
|
2114
|
+
Logger.warning(
|
|
2115
|
+
messages.blocks.timeoutFollow(
|
|
2116
|
+
blockId,
|
|
2117
|
+
currentEnv,
|
|
2118
|
+
env.currentProject
|
|
2119
|
+
)
|
|
2120
|
+
);
|
|
2121
|
+
stopFollowing();
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
// wait n. seconds then poll for logs again
|
|
2125
|
+
await delay.wait();
|
|
2126
|
+
|
|
2127
|
+
const [lastErr, lastLogs] = following
|
|
2128
|
+
? await contensis.blocks.GetBlockLogs({
|
|
2129
|
+
blockId,
|
|
2130
|
+
branchId: branch,
|
|
2131
|
+
version,
|
|
2132
|
+
dataCenter,
|
|
2133
|
+
})
|
|
2134
|
+
: [null, null];
|
|
2135
|
+
|
|
2136
|
+
if (lastLogs) {
|
|
2137
|
+
// Find the difference and output it next
|
|
2138
|
+
const difference = diffLogStrings(lastLogs, alreadyShown);
|
|
2139
|
+
if (difference) {
|
|
2140
|
+
if (needsNewLine) {
|
|
2141
|
+
console.log('');
|
|
2142
|
+
}
|
|
2143
|
+
// Take the trailing newline off of the logged output to
|
|
2144
|
+
// avoid blank lines inbetween logs fetched sequentially
|
|
2145
|
+
const render = removeTrailingNewline(difference);
|
|
2146
|
+
console.log(log.infoText(render));
|
|
2147
|
+
|
|
2148
|
+
// Add what we've just rendered to already shown "cache"
|
|
2149
|
+
alreadyShown += `${render}\n`;
|
|
2150
|
+
needsNewLine = false;
|
|
2151
|
+
} else {
|
|
2152
|
+
// If no difference output a dot
|
|
2153
|
+
process.stdout.write('.');
|
|
2154
|
+
needsNewLine = true;
|
|
2155
|
+
}
|
|
2156
|
+
} else if (lastErr) {
|
|
2157
|
+
// If error output an x
|
|
2158
|
+
process.stdout.write('x');
|
|
2159
|
+
needsNewLine = true;
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
};
|
|
2165
|
+
|
|
2166
|
+
PrintProxies = async (proxyId?: string) => {
|
|
2167
|
+
const { currentEnv, env, log, messages } = this;
|
|
2168
|
+
const contensis = await this.ConnectContensis();
|
|
2169
|
+
if (contensis) {
|
|
2170
|
+
// Retrieve proxies list for env
|
|
2171
|
+
const [err, proxies] = await contensis.proxies.GetProxies(proxyId);
|
|
2172
|
+
|
|
2173
|
+
if (Array.isArray(proxies)) {
|
|
2174
|
+
this.HandleFormattingAndOutput(proxies, () => {
|
|
2175
|
+
// print the proxies to console
|
|
2176
|
+
log.success(messages.proxies.list(currentEnv, env.currentProject));
|
|
2177
|
+
for (const { id, name, description, endpoints, version } of proxies) {
|
|
2178
|
+
console.log(
|
|
2179
|
+
` - ${name} [${
|
|
2180
|
+
version.versionNo
|
|
2181
|
+
}] ${id} ${log.infoText`${description}`}`
|
|
2182
|
+
);
|
|
2183
|
+
for (const [language, endpoint] of Object.entries(endpoints))
|
|
2184
|
+
console.log(
|
|
2185
|
+
` - ${log.infoText`language: ${language}
|
|
2186
|
+
server: ${endpoint.server}
|
|
2187
|
+
headers.host: ${endpoint.headers.host}
|
|
2188
|
+
ssl: ${endpoint.ssl}`}`
|
|
2189
|
+
);
|
|
2190
|
+
}
|
|
1338
2191
|
});
|
|
1339
2192
|
}
|
|
1340
2193
|
|
|
1341
2194
|
if (err) {
|
|
1342
|
-
log.error(messages.
|
|
2195
|
+
log.error(messages.proxies.noList(currentEnv, env.currentProject));
|
|
1343
2196
|
log.error(jsonFormatter(err));
|
|
1344
2197
|
}
|
|
1345
2198
|
}
|
|
1346
2199
|
};
|
|
1347
2200
|
|
|
2201
|
+
PrintRenderers = async (rendererId?: string) => {
|
|
2202
|
+
const { currentEnv, env, log, messages } = this;
|
|
2203
|
+
const contensis = await this.ConnectContensis();
|
|
2204
|
+
if (contensis) {
|
|
2205
|
+
// Retrieve renderers list for env
|
|
2206
|
+
const [err, renderers] = await contensis.renderers.GetRenderers(
|
|
2207
|
+
rendererId
|
|
2208
|
+
);
|
|
2209
|
+
|
|
2210
|
+
if (Array.isArray(renderers)) {
|
|
2211
|
+
this.HandleFormattingAndOutput(renderers, () => {
|
|
2212
|
+
// print the renderers to console
|
|
2213
|
+
log.success(messages.renderers.list(currentEnv, env.currentProject));
|
|
2214
|
+
for (const {
|
|
2215
|
+
id,
|
|
2216
|
+
description,
|
|
2217
|
+
assignedContentTypes,
|
|
2218
|
+
rules,
|
|
2219
|
+
version,
|
|
2220
|
+
} of renderers) {
|
|
2221
|
+
console.log(
|
|
2222
|
+
` - ${id} [${version.versionNo}] ${log.infoText`${description}`}`
|
|
2223
|
+
);
|
|
2224
|
+
if (assignedContentTypes?.length)
|
|
2225
|
+
console.log(
|
|
2226
|
+
log.infoText` assignedContentTypes: ${assignedContentTypes.join(
|
|
2227
|
+
', '
|
|
2228
|
+
)}`
|
|
2229
|
+
);
|
|
2230
|
+
for (const rule of rules)
|
|
2231
|
+
if (rule.return)
|
|
2232
|
+
console.log(
|
|
2233
|
+
log.infoText` ${
|
|
2234
|
+
rule.return.endpointId ? 'endpointId' : 'blockId'
|
|
2235
|
+
}: ${rule.return.endpointId || rule.return.blockId}`
|
|
2236
|
+
);
|
|
2237
|
+
}
|
|
2238
|
+
});
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
if (err) {
|
|
2242
|
+
log.error(messages.renderers.noList(currentEnv, env.currentProject));
|
|
2243
|
+
log.error(jsonFormatter(err));
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
};
|
|
1348
2247
|
HandleFormattingAndOutput = <T>(obj: T, logFn: (obj: T) => void) => {
|
|
1349
2248
|
const { format, log, messages, output } = this;
|
|
2249
|
+
if (!format) {
|
|
2250
|
+
// print the object to console
|
|
2251
|
+
logFn(obj);
|
|
2252
|
+
} else if (format === 'csv') {
|
|
2253
|
+
log.raw('');
|
|
2254
|
+
log.raw(log.infoText(csvFormatter(obj)));
|
|
2255
|
+
} else if (format === 'xml') {
|
|
2256
|
+
log.raw('');
|
|
2257
|
+
log.raw(log.infoText(xmlFormatter(obj)));
|
|
2258
|
+
} else if (format === 'json') {
|
|
2259
|
+
log.raw('');
|
|
2260
|
+
log.raw(log.infoText(jsonFormatter(obj)));
|
|
2261
|
+
}
|
|
2262
|
+
log.raw('');
|
|
2263
|
+
|
|
1350
2264
|
if (output) {
|
|
1351
2265
|
let writeString = '';
|
|
2266
|
+
const isText = !tryParse(obj) && typeof obj === 'string';
|
|
1352
2267
|
if (format === 'csv') {
|
|
1353
2268
|
writeString = csvFormatter(obj as any);
|
|
1354
2269
|
} else if (format === 'xml') {
|
|
1355
2270
|
writeString = xmlFormatter(obj as any);
|
|
1356
|
-
} else writeString = jsonFormatter(obj);
|
|
2271
|
+
} else writeString = isText ? (obj as string) : jsonFormatter(obj);
|
|
1357
2272
|
// write output to file
|
|
1358
2273
|
if (writeString) {
|
|
1359
2274
|
fs.writeFileSync(output, writeString);
|
|
1360
|
-
log.success(messages.app.fileOutput(format, output));
|
|
2275
|
+
log.success(messages.app.fileOutput(isText ? 'text' : format, output));
|
|
1361
2276
|
} else {
|
|
1362
2277
|
log.info(messages.app.noFileOutput());
|
|
1363
2278
|
}
|
|
1364
|
-
} else {
|
|
1365
|
-
if (!format) {
|
|
1366
|
-
// print the object to console
|
|
1367
|
-
logFn(obj);
|
|
1368
|
-
} else if (format === 'csv') {
|
|
1369
|
-
log.raw('');
|
|
1370
|
-
log.raw(log.infoText(csvFormatter(obj)));
|
|
1371
|
-
} else if (format === 'xml') {
|
|
1372
|
-
log.raw('');
|
|
1373
|
-
log.raw(log.infoText(xmlFormatter(obj)));
|
|
1374
|
-
} else if (format === 'json') {
|
|
1375
|
-
log.raw('');
|
|
1376
|
-
log.raw(log.infoText(jsonFormatter(obj)));
|
|
1377
|
-
}
|
|
1378
|
-
log.raw('');
|
|
1379
2279
|
}
|
|
1380
2280
|
};
|
|
1381
2281
|
}
|