@cxtms/cx-schema 1.1.1 → 1.2.1
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-workflow/SKILL.md +2 -2
- package/.claude/skills/cx-workflow/ref-utilities.md +21 -0
- package/dist/cli.js +252 -33
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/schemas/workflows/tasks/action-event.json +65 -0
- package/schemas/workflows/tasks/all.json +126 -26
- package/schemas/workflows/tasks/appmodule.json +56 -0
- package/schemas/workflows/tasks/attachment.json +4 -1
- package/schemas/workflows/tasks/authentication.json +72 -0
- package/schemas/workflows/tasks/caching.json +68 -0
- package/schemas/workflows/tasks/charge.json +3 -1
- package/schemas/workflows/tasks/commodity.json +3 -0
- package/schemas/workflows/tasks/contact-address.json +72 -0
- package/schemas/workflows/tasks/contact-payment-method.json +72 -0
- package/schemas/workflows/tasks/edi.json +65 -0
- package/schemas/workflows/tasks/filetransfer.json +102 -0
- package/schemas/workflows/tasks/flow-transition.json +68 -0
- package/schemas/workflows/tasks/httpRequest.json +23 -0
- package/schemas/workflows/tasks/import.json +64 -0
- package/schemas/workflows/tasks/inventory.json +67 -0
- package/schemas/workflows/tasks/movement.json +54 -0
- package/schemas/workflows/tasks/note.json +59 -0
- package/schemas/workflows/tasks/number.json +65 -0
- package/schemas/workflows/tasks/order.json +8 -1
- package/schemas/workflows/tasks/pdf-document.json +60 -0
- package/schemas/workflows/tasks/user.json +70 -0
- package/scripts/postinstall.js +2 -2
|
@@ -9,9 +9,9 @@ You are a CargoXplorer workflow YAML builder. You generate schema-valid YAML for
|
|
|
9
9
|
**IMPORTANT — use `cx-cli` for all workflow operations:**
|
|
10
10
|
- **Scaffold**: `npx cx-cli create workflow <name> --template <template>` — generates a schema-valid YAML file. ALWAYS run this first, then read the generated file, then customize. Do NOT write YAML from scratch or copy templates manually.
|
|
11
11
|
- **Validate**: `npx cx-cli <file.yaml>` — run after every change
|
|
12
|
-
- **Schema lookup**: `npx cx-cli schema <task>` — e.g., `cx-cli schema graphql`, `cx-cli schema foreach`
|
|
12
|
+
- **Schema lookup**: `npx cx-cli schema <task>` — e.g., `cx-cli schema graphql`, `cx-cli schema foreach`, `cx-cli schema action-event`. Schema names use kebab-case file names. Case-insensitive: `ActionEvent` resolves to `action-event`.
|
|
13
13
|
- **Examples**: `npx cx-cli example <task>` — show example YAML for a task
|
|
14
|
-
- **List schemas**: `npx cx-cli list --type workflow`
|
|
14
|
+
- **List schemas**: `npx cx-cli list --type workflow` — shows all available task schemas in the Tasks section
|
|
15
15
|
- **Feature folder**: `npx cx-cli create workflow <name> --template <template> --feature <feature-name>`
|
|
16
16
|
|
|
17
17
|
## Generation Workflow
|
|
@@ -91,6 +91,27 @@ Performs HTTP requests to external APIs.
|
|
|
91
91
|
|
|
92
92
|
Response available at `ActivityName?.CallApi?.result?`.
|
|
93
93
|
|
|
94
|
+
**Action events**: When an HTTP request operates on a specific entity (e.g., sending parcel info for an order), enable `actionEvents` in the inputs so the system can track and notify about the request. Include `eventDataExt` with the entity ID to link the event to the entity.
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
- task: "Utilities/HttpRequest@1"
|
|
98
|
+
name: CallCarrierApi
|
|
99
|
+
inputs:
|
|
100
|
+
actionEvents:
|
|
101
|
+
enabled: true
|
|
102
|
+
eventName: "carrier.sendParcelInfo"
|
|
103
|
+
eventDataExt:
|
|
104
|
+
orderId: "{{ inputs.orderId }}"
|
|
105
|
+
url: "{{ carrierConfig?.baseUrl? }}/api/shipments"
|
|
106
|
+
method: POST
|
|
107
|
+
contentType: "application/json"
|
|
108
|
+
body:
|
|
109
|
+
trackingNumber: "{{ Data?.GetOrder?.order?.trackingNumber? }}"
|
|
110
|
+
outputs:
|
|
111
|
+
- name: result
|
|
112
|
+
mapping: "response?.body?"
|
|
113
|
+
```
|
|
114
|
+
|
|
94
115
|
## Map@1
|
|
95
116
|
|
|
96
117
|
Extracts/reshapes data from variables into new variables.
|
package/dist/cli.js
CHANGED
|
@@ -72,8 +72,9 @@ ${chalk_1.default.bold.yellow('COMMANDS:')}
|
|
|
72
72
|
${chalk_1.default.green('validate')} Validate YAML file(s) ${chalk_1.default.gray('(default command)')}
|
|
73
73
|
${chalk_1.default.green('report')} Generate validation report for multiple files
|
|
74
74
|
${chalk_1.default.green('init')} Initialize a new CX project with app.yaml, README.md, AGENTS.md
|
|
75
|
-
${chalk_1.default.green('create')} Create a new module or
|
|
75
|
+
${chalk_1.default.green('create')} Create a new module, workflow, or task-schema from template
|
|
76
76
|
${chalk_1.default.green('extract')} Extract a component (and its routes) to another module
|
|
77
|
+
${chalk_1.default.green('sync-schemas')} Regenerate all.json from task schema directory
|
|
77
78
|
${chalk_1.default.green('schema')} Show JSON schema for a component or task
|
|
78
79
|
${chalk_1.default.green('example')} Show example YAML for a component or task
|
|
79
80
|
${chalk_1.default.green('list')} List available schemas (modules, workflows, tasks)
|
|
@@ -92,6 +93,7 @@ ${chalk_1.default.bold.yellow('OPTIONS:')}
|
|
|
92
93
|
${chalk_1.default.green('--template <name>')} Template variant for create command (e.g., ${chalk_1.default.cyan('basic')})
|
|
93
94
|
${chalk_1.default.green('--feature <name>')} Place file under features/<name>/ instead of root
|
|
94
95
|
${chalk_1.default.green('--options <json>')} JSON field definitions for create (inline or file path)
|
|
96
|
+
${chalk_1.default.green('--tasks <list>')} Comma-separated task enums for create task-schema
|
|
95
97
|
${chalk_1.default.green('--to <file>')} Target file for extract command
|
|
96
98
|
|
|
97
99
|
${chalk_1.default.bold.yellow('VALIDATION EXAMPLES:')}
|
|
@@ -132,6 +134,12 @@ ${chalk_1.default.bold.yellow('PROJECT COMMANDS:')}
|
|
|
132
134
|
${chalk_1.default.gray('# Create module with custom fields')}
|
|
133
135
|
${chalk_1.default.cyan(`${PROGRAM_NAME} create module my-config --template configuration --options '[{"name":"host","type":"text"},{"name":"port","type":"number"}]'`)}
|
|
134
136
|
|
|
137
|
+
${chalk_1.default.gray('# Create a task schema with pre-populated task enums')}
|
|
138
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} create task-schema filetransfer --tasks "FileTransfer/Connect@1,FileTransfer/Disconnect@1"`)}
|
|
139
|
+
|
|
140
|
+
${chalk_1.default.gray('# Sync all.json after manually adding/removing task schemas')}
|
|
141
|
+
${chalk_1.default.cyan(`${PROGRAM_NAME} sync-schemas`)}
|
|
142
|
+
|
|
135
143
|
${chalk_1.default.gray('# Extract a component to a new module')}
|
|
136
144
|
${chalk_1.default.cyan(`${PROGRAM_NAME} extract modules/orders.yaml Orders/CreateItem --to modules/order-create.yaml`)}
|
|
137
145
|
|
|
@@ -194,9 +202,13 @@ ${chalk_1.default.bold.yellow('AVAILABLE SCHEMAS:')}
|
|
|
194
202
|
|
|
195
203
|
${chalk_1.default.bold('Workflow Tasks:')}
|
|
196
204
|
foreach, switch, while, validation, graphql, httpRequest,
|
|
197
|
-
setVariable, map, log, error, csv, export, template,
|
|
198
|
-
order, contact,
|
|
199
|
-
|
|
205
|
+
setVariable, map, log, error, csv, export, template, import,
|
|
206
|
+
order, contact, contact-address, contact-payment-method,
|
|
207
|
+
commodity, job, attachment, charge, payment,
|
|
208
|
+
email-send, document-render, document-send, pdf-document,
|
|
209
|
+
accounting-transaction, number, workflow-execute,
|
|
210
|
+
filetransfer, caching, flow-transition, user, authentication,
|
|
211
|
+
edi, note, appmodule, action-event, inventory, movement
|
|
200
212
|
|
|
201
213
|
${chalk_1.default.bold.yellow('EXAMPLES:')}
|
|
202
214
|
${chalk_1.default.cyan(`${PROGRAM_NAME} schema form`)}
|
|
@@ -910,8 +922,13 @@ function runInit() {
|
|
|
910
922
|
console.log('');
|
|
911
923
|
}
|
|
912
924
|
function runCreate(type, name, template, feature, createOptions) {
|
|
925
|
+
// Handle task-schema creation separately
|
|
926
|
+
if (type === 'task-schema') {
|
|
927
|
+
runCreateTaskSchema(name, createOptions);
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
913
930
|
if (!type || !['module', 'workflow'].includes(type)) {
|
|
914
|
-
console.error(chalk_1.default.red('Error: Invalid or missing type. Use: module or
|
|
931
|
+
console.error(chalk_1.default.red('Error: Invalid or missing type. Use: module, workflow, or task-schema'));
|
|
915
932
|
console.error(chalk_1.default.gray(`Example: ${PROGRAM_NAME} create module my-module`));
|
|
916
933
|
process.exit(2);
|
|
917
934
|
}
|
|
@@ -920,13 +937,13 @@ function runCreate(type, name, template, feature, createOptions) {
|
|
|
920
937
|
console.error(chalk_1.default.gray(`Example: ${PROGRAM_NAME} create ${type} my-${type}`));
|
|
921
938
|
process.exit(2);
|
|
922
939
|
}
|
|
923
|
-
// Sanitize name
|
|
924
|
-
const safeName = name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
940
|
+
// Sanitize name: replace invalid chars with hyphen, collapse runs, trim edges
|
|
941
|
+
const safeName = name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-{2,}/g, '-').replace(/^-|-$/g, '');
|
|
925
942
|
// Determine output directory and file
|
|
926
943
|
// workflows/ or features/<feature>/workflows/ (same for modules)
|
|
927
944
|
const baseDir = type === 'module' ? 'modules' : 'workflows';
|
|
928
945
|
const dir = feature
|
|
929
|
-
? path.join('features', feature.toLowerCase().replace(/[^a-z0-9-]/g, '-'), baseDir)
|
|
946
|
+
? path.join('features', feature.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-{2,}/g, '-').replace(/^-|-$/g, ''), baseDir)
|
|
930
947
|
: baseDir;
|
|
931
948
|
const fileName = `${safeName}.yaml`;
|
|
932
949
|
const filePath = path.join(process.cwd(), dir, fileName);
|
|
@@ -960,6 +977,160 @@ function runCreate(type, name, template, feature, createOptions) {
|
|
|
960
977
|
console.log('');
|
|
961
978
|
}
|
|
962
979
|
// ============================================================================
|
|
980
|
+
// Create Task Schema Command
|
|
981
|
+
// ============================================================================
|
|
982
|
+
function runCreateTaskSchema(name, tasks) {
|
|
983
|
+
if (!name) {
|
|
984
|
+
console.error(chalk_1.default.red('Error: Missing name for task-schema'));
|
|
985
|
+
console.error(chalk_1.default.gray(`Example: ${PROGRAM_NAME} create task-schema filetransfer --tasks "FileTransfer/Connect@1,FileTransfer/Disconnect@1"`));
|
|
986
|
+
process.exit(2);
|
|
987
|
+
}
|
|
988
|
+
const safeName = name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-{2,}/g, '-').replace(/^-|-$/g, '');
|
|
989
|
+
// Find schemas directory — prefer source schemas/ in dev, fall back to standard resolution
|
|
990
|
+
let schemasDir = path.join(process.cwd(), 'schemas');
|
|
991
|
+
if (!fs.existsSync(schemasDir)) {
|
|
992
|
+
const resolved = findSchemasPath();
|
|
993
|
+
if (!resolved) {
|
|
994
|
+
console.error(chalk_1.default.red('Error: Cannot find schemas directory'));
|
|
995
|
+
process.exit(2);
|
|
996
|
+
}
|
|
997
|
+
schemasDir = resolved;
|
|
998
|
+
}
|
|
999
|
+
const tasksDir = path.join(schemasDir, 'workflows', 'tasks');
|
|
1000
|
+
if (!fs.existsSync(tasksDir)) {
|
|
1001
|
+
fs.mkdirSync(tasksDir, { recursive: true });
|
|
1002
|
+
}
|
|
1003
|
+
const filePath = path.join(tasksDir, `${safeName}.json`);
|
|
1004
|
+
if (fs.existsSync(filePath)) {
|
|
1005
|
+
console.error(chalk_1.default.red(`Error: Schema file already exists: ${filePath}`));
|
|
1006
|
+
process.exit(2);
|
|
1007
|
+
}
|
|
1008
|
+
// Parse --tasks flag (passed via --options)
|
|
1009
|
+
const taskEnums = [];
|
|
1010
|
+
if (tasks) {
|
|
1011
|
+
for (const t of tasks.split(',')) {
|
|
1012
|
+
const trimmed = t.trim();
|
|
1013
|
+
if (trimmed)
|
|
1014
|
+
taskEnums.push(trimmed);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
// Derive a title from the name
|
|
1018
|
+
const title = safeName
|
|
1019
|
+
.split('-')
|
|
1020
|
+
.map(w => w.charAt(0).toUpperCase() + w.slice(1))
|
|
1021
|
+
.join(' ') + ' Tasks';
|
|
1022
|
+
// Build the schema JSON
|
|
1023
|
+
const schema = {
|
|
1024
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
1025
|
+
title,
|
|
1026
|
+
description: `${title} operations`,
|
|
1027
|
+
type: 'object',
|
|
1028
|
+
properties: {
|
|
1029
|
+
task: {
|
|
1030
|
+
type: 'string',
|
|
1031
|
+
...(taskEnums.length > 0 ? { enum: taskEnums } : {}),
|
|
1032
|
+
description: 'Task type identifier'
|
|
1033
|
+
},
|
|
1034
|
+
name: {
|
|
1035
|
+
type: 'string',
|
|
1036
|
+
description: 'Step name identifier'
|
|
1037
|
+
},
|
|
1038
|
+
description: {
|
|
1039
|
+
type: 'string',
|
|
1040
|
+
description: 'Step description'
|
|
1041
|
+
},
|
|
1042
|
+
conditions: {
|
|
1043
|
+
type: 'array',
|
|
1044
|
+
items: {
|
|
1045
|
+
type: 'object',
|
|
1046
|
+
properties: {
|
|
1047
|
+
expression: { type: 'string' }
|
|
1048
|
+
},
|
|
1049
|
+
required: ['expression']
|
|
1050
|
+
}
|
|
1051
|
+
},
|
|
1052
|
+
continueOnError: {
|
|
1053
|
+
type: 'boolean'
|
|
1054
|
+
},
|
|
1055
|
+
inputs: {
|
|
1056
|
+
type: 'object',
|
|
1057
|
+
description: `${title} inputs`,
|
|
1058
|
+
additionalProperties: true
|
|
1059
|
+
},
|
|
1060
|
+
outputs: {
|
|
1061
|
+
type: 'array',
|
|
1062
|
+
items: {
|
|
1063
|
+
type: 'object',
|
|
1064
|
+
properties: {
|
|
1065
|
+
name: { type: 'string' },
|
|
1066
|
+
mapping: { type: 'string' }
|
|
1067
|
+
},
|
|
1068
|
+
required: ['name', 'mapping']
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
},
|
|
1072
|
+
required: ['task'],
|
|
1073
|
+
additionalProperties: true
|
|
1074
|
+
};
|
|
1075
|
+
fs.writeFileSync(filePath, JSON.stringify(schema, null, 2) + '\n', 'utf-8');
|
|
1076
|
+
// Sync all.json
|
|
1077
|
+
syncAllJson(tasksDir);
|
|
1078
|
+
// Invalidate cache so new schema is immediately discoverable
|
|
1079
|
+
_workflowTaskNamesCache = null;
|
|
1080
|
+
console.log(chalk_1.default.green(`\n✓ Created task schema: ${path.relative(process.cwd(), filePath)}`));
|
|
1081
|
+
console.log(chalk_1.default.gray(`\n Next steps:`));
|
|
1082
|
+
console.log(chalk_1.default.gray(` 1. Edit ${chalk_1.default.white(filePath)} to add typed input properties`));
|
|
1083
|
+
console.log(chalk_1.default.gray(` 2. Verify: ${chalk_1.default.white(`${PROGRAM_NAME} schema ${safeName}`)}`));
|
|
1084
|
+
console.log(chalk_1.default.gray(` 3. all.json has been auto-updated with the new reference`));
|
|
1085
|
+
console.log('');
|
|
1086
|
+
}
|
|
1087
|
+
// ============================================================================
|
|
1088
|
+
// Sync all.json (auto-regenerate $ref entries from task schema directory)
|
|
1089
|
+
// ============================================================================
|
|
1090
|
+
function syncAllJson(tasksDir) {
|
|
1091
|
+
const files = fs.readdirSync(tasksDir)
|
|
1092
|
+
.filter(f => f.endsWith('.json') && f !== 'all.json' && f !== 'generic.json')
|
|
1093
|
+
.sort();
|
|
1094
|
+
const anyOfRefs = files.map(f => ({ $ref: f }));
|
|
1095
|
+
// generic.json always last as fallback
|
|
1096
|
+
if (fs.existsSync(path.join(tasksDir, 'generic.json'))) {
|
|
1097
|
+
anyOfRefs.push({ $ref: 'generic.json' });
|
|
1098
|
+
}
|
|
1099
|
+
const allJson = {
|
|
1100
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
1101
|
+
title: 'All Workflow Tasks',
|
|
1102
|
+
description: 'Aggregator schema for all workflow task types. Uses anyOf to allow matching any known task type or falling back to generic task structure.',
|
|
1103
|
+
type: 'object',
|
|
1104
|
+
anyOf: anyOfRefs
|
|
1105
|
+
};
|
|
1106
|
+
fs.writeFileSync(path.join(tasksDir, 'all.json'), JSON.stringify(allJson, null, 2) + '\n', 'utf-8');
|
|
1107
|
+
}
|
|
1108
|
+
function runSyncSchemas() {
|
|
1109
|
+
// Find schemas directory
|
|
1110
|
+
let schemasDir = path.join(process.cwd(), 'schemas');
|
|
1111
|
+
if (!fs.existsSync(schemasDir)) {
|
|
1112
|
+
const resolved = findSchemasPath();
|
|
1113
|
+
if (!resolved) {
|
|
1114
|
+
console.error(chalk_1.default.red('Error: Cannot find schemas directory'));
|
|
1115
|
+
process.exit(2);
|
|
1116
|
+
}
|
|
1117
|
+
schemasDir = resolved;
|
|
1118
|
+
}
|
|
1119
|
+
const tasksDir = path.join(schemasDir, 'workflows', 'tasks');
|
|
1120
|
+
if (!fs.existsSync(tasksDir)) {
|
|
1121
|
+
console.error(chalk_1.default.red('Error: Tasks directory not found'));
|
|
1122
|
+
process.exit(2);
|
|
1123
|
+
}
|
|
1124
|
+
syncAllJson(tasksDir);
|
|
1125
|
+
// Invalidate cache
|
|
1126
|
+
_workflowTaskNamesCache = null;
|
|
1127
|
+
const taskCount = fs.readdirSync(tasksDir)
|
|
1128
|
+
.filter(f => f.endsWith('.json') && f !== 'all.json' && f !== 'generic.json')
|
|
1129
|
+
.length;
|
|
1130
|
+
console.log(chalk_1.default.green(`\n✓ Synced all.json with ${taskCount} task schemas (+ generic fallback)`));
|
|
1131
|
+
console.log('');
|
|
1132
|
+
}
|
|
1133
|
+
// ============================================================================
|
|
963
1134
|
// Extract Command
|
|
964
1135
|
// ============================================================================
|
|
965
1136
|
function runExtract(sourceFile, componentName, targetFile) {
|
|
@@ -1090,7 +1261,7 @@ function parseArgs(args) {
|
|
|
1090
1261
|
reportFormat: 'json'
|
|
1091
1262
|
};
|
|
1092
1263
|
// Check for commands
|
|
1093
|
-
const commands = ['validate', 'schema', 'example', 'list', 'help', 'report', 'init', 'create', 'extract'];
|
|
1264
|
+
const commands = ['validate', 'schema', 'example', 'list', 'help', 'report', 'init', 'create', 'extract', 'sync-schemas'];
|
|
1094
1265
|
if (args.length > 0 && commands.includes(args[0])) {
|
|
1095
1266
|
command = args[0];
|
|
1096
1267
|
args = args.slice(1);
|
|
@@ -1157,6 +1328,9 @@ function parseArgs(args) {
|
|
|
1157
1328
|
else if (arg === '--options') {
|
|
1158
1329
|
options.createOptions = args[++i];
|
|
1159
1330
|
}
|
|
1331
|
+
else if (arg === '--tasks') {
|
|
1332
|
+
options.createTasks = args[++i];
|
|
1333
|
+
}
|
|
1160
1334
|
else if (arg === '--to') {
|
|
1161
1335
|
options.extractTo = args[++i];
|
|
1162
1336
|
}
|
|
@@ -1244,47 +1418,81 @@ function detectFileType(filePath) {
|
|
|
1244
1418
|
// ============================================================================
|
|
1245
1419
|
// Schema Display
|
|
1246
1420
|
// ============================================================================
|
|
1421
|
+
// Cache for dynamically discovered workflow task schema names
|
|
1422
|
+
let _workflowTaskNamesCache = null;
|
|
1423
|
+
function getWorkflowTaskNames(schemasPath) {
|
|
1424
|
+
if (_workflowTaskNamesCache)
|
|
1425
|
+
return _workflowTaskNamesCache;
|
|
1426
|
+
const tasksDir = path.join(schemasPath, 'workflows', 'tasks');
|
|
1427
|
+
_workflowTaskNamesCache = new Set();
|
|
1428
|
+
if (fs.existsSync(tasksDir)) {
|
|
1429
|
+
for (const file of fs.readdirSync(tasksDir)) {
|
|
1430
|
+
if (file.endsWith('.json') && file !== 'all.json') {
|
|
1431
|
+
_workflowTaskNamesCache.add(file.replace('.json', '').toLowerCase().replace(/[^a-z0-9-]/g, ''));
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
// Also include common definitions
|
|
1436
|
+
const commonDir = path.join(schemasPath, 'workflows', 'common');
|
|
1437
|
+
if (fs.existsSync(commonDir)) {
|
|
1438
|
+
for (const file of fs.readdirSync(commonDir)) {
|
|
1439
|
+
if (file.endsWith('.json')) {
|
|
1440
|
+
_workflowTaskNamesCache.add(file.replace('.json', '').toLowerCase().replace(/[^a-z0-9-]/g, ''));
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
return _workflowTaskNamesCache;
|
|
1445
|
+
}
|
|
1247
1446
|
function findSchemaFile(schemasPath, name, preferWorkflow = false) {
|
|
1248
|
-
// Normalize name
|
|
1447
|
+
// Normalize name: lowercase, strip non-alphanumeric except hyphens
|
|
1249
1448
|
const normalizedName = name.toLowerCase().replace(/[^a-z0-9-]/g, '');
|
|
1250
|
-
//
|
|
1449
|
+
// Dynamically detect workflow schema names from directory contents
|
|
1251
1450
|
const workflowCoreNames = ['workflow', 'activity', 'input', 'output', 'variable', 'trigger', 'schedule'];
|
|
1252
|
-
const workflowTaskNames =
|
|
1253
|
-
'foreach', 'switch', 'while', 'validation', 'map', 'setvariable', 'httprequest',
|
|
1254
|
-
'log', 'error', 'csv', 'export', 'template', 'graphql', 'order', 'contact',
|
|
1255
|
-
'commodity', 'job', 'attachment', 'email-send', 'document-render', 'document-send',
|
|
1256
|
-
'charge', 'accounting-transaction', 'payment', 'workflow-execute', 'condition',
|
|
1257
|
-
'expression', 'mapping'
|
|
1258
|
-
];
|
|
1451
|
+
const workflowTaskNames = getWorkflowTaskNames(schemasPath);
|
|
1259
1452
|
const isWorkflowSchema = workflowCoreNames.includes(normalizedName) ||
|
|
1260
|
-
workflowTaskNames.
|
|
1261
|
-
//
|
|
1453
|
+
workflowTaskNames.has(normalizedName);
|
|
1454
|
+
// Build search paths using normalized name for consistency
|
|
1262
1455
|
const searchPaths = preferWorkflow || isWorkflowSchema
|
|
1263
1456
|
? [
|
|
1264
1457
|
// Workflow schemas first for workflow-related names
|
|
1265
|
-
path.join(schemasPath, 'workflows', `${
|
|
1266
|
-
path.join(schemasPath, 'workflows', 'tasks', `${
|
|
1267
|
-
path.join(schemasPath, 'workflows', 'common', `${
|
|
1458
|
+
path.join(schemasPath, 'workflows', `${normalizedName}.json`),
|
|
1459
|
+
path.join(schemasPath, 'workflows', 'tasks', `${normalizedName}.json`),
|
|
1460
|
+
path.join(schemasPath, 'workflows', 'common', `${normalizedName}.json`),
|
|
1268
1461
|
// Then module schemas
|
|
1269
|
-
path.join(schemasPath, 'components', `${
|
|
1270
|
-
path.join(schemasPath, 'fields', `${
|
|
1271
|
-
path.join(schemasPath, 'actions', `${
|
|
1462
|
+
path.join(schemasPath, 'components', `${normalizedName}.json`),
|
|
1463
|
+
path.join(schemasPath, 'fields', `${normalizedName}.json`),
|
|
1464
|
+
path.join(schemasPath, 'actions', `${normalizedName}.json`)
|
|
1272
1465
|
]
|
|
1273
1466
|
: [
|
|
1274
1467
|
// Module schemas first
|
|
1275
|
-
path.join(schemasPath, 'components', `${
|
|
1276
|
-
path.join(schemasPath, 'fields', `${
|
|
1277
|
-
path.join(schemasPath, 'actions', `${
|
|
1468
|
+
path.join(schemasPath, 'components', `${normalizedName}.json`),
|
|
1469
|
+
path.join(schemasPath, 'fields', `${normalizedName}.json`),
|
|
1470
|
+
path.join(schemasPath, 'actions', `${normalizedName}.json`),
|
|
1278
1471
|
// Then workflow schemas
|
|
1279
|
-
path.join(schemasPath, 'workflows', `${
|
|
1280
|
-
path.join(schemasPath, 'workflows', 'tasks', `${
|
|
1281
|
-
path.join(schemasPath, 'workflows', 'common', `${
|
|
1472
|
+
path.join(schemasPath, 'workflows', `${normalizedName}.json`),
|
|
1473
|
+
path.join(schemasPath, 'workflows', 'tasks', `${normalizedName}.json`),
|
|
1474
|
+
path.join(schemasPath, 'workflows', 'common', `${normalizedName}.json`)
|
|
1282
1475
|
];
|
|
1283
1476
|
for (const schemaPath of searchPaths) {
|
|
1284
1477
|
if (fs.existsSync(schemaPath)) {
|
|
1285
1478
|
return schemaPath;
|
|
1286
1479
|
}
|
|
1287
1480
|
}
|
|
1481
|
+
// Also try with the original name (preserving case) for backwards compatibility
|
|
1482
|
+
if (normalizedName !== name) {
|
|
1483
|
+
const caseSensitivePaths = [
|
|
1484
|
+
path.join(schemasPath, 'workflows', 'tasks', `${name}.json`),
|
|
1485
|
+
path.join(schemasPath, 'workflows', `${name}.json`),
|
|
1486
|
+
path.join(schemasPath, 'components', `${name}.json`),
|
|
1487
|
+
path.join(schemasPath, 'fields', `${name}.json`),
|
|
1488
|
+
path.join(schemasPath, 'actions', `${name}.json`)
|
|
1489
|
+
];
|
|
1490
|
+
for (const schemaPath of caseSensitivePaths) {
|
|
1491
|
+
if (fs.existsSync(schemaPath)) {
|
|
1492
|
+
return schemaPath;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1288
1496
|
// Try fuzzy matching
|
|
1289
1497
|
const allSchemas = getAllSchemas(schemasPath);
|
|
1290
1498
|
for (const schema of allSchemas) {
|
|
@@ -1940,7 +2148,18 @@ async function main() {
|
|
|
1940
2148
|
}
|
|
1941
2149
|
// Handle create command
|
|
1942
2150
|
if (command === 'create') {
|
|
1943
|
-
|
|
2151
|
+
// For task-schema, pass --tasks (from options.createTasks) as the tasks argument
|
|
2152
|
+
if (files[0] === 'task-schema') {
|
|
2153
|
+
runCreate(files[0], files[1], options.template, options.feature, options.createTasks);
|
|
2154
|
+
}
|
|
2155
|
+
else {
|
|
2156
|
+
runCreate(files[0], files[1], options.template, options.feature, options.createOptions);
|
|
2157
|
+
}
|
|
2158
|
+
process.exit(0);
|
|
2159
|
+
}
|
|
2160
|
+
// Handle sync-schemas command
|
|
2161
|
+
if (command === 'sync-schemas') {
|
|
2162
|
+
runSyncSchemas();
|
|
1944
2163
|
process.exit(0);
|
|
1945
2164
|
}
|
|
1946
2165
|
// Handle extract command
|