@swell/cli 2.9.8 → 2.9.9
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/commands/app/push.js +2 -1
- package/dist/commands/app/release.d.ts +0 -1
- package/dist/commands/app/release.js +16 -18
- package/dist/lib/app-config.js +3 -0
- package/dist/lib/apps/index.d.ts +18 -0
- package/dist/lib/apps/index.js +3 -0
- package/dist/push-app-command.d.ts +1 -1
- package/dist/push-app-command.js +3 -3
- package/dist/remote-app-command.d.ts +1 -1
- package/dist/remote-app-command.js +4 -1
- package/oclif.manifest.json +3 -3
- package/package.json +1 -1
|
@@ -17,7 +17,8 @@ type to an app in your store's test environment.
|
|
|
17
17
|
If the app does not exist, it will be created and its global ID saved to a .swellrc file.
|
|
18
18
|
|
|
19
19
|
- If no file is specified, all configuration files will be pushed to the store.
|
|
20
|
-
This includes the app icon (assets/icon.png)
|
|
20
|
+
This includes the app icon (assets/icon.png), cover image (assets/image.png),
|
|
21
|
+
and swell.json.
|
|
21
22
|
- If a file is specified, only that file will be pushed to the store.
|
|
22
23
|
- If a directory is specified, only files in that directory will be pushed.
|
|
23
24
|
|
|
@@ -53,7 +53,7 @@ The app must be connected to a partner account with access to publish.`;
|
|
|
53
53
|
}),
|
|
54
54
|
yes: Flags.boolean({
|
|
55
55
|
char: 'y',
|
|
56
|
-
description: 'skip confirmation
|
|
56
|
+
description: 'skip confirmation prompts, including unstaging another staged version',
|
|
57
57
|
}),
|
|
58
58
|
};
|
|
59
59
|
static orientation = {
|
|
@@ -82,6 +82,20 @@ The app must be connected to a partner account with access to publish.`;
|
|
|
82
82
|
if (appVersion.released && !amend) {
|
|
83
83
|
throw new Error(`Version ${appVersion.version} has already been released. Use --amend to update version details.`);
|
|
84
84
|
}
|
|
85
|
+
const stagedVersion = this.app.staged_props?.version;
|
|
86
|
+
const hasOtherStagedVersion = !amend && stagedVersion && stagedVersion !== appVersion.version;
|
|
87
|
+
if (hasOtherStagedVersion) {
|
|
88
|
+
this.log(style.funcWarn(`Version ${stagedVersion} is currently staged. Releasing version ${appVersion.version} will unstage it.`));
|
|
89
|
+
if (!yes) {
|
|
90
|
+
const continueUnstage = await confirm({
|
|
91
|
+
default: false,
|
|
92
|
+
message: `Continue?`,
|
|
93
|
+
});
|
|
94
|
+
if (!continueUnstage) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
85
99
|
const releaseData = {
|
|
86
100
|
description: message || appVersion.description,
|
|
87
101
|
release_notes: releaseNotesFile ? releaseNotes : appVersion.release_notes,
|
|
@@ -108,22 +122,6 @@ The app must be connected to a partner account with access to publish.`;
|
|
|
108
122
|
}, spinner);
|
|
109
123
|
spinner.succeed(`${style.appConfigValue(this.app.name)} release ${appVersion.version} ${amend ? 'updated' : 'released'}.`);
|
|
110
124
|
}
|
|
111
|
-
validateReleaseDetails() {
|
|
112
|
-
if (!this.app.description) {
|
|
113
|
-
throw new Error('App must have a description');
|
|
114
|
-
}
|
|
115
|
-
const requiresPreviewImages = this.app.type === 'storefront' &&
|
|
116
|
-
(!this.app.kind || this.app.kind === 'shop') &&
|
|
117
|
-
this.app.storefront?.theme.provider !== 'app';
|
|
118
|
-
if (requiresPreviewImages) {
|
|
119
|
-
if (!this.app.preview_image) {
|
|
120
|
-
throw new Error('Storefront app must have a preview image to release');
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else if (this.app.type !== 'theme' && !this.app.logo_icon) {
|
|
124
|
-
throw new Error('App must have a logo icon to release');
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
125
|
async validateCreateVersion(inputVersion, flags) {
|
|
128
126
|
let version = inputVersion;
|
|
129
127
|
if (!version) {
|
|
@@ -132,7 +130,7 @@ The app must be connected to a partner account with access to publish.`;
|
|
|
132
130
|
throw new Error('No version specified');
|
|
133
131
|
}
|
|
134
132
|
}
|
|
135
|
-
|
|
133
|
+
// Mandatory app details are validated server-side when the version is released.
|
|
136
134
|
let appVersion = await this.getVersion(version);
|
|
137
135
|
if (!appVersion) {
|
|
138
136
|
if (flags.amend) {
|
package/dist/lib/app-config.js
CHANGED
|
@@ -12,6 +12,9 @@ const schema = {
|
|
|
12
12
|
integrations: { type: 'array' },
|
|
13
13
|
name: { type: 'string' },
|
|
14
14
|
permissions: { type: 'array' },
|
|
15
|
+
price: { type: 'number', minimum: 0 },
|
|
16
|
+
price_external: { type: 'boolean' },
|
|
17
|
+
price_interval: { type: 'string', enum: ['once', 'monthly'] },
|
|
15
18
|
storefront: { type: 'object' },
|
|
16
19
|
theme: { type: 'object' },
|
|
17
20
|
type: { type: 'string' },
|
package/dist/lib/apps/index.d.ts
CHANGED
|
@@ -16,9 +16,12 @@ export interface App {
|
|
|
16
16
|
[key: string]: string;
|
|
17
17
|
};
|
|
18
18
|
configs?: AppConfig[];
|
|
19
|
+
cover_image?: unknown;
|
|
19
20
|
date_created?: string;
|
|
20
21
|
date_updated?: string;
|
|
22
|
+
demo_url?: string;
|
|
21
23
|
description?: string;
|
|
24
|
+
documentation_url?: string;
|
|
22
25
|
extensions?: any[];
|
|
23
26
|
features?: string[];
|
|
24
27
|
frontend?: {
|
|
@@ -29,6 +32,7 @@ export interface App {
|
|
|
29
32
|
service?: string;
|
|
30
33
|
url?: string;
|
|
31
34
|
};
|
|
35
|
+
full_description?: string;
|
|
32
36
|
highlights?: Array<{
|
|
33
37
|
id: string;
|
|
34
38
|
image_src?: unknown;
|
|
@@ -45,10 +49,19 @@ export interface App {
|
|
|
45
49
|
owned?: boolean;
|
|
46
50
|
preview_image?: unknown;
|
|
47
51
|
preview_mobile_image?: unknown;
|
|
52
|
+
price?: number;
|
|
53
|
+
price_external?: boolean;
|
|
54
|
+
price_interval?: 'once' | 'monthly';
|
|
55
|
+
preview_video_url?: string;
|
|
48
56
|
private_id?: string;
|
|
49
57
|
public_id?: string;
|
|
50
58
|
published?: boolean;
|
|
51
59
|
purchase_options?: string[];
|
|
60
|
+
repository_url?: string;
|
|
61
|
+
staged_props?: {
|
|
62
|
+
[key: string]: any;
|
|
63
|
+
version?: string;
|
|
64
|
+
};
|
|
52
65
|
storefront?: {
|
|
53
66
|
[key: string]: any;
|
|
54
67
|
};
|
|
@@ -60,6 +73,8 @@ export interface App {
|
|
|
60
73
|
preview_image?: unknown;
|
|
61
74
|
preview_mobile_image?: unknown;
|
|
62
75
|
}>;
|
|
76
|
+
support_email?: string;
|
|
77
|
+
support_url?: string;
|
|
63
78
|
theme?: {
|
|
64
79
|
[key: string]: any;
|
|
65
80
|
};
|
|
@@ -74,6 +89,9 @@ export declare enum SwellJsonFields {
|
|
|
74
89
|
KIND = "kind",
|
|
75
90
|
NAME = "name",
|
|
76
91
|
PERMISSIONS = "permissions",
|
|
92
|
+
PRICE = "price",
|
|
93
|
+
PRICE_EXTERNAL = "price_external",
|
|
94
|
+
PRICE_INTERVAL = "price_interval",
|
|
77
95
|
STOREFRONT = "storefront",
|
|
78
96
|
THEME = "theme",
|
|
79
97
|
TYPE = "type",
|
package/dist/lib/apps/index.js
CHANGED
|
@@ -15,6 +15,9 @@ export var SwellJsonFields;
|
|
|
15
15
|
SwellJsonFields["KIND"] = "kind";
|
|
16
16
|
SwellJsonFields["NAME"] = "name";
|
|
17
17
|
SwellJsonFields["PERMISSIONS"] = "permissions";
|
|
18
|
+
SwellJsonFields["PRICE"] = "price";
|
|
19
|
+
SwellJsonFields["PRICE_EXTERNAL"] = "price_external";
|
|
20
|
+
SwellJsonFields["PRICE_INTERVAL"] = "price_interval";
|
|
18
21
|
SwellJsonFields["STOREFRONT"] = "storefront";
|
|
19
22
|
SwellJsonFields["THEME"] = "theme";
|
|
20
23
|
SwellJsonFields["TYPE"] = "type";
|
|
@@ -26,7 +26,7 @@ export declare abstract class PushAppCommand extends RemoteAppCommand {
|
|
|
26
26
|
createAppStorefront(hasOtherStorefronts?: boolean, nonInteractive?: boolean): Promise<any>;
|
|
27
27
|
deployAppFrontend(force?: boolean, log?: boolean): Promise<void>;
|
|
28
28
|
deployFrontend(projectType: FrontendProjectType): Promise<string>;
|
|
29
|
-
ensureAppExists(file?: string, shouldCreate?: boolean): Promise<boolean>;
|
|
29
|
+
ensureAppExists(file?: string, shouldCreate?: boolean, force?: boolean): Promise<boolean>;
|
|
30
30
|
ensureLoggedIn(): Promise<void>;
|
|
31
31
|
exec(command: string, cwd?: string, onOutput?: (string: string) => any | false): Promise<void>;
|
|
32
32
|
execFrontend(command: string, onOutput?: (string: string) => any | false): Promise<void>;
|
package/dist/push-app-command.js
CHANGED
|
@@ -282,7 +282,7 @@ export class PushAppCommand extends RemoteAppCommand {
|
|
|
282
282
|
this.error(`Error deploying frontend: ${error.message}`);
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
|
-
async ensureAppExists(file, shouldCreate = true) {
|
|
285
|
+
async ensureAppExists(file, shouldCreate = true, force = false) {
|
|
286
286
|
const klass = this.ctor;
|
|
287
287
|
const currentStore = localConfig.getDefaultStore();
|
|
288
288
|
await this.ensureLoggedIn();
|
|
@@ -311,14 +311,14 @@ export class PushAppCommand extends RemoteAppCommand {
|
|
|
311
311
|
// If app exists but owned by another client, create a new instance
|
|
312
312
|
if (app?.client_id && app.client_id !== currentStore) {
|
|
313
313
|
// Create a new app
|
|
314
|
-
this.app = await this.getCreateUpdateApp();
|
|
314
|
+
this.app = await this.getCreateUpdateApp(undefined, force);
|
|
315
315
|
if (!this.app) {
|
|
316
316
|
return false;
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
else if (!file) {
|
|
320
320
|
// Update existing app if not targeting a file
|
|
321
|
-
this.app = await this.getCreateUpdateApp(app);
|
|
321
|
+
this.app = await this.getCreateUpdateApp(app, force);
|
|
322
322
|
}
|
|
323
323
|
return true;
|
|
324
324
|
}
|
|
@@ -24,7 +24,7 @@ export declare abstract class RemoteAppCommand extends AppCommand {
|
|
|
24
24
|
protected getApp(id?: string): Promise<App>;
|
|
25
25
|
protected getAppWithConfig(id?: string): Promise<App>;
|
|
26
26
|
getConfigData(configId: string): Promise<any>;
|
|
27
|
-
protected getCreateUpdateApp(updateApp?: App | null): Promise<App>;
|
|
27
|
+
protected getCreateUpdateApp(updateApp?: App | null, force?: boolean): Promise<App>;
|
|
28
28
|
protected getInstalledApp(): Promise<any>;
|
|
29
29
|
protected getLocalAppConfigs(): Promise<AppConfig[]>;
|
|
30
30
|
protected getVersion(version?: null | string | undefined): Promise<AppVersion>;
|
|
@@ -172,7 +172,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
172
172
|
adminPath: `/apps/${this.app.id}/configs/${configId}/data`,
|
|
173
173
|
}, { query: { ...(themeId ? { theme_id: themeId } : undefined) } });
|
|
174
174
|
}
|
|
175
|
-
async getCreateUpdateApp(updateApp) {
|
|
175
|
+
async getCreateUpdateApp(updateApp, force = false) {
|
|
176
176
|
const spinner = ora();
|
|
177
177
|
let sourceApp;
|
|
178
178
|
try {
|
|
@@ -195,6 +195,9 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
195
195
|
? { private_id: this.swellConfig.store.id }
|
|
196
196
|
: undefined),
|
|
197
197
|
...(sourceApp?.id ? { source_id: sourceApp.id } : undefined),
|
|
198
|
+
// Overwrite name/description/logo_icon on the server
|
|
199
|
+
// instead of only filling them in when empty
|
|
200
|
+
...(force ? { $force_meta: true } : undefined),
|
|
198
201
|
};
|
|
199
202
|
const appLabel = this.app.type === 'theme' ? 'theme' : 'app';
|
|
200
203
|
let app = updateApp || {};
|
package/oclif.manifest.json
CHANGED
|
@@ -1180,7 +1180,7 @@
|
|
|
1180
1180
|
"name": "file"
|
|
1181
1181
|
}
|
|
1182
1182
|
},
|
|
1183
|
-
"description": "Push all app files, a specific file, or a specific configuration\ntype to an app in your store's test environment.\n\nIf the app does not exist, it will be created and its global ID saved to a .swellrc file.\n\n- If no file is specified, all configuration files will be pushed to the store.\n This includes the app icon (assets/icon.png) and swell.json.\n- If a file is specified, only that file will be pushed to the store.\n- If a directory is specified, only files in that directory will be pushed.\n\nApp file directories:\nassets/\ncontent/\nfrontend/\ncomponents/\nfunctions/\nmodels/\nnotifications/\nsettings/\ntheme/\nwebhooks/",
|
|
1183
|
+
"description": "Push all app files, a specific file, or a specific configuration\ntype to an app in your store's test environment.\n\nIf the app does not exist, it will be created and its global ID saved to a .swellrc file.\n\n- If no file is specified, all configuration files will be pushed to the store.\n This includes the app icon (assets/icon.png), cover image (assets/image.png),\n and swell.json.\n- If a file is specified, only that file will be pushed to the store.\n- If a directory is specified, only files in that directory will be pushed.\n\nApp file directories:\nassets/\ncontent/\nfrontend/\ncomponents/\nfunctions/\nmodels/\nnotifications/\nsettings/\ntheme/\nwebhooks/",
|
|
1184
1184
|
"examples": [
|
|
1185
1185
|
"swell app push",
|
|
1186
1186
|
"swell app push content",
|
|
@@ -1285,7 +1285,7 @@
|
|
|
1285
1285
|
},
|
|
1286
1286
|
"yes": {
|
|
1287
1287
|
"char": "y",
|
|
1288
|
-
"description": "skip confirmation
|
|
1288
|
+
"description": "skip confirmation prompts, including unstaging another staged version",
|
|
1289
1289
|
"name": "yes",
|
|
1290
1290
|
"allowNo": false,
|
|
1291
1291
|
"type": "boolean"
|
|
@@ -3594,5 +3594,5 @@
|
|
|
3594
3594
|
]
|
|
3595
3595
|
}
|
|
3596
3596
|
},
|
|
3597
|
-
"version": "2.9.
|
|
3597
|
+
"version": "2.9.9"
|
|
3598
3598
|
}
|