@swell/cli 2.1.0 → 2.2.1

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.
Files changed (112) hide show
  1. package/dist/commands/api/delete.d.ts +15 -0
  2. package/dist/commands/api/delete.js +26 -0
  3. package/dist/commands/api/get.d.ts +15 -0
  4. package/dist/commands/api/get.js +31 -0
  5. package/dist/commands/api/index.d.ts +7 -0
  6. package/dist/commands/api/index.js +16 -0
  7. package/dist/commands/api/post.d.ts +16 -0
  8. package/dist/commands/api/post.js +33 -0
  9. package/dist/commands/api/put.d.ts +16 -0
  10. package/dist/commands/api/put.js +33 -0
  11. package/dist/commands/app/dev.d.ts +9 -9
  12. package/dist/commands/app/dev.js +163 -139
  13. package/dist/commands/app/frontend/dev.d.ts +1 -1
  14. package/dist/commands/app/frontend/dev.js +84 -78
  15. package/dist/commands/app/install.js +3 -3
  16. package/dist/commands/app/pull.d.ts +1 -1
  17. package/dist/commands/app/pull.js +6 -6
  18. package/dist/commands/app/push.d.ts +3 -3
  19. package/dist/commands/app/push.js +8 -6
  20. package/dist/commands/app/release.d.ts +1 -1
  21. package/dist/commands/app/release.js +1 -1
  22. package/dist/commands/app/version.d.ts +1 -1
  23. package/dist/commands/app/version.js +5 -3
  24. package/dist/commands/create/app.d.ts +10 -2
  25. package/dist/commands/create/app.js +226 -57
  26. package/dist/commands/create/content.d.ts +4 -0
  27. package/dist/commands/create/content.js +83 -15
  28. package/dist/commands/create/function.js +27 -5
  29. package/dist/commands/create/index.js +5 -1
  30. package/dist/commands/create/model.d.ts +4 -0
  31. package/dist/commands/create/model.js +120 -25
  32. package/dist/commands/create/tests.d.ts +15 -0
  33. package/dist/commands/create/tests.js +79 -0
  34. package/dist/commands/inspect/content.d.ts +25 -0
  35. package/dist/commands/inspect/content.js +159 -0
  36. package/dist/commands/inspect/index.d.ts +7 -0
  37. package/dist/commands/inspect/index.js +16 -0
  38. package/dist/commands/inspect/models.d.ts +27 -0
  39. package/dist/commands/inspect/models.js +197 -0
  40. package/dist/commands/schema.d.ts +27 -0
  41. package/dist/commands/schema.js +231 -0
  42. package/dist/commands/theme/dev.d.ts +1 -1
  43. package/dist/commands/theme/dev.js +2 -2
  44. package/dist/commands/theme/init.d.ts +1 -1
  45. package/dist/commands/theme/init.js +1 -1
  46. package/dist/commands/theme/pull.d.ts +2 -2
  47. package/dist/commands/theme/pull.js +2 -2
  48. package/dist/commands/theme/push.d.ts +1 -1
  49. package/dist/commands/theme/push.js +1 -1
  50. package/dist/create-app-command.d.ts +12 -2
  51. package/dist/create-app-command.js +103 -80
  52. package/dist/create-collection-command.js +4 -1
  53. package/dist/create-config-command.js +4 -0
  54. package/dist/env/local.d.ts +1 -0
  55. package/dist/env/local.js +1 -0
  56. package/dist/env/production.d.ts +1 -0
  57. package/dist/env/production.js +1 -0
  58. package/dist/env/review.d.ts +1 -0
  59. package/dist/env/review.js +1 -0
  60. package/dist/env/staging.d.ts +1 -0
  61. package/dist/env/staging.js +1 -0
  62. package/dist/lib/api.d.ts +16 -5
  63. package/dist/lib/api.js +67 -25
  64. package/dist/lib/app-config.js +1 -0
  65. package/dist/lib/apps/index.d.ts +2 -0
  66. package/dist/lib/apps/index.js +20 -14
  67. package/dist/lib/config.d.ts +1 -1
  68. package/dist/lib/constants.d.ts +1 -0
  69. package/dist/lib/constants.js +1 -0
  70. package/dist/lib/create/content.d.ts +5 -1
  71. package/dist/lib/create/content.js +8 -1
  72. package/dist/lib/create/function.d.ts +2 -1
  73. package/dist/lib/create/function.js +7 -3
  74. package/dist/lib/create/model.d.ts +1 -0
  75. package/dist/lib/create/schemas.d.ts +6 -0
  76. package/dist/lib/create/schemas.js +6 -0
  77. package/dist/lib/create/tests/templates/env-dts.d.ts +1 -0
  78. package/dist/lib/create/tests/templates/env-dts.js +14 -0
  79. package/dist/lib/create/tests/templates/index.d.ts +8 -0
  80. package/dist/lib/create/tests/templates/index.js +8 -0
  81. package/dist/lib/create/tests/templates/integration-test.d.ts +1 -0
  82. package/dist/lib/create/tests/templates/integration-test.js +19 -0
  83. package/dist/lib/create/tests/templates/mock-request.d.ts +2 -0
  84. package/dist/lib/create/tests/templates/mock-request.js +112 -0
  85. package/dist/lib/create/tests/templates/setup-globals.d.ts +1 -0
  86. package/dist/lib/create/tests/templates/setup-globals.js +23 -0
  87. package/dist/lib/create/tests/templates/swell-client.d.ts +1 -0
  88. package/dist/lib/create/tests/templates/swell-client.js +126 -0
  89. package/dist/lib/create/tests/templates/tsconfig.d.ts +1 -0
  90. package/dist/lib/create/tests/templates/tsconfig.js +15 -0
  91. package/dist/lib/create/tests/templates/unit-test.d.ts +1 -0
  92. package/dist/lib/create/tests/templates/unit-test.js +42 -0
  93. package/dist/lib/create/tests/templates/vitest-config.d.ts +2 -0
  94. package/dist/lib/create/tests/templates/vitest-config.js +121 -0
  95. package/dist/lib/create/tests/types.d.ts +21 -0
  96. package/dist/lib/create/tests/types.js +1 -0
  97. package/dist/lib/create/tests.d.ts +4 -0
  98. package/dist/lib/create/tests.js +113 -0
  99. package/dist/lib/sessions.js +4 -3
  100. package/dist/lib/style.js +0 -1
  101. package/dist/lib/theme-sync.d.ts +6 -6
  102. package/dist/lib/theme-sync.js +49 -39
  103. package/dist/push-app-command.d.ts +7 -7
  104. package/dist/push-app-command.js +38 -36
  105. package/dist/remote-app-command.d.ts +1 -1
  106. package/dist/remote-app-command.js +4 -2
  107. package/dist/swell-api-command.d.ts +13 -0
  108. package/dist/swell-api-command.js +75 -0
  109. package/dist/swell-command.d.ts +1 -1
  110. package/dist/swell-command.js +9 -9
  111. package/oclif.manifest.json +639 -46
  112. package/package.json +8 -1
