contensis-cli 1.0.0-beta.11 → 1.0.0-beta.13

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.
@@ -58,14 +58,17 @@ class ContensisCli {
58
58
  process.exit(exitCode);
59
59
  };
60
60
 
61
- cache: SessionCache;
61
+ private command: CliCommand;
62
+ private format?: OutputFormat;
63
+ private output?: string;
64
+ private session: SessionCacheProvider;
65
+
62
66
  contensis?: ContensisMigrationService;
63
67
  contensisOpts: Partial<MigrateRequest>;
64
68
  contentTypes?: ContentType[];
65
69
  components?: Component[];
66
- currentEnv: string;
67
70
  currentProject: string;
68
- env: EnvironmentCache;
71
+
69
72
  sourceEnv?: string;
70
73
  targetEnv?: string;
71
74
  urls:
@@ -78,17 +81,41 @@ class ContensisCli {
78
81
  iisPreviewWeb: string;
79
82
  }
80
83
  | undefined;
81
- private command: CliCommand;
82
- private format?: OutputFormat;
83
- private output?: string;
84
84
  log = Logger;
85
85
  messages = LogMessages;
86
- private session: SessionCacheProvider;
87
86
 
88
87
  verb: string;
89
88
  noun: string;
90
89
  thirdArg: string;
91
90
 
