@swell/cli 2.9.6 → 2.9.7

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.
@@ -11,6 +11,7 @@ export default class AppDev extends PushAppCommand {
11
11
  function: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
12
  'storefront-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
13
  'storefront-select': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
14
+ 'json-events': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
14
15
  yes: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
15
16
  };
16
17
  static orientation: {
@@ -24,10 +25,12 @@ export default class AppDev extends PushAppCommand {
24
25
  tmpDir: string;
25
26
  frontendPort: number | null;
26
27
  isCleaningUp: boolean;
28
+ jsonEvents: boolean;
27
29
  run(): Promise<void>;
28
30
  private cleanupOnExit;
29
31
  runAppFrontendDevIfApplicable(frontendPort?: number): Promise<number | undefined>;
30
32
  private createFunctionRouter;
33
+ private emitLifecycleEvent;
31
34
  private createTmpDirectory;
32
35
  private generateWranglerConfig;
33
36
  private getAppFunctions;
@@ -42,6 +42,10 @@ export default class AppDev extends PushAppCommand {
42
42
  default: false,
43
43
  description: 'for storefront apps, prompt to select a storefront to preview',
44
44
  }),
45
+ 'json-events': Flags.boolean({
46
+ description: 'emit machine-readable dev server lifecycle events',
47
+ hidden: true,
48
+ }),
45
49
  // Declared here so oclif accepts -y; passed through to app:frontend:dev via this.argv
46
50
  yes: Flags.boolean({
47
51
  char: 'y',
@@ -65,10 +69,12 @@ export default class AppDev extends PushAppCommand {
65
69
  frontendPort = null;
66
70
  // Guard against multiple cleanup calls
67
71
  isCleaningUp = false;
72
+ jsonEvents = false;
68
73
  async run() {
69
74
  const { flags } = await this.parse(AppDev);
70
75
  const { port, 'frontend-port': frontendPort } = flags;
71
76
  const noPush = flags['no-push'];
77
+ this.jsonEvents = flags['json-events'];
72
78
  this.functionFilter = flags.function ?? null;
73
79
  if (!(await this.ensureAppExists(undefined, false))) {
74
80
  return;
@@ -88,6 +94,10 @@ export default class AppDev extends PushAppCommand {
88
94
  process.on('SIGTERM', this.cleanupOnExit.bind(this));
89
95
  const serverPort = await this.startProxyServer(port);
90
96
  await this.startAppFunctionServer(spinner, serverPort);
97
+ this.emitLifecycleEvent('preview:proxy-ready', {
98
+ proxyPort: serverPort,
99
+ storefrontId: this.storefront?.id ?? null,
100
+ });
91
101
  await this.runAppFrontendDevIfApplicable(frontendPort);
92
102
  }
93
103
  async cleanupOnExit() {
@@ -103,6 +113,9 @@ export default class AppDev extends PushAppCommand {
103
113
  catch {
104
114
  // Ignore errors during cleanup
105
115
  }
116
+ this.emitLifecycleEvent('preview:stopped', {
117
+ storefrontId: this.storefront?.id ?? null,
118
+ });
106
119
  this.log();
107
120
  // eslint-disable-next-line no-process-exit, unicorn/no-process-exit
108
121
  process.exit();
@@ -199,7 +212,18 @@ export default class AppDev extends PushAppCommand {
199
212
  : ''}`);
200
213
  }
201
214
  });
202
- server.listen(serverPort);
215
+ await new Promise((resolve, reject) => {
216
+ server.once('error', reject);
217
+ server.listen(serverPort, () => {
218
+ server.off('error', reject);
219
+ resolve();
220
+ });
221
+ });
222
+ }
223
+ emitLifecycleEvent(type, data) {
224
+ if (!this.jsonEvents)
225
+ return;
226
+ this.log(JSON.stringify({ type, ...data }));
203
227
  }
204
228
  async createTmpDirectory() {
205
229
  const tmpBase = path.join(os.tmpdir(), 'swell-cli');
@@ -11,6 +11,7 @@ export default class AppFrontendDev extends PushAppCommand {
11
11
  port: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
12
  'frontend-port': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
13
  function: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
+ 'json-events': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
14
15
  };
15
16
  static orientation: {
16
17
  env: string;
@@ -14,6 +14,8 @@ export default class CreateApp extends CreateAppCommand {
14
14
  static helpMeta: HelpMeta;
15
15
  static flags: any;
16
16
  appType: string;
17
+ private jsonOutput;
18
+ log(message?: string, ...args: any[]): void;
17
19
  createSwellConfig({ allowOverwrite, inputId, inputStorefrontApp, inputType, inputName, inputVersion, inputDescription, inputFrontend, inputIntegrationType, inputIntegrationId, inputYes, nestedPath, }: {
18
20
  allowOverwrite?: boolean;
19
21
  inputDescription?: string;
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import ora from 'ora';
5
5
  import { CreateAppCommand } from '../../create-app-command.js';
6
6
  import { newConfig, swellConfigFileExists } from '../../lib/app-config.js';
7
+ import { buildCreateAppResult } from '../../lib/apps/create-app-result.js';
7
8
  import { toAppId, toAppName } from '../../lib/create/index.js';
8
9
  import style from '../../lib/style.js';
9
10
  /**
@@ -90,8 +91,16 @@ export default class CreateApp extends CreateAppCommand {
90
91
  char: 'd',
91
92
  description: 'Description',
92
93
  }),
94
+ json: Flags.boolean({
95
+ description: 'Output the command result as JSON',
96
+ }),
93
97
  };
94
98
  appType = '';
99
+ jsonOutput = false;
100
+ log(message, ...args) {
101
+ if (!this.jsonOutput)
102
+ super.log(message, ...args);
103
+ }
95
104
  async createSwellConfig({ allowOverwrite = true, inputId = '', inputStorefrontApp, inputType, inputName, inputVersion, inputDescription, inputFrontend, inputIntegrationType, inputIntegrationId, inputYes, nestedPath = true, }) {
96
105
  const confirmYes = inputYes;
97
106
  let appId = toAppId(inputId || '');
@@ -352,7 +361,8 @@ export default class CreateApp extends CreateAppCommand {
352
361
  async run() {
353
362
  const { args, flags } = await this.parse(CreateApp);
354
363
  const { id } = args;
355
- const { pkg, yes, name, type, version, description, frontend } = flags;
364
+ const { pkg, yes, name, type, version, description, frontend, json } = flags;
365
+ this.jsonOutput = Boolean(json);
356
366
  const confirmYes = Boolean(yes);
357
367
  const createParams = await this.createSwellConfig({
358
368
  inputId: id,
@@ -369,7 +379,7 @@ export default class CreateApp extends CreateAppCommand {
369
379
  if (!createParams) {
370
380
  return;
371
381
  }
372
- const { appId, config, installedStorefrontApp } = createParams;
382
+ const { appId, config, installedStorefrontApp, swellConfigJson } = createParams;
373
383
  !confirmYes && this.log();
374
384
  const spinner = ora();
375
385
  spinner.start('Creating app...');
@@ -378,21 +388,37 @@ export default class CreateApp extends CreateAppCommand {
378
388
  }
379
389
  await this.createAppConfigFolders(config);
380
390
  spinner.succeed(`${style.appConfigValue(config.get('name'))} app created.\n`);
381
- let createdFrontend;
391
+ let frontendResult;
392
+ let resources;
382
393
  let createdTheme;
383
394
  if (installedStorefrontApp) {
384
395
  createdTheme = await this.createThemeApp(config, flags, installedStorefrontApp);
385
396
  }
386
397
  else if (config.get('type') === 'storefront') {
387
- createdFrontend = await this.createStorefrontApp(config, flags);
398
+ const storefrontResult = await this.createStorefrontApp(config, flags, {
399
+ provisionResources: true,
400
+ });
401
+ frontendResult = storefrontResult;
402
+ resources = storefrontResult.resources;
388
403
  }
389
404
  else {
390
- createdFrontend = await this.createFrontendApp(config, flags);
405
+ frontendResult = await this.createFrontendApp(config, flags);
406
+ }
407
+ if (json) {
408
+ super.log(JSON.stringify(buildCreateAppResult({
409
+ privateId: swellConfigJson.id,
410
+ resources,
411
+ name: swellConfigJson.name,
412
+ type: swellConfigJson.type,
413
+ frontend: frontendResult?.framework ?? null,
414
+ path: path.dirname(config.path),
415
+ })));
416
+ return;
391
417
  }
392
418
  this.log('\nNext steps:');
393
419
  this.log(`Run ${style.command('swell app push')} to push configurations to your test store.`);
394
420
  this.log(`Run ${style.command('swell app install')} to install the app in another store or environment.`);
395
- if (createdFrontend) {
421
+ if (frontendResult?.created) {
396
422
  this.log(`Run ${style.command('swell app frontend dev')} to start a local dev server for your frontend app.`);
397
423
  }
398
424
  else if (createdTheme) {
@@ -32,7 +32,9 @@ export default class CreateFrontend extends CreateAppCommand {
32
32
  return;
33
33
  }
34
34
  await (appType === 'storefront'
35
- ? this.createStorefrontApp(newSwellConfig, flags, true)
35
+ ? this.createStorefrontApp(newSwellConfig, flags, {
36
+ directCreate: true,
37
+ })
36
38
  : this.createFrontendApp(newSwellConfig, flags, true));
37
39
  }
38
40
  }
@@ -1,5 +1,18 @@
1
+ import { type StorefrontResourceResult } from './lib/apps/storefront-resources.js';
1
2
  import { PackageManager } from './lib/package-manager.js';
2
3
  import { SwellCommand } from './swell-command.js';
4
+ export interface FrontendCreationResult {
5
+ created: boolean;
6
+ framework: string | null;
7
+ provisionsStorefront: boolean;
8
+ }
9
+ export interface StorefrontCreationResult extends FrontendCreationResult {
10
+ resources?: StorefrontResourceResult;
11
+ }
12
+ export interface StorefrontCreationOptions {
13
+ directCreate?: boolean;
14
+ provisionResources?: boolean;
15
+ }
3
16
  export declare abstract class CreateAppCommand extends SwellCommand {
4
17
  protected commandExample: string;
5
18
  static baseFlags: {
@@ -25,8 +38,8 @@ export declare abstract class CreateAppCommand extends SwellCommand {
25
38
  */
26
39
  private addViteAllowedHosts;
27
40
  createAppConfigFolders(swellConfig: any): Promise<void>;
28
- createFrontendApp(swellConfig: any, flags: any, directCreate?: boolean, kind?: string): Promise<boolean>;
29
- createStorefrontApp(swellConfig: any, flags: any, directCreate?: boolean): Promise<boolean>;
41
+ createFrontendApp(swellConfig: any, flags: any, directCreate?: boolean, kind?: string): Promise<FrontendCreationResult>;
42
+ createStorefrontApp(swellConfig: any, flags: any, options?: StorefrontCreationOptions): Promise<StorefrontCreationResult>;
30
43
  createThemeApp(config: any, flags: any, installedStorefrontApp: any): Promise<boolean>;
31
44
  doesPackageManagerExist(packageManager: string): Promise<boolean>;
32
45
  execWithStdio(cwd: string, command: string, onOutput?: (string: string) => any | false): Promise<void>;
@@ -40,6 +53,7 @@ export declare abstract class CreateAppCommand extends SwellCommand {
40
53
  displayOrder?: number | undefined;
41
54
  mainPackage: string;
42
55
  name: string;
56
+ provisionsStorefront?: boolean | undefined;
43
57
  slug: string;
44
58
  };
45
59
  setupPackage(name: string, config: any, pkg: PackageManager): Promise<void>;
@@ -9,6 +9,7 @@ import { promisify } from 'node:util';
9
9
  import ora from 'ora';
10
10
  import Api from './lib/api.js';
11
11
  import { FrontendProjectTypes, getFrontendProjectValidValues, getAllConfigPaths, getFrontendProjectSlugs, writeFile, writeJsonFile, } from './lib/apps/index.js';
12
+ import { ensureStorefrontResources, } from './lib/apps/storefront-resources.js';
12
13
  import { getPackageManagerCommands, transformCreateCommand, } from './lib/package-manager.js';
13
14
  import style from './lib/style.js';
14
15
  import { SwellCommand } from './swell-command.js';
@@ -287,7 +288,11 @@ export class CreateAppCommand extends SwellCommand {
287
288
  const files = await fs.readdir(frontendPath);
288
289
  if (files.length > 0) {
289
290
  spinner.fail('frontend/ folder is not empty. Please remove existing files before scaffolding.');
290
- return false;
291
+ return {
292
+ created: false,
293
+ framework: projectType.slug,
294
+ provisionsStorefront: Boolean(projectType.provisionsStorefront),
295
+ };
291
296
  }
292
297
  }
293
298
  catch {
@@ -298,11 +303,28 @@ export class CreateAppCommand extends SwellCommand {
298
303
  await execAsync(`mkdir -p frontend`, {
299
304
  cwd: configPath,
300
305
  });
301
- // Transform install command for the selected package manager
302
- const installCommand = transformCreateCommand(projectType.installCommand, pkg);
303
- await execAsync(installCommand, {
304
- cwd: configPath,
305
- });
306
+ // SWELL_LOCAL_TEMPLATE_PATH overrides the scaffold for local dev copies
307
+ // the directory at the path into frontend/ instead of running the install
308
+ // command. Used to iterate on the canonical template repo without pushing.
309
+ const localTemplatePath = process.env.SWELL_LOCAL_TEMPLATE_PATH;
310
+ if (localTemplatePath) {
311
+ const source = path.resolve(localTemplatePath);
312
+ const dest = path.join(configPath, 'frontend');
313
+ await fs.cp(source, dest, {
314
+ recursive: true,
315
+ filter: (src) => !src.includes('/node_modules') &&
316
+ !src.endsWith('/.git') &&
317
+ !src.includes('/dist') &&
318
+ !src.includes('/.wrangler'),
319
+ });
320
+ }
321
+ else {
322
+ // Transform install command for the selected package manager
323
+ const installCommand = transformCreateCommand(projectType.installCommand, pkg);
324
+ await execAsync(installCommand, {
325
+ cwd: configPath,
326
+ });
327
+ }
306
328
  // Use this command to debug output, i.e.e when command becomes non-responsive
307
329
  /* await this.execWithStdio(
308
330
  configPath,
@@ -317,7 +339,11 @@ export class CreateAppCommand extends SwellCommand {
317
339
  .join('\n') || (error.message ?? '').trim();
318
340
  if (detail)
319
341
  this.log(detail);
320
- return false;
342
+ return {
343
+ created: false,
344
+ framework: projectType.slug,
345
+ provisionsStorefront: Boolean(projectType.provisionsStorefront),
346
+ };
321
347
  }
322
348
  // Ensure frontend package.json has correct name for workspace
323
349
  try {
@@ -346,12 +372,34 @@ export class CreateAppCommand extends SwellCommand {
346
372
  if (directCreate) {
347
373
  this.log();
348
374
  }
349
- return true;
375
+ return {
376
+ created: true,
377
+ framework: projectType.slug,
378
+ provisionsStorefront: Boolean(projectType.provisionsStorefront),
379
+ };
350
380
  }
351
- return false;
381
+ return {
382
+ created: false,
383
+ framework: null,
384
+ provisionsStorefront: false,
385
+ };
352
386
  }
353
- async createStorefrontApp(swellConfig, flags, directCreate) {
354
- return this.createFrontendApp(swellConfig, flags, directCreate, 'storefront');
387
+ async createStorefrontApp(swellConfig, flags, options = {}) {
388
+ const frontend = await this.createFrontendApp(swellConfig, flags, options.directCreate, 'storefront');
389
+ if (!options.provisionResources ||
390
+ !frontend.created ||
391
+ !frontend.provisionsStorefront) {
392
+ return frontend;
393
+ }
394
+ const resources = await ensureStorefrontResources(this.api, {
395
+ description: swellConfig.get('description'),
396
+ name: swellConfig.get('name'),
397
+ privateId: swellConfig.get('id'),
398
+ type: 'storefront',
399
+ version: swellConfig.get('version'),
400
+ });
401
+ this.log(`Storefront ${style.appConfigValue(resources.storefront.id)} created for app ${style.appConfigValue(resources.app.id)}.`);
402
+ return { ...frontend, resources };
355
403
  }
356
404
  async createThemeApp(config, flags, installedStorefrontApp) {
357
405
  const spinner = ora();
@@ -0,0 +1,31 @@
1
+ import type { StorefrontResourceResult } from './storefront-resources.js';
2
+ export interface CreateAppResultInput {
3
+ frontend: string | null;
4
+ name: string;
5
+ path: string;
6
+ privateId: string;
7
+ resources?: StorefrontResourceResult;
8
+ type: string;
9
+ }
10
+ export interface CreateAppResult {
11
+ app: {
12
+ name: string;
13
+ privateId: string;
14
+ resourceId: string | null;
15
+ type: string;
16
+ };
17
+ frontend: string | null;
18
+ path: string;
19
+ storefront: {
20
+ resourceId: string;
21
+ } | null;
22
+ }
23
+ /**
24
+ * Build the stable JSON contract for every `swell create app` variant.
25
+ * Remote resource IDs are nullable because only provisioning frontends create
26
+ * them; the shape itself never changes by app type or frontend.
27
+ *
28
+ * @param input completed local and optional remote creation result
29
+ * @returns serializable command result
30
+ */
31
+ export declare function buildCreateAppResult(input: CreateAppResultInput): CreateAppResult;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Build the stable JSON contract for every `swell create app` variant.
3
+ * Remote resource IDs are nullable because only provisioning frontends create
4
+ * them; the shape itself never changes by app type or frontend.
5
+ *
6
+ * @param input completed local and optional remote creation result
7
+ * @returns serializable command result
8
+ */
9
+ export function buildCreateAppResult(input) {
10
+ return {
11
+ app: {
12
+ privateId: input.privateId,
13
+ resourceId: input.resources?.app.id ?? null,
14
+ name: input.name,
15
+ type: input.type,
16
+ },
17
+ storefront: input.resources
18
+ ? { resourceId: input.resources.storefront.id }
19
+ : null,
20
+ frontend: input.frontend,
21
+ path: input.path,
22
+ };
23
+ }
@@ -128,6 +128,7 @@ export interface FrontendProjectType {
128
128
  installCommand?: string;
129
129
  mainPackage: string;
130
130
  name: string;
131
+ provisionsStorefront?: boolean;
131
132
  slug: string;
132
133
  }
133
134
  export declare const CUSTOM_FRAMEWORK_SLUG = "custom";
@@ -130,6 +130,7 @@ export const FrontendProjectTypes = [
130
130
  installCommand: 'npm create cloudflare@latest -- frontend --template=swellstores/storefront-react-ai-template#main --deploy=false --git=false --no-agents',
131
131
  mainPackage: '@swell/storefront-app-sdk-react',
132
132
  name: 'Swell React Storefront',
133
+ provisionsStorefront: true,
133
134
  slug: 'react-storefront',
134
135
  },
135
136
  {
@@ -0,0 +1,28 @@
1
+ import Api from '../api.js';
2
+ export interface StorefrontResourceInput {
3
+ description?: string;
4
+ name: string;
5
+ privateId: string;
6
+ type: 'storefront';
7
+ version: string;
8
+ }
9
+ export interface StorefrontResourceResult {
10
+ app: {
11
+ id: string;
12
+ privateId: string;
13
+ };
14
+ storefront: {
15
+ id: string;
16
+ };
17
+ }
18
+ /**
19
+ * Ensure the remote development app and its storefront exist.
20
+ *
21
+ * `swell create app --frontend react-storefront` calls this after the local
22
+ * scaffold succeeds. Retrying is safe: existing resources are reused.
23
+ *
24
+ * @param api authenticated Swell API client
25
+ * @param input storefront app identity from the generated swell.json
26
+ * @returns the stable remote app and storefront IDs
27
+ */
28
+ export declare function ensureStorefrontResources(api: Api, input: StorefrontResourceInput): Promise<StorefrontResourceResult>;
@@ -0,0 +1,60 @@
1
+ import config from '../config.js';
2
+ /**
3
+ * Ensure the remote development app and its storefront exist.
4
+ *
5
+ * `swell create app --frontend react-storefront` calls this after the local
6
+ * scaffold succeeds. Retrying is safe: existing resources are reused.
7
+ *
8
+ * @param api authenticated Swell API client
9
+ * @param input storefront app identity from the generated swell.json
10
+ * @returns the stable remote app and storefront IDs
11
+ */
12
+ export async function ensureStorefrontResources(api, input) {
13
+ const storeId = config.getDefaultStore();
14
+ await api.setStoreEnv(storeId, 'test');
15
+ let app;
16
+ try {
17
+ const existing = await api.get({
18
+ adminPath: `/apps/${input.privateId}`,
19
+ });
20
+ if (existing?.client_id === storeId) {
21
+ app = existing;
22
+ }
23
+ }
24
+ catch {
25
+ // App not found — create it below.
26
+ }
27
+ if (!app) {
28
+ app = await api.post({ adminPath: '/apps' }, {
29
+ body: {
30
+ description: input.description,
31
+ name: input.name,
32
+ private_id: input.privateId,
33
+ type: input.type,
34
+ version: input.version,
35
+ permissions: [],
36
+ },
37
+ });
38
+ }
39
+ const storefronts = await api.get({
40
+ adminPath: `/apps/${app.id}/storefronts`,
41
+ });
42
+ let storefront = storefronts?.results?.[0];
43
+ if (!storefront) {
44
+ storefront = await api.post({ adminPath: '/storefronts' }, {
45
+ body: {
46
+ app_id: app.id,
47
+ name: input.name,
48
+ },
49
+ });
50
+ }
51
+ return {
52
+ app: {
53
+ id: app.id,
54
+ privateId: input.privateId,
55
+ },
56
+ storefront: {
57
+ id: storefront.id,
58
+ },
59
+ };
60
+ }
@@ -779,6 +779,13 @@
779
779
  "allowNo": false,
780
780
  "type": "boolean"
781
781
  },
782
+ "json-events": {
783
+ "description": "emit machine-readable dev server lifecycle events",
784
+ "hidden": true,
785
+ "name": "json-events",
786
+ "allowNo": false,
787
+ "type": "boolean"
788
+ },
782
789
  "yes": {
783
790
  "char": "y",
784
791
  "description": "skip prompts (non-interactive mode)",
@@ -976,6 +983,12 @@
976
983
  "hasDynamicHelp": false,
977
984
  "multiple": false,
978
985
  "type": "option"
986
+ },
987
+ "json": {
988
+ "description": "Output the command result as JSON",
989
+ "name": "json",
990
+ "allowNo": false,
991
+ "type": "boolean"
979
992
  }
980
993
  },
981
994
  "hasDynamicHelp": false,
@@ -1536,6 +1549,12 @@
1536
1549
  "hasDynamicHelp": false,
1537
1550
  "multiple": false,
1538
1551
  "type": "option"
1552
+ },
1553
+ "json": {
1554
+ "description": "Output the command result as JSON",
1555
+ "name": "json",
1556
+ "allowNo": false,
1557
+ "type": "boolean"
1539
1558
  }
1540
1559
  },
1541
1560
  "hasDynamicHelp": false,
@@ -3215,6 +3234,12 @@
3215
3234
  "hasDynamicHelp": false,
3216
3235
  "multiple": false,
3217
3236
  "type": "option"
3237
+ },
3238
+ "json": {
3239
+ "description": "Output the command result as JSON",
3240
+ "name": "json",
3241
+ "allowNo": false,
3242
+ "type": "boolean"
3218
3243
  }
3219
3244
  },
3220
3245
  "hasDynamicHelp": false,
@@ -3514,6 +3539,13 @@
3514
3539
  "allowNo": false,
3515
3540
  "type": "boolean"
3516
3541
  },
3542
+ "json-events": {
3543
+ "description": "emit machine-readable dev server lifecycle events",
3544
+ "hidden": true,
3545
+ "name": "json-events",
3546
+ "allowNo": false,
3547
+ "type": "boolean"
3548
+ },
3517
3549
  "yes": {
3518
3550
  "char": "y",
3519
3551
  "description": "skip prompts (non-interactive mode)",
@@ -3556,5 +3588,5 @@
3556
3588
  ]
3557
3589
  }
3558
3590
  },
3559
- "version": "2.9.6"
3591
+ "version": "2.9.7"
3560
3592
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swell/cli",
3
- "version": "2.9.6",
3
+ "version": "2.9.7",
4
4
  "type": "module",
5
5
  "description": "Swell's command line interface/utility",
6
6
  "keywords": [