@@ -26,8 +26,8 @@ export declare abstract class PushAppCommand extends RemoteAppCommand {
26
26
  deployFrontend(projectType: FrontendProjectType): Promise<string>;
27
27
  ensureAppExists(file?: string, shouldCreate?: boolean): Promise<boolean>;
28
28
  ensureLoggedIn(): Promise<true | undefined>;
29
- execFrontend(command: string, onOutput?: (string: string) => any | false): Promise<void>;
30
29
  exec(command: string, cwd?: string, onOutput?: (string: string) => any | false): Promise<void>;
30
+ execFrontend(command: string, onOutput?: (string: string) => any | false): Promise<void>;
31
31
  getAllAppStorefronts(params?: {
32
32
  type?: string;
33
33
  }): Promise<any>;
@@ -51,19 +51,19 @@ export declare abstract class PushAppCommand extends RemoteAppCommand {
51
51
  appId?: string;
52
52
  targetPath?: string;
53
53
  }, flags?: {
54
+ env?: string;
54
55
  'storefront-id'?: string;
55
56
  'storefront-select'?: boolean;
56
- env?: string;
57
57
  }): Promise<any>;
58
58
  getStorefrontToPush(flags?: {
59
+ env?: string;
59
60
  'storefront-id'?: string;
60
61
  'storefront-select'?: boolean;
61
- env?: string;
62
62
  }): Promise<any>;
63
63
  setStorefrontEnv(flags: {
64
+ env?: string;
64
65
  'storefront-id'?: string;
65
66
  'storefront-select'?: boolean;
66
- env?: string;
67
67
  }, defaultStorefront?: any): Promise<void>;
68
68
  handleWatchFileChange(configFile: string, configType: ConfigType, event: WatchFileEvent): Promise<void>;
