@cxtms/cx-schema 1.7.6 → 1.7.8
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/.claude/skills/cx-core/ref-cli-auth.md +37 -1
- package/.claude/skills/cx-module/SKILL.md +3 -3
- package/.claude/skills/cx-workflow/SKILL.md +6 -6
- package/dist/cli.js +289 -2
- package/dist/cli.js.map +1 -1
- package/dist/validator.d.ts +4 -0
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +26 -0
- package/dist/validator.js.map +1 -1
- package/package.json +1 -1
- package/schemas/components/appComponent.json +8 -0
- package/schemas/components/module.json +29 -0
- package/templates/module-configuration.yaml +5 -16
|
@@ -61,7 +61,7 @@ npx cxtms orgs use <orgId>
|
|
|
61
61
|
npx cxtms orgs use
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
The active org is cached in the session file and used by all server commands.
|
|
64
|
+
The active org is cached in the session file and used by all server commands. **Always pass `--org <id>` on deploy/undeploy/publish/execute/logs commands** to avoid the interactive org picker blocking automation.
|
|
65
65
|
|
|
66
66
|
## Session Resolution
|
|
67
67
|
|
|
@@ -85,3 +85,39 @@ npx cxtms publish --org 42
|
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
Validates all YAML files first, then pushes modules and workflows to the server. Skips files with validation errors and reports results.
|
|
88
|
+
|
|
89
|
+
## App Manifest Management
|
|
90
|
+
|
|
91
|
+
Server-side app manifest operations — install from git, publish changes to git, and list installed apps.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Install/refresh app from its git repository into the CX server
|
|
95
|
+
npx cxtms app install
|
|
96
|
+
|
|
97
|
+
# Force reinstall even if same version is already installed
|
|
98
|
+
npx cxtms app install --force
|
|
99
|
+
|
|
100
|
+
# Install from a specific branch
|
|
101
|
+
npx cxtms app install --branch develop
|
|
102
|
+
|
|
103
|
+
# Install but skip modules that have unpublished local changes
|
|
104
|
+
npx cxtms app install --skip-changed
|
|
105
|
+
|
|
106
|
+
# Publish server changes to git (creates a PR)
|
|
107
|
+
npx cxtms app publish
|
|
108
|
+
|
|
109
|
+
# Publish with a custom commit message
|
|
110
|
+
npx cxtms app publish --message "Add new shipping module"
|
|
111
|
+
|
|
112
|
+
# Force publish all modules and workflows (not just changed ones)
|
|
113
|
+
npx cxtms app publish --force
|
|
114
|
+
|
|
115
|
+
# List installed app manifests on the server
|
|
116
|
+
npx cxtms app list
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**`app install`** reads `repository` and `branch` from `app.yaml`, downloads the repo on the server side, and installs/updates all modules and workflows. Use `--force` to reinstall even if the version hasn't changed. Use `--skip-changed` to preserve modules with unpublished changes.
|
|
120
|
+
|
|
121
|
+
**`app publish`** takes the current server state and publishes it to git by creating a PR. The server increments the version, creates a publish branch, commits all module/workflow YAML files, and opens a pull request to the target branch.
|
|
122
|
+
|
|
123
|
+
**`app list`** shows all installed app manifests with their version, status flags (disabled, unpublished changes, update available), and repository info.
|
|
@@ -18,9 +18,9 @@ You are a CargoXplorer module YAML builder. You generate schema-valid YAML for C
|
|
|
18
18
|
- **List schemas**: `npx cxtms list`
|
|
19
19
|
- **Extract**: `npx cxtms extract <source> <component> --to <target>` — move components between modules
|
|
20
20
|
- **Feature folder**: `npx cxtms create module <name> --template <template> --feature <feature-name>`
|
|
21
|
-
- **Deploy to server**: `npx cxtms appmodule deploy <file.yaml>` — creates or updates module on the CX server
|
|
22
|
-
- **Undeploy from server**: `npx cxtms appmodule undeploy <appModuleId>` — removes a module by UUID
|
|
23
|
-
- **Publish all**: `npx cxtms publish [--feature <name>]
|
|
21
|
+
- **Deploy to server**: `npx cxtms appmodule deploy <file.yaml> --org <id>` — creates or updates module on the CX server
|
|
22
|
+
- **Undeploy from server**: `npx cxtms appmodule undeploy <appModuleId> --org <id>` — removes a module by UUID
|
|
23
|
+
- **Publish all**: `npx cxtms publish [--feature <name>] --org <id>` — push all modules and workflows to the server
|
|
24
24
|
|
|
25
25
|
## Generation Workflow
|
|
26
26
|
|
|
@@ -16,12 +16,12 @@ You are a CargoXplorer workflow YAML builder. You generate schema-valid YAML for
|
|
|
16
16
|
- **Examples**: `npx cxtms example <task>` — show example YAML for a task
|
|
17
17
|
- **List schemas**: `npx cxtms list --type workflow` — shows all available task schemas in the Tasks section
|
|
18
18
|
- **Feature folder**: `npx cxtms create workflow <name> --template <template> --feature <feature-name>`
|
|
19
|
-
- **Deploy to server**: `npx cxtms workflow deploy <file.yaml>` — creates or updates workflow on the CX server
|
|
20
|
-
- **Undeploy from server**: `npx cxtms workflow undeploy <workflowId>` — removes a workflow by UUID
|
|
21
|
-
- **Execute**: `npx cxtms workflow execute <workflowId|file.yaml> [--vars '<json>']` — trigger a workflow execution
|
|
22
|
-
- **List logs**: `npx cxtms workflow logs <workflowId|file.yaml> [--from YYYY-MM-DD] [--to YYYY-MM-DD]` — list executions with log availability
|
|
23
|
-
- **Download log**: `npx cxtms workflow log <executionId> [--json] [--console] [--output <file>]` — download execution log
|
|
24
|
-
- **Publish all**: `npx cxtms publish [--feature <name>]
|
|
19
|
+
- **Deploy to server**: `npx cxtms workflow deploy <file.yaml> --org <id>` — creates or updates workflow on the CX server
|
|
20
|
+
- **Undeploy from server**: `npx cxtms workflow undeploy <workflowId> --org <id>` — removes a workflow by UUID
|
|
21
|
+
- **Execute**: `npx cxtms workflow execute <workflowId|file.yaml> --org <id> [--vars '<json>']` — trigger a workflow execution
|
|
22
|
+
- **List logs**: `npx cxtms workflow logs <workflowId|file.yaml> --org <id> [--from YYYY-MM-DD] [--to YYYY-MM-DD]` — list executions with log availability
|
|
23
|
+
- **Download log**: `npx cxtms workflow log <executionId> --org <id> [--json] [--console] [--output <file>]` — download execution log
|
|
24
|
+
- **Publish all**: `npx cxtms publish [--feature <name>] --org <id>` — push all modules and workflows to the server
|
|
25
25
|
|
|
26
26
|
## Generation Workflow
|
|
27
27
|
|
package/dist/cli.js
CHANGED
|
@@ -117,6 +117,7 @@ ${chalk_1.default.bold.yellow('COMMANDS:')}
|
|
|
117
117
|
${chalk_1.default.green('appmodule')} Manage app modules on a CX server (deploy, undeploy)
|
|
118
118
|
${chalk_1.default.green('workflow')} Manage workflows on a CX server (deploy, undeploy, execute, logs, log)
|
|
119
119
|
${chalk_1.default.green('publish')} Publish all modules and workflows to a CX server
|
|
120
|
+
${chalk_1.default.green('app')} Manage app manifests (install/upgrade from git, publish to git, list)
|
|
120
121
|
${chalk_1.default.green('query')} Run a GraphQL query against the CX server
|
|
121
122
|
${chalk_1.default.green('schema')} Show JSON schema for a component or task
|
|
122
123
|
${chalk_1.default.green('example')} Show example YAML for a component or task
|
|
@@ -147,6 +148,10 @@ ${chalk_1.default.bold.yellow('OPTIONS:')}
|
|
|
147
148
|
${chalk_1.default.green('--output <file>')} Save workflow log to file (or -o)
|
|
148
149
|
${chalk_1.default.green('--console')} Print workflow log to stdout
|
|
149
150
|
${chalk_1.default.green('--json')} Download JSON log instead of text
|
|
151
|
+
${chalk_1.default.green('-m, --message <msg>')} Commit message for app publish
|
|
152
|
+
${chalk_1.default.green('-b, --branch <branch>')} Branch override for app install/publish
|
|
153
|
+
${chalk_1.default.green('--force')} Force install (even if same version) or publish all
|
|
154
|
+
${chalk_1.default.green('--skip-changed')} Skip modules with unpublished changes during install
|
|
150
155
|
|
|
151
156
|
${chalk_1.default.bold.yellow('VALIDATION EXAMPLES:')}
|
|
152
157
|
${chalk_1.default.gray('# Validate a module YAML file')}
|
|
@@ -288,6 +293,35 @@ ${chalk_1.default.bold.yellow('PUBLISH COMMANDS:')}
|
|
|
288
293
|
${chalk_1.default.gray('# Publish with explicit org ID')}
|
|
289
294
|
${chalk_1.default.cyan(`${PROGRAM_NAME} publish --org 42`)}
|
|
290
295
|
|
|
296
|
+
${chalk_1.default.bold.yellow('APP COMMANDS:')}
|
|
297
|
+
${chalk_1.default.gray('# Install/refresh app from git repository into the CX server')}
|
|
298
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app install`)}
|
|
299
|
+
|
|
300
|
+
${chalk_1.default.gray('# Force reinstall even if same version')}
|
|
301
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app install --force`)}
|
|
302
|
+
|
|
303
|
+
${chalk_1.default.gray('# Install from a specific branch')}
|
|
304
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app install --branch develop`)}
|
|
305
|
+
|
|
306
|
+
${chalk_1.default.gray('# Install but skip modules that have local changes')}
|
|
307
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app install --skip-changed`)}
|
|
308
|
+
|
|
309
|
+
${chalk_1.default.gray('# Upgrade app from git (alias for install)')}
|
|
310
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app upgrade`)}
|
|
311
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app upgrade --force`)}
|
|
312
|
+
|
|
313
|
+
${chalk_1.default.gray('# Publish server changes to git (creates a PR)')}
|
|
314
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app publish`)}
|
|
315
|
+
|
|
316
|
+
${chalk_1.default.gray('# Publish with a custom commit message')}
|
|
317
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app publish --message "Add new shipping module"`)}
|
|
318
|
+
|
|
319
|
+
${chalk_1.default.gray('# Force publish all modules and workflows')}
|
|
320
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app publish --force`)}
|
|
321
|
+
|
|
322
|
+
${chalk_1.default.gray('# List installed app manifests on the server')}
|
|
323
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} app list`)}
|
|
324
|
+
|
|
291
325
|
${chalk_1.default.bold.yellow('QUERY COMMANDS:')}
|
|
292
326
|
${chalk_1.default.gray('# Run an inline GraphQL query')}
|
|
293
327
|
${chalk_1.default.cyan(`${PROGRAM_NAME} query '{ organizations(take: 5) { items { organizationId companyName } } }'`)}
|
|
@@ -840,6 +874,23 @@ function applyFieldsToForm(form, fields) {
|
|
|
840
874
|
}
|
|
841
875
|
}
|
|
842
876
|
}
|
|
877
|
+
function applyFieldsToConfiguration(layout, fields) {
|
|
878
|
+
// Configuration fields are stored under customValues, so prefix all field names
|
|
879
|
+
const configFields = fields.map(f => ({
|
|
880
|
+
component: 'field',
|
|
881
|
+
name: `customValues.${f.name}`,
|
|
882
|
+
props: {
|
|
883
|
+
type: f.type,
|
|
884
|
+
label: { 'en-US': f.label || fieldNameToLabel(f.name) },
|
|
885
|
+
...(f.required ? { required: true } : {})
|
|
886
|
+
}
|
|
887
|
+
}));
|
|
888
|
+
if (!layout.children)
|
|
889
|
+
layout.children = [];
|
|
890
|
+
layout.children.push(...configFields);
|
|
891
|
+
// Update defaultValue in configurations if present
|
|
892
|
+
// (handled separately since configurations is a top-level key)
|
|
893
|
+
}
|
|
843
894
|
function findDataGridComponents(obj) {
|
|
844
895
|
const grids = [];
|
|
845
896
|
if (!obj || typeof obj !== 'object')
|
|
@@ -967,9 +1018,16 @@ function applyCreateOptions(content, optionsArg) {
|
|
|
967
1018
|
if (!doc)
|
|
968
1019
|
throw new Error('Failed to parse template YAML for --options processing');
|
|
969
1020
|
let applied = false;
|
|
1021
|
+
const isConfiguration = Array.isArray(doc.configurations);
|
|
970
1022
|
if (doc.components && Array.isArray(doc.components)) {
|
|
971
1023
|
for (const comp of doc.components) {
|
|
972
|
-
// Apply to
|
|
1024
|
+
// Apply to configuration templates (fields go directly into layout children)
|
|
1025
|
+
if (isConfiguration && comp.layout) {
|
|
1026
|
+
applyFieldsToConfiguration(comp.layout, fields);
|
|
1027
|
+
applied = true;
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
// Apply to form components
|
|
973
1031
|
const forms = findFormComponents(comp);
|
|
974
1032
|
for (const form of forms) {
|
|
975
1033
|
applyFieldsToForm(form, fields);
|
|
@@ -997,6 +1055,18 @@ function applyCreateOptions(content, optionsArg) {
|
|
|
997
1055
|
applyFieldsToEntities(doc, fields, opts.entityName);
|
|
998
1056
|
applied = true;
|
|
999
1057
|
}
|
|
1058
|
+
// Apply defaults to configuration defaultValue
|
|
1059
|
+
if (isConfiguration && doc.configurations) {
|
|
1060
|
+
for (const config of doc.configurations) {
|
|
1061
|
+
if (!config.defaultValue)
|
|
1062
|
+
config.defaultValue = {};
|
|
1063
|
+
for (const f of fields) {
|
|
1064
|
+
if (f.default !== undefined) {
|
|
1065
|
+
config.defaultValue[f.name] = f.default;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1000
1070
|
if (!applied) {
|
|
1001
1071
|
console.warn(chalk_1.default.yellow('Warning: --options provided but no form or dataGrid component found in template'));
|
|
1002
1072
|
return content;
|
|
@@ -2763,6 +2833,192 @@ async function runPublish(featureDir, orgOverride) {
|
|
|
2763
2833
|
}
|
|
2764
2834
|
}
|
|
2765
2835
|
// ============================================================================
|
|
2836
|
+
// App Manifest Commands (install from git, publish to git, list)
|
|
2837
|
+
// ============================================================================
|
|
2838
|
+
function readAppYaml() {
|
|
2839
|
+
const appYamlPath = path.join(process.cwd(), 'app.yaml');
|
|
2840
|
+
if (!fs.existsSync(appYamlPath)) {
|
|
2841
|
+
console.error(chalk_1.default.red('Error: app.yaml not found in current directory'));
|
|
2842
|
+
process.exit(2);
|
|
2843
|
+
}
|
|
2844
|
+
return yaml_1.default.parse(fs.readFileSync(appYamlPath, 'utf-8'));
|
|
2845
|
+
}
|
|
2846
|
+
async function runAppInstall(orgOverride, branch, force, skipChanged) {
|
|
2847
|
+
const session = resolveSession();
|
|
2848
|
+
const domain = session.domain;
|
|
2849
|
+
const token = session.access_token;
|
|
2850
|
+
const orgId = await resolveOrgId(domain, token, orgOverride);
|
|
2851
|
+
const appYaml = readAppYaml();
|
|
2852
|
+
const repository = appYaml.repository;
|
|
2853
|
+
if (!repository) {
|
|
2854
|
+
console.error(chalk_1.default.red('Error: app.yaml must have a `repository` field'));
|
|
2855
|
+
process.exit(2);
|
|
2856
|
+
}
|
|
2857
|
+
const repositoryBranch = branch || appYaml.branch || 'main';
|
|
2858
|
+
console.log(chalk_1.default.bold.cyan('\n App Install\n'));
|
|
2859
|
+
console.log(chalk_1.default.gray(` Server: ${new URL(domain).hostname}`));
|
|
2860
|
+
console.log(chalk_1.default.gray(` Org: ${orgId}`));
|
|
2861
|
+
console.log(chalk_1.default.gray(` Repository: ${repository}`));
|
|
2862
|
+
console.log(chalk_1.default.gray(` Branch: ${repositoryBranch}`));
|
|
2863
|
+
if (force)
|
|
2864
|
+
console.log(chalk_1.default.gray(` Force: yes`));
|
|
2865
|
+
if (skipChanged)
|
|
2866
|
+
console.log(chalk_1.default.gray(` Skip changed: yes`));
|
|
2867
|
+
console.log('');
|
|
2868
|
+
try {
|
|
2869
|
+
const data = await graphqlRequest(domain, token, `
|
|
2870
|
+
mutation ($input: InstallAppManifestInput!) {
|
|
2871
|
+
installAppManifest(input: $input) {
|
|
2872
|
+
appManifest {
|
|
2873
|
+
appManifestId
|
|
2874
|
+
name
|
|
2875
|
+
currentVersion
|
|
2876
|
+
isEnabled
|
|
2877
|
+
hasUnpublishedChanges
|
|
2878
|
+
isUpdateAvailable
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
`, {
|
|
2883
|
+
input: {
|
|
2884
|
+
organizationId: orgId,
|
|
2885
|
+
values: {
|
|
2886
|
+
repository,
|
|
2887
|
+
repositoryBranch,
|
|
2888
|
+
force: force || false,
|
|
2889
|
+
skipModulesWithChanges: skipChanged || false,
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
});
|
|
2893
|
+
const manifest = data?.installAppManifest?.appManifest;
|
|
2894
|
+
if (manifest) {
|
|
2895
|
+
console.log(chalk_1.default.green(` ✓ Installed ${manifest.name} v${manifest.currentVersion}`));
|
|
2896
|
+
if (manifest.hasUnpublishedChanges) {
|
|
2897
|
+
console.log(chalk_1.default.yellow(` Has unpublished changes`));
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
else {
|
|
2901
|
+
console.log(chalk_1.default.green(' ✓ Install completed'));
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
catch (e) {
|
|
2905
|
+
console.error(chalk_1.default.red(` ✗ Install failed: ${e.message}`));
|
|
2906
|
+
process.exit(1);
|
|
2907
|
+
}
|
|
2908
|
+
console.log('');
|
|
2909
|
+
}
|
|
2910
|
+
async function runAppPublish(orgOverride, message, branch, force) {
|
|
2911
|
+
const session = resolveSession();
|
|
2912
|
+
const domain = session.domain;
|
|
2913
|
+
const token = session.access_token;
|
|
2914
|
+
const orgId = await resolveOrgId(domain, token, orgOverride);
|
|
2915
|
+
const appYaml = readAppYaml();
|
|
2916
|
+
const appManifestId = appYaml.id;
|
|
2917
|
+
if (!appManifestId) {
|
|
2918
|
+
console.error(chalk_1.default.red('Error: app.yaml must have an `id` field'));
|
|
2919
|
+
process.exit(2);
|
|
2920
|
+
}
|
|
2921
|
+
console.log(chalk_1.default.bold.cyan('\n App Publish\n'));
|
|
2922
|
+
console.log(chalk_1.default.gray(` Server: ${new URL(domain).hostname}`));
|
|
2923
|
+
console.log(chalk_1.default.gray(` Org: ${orgId}`));
|
|
2924
|
+
console.log(chalk_1.default.gray(` App: ${appYaml.name || appManifestId}`));
|
|
2925
|
+
if (message)
|
|
2926
|
+
console.log(chalk_1.default.gray(` Message: ${message}`));
|
|
2927
|
+
if (branch)
|
|
2928
|
+
console.log(chalk_1.default.gray(` Branch: ${branch}`));
|
|
2929
|
+
if (force)
|
|
2930
|
+
console.log(chalk_1.default.gray(` Force: yes`));
|
|
2931
|
+
console.log('');
|
|
2932
|
+
try {
|
|
2933
|
+
const data = await graphqlRequest(domain, token, `
|
|
2934
|
+
mutation ($input: PublishAppManifestInput!) {
|
|
2935
|
+
publishAppManifest(input: $input) {
|
|
2936
|
+
appManifest {
|
|
2937
|
+
appManifestId
|
|
2938
|
+
name
|
|
2939
|
+
currentVersion
|
|
2940
|
+
hasUnpublishedChanges
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
`, {
|
|
2945
|
+
input: {
|
|
2946
|
+
organizationId: orgId,
|
|
2947
|
+
appManifestId,
|
|
2948
|
+
values: {
|
|
2949
|
+
message: message || undefined,
|
|
2950
|
+
branch: branch || undefined,
|
|
2951
|
+
force: force || false,
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
});
|
|
2955
|
+
const manifest = data?.publishAppManifest?.appManifest;
|
|
2956
|
+
if (manifest) {
|
|
2957
|
+
console.log(chalk_1.default.green(` ✓ Published ${manifest.name} v${manifest.currentVersion}`));
|
|
2958
|
+
}
|
|
2959
|
+
else {
|
|
2960
|
+
console.log(chalk_1.default.green(' ✓ Publish completed'));
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
catch (e) {
|
|
2964
|
+
console.error(chalk_1.default.red(` ✗ Publish failed: ${e.message}`));
|
|
2965
|
+
process.exit(1);
|
|
2966
|
+
}
|
|
2967
|
+
console.log('');
|
|
2968
|
+
}
|
|
2969
|
+
async function runAppList(orgOverride) {
|
|
2970
|
+
const session = resolveSession();
|
|
2971
|
+
const domain = session.domain;
|
|
2972
|
+
const token = session.access_token;
|
|
2973
|
+
const orgId = await resolveOrgId(domain, token, orgOverride);
|
|
2974
|
+
console.log(chalk_1.default.bold.cyan('\n App Manifests\n'));
|
|
2975
|
+
console.log(chalk_1.default.gray(` Server: ${new URL(domain).hostname}`));
|
|
2976
|
+
console.log(chalk_1.default.gray(` Org: ${orgId}\n`));
|
|
2977
|
+
try {
|
|
2978
|
+
const data = await graphqlRequest(domain, token, `
|
|
2979
|
+
query ($organizationId: Int!) {
|
|
2980
|
+
appManifests(organizationId: $organizationId) {
|
|
2981
|
+
items {
|
|
2982
|
+
appManifestId
|
|
2983
|
+
name
|
|
2984
|
+
currentVersion
|
|
2985
|
+
isEnabled
|
|
2986
|
+
hasUnpublishedChanges
|
|
2987
|
+
isUpdateAvailable
|
|
2988
|
+
repository
|
|
2989
|
+
repositoryBranch
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
`, { organizationId: orgId });
|
|
2994
|
+
const items = data?.appManifests?.items || [];
|
|
2995
|
+
if (items.length === 0) {
|
|
2996
|
+
console.log(chalk_1.default.gray(' No app manifests installed\n'));
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
for (const app of items) {
|
|
3000
|
+
const flags = [];
|
|
3001
|
+
if (!app.isEnabled)
|
|
3002
|
+
flags.push(chalk_1.default.red('disabled'));
|
|
3003
|
+
if (app.hasUnpublishedChanges)
|
|
3004
|
+
flags.push(chalk_1.default.yellow('unpublished'));
|
|
3005
|
+
if (app.isUpdateAvailable)
|
|
3006
|
+
flags.push(chalk_1.default.cyan('update available'));
|
|
3007
|
+
const flagStr = flags.length > 0 ? ` [${flags.join(', ')}]` : '';
|
|
3008
|
+
console.log(` ${chalk_1.default.bold(app.name)} ${chalk_1.default.gray(`v${app.currentVersion}`)}${flagStr}`);
|
|
3009
|
+
console.log(chalk_1.default.gray(` ID: ${app.appManifestId}`));
|
|
3010
|
+
if (app.repository) {
|
|
3011
|
+
console.log(chalk_1.default.gray(` Repo: ${app.repository} (${app.repositoryBranch || 'main'})`));
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
console.log('');
|
|
3015
|
+
}
|
|
3016
|
+
catch (e) {
|
|
3017
|
+
console.error(chalk_1.default.red(` ✗ Failed to list apps: ${e.message}`));
|
|
3018
|
+
process.exit(1);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
// ============================================================================
|
|
2766
3022
|
// Query Command
|
|
2767
3023
|
// ============================================================================
|
|
2768
3024
|
async function runQuery(queryArg, variables) {
|
|
@@ -3008,7 +3264,7 @@ function parseArgs(args) {
|
|
|
3008
3264
|
reportFormat: 'json'
|
|
3009
3265
|
};
|
|
3010
3266
|
// Check for commands
|
|
3011
|
-
const commands = ['validate', 'schema', 'example', 'list', 'help', 'version', 'report', 'init', 'create', 'extract', 'sync-schemas', 'install-skills', 'update', 'setup-claude', 'login', 'logout', 'pat', 'appmodule', 'orgs', 'workflow', 'publish', 'query'];
|
|
3267
|
+
const commands = ['validate', 'schema', 'example', 'list', 'help', 'version', 'report', 'init', 'create', 'extract', 'sync-schemas', 'install-skills', 'update', 'setup-claude', 'login', 'logout', 'pat', 'appmodule', 'orgs', 'workflow', 'publish', 'query', 'app'];
|
|
3012
3268
|
if (args.length > 0 && commands.includes(args[0])) {
|
|
3013
3269
|
command = args[0];
|
|
3014
3270
|
args = args.slice(1);
|
|
@@ -3108,6 +3364,18 @@ function parseArgs(args) {
|
|
|
3108
3364
|
else if (arg === '--console') {
|
|
3109
3365
|
options.console = true;
|
|
3110
3366
|
}
|
|
3367
|
+
else if (arg === '--message' || arg === '-m') {
|
|
3368
|
+
options.message = args[++i];
|
|
3369
|
+
}
|
|
3370
|
+
else if (arg === '--branch' || arg === '-b') {
|
|
3371
|
+
options.branch = args[++i];
|
|
3372
|
+
}
|
|
3373
|
+
else if (arg === '--force') {
|
|
3374
|
+
options.force = true;
|
|
3375
|
+
}
|
|
3376
|
+
else if (arg === '--skip-changed') {
|
|
3377
|
+
options.skipChanged = true;
|
|
3378
|
+
}
|
|
3111
3379
|
else if (!arg.startsWith('-')) {
|
|
3112
3380
|
files.push(arg);
|
|
3113
3381
|
}
|
|
@@ -4009,6 +4277,25 @@ async function main() {
|
|
|
4009
4277
|
await runPublish(files[0] || options.feature, options.orgId);
|
|
4010
4278
|
process.exit(0);
|
|
4011
4279
|
}
|
|
4280
|
+
// Handle app command (no schemas needed)
|
|
4281
|
+
if (command === 'app') {
|
|
4282
|
+
const sub = files[0];
|
|
4283
|
+
if (sub === 'install' || sub === 'upgrade') {
|
|
4284
|
+
await runAppInstall(options.orgId, options.branch, options.force, options.skipChanged);
|
|
4285
|
+
}
|
|
4286
|
+
else if (sub === 'publish') {
|
|
4287
|
+
await runAppPublish(options.orgId, options.message, options.branch, options.force);
|
|
4288
|
+
}
|
|
4289
|
+
else if (sub === 'list' || !sub) {
|
|
4290
|
+
await runAppList(options.orgId);
|
|
4291
|
+
}
|
|
4292
|
+
else {
|
|
4293
|
+
console.error(chalk_1.default.red(`Unknown app subcommand: ${sub}`));
|
|
4294
|
+
console.error(chalk_1.default.gray(`Usage: ${PROGRAM_NAME} app <install|upgrade|publish|list>`));
|
|
4295
|
+
process.exit(2);
|
|
4296
|
+
}
|
|
4297
|
+
process.exit(0);
|
|
4298
|
+
}
|
|
4012
4299
|
// Handle query command (no schemas needed)
|
|
4013
4300
|
if (command === 'query') {
|
|
4014
4301
|
await runQuery(files[0], options.vars);
|