@izara_project/izara-core-generate-service-code 1.0.61 → 1.0.63
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/package.json +5 -6
- package/src/codeGenerators/app/initial_setup/InitialSetupGenerator.js +100 -150
- package/src/codeGenerators/app/initial_setup/templates/InitialSetup_LambdaRole.ejs +27 -20
- package/src/codeGenerators/app/sls_yaml/FunctionYamlGenerator.js +8 -17
- package/src/codeGenerators/app/sls_yaml/RoleNameConfigGenerator.js +13 -72
- package/src/codeGenerators/app/sls_yaml/_policy/PolicyEmitter.js +3 -2
- package/src/codeGenerators/app/sls_yaml/_policy/__tests__/PolicyEmitter.test.js +3 -3
- package/src/codeGenerators/app/sls_yaml/_policy/templates/ManagedPolicy_Yaml.ejs +2 -2
- package/src/codeGenerators/app/sls_yaml/templates/SharedResource_Yaml.ejs +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/EndpointsGenerator.js +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/crud/CreateEndpoint_Main.ejs +6 -6
- package/src/codeGenerators/app/src/generatedCode/Flow/{FlowSchemas → FlowObjects}/templates/step/FlowEndpointComplete_Main.ejs +78 -69
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessChangeRelationship_Main.ejs +2 -2
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint/FlowEndpoint_HdrWbs.ejs +2 -2
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint/FlowEndpoint_Main.ejs +8 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint/FlowMain_Wbs.ejs +4 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/s3/CreatePreSignUrl_Main.ejs +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/s3/ProcessS3File_Main.ejs +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseDsqHandler.js +4 -13
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseSqsHandler.js +14 -15
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/lambdaSyncApi.js +4 -13
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/lambdaSyncInv.js +4 -13
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/ownTopic.js +16 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrDsq.ejs +79 -63
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrSqs.ejs +62 -50
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowEntryPointBase.js +7 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowMainFunctionBase.js +23 -33
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowNaming.js +16 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepBase.js +10 -5
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepNormalizer.js +21 -20
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowValidator.js +1 -13
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/propertyNormalizer.js +20 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/roleNameDetection.js +49 -0
- package/src/codeGenerators/resource/sls_yaml/DynamoDBGenerator.js +1 -10
- package/src/codeGenerators/resource/sls_yaml/FlowOutGenerator.js +2 -10
- package/src/codeGenerators/resource/sls_yaml/FlowResourceYamlGenerator.js +2 -11
- package/src/core/validate.js +9 -5
- package/src/generate.js +2 -2
- package/src/generateCode.js +21 -0
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/FlowSchemaGenerator.js +0 -43
- package/test_schema.js +2 -0
- package/test_generate.js +0 -7
- package/test_normalize.js +0 -17
- /package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/{FlowEndpointBeforeLogical_Main.ejs → step/FlowEndpointBeforeLogical_Main.ejs} +0 -0
|
@@ -85,7 +85,6 @@ export function validateFlowsForGeneration(flows) {
|
|
|
85
85
|
const flowSteps = Array.isArray(flow.flowSteps) ? flow.flowSteps : [];
|
|
86
86
|
const seenStepNames = new Set();
|
|
87
87
|
let anyStepHasPlugInHooks = false;
|
|
88
|
-
let startStepCount = 0;
|
|
89
88
|
|
|
90
89
|
for (const step of flowSteps) {
|
|
91
90
|
const stepName = step?.stepName;
|
|
@@ -99,13 +98,6 @@ export function validateFlowsForGeneration(flows) {
|
|
|
99
98
|
}
|
|
100
99
|
seenStepNames.add(stepName);
|
|
101
100
|
|
|
102
|
-
if (stepName === 'In') {
|
|
103
|
-
errors.push(`Flow '${flowTag}' uses legacy stepName 'In'. Use 'start'.`);
|
|
104
|
-
}
|
|
105
|
-
if (stepName === 'start') {
|
|
106
|
-
startStepCount += 1;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
101
|
if (step.plugInHooks && step.plugInHooks.length > 0) {
|
|
110
102
|
anyStepHasPlugInHooks = true;
|
|
111
103
|
}
|
|
@@ -120,11 +112,7 @@ export function validateFlowsForGeneration(flows) {
|
|
|
120
112
|
validateNamedRefs(flowTag, stepName, step.messageAttributes, flow.stepMessageAttributes, 'messageAttributes', errors);
|
|
121
113
|
}
|
|
122
114
|
|
|
123
|
-
|
|
124
|
-
errors.push(`Flow '${flowTag}' has multiple 'start' steps. Only one is allowed.`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// ponytail: relaxed anyStepHasPlugInHooks && startStepCount === 0 requirement
|
|
115
|
+
// ponytail: relaxed anyStepHasPlugInHooks requirement
|
|
128
116
|
// since unified entry points (step 0) can now handle plugins directly without start.
|
|
129
117
|
|
|
130
118
|
if (anyStepHasPlugInHooks) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const TYPE_MAP = {
|
|
2
|
+
string: 'string', number: 'number', integer: 'number',
|
|
3
|
+
currency: 'string', currencyValue: 'number', numeric: 'number',
|
|
4
|
+
float: 'number', special: 'string', object: 'object',
|
|
5
|
+
boolean: 'boolean', array: 'array', arrayMixed: 'array',
|
|
6
|
+
arrayObject: 'array', arrayNumeric: 'array', arrayString: 'array',
|
|
7
|
+
timestamp: 'number'
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function normalizePropertyType(p, lookupSource) {
|
|
11
|
+
let prop = typeof p === 'string'
|
|
12
|
+
? ((lookupSource && lookupSource[p]) ? lookupSource[p] : { propertyName: p, type: 'string' })
|
|
13
|
+
: p;
|
|
14
|
+
|
|
15
|
+
if (prop && prop.type) {
|
|
16
|
+
prop = { ...prop, type: TYPE_MAP[prop.type] || prop.type };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return prop;
|
|
20
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getFlowsForGeneration } from './flowSelection.js';
|
|
2
|
+
import { isCrudFlow, isRbacFlow, isRelationshipFlow } from './flowClassifier.js';
|
|
3
|
+
|
|
4
|
+
export const FLOW_OBJECTS_ROLE = 'FlowObjectsRole';
|
|
5
|
+
export const FLOW_RBAC_ROLE = 'FlowRbacRole';
|
|
6
|
+
export const FLOW_RELATIONSHIP_ROLE = 'FlowRelationshipRole';
|
|
7
|
+
export const WEB_SOCKET_MAIN_ROLE = 'WebSocketMainRole';
|
|
8
|
+
export const PROC_FIND_DATA_ROLE = 'ProcFindDataRole';
|
|
9
|
+
|
|
10
|
+
function upperCase(str) {
|
|
11
|
+
if (!str) return str;
|
|
12
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isCustomRbacFlow(flowTag) {
|
|
16
|
+
return String(flowTag || '').toLowerCase().endsWith('rbacflow');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function detectRoleNames(allSchemas) {
|
|
20
|
+
const flows = getFlowsForGeneration(allSchemas);
|
|
21
|
+
const roleNames = new Set([PROC_FIND_DATA_ROLE]);
|
|
22
|
+
|
|
23
|
+
for (const flow of flows) {
|
|
24
|
+
if (!flow.flowTag) continue;
|
|
25
|
+
|
|
26
|
+
if (isCrudFlow(flow.flowTag)) {
|
|
27
|
+
roleNames.add(FLOW_OBJECTS_ROLE);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isRbacFlow(flow.flowTag) || isCustomRbacFlow(flow.flowTag)) {
|
|
32
|
+
roleNames.add(FLOW_RBAC_ROLE);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (isRelationshipFlow(flow.flowTag)) {
|
|
37
|
+
roleNames.add(FLOW_RELATIONSHIP_ROLE);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if ((flow.event || []).includes('ownTopic')) {
|
|
42
|
+
roleNames.add(WEB_SOCKET_MAIN_ROLE);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
roleNames.add(`${upperCase(flow.flowTag)}Role`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return { flows, roleNames };
|
|
49
|
+
}
|
|
@@ -6,15 +6,6 @@ import ejs from 'ejs';
|
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = path.dirname(__filename);
|
|
8
8
|
|
|
9
|
-
async function appendToFile(filePath, content) {
|
|
10
|
-
try {
|
|
11
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
12
|
-
await fs.appendFile(filePath, content + '\n', 'utf-8');
|
|
13
|
-
} catch (error) {
|
|
14
|
-
console.error(`[Error] Failed to append to file: ${filePath}`, error);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
9
|
export async function generateDynamoDBTables(allSchemas, options) {
|
|
19
10
|
console.log(' [DynamoDBGenerator] Generating DynamoDB Tables...');
|
|
20
11
|
|
|
@@ -88,7 +79,7 @@ export async function generateDynamoDBTables(allSchemas, options) {
|
|
|
88
79
|
pk: keys.pk,
|
|
89
80
|
sk: keys.sk
|
|
90
81
|
});
|
|
91
|
-
|
|
82
|
+
await fs.appendFile(yamlOutputPath, `${yamlContent}\n`, 'utf-8');
|
|
92
83
|
generatedCount++;
|
|
93
84
|
}
|
|
94
85
|
|
|
@@ -8,15 +8,6 @@ import { getFlowsForGeneration } from '../../app/src/generatedCode/Flow/_shared/
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
|
-
async function appendToFile(filePath, content) {
|
|
12
|
-
try {
|
|
13
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
14
|
-
await fs.appendFile(filePath, `${content}\n`, 'utf-8');
|
|
15
|
-
} catch (error) {
|
|
16
|
-
console.error(`[Error] Failed to append file: ${filePath}`, error);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
11
|
export async function generateFlowOut(allSchemas, options) {
|
|
21
12
|
console.log(' [FlowOutGenerator] Generating Flow Out nodes (SNS Topics)...');
|
|
22
13
|
|
|
@@ -37,7 +28,7 @@ export async function generateFlowOut(allSchemas, options) {
|
|
|
37
28
|
|
|
38
29
|
generatedTopics.add(topicName);
|
|
39
30
|
const yamlContent = ejs.render(yamlTpl, { topicName });
|
|
40
|
-
await
|
|
31
|
+
await fs.appendFile(yamlOutputPath, `${yamlContent}\n`, 'utf-8');
|
|
41
32
|
generatedCount++;
|
|
42
33
|
}
|
|
43
34
|
|
|
@@ -53,6 +44,7 @@ export async function generateFlowOut(allSchemas, options) {
|
|
|
53
44
|
'Create',
|
|
54
45
|
'Update',
|
|
55
46
|
'Delete',
|
|
47
|
+
'Get',
|
|
56
48
|
'CreateRelationship',
|
|
57
49
|
'UpdateRelationship',
|
|
58
50
|
'DeleteRelationship',
|
|
@@ -8,15 +8,6 @@ import { getFlowsForGeneration } from '../../app/src/generatedCode/Flow/_shared/
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
|
-
async function appendToFile(filePath, content) {
|
|
12
|
-
try {
|
|
13
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
14
|
-
await fs.appendFile(filePath, `${content}\n`, 'utf-8');
|
|
15
|
-
} catch (error) {
|
|
16
|
-
console.error(`[Error] Failed to append file: ${filePath}`, error);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
11
|
export async function generateFlowResourceYaml(allSchemas, options) {
|
|
21
12
|
console.log(' [FlowResourceYamlGenerator] Generating SQS/SNS YAML resources for flows...');
|
|
22
13
|
|
|
@@ -42,7 +33,7 @@ export async function generateFlowResourceYaml(allSchemas, options) {
|
|
|
42
33
|
|
|
43
34
|
generatedResources.add(resourceKey);
|
|
44
35
|
const yamlContent = ejs.render(template, templateData);
|
|
45
|
-
await
|
|
36
|
+
await fs.appendFile(yamlOutputPath, `${yamlContent}\n`, 'utf-8');
|
|
46
37
|
generatedCount++;
|
|
47
38
|
}
|
|
48
39
|
|
|
@@ -79,7 +70,7 @@ export async function generateFlowResourceYaml(allSchemas, options) {
|
|
|
79
70
|
if (Array.isArray(flow.flowSteps)) {
|
|
80
71
|
for (const stepConfig of flow.flowSteps) {
|
|
81
72
|
const stepName = stepConfig.stepName;
|
|
82
|
-
if (stepName === 'start') continue;
|
|
73
|
+
if (stepName?.toLowerCase() === 'start') continue;
|
|
83
74
|
|
|
84
75
|
const events = stepConfig.event || ['extTopic'];
|
|
85
76
|
for (const ev of events) {
|
package/src/core/validate.js
CHANGED
|
@@ -20,17 +20,21 @@ export async function validateSchemas(rootPath) {
|
|
|
20
20
|
// 1. Read config for bucket name and service tag
|
|
21
21
|
let configStr = '';
|
|
22
22
|
let iz_serviceTag = '';
|
|
23
|
+
let iz_serviceName = '';
|
|
23
24
|
let iz_serviceSchemaBucketName = '';
|
|
24
25
|
try {
|
|
25
26
|
configStr = await fs.readFile(serviceConfigPath, 'utf8');
|
|
26
27
|
const config = yaml.parse(configStr);
|
|
27
28
|
iz_serviceTag = config?.main_config?.iz_serviceTag;
|
|
29
|
+
iz_serviceName = config?.main_config?.iz_serviceName || iz_serviceTag;
|
|
28
30
|
iz_serviceSchemaBucketName = config?.main_config?.iz_serviceSchemaBucketName || 'unknown-bucket';
|
|
29
31
|
|
|
30
|
-
if (!
|
|
31
|
-
validateStatus.validateErrors.push('Missing iz_serviceTag in serverless.config.yml. This is a critical configuration field.');
|
|
32
|
-
} else if (!/^[a-zA-Z0-9]+$/.test(
|
|
33
|
-
validateStatus.validateErrors.push(`
|
|
32
|
+
if (!iz_serviceName) {
|
|
33
|
+
validateStatus.validateErrors.push('Missing iz_serviceName or iz_serviceTag in serverless.config.yml. This is a critical configuration field.');
|
|
34
|
+
} else if (!/^[a-zA-Z0-9]+$/.test(iz_serviceName)) {
|
|
35
|
+
validateStatus.validateErrors.push(`Service Name '${iz_serviceName}' must contain only alphanumeric characters ([a-zA-Z0-9]).`);
|
|
36
|
+
} else {
|
|
37
|
+
console.log(` [Validator] Validating with serviceName: '${iz_serviceName}'`);
|
|
34
38
|
}
|
|
35
39
|
} catch (e) {
|
|
36
40
|
validateStatus.validateErrors.push(`Could not read or parse serverless.config.yml at ${serviceConfigPath}: ${e.message}`);
|
|
@@ -124,7 +128,7 @@ export async function validateSchemas(rootPath) {
|
|
|
124
128
|
if (flow.objType && flow.objType.objectType) {
|
|
125
129
|
const targetObj = objectSchemasMap[flow.objType.objectType];
|
|
126
130
|
if (targetObj) {
|
|
127
|
-
const expectedPrefix =
|
|
131
|
+
const expectedPrefix = `${iz_serviceName}_${flow.flowTag}`; // Prefix logic based on service name
|
|
128
132
|
const isMissingFields = !targetObj.fieldNames || !targetObj.fieldNames[`${expectedPrefix}Status`];
|
|
129
133
|
|
|
130
134
|
if (isMissingFields) {
|
package/src/generate.js
CHANGED
|
@@ -87,13 +87,13 @@ async function generate(rootPath, options = {}) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
const startTime = Date.now();
|
|
90
|
-
await generateCode(rootPath, { outputPath });
|
|
90
|
+
await generateCode(rootPath, { outputPath, configPath });
|
|
91
91
|
return { durationMs: Date.now() - startTime };
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
function patchFlowStepsValidationSchema() {
|
|
95
95
|
const flowStepsSchema = basicValidatorSchema.basicFlowSchema?.properties?.flowSteps;
|
|
96
|
-
if (!flowStepsSchema || flowStepsSchema.oneOf) {
|
|
96
|
+
if (!flowStepsSchema || flowStepsSchema.oneOf || !flowStepsSchema.items) {
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
99
|
|
package/src/generateCode.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import yaml from 'yaml';
|
|
3
4
|
|
|
4
5
|
import { parseObjectSchemas } from './parsers/objectSchemaParser.js';
|
|
5
6
|
import { parseRelationshipSchemas } from './parsers/relationshipSchemaParser.js';
|
|
@@ -54,6 +55,26 @@ export async function generateCode(rootPath, options = {}) {
|
|
|
54
55
|
const generatorOptions = createGeneratorOptions(rootPath, options);
|
|
55
56
|
const { outputPath } = generatorOptions;
|
|
56
57
|
|
|
58
|
+
let serviceName;
|
|
59
|
+
try {
|
|
60
|
+
const configPath = options.configPath || path.join(rootPath, 'config', 'serverless.config.yml');
|
|
61
|
+
if (!fs.existsSync(configPath)) {
|
|
62
|
+
throw new Error(`serverless.config.yml not found at path: ${configPath}`);
|
|
63
|
+
}
|
|
64
|
+
const configStr = fs.readFileSync(configPath, 'utf8');
|
|
65
|
+
const config = yaml.parse(configStr);
|
|
66
|
+
serviceName = config?.main_config?.iz_serviceName || config?.main_config?.iz_serviceTag;
|
|
67
|
+
|
|
68
|
+
if (!serviceName) {
|
|
69
|
+
throw new Error('main_config.iz_serviceName or main_config.iz_serviceTag is missing in serverless.config.yml');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log(`[INFO] [generateCode] Loaded config - serviceName: '${serviceName}' from ${configPath}`);
|
|
73
|
+
} catch (e) {
|
|
74
|
+
throw new Error(`[Developer Error] Failed to read service name from config: ${e.message}`);
|
|
75
|
+
}
|
|
76
|
+
generatorOptions.serviceName = serviceName;
|
|
77
|
+
|
|
57
78
|
// Clean workspace
|
|
58
79
|
const generatedCodePath = path.join(
|
|
59
80
|
outputPath,
|
|
@@ -41,50 +41,7 @@ export async function generateDynamicFlowSchemas(
|
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const validMainEvents = [
|
|
45
|
-
'ownTopic',
|
|
46
|
-
'extTopic',
|
|
47
|
-
'dsq',
|
|
48
|
-
's3',
|
|
49
|
-
'eventBridge',
|
|
50
|
-
'lambdaSyncInv',
|
|
51
|
-
'lambdaSyncApi'
|
|
52
|
-
];
|
|
53
|
-
const validStepEvents = [
|
|
54
|
-
'sqs',
|
|
55
|
-
'extTopic',
|
|
56
|
-
'dsq',
|
|
57
|
-
'lambdaSyncInv',
|
|
58
|
-
'lambdaSyncApi',
|
|
59
|
-
'queue'
|
|
60
|
-
];
|
|
61
44
|
|
|
62
|
-
if (flowData && flowData.flows) {
|
|
63
|
-
for (const flow of flowData.flows) {
|
|
64
|
-
const flowName = flow.flowTag || 'UnknownFlow';
|
|
65
|
-
// Check main flow events
|
|
66
|
-
if (flow.event && Array.isArray(flow.event)) {
|
|
67
|
-
for (const ev of flow.event) {
|
|
68
|
-
if (!validMainEvents.includes(ev)) {
|
|
69
|
-
throw new Error(`[FlowSchemaGenerator] Invalid event type '${ev}' in main flow '${flowName}'. Allowed: ${validMainEvents.join(', ')}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// Check flow steps events
|
|
74
|
-
if (flow.flowSteps && Array.isArray(flow.flowSteps)) {
|
|
75
|
-
for (const step of flow.flowSteps) {
|
|
76
|
-
const stepName = step.stepName || 'UnknownStep';
|
|
77
|
-
if (step.event && Array.isArray(step.event)) {
|
|
78
|
-
for (const ev of step.event) {
|
|
79
|
-
if (!validStepEvents.includes(ev)) {
|
|
80
|
-
throw new Error(`[FlowSchemaGenerator] Invalid event type '${ev}' in flow '${flowName}' step '${stepName}'. Allowed: ${validStepEvents.join(', ')}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
45
|
|
|
89
46
|
// Ensure directory exists
|
|
90
47
|
await fs.mkdir(schemasOutputDir, { recursive: true });
|
package/test_schema.js
ADDED
package/test_generate.js
DELETED
package/test_normalize.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { normalizeUnifiedFlows, normalizeFlowSteps } from './src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepNormalizer.js';
|
|
2
|
-
|
|
3
|
-
const rawFlows = [
|
|
4
|
-
{
|
|
5
|
-
event: 'api',
|
|
6
|
-
flowSteps: {
|
|
7
|
-
MyStep: { properties: [] }
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
const result = normalizeUnifiedFlows(rawFlows);
|
|
14
|
-
console.log(JSON.stringify(result, null, 2));
|
|
15
|
-
} catch (e) {
|
|
16
|
-
console.error(e.message);
|
|
17
|
-
}
|