69
69
  logAppFrontendUrl(): void;
@@ -78,15 +78,15 @@ export declare abstract class PushAppCommand extends RemoteAppCommand {
78
78
  runWatchChangeQueue(): Promise<void>;
79
79
  saveCurrentStorefront(): void;
80
80
  setWatchingFiles(): Promise<void>;
81
+ startProxyServer(port?: number): Promise<number>;
81
82
  updateFrontendDeployment(currentStore: string, projectType: FrontendProjectType, deploymentUrl: string, deploymentHash: string): Promise<void>;
83
+ updateLocalProxy(proxyUrl: string, storefrontId?: string): Promise<void>;
82
84
  watchForChanges({ logChanges, onChange, syncAll, }?: {
83
85
  logChanges?: boolean;
84
86
  onChange?: (appConfig?: AppConfig, result?: any) => void;
85
87
  syncAll?: boolean;
86
88
  }): Promise<void>;
87
- startProxyServer(port?: number): Promise<number>;
88
- updateLocalProxy(proxyUrl: string, storefrontId?: string): Promise<void>;
89
- wranglerDeployFrontend(projectType: FrontendProjectType): Promise<string>;
89
+ wranglerDeployFrontend(_projectType: FrontendProjectType): Promise<string>;
90
90
  private confirmRemoveInstalledApp;
91
91
  }
92
92
  export {};
@@ -1,19 +1,19 @@
1
1
  import { confirm, input, select } from '@inquirer/prompts';
2
2
  import { $ } from 'execa';
3
+ import getPort, { portNumbers } from 'get-port';
3
4
  import * as fs from 'node:fs';
4
5
  import * as path from 'node:path';
5
6
  import Stream from 'node:stream';
6
- import getPort, { portNumbers } from 'get-port';
7
7
  import ora from 'ora';
8
8
  import { default as swellConfig } from './lib/app-config.js';
9
- import { ConfigType, FrontendProjectTypes, allConfigFilesInDir, appConfigFromFile, filePathExists, filePathExistsAsync, findAppConfig, getAppSlugId, getConfigTypeFromPath, getConfigTypeKeyFromValue, getFrontendProjectType, globAllFilesByPath, hashString, isPathDirectory, } from './lib/apps/index.js';
10
- import { selectEnvironmentId } from './lib/stores.js';
9
+ import { ConfigType, getFrontendProjectValidValues, allConfigFilesInDir, appConfigFromFile, filePathExists, filePathExistsAsync, findAppConfig, getAppSlugId, getConfigTypeFromPath, getConfigTypeKeyFromValue, getFrontendProjectType, globAllFilesByPath, hashString, isPathDirectory, } from './lib/apps/index.js';
11
10
  import { getGlobIgnorePathsChecker } from './lib/apps/paths.js';
12
11
  import { default as localConfig } from './lib/config.js';
13
12
  import { toAppId } from './lib/create/index.js';
13
+ import { getProxyUrl } from './lib/proxy.js';
14
+ import { selectEnvironmentId } from './lib/stores.js';
14
15
  import style from './lib/style.js';
15
16
  import { RemoteAppCommand } from './remote-app-command.js';
16
- import { getProxyUrl } from './lib/proxy.js';
17
17
  const PUSH_CONCURRENCY = 3;
18
18
  const WATCH_WINDOW_MS = 100;
19
19
  const DEV_SERVER_FALLBACK_PORT = 3000;
@@ -307,9 +307,6 @@ export class PushAppCommand extends RemoteAppCommand {
307
307
  return true;
308
308
  }
309
309
  }
310
- async execFrontend(command, onOutput) {
311
- return this.exec(command, this.frontendPath, onOutput);
312
- }
313
310
  async exec(command, cwd, onOutput) {
314
311
  const $$ = $({
315
312
  cwd: cwd || this.appPath,
@@ -334,6 +331,9 @@ export class PushAppCommand extends RemoteAppCommand {
334
331
  await $$ `${command}`;
335
332
  }
336
333
  }
334
+ async execFrontend(command, onOutput) {
335
+ return this.exec(command, this.frontendPath, onOutput);
336
+ }
337
337
  async getAllAppStorefronts(params) {
338
338
  const query = Object.entries(params || {})
339
339
  .map(([key, value]) => `${key}=${value}`)
@@ -435,7 +435,7 @@ export class PushAppCommand extends RemoteAppCommand {
435
435
  this.showFrontendMigrationError();
436
436
  }
437
437
  // Frontend directory doesn't exist at all
438
- this.error(`No valid frontend app found in ${this.frontendPath}. Supported frameworks include: ${FrontendProjectTypes.map((type) => type.slug).join(', ')}.`);
438
+ this.error(`No valid frontend app found in ${this.frontendPath}. Supported frameworks include: ${getFrontendProjectValidValues(false)}.`);
439
439
  }
440
440
  return projectType;
441
441
  }
@@ -561,8 +561,8 @@ export class PushAppCommand extends RemoteAppCommand {
561
561
  await this.api.setStoreEnv(currentStore, defaultStorefront?.env);
562
562
  }
563
563
  }
