@swell/cli 2.9.31 → 2.9.33
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/action.d.ts +25 -0
- package/dist/commands/app/action.js +233 -0
- package/dist/commands/app/dev.js +2 -1
- package/dist/commands/app/frontend/deploy.d.ts +1 -0
- package/dist/commands/app/frontend/deploy.js +4 -0
- package/dist/commands/app/frontend/dev.js +4 -2
- package/dist/commands/app/push.d.ts +3 -0
- package/dist/commands/app/push.js +100 -4
- package/dist/commands/app/version.js +3 -0
- package/dist/commands/create/function.js +14 -4
- package/dist/commands/create/model.js +9 -24
- package/dist/commands/create/webhook.js +7 -13
- package/dist/commands/inspect/components.d.ts +31 -0
- package/dist/commands/inspect/components.js +110 -0
- package/dist/commands/inspect/extensions.js +18 -9
- package/dist/commands/inspect/frontend.d.ts +37 -0
- package/dist/commands/inspect/frontend.js +75 -0
- package/dist/commands/inspect/functions.d.ts +11 -1
- package/dist/commands/inspect/functions.js +89 -6
- package/dist/commands/inspect/index.js +2 -0
- package/dist/commands/schema.js +5 -0
- package/dist/help/custom-help.js +5 -1
- package/dist/inspect-resource-command.d.ts +1 -1
- package/dist/inspect-resource-command.js +8 -2
- package/dist/lib/api-errors.d.ts +1 -0
- package/dist/lib/api-errors.js +28 -0
- package/dist/lib/apps/actions.d.ts +45 -0
- package/dist/lib/apps/actions.js +114 -0
- package/dist/lib/apps/components.d.ts +7 -0
- package/dist/lib/apps/components.js +10 -0
- package/dist/lib/apps/extension-manifest.d.ts +1 -0
- package/dist/lib/apps/extension-manifest.js +43 -0
- package/dist/lib/apps/index.d.ts +1 -0
- package/dist/lib/apps/index.js +30 -0
- package/dist/lib/apps/listing.d.ts +1 -0
- package/dist/lib/apps/listing.js +41 -0
- package/dist/lib/apps/paths.d.ts +8 -0
- package/dist/lib/apps/paths.js +34 -4
- package/dist/lib/bundle.js +26 -41
- package/dist/lib/create/function.d.ts +1 -1
- package/dist/lib/create/function.js +9 -5
- package/dist/lib/create/index.js +2 -1
- package/dist/lib/create/model.d.ts +7 -3
- package/dist/lib/create/model.js +67 -9
- package/dist/lib/function-declarations.d.ts +8 -0
- package/dist/lib/function-declarations.js +27 -0
- package/dist/lib/inspect/extensions.d.ts +4 -3
- package/dist/lib/inspect/extensions.js +36 -5
- package/dist/lib/swell-function-wrapper.js +13 -5
- package/dist/lib/swell-workflow-request.d.ts +34 -0
- package/dist/lib/swell-workflow-request.js +58 -0
- package/dist/push-app-command.d.ts +2 -1
- package/dist/push-app-command.js +43 -22
- package/dist/remote-app-command.d.ts +2 -2
- package/dist/remote-app-command.js +79 -51
- package/oclif.manifest.json +263 -10
- package/package.json +2 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { confirm, select } from '@inquirer/prompts';
|
|
2
|
-
import { inflect } from 'inflection';
|
|
3
2
|
import sortBy from 'lodash/sortBy.js';
|
|
4
3
|
import * as path from 'node:path';
|
|
5
4
|
import { default as ora } from 'ora';
|
|
6
5
|
import { AppCommand } from './app-command.js';
|
|
6
|
+
import { errorReasons } from './lib/api-errors.js';
|
|
7
7
|
import { readRcFile, writeRcFile } from './lib/app-config.js';
|
|
8
|
-
import {
|
|
8
|
+
import { isUnloadableComponentFile } from './lib/apps/components.js';
|
|
9
|
+
import { AppConfig, ConfigType, FunctionProcessingError, IgnoringFileError, SwellJsonFields, allBaseFilesInDir, allConfigFilesPaths, appConfigFromFile, batchAppFilesByType, deleteFile, kebabCaseFilePath, writeFile, writeJsonFile, PUSH_CONCURRENCY, } from './lib/apps/index.js';
|
|
10
|
+
import { isCredentialFile } from './lib/apps/paths.js';
|
|
9
11
|
import { default as localConfig } from './lib/config.js';
|
|
10
12
|
import { getAppFrontendHost, getLocalFrontendHost, getLoginHost, getStorefrontFrontendHost, } from './lib/constants.js';
|
|
11
13
|
import { toAppId } from './lib/create/index.js';
|
|
@@ -176,7 +178,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
176
178
|
adminPath: `/apps/${this.app.id}/configs/${configId}/data`,
|
|
177
179
|
}, { query: { ...(themeId ? { theme_id: themeId } : undefined) } });
|
|
178
180
|
}
|
|
179
|
-
async getCreateUpdateApp(updateApp
|
|
181
|
+
async getCreateUpdateApp(updateApp) {
|
|
180
182
|
const spinner = ora();
|
|
181
183
|
let sourceApp;
|
|
182
184
|
try {
|
|
@@ -205,9 +207,6 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
205
207
|
? { private_id: this.swellConfig.store.id }
|
|
206
208
|
: undefined),
|
|
207
209
|
...(sourceApp?.id ? { source_id: sourceApp.id } : undefined),
|
|
208
|
-
// Overwrite name/description/logo_icon on the server
|
|
209
|
-
// instead of only filling them in when empty
|
|
210
|
-
...(force ? { $force_meta: true } : undefined),
|
|
211
210
|
};
|
|
212
211
|
const appLabel = this.app.type === 'theme' ? 'theme' : 'app';
|
|
213
212
|
let app = updateApp || {};
|
|
@@ -405,38 +404,37 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
405
404
|
});
|
|
406
405
|
return versionsResponse.results || [];
|
|
407
406
|
}
|
|
407
|
+
// A refused request fails with every reason the API gives, so that they
|
|
408
|
+
// reach stderr together with the failure
|
|
408
409
|
async handleRequestErrors(request, spinnerError) {
|
|
409
|
-
let
|
|
410
|
+
let response;
|
|
410
411
|
try {
|
|
411
|
-
|
|
412
|
-
if (response?.status !== 200 && response?.errors) {
|
|
413
|
-
this.showErrors(response.errors, spinnerError);
|
|
414
|
-
showedErrors = true;
|
|
415
|
-
this.error('Something went wrong.');
|
|
416
|
-
}
|
|
417
|
-
return response;
|
|
412
|
+
response = await request();
|
|
418
413
|
}
|
|
419
414
|
catch (error) {
|
|
420
415
|
let jsonError;
|
|
421
416
|
try {
|
|
422
417
|
jsonError = JSON.parse(error.message);
|
|
423
418
|
}
|
|
424
|
-
catch (
|
|
419
|
+
catch (parseError) {
|
|
425
420
|
// Skip JSON parse error
|
|
426
|
-
if (!(
|
|
427
|
-
throw
|
|
421
|
+
if (!(parseError instanceof SyntaxError)) {
|
|
422
|
+
throw parseError;
|
|
428
423
|
}
|
|
429
424
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
else if (typeof error.message === 'string') {
|
|
435
|
-
this.showErrors(error, spinnerError);
|
|
436
|
-
}
|
|
425
|
+
spinnerError?.();
|
|
426
|
+
const reasons = jsonError?.error ? errorReasons(jsonError) : [];
|
|
427
|
+
if (reasons.length > 0) {
|
|
428
|
+
this.error(reasons.join('\n'));
|
|
437
429
|
}
|
|
438
430
|
throw error;
|
|
439
431
|
}
|
|
432
|
+
if (response?.status !== 200 && response?.errors) {
|
|
433
|
+
spinnerError?.();
|
|
434
|
+
const reasons = errorReasons(response.errors);
|
|
435
|
+
this.error(reasons.length > 0 ? reasons.join('\n') : 'Something went wrong.');
|
|
436
|
+
}
|
|
437
|
+
return response;
|
|
440
438
|
}
|
|
441
439
|
async init() {
|
|
442
440
|
await super.init();
|
|
@@ -489,7 +487,11 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
489
487
|
const removed = [];
|
|
490
488
|
const [localConfigs, remoteConfigs] = await Promise.all([
|
|
491
489
|
this.getLocalAppConfigs(),
|
|
492
|
-
this.pullAppJsonAndRemoteConfigs()
|
|
490
|
+
this.pullAppJsonAndRemoteConfigs()
|
|
491
|
+
.then((remoteConfigs) => this.cleanRemoteConfigs(remoteConfigs, false))
|
|
492
|
+
// An older push could send .env and .dev.vars files, which must not
|
|
493
|
+
// replace the local ones
|
|
494
|
+
.then((remoteConfigs) => remoteConfigs.filter((config) => !isCredentialFile(config.filePath))),
|
|
493
495
|
]);
|
|
494
496
|
const batches = batchAppFilesByType(remoteConfigs);
|
|
495
497
|
for (const batch of batches) {
|
|
@@ -632,7 +634,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
632
634
|
if (pushFiles.length > 0) {
|
|
633
635
|
while (pushFiles.length > 0) {
|
|
634
636
|
// eslint-disable-next-line no-await-in-loop
|
|
635
|
-
await
|
|
637
|
+
await this.runTogether(pushFiles.splice(0, batch.concurrency).map(async (config) => {
|
|
636
638
|
const pushedConfig = await this.pushRemoteFile(config);
|
|
637
639
|
if (pushedConfig) {
|
|
638
640
|
pushed.push(pushedConfig.id);
|
|
@@ -647,7 +649,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
647
649
|
if (filesToRemove.length > 0) {
|
|
648
650
|
while (filesToRemove.length > 0) {
|
|
649
651
|
// eslint-disable-next-line no-await-in-loop
|
|
650
|
-
await
|
|
652
|
+
await this.runTogether(filesToRemove.splice(0, batch.concurrency).map(async (config) => {
|
|
651
653
|
await this.removeRemoteFile(config);
|
|
652
654
|
removed.push(config.id);
|
|
653
655
|
}));
|
|
@@ -662,15 +664,43 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
662
664
|
}
|
|
663
665
|
async pushRemoteFile(config, log = true) {
|
|
664
666
|
const spinner = ora();
|
|
667
|
+
// A file the app already has keeps deploying under its name
|
|
668
|
+
const unloadable = isUnloadableComponentFile(config.filePath);
|
|
669
|
+
const pushedBefore = this.app?.configs?.some((remote) => remote.filePath === config.filePath);
|
|
670
|
+
if (unloadable && !pushedBefore) {
|
|
671
|
+
log &&
|
|
672
|
+
spinner.fail(`${config.filePath} would never load: name a component with letters, digits and dashes only`);
|
|
673
|
+
this.failedFiles.push(config.filePath);
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
665
676
|
log && spinner.start(`Pushing ${config.filePath}`);
|
|
677
|
+
// A refused push has failed the spinner, and its reasons end the command
|
|
678
|
+
let isRefused = false;
|
|
666
679
|
try {
|
|
667
680
|
const postData = await config.postData();
|
|
668
681
|
if (!postData) {
|
|
669
682
|
spinner.stop();
|
|
670
683
|
return;
|
|
671
684
|
}
|
|
672
|
-
const result = await this.handleRequestErrors(async () => this.postConfigData(postData), () =>
|
|
685
|
+
const result = await this.handleRequestErrors(async () => this.postConfigData(postData), () => {
|
|
686
|
+
isRefused = true;
|
|
687
|
+
log && spinner.fail(`Error pushing ${config.filePath}`);
|
|
688
|
+
});
|
|
673
689
|
log && spinner.succeed(`${this.timestampStyled()} ${config.filePath}`);
|
|
690
|
+
// A config named in its values deploys under that name instead of its
|
|
691
|
+
// file's, and a model as its collection, whatever name it gives
|
|
692
|
+
const deployName = config.type === ConfigType.MODEL
|
|
693
|
+
? postData.values?.collection
|
|
694
|
+
: postData.name;
|
|
695
|
+
const kebabPath = deployName === config.name
|
|
696
|
+
? kebabCaseFilePath(config.filePath)
|
|
697
|
+
: undefined;
|
|
698
|
+
if (log && kebabPath) {
|
|
699
|
+
ora().warn(`${config.filePath} deploys as '${config.name}': use kebab-case: ${kebabPath}`);
|
|
700
|
+
}
|
|
701
|
+
if (log && unloadable) {
|
|
702
|
+
ora().warn(`${config.filePath} never loads: name a component with letters, digits and dashes only`);
|
|
703
|
+
}
|
|
674
704
|
return result;
|
|
675
705
|
}
|
|
676
706
|
catch (error) {
|
|
@@ -686,10 +716,31 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
686
716
|
this.failedFiles.push(config.filePath);
|
|
687
717
|
return;
|
|
688
718
|
}
|
|
719
|
+
if (isRefused) {
|
|
720
|
+
// Each reason names its file, as a batch fails with all of them
|
|
721
|
+
this.error(error.message
|
|
722
|
+
.split('\n')
|
|
723
|
+
.map((reason) => `${config.filePath}: ${reason}`)
|
|
724
|
+
.join('\n'));
|
|
725
|
+
}
|
|
689
726
|
log && spinner.fail(error.message);
|
|
690
727
|
throw error;
|
|
691
728
|
}
|
|
692
729
|
}
|
|
730
|
+
// Runs pushes or removals together and, when some fail, fails once with
|
|
731
|
+
// the reasons of each of them, not only the first
|
|
732
|
+
async runTogether(tasks) {
|
|
733
|
+
const results = await Promise.allSettled(tasks);
|
|
734
|
+
const failures = results.flatMap((result) => result.status === 'rejected' ? [result.reason] : []);
|
|
735
|
+
if (failures.length === 1) {
|
|
736
|
+
throw failures[0];
|
|
737
|
+
}
|
|
738
|
+
if (failures.length > 1) {
|
|
739
|
+
this.error(failures
|
|
740
|
+
.map((failure) => failure?.message ?? String(failure))
|
|
741
|
+
.join('\n'));
|
|
742
|
+
}
|
|
743
|
+
}
|
|
693
744
|
async removeLocalFile(config, log = true) {
|
|
694
745
|
if (!config.fileData) {
|
|
695
746
|
return;
|
|
@@ -709,29 +760,6 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
709
760
|
spinner.warn(`${this.timestampStyled()} ${style.strike(config.filePath)}`);
|
|
710
761
|
return result;
|
|
711
762
|
}
|
|
712
|
-
showErrors(errors, spinnerError) {
|
|
713
|
-
const actualErrors = Object.keys(errors).filter((err) => Object.prototype.hasOwnProperty.call(errors, err));
|
|
714
|
-
if (spinnerError) {
|
|
715
|
-
spinnerError();
|
|
716
|
-
}
|
|
717
|
-
else {
|
|
718
|
-
this.logError(inflect('Error', actualErrors.length));
|
|
719
|
-
}
|
|
720
|
-
for (const err of actualErrors) {
|
|
721
|
-
if (!errors[err]?.message)
|
|
722
|
-
continue;
|
|
723
|
-
// we need to display `id` instead of `private_id`
|
|
724
|
-
// developers don't have any knowledge of private ids
|
|
725
|
-
const displayErr = err === 'private_id' ? 'id' : err;
|
|
726
|
-
this.logError([
|
|
727
|
-
' -',
|
|
728
|
-
`${displayErr}:`.toLowerCase().replace(/^error:/, ''),
|
|
729
|
-
errors[err].message,
|
|
730
|
-
]
|
|
731
|
-
.filter(Boolean)
|
|
732
|
-
.join(' '));
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
763
|
storefrontFrontendUrl(storeId, storefront, branchId, preview = true) {
|
|
736
764
|
const storefrontSlug = storefront && preview
|
|
737
765
|
? `${storeId}--${storefront.id.toLowerCase()}--preview`
|
package/oclif.manifest.json
CHANGED
|
@@ -721,6 +721,126 @@
|
|
|
721
721
|
"_uninstall.js"
|
|
722
722
|
]
|
|
723
723
|
},
|
|
724
|
+
"app:action": {
|
|
725
|
+
"aliases": [],
|
|
726
|
+
"args": {
|
|
727
|
+
"id": {
|
|
728
|
+
"description": "id of the action, as declared in content or settings",
|
|
729
|
+
"name": "id",
|
|
730
|
+
"required": true
|
|
731
|
+
}
|
|
732
|
+
},
|
|
733
|
+
"description": "Runs a function action of the app as the logged-in dashboard user, the way a click in the dashboard does. The action is looked up in the app's content and settings as pushed.\n\nA record action or action field needs --record, and a bulk action --ids or --all. Pass the values of the action's modal with --values. When the same id is declared in more than one place, pick one with --collection, --view, --settings or --source.",
|
|
734
|
+
"examples": [
|
|
735
|
+
"swell app action sync_now",
|
|
736
|
+
"swell app action ship --record 64e8dfb633c44a0039477251",
|
|
737
|
+
"swell app action ship --record 64e8dfb633c44a0039477251 --values '{\"carrier\":\"ups\"}'",
|
|
738
|
+
"swell app action ship-selected --ids 64e8dfb633c44a0039477251,64e8dfb633c44a0039477252",
|
|
739
|
+
"swell app action ship --collection shipments --view edit --record 64e8dfb633c44a0039477251",
|
|
740
|
+
"swell app action export --source bulk --all"
|
|
741
|
+
],
|
|
742
|
+
"flags": {
|
|
743
|
+
"app-path": {
|
|
744
|
+
"description": "Path to your app directory",
|
|
745
|
+
"name": "app-path",
|
|
746
|
+
"hasDynamicHelp": false,
|
|
747
|
+
"multiple": false,
|
|
748
|
+
"type": "option"
|
|
749
|
+
},
|
|
750
|
+
"all": {
|
|
751
|
+
"description": "run a bulk action on all records its view lists with no filters set, as selecting all in the dashboard does",
|
|
752
|
+
"exclusive": [
|
|
753
|
+
"ids"
|
|
754
|
+
],
|
|
755
|
+
"name": "all",
|
|
756
|
+
"allowNo": false,
|
|
757
|
+
"type": "boolean"
|
|
758
|
+
},
|
|
759
|
+
"collection": {
|
|
760
|
+
"description": "collection of the content that declares the action, or the model's name for a collection of the app",
|
|
761
|
+
"name": "collection",
|
|
762
|
+
"hasDynamicHelp": false,
|
|
763
|
+
"multiple": false,
|
|
764
|
+
"type": "option"
|
|
765
|
+
},
|
|
766
|
+
"ids": {
|
|
767
|
+
"description": "comma-separated ids of the records a bulk action runs on",
|
|
768
|
+
"exclusive": [
|
|
769
|
+
"all"
|
|
770
|
+
],
|
|
771
|
+
"name": "ids",
|
|
772
|
+
"hasDynamicHelp": false,
|
|
773
|
+
"multiple": false,
|
|
774
|
+
"type": "option"
|
|
775
|
+
},
|
|
776
|
+
"live": {
|
|
777
|
+
"description": "run in the live environment instead of test",
|
|
778
|
+
"name": "live",
|
|
779
|
+
"allowNo": false,
|
|
780
|
+
"type": "boolean"
|
|
781
|
+
},
|
|
782
|
+
"record": {
|
|
783
|
+
"description": "id of the record a record action or action field runs on",
|
|
784
|
+
"name": "record",
|
|
785
|
+
"hasDynamicHelp": false,
|
|
786
|
+
"multiple": false,
|
|
787
|
+
"type": "option"
|
|
788
|
+
},
|
|
789
|
+
"settings": {
|
|
790
|
+
"description": "name of the settings that declare the action",
|
|
791
|
+
"name": "settings",
|
|
792
|
+
"hasDynamicHelp": false,
|
|
793
|
+
"multiple": false,
|
|
794
|
+
"type": "option"
|
|
795
|
+
},
|
|
796
|
+
"source": {
|
|
797
|
+
"description": "where the action is declared: list or record (a view's actions), bulk (a view's bulk actions), field (an action field) or settings (a settings action)",
|
|
798
|
+
"name": "source",
|
|
799
|
+
"hasDynamicHelp": false,
|
|
800
|
+
"multiple": false,
|
|
801
|
+
"options": [
|
|
802
|
+
"list",
|
|
803
|
+
"record",
|
|
804
|
+
"bulk",
|
|
805
|
+
"field",
|
|
806
|
+
"settings"
|
|
807
|
+
],
|
|
808
|
+
"type": "option"
|
|
809
|
+
},
|
|
810
|
+
"values": {
|
|
811
|
+
"description": "values of the action's modal fields, as JSON",
|
|
812
|
+
"name": "values",
|
|
813
|
+
"hasDynamicHelp": false,
|
|
814
|
+
"multiple": false,
|
|
815
|
+
"type": "option"
|
|
816
|
+
},
|
|
817
|
+
"view": {
|
|
818
|
+
"description": "id of the content view that declares the action",
|
|
819
|
+
"name": "view",
|
|
820
|
+
"hasDynamicHelp": false,
|
|
821
|
+
"multiple": false,
|
|
822
|
+
"type": "option"
|
|
823
|
+
}
|
|
824
|
+
},
|
|
825
|
+
"hasDynamicHelp": false,
|
|
826
|
+
"hiddenAliases": [],
|
|
827
|
+
"id": "app:action",
|
|
828
|
+
"pluginAlias": "@swell/cli",
|
|
829
|
+
"pluginName": "@swell/cli",
|
|
830
|
+
"pluginType": "core",
|
|
831
|
+
"strict": true,
|
|
832
|
+
"summary": "Run an app action from the command line.",
|
|
833
|
+
"enableJsonFlag": false,
|
|
834
|
+
"requiresSwellConfig": true,
|
|
835
|
+
"delayOrientation": false,
|
|
836
|
+
"isESM": true,
|
|
837
|
+
"relativePath": [
|
|
838
|
+
"dist",
|
|
839
|
+
"commands",
|
|
840
|
+
"app",
|
|
841
|
+
"action.js"
|
|
842
|
+
]
|
|
843
|
+
},
|
|
724
844
|
"app:delete": {
|
|
725
845
|
"aliases": [],
|
|
726
846
|
"args": {},
|
|
@@ -1237,7 +1357,7 @@
|
|
|
1237
1357
|
"name": "file"
|
|
1238
1358
|
}
|
|
1239
1359
|
},
|
|
1240
|
-
"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), screenshots (assets/screenshots/),\n
|
|
1360
|
+
"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), screenshots (assets/screenshots/),\n DESCRIPTION.md, 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\nPushing anything under frontend/ also builds and deploys the app frontend, so\nthe deployed frontend matches what was pushed. Use --no-deploy to skip it.\n\nApp file directories:\nassets/\ncontent/\nfrontend/\ncomponents/\nfunctions/\nmodels/\nnotifications/\nsettings/\ntheme/\nwebhooks/",
|
|
1241
1361
|
"examples": [
|
|
1242
1362
|
"swell app push",
|
|
1243
1363
|
"swell app push content",
|
|
@@ -1968,12 +2088,13 @@
|
|
|
1968
2088
|
},
|
|
1969
2089
|
"trigger": {
|
|
1970
2090
|
"default": "",
|
|
1971
|
-
"description": "cron | model | route | workflow",
|
|
2091
|
+
"description": "cron | model | route | action | workflow",
|
|
1972
2092
|
"name": "trigger",
|
|
1973
2093
|
"options": [
|
|
1974
2094
|
"cron",
|
|
1975
2095
|
"model",
|
|
1976
2096
|
"route",
|
|
2097
|
+
"action",
|
|
1977
2098
|
"workflow"
|
|
1978
2099
|
]
|
|
1979
2100
|
}
|
|
@@ -1983,6 +2104,7 @@
|
|
|
1983
2104
|
"$ swell create function order-handler.ts model -e order.created,order.updated -y",
|
|
1984
2105
|
"$ swell create function cleanup.ts cron -s \"0 0 * * *\" -y",
|
|
1985
2106
|
"$ swell create function api-endpoint.ts route -r public -y",
|
|
2107
|
+
"$ swell create function mark-shipped.ts action -y",
|
|
1986
2108
|
"$ swell create function run-import.ts --type workflow -y",
|
|
1987
2109
|
"$ swell create function run-import.ts workflow -y"
|
|
1988
2110
|
],
|
|
@@ -2086,6 +2208,11 @@
|
|
|
2086
2208
|
"flag": "-r, --route=<option>",
|
|
2087
2209
|
"description": "Access: public (default) | private"
|
|
2088
2210
|
},
|
|
2211
|
+
{
|
|
2212
|
+
"name": "action",
|
|
2213
|
+
"flag": "",
|
|
2214
|
+
"description": "Runs from a dashboard action"
|
|
2215
|
+
},
|
|
2089
2216
|
{
|
|
2090
2217
|
"name": "workflow",
|
|
2091
2218
|
"flag": "--type=workflow",
|
|
@@ -2144,7 +2271,8 @@
|
|
|
2144
2271
|
"examples": [
|
|
2145
2272
|
"$ swell create model",
|
|
2146
2273
|
"$ swell create model products -y",
|
|
2147
|
-
"$ swell create model visitors -f title:string,photo:
|
|
2274
|
+
"$ swell create model visitors -f title:string,photo:file -l \"Visitors\" -y",
|
|
2275
|
+
"$ swell create model reviews -f owner:link:accounts,tags:array:string -y"
|
|
2148
2276
|
],
|
|
2149
2277
|
"flags": {
|
|
2150
2278
|
"app-path": {
|
|
@@ -2174,7 +2302,7 @@
|
|
|
2174
2302
|
},
|
|
2175
2303
|
"fields": {
|
|
2176
2304
|
"char": "f",
|
|
2177
|
-
"description": "Fields as id:type pairs (e.g., title:string,
|
|
2305
|
+
"description": "Fields as id:type pairs, id:link:<model> or id:array:<type> (e.g., title:string,owner:link:accounts)",
|
|
2178
2306
|
"name": "fields",
|
|
2179
2307
|
"default": "",
|
|
2180
2308
|
"hasDynamicHelp": false,
|
|
@@ -2475,7 +2603,7 @@
|
|
|
2475
2603
|
"examples": [
|
|
2476
2604
|
"$ swell create webhook",
|
|
2477
2605
|
"$ swell create webhook order-sync -u https://example.com/hook -e order.created -y",
|
|
2478
|
-
"$ swell create webhook payment-handler -u https://api.example.com/payments -e payment.succeeded,payment.failed --enabled -y"
|
|
2606
|
+
"$ swell create webhook payment-handler -u https://api.example.com/payments -e payment.succeeded,payment.failed --no-enabled -y"
|
|
2479
2607
|
],
|
|
2480
2608
|
"flags": {
|
|
2481
2609
|
"app-path": {
|
|
@@ -2513,9 +2641,9 @@
|
|
|
2513
2641
|
"type": "option"
|
|
2514
2642
|
},
|
|
2515
2643
|
"enabled": {
|
|
2516
|
-
"description": "Enable webhook (default:
|
|
2644
|
+
"description": "Enable webhook (default: true)",
|
|
2517
2645
|
"name": "enabled",
|
|
2518
|
-
"allowNo":
|
|
2646
|
+
"allowNo": true,
|
|
2519
2647
|
"type": "boolean"
|
|
2520
2648
|
},
|
|
2521
2649
|
"overwrite": {
|
|
@@ -2551,6 +2679,68 @@
|
|
|
2551
2679
|
"webhook.js"
|
|
2552
2680
|
]
|
|
2553
2681
|
},
|
|
2682
|
+
"inspect:components": {
|
|
2683
|
+
"aliases": [],
|
|
2684
|
+
"args": {
|
|
2685
|
+
"identifier": {
|
|
2686
|
+
"description": "Resource identifier — see \"Identifier forms\" below.",
|
|
2687
|
+
"name": "identifier",
|
|
2688
|
+
"required": false
|
|
2689
|
+
}
|
|
2690
|
+
},
|
|
2691
|
+
"description": "Lists the components of installed apps, grouped by app. Pass --app=<slug> or --app=. (current swell.json) to scope.\n\nList output: paste-back key + the targets the component renders in and the extension it belongs to.\n\nPass an identifier to view a single component config as JSON.\n\nIdentifier forms:\n app.<app>.<name> — full paste-back key (list column 1)\n <name> — requires --app= scope\n <24-char id> — any scope\n",
|
|
2692
|
+
"examples": [
|
|
2693
|
+
"swell inspect components",
|
|
2694
|
+
"swell inspect components --app=my-app",
|
|
2695
|
+
"swell inspect components app.my-app.card",
|
|
2696
|
+
"swell inspect components card --app=my-app",
|
|
2697
|
+
"swell inspect components --live"
|
|
2698
|
+
],
|
|
2699
|
+
"flags": {
|
|
2700
|
+
"app": {
|
|
2701
|
+
"description": "Filter by app slug, or \".\" for current swell.json.",
|
|
2702
|
+
"name": "app",
|
|
2703
|
+
"hasDynamicHelp": false,
|
|
2704
|
+
"multiple": false,
|
|
2705
|
+
"type": "option"
|
|
2706
|
+
},
|
|
2707
|
+
"live": {
|
|
2708
|
+
"description": "Use live environment (default: test).",
|
|
2709
|
+
"name": "live",
|
|
2710
|
+
"allowNo": false,
|
|
2711
|
+
"type": "boolean"
|
|
2712
|
+
},
|
|
2713
|
+
"json": {
|
|
2714
|
+
"description": "Emit pure JSON without the \"Next steps\" footer. Detail mode only.",
|
|
2715
|
+
"name": "json",
|
|
2716
|
+
"allowNo": false,
|
|
2717
|
+
"type": "boolean"
|
|
2718
|
+
},
|
|
2719
|
+
"yes": {
|
|
2720
|
+
"char": "y",
|
|
2721
|
+
"description": "No-op; accepted for agent compatibility.",
|
|
2722
|
+
"hidden": true,
|
|
2723
|
+
"name": "yes",
|
|
2724
|
+
"allowNo": false,
|
|
2725
|
+
"type": "boolean"
|
|
2726
|
+
}
|
|
2727
|
+
},
|
|
2728
|
+
"hasDynamicHelp": false,
|
|
2729
|
+
"hiddenAliases": [],
|
|
2730
|
+
"id": "inspect:components",
|
|
2731
|
+
"pluginAlias": "@swell/cli",
|
|
2732
|
+
"pluginName": "@swell/cli",
|
|
2733
|
+
"pluginType": "core",
|
|
2734
|
+
"strict": true,
|
|
2735
|
+
"summary": "Components with their targets.",
|
|
2736
|
+
"isESM": true,
|
|
2737
|
+
"relativePath": [
|
|
2738
|
+
"dist",
|
|
2739
|
+
"commands",
|
|
2740
|
+
"inspect",
|
|
2741
|
+
"components.js"
|
|
2742
|
+
]
|
|
2743
|
+
},
|
|
2554
2744
|
"inspect:content": {
|
|
2555
2745
|
"aliases": [],
|
|
2556
2746
|
"args": {
|
|
@@ -2678,6 +2868,67 @@
|
|
|
2678
2868
|
"extensions.js"
|
|
2679
2869
|
]
|
|
2680
2870
|
},
|
|
2871
|
+
"inspect:frontend": {
|
|
2872
|
+
"aliases": [],
|
|
2873
|
+
"args": {
|
|
2874
|
+
"identifier": {
|
|
2875
|
+
"description": "Resource identifier — see \"Identifier forms\" below.",
|
|
2876
|
+
"name": "identifier",
|
|
2877
|
+
"required": false
|
|
2878
|
+
}
|
|
2879
|
+
},
|
|
2880
|
+
"description": "Lists the frontends of installed apps. Pass --app=<slug> or --app=. (current swell.json) to scope.\n\nList output: paste-back key + hosting (managed or self-hosted), framework, and the address the store serves the frontend at.\n\nPass an identifier to view an app's frontend as JSON: the app's frontend selection (package or self-hosted URL) with its installation and address.\n\nIdentifier forms:\n app.<app> — full paste-back key (list column 1)\n <app> — the app's slug\n <24-char id> — the app's id\n",
|
|
2881
|
+
"examples": [
|
|
2882
|
+
"swell inspect frontend",
|
|
2883
|
+
"swell inspect frontend --app=.",
|
|
2884
|
+
"swell inspect frontend app.my-app",
|
|
2885
|
+
"swell inspect frontend --live"
|
|
2886
|
+
],
|
|
2887
|
+
"flags": {
|
|
2888
|
+
"app": {
|
|
2889
|
+
"description": "Filter by app slug, or \".\" for current swell.json.",
|
|
2890
|
+
"name": "app",
|
|
2891
|
+
"hasDynamicHelp": false,
|
|
2892
|
+
"multiple": false,
|
|
2893
|
+
"type": "option"
|
|
2894
|
+
},
|
|
2895
|
+
"live": {
|
|
2896
|
+
"description": "Use live environment (default: test).",
|
|
2897
|
+
"name": "live",
|
|
2898
|
+
"allowNo": false,
|
|
2899
|
+
"type": "boolean"
|
|
2900
|
+
},
|
|
2901
|
+
"json": {
|
|
2902
|
+
"description": "Emit pure JSON without the \"Next steps\" footer. Detail mode only.",
|
|
2903
|
+
"name": "json",
|
|
2904
|
+
"allowNo": false,
|
|
2905
|
+
"type": "boolean"
|
|
2906
|
+
},
|
|
2907
|
+
"yes": {
|
|
2908
|
+
"char": "y",
|
|
2909
|
+
"description": "No-op; accepted for agent compatibility.",
|
|
2910
|
+
"hidden": true,
|
|
2911
|
+
"name": "yes",
|
|
2912
|
+
"allowNo": false,
|
|
2913
|
+
"type": "boolean"
|
|
2914
|
+
}
|
|
2915
|
+
},
|
|
2916
|
+
"hasDynamicHelp": false,
|
|
2917
|
+
"hiddenAliases": [],
|
|
2918
|
+
"id": "inspect:frontend",
|
|
2919
|
+
"pluginAlias": "@swell/cli",
|
|
2920
|
+
"pluginName": "@swell/cli",
|
|
2921
|
+
"pluginType": "core",
|
|
2922
|
+
"strict": true,
|
|
2923
|
+
"summary": "App frontends with hosting and address.",
|
|
2924
|
+
"isESM": true,
|
|
2925
|
+
"relativePath": [
|
|
2926
|
+
"dist",
|
|
2927
|
+
"commands",
|
|
2928
|
+
"inspect",
|
|
2929
|
+
"frontend.js"
|
|
2930
|
+
]
|
|
2931
|
+
},
|
|
2681
2932
|
"inspect:functions": {
|
|
2682
2933
|
"aliases": [],
|
|
2683
2934
|
"args": {
|
|
@@ -2687,7 +2938,7 @@
|
|
|
2687
2938
|
"required": false
|
|
2688
2939
|
}
|
|
2689
2940
|
},
|
|
2690
|
-
"description": "Lists functions across all apps, grouped by app. Pass --app=<slug> or --app=. (current swell.json) to scope.\n\nList output: paste-back key + status (disabled, trigger, next cron run, last
|
|
2941
|
+
"description": "Lists functions across all apps, grouped by app. Pass --app=<slug> or --app=. (current swell.json) to scope.\n\nList output: paste-back key + status (disabled or auto-disabled, failing since and failure count, the date it gets disabled, trigger, next cron run) and whether its app is inactive, which stops all of its functions. The detail view also shows the last failed delivery.\n\nPass an identifier to view a single record as JSON.\n\nIdentifier forms:\n app.<app>.<name> — full paste-back key (list column 1)\n <name> — requires --app= scope\n <24-char id> — any scope\n",
|
|
2691
2942
|
"examples": [
|
|
2692
2943
|
"swell inspect functions",
|
|
2693
2944
|
"swell inspect functions --app=my-app",
|
|
@@ -2751,7 +3002,9 @@
|
|
|
2751
3002
|
"swell inspect functions app.my-app.payment-sync",
|
|
2752
3003
|
"swell inspect workflow-runs --workflow app.my-app.run-import --status active",
|
|
2753
3004
|
"swell inspect notifications com.orders.receipt.v2",
|
|
2754
|
-
"swell inspect settings app.my-app"
|
|
3005
|
+
"swell inspect settings app.my-app",
|
|
3006
|
+
"swell inspect components --app=.",
|
|
3007
|
+
"swell inspect frontend app.my-app"
|
|
2755
3008
|
],
|
|
2756
3009
|
"flags": {},
|
|
2757
3010
|
"hasDynamicHelp": false,
|
|
@@ -3738,5 +3991,5 @@
|
|
|
3738
3991
|
]
|
|
3739
3992
|
}
|
|
3740
3993
|
},
|
|
3741
|
-
"version": "2.9.
|
|
3994
|
+
"version": "2.9.33"
|
|
3742
3995
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swell/cli",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.33",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Swell's command line interface/utility",
|
|
6
6
|
"keywords": [
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"@npmcli/git": "5.0.3",
|
|
31
31
|
"@oclif/core": "3.7.1",
|
|
32
32
|
"@oclif/plugin-help": "6.0.4",
|
|
33
|
+
"@swell/app-types": "1.3.0",
|
|
33
34
|
"ajv": "8.20.0",
|
|
34
35
|
"ajv-errors": "3.0.0",
|
|
35
36
|
"ajv-formats": "3.0.1",
|