@swell/cli 2.9.6 → 2.9.8
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/dist/app-command.d.ts +1 -0
- package/dist/app-command.js +14 -2
- package/dist/commands/app/dev.d.ts +3 -0
- package/dist/commands/app/dev.js +25 -1
- package/dist/commands/app/frontend/dev.d.ts +1 -0
- package/dist/commands/app/pull.d.ts +1 -0
- package/dist/commands/app/pull.js +1 -0
- package/dist/commands/create/app.d.ts +2 -0
- package/dist/commands/create/app.js +32 -6
- package/dist/commands/create/frontend.js +3 -1
- package/dist/create-app-command.d.ts +16 -2
- package/dist/create-app-command.js +66 -21
- package/dist/lib/apps/create-app-result.d.ts +31 -0
- package/dist/lib/apps/create-app-result.js +23 -0
- package/dist/lib/apps/index.d.ts +2 -1
- package/dist/lib/apps/index.js +2 -1
- package/dist/lib/apps/paths.d.ts +1 -0
- package/dist/lib/apps/paths.js +6 -2
- package/dist/lib/apps/storefront-resources.d.ts +28 -0
- package/dist/lib/apps/storefront-resources.js +60 -0
- package/dist/push-app-command.js +10 -10
- package/oclif.manifest.json +39 -1
- package/package.json +1 -1
package/dist/app-command.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare abstract class AppCommand extends SwellCommand {
|
|
|
14
14
|
static baseFlags: {
|
|
15
15
|
'app-path': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
16
16
|
};
|
|
17
|
+
static requiresSwellConfig: boolean;
|
|
17
18
|
appPath: string;
|
|
18
19
|
swellConfig: LocalApp;
|
|
19
20
|
init(): Promise<void>;
|
package/dist/app-command.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
-
import { default as swellConfig } from './lib/app-config.js';
|
|
3
|
+
import { default as swellConfig, swellConfigFileExists, } from './lib/app-config.js';
|
|
4
|
+
import style from './lib/style.js';
|
|
4
5
|
import { SwellCommand } from './swell-command.js';
|
|
5
6
|
/**
|
|
6
7
|
* A base class for Swell CLI commands that do not require an app to be saved
|
|
@@ -20,6 +21,8 @@ export class AppCommand extends SwellCommand {
|
|
|
20
21
|
description: 'Path to your app directory',
|
|
21
22
|
}),
|
|
22
23
|
};
|
|
24
|
+
// set to false for commands that may run before an app directory exists (pull)
|
|
25
|
+
static requiresSwellConfig = true;
|
|
23
26
|
// the local path to the app directory
|
|
24
27
|
appPath = '';
|
|
25
28
|
// local app configuration, what developers define
|
|
@@ -35,8 +38,17 @@ export class AppCommand extends SwellCommand {
|
|
|
35
38
|
// ensure the base flags are available
|
|
36
39
|
klass.flags = { ...klass.flags, ...AppCommand.baseFlags };
|
|
37
40
|
const { flags } = await this.parse(klass);
|
|
41
|
+
const targetDir = flags['app-path']
|
|
42
|
+
? path.resolve(flags['app-path'])
|
|
43
|
+
: process.cwd();
|
|
44
|
+
// swell.json is only ever looked up in this exact directory
|
|
45
|
+
// Searching parent directories (the previous behavior) can silently pick up an unrelated app's config
|
|
46
|
+
if (klass.requiresSwellConfig &&
|
|
47
|
+
!(await swellConfigFileExists(path.join(targetDir, 'swell.json')))) {
|
|
48
|
+
this.error(`No swell.json found in ${style.path(targetDir)}. Run this command from your app's root directory, or pass --app-path.`);
|
|
49
|
+
}
|
|
38
50
|
// if the user passed an app path, use it: reload the app config
|
|
39
|
-
this.swellConfig = await swellConfig(
|
|
51
|
+
this.swellConfig = await swellConfig(targetDir);
|
|
40
52
|
this.appPath = path.resolve(this.swellConfig.swDirPath);
|
|
41
53
|
}
|
|
42
54
|
}
|
|
@@ -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;
|
package/dist/commands/app/dev.js
CHANGED
|
@@ -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
|
-
|
|
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;
|
|
@@ -4,6 +4,7 @@ export default class AppPull extends PushAppCommand {
|
|
|
4
4
|
appId: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
5
5
|
targetPath: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
6
6
|
};
|
|
7
|
+
static requiresSwellConfig: boolean;
|
|
7
8
|
static description: string;
|
|
8
9
|
static examples: string[];
|
|
9
10
|
static flags: {
|
|
@@ -11,6 +11,7 @@ export default class AppPull extends PushAppCommand {
|
|
|
11
11
|
description: 'path to download app files into',
|
|
12
12
|
}),
|
|
13
13
|
};
|
|
14
|
+
static requiresSwellConfig = false;
|
|
14
15
|
static description = `Pull all app files, a specific file, or a specific configuration
|
|
15
16
|
type from an app in your store's test environment to your local machine.
|
|
16
17
|
|
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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,
|
|
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<
|
|
29
|
-
createStorefrontApp(swellConfig: any, flags: any,
|
|
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';
|
|
@@ -208,12 +209,11 @@ export class CreateAppCommand extends SwellCommand {
|
|
|
208
209
|
await fs.writeFile(configFilePath, content, 'utf8');
|
|
209
210
|
}
|
|
210
211
|
async createAppConfigFolders(swellConfig) {
|
|
212
|
+
const configPath = path.dirname(swellConfig.path);
|
|
211
213
|
for (const type of getAllConfigPaths(swellConfig.get('type'))) {
|
|
212
214
|
// Create a config folder
|
|
213
215
|
// eslint-disable-next-line no-await-in-loop
|
|
214
|
-
await
|
|
215
|
-
cwd: path.dirname(swellConfig.path),
|
|
216
|
-
});
|
|
216
|
+
await fs.mkdir(path.join(configPath, type), { recursive: true });
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
async createFrontendApp(swellConfig, flags, directCreate, kind) {
|
|
@@ -287,7 +287,11 @@ export class CreateAppCommand extends SwellCommand {
|
|
|
287
287
|
const files = await fs.readdir(frontendPath);
|
|
288
288
|
if (files.length > 0) {
|
|
289
289
|
spinner.fail('frontend/ folder is not empty. Please remove existing files before scaffolding.');
|
|
290
|
-
return
|
|
290
|
+
return {
|
|
291
|
+
created: false,
|
|
292
|
+
framework: projectType.slug,
|
|
293
|
+
provisionsStorefront: Boolean(projectType.provisionsStorefront),
|
|
294
|
+
};
|
|
291
295
|
}
|
|
292
296
|
}
|
|
293
297
|
catch {
|
|
@@ -295,14 +299,31 @@ export class CreateAppCommand extends SwellCommand {
|
|
|
295
299
|
}
|
|
296
300
|
spinner.start(`Creating ${projectType?.name} frontend app (this may take a while)...`);
|
|
297
301
|
try {
|
|
298
|
-
await
|
|
299
|
-
|
|
300
|
-
});
|
|
301
|
-
// Transform install command for the selected package manager
|
|
302
|
-
const installCommand = transformCreateCommand(projectType.installCommand, pkg);
|
|
303
|
-
await execAsync(installCommand, {
|
|
304
|
-
cwd: configPath,
|
|
302
|
+
await fs.mkdir(path.join(configPath, 'frontend'), {
|
|
303
|
+
recursive: true,
|
|
305
304
|
});
|
|
305
|
+
// SWELL_LOCAL_TEMPLATE_PATH overrides the scaffold for local dev — copies
|
|
306
|
+
// the directory at the path into frontend/ instead of running the install
|
|
307
|
+
// command. Used to iterate on the canonical template repo without pushing.
|
|
308
|
+
const localTemplatePath = process.env.SWELL_LOCAL_TEMPLATE_PATH;
|
|
309
|
+
if (localTemplatePath) {
|
|
310
|
+
const source = path.resolve(localTemplatePath);
|
|
311
|
+
const dest = path.join(configPath, 'frontend');
|
|
312
|
+
await fs.cp(source, dest, {
|
|
313
|
+
recursive: true,
|
|
314
|
+
filter: (src) => !src.includes('/node_modules') &&
|
|
315
|
+
!src.endsWith('/.git') &&
|
|
316
|
+
!src.includes('/dist') &&
|
|
317
|
+
!src.includes('/.wrangler'),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
// Transform install command for the selected package manager
|
|
322
|
+
const installCommand = transformCreateCommand(projectType.installCommand, pkg);
|
|
323
|
+
await execAsync(installCommand, {
|
|
324
|
+
cwd: configPath,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
306
327
|
// Use this command to debug output, i.e.e when command becomes non-responsive
|
|
307
328
|
/* await this.execWithStdio(
|
|
308
329
|
configPath,
|
|
@@ -317,7 +338,11 @@ export class CreateAppCommand extends SwellCommand {
|
|
|
317
338
|
.join('\n') || (error.message ?? '').trim();
|
|
318
339
|
if (detail)
|
|
319
340
|
this.log(detail);
|
|
320
|
-
return
|
|
341
|
+
return {
|
|
342
|
+
created: false,
|
|
343
|
+
framework: projectType.slug,
|
|
344
|
+
provisionsStorefront: Boolean(projectType.provisionsStorefront),
|
|
345
|
+
};
|
|
321
346
|
}
|
|
322
347
|
// Ensure frontend package.json has correct name for workspace
|
|
323
348
|
try {
|
|
@@ -346,12 +371,34 @@ export class CreateAppCommand extends SwellCommand {
|
|
|
346
371
|
if (directCreate) {
|
|
347
372
|
this.log();
|
|
348
373
|
}
|
|
349
|
-
return
|
|
374
|
+
return {
|
|
375
|
+
created: true,
|
|
376
|
+
framework: projectType.slug,
|
|
377
|
+
provisionsStorefront: Boolean(projectType.provisionsStorefront),
|
|
378
|
+
};
|
|
350
379
|
}
|
|
351
|
-
return
|
|
380
|
+
return {
|
|
381
|
+
created: false,
|
|
382
|
+
framework: null,
|
|
383
|
+
provisionsStorefront: false,
|
|
384
|
+
};
|
|
352
385
|
}
|
|
353
|
-
async createStorefrontApp(swellConfig, flags,
|
|
354
|
-
|
|
386
|
+
async createStorefrontApp(swellConfig, flags, options = {}) {
|
|
387
|
+
const frontend = await this.createFrontendApp(swellConfig, flags, options.directCreate, 'storefront');
|
|
388
|
+
if (!options.provisionResources ||
|
|
389
|
+
!frontend.created ||
|
|
390
|
+
!frontend.provisionsStorefront) {
|
|
391
|
+
return frontend;
|
|
392
|
+
}
|
|
393
|
+
const resources = await ensureStorefrontResources(this.api, {
|
|
394
|
+
description: swellConfig.get('description'),
|
|
395
|
+
name: swellConfig.get('name'),
|
|
396
|
+
privateId: swellConfig.get('id'),
|
|
397
|
+
type: 'storefront',
|
|
398
|
+
version: swellConfig.get('version'),
|
|
399
|
+
});
|
|
400
|
+
this.log(`Storefront ${style.appConfigValue(resources.storefront.id)} created for app ${style.appConfigValue(resources.app.id)}.`);
|
|
401
|
+
return { ...frontend, resources };
|
|
355
402
|
}
|
|
356
403
|
async createThemeApp(config, flags, installedStorefrontApp) {
|
|
357
404
|
const spinner = ora();
|
|
@@ -369,16 +416,14 @@ export class CreateAppCommand extends SwellCommand {
|
|
|
369
416
|
this.log();
|
|
370
417
|
spinner.start(`Creating theme template...`);
|
|
371
418
|
try {
|
|
372
|
-
await
|
|
373
|
-
cwd: configPath,
|
|
374
|
-
});
|
|
419
|
+
await fs.mkdir(path.join(configPath, 'theme'), { recursive: true });
|
|
375
420
|
for (const themeConfig of defaultThemeConfigs.results) {
|
|
376
421
|
const filePath = themeConfig.file_path.replace(/^frontend\/theme-template\//, '');
|
|
377
422
|
const fileContent = themeConfig.file_data;
|
|
378
423
|
const isJson = filePath.endsWith('.json');
|
|
379
424
|
// eslint-disable-next-line no-await-in-loop
|
|
380
|
-
await
|
|
381
|
-
|
|
425
|
+
await fs.mkdir(path.join(configPath, path.dirname(filePath)), {
|
|
426
|
+
recursive: true,
|
|
382
427
|
});
|
|
383
428
|
// eslint-disable-next-line no-await-in-loop
|
|
384
429
|
await (isJson
|
|
@@ -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
|
+
}
|
package/dist/lib/apps/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/// <reference types="node" resolution-mode="require"/>
|
|
3
3
|
import { AppConfig } from './app-config.js';
|
|
4
4
|
export { AppConfig, FunctionProcessingError, IgnoringFileError, } from './app-config.js';
|
|
5
|
-
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, } from './paths.js';
|
|
5
|
+
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, toPosixPath, } from './paths.js';
|
|
6
6
|
export declare const PUSH_CONCURRENCY = 3;
|
|
7
7
|
/**
|
|
8
8
|
* An app as defined by the Swell API. This is different than an app
|
|
@@ -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";
|
package/dist/lib/apps/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import * as path from 'node:path';
|
|
|
5
5
|
import { detectPackageManager, transformCommand } from '../package-manager.js';
|
|
6
6
|
import { AppConfig } from './app-config.js';
|
|
7
7
|
export { AppConfig, FunctionProcessingError, IgnoringFileError, } from './app-config.js';
|
|
8
|
-
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, } from './paths.js';
|
|
8
|
+
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, toPosixPath, } from './paths.js';
|
|
9
9
|
export const PUSH_CONCURRENCY = 3;
|
|
10
10
|
export var SwellJsonFields;
|
|
11
11
|
(function (SwellJsonFields) {
|
|
@@ -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
|
{
|
package/dist/lib/apps/paths.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type GlobbyFilterFunction } from 'globby';
|
|
2
2
|
import { ConfigType } from './index.js';
|
|
3
|
+
export declare function toPosixPath(inputPath: string): string;
|
|
3
4
|
export declare function globAllFilesByPath(appPath: string, dirPath?: string): Promise<string[]>;
|
|
4
5
|
export declare function getGlobIgnorePathsChecker(appPath: string): Promise<GlobbyFilterFunction>;
|
|
5
6
|
export declare function allConfigDirsPaths(appPath: string): Generator<{
|
package/dist/lib/apps/paths.js
CHANGED
|
@@ -27,11 +27,15 @@ function globOptions(appPath, options) {
|
|
|
27
27
|
],
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
+
// use forward slashes to support Windows
|
|
31
|
+
export function toPosixPath(inputPath) {
|
|
32
|
+
return inputPath.split(path.sep).join('/');
|
|
33
|
+
}
|
|
30
34
|
function globFilesSync(pattern, appPath, dirPath = '.', options = {}) {
|
|
31
|
-
return globbySync(`${dirPath}
|
|
35
|
+
return globbySync(`${toPosixPath(dirPath)}/${pattern}`, globOptions(appPath, options));
|
|
32
36
|
}
|
|
33
37
|
function globFiles(pattern, appPath, dirPath = '.', options = {}) {
|
|
34
|
-
return globby(`${dirPath}
|
|
38
|
+
return globby(`${toPosixPath(dirPath)}/${pattern}`, globOptions(appPath, options));
|
|
35
39
|
}
|
|
36
40
|
export function globAllFilesByPath(appPath, dirPath) {
|
|
37
41
|
return globFiles('**', appPath, dirPath);
|
|
@@ -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
|
+
}
|
package/dist/push-app-command.js
CHANGED
|
@@ -6,7 +6,7 @@ import * as path from 'node:path';
|
|
|
6
6
|
import Stream from 'node:stream';
|
|
7
7
|
import ora from 'ora';
|
|
8
8
|
import { default as swellConfig } from './lib/app-config.js';
|
|
9
|
-
import { ConfigType, getFrontendProjectValidValues, allConfigFilesInDir, CUSTOM_FRAMEWORK_SLUG, appConfigFromFile, filePathExistsAsync, findAppConfig, getConfigTypeFromPath, getConfigTypeKeyFromValue, getFrontendProjectType, getProjectCommands, globAllFilesByPath, hashString, isPathDirectory, } from './lib/apps/index.js';
|
|
9
|
+
import { ConfigType, getFrontendProjectValidValues, allConfigFilesInDir, CUSTOM_FRAMEWORK_SLUG, appConfigFromFile, filePathExistsAsync, findAppConfig, getConfigTypeFromPath, getConfigTypeKeyFromValue, getFrontendProjectType, getProjectCommands, globAllFilesByPath, hashString, isPathDirectory, toPosixPath, } from './lib/apps/index.js';
|
|
10
10
|
import { getGlobIgnorePathsChecker } from './lib/apps/paths.js';
|
|
11
11
|
import { slugFromApp } from './lib/apps/slug.js';
|
|
12
12
|
import { default as localConfig } from './lib/config.js';
|
|
@@ -32,14 +32,12 @@ export class PushAppCommand extends RemoteAppCommand {
|
|
|
32
32
|
if (!filename) {
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
const configFile = toPosixPath(filename);
|
|
36
|
+
if (this.watchingIgnoreFilter && this.watchingIgnoreFilter(configFile)) {
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
|
-
const configFile = filename;
|
|
39
|
-
const pathParsed = path.parse(configFile);
|
|
40
|
-
const fileDirs = pathParsed.dir.split(path.sep);
|
|
41
39
|
// only the first directory is relevant for us
|
|
42
|
-
const configDir =
|
|
40
|
+
const configDir = configFile.split('/')[0];
|
|
43
41
|
// we only want to watch files in the root of the app directory
|
|
44
42
|
// and ignore build files etc
|
|
45
43
|
// TODO: renaming a folder doesn't seem to work
|
|
@@ -433,7 +431,7 @@ export class PushAppCommand extends RemoteAppCommand {
|
|
|
433
431
|
async getFrontendDeploymentHash() {
|
|
434
432
|
const localConfigs = await this.getLocalAppConfigs();
|
|
435
433
|
let frontendHashes = localConfigs
|
|
436
|
-
.filter((config) => config.filePath?.startsWith(
|
|
434
|
+
.filter((config) => config.filePath?.startsWith('frontend/'))
|
|
437
435
|
.map((config) => config.hash)
|
|
438
436
|
.sort()
|
|
439
437
|
.join('|');
|
|
@@ -675,16 +673,18 @@ export class PushAppCommand extends RemoteAppCommand {
|
|
|
675
673
|
this.log(`View your storefront at ${style.link(this.storefrontFrontendUrl(currentStore, storefront, branchId))}.`);
|
|
676
674
|
}
|
|
677
675
|
async pushFile(relativePath) {
|
|
678
|
-
const
|
|
676
|
+
const relativePathPosix = toPosixPath(relativePath);
|
|
677
|
+
const basePath = relativePathPosix.split('/')[0];
|
|
679
678
|
const configType = getConfigTypeFromPath(basePath) || ConfigType.FILE;
|
|
680
|
-
const config = await appConfigFromFile(
|
|
679
|
+
const config = await appConfigFromFile(relativePathPosix, configType, this.appPath);
|
|
681
680
|
await this.pushRemoteFile(config);
|
|
682
681
|
}
|
|
683
682
|
async pushFilePath(relativePath, force) {
|
|
684
683
|
const topDir = relativePath.split(path.sep)[0];
|
|
685
684
|
const configType = getConfigTypeFromPath(topDir) || ConfigType.FILE;
|
|
686
685
|
const configTypeKey = getConfigTypeKeyFromValue(configType) || ConfigType.FILE;
|
|
687
|
-
const
|
|
686
|
+
const relativePathPosix = toPosixPath(relativePath);
|
|
687
|
+
const exAppConfigs = (this.app?.configs || []).filter((config) => config.filePath?.startsWith(`${relativePathPosix}/`));
|
|
688
688
|
const promises = [];
|
|
689
689
|
for (const { configFile } of allConfigFilesInDir(this.appPath, relativePath, configTypeKey)) {
|
|
690
690
|
promises.push(appConfigFromFile(configFile, configType, this.appPath));
|
package/oclif.manifest.json
CHANGED
|
@@ -708,6 +708,7 @@
|
|
|
708
708
|
"pluginType": "core",
|
|
709
709
|
"strict": true,
|
|
710
710
|
"enableJsonFlag": false,
|
|
711
|
+
"requiresSwellConfig": true,
|
|
711
712
|
"delayOrientation": false,
|
|
712
713
|
"orientation": {
|
|
713
714
|
"env": "test"
|
|
@@ -779,6 +780,13 @@
|
|
|
779
780
|
"allowNo": false,
|
|
780
781
|
"type": "boolean"
|
|
781
782
|
},
|
|
783
|
+
"json-events": {
|
|
784
|
+
"description": "emit machine-readable dev server lifecycle events",
|
|
785
|
+
"hidden": true,
|
|
786
|
+
"name": "json-events",
|
|
787
|
+
"allowNo": false,
|
|
788
|
+
"type": "boolean"
|
|
789
|
+
},
|
|
782
790
|
"yes": {
|
|
783
791
|
"char": "y",
|
|
784
792
|
"description": "skip prompts (non-interactive mode)",
|
|
@@ -844,6 +852,7 @@
|
|
|
844
852
|
"strict": true,
|
|
845
853
|
"summary": "Show information about your Swell app.",
|
|
846
854
|
"enableJsonFlag": false,
|
|
855
|
+
"requiresSwellConfig": true,
|
|
847
856
|
"delayOrientation": false,
|
|
848
857
|
"isESM": true,
|
|
849
858
|
"relativePath": [
|
|
@@ -976,6 +985,12 @@
|
|
|
976
985
|
"hasDynamicHelp": false,
|
|
977
986
|
"multiple": false,
|
|
978
987
|
"type": "option"
|
|
988
|
+
},
|
|
989
|
+
"json": {
|
|
990
|
+
"description": "Output the command result as JSON",
|
|
991
|
+
"name": "json",
|
|
992
|
+
"allowNo": false,
|
|
993
|
+
"type": "boolean"
|
|
979
994
|
}
|
|
980
995
|
},
|
|
981
996
|
"hasDynamicHelp": false,
|
|
@@ -1088,6 +1103,7 @@
|
|
|
1088
1103
|
"strict": true,
|
|
1089
1104
|
"summary": "Install an existing app in another store environment.",
|
|
1090
1105
|
"enableJsonFlag": false,
|
|
1106
|
+
"requiresSwellConfig": true,
|
|
1091
1107
|
"delayOrientation": false,
|
|
1092
1108
|
"orientation": {
|
|
1093
1109
|
"env": "test"
|
|
@@ -1144,6 +1160,7 @@
|
|
|
1144
1160
|
"pluginType": "core",
|
|
1145
1161
|
"strict": true,
|
|
1146
1162
|
"summary": "Pull app files from Swell to your local machine.",
|
|
1163
|
+
"requiresSwellConfig": false,
|
|
1147
1164
|
"orientation": {
|
|
1148
1165
|
"env": "test"
|
|
1149
1166
|
},
|
|
@@ -1536,6 +1553,12 @@
|
|
|
1536
1553
|
"hasDynamicHelp": false,
|
|
1537
1554
|
"multiple": false,
|
|
1538
1555
|
"type": "option"
|
|
1556
|
+
},
|
|
1557
|
+
"json": {
|
|
1558
|
+
"description": "Output the command result as JSON",
|
|
1559
|
+
"name": "json",
|
|
1560
|
+
"allowNo": false,
|
|
1561
|
+
"type": "boolean"
|
|
1539
1562
|
}
|
|
1540
1563
|
},
|
|
1541
1564
|
"hasDynamicHelp": false,
|
|
@@ -2279,6 +2302,7 @@
|
|
|
2279
2302
|
"strict": true,
|
|
2280
2303
|
"summary": "Create tests scaffolding for your Swell app.",
|
|
2281
2304
|
"enableJsonFlag": false,
|
|
2305
|
+
"requiresSwellConfig": true,
|
|
2282
2306
|
"helpMeta": {
|
|
2283
2307
|
"usageDirect": "[-y]"
|
|
2284
2308
|
},
|
|
@@ -3215,6 +3239,12 @@
|
|
|
3215
3239
|
"hasDynamicHelp": false,
|
|
3216
3240
|
"multiple": false,
|
|
3217
3241
|
"type": "option"
|
|
3242
|
+
},
|
|
3243
|
+
"json": {
|
|
3244
|
+
"description": "Output the command result as JSON",
|
|
3245
|
+
"name": "json",
|
|
3246
|
+
"allowNo": false,
|
|
3247
|
+
"type": "boolean"
|
|
3218
3248
|
}
|
|
3219
3249
|
},
|
|
3220
3250
|
"hasDynamicHelp": false,
|
|
@@ -3301,6 +3331,7 @@
|
|
|
3301
3331
|
"pluginName": "@swell/cli",
|
|
3302
3332
|
"pluginType": "core",
|
|
3303
3333
|
"summary": "Pull theme files from Swell to your local machine.",
|
|
3334
|
+
"requiresSwellConfig": false,
|
|
3304
3335
|
"orientation": {
|
|
3305
3336
|
"env": "test"
|
|
3306
3337
|
},
|
|
@@ -3514,6 +3545,13 @@
|
|
|
3514
3545
|
"allowNo": false,
|
|
3515
3546
|
"type": "boolean"
|
|
3516
3547
|
},
|
|
3548
|
+
"json-events": {
|
|
3549
|
+
"description": "emit machine-readable dev server lifecycle events",
|
|
3550
|
+
"hidden": true,
|
|
3551
|
+
"name": "json-events",
|
|
3552
|
+
"allowNo": false,
|
|
3553
|
+
"type": "boolean"
|
|
3554
|
+
},
|
|
3517
3555
|
"yes": {
|
|
3518
3556
|
"char": "y",
|
|
3519
3557
|
"description": "skip prompts (non-interactive mode)",
|
|
@@ -3556,5 +3594,5 @@
|
|
|
3556
3594
|
]
|
|
3557
3595
|
}
|
|
3558
3596
|
},
|
|
3559
|
-
"version": "2.9.
|
|
3597
|
+
"version": "2.9.8"
|
|
3560
3598
|
}
|