564
- else if (flags['env']) {
565
- await this.api.setStoreEnv(currentStore, flags['env']);
564
+ else if (flags.env) {
565
+ await this.api.setStoreEnv(currentStore, flags.env);
566
566
  }
567
567
  else {
568
568
  const hasTestEnv = await this.api.isTestEnvEnabled();
@@ -703,8 +703,9 @@ export class PushAppCommand extends RemoteAppCommand {
703
703
  }
704
704
  const queue = [...this.watchingChangeQueue.values()];
705
705
  this.watchingChangeQueue.clear();
706
+ // Process queue in batches with concurrency control
707
+ /* eslint-disable no-await-in-loop */
706
708
  while (queue.length > 0) {
707
- // eslint-disable-next-line no-await-in-loop
708
709
  try {
709
710
  await Promise.all(queue
710
711
  .splice(0, PUSH_CONCURRENCY)
@@ -715,10 +716,11 @@ export class PushAppCommand extends RemoteAppCommand {
715
716
  this.onWatchChange?.(appConfig, action, result);
716
717
  }));
717
718
  }
718
- catch (_err) {
719
- //noop
719
+ catch {
720
+ // noop
720
721
  }
721
722
  }
723
+ /* eslint-enable no-await-in-loop */
722
724
  // refetch app to get updated configs
723
725
  this.app = await this.getAppWithConfig(this.app.id);
724
726
  // Process next accumulated changes
@@ -733,6 +735,16 @@ export class PushAppCommand extends RemoteAppCommand {
733
735
  async setWatchingFiles() {
734
736
  this.watchingFiles = new Set(await globAllFilesByPath(this.appPath));
735
737
  }
738
+ async startProxyServer(port) {
739
+ // Find an open port starting at 3000
740
+ const freePort = port ||
741
+ (await getPort({ port: portNumbers(3000, 3100) })) ||
742
+ DEV_SERVER_FALLBACK_PORT;
743
+ // Start proxy
744
+ const proxyUrl = await getProxyUrl(freePort);
745
+ await this.updateLocalProxy(proxyUrl, this.storefront?.id);
746
+ return freePort;
747
+ }
736
748
  async updateFrontendDeployment(currentStore, projectType, deploymentUrl, deploymentHash) {
737
749
  const spinner = ora();
738
750
  spinner.start('Updating frontend deployment...');
@@ -750,6 +762,17 @@ export class PushAppCommand extends RemoteAppCommand {
750
762
  }), () => spinner.fail('Error updating app deployment'));
751
763
  spinner.succeed('Updated frontend deployment.\n');
752
764
  }
765
+ async updateLocalProxy(proxyUrl, storefrontId) {
766
+ const storefront = this.app.type === 'storefront' &&
767
+ (await this.getAppStorefront({ storefront_id: storefrontId }));
768
+ await this.handleRequestErrors(async () => this.api.put({ adminPath: `/client/apps/${this.app.id}/local-proxy` }, {
769
+ body: {
770
+ proxy_url: proxyUrl,
771
+ storefront_id: storefront?.id || null,
772
+ storefront_slug: storefront?.slug || null,
773
+ },
774
+ }));
775
+ }
753
776
  async watchForChanges({ logChanges, onChange, syncAll, } = {}) {
754
777
  this.watchingIgnoreFilter = await getGlobIgnorePathsChecker(this.appPath);
755
778
  this.logWatchChanges = logChanges ?? true;
@@ -765,28 +788,7 @@ export class PushAppCommand extends RemoteAppCommand {
765
788
  }
766
789
  fs.watch(this.appPath, { recursive: true }, this.watchListener);
767
790
  }
768
- async startProxyServer(port) {
769
- // Find an open port starting at 3000
770
- const freePort = port ||
771
- (await getPort({ port: portNumbers(3000, 3100) })) ||
772
- DEV_SERVER_FALLBACK_PORT;
773
- // Start proxy
774
- const proxyUrl = await getProxyUrl(freePort);
775
- await this.updateLocalProxy(proxyUrl, this.storefront?.id);
776
- return freePort;
777
- }
778
- async updateLocalProxy(proxyUrl, storefrontId) {
779
- const storefront = this.app.type === 'storefront' &&
780
- (await this.getAppStorefront({ storefront_id: storefrontId }));
781
- await this.handleRequestErrors(async () => this.api.put({ adminPath: `/client/apps/${this.app.id}/local-proxy` }, {
782
- body: {
783
- proxy_url: proxyUrl,
784
- storefront_id: storefront?.id || null,
785
- storefront_slug: storefront?.slug || null,
786
- },
787
- }));
788
- }
789
- async wranglerDeployFrontend(projectType) {
791
+ async wranglerDeployFrontend(_projectType) {
790
792
  let deploymentUrl;
791
793
  let interactiveError = false;
792
794
  let pagesProjectError = false;
@@ -795,7 +797,7 @@ export class PushAppCommand extends RemoteAppCommand {
795
797
  await this.execFrontend(`npx wrangler deploy`, (string) => {
796
798
  // Dependent on wrangler output
797
799
  // Parse the deployment URL from the wrangler output.
798
- const match = string.match(/^\s*(https:\/\/\S+\.workers\.dev)\s*[\s\S]*?Current Version ID: [\w-]+/m);
800
+ const match = string.match(/^\s*(https:\/\/\S+\.workers\.dev)\s*[\S\s]*?Current Version ID: [\w-]+/m);
799
801
  if (match && match.length > 0) {
800
802
  deploymentUrl = match[1];
801
803
  return false;
@@ -5,11 +5,11 @@ import { App, AppConfig, AppVersion } from './lib/apps/index.js';
5
5
  * configurations.
6
6
  */
7
7
  export declare abstract class RemoteAppCommand extends AppCommand {
8
- appType: string;
9
8
  static delayOrientation: boolean;
10
9
  static orientation: AppCommandOrientation;
11
10
  app: App;
12
11
  appCreated: boolean;
12
+ appType: string;
13
13
  storefront?: any;
14
14
  storefrontLocalUrl?: string;
15
15
  themeSyncApp?: boolean;
@@ -15,7 +15,6 @@ import style from './lib/style.js';
15
15
  * configurations.
16
16
  */
17
17
  export class RemoteAppCommand extends AppCommand {
18
- appType = 'any';
19
18
  // allows child commands to set orientation
20
19
  static delayOrientation = false;
21
20
  // most of the times this will be the target environment
@@ -24,6 +23,7 @@ export class RemoteAppCommand extends AppCommand {
24
23
  app = {};
25
24
  // Indicates the app was created during the command execution
26
25
  appCreated = false;
26
+ appType = 'any';
27
27
  // API instance of the target storefront, if applicable
28
28
  storefront = null;
29
29
  // Indicates we are syncing with a local app frontend via proxy
@@ -638,7 +638,9 @@ export class RemoteAppCommand extends AppCommand {
638
638
  const { env, store } = flags;
639
639
  if (this.app.name) {
640
640
  // Show theme version if not syncing app
641
- const version = !this.themeSyncApp && this.app.type === 'theme' && this.storefront?.theme_version
641
+ const version = !this.themeSyncApp &&
642
+ this.app.type === 'theme' &&
643
+ this.storefront?.theme_version
642
644
  ? this.storefront?.theme_version
643
645
  : this.app.version;
644
646
  orientationOutput.push(`[${this.app.type === 'theme' ? 'theme' : 'app'}] ${style.appName(this.app.name)}${version ? ` v${version}` : ''}`);
@@ -0,0 +1,13 @@
1
+ import { HttpMethod } from './lib/api.js';
2
+ import { SwellCommand } from './swell-command.js';
3
+ export declare abstract class SwellApiCommand extends SwellCommand {
4
+ protected abstract get method(): HttpMethod;
5
+ protected request(command: typeof SwellApiCommand, requestOptions?: Api.RequestOptions): Promise<void>;
6
+ protected catch(error: Error): Promise<any>;
7
+ private parseCommand;
8
+ private processBody;
9
+ private isFilePath;
10
+ private handleResponse;
11
+ private onSuccess;
12
+ private onError;
13
+ }
@@ -0,0 +1,75 @@
1
+ import * as fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { FetchError } from 'node-fetch';
4
+ import { SwellCommand } from './swell-command.js';
5
+ export class SwellApiCommand extends SwellCommand {
6
+ async request(command, requestOptions = {}) {
7
+ const { paths, options } = await this.parseCommand(command);
8
+ const response = await this.api[this.method](paths, {
9
+ rawResponse: true,
10
+ ...options,
11
+ ...requestOptions,
12
+ });
13
+ await this.handleResponse(response);
14
+ }
15
+ async catch(error) {
16
+ if (error instanceof FetchError) {
17
+ const message = `Could not connect to Swell API. Please try again later: ${error.message}`;
18
+ return this.onError(message, { exit: 2, code: error.code });
19
+ }
20
+ return this.onError(error.message, { exit: 1 });
21
+ }
22
+ async parseCommand(options, argv) {
23
+ const parsedInput = await super.parse(options, argv);
24
+ const { args, flags } = parsedInput;
25
+ const { path } = args;
26
+ const { live, body } = flags;
27
+ if (!live) {
28
+ await this.api.setEnv('test');
29
+ }
30
+ if (!path.startsWith('/')) {
31
+ throw new Error('Path must start with a forward slash (/)');
32
+ }
33
+ return {
34
+ ...parsedInput,
35
+ paths: { adminPath: `/data${path}` },
36
+ options: {
37
+ body: await this.processBody(body),
38
+ },
39
+ };
40
+ }
41
+ async processBody(body) {
42
+ if (!body) {
43
+ return;
44
+ }
45
+ const bodyData = this.isFilePath(body)
46
+ ? await fs.promises.readFile(path.resolve(body), 'utf8')
47
+ : body;
48
+ return JSON.parse(bodyData);
49
+ }
50
+ isFilePath(filePath) {
51
+ return (path.isAbsolute(filePath) ||
52
+ filePath.startsWith('./') ||
53
+ filePath.startsWith('../'));
54
+ }
55
+ async handleResponse(response) {
56
+ const responseText = await response.text();
57
+ if (responseText.length <= 2) {
58
+ throw new Error('Not found');
59
+ }
60
+ const result = JSON.parse(responseText);
61
+ if (result.error || result.errors || !response.ok) {
62
+ throw new Error(responseText);
63
+ }
64
+ this.onSuccess(result);
65
+ }
66
+ onSuccess(result) {
67
+ this.log(JSON.stringify(result, null, 2));
68
+ }
69
+ onError(message, { code, exit }) {
70
+ this.error(message, {
71
+ code,
72
+ exit,
73
+ });
74
+ }
75
+ }
@@ -14,8 +14,8 @@ export declare abstract class SwellCommand extends Command {
14
14
  api: Api;
15
15
  requiresAuth: boolean;
16
16
  constructor(argv: string[], config: Config);
17
- catch(error: any): Promise<void>;
18
17
  debugJson(...args: any[]): void;
19
18
  logError(message: string): void;
20
19
  logSuccess(message: string): void;
20
+ protected catch(error: any): Promise<void>;
21
21
  }
@@ -21,15 +21,6 @@ export class SwellCommand extends Command {
21
21
  super(argv, config);
22
22
  this.api = new Api();
23
23
  }
24
- async catch(error) {
25
- if (error instanceof GitUnknownError) {
26
- this.error(style.error(`git: ${error.stderr || error.stdout || error.message}`));
27
- }
28
- else if (error instanceof FetchError) {
29
- this.error(`Could not connect to Swell API. Please try again later: ${error.message}`);
30
- }
31
- throw error;
32
- }
33
24
  debugJson(...args) {
34
25
  const stringified = args.map((arg) => typeof arg === 'string' ? arg : JSON.stringify(arg, null, 4));
35
26
  this.debug(...stringified);
@@ -40,4 +31,13 @@ export class SwellCommand extends Command {
40
31
  logSuccess(message) {
41
32
  this.log(`${style.success(message)}`);
42
33
  }
34
+ async catch(error) {
35
+ if (error instanceof GitUnknownError) {
36
+ this.error(style.error(`git: ${error.stderr || error.stdout || error.message}`));
37
+ }
38
+ else if (error instanceof FetchError) {
39
+ this.error(`Could not connect to Swell API. Please try again later: ${error.message}`);
40
+ }
41
+ throw error;
42
+ }
43
43
  }