@swell/cli 2.0.1-alpha.16 → 2.0.1-alpha.17
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 -1
- package/dist/app-command.js +8 -8
- package/dist/commands/app/dev.d.ts +18 -0
- package/dist/commands/app/dev.js +31 -0
- package/dist/commands/app/frontend/deploy.d.ts +17 -0
- package/dist/commands/app/frontend/deploy.js +44 -0
- package/dist/commands/app/frontend/dev.d.ts +21 -0
- package/dist/commands/app/frontend/dev.js +111 -0
- package/dist/commands/app/info.js +15 -8
- package/dist/commands/app/init.d.ts +12 -0
- package/dist/commands/app/init.js +34 -0
- package/dist/commands/app/install.d.ts +0 -3
- package/dist/commands/app/install.js +12 -20
- package/dist/commands/app/pull.d.ts +15 -0
- package/dist/commands/app/pull.js +50 -0
- package/dist/commands/app/push.d.ts +10 -13
- package/dist/commands/app/push.js +64 -135
- package/dist/commands/app/release.d.ts +13 -0
- package/dist/commands/app/release.js +150 -0
- package/dist/commands/app/version.d.ts +7 -6
- package/dist/commands/app/version.js +61 -40
- package/dist/commands/app/watch.d.ts +2 -4
- package/dist/commands/app/watch.js +3 -83
- package/dist/commands/create/app.d.ts +35 -11
- package/dist/commands/create/app.js +141 -138
- package/dist/commands/create/frontend.d.ts +12 -0
- package/dist/commands/create/frontend.js +41 -0
- package/dist/commands/create/function.d.ts +2 -2
- package/dist/commands/create/function.js +2 -2
- package/dist/commands/create/notification.d.ts +2 -2
- package/dist/commands/create/notification.js +2 -2
- package/dist/commands/login.js +6 -4
- package/dist/commands/logs.js +0 -1
- package/dist/commands/theme/dev.d.ts +23 -0
- package/dist/commands/theme/dev.js +167 -0
- package/dist/commands/theme/init.d.ts +9 -0
- package/dist/commands/theme/init.js +15 -0
- package/dist/commands/theme/pull.d.ts +20 -0
- package/dist/commands/theme/pull.js +65 -0
- package/dist/commands/theme/push.d.ts +19 -0
- package/dist/commands/theme/push.js +92 -0
- package/dist/create-app-command.d.ts +20 -0
- package/dist/create-app-command.js +254 -0
- package/dist/create-collection-command.d.ts +3 -3
- package/dist/create-collection-command.js +4 -4
- package/dist/{create-command.d.ts → create-config-command.d.ts} +1 -1
- package/dist/{create-command.js → create-config-command.js} +3 -3
- package/dist/lib/api.d.ts +3 -2
- package/dist/lib/api.js +47 -21
- package/dist/lib/app-config.d.ts +12 -5
- package/dist/lib/app-config.js +59 -24
- package/dist/lib/apps/app-config.d.ts +22 -8
- package/dist/lib/apps/app-config.js +202 -68
- package/dist/lib/apps/index.d.ts +93 -13
- package/dist/lib/apps/index.js +150 -50
- package/dist/lib/apps/paths.d.ts +14 -7
- package/dist/lib/apps/paths.js +73 -28
- package/dist/lib/config.d.ts +5 -1
- package/dist/lib/config.js +14 -0
- package/dist/lib/constants.d.ts +5 -0
- package/dist/lib/constants.js +20 -0
- package/dist/lib/create/content.d.ts +1 -1
- package/dist/lib/create/index.js +5 -1
- package/dist/lib/info.js +2 -2
- package/dist/lib/stores.d.ts +1 -1
- package/dist/lib/stores.js +3 -3
- package/dist/lib/style.d.ts +2 -0
- package/dist/lib/style.js +2 -0
- package/dist/push-app-command.d.ts +73 -0
- package/dist/push-app-command.js +765 -0
- package/dist/remote-app-command.d.ts +33 -7
- package/dist/remote-app-command.js +423 -151
- package/oclif.manifest.json +794 -81
- package/package.json +13 -2
- package/dist/commands/app/_pull.d.ts +0 -8
- package/dist/commands/app/_pull.js +0 -45
package/dist/app-command.d.ts
CHANGED
|
@@ -14,7 +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
|
-
|
|
17
|
+
swellConfig: any;
|
|
18
18
|
appPath: string;
|
|
19
19
|
constructor(argv: string[], config: Config);
|
|
20
20
|
init(): Promise<void>;
|
package/dist/app-command.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
1
2
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import { default as
|
|
3
|
+
import { default as swellConfig } from './lib/app-config.js';
|
|
3
4
|
import { SwellCommand } from './swell-command.js';
|
|
4
5
|
/**
|
|
5
6
|
* A base class for Swell CLI commands that do not require an app to be saved
|
|
@@ -16,17 +17,17 @@ export class AppCommand extends SwellCommand {
|
|
|
16
17
|
// needs to be in a ES2021 format: https://github.com/oclif/oclif/issues/1100
|
|
17
18
|
static baseFlags = {
|
|
18
19
|
'app-path': Flags.string({
|
|
19
|
-
description: 'path to
|
|
20
|
+
description: 'path to your app directory',
|
|
20
21
|
}),
|
|
21
22
|
};
|
|
22
23
|
// local app configuration, what developers define
|
|
23
|
-
|
|
24
|
+
swellConfig;
|
|
24
25
|
// the local path to the app directory
|
|
25
26
|
appPath = '';
|
|
26
27
|
constructor(argv, config) {
|
|
27
28
|
super(argv, config);
|
|
28
|
-
this.
|
|
29
|
-
this.appPath = this.
|
|
29
|
+
this.swellConfig = swellConfig();
|
|
30
|
+
this.appPath = path.resolve(this.swellConfig.swDirPath);
|
|
30
31
|
}
|
|
31
32
|
async init() {
|
|
32
33
|
await super.init();
|
|
@@ -38,8 +39,7 @@ export class AppCommand extends SwellCommand {
|
|
|
38
39
|
klass.flags = { ...klass.flags, ...AppCommand.baseFlags };
|
|
39
40
|
const { flags } = await this.parse(klass);
|
|
40
41
|
// if the user passed an app path, use it: reload the app config
|
|
41
|
-
this.
|
|
42
|
-
this.appPath = this.
|
|
43
|
-
this.debug(`config path loaded: ${this.appConfig.path}`);
|
|
42
|
+
this.swellConfig = swellConfig(flags['app-path']);
|
|
43
|
+
this.appPath = path.resolve(this.swellConfig.swDirPath);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Config } from '@oclif/core';
|
|
2
|
+
import { PushAppCommand } from '../../push-app-command.js';
|
|
3
|
+
export default class AppDev extends PushAppCommand {
|
|
4
|
+
static summary: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
'storefront-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
8
|
+
'storefront-select': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
9
|
+
port: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
10
|
+
'no-push': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
static orientation: {
|
|
13
|
+
env: string;
|
|
14
|
+
};
|
|
15
|
+
static delayOrientation: boolean;
|
|
16
|
+
constructor(argv: string[], config: Config);
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { PushAppCommand } from '../../push-app-command.js';
|
|
3
|
+
import AppFrontendDev from './frontend/dev.js';
|
|
4
|
+
export default class AppDev extends PushAppCommand {
|
|
5
|
+
static summary = `Run an app in dev mode from your local machine.`;
|
|
6
|
+
static examples = [
|
|
7
|
+
'swell app dev',
|
|
8
|
+
'swell app dev --storefront-id <id>',
|
|
9
|
+
'swell app dev --port 3000',
|
|
10
|
+
];
|
|
11
|
+
static flags = {
|
|
12
|
+
...AppFrontendDev.flags,
|
|
13
|
+
'storefront-id': Flags.string({
|
|
14
|
+
description: 'for storefront apps, identify a storefront to preview and push theme files to',
|
|
15
|
+
}),
|
|
16
|
+
'storefront-select': Flags.boolean({
|
|
17
|
+
description: 'for storefront apps, prompt to select a storefront to preview',
|
|
18
|
+
default: false,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static orientation = {
|
|
22
|
+
env: 'test',
|
|
23
|
+
};
|
|
24
|
+
static delayOrientation = true;
|
|
25
|
+
constructor(argv, config) {
|
|
26
|
+
super(argv, config);
|
|
27
|
+
}
|
|
28
|
+
async run() {
|
|
29
|
+
await this.config.runCommand('app:frontend:dev', this.argv);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Config } from '@oclif/core';
|
|
2
|
+
import { PushAppCommand } from '../../../push-app-command.js';
|
|
3
|
+
export default class AppFrontendDeploy extends PushAppCommand {
|
|
4
|
+
static summary: string;
|
|
5
|
+
static description: string;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
9
|
+
'storefront-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
10
|
+
'storefront-select': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
static orientation: {
|
|
13
|
+
env: string;
|
|
14
|
+
};
|
|
15
|
+
constructor(argv: string[], config: Config);
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { PushAppCommand } from '../../../push-app-command.js';
|
|
3
|
+
export default class AppFrontendDeploy extends PushAppCommand {
|
|
4
|
+
static summary = `Push frontend files to your Swell app.`;
|
|
5
|
+
static description = `Creates a new build using the relevant command depending on your frontend framework.
|
|
6
|
+
Once the build succeeds, this command will invoke Cloudflare Wrangler to upload
|
|
7
|
+
build assets using your own Cloudflare account. Once complete, Swell will update
|
|
8
|
+
the app's deployment URL and push the updated frontend files.`;
|
|
9
|
+
static examples = [
|
|
10
|
+
'swell app frontend deploy',
|
|
11
|
+
'swell app frontend deploy --force',
|
|
12
|
+
'swell app frontend deploy --storefront-select',
|
|
13
|
+
'swell app frontend deploy --storefront-id <id>',
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
force: Flags.boolean({
|
|
17
|
+
description: 'force push and build all frontend files',
|
|
18
|
+
}),
|
|
19
|
+
'storefront-id': Flags.string({
|
|
20
|
+
description: 'identify a storefront to preview deployment with',
|
|
21
|
+
}),
|
|
22
|
+
'storefront-select': Flags.boolean({
|
|
23
|
+
description: 'prompt to select a storefront to preview deployment with',
|
|
24
|
+
default: false,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
static orientation = {
|
|
28
|
+
env: 'test',
|
|
29
|
+
};
|
|
30
|
+
constructor(argv, config) {
|
|
31
|
+
super(argv, config);
|
|
32
|
+
}
|
|
33
|
+
async run() {
|
|
34
|
+
const { flags } = await this.parse(AppFrontendDeploy);
|
|
35
|
+
const { force } = flags;
|
|
36
|
+
if (!(await this.ensureAppExists())) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (this.app.type === 'storefront') {
|
|
40
|
+
await this.getStorefrontToPush(flags);
|
|
41
|
+
}
|
|
42
|
+
await this.deployAppFrontend(force);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Config } from '@oclif/core';
|
|
2
|
+
import { PushAppCommand } from '../../../push-app-command.js';
|
|
3
|
+
import { FrontendProjectType } from '../../../lib/apps/index.js';
|
|
4
|
+
export default class AppFrontendDev extends PushAppCommand {
|
|
5
|
+
static summary: string;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
port: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
9
|
+
'no-push': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
|
+
'storefront-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
|
+
'storefront-select': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
static orientation: {
|
|
14
|
+
env: string;
|
|
15
|
+
};
|
|
16
|
+
constructor(argv: string[], config: Config);
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
startDevServer(projectType: FrontendProjectType, port?: number): Promise<void>;
|
|
19
|
+
updateLocalProxy(proxyUrl: string, spinner: any, storefrontId?: string): Promise<void>;
|
|
20
|
+
logAppLocalUrl(storeId: string, sessionId: string): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import ngrok from 'ngrok';
|
|
3
|
+
import getPort, { portNumbers } from 'get-port';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import { default as localConfig } from '../../../lib/config.js';
|
|
6
|
+
import { PushAppCommand } from '../../../push-app-command.js';
|
|
7
|
+
import style from '../../../lib/style.js';
|
|
8
|
+
const FALLBACK_PORT = 3000;
|
|
9
|
+
export default class AppFrontendDev extends PushAppCommand {
|
|
10
|
+
static summary = `Run a frontend app in dev mode from your local machine.`;
|
|
11
|
+
static examples = [
|
|
12
|
+
'swell app frontend dev',
|
|
13
|
+
'swell app frontend dev --no-push',
|
|
14
|
+
'swell app frontend dev --port 3000',
|
|
15
|
+
'swell app frontend dev --storefront-select',
|
|
16
|
+
'swell app frontend dev --storefront-id <id>',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
port: Flags.integer({
|
|
20
|
+
char: 'p',
|
|
21
|
+
description: 'override the default port to run the app locally',
|
|
22
|
+
}),
|
|
23
|
+
'no-push': Flags.boolean({
|
|
24
|
+
description: 'skip pushing app files initially',
|
|
25
|
+
}),
|
|
26
|
+
'storefront-id': Flags.string({
|
|
27
|
+
description: 'identify a storefront to preview with and push theme files to',
|
|
28
|
+
}),
|
|
29
|
+
'storefront-select': Flags.boolean({
|
|
30
|
+
description: 'prompt to select a storefront to preview with',
|
|
31
|
+
default: false,
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
34
|
+
static orientation = {
|
|
35
|
+
env: 'test',
|
|
36
|
+
};
|
|
37
|
+
constructor(argv, config) {
|
|
38
|
+
super(argv, config);
|
|
39
|
+
}
|
|
40
|
+
async run() {
|
|
41
|
+
const { flags } = await this.parse(AppFrontendDev);
|
|
42
|
+
const { port } = flags;
|
|
43
|
+
const noPush = flags['no-push'];
|
|
44
|
+
if (!(await this.ensureAppExists(undefined, false))) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!noPush) {
|
|
48
|
+
await this.pushAppConfigs();
|
|
49
|
+
}
|
|
50
|
+
if (this.app.type === 'storefront') {
|
|
51
|
+
await this.getStorefrontToPush(flags);
|
|
52
|
+
this.logStorefrontConnected();
|
|
53
|
+
}
|
|
54
|
+
this.saveCurrentStorefront();
|
|
55
|
+
const projectType = this.getFrontendProjectType();
|
|
56
|
+
await this.startDevServer(projectType, port);
|
|
57
|
+
}
|
|
58
|
+
async startDevServer(projectType, port) {
|
|
59
|
+
const currentStore = localConfig.getDefaultStore();
|
|
60
|
+
const spinner = ora();
|
|
61
|
+
// Find an open port starting at 3000
|
|
62
|
+
const freePort = port ||
|
|
63
|
+
(await getPort({ port: portNumbers(3000, 3100) })) ||
|
|
64
|
+
FALLBACK_PORT;
|
|
65
|
+
this.log(`Starting ${projectType.name} dev server...\n`);
|
|
66
|
+
// Start ngrok proxy
|
|
67
|
+
const proxyUrl = await ngrok.connect({
|
|
68
|
+
addr: freePort,
|
|
69
|
+
region: 'us', // TODO: make it configurable
|
|
70
|
+
});
|
|
71
|
+
await this.updateLocalProxy(proxyUrl, spinner, this.storefront?.id);
|
|
72
|
+
return this.exec(projectType.devCommand.replace('${PORT}', String(freePort)), (string) => {
|
|
73
|
+
// Hide useless astro warning about image optimization
|
|
74
|
+
if (string.includes('The current configuration does not support image optimization')) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
// Hide useless astro warning about .dev.vars
|
|
78
|
+
if (string.includes('There is no `.dev.vars` file')) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
// Hide astro localhost URL/network as it can confuse the user
|
|
82
|
+
if (string.includes('┃ Local') || string.includes('┃ Network')) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
// Started, show app url (TODO for nextjs)
|
|
86
|
+
if (string.includes('watching for file changes')) {
|
|
87
|
+
spinner.succeed(`Started ${projectType.name} dev server on port ${freePort}.\n`);
|
|
88
|
+
const sessionId = localConfig.getSessionId(currentStore);
|
|
89
|
+
setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100);
|
|
90
|
+
this.watchForChanges();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
async updateLocalProxy(proxyUrl, spinner, storefrontId) {
|
|
95
|
+
const storefront = this.app.type === 'storefront' &&
|
|
96
|
+
(await this.getAppStorefront({ storefront_id: storefrontId }));
|
|
97
|
+
await this.handleRequestErrors(async () => this.api.put({ adminPath: `/client/apps/${this.app.id}/local-proxy` }, {
|
|
98
|
+
body: {
|
|
99
|
+
proxy_url: proxyUrl,
|
|
100
|
+
storefront_id: storefront?.id || null,
|
|
101
|
+
storefront_slug: storefront?.slug || null,
|
|
102
|
+
},
|
|
103
|
+
}), () => spinner.fail('Error starting local proxy'));
|
|
104
|
+
}
|
|
105
|
+
logAppLocalUrl(storeId, sessionId) {
|
|
106
|
+
const frontendAppRoute = this.app.type === 'storefront' && this.app.storefront?.external
|
|
107
|
+
? `/${this.app.private_id}`
|
|
108
|
+
: '';
|
|
109
|
+
this.log(`View it at ${style.link(`${this.localFrontendUrl(storeId, sessionId)}${frontendAppRoute}`)}\n`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -13,7 +13,6 @@ const FIELDS_TO_DISPLAY = [
|
|
|
13
13
|
'published',
|
|
14
14
|
'date_created',
|
|
15
15
|
'date_updated',
|
|
16
|
-
'installed',
|
|
17
16
|
'client',
|
|
18
17
|
];
|
|
19
18
|
export default class AppInfo extends RemoteAppCommand {
|
|
@@ -46,25 +45,33 @@ it will output all versions of the app instead.`;
|
|
|
46
45
|
async showAppInfo() {
|
|
47
46
|
const spinner = ora();
|
|
48
47
|
spinner.start('Retrieving app info...');
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
throw error;
|
|
48
|
+
const app = await this.getAppWithConfig().catch((error) => {
|
|
49
|
+
return null;
|
|
52
50
|
});
|
|
51
|
+
this.app = app || this.swellConfig.store;
|
|
52
|
+
if (!this.app) {
|
|
53
|
+
spinner.fail('App not found');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
53
56
|
if (spinner.isSpinning) {
|
|
54
57
|
spinner.stop();
|
|
55
58
|
}
|
|
56
59
|
// we pull versions to make sure that what is displayed is the latest
|
|
57
|
-
const versions = await this.getVersions();
|
|
60
|
+
const versions = app ? await this.getVersions() : [];
|
|
58
61
|
// Output the app field information, e.g.:
|
|
59
62
|
// Name: My App
|
|
60
63
|
const fieldDefinitions = new FieldDefinitions(this.app, versions);
|
|
61
64
|
for (const field of FIELDS_TO_DISPLAY) {
|
|
62
65
|
const fieldDef = fieldDefinitions.getFieldDefinition(field);
|
|
63
|
-
|
|
66
|
+
if (fieldDef.value) {
|
|
67
|
+
this.log(style.appConfigName(`${fieldDef.label}:`), fieldDef.value);
|
|
68
|
+
}
|
|
64
69
|
}
|
|
65
70
|
// dashboard url is built, not part of the app object
|
|
66
71
|
// we display it at the end for better readability and simplicity
|
|
67
|
-
|
|
72
|
+
if (this.app.client_id) {
|
|
73
|
+
this.log(style.appConfigName('Dashboard:'), style.link(this.dashboardUrl({}, this.app.client_id)));
|
|
74
|
+
}
|
|
68
75
|
}
|
|
69
76
|
async showVersions() {
|
|
70
77
|
const spinner = ora();
|
|
@@ -81,7 +88,7 @@ it will output all versions of the app instead.`;
|
|
|
81
88
|
spinner.succeed(`${this.app.name} app versions:\n`);
|
|
82
89
|
const displayData = versions.map((appVersion) => [
|
|
83
90
|
style.appConfigValue(appVersion.version),
|
|
84
|
-
appVersion.
|
|
91
|
+
appVersion.description,
|
|
85
92
|
new Date(appVersion.date_created).toUTCString(),
|
|
86
93
|
]);
|
|
87
94
|
this.log(table(displayData, {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import CreateApp from '../create/app.js';
|
|
2
|
+
export default class InitApp extends CreateApp {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: {
|
|
5
|
+
command: string;
|
|
6
|
+
description: string;
|
|
7
|
+
}[];
|
|
8
|
+
static flags: {
|
|
9
|
+
yes: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import CreateApp from '../create/app.js';
|
|
4
|
+
export default class InitApp extends CreateApp {
|
|
5
|
+
static description = 'Initialize app swell.json in the current directory.';
|
|
6
|
+
static examples = [
|
|
7
|
+
{
|
|
8
|
+
command: 'swell app init',
|
|
9
|
+
description: 'Initialize app following command prompts.',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
command: 'swell app init -y',
|
|
13
|
+
description: 'Initialize app and accept all default values.',
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
yes: Flags.boolean({
|
|
18
|
+
char: 'y',
|
|
19
|
+
description: `accept all default values`,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
async run() {
|
|
23
|
+
const { flags } = await this.parse(InitApp);
|
|
24
|
+
const { yes: confirmYes } = flags;
|
|
25
|
+
const id = process.cwd().split(path.sep).pop() || 'Swell App';
|
|
26
|
+
await this.createSwellConfig({
|
|
27
|
+
inputId: id,
|
|
28
|
+
inputYes: confirmYes,
|
|
29
|
+
inputType: this.appType,
|
|
30
|
+
allowOverwrite: false,
|
|
31
|
+
nestedPath: false,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -13,8 +13,5 @@ export default class AppInstall extends RemoteAppCommand {
|
|
|
13
13
|
static summary: string;
|
|
14
14
|
run(): Promise<void>;
|
|
15
15
|
private confirmRemoveDevelopmentApp;
|
|
16
|
-
private getInstalledApp;
|
|
17
|
-
private installApp;
|
|
18
16
|
private installConfirmationMessage;
|
|
19
|
-
private updateApp;
|
|
20
17
|
}
|
|
@@ -11,9 +11,9 @@ export default class AppInstall extends RemoteAppCommand {
|
|
|
11
11
|
|
|
12
12
|
Without a store specified, install the app in the Live environment of the current store.`;
|
|
13
13
|
static examples = [
|
|
14
|
-
'swell install',
|
|
15
|
-
'swell install -v 3.2.7',
|
|
16
|
-
'swell install -v 1.0.0 -s my-store-id',
|
|
14
|
+
'swell app install',
|
|
15
|
+
'swell app install -v 3.2.7',
|
|
16
|
+
'swell app install -v 1.0.0 -s my-store-id',
|
|
17
17
|
];
|
|
18
18
|
static flags = {
|
|
19
19
|
env: Flags.string({
|
|
@@ -102,21 +102,25 @@ Without a store specified, install the app in the Live environment of the curren
|
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
const spinner = ora();
|
|
105
|
+
this.log();
|
|
105
106
|
// install or update app depending on whether it's already installed
|
|
106
107
|
let request;
|
|
107
108
|
if (existingInstalledApp?.id) {
|
|
108
|
-
spinner.start(`Updating${extraMessage}
|
|
109
|
-
request = async () => this.
|
|
109
|
+
spinner.start(`Updating${extraMessage}`);
|
|
110
|
+
request = async () => this.updateInstalledApp(versionToInstall, spinner);
|
|
110
111
|
}
|
|
111
112
|
else {
|
|
112
|
-
spinner.start(`Installing${extraMessage}
|
|
113
|
-
request = async () => this.installApp(versionToInstall);
|
|
113
|
+
spinner.start(`Installing${extraMessage}`);
|
|
114
|
+
request = async () => this.installApp(versionToInstall, spinner);
|
|
114
115
|
}
|
|
115
116
|
const response = await this.handleRequestErrors(request, () => spinner.fail('Something went wrong.'));
|
|
116
117
|
if (response?.errors) {
|
|
117
118
|
spinner.fail(`Error installing app: ${JSON.stringify(response.errors)}`);
|
|
118
119
|
}
|
|
119
|
-
|
|
120
|
+
else {
|
|
121
|
+
spinner.succeed(`${existingInstalledApp?.id ? 'Update' : 'Install'} complete.\n`);
|
|
122
|
+
this.log(`Manage app settings in your dashboard at ${style.link(this.dashboardUrl({ flags: { env: envToInstall } }, storeToInstall))}.`);
|
|
123
|
+
}
|
|
120
124
|
}
|
|
121
125
|
async confirmRemoveDevelopmentApp(storeToInstall) {
|
|
122
126
|
const existingSourcedApps = await this.api.get({ adminPath: `/client/apps` }, {
|
|
@@ -150,15 +154,6 @@ Without a store specified, install the app in the Live environment of the curren
|
|
|
150
154
|
}
|
|
151
155
|
return true;
|
|
152
156
|
}
|
|
153
|
-
async getInstalledApp() {
|
|
154
|
-
// check if app is already installed on store
|
|
155
|
-
return this.api.get({ adminPath: `/client/apps/${this.app.id}` }, {});
|
|
156
|
-
}
|
|
157
|
-
async installApp(version) {
|
|
158
|
-
return this.api.post({ adminPath: `/client/apps` },
|
|
159
|
-
// eslint-disable-next-line camelcase
|
|
160
|
-
{ body: { app_id: this.app.id, version } });
|
|
161
|
-
}
|
|
162
157
|
installConfirmationMessage(storeToInstall, envToInstall, versionToInstall, existingVersion) {
|
|
163
158
|
const message = [];
|
|
164
159
|
if (existingVersion && semver.gt(versionToInstall, existingVersion)) {
|
|
@@ -176,7 +171,4 @@ Without a store specified, install the app in the Live environment of the curren
|
|
|
176
171
|
message.push(style.appConfigValue(this.app.name), `v${versionToShow}`, `on ${style.storeId(storeToInstall)} [${envToInstall || 'live'}]?`);
|
|
177
172
|
return message.join(' ');
|
|
178
173
|
}
|
|
179
|
-
async updateApp(version) {
|
|
180
|
-
await this.api.put({ adminPath: `/client/apps/${this.app.id}` }, { body: { version } });
|
|
181
|
-
}
|
|
182
174
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PushAppCommand } from '../../push-app-command.js';
|
|
2
|
+
export default class AppPull extends PushAppCommand {
|
|
3
|
+
static args: {
|
|
4
|
+
appId: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
5
|
+
targetPath: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static flags: {
|
|
8
|
+
force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
9
|
+
};
|
|
10
|
+
static summary: string;
|
|
11
|
+
static description: string;
|
|
12
|
+
static examples: string[];
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
logPulledChanges(pulled: string[], removed: string[]): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { ConfigPaths, } from '../../lib/apps/index.js';
|
|
4
|
+
import style from '../../lib/style.js';
|
|
5
|
+
import { PushAppCommand } from '../../push-app-command.js';
|
|
6
|
+
export default class AppPull extends PushAppCommand {
|
|
7
|
+
static args = {
|
|
8
|
+
appId: Args.string({ default: '', description: 'app id to pull' }),
|
|
9
|
+
targetPath: Args.string({
|
|
10
|
+
default: '',
|
|
11
|
+
description: 'path to download app files into',
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
static flags = {
|
|
15
|
+
force: Flags.boolean({
|
|
16
|
+
description: 'force pull all files',
|
|
17
|
+
default: false,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
static summary = 'Pull app files from Swell to your local machine.';
|
|
21
|
+
static description = `Pull all app files, a specific file, or a specific configuration
|
|
22
|
+
type from an app in your store's test environment to your local machine.
|
|
23
|
+
|
|
24
|
+
If APPID is not specified, you will be prompted with a list of apps to choose from.
|
|
25
|
+
|
|
26
|
+
App file directories:
|
|
27
|
+
${Object.values(ConfigPaths)
|
|
28
|
+
.map((dir) => style.path(`${dir}/`))
|
|
29
|
+
.join('\n')}\n${style.path(`frontend/`)}`;
|
|
30
|
+
static examples = [
|
|
31
|
+
'swell app pull',
|
|
32
|
+
'swell app pull example_app',
|
|
33
|
+
'swell app pull example_app example-folder',
|
|
34
|
+
'swell app pull --force',
|
|
35
|
+
];
|
|
36
|
+
async run() {
|
|
37
|
+
const { args, flags } = await this.parse(AppPull);
|
|
38
|
+
const { force } = flags;
|
|
39
|
+
await this.ensureLoggedIn();
|
|
40
|
+
this.app = await this.getAppToPull(args);
|
|
41
|
+
const { pulled, removed } = await this.pullAppConfigs(force);
|
|
42
|
+
this.logPulledChanges(pulled, removed);
|
|
43
|
+
}
|
|
44
|
+
logPulledChanges(pulled, removed) {
|
|
45
|
+
const typeLabel = this.appType === 'theme' ? 'theme' : 'app';
|
|
46
|
+
const changeCount = pulled.length + removed.length;
|
|
47
|
+
const pluralFiles = changeCount !== 1 ? 'files' : 'file';
|
|
48
|
+
this.log(`Pulled ${changeCount} ${pluralFiles} from ${style.appConfigValue(this.app.name)} ${typeLabel} in ${style.path(path.resolve(this.appPath))}.`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class AppPush extends
|
|
1
|
+
import { PushAppCommand } from '../../push-app-command.js';
|
|
2
|
+
export default class AppPush extends PushAppCommand {
|
|
3
3
|
static args: {
|
|
4
4
|
file: import("@oclif/core/lib/interfaces/parser.js").Arg<string | undefined, Record<string, unknown>>;
|
|
5
5
|
};
|
|
6
|
+
static flags: any;
|
|
7
|
+
static orientation: any;
|
|
8
|
+
static summary: string;
|
|
6
9
|
static description: string;
|
|
7
10
|
static examples: string[];
|
|
8
|
-
static
|
|
9
|
-
file: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
10
|
-
};
|
|
11
|
-
static orientation: {
|
|
12
|
-
env: string;
|
|
13
|
-
};
|
|
14
|
-
static summary: string;
|
|
11
|
+
static delayOrientation: boolean;
|
|
15
12
|
run(): Promise<void>;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
resolvePushPaths(file: string): {
|
|
14
|
+
filePath: string;
|
|
15
|
+
relativePath: string;
|
|
16
|
+
};
|
|
20
17
|
}
|