91
+ get cache() {
92
+ return this.session.Get();
93
+ }
94
+ get currentEnv() {
95
+ return this.cache.currentEnvironment || '';
96
+ }
97
+
98
+ set currentEnv(currentEnvironment: string) {
99
+ this.session.Update({ currentEnvironment });
100
+ }
101
+
102
+ get env() {
103
+ const currentEnvironment = this.currentEnv;
104
+ const environments = this.cache.environments || {};
105
+
106
+ if (!currentEnvironment) return {} as EnvironmentCache;
107
+ else if (!!environments[currentEnvironment])
108
+ return environments[currentEnvironment];
109
+ else {
110
+ return {
111
+ history: [],
112
+ lastUserId: '',
113
+ projects: [],
114
+ versionStatus: 'latest',
115
+ } as EnvironmentCache;
116
+ }
117
+ }
118
+
92
119
  constructor(
93
120
  args: string[],
94
121
  outputOpts?: OutputOptions & IConnectOptions & IImportOptions,
@@ -106,38 +133,26 @@ class ContensisCli {
106
133
  }`.trim();
107
134
 
108
135
  this.session = new SessionCacheProvider();
109
- this.cache = this.session.Get();
136
+
110
137
  this.contensisOpts = contensisOpts;
111
138
  this.format = outputOpts?.format;
112
139
  this.output =
113
140
  outputOpts?.output && path.join(process.cwd(), outputOpts.output);
114
141
 
115
- const currentEnvironment =
116
- outputOpts?.alias || this.cache.currentEnvironment || '';
142
+ const currentEnvironment = outputOpts?.alias || this.currentEnv;
117
143
  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
- }
144
+ this.currentEnv = currentEnvironment;
130
145
 
131
146
  const env = this.env;
132
147
 
133
148
  if (outputOpts?.projectId) env.currentProject = outputOpts.projectId;
134
149
  if (outputOpts?.user) env.lastUserId = outputOpts.user;
150
+ // setting this in env means passwordFallback is written to environments.json
135
151
  if (outputOpts?.password) env.passwordFallback = outputOpts.password;
136
152
  if (outputOpts?.clientId) env.lastUserId = outputOpts.clientId;
137
153
  if (outputOpts?.sharedSecret)
138
154
  env.passwordFallback = outputOpts.sharedSecret;
139
155
 
140
- this.currentEnv = currentEnvironment;
141
156
  this.currentProject = env?.currentProject || 'null';
142
157
  this.sourceEnv = outputOpts?.sourceEnv || currentEnvironment;
143
158
 
@@ -154,7 +169,7 @@ class ContensisCli {
154
169
  if (currentEnvironment) {
155
170
  env.history = [this.command];
156
171
  if (commandText) {
157
- environments[currentEnvironment] = this.env;
172
+ environments[currentEnvironment] = env;
158
173
  this.session.Update({
159
174
  currentEnvironment,
160
175
  environments,
@@ -181,45 +196,24 @@ class ContensisCli {
181
196
  };
182
197
 
183
198
  Connect = async (environment: string) => {
184
- const { cache, log, messages, session } = this;
199
+ const { log, messages, session } = this;
185
200
 
186
201
  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
202
  this.currentEnv = environment;
199
203
  this.urls = url(environment, 'website');
200
204
 
201
205
  const [fetchErr, response] = await to(fetch(this.urls.cms));
202
206
  if (response && response?.status < 400) {
203
207
  log.success(messages.connect.connected(environment));
208
+ session.UpdateEnv(this.env, environment);
204
209
 
205
210
  if (this.env?.lastUserId) {
206
- await this.ConnectContensis();
211
+ // await this.ConnectContensis();
207
212
  await this.PrintProjects();
208
213
  } else {
209
214
  log.warning(messages.projects.noList());
210
215
  log.help(messages.connect.tip());
211
- // cache.environments[environment] = {
212
- // versionStatus: 'published',
213
- // history: [],
214
- // lastUserId: '',
215
- // projects: [],
216
- // };
217
216
  }
218
-
219
- session.Update({
220
- currentEnvironment: environment,
221
- environments: cache.environments,
222
- });
223
217
  } else {
224
218
  // Cannot reach environment - status X
225
219
  log.error(
@@ -238,19 +232,11 @@ class ContensisCli {
238
232
  const isGuidId = userId && isUuid(userId);
239
233
 
240
234
  if (currentEnv && userId) {
241
- const [credentialError, credentials] = await new CredentialProvider(
242
- {
243
- userId,
244
- alias: currentEnv,
245
- },
235
+ const credentials = await this.GetCredentials(
236
+ userId,
246
237
  env.passwordFallback
247
- ).Init();
238
+ );
248
239
 
249
- if (credentialError && !credentials.current) {
250
- // Log problem with Credential Provider
251
- log.error(credentialError as any);
252
- return;
253
- }
254
240
  const cachedPassword = credentials?.current?.password;
255
241
 
256
242
  if (cachedPassword) {
@@ -314,36 +300,19 @@ class ContensisCli {
314
300
  const isTargetGuidId = targetUserId && isUuid(targetUserId);
315
301
 
316
302
  if (sourceUserId && currentEnv && targetUserId) {
317
- const [sourceCredentialError, sourceCredentials] =
318
- await new CredentialProvider(
319
- {
320
- userId: sourceUserId,
321
- alias: currentEnv,
322
- },
323
- sourcePassword
324
- ).Init();
303
+ const sourceCredentials = await this.GetCredentials(
304
+ sourceUserId,
305
+ sourcePassword,
306
+ sourceEnv
307
+ );
325
308
 
326
- if (sourceCredentialError && !sourceCredentials.current) {
327
- // Log problem with Credential Provider
328
- logError(sourceCredentialError);
329
- return;
330
- }
331
309
  const cachedSourcePassword = sourceCredentials?.current?.password;
332
310
 
333
- const [targetCredentialError, targetCredentials] =
334
- await new CredentialProvider(
335
- {
336
- userId: targetUserId,
337
- alias: currentEnv,
338
- },
339
- env.passwordFallback
340
- ).Init();
311
+ const targetCredentials = await this.GetCredentials(
312
+ targetUserId,
313
+ env.passwordFallback
314
+ );
341
315
 
342
- if (targetCredentialError && !targetCredentials.current) {
343
- // Log problem with Credential Provider
344
- log.error(targetCredentialError as any);
345
- return;
346
- }
347
316
  const cachedTargetPassword = targetCredentials?.current?.password;
348
317
 
349
318
  if (cachedSourcePassword && cachedTargetPassword) {
@@ -402,6 +371,34 @@ class ContensisCli {
402
371
  }
403
372
  };
404
373
 
374
+ GetCredentials = async (
375
+ userId: string,
376
+ password?: string,
377
+ currentEnv = this.currentEnv
378
+ ): Promise<CredentialProvider | undefined> => {
379
+ const { env, log, messages } = this;
380
+ if (userId) {
381
+ const [credentialError, credentials] = await new CredentialProvider(
382
+ { userId, alias: currentEnv },
383
+ password
384
+ ).Init();
385
+
386
+ if (credentialError && !credentials.current) {
387
+ // Log problem with Credential Provider
388
+ log.error(credentialError as any);
389
+ return;
390
+ }
391
+
392
+ if (credentials.remarks.secure !== true) {
393
+ log.warning(messages.login.insecurePassword());
394
+ } else {
395
+ env.passwordFallback = undefined;
396
+ this.session.UpdateEnv(env, currentEnv);
397
+ }
398
+ return credentials;
399
+ }
400
+ };
401
+
405
402
  Login = async (
406
403
  userId: string,
407
404
  {
@@ -409,111 +406,101 @@ class ContensisCli {
409
406
  promptPassword = true,
410
407
  sharedSecret = isSharedSecret(this.env.passwordFallback),
411
408
  silent = false,
409
+ attempt = 1,
412
410
  }: {
413
411
  password?: string;
414
412
  promptPassword?: boolean;
415
413
  sharedSecret?: string;
416
414
  silent?: boolean;
417
- }
415
+ attempt?: number;
416
+ } = {}
418
417
  ): Promise<string | undefined> => {
419
- let inputPassword = password;
418
+ let inputPassword = password || sharedSecret;
420
419
  const { log, messages } = this;
421
420
 
422
421
  if (userId) {
423
- const { cache, currentEnv, env } = this;
422
+ const { currentEnv, env } = this;
424
423
 
425
424
  if (currentEnv) {
426
- const [credentialError, credentials] = await new CredentialProvider(
427
- { userId, alias: currentEnv },
428
- inputPassword || sharedSecret
429
- ).Init();
430
-
431
- if (credentialError && !credentials.current) {
432
- // Log problem with Credential Provider
433
- log.error(credentialError as any);
434
- return;
435
- }
425
+ const credentials = await this.GetCredentials(userId, inputPassword);
426
+
427
+ if (credentials) {
428
+ const cachedPassword = isPassword(credentials.current?.password);
429
+ const cachedSecret = isSharedSecret(credentials.current?.password);
430
+
431
+ if (!cachedPassword && !cachedSecret && promptPassword) {
432
+ // Password prompt
433
+ ({ inputPassword } = await inquirer.prompt([
434
+ {
435
+ type: 'password',
436
+ message: messages.login.passwordPrompt(currentEnv, userId),
437
+ name: 'inputPassword',
438
+ mask: '*',
439
+ prefix: undefined,
440
+ },
441
+ ]));
442
+ }
436
443
 
437
- if (credentials.remarks.secure !== true)
438
- log.warning(messages.login.insecurePassword());
439
-
440
- const cachedPassword = isPassword(credentials?.current?.password);
441
- const cachedSecret = isSharedSecret(credentials?.current?.password);
442
-
443
- if (
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
- }
444
+ if (inputPassword || cachedPassword || cachedSecret) {
445
+ const authService = new ContensisAuthService({
446
+ username: userId,
447
+ password: inputPassword || cachedPassword,
448
+ projectId: env?.currentProject || 'website',
449
+ rootUrl: this.urls?.cms || '',
450
+ clientId: userId,
451
+ clientSecret: sharedSecret || cachedSecret,
452
+ });
453
+
454
+ const [authError, bearerToken] = await to(
455
+ authService.BearerToken()
456
+ );
461
457
 
462
- if (sharedSecret || cachedSecret || inputPassword || cachedPassword) {
463
- const authService = new ContensisAuthService({
464
- username: userId,
465
- password: inputPassword || cachedPassword,
466
- projectId: env?.currentProject || 'website',
467
- rootUrl: this.urls?.cms || '',
468
- clientId: userId,
469
- clientSecret: sharedSecret || cachedSecret,
470
- });
471
-
472
- const [authError, bearerToken] = await to(authService.BearerToken());
473
-
474
- // Login successful
475
- if (bearerToken) {
476
- // Set env vars
477
- env.authToken = bearerToken;
478
- env.lastUserId = userId;
479
- env.passwordFallback =
480
- credentials.remarks.secure !== true
481
- ? credentials.current?.password
482
- : undefined;
483
-
484
- if (!silent) {
485
- Logger.success(messages.login.success(currentEnv, userId));
486
- await this.PrintProjects();
487
- }
488
- if (inputPassword) await credentials.Save(inputPassword);
489
- if (sharedSecret) await credentials.Save(sharedSecret);
490
- } else if (authError) {
491
- Logger.error(authError.toString());
492
- // Clear env vars
493
- env.authToken = '';
494
- env.lastUserId = '';
495
- env.passwordFallback = undefined;
496
-
497
- // If the auth error was raised using a cached password
498
- if (
499
- (cachedPassword || cachedSecret) &&
500
- credentials.remarks.secure
501
- ) {
502
- // Remove any bad stored credential and trigger login prompt again
503
- await credentials.Delete();
504
- return await this.Login(userId, { password, sharedSecret });
505
- } else {
506
- throw new Error(messages.login.failed(currentEnv, userId));
458
+ // Login successful
459
+ if (bearerToken) {
460
+ // Set env vars
461
+ env.authToken = bearerToken;
462
+ env.lastUserId = userId;
463
+ env.passwordFallback =
464
+ credentials.remarks.secure !== true
465
+ ? credentials.current?.password
466
+ : undefined;
467
+ // Persist env before finding projects or doing anything else
468
+ this.session.UpdateEnv(env);
469
+
470
+ if (!silent) {
471
+ Logger.success(messages.login.success(currentEnv, userId));
472
+ await this.PrintProjects();
473
+ }
474
+ if (inputPassword) await credentials.Save(inputPassword);
475
+ if (sharedSecret) await credentials.Save(sharedSecret);
476
+ } else if (authError) {
477
+ Logger.error(authError.toString());
478
+ // Clear env vars
479
+ env.authToken = '';
480
+ env.lastUserId = '';
481
+ env.passwordFallback = undefined;
482
+ // Persist env to remove cleared values
483
+ this.session.UpdateEnv(env);
484
+
485
+ // If the auth error was raised using a cached password
486
+ if (
487
+ (cachedPassword || cachedSecret) &&
488
+ credentials.remarks.secure
489
+ ) {
490
+ // Remove any bad stored credential and trigger login prompt again
491
+ await credentials.Delete();
492
+ return await this.Login(userId, { password, sharedSecret });
493
+ } else {
494
+ throw new Error(messages.login.failed(currentEnv, userId));
495
+ }
507
496
  }
508
- }
509
497
 
510
- // Persist env
511
- this.session.Update({
512
- environments: cache.environments,
513
- });
514
- return env.authToken;
515
- } else {
516
- Logger.error(messages.login.passwordPrompt(currentEnv, userId));
498
+ return env.authToken;
499
+ } else {
500
+ Logger.error(messages.login.passwordPrompt());
501
+ if (attempt < 2)
502
+ return await this.Login(userId, { attempt: attempt + 1 });
503
+ }
517
504
  }
518
505
  } else {
519
506
  // No environment set, use `contensis connect {alias}` first
@@ -526,7 +513,7 @@ class ContensisCli {
526
513
  };
527
514
 
528
515
  PrintProjects = async () => {
529
- const { cache, currentEnv, currentProject, log, messages, session } = this;
516
+ const { currentProject, log, messages, session } = this;
530
517
  if (!this.contensis) await this.ConnectContensis();
531
518
 
532
519
  if (this.contensis) {
@@ -537,7 +524,6 @@ class ContensisCli {
537
524
 
538
525
  if (Array.isArray(projects)) {
539
526
  // save these projects in cache
540
- const currentVals = cache.environments[currentEnv] || {};
541
527
  const nextCurrentProject =
542
528
  currentProject && currentProject !== 'null'
543
529
  ? currentProject
@@ -545,11 +531,10 @@ class ContensisCli {
545
531
  ? 'website'
546
532
  : undefined;
547
533
 
548
- cache.environments[currentEnv] = {
549
- ...currentVals,
534
+ session.UpdateEnv({
550
535
  projects: projects.map(p => p.id),
551
536
  currentProject: nextCurrentProject,
552
- };
537
+ });
553
538
 
554
539
  log.success(messages.projects.list());
555
540
  this.HandleFormattingAndOutput(projects, () => {
@@ -563,28 +548,19 @@ class ContensisCli {
563
548
  }
564
549
  });
565
550
 
566
- session.Update({
567
- environments: cache.environments,
568
- });
569
-
570
- if (nextCurrentProject) {
571
- this.env = cache.environments[currentEnv];
572
- this.SetProject(nextCurrentProject);
573
- }
551
+ if (!this.SetProject(nextCurrentProject))
552
+ log.warning(messages.projects.tip());
574
553
  }
575
554
 
576
555
  if (projectsErr) {
577
556
  log.error(messages.projects.noList());
578
557
  log.error(projectsErr.message);
579
558
  }
580
- // } else {
581
- // log.warning(messages.projects.noList());
582
- // log.help(messages.connect.tip());
583
559
  }
584
560
  };
585
561
 
586
- SetProject = async (projectId = '') => {
587
- const { cache, env, log, messages, session } = this;
562
+ SetProject = (projectId = 'website') => {
563
+ const { env, log, messages, session } = this;
588
564
  let nextProjectId: string | undefined;
589
565
  if (env?.projects.length > 0 && env?.lastUserId) {
590
566
  nextProjectId = env.projects.find(
@@ -592,9 +568,7 @@ class ContensisCli {
592
568
  );
593
569
  if (nextProjectId) {
594
570
  env.currentProject = nextProjectId;
595
- session.Update({
596
- environments: cache.environments,
597
- });
571
+ session.UpdateEnv(env);
598
572
  log.success(messages.projects.set(projectId));
599
573
  } else {
600
574
  log.error(messages.projects.failedSet(projectId));
@@ -607,8 +581,8 @@ class ContensisCli {
607
581
  return nextProjectId;
608
582
  };
609
583
 
610
- SetVersion = async (versionStatus: 'latest' | 'published') => {
611
- const { cache, env, log, messages, session } = this;
584
+ SetVersion = (versionStatus: 'latest' | 'published') => {
585
+ const { env, log, messages, session } = this;
612
586
  if (!['latest', 'published'].includes(versionStatus)) {
613
587
  log.error(messages.version.invalid(versionStatus));
614
588
  return false;
@@ -618,10 +592,7 @@ class ContensisCli {
618
592
  return false;
619
593
  }
620
594
  if (env?.projects.length > 0 && env?.lastUserId) {
621
- env.versionStatus = versionStatus;
622
- session.Update({
623
- environments: cache.environments,
624
- });
595
+ session.UpdateEnv({ versionStatus });
625
596
  log.success(messages.version.set(this.currentEnv, versionStatus));
626
597
  return true;
627
598
  } else {
package/src/shell.ts CHANGED
@@ -72,8 +72,13 @@ class ContensisShell {
72
72
  );
73
73
  }
74
74
 
75
+ restart = async () => {
76
+ this.firstStart = false;
77
+ this.log.line(); // add a line so we can see where the shell has been restarted
78
+ await this.start();
79
+ };
80
+
75
81
  start = async () => {
76
- this.log.line();
77
82
  this.refreshEnvironment();
78
83
  this.userId = '';
79
84
  const { currentEnvironment, env, log, messages } = this;
@@ -98,7 +103,10 @@ class ContensisShell {
98
103
  silent: true,
99
104
  }
100
105
  );
101
- if (token) this.userId = env.lastUserId;
106
+ if (token) {
107
+ this.userId = env.lastUserId;
108
+ if (!env.currentProject) log.warning(messages.projects.tip());
109
+ }
102
110
  this.firstStart = false;
103
111
  this.refreshEnvironment();
104
112
  } else {
@@ -221,7 +229,10 @@ class ContensisShell {
221
229
  let globalShell: ContensisShell;
222
230
 
223
231
  export const shell = () => {
224
- if (typeof process.argv?.[2] !== 'undefined') return { start() {} } as any;
232
+ // Return a benign function for shell().restart() when used in cli context
233
+ // as some commands need to restart the shell to show an updated prompt
234
+ // after successful connect / login / set project
235
+ if (typeof process.argv?.[2] !== 'undefined') return { restart() {} } as any;
225
236
  if (!globalShell) globalShell = new ContensisShell();
226
237
  return globalShell;
227
238
  };
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const LIB_VERSION = "1.0.0-beta.11";
1
+ export const LIB_VERSION = "1.0.0-beta.13";