@swell/cli 2.0.1-alpha.0 → 2.0.1-alpha.11
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/README.md +2 -140
- package/dist/commands/app/_pull.js +2 -2
- package/dist/commands/app/info.js +1 -1
- package/dist/commands/app/install.js +3 -1
- package/dist/commands/app/push.d.ts +3 -0
- package/dist/commands/app/push.js +18 -6
- package/dist/commands/logs.d.ts +1 -0
- package/dist/commands/logs.js +5 -0
- package/dist/lib/api.js +11 -2
- package/dist/lib/apps/app-config.js +4 -1
- package/dist/lib/bundle.js +3 -0
- package/dist/lib/constants.js +1 -1
- package/dist/lib/create/index.d.ts +1 -1
- package/dist/lib/create/index.js +5 -3
- package/dist/remote-app-command.js +31 -10
- package/oclif.manifest.json +7 -2
- package/package.json +9 -18
package/README.md
CHANGED
|
@@ -1,141 +1,3 @@
|
|
|
1
|
-
# @swell/cli
|
|
1
|
+
# @swell/cli 2 alpha
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Install with:
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
npm install -g @swell/cli
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
If you are using tools for version managing like [asdf](https://asdf-vm.com/), make sure you [reshim](https://asdf-vm.com/manage/core.html#reshim) after install:
|
|
12
|
-
|
|
13
|
-
```sh
|
|
14
|
-
asdf reshim
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
# Commands
|
|
18
|
-
|
|
19
|
-
## General options
|
|
20
|
-
|
|
21
|
-
Commands tend to support the following helper options:
|
|
22
|
-
|
|
23
|
-
- --quiet (-q): Boolean, quiets the progress indicator and output of intermediary commands
|
|
24
|
-
- --verbose (-v): Boolean, outputs all commands
|
|
25
|
-
- --dry-run: Boolean, dry runs requests that delete data, but doesn't run them
|
|
26
|
-
- --yes (-y): Boolean, answers all confirmation questions with **yes**.
|
|
27
|
-
|
|
28
|
-
## Login
|
|
29
|
-
|
|
30
|
-
The `admin login` command authenticates and stores a user's session locally. Saved sessions can/will be used by other commands, unless a secret key is specified.
|
|
31
|
-
|
|
32
|
-
```sh
|
|
33
|
-
swell login [--username (-u) String] [--password (-p) String] [--set-default Boolean]
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Examples
|
|
37
|
-
|
|
38
|
-
```sh
|
|
39
|
-
swell login
|
|
40
|
-
swell login --set-default
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Storefronts
|
|
44
|
-
|
|
45
|
-
List all storefronts associated to logged in user:
|
|
46
|
-
|
|
47
|
-
```sh
|
|
48
|
-
swell storefronts list
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Retrieves storefront configuration data from the server and writes it to a file if specified or stdout by default. It requires a type to run. Configuration types allowed are "editor", "menus" and "settings":
|
|
52
|
-
```sh
|
|
53
|
-
swell storefronts pull --id String --type (-t) String [--file (-f) String]
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Send storefront configuration data to the server. Configuration types allowed are "editor", "menus" and "settings":
|
|
57
|
-
```sh
|
|
58
|
-
swell storefronts push --id String --type (-t) String [--file (-f) String] [--strategy (-i) String]
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Examples
|
|
62
|
-
|
|
63
|
-
```sh
|
|
64
|
-
swell storefronts pull --id P5OzfzLD -t editor
|
|
65
|
-
swell storefronts pull --id P5OzfzLD -t menus -f menus.json
|
|
66
|
-
swell storefronts push --id P5OzfzLD -t editor -s set -f ../origin-storefront/config/editor.json
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Without logging in
|
|
70
|
-
|
|
71
|
-
```sh
|
|
72
|
-
swell storefronts pull --id P5OzfzLD -t editor --store my-test-store --secret-key my-dev-secret-key
|
|
73
|
-
swell storefronts pull --id P5OzfzLD -t menus -f menus.json --store my-test-store --secret-key my-dev-secret-key
|
|
74
|
-
swell storefronts push --id P5OzfzLD -t editor -s set -f ../origin-storefront/config/editor.json --store my-test-store --secret-key my-dev-secret-key
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Model
|
|
78
|
-
|
|
79
|
-
Push or pull model definitions, including namespaced models (e.g. content models), abstract content models and content fields.
|
|
80
|
-
|
|
81
|
-
```sh
|
|
82
|
-
# pull => retrieves a model from the server and tries to merge and/or write to a specified JSON file or stdout (by default)
|
|
83
|
-
# --content flag toggles between base models and abstract content models or content fields
|
|
84
|
-
swell model pull -m MODEL_ID [--file (-f) String] [--strategy (-s) String] [--content Boolean]
|
|
85
|
-
|
|
86
|
-
# push => send a model definition from a JSON file or stdin to the server
|
|
87
|
-
swell model push [--file (-f) String] [--input (-i) stdin] [--content Boolean]
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
It is important that the model definition includes some fields depending on the type/source of the model.
|
|
91
|
-
|
|
92
|
-
#### Basic model
|
|
93
|
-
|
|
94
|
-
```json
|
|
95
|
-
{
|
|
96
|
-
"name": "Test", // slug will be assumed from this field
|
|
97
|
-
"slug": "test_model", // or you can define one explicitly
|
|
98
|
-
"fields": { ... }
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
#### Namespaced model
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
{
|
|
106
|
-
"name": "Page", // slug will be assumed from this field
|
|
107
|
-
"namespace": "content",
|
|
108
|
-
"fields": { ... }
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
#### Theme content (abstract) model/fields (use with --content flag)
|
|
113
|
-
|
|
114
|
-
```json
|
|
115
|
-
{
|
|
116
|
-
"name": "Test", // slug will be assumed from this field
|
|
117
|
-
"fields": { ... },
|
|
118
|
-
"source_type": "theme",
|
|
119
|
-
"source_id": "origin"
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Examples
|
|
124
|
-
|
|
125
|
-
```sh
|
|
126
|
-
swell model pull -m products # pull products model and display in stdout
|
|
127
|
-
swell model pull -m theme.origin.page --content -f models/page.json # pull a content model and save it to a file
|
|
128
|
-
|
|
129
|
-
swell model push -f models/orders.json
|
|
130
|
-
swell model push -c -f models/page.json # push a content model
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Without logging in
|
|
134
|
-
|
|
135
|
-
```sh
|
|
136
|
-
swell model pull -m products --store my-test-store --secret-key my-dev-secret-key
|
|
137
|
-
swell model pull -m theme.origin.page --content -f models/page.json --store my-test-store --secret-key my-dev-secret-key
|
|
138
|
-
|
|
139
|
-
swell model push -f models/orders.json --store my-test-store --secret-key my-dev-secret-key
|
|
140
|
-
swell model push -c -f models/page.json --store my-test-store --secret-key my-dev-secret-key
|
|
141
|
-
```
|
|
3
|
+
Find the alpha docs at https://www.notion.so/swellcorp/CLI-reference-c3553ebb3de24d94becbedf95a5a25d8?pvs=4
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
2
|
import { dasherize, pluralize, underscore } from 'inflection';
|
|
3
|
-
import snakeCase from 'lodash/snakeCase.js';
|
|
4
3
|
import * as path from 'node:path';
|
|
5
4
|
import { newConfig } from '../../lib/app-config.js';
|
|
6
5
|
import { ConfigPaths, writeJsonFile, } from '../../lib/apps/index.js';
|
|
6
|
+
import { toAppId } from '../../lib/create/index.js';
|
|
7
7
|
import style from '../../lib/style.js';
|
|
8
8
|
import { RemoteAppCommand } from '../../remote-app-command.js';
|
|
9
9
|
export default class AppPull extends RemoteAppCommand {
|
|
@@ -25,7 +25,7 @@ export default class AppPull extends RemoteAppCommand {
|
|
|
25
25
|
const config = newConfig();
|
|
26
26
|
const appConfigJson = {
|
|
27
27
|
description: this.app.description || '',
|
|
28
|
-
id:
|
|
28
|
+
id: toAppId(this.app.name),
|
|
29
29
|
name: this.app.name,
|
|
30
30
|
version: this.app.version,
|
|
31
31
|
};
|
|
@@ -47,7 +47,7 @@ it will output all versions of the app instead.`;
|
|
|
47
47
|
const spinner = ora();
|
|
48
48
|
spinner.start('Retrieving app info...');
|
|
49
49
|
this.app = await this.getAppWithConfig().catch((error) => {
|
|
50
|
-
spinner.fail(`Error fetching app info
|
|
50
|
+
spinner.fail(`Error fetching app info:`);
|
|
51
51
|
throw error;
|
|
52
52
|
});
|
|
53
53
|
if (spinner.isSpinning) {
|
|
@@ -93,7 +93,8 @@ Without a store specified, install the app in the Live environment of the curren
|
|
|
93
93
|
else {
|
|
94
94
|
extraMessage = ` ${style.appConfigValue(this.app.name)} v${versionToInstall} on ${style.storeId(storeToInstall)} [${envToInstall ? envToInstall : 'live'}]`;
|
|
95
95
|
}
|
|
96
|
-
const shouldContinue =
|
|
96
|
+
const shouldContinue = existingVersion ||
|
|
97
|
+
(await this.confirmRemoveDevelopmentApp(storeToInstall));
|
|
97
98
|
if (!shouldContinue) {
|
|
98
99
|
return;
|
|
99
100
|
}
|
|
@@ -148,6 +149,7 @@ Without a store specified, install the app in the Live environment of the curren
|
|
|
148
149
|
query: { source_id: this.app.id },
|
|
149
150
|
});
|
|
150
151
|
if (existingSourcedApps.results[0]?.id) {
|
|
152
|
+
console.log(existingSourcedApps.results[0]);
|
|
151
153
|
const continueInstall = await confirm({
|
|
152
154
|
message: `${style.storeId(storeToInstall)} has a development version of ${style.appConfigValue(this.app.name)}. Do you want to replace it with an installed instance?`,
|
|
153
155
|
default: false,
|
|
@@ -2,6 +2,9 @@ import { RemoteAppCommand } from '../../remote-app-command.js';
|
|
|
2
2
|
export default class AppPush extends RemoteAppCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
file: import("@oclif/core/lib/interfaces/parser.js").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
5
8
|
static flags: {
|
|
6
9
|
file: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
7
10
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { confirm } from '@inquirer/prompts';
|
|
2
|
-
import { Flags } from '@oclif/core';
|
|
2
|
+
import { Flags, Args } from '@oclif/core';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import { appConfigFileExists } from '../../lib/app-config.js';
|
|
@@ -26,6 +26,13 @@ ${Object.values(ConfigPaths)
|
|
|
26
26
|
'swell app push -f content',
|
|
27
27
|
'swell app push -f models/products.json',
|
|
28
28
|
];
|
|
29
|
+
static args = {
|
|
30
|
+
file: Args.string({
|
|
31
|
+
char: 'f',
|
|
32
|
+
description: 'relative path to a configuration file or directory to push',
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
// Deprecating the flags in favor of args
|
|
29
36
|
static flags = {
|
|
30
37
|
file: Flags.string({
|
|
31
38
|
char: 'f',
|
|
@@ -37,20 +44,25 @@ ${Object.values(ConfigPaths)
|
|
|
37
44
|
};
|
|
38
45
|
static summary = 'Push configuration files to your Swell app.';
|
|
39
46
|
async run() {
|
|
40
|
-
const { flags } = await this.parse(AppPush);
|
|
41
|
-
const { file } =
|
|
47
|
+
const { args, flags } = await this.parse(AppPush);
|
|
48
|
+
const { file: fileArg } = args;
|
|
49
|
+
const { file: fileFlag } = flags;
|
|
50
|
+
const file = fileArg || fileFlag;
|
|
42
51
|
const currentStore = swellConfig.getDefaultStore();
|
|
43
52
|
this.api.setStoreEnv(currentStore, 'test');
|
|
44
|
-
this.app = await this.getAppWithConfig(
|
|
53
|
+
this.app = await this.getAppWithConfig('', false);
|
|
45
54
|
const confirmExistingApp = await this.confirmRemoveInstalledApp(currentStore);
|
|
46
55
|
if (confirmExistingApp === false) {
|
|
47
56
|
return;
|
|
48
57
|
}
|
|
49
58
|
// If app exists but owned by another client, offer to create a new instance
|
|
50
|
-
if (this.app.client_id !== currentStore) {
|
|
59
|
+
if (this.app.client_id && this.app.client_id !== currentStore) {
|
|
51
60
|
if (!confirmExistingApp?.id) {
|
|
61
|
+
const otherAppName = this.app.name || this.appConfig.get('name');
|
|
52
62
|
const confirmPushNew = await confirm({
|
|
53
|
-
message: `${style.appConfigValue(
|
|
63
|
+
message: `${style.appConfigValue(otherAppName)} has a dev version in another ${this.app.client_id
|
|
64
|
+
? `store ${style.dim(`(${this.app.client_id})`)}`
|
|
65
|
+
: 'environment'}. Do you want to create a new development instance in ${style.storeId(currentStore)}?`,
|
|
54
66
|
default: false,
|
|
55
67
|
});
|
|
56
68
|
if (!confirmPushNew) {
|
package/dist/commands/logs.d.ts
CHANGED
package/dist/commands/logs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
+
import ora from 'ora';
|
|
2
3
|
import { LineOutput, LoggedItem, TableOutput } from '../lib/logs/index.js';
|
|
3
4
|
import { SwellCommand } from '../swell-command.js';
|
|
4
5
|
// the columns available to display in the table
|
|
@@ -162,6 +163,10 @@ export default class Logs extends SwellCommand {
|
|
|
162
163
|
static summary = 'Output or stream store logs to the terminal.';
|
|
163
164
|
output;
|
|
164
165
|
async run() {
|
|
166
|
+
const spinner = ora();
|
|
167
|
+
spinner.fail('This command is temporarily disabled. Check back soon.');
|
|
168
|
+
}
|
|
169
|
+
async __run() {
|
|
165
170
|
const { flags } = await this.parse(Logs);
|
|
166
171
|
// indentify the columns to display
|
|
167
172
|
const columns = flags.columns.split(',');
|
package/dist/lib/api.js
CHANGED
|
@@ -65,8 +65,17 @@ export default class Api {
|
|
|
65
65
|
throw new Error('Operation not supported.');
|
|
66
66
|
const resp = await fetch(path, fetchOptions);
|
|
67
67
|
const respData = await resp.text();
|
|
68
|
-
if (!resp.ok)
|
|
69
|
-
|
|
68
|
+
if (!resp.ok) {
|
|
69
|
+
// Try to parse error message
|
|
70
|
+
let errorJson;
|
|
71
|
+
try {
|
|
72
|
+
errorJson = JSON.parse(respData);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// ignore
|
|
76
|
+
}
|
|
77
|
+
throw new Error(errorJson?.error?.message || errorJson?.error || respData);
|
|
78
|
+
}
|
|
70
79
|
try {
|
|
71
80
|
return JSON.parse(respData);
|
|
72
81
|
}
|
|
@@ -68,9 +68,12 @@ class AppConfig {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
async postData() {
|
|
71
|
-
if (!this.localPath
|
|
71
|
+
if (!this.localPath) {
|
|
72
72
|
throw new Error('Missing local config path');
|
|
73
73
|
}
|
|
74
|
+
if (!this.fileData) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
74
77
|
if (this.localPath.endsWith('.json')) {
|
|
75
78
|
try {
|
|
76
79
|
this.values = JSON.parse(this.fileData);
|
package/dist/lib/bundle.js
CHANGED
|
@@ -22,6 +22,9 @@ export async function bundleFunction(filePath) {
|
|
|
22
22
|
? line.replace('module.exports', 'var moduleExports')
|
|
23
23
|
: line)
|
|
24
24
|
.join('\n');
|
|
25
|
+
// Remove comments with to get a unique hash in the API
|
|
26
|
+
// Because esbuild puts the file name as a comment
|
|
27
|
+
code = code.replace(/^[\n]?\/\/.*/gm, '');
|
|
25
28
|
// eslint-disable-next-line no-new-func
|
|
26
29
|
const evalFn = new Function(`${code}\nreturn { ...moduleExports }`);
|
|
27
30
|
const { config, ...moduleExports } = evalFn();
|
package/dist/lib/constants.js
CHANGED
|
@@ -13,5 +13,5 @@ export function getAdminApiBaseUrl(storeId) {
|
|
|
13
13
|
return ADMIN_API_BASE_URL.replace('${STORE_ID}', storeId);
|
|
14
14
|
}
|
|
15
15
|
export function getLoginHost(storeId) {
|
|
16
|
-
return LOGIN_HOST.replace('${STORE_ID}', storeId || '
|
|
16
|
+
return LOGIN_HOST.replace('${STORE_ID}', storeId || 'login');
|
|
17
17
|
}
|
|
@@ -5,7 +5,7 @@ interface CreateFileParams {
|
|
|
5
5
|
}
|
|
6
6
|
declare const toFileName: (value: string) => string;
|
|
7
7
|
declare const toAppName: (value: string) => string;
|
|
8
|
-
declare const toAppId: (value: string) => string;
|
|
8
|
+
declare const toAppId: (value: string | undefined) => string;
|
|
9
9
|
declare const toFunctionFileName: (value: string) => string;
|
|
10
10
|
declare const toCollectionName: (value: string) => string;
|
|
11
11
|
declare const toCollectionLabel: (value: string) => string;
|
package/dist/lib/create/index.js
CHANGED
|
@@ -4,9 +4,11 @@ const toFileName = (value) => dasherize(underscore(value.split('.')[0].replace('
|
|
|
4
4
|
// Example: 'my-things' => 'My Things'
|
|
5
5
|
const toAppName = (value) => pluralize(titleize(value).replace('-', ' '));
|
|
6
6
|
// Example: 'My App' => 'my_app'
|
|
7
|
-
const toAppId = (value) => value
|
|
8
|
-
.replace(/[^a-
|
|
9
|
-
.replace(
|
|
7
|
+
const toAppId = (value) => String(value || '')
|
|
8
|
+
.replace(/[^a-zA-Z0-9\-_\s:\.\/]/g, '')
|
|
9
|
+
.replace(/[_\s-:\.\/]+/g, '_')
|
|
10
|
+
.replace(/^[_]+|[_]+$/g, '')
|
|
11
|
+
.replace(/([a-z])([A-Z])/g, '$1_$2')
|
|
10
12
|
.toLowerCase();
|
|
11
13
|
// Example: 'My Thing' => 'my-thing'
|
|
12
14
|
// And: 'myThing' => 'myThing'
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { inflect } from 'inflection';
|
|
2
|
-
import snakeCase from 'lodash/snakeCase.js';
|
|
3
2
|
import * as fs from 'node:fs';
|
|
4
3
|
import * as path from 'node:path';
|
|
5
4
|
import ora from 'ora';
|
|
6
5
|
import { AppCommand } from './app-command.js';
|
|
7
6
|
import { appConfigFileExists, readRcFile, writeRcFile, } from './lib/app-config.js';
|
|
8
7
|
import { FunctionProcessingError, IgnoringFileError, allConfigFilesPaths, appConfigFromFile, appLogoIcon, batchAppConfigsByType, configFilePath, isAppLogoIcon, } from './lib/apps/index.js';
|
|
8
|
+
import { toAppId } from './lib/create/index.js';
|
|
9
9
|
import { default as swellConfig } from './lib/config.js';
|
|
10
10
|
import { getLoginHost } from './lib/constants.js';
|
|
11
11
|
import style from './lib/style.js';
|
|
@@ -64,7 +64,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
64
64
|
this.error(`App ${style.appConfigName('id')} is not defined in swell.json.`);
|
|
65
65
|
}
|
|
66
66
|
if (privateId !== appConfigId) {
|
|
67
|
-
this.error(`App ${style.appConfigName('id')} must be
|
|
67
|
+
this.error(`App ${style.appConfigName('id')} must be declared in snake_case: ${style.appConfigValue(appConfigId)}.`);
|
|
68
68
|
}
|
|
69
69
|
appId = privateId;
|
|
70
70
|
}
|
|
@@ -97,7 +97,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
97
97
|
: errorJson.error.message;
|
|
98
98
|
this.error(errorMessage);
|
|
99
99
|
}
|
|
100
|
-
if (swellId) {
|
|
100
|
+
if (swellId && swellId !== id && swellId !== this.app?.id) {
|
|
101
101
|
app = await this.getAppWithConfig(swellId);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
@@ -105,7 +105,15 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
105
105
|
}
|
|
106
106
|
async getCreateUpdateApp(updateApp) {
|
|
107
107
|
const spinner = ora();
|
|
108
|
-
|
|
108
|
+
let remoteApp;
|
|
109
|
+
try {
|
|
110
|
+
remoteApp = await readRcFile(this.swellRcPath());
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (error.code !== 'ENOENT') {
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
109
117
|
/* eslint-disable camelcase */
|
|
110
118
|
const body = {
|
|
111
119
|
...this.appConfig.store,
|
|
@@ -113,7 +121,9 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
113
121
|
// when posting to the API
|
|
114
122
|
id: undefined,
|
|
115
123
|
logo_icon: null,
|
|
116
|
-
|
|
124
|
+
...(this.appConfig.store.id
|
|
125
|
+
? { private_id: this.appConfig.store.id }
|
|
126
|
+
: undefined),
|
|
117
127
|
...(remoteApp?.id ? { source_id: remoteApp.id } : undefined),
|
|
118
128
|
};
|
|
119
129
|
const logoIcon = appLogoIcon(this.appPath);
|
|
@@ -126,17 +136,23 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
126
136
|
let appCreated = false;
|
|
127
137
|
if (!app.id) {
|
|
128
138
|
// May already have a dev instance
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
let existingDevApp;
|
|
140
|
+
try {
|
|
141
|
+
existingDevApp = await this.api.get({
|
|
142
|
+
adminPath: `/apps/${this.appConfig.store.id}`,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
// noop
|
|
147
|
+
}
|
|
132
148
|
spinner.start(`Creating app...`);
|
|
133
149
|
if (existingDevApp) {
|
|
134
150
|
app = await this.handleRequestErrors(async () => this.api.put({ adminPath: `/apps/${existingDevApp.id}` }, { body }), () => spinner.fail('Error creating app'));
|
|
135
151
|
}
|
|
136
152
|
else {
|
|
137
153
|
app = await this.handleRequestErrors(async () => this.api.post({ adminPath: '/apps' }, { body }), () => spinner.fail('Error creating app'));
|
|
154
|
+
appCreated = true;
|
|
138
155
|
}
|
|
139
|
-
appCreated = true;
|
|
140
156
|
}
|
|
141
157
|
else if (app.id) {
|
|
142
158
|
spinner.start(`Updating app...`);
|
|
@@ -220,6 +236,10 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
220
236
|
spinner.start(`Pushing ${pathDesc}`);
|
|
221
237
|
try {
|
|
222
238
|
postData = await appConfig.postData();
|
|
239
|
+
if (!postData) {
|
|
240
|
+
spinner.stop();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
223
243
|
}
|
|
224
244
|
catch (error) {
|
|
225
245
|
if (error instanceof IgnoringFileError) {
|
|
@@ -327,8 +347,9 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
327
347
|
}
|
|
328
348
|
}
|
|
329
349
|
if (this.appConfig.get('id')) {
|
|
350
|
+
// use the same formula as the backend api
|
|
330
351
|
// eslint-disable-next-line camelcase
|
|
331
|
-
remoteApp.private_id =
|
|
352
|
+
remoteApp.private_id = toAppId(this.appConfig.get('id'));
|
|
332
353
|
}
|
|
333
354
|
return remoteApp;
|
|
334
355
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -452,7 +452,12 @@
|
|
|
452
452
|
},
|
|
453
453
|
"app:push": {
|
|
454
454
|
"aliases": [],
|
|
455
|
-
"args": {
|
|
455
|
+
"args": {
|
|
456
|
+
"file": {
|
|
457
|
+
"description": "relative path to a configuration file or directory to push",
|
|
458
|
+
"name": "file"
|
|
459
|
+
}
|
|
460
|
+
},
|
|
456
461
|
"description": "Push all app configurations, a specific file, or a specific configuration\ntype to an app in your store's test environment. If the app does not exist yet,\nit 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 configuration directories:\nassets/\ncontent/\nfunctions/\nmodels/\nnotifications/\nsettings/\nwebhooks/",
|
|
457
462
|
"examples": [
|
|
458
463
|
"swell app push",
|
|
@@ -1081,5 +1086,5 @@
|
|
|
1081
1086
|
]
|
|
1082
1087
|
}
|
|
1083
1088
|
},
|
|
1084
|
-
"version": "2.0.1-alpha.
|
|
1089
|
+
"version": "2.0.1-alpha.11"
|
|
1085
1090
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swell/cli",
|
|
3
|
-
"version": "2.0.1-alpha.
|
|
3
|
+
"version": "2.0.1-alpha.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Swell's command line interface/utility",
|
|
6
6
|
"keywords": [
|
|
@@ -26,27 +26,28 @@
|
|
|
26
26
|
"/oclif.manifest.json"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
+
"@inquirer/prompts": "3.2.0",
|
|
29
30
|
"@npmcli/git": "5.0.3",
|
|
30
31
|
"@oclif/core": "3.7.1",
|
|
32
|
+
"@oclif/errors": "1.3.6",
|
|
31
33
|
"@oclif/plugin-help": "6.0.4",
|
|
32
34
|
"@oclif/plugin-plugins": "3.9.4",
|
|
35
|
+
"chalk": "5.3.0",
|
|
33
36
|
"conf": "11.0.2",
|
|
34
37
|
"configstore": "6.0.0",
|
|
38
|
+
"esbuild": "0.19.5",
|
|
35
39
|
"inflection": "3.0.0",
|
|
40
|
+
"lodash": "4.17.21",
|
|
36
41
|
"node-fetch": "3.3.2",
|
|
37
42
|
"oclif": "4.0.3",
|
|
38
43
|
"open": "9.1.0",
|
|
44
|
+
"ora": "7.0.1",
|
|
39
45
|
"semver": "7.5.4",
|
|
40
46
|
"table": "6.8.1"
|
|
41
47
|
},
|
|
42
48
|
"devDependencies": {
|
|
43
|
-
"@inquirer/prompts": "3.2.0",
|
|
44
49
|
"@inquirer/testing": "2.1.8",
|
|
45
|
-
"@oclif/errors": "1.3.6",
|
|
46
50
|
"@oclif/test": "3.0.3",
|
|
47
|
-
"@rollup/plugin-commonjs": "25.0.7",
|
|
48
|
-
"@rollup/plugin-json": "6.0.1",
|
|
49
|
-
"@rollup/plugin-node-resolve": "15.2.3",
|
|
50
51
|
"@types/chai": "4.3.9",
|
|
51
52
|
"@types/configstore": "6.0.1",
|
|
52
53
|
"@types/inquirer": "9.0.6",
|
|
@@ -54,30 +55,20 @@
|
|
|
54
55
|
"@types/node": "20.8.8",
|
|
55
56
|
"@typescript-eslint/eslint-plugin": "6.9.0",
|
|
56
57
|
"chai": "4.3.10",
|
|
57
|
-
"chalk": "5.3.0",
|
|
58
|
-
"configstore": "6.0.0",
|
|
59
58
|
"dotenv": "16.3.1",
|
|
60
|
-
"esbuild": "0.19.5",
|
|
61
59
|
"eslint": "8.52.0",
|
|
62
60
|
"eslint-config-oclif": "5.0.0",
|
|
63
61
|
"eslint-config-oclif-typescript": "3.0.8",
|
|
64
62
|
"eslint-config-prettier": "9.0.0",
|
|
65
63
|
"eslint-plugin-prettier": "5.0.1",
|
|
66
64
|
"eslint-plugin-unicorn": "48.0.1",
|
|
67
|
-
"list-it": "1.3.12",
|
|
68
|
-
"lodash": "4.17.21",
|
|
69
65
|
"mocha": "10.2.0",
|
|
70
66
|
"nock": "13.3.6",
|
|
71
|
-
"npm-decode": "1.4.2",
|
|
72
67
|
"oclif": "4.0.3",
|
|
73
|
-
"ora": "7.0.1",
|
|
74
|
-
"rollup": "4.1.4",
|
|
75
68
|
"shx": "0.3.4",
|
|
76
69
|
"testdouble": "3.20.0",
|
|
77
70
|
"ts-node": "10.9.1",
|
|
78
|
-
"
|
|
79
|
-
"typescript": "5.2.2",
|
|
80
|
-
"uvu": "0.5.6"
|
|
71
|
+
"typescript": "5.2.2"
|
|
81
72
|
},
|
|
82
73
|
"oclif": {
|
|
83
74
|
"bin": "swell",
|
|
@@ -103,7 +94,7 @@
|
|
|
103
94
|
"posttest": "npm run lint",
|
|
104
95
|
"prepack": "npm run build && oclif manifest && oclif readme",
|
|
105
96
|
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
|
|
106
|
-
"
|
|
97
|
+
"publish-alpha": "npm version prerelease --preid=alpha && npm publish --tag alpha"
|
|
107
98
|
},
|
|
108
99
|
"engines": {
|
|
109
100
|
"node": ">= 18.16.1"
|