@swell/cli 2.9.4 → 2.9.6
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 +2 -3
- package/dist/app-command.js +3 -6
- package/dist/commands/app/dev.d.ts +2 -2
- package/dist/commands/app/dev.js +49 -33
- package/dist/commands/app/frontend/dev.js +12 -6
- package/dist/commands/app/push.d.ts +1 -0
- package/dist/commands/app/push.js +3 -3
- package/dist/commands/app/release.js +2 -2
- package/dist/commands/create/app.d.ts +1 -1
- package/dist/commands/create/app.js +1 -1
- package/dist/commands/create/frontend.js +3 -3
- package/dist/commands/create/tests.js +10 -8
- package/dist/commands/inspect/extensions.js +4 -4
- package/dist/commands/schema.js +21 -18
- package/dist/commands/theme/dev.js +5 -5
- package/dist/commands/theme/push.d.ts +1 -0
- package/dist/commands/theme/push.js +3 -3
- package/dist/create-app-command.js +2 -2
- package/dist/create-config-command.d.ts +1 -1
- package/dist/create-config-command.js +3 -3
- package/dist/help/custom-help.d.ts +1 -1
- package/dist/help/types.d.ts +1 -1
- package/dist/lib/api.d.ts +1 -0
- package/dist/lib/api.js +1 -1
- package/dist/lib/app-config.d.ts +13 -8
- package/dist/lib/app-config.js +25 -23
- package/dist/lib/apps/app-config.d.ts +5 -5
- package/dist/lib/apps/app-config.js +53 -37
- package/dist/lib/apps/index.d.ts +15 -14
- package/dist/lib/apps/index.js +40 -23
- package/dist/lib/apps/paths.d.ts +1 -1
- package/dist/lib/apps/paths.js +3 -3
- package/dist/lib/bundle.js +26 -17
- package/dist/lib/config.d.ts +8 -8
- package/dist/lib/config.js +8 -10
- package/dist/lib/constants.d.ts +9 -9
- package/dist/lib/create/content.d.ts +6 -6
- package/dist/lib/create/content.js +7 -8
- package/dist/lib/create/function.d.ts +5 -6
- package/dist/lib/create/function.js +7 -8
- package/dist/lib/create/index.d.ts +8 -9
- package/dist/lib/create/index.js +7 -8
- package/dist/lib/create/model.d.ts +4 -4
- package/dist/lib/create/model.js +4 -5
- package/dist/lib/create/notification.d.ts +2 -3
- package/dist/lib/create/setting.d.ts +4 -4
- package/dist/lib/create/setting.js +3 -4
- package/dist/lib/create/tests/templates/mock-request.js +30 -0
- package/dist/lib/create/tests/templates/setup-globals.js +35 -0
- package/dist/lib/create/tests/types.d.ts +3 -4
- package/dist/lib/create/tests.d.ts +1 -2
- package/dist/lib/create/tests.js +12 -13
- package/dist/lib/create/webhook.d.ts +6 -6
- package/dist/lib/create/webhook.js +15 -10
- package/dist/lib/function-source-analysis.js +3 -3
- package/dist/lib/info.d.ts +1 -1
- package/dist/lib/logs/index.d.ts +1 -0
- package/dist/lib/logs/line-output.d.ts +1 -0
- package/dist/lib/logs/line-output.js +12 -4
- package/dist/lib/logs/output.d.ts +1 -0
- package/dist/lib/logs/table-output.d.ts +1 -0
- package/dist/lib/logs/table-output.js +8 -5
- package/dist/lib/package-manager.d.ts +5 -5
- package/dist/lib/package-manager.js +9 -7
- package/dist/lib/proxy.js +4 -3
- package/dist/lib/sessions.d.ts +1 -2
- package/dist/lib/sessions.js +1 -2
- package/dist/lib/stores.d.ts +6 -6
- package/dist/lib/stores.js +5 -6
- package/dist/lib/swell-function-wrapper.d.ts +1 -193
- package/dist/lib/swell-function-wrapper.js +24 -1
- package/dist/lib/theme-sync.js +0 -5
- package/dist/push-app-command.d.ts +7 -6
- package/dist/push-app-command.js +35 -37
- package/dist/remote-app-command.d.ts +6 -4
- package/dist/remote-app-command.js +39 -25
- package/dist/swell-api-command.d.ts +1 -0
- package/dist/swell-api-command.js +3 -3
- package/dist/types/index.d.ts +94 -0
- package/dist/types/index.js +4 -0
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
|
@@ -5,7 +5,7 @@ import * as path from 'node:path';
|
|
|
5
5
|
import { default as ora } from 'ora';
|
|
6
6
|
import { AppCommand } from './app-command.js';
|
|
7
7
|
import { readRcFile, writeRcFile } from './lib/app-config.js';
|
|
8
|
-
import { AppConfig, FunctionProcessingError, IgnoringFileError, SwellJsonFields, allBaseFilesInDir, allConfigFilesPaths, appConfigFromFile, batchAppFilesByType, deleteFile, hashFile, writeFile, writeJsonFile, PUSH_CONCURRENCY, } from './lib/apps/index.js';
|
|
8
|
+
import { AppConfig, ConfigType, FunctionProcessingError, IgnoringFileError, SwellJsonFields, allBaseFilesInDir, allConfigFilesPaths, appConfigFromFile, batchAppFilesByType, deleteFile, hashFile, writeFile, writeJsonFile, PUSH_CONCURRENCY, } from './lib/apps/index.js';
|
|
9
9
|
import { default as localConfig } from './lib/config.js';
|
|
10
10
|
import { getAppFrontendHost, getLocalFrontendHost, getLoginHost, getStorefrontFrontendHost, } from './lib/constants.js';
|
|
11
11
|
import { toAppId } from './lib/create/index.js';
|
|
@@ -78,20 +78,21 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
78
78
|
},
|
|
79
79
|
});
|
|
80
80
|
// Instantiate AppConfig for each object
|
|
81
|
-
app.configs = (configs.results || []).map((config) => AppConfig.create({
|
|
81
|
+
app.configs = await Promise.all((configs.results || []).map((config) => AppConfig.create({
|
|
82
82
|
...config,
|
|
83
83
|
appPath: this.appPath,
|
|
84
|
-
}));
|
|
84
|
+
})));
|
|
85
85
|
// Pull app configs to compare with theme for push/pull
|
|
86
86
|
if (themeId && this.themeSyncApp) {
|
|
87
87
|
const appConfigs = await this.api.get({ adminPath: `/apps/${id}/configs` }, { query: { limit: 1000 } });
|
|
88
|
+
const promises = [];
|
|
88
89
|
for (const appConfig of appConfigs.results || []) {
|
|
89
90
|
const themeConfig = app.configs.find((config) => config.filePath === appConfig.file_path);
|
|
90
91
|
if (themeConfig && themeConfig.fileHash !== appConfig.hash) {
|
|
91
92
|
themeConfig.hash = appConfig.hash;
|
|
92
93
|
}
|
|
93
94
|
else if (!themeConfig && appConfig) {
|
|
94
|
-
|
|
95
|
+
promises.push(AppConfig.create({
|
|
95
96
|
...appConfig,
|
|
96
97
|
appConfigId: appConfig.id,
|
|
97
98
|
appPath: this.appPath,
|
|
@@ -99,6 +100,10 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
99
100
|
}));
|
|
100
101
|
}
|
|
101
102
|
}
|
|
103
|
+
if (promises.length > 0) {
|
|
104
|
+
const list = await Promise.all(promises);
|
|
105
|
+
app.configs.push(...list);
|
|
106
|
+
}
|
|
102
107
|
for (const themeConfig of app.configs) {
|
|
103
108
|
const appConfig = appConfigs.results.find((config) => themeConfig.filePath === config.file_path);
|
|
104
109
|
if (!appConfig) {
|
|
@@ -178,7 +183,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
178
183
|
throw error;
|
|
179
184
|
}
|
|
180
185
|
}
|
|
181
|
-
if (!this.swellConfig.store
|
|
186
|
+
if (!this.swellConfig.store?.id) {
|
|
182
187
|
throw new Error('App swell.json is missing or `id` is not defined.');
|
|
183
188
|
}
|
|
184
189
|
const body = {
|
|
@@ -244,17 +249,15 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
244
249
|
// check if app is already installed on store
|
|
245
250
|
return this.api.get({ adminPath: `/client/apps/${this.app.id}` }, {});
|
|
246
251
|
}
|
|
247
|
-
getLocalAppConfigs() {
|
|
248
|
-
const
|
|
252
|
+
async getLocalAppConfigs() {
|
|
253
|
+
const promises = [];
|
|
249
254
|
for (const { configFile, configType } of allConfigFilesPaths(this.appPath)) {
|
|
250
|
-
|
|
251
|
-
localConfigs.push(config);
|
|
255
|
+
promises.push(appConfigFromFile(configFile, configType, this.appPath));
|
|
252
256
|
}
|
|
253
257
|
for (const filePath of allBaseFilesInDir(this.appPath)) {
|
|
254
|
-
|
|
255
|
-
localConfigs.push(config);
|
|
258
|
+
promises.push(appConfigFromFile(filePath, ConfigType.FILE, this.appPath));
|
|
256
259
|
}
|
|
257
|
-
return
|
|
260
|
+
return Promise.all(promises);
|
|
258
261
|
}
|
|
259
262
|
async getVersion(version) {
|
|
260
263
|
const versionsResponse = await this.api.get({ adminPath: `/apps/${this.app.id}/versions` }, {
|
|
@@ -289,8 +292,11 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
289
292
|
try {
|
|
290
293
|
jsonError = JSON.parse(error.message);
|
|
291
294
|
}
|
|
292
|
-
catch {
|
|
293
|
-
//
|
|
295
|
+
catch (error) {
|
|
296
|
+
// Skip JSON parse error
|
|
297
|
+
if (!(error instanceof SyntaxError)) {
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
294
300
|
}
|
|
295
301
|
if (!showedErrors) {
|
|
296
302
|
if (jsonError && jsonError.error) {
|
|
@@ -312,8 +318,8 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
312
318
|
await this.logOrientation();
|
|
313
319
|
}
|
|
314
320
|
}
|
|
315
|
-
|
|
316
|
-
return this.api.post({ adminPath:
|
|
321
|
+
installApp(version, spinner) {
|
|
322
|
+
return this.api.post({ adminPath: '/client/apps' }, {
|
|
317
323
|
body: { app_id: this.app.id, version },
|
|
318
324
|
onAsyncGetPath: (response) => ({
|
|
319
325
|
adminPath: `/client/app-async-status/${response.app_id}`,
|
|
@@ -352,8 +358,10 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
352
358
|
async pullAppConfigs(force, confirmRemove = true) {
|
|
353
359
|
const pulled = [];
|
|
354
360
|
const removed = [];
|
|
355
|
-
const localConfigs =
|
|
356
|
-
|
|
361
|
+
const [localConfigs, remoteConfigs] = await Promise.all([
|
|
362
|
+
this.getLocalAppConfigs(),
|
|
363
|
+
this.pullAppJsonAndRemoteConfigs().then((remoteConfigs) => this.cleanRemoteConfigs(remoteConfigs, false)),
|
|
364
|
+
]);
|
|
357
365
|
const batches = batchAppFilesByType(remoteConfigs);
|
|
358
366
|
for (const batch of batches) {
|
|
359
367
|
const remoteBatchConfigs = remoteConfigs.filter((config) => config.type === batch.type);
|
|
@@ -364,13 +372,15 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
364
372
|
try {
|
|
365
373
|
const localConfig = localBatchConfigs.find((config) => config.filePath === batchConfig.filePath);
|
|
366
374
|
if (localConfig) {
|
|
367
|
-
const hash = hashFile(batchConfig.appPath,
|
|
375
|
+
const hash = hashFile(batchConfig.appPath, localConfig.fileData, batchConfig.filePath);
|
|
368
376
|
if (hash === batchConfig.hash) {
|
|
369
377
|
return false;
|
|
370
378
|
}
|
|
371
379
|
}
|
|
372
380
|
}
|
|
373
|
-
catch {
|
|
381
|
+
catch {
|
|
382
|
+
// TODO: Ignore only some errors
|
|
383
|
+
}
|
|
374
384
|
return true;
|
|
375
385
|
});
|
|
376
386
|
const filesToRemove = localBatchConfigs.filter((config) => !batch.configs.some((batchConfig) => batchConfig.filePath === config.filePath));
|
|
@@ -439,7 +449,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
439
449
|
swellConfigJson.id = toAppId(this.app.private_id);
|
|
440
450
|
await writeJsonFile(path.join(this.appPath, 'swell.json'), swellConfigJson);
|
|
441
451
|
}
|
|
442
|
-
const swellConfig = appConfigFromFile('swell.json',
|
|
452
|
+
const swellConfig = await appConfigFromFile('swell.json', ConfigType.FILE, this.appPath);
|
|
443
453
|
swellConfig.id = swellJson?.id;
|
|
444
454
|
return [swellConfig, ...allOtherConfigs];
|
|
445
455
|
}
|
|
@@ -460,8 +470,10 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
460
470
|
async pushAppConfigs(force) {
|
|
461
471
|
const pushed = [];
|
|
462
472
|
const removed = [];
|
|
463
|
-
const localConfigs =
|
|
464
|
-
|
|
473
|
+
const [localConfigs, remoteConfigs] = await Promise.all([
|
|
474
|
+
this.getLocalAppConfigs(),
|
|
475
|
+
this.cleanRemoteConfigs(this.app?.configs || []),
|
|
476
|
+
]);
|
|
465
477
|
// Do not allow more than 10K files
|
|
466
478
|
if (localConfigs.length > 10000) {
|
|
467
479
|
this.error(`Apps only support up to 10,000 files. Found ${localConfigs.length} files.`);
|
|
@@ -470,8 +482,10 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
470
482
|
for (const batch of batches) {
|
|
471
483
|
const remoteBatchConfigs = remoteConfigs.filter((config) => config.type === batch.type);
|
|
472
484
|
const pushFiles = batch.configs.filter((batchConfig) => {
|
|
485
|
+
if (force)
|
|
486
|
+
return true;
|
|
473
487
|
const remoteConfig = remoteBatchConfigs.find((config) => batchConfig.filePath === config.filePath);
|
|
474
|
-
return Boolean(
|
|
488
|
+
return Boolean(!remoteConfig || remoteConfig.hash !== batchConfig.hash);
|
|
475
489
|
});
|
|
476
490
|
const filesToRemove = remoteBatchConfigs.filter((config) => !batch.configs.some((batchConfig) => batchConfig.filePath === config.filePath));
|
|
477
491
|
// Skip if there are no config changes
|
|
@@ -538,7 +552,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
538
552
|
}
|
|
539
553
|
if (error instanceof FunctionProcessingError) {
|
|
540
554
|
log &&
|
|
541
|
-
spinner.fail(`${error.message} ${error.
|
|
555
|
+
spinner.fail(`${error.message} ${error.cause?.message?.toLowerCase()}`);
|
|
542
556
|
return;
|
|
543
557
|
}
|
|
544
558
|
log && spinner.fail(error.message);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type Api from './types/index.js';
|
|
1
2
|
import { HttpMethod } from './lib/api.js';
|
|
2
3
|
import { SwellCommand } from './swell-command.js';
|
|
3
4
|
export declare const headerFlag: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
4
|
import { FetchError } from 'node-fetch';
|
|
5
5
|
import { HttpMethod } from './lib/api.js';
|
|
6
6
|
import { resolveAppId } from './lib/apps/resolve.js';
|
|
@@ -168,7 +168,7 @@ export class SwellApiCommand extends SwellCommand {
|
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
170
|
const bodyData = this.isFilePath(body)
|
|
171
|
-
? await fs.
|
|
171
|
+
? await fs.readFile(path.resolve(body), 'utf8')
|
|
172
172
|
: body;
|
|
173
173
|
return JSON.parse(bodyData);
|
|
174
174
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type definitions for the application.
|
|
3
|
+
*/
|
|
4
|
+
import type { default as Conf } from 'conf';
|
|
5
|
+
declare namespace Api {
|
|
6
|
+
export interface AuthenticationHeaders {
|
|
7
|
+
publicKey?: string;
|
|
8
|
+
secretKey?: string;
|
|
9
|
+
sessionId?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The paths to the API endpoints. Typically a Command will define the
|
|
13
|
+
* path to the API endpoint it needs.
|
|
14
|
+
*/
|
|
15
|
+
export interface Paths {
|
|
16
|
+
adminPath?: string;
|
|
17
|
+
backendPath?: string;
|
|
18
|
+
frontendPath?: string;
|
|
19
|
+
}
|
|
20
|
+
type RequestInit = import('node-fetch').RequestInit;
|
|
21
|
+
/**
|
|
22
|
+
* The options to pass to our generic API request function. This extends
|
|
23
|
+
* the built-in fetch RequestInit interface.
|
|
24
|
+
*/
|
|
25
|
+
export interface RequestOptions extends RequestInit {
|
|
26
|
+
body?: any;
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
onAsyncGetPath?: (response: any) => Paths;
|
|
29
|
+
query?: any;
|
|
30
|
+
sessionId?: string;
|
|
31
|
+
spinner?: any;
|
|
32
|
+
rawResponse?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
35
|
+
}
|
|
36
|
+
export default Api;
|
|
37
|
+
/**
|
|
38
|
+
* The configuration of an app as defined by the developer.
|
|
39
|
+
*/
|
|
40
|
+
export interface LocalApp extends Conf<App> {
|
|
41
|
+
swDirPath: string;
|
|
42
|
+
}
|
|
43
|
+
export interface AppCommandOrientation {
|
|
44
|
+
env?: string;
|
|
45
|
+
storeId?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A log item as defined by the Swell API.
|
|
49
|
+
*/
|
|
50
|
+
export interface LogItem {
|
|
51
|
+
app: string;
|
|
52
|
+
data: string;
|
|
53
|
+
date: string;
|
|
54
|
+
env: string;
|
|
55
|
+
ip: string;
|
|
56
|
+
req: string;
|
|
57
|
+
request: string;
|
|
58
|
+
status: string;
|
|
59
|
+
time: string;
|
|
60
|
+
type: string;
|
|
61
|
+
}
|
|
62
|
+
export interface Store {
|
|
63
|
+
name: string;
|
|
64
|
+
email: string;
|
|
65
|
+
sessionId: string;
|
|
66
|
+
storeId: string;
|
|
67
|
+
}
|
|
68
|
+
export interface User {
|
|
69
|
+
email: string;
|
|
70
|
+
name: string;
|
|
71
|
+
}
|
|
72
|
+
export interface UserAuthorization {
|
|
73
|
+
client_id: string;
|
|
74
|
+
client_name: string;
|
|
75
|
+
}
|
|
76
|
+
export interface App {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
type: string;
|
|
80
|
+
private_id: string;
|
|
81
|
+
public_id?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface Model {
|
|
84
|
+
name: string;
|
|
85
|
+
namespace?: string;
|
|
86
|
+
app_id?: string;
|
|
87
|
+
deprecated?: boolean;
|
|
88
|
+
fields: {
|
|
89
|
+
[key: string]: {
|
|
90
|
+
name: string;
|
|
91
|
+
type: string;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swell/cli",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Swell's command line interface/utility",
|
|
6
6
|
"keywords": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@oclif/errors": "1.3.6",
|
|
33
33
|
"@oclif/plugin-help": "6.0.4",
|
|
34
34
|
"@oclif/plugin-plugins": "3.9.4",
|
|
35
|
-
"ajv": "8.
|
|
35
|
+
"ajv": "8.20.0",
|
|
36
36
|
"ajv-errors": "3.0.0",
|
|
37
37
|
"ajv-formats": "3.0.1",
|
|
38
38
|
"blake3-wasm": "2.1.5",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"eslint-config-prettier": "9.0.0",
|
|
84
84
|
"eslint-plugin-prettier": "5.0.1",
|
|
85
85
|
"eslint-plugin-unicorn": "48.0.1",
|
|
86
|
-
"mocha": "
|
|
86
|
+
"mocha": "11.7.6",
|
|
87
87
|
"nock": "13.3.6",
|
|
88
88
|
"oclif": "4.0.3",
|
|
89
89
|
"shx": "0.3.4",
|