@izara_project/izara-core-generate-service-code 1.0.91 → 1.0.92
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 +7 -10
- package/src/compile/flowValidator.js +6 -0
- package/src/compile/loadSchemas.js +177 -69
- package/src/emit/crud/generateCrudApplicationArtifacts.js +15 -17
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +16 -21
- package/src/emit/crud/loadLocalSchemaArrays.js +4 -8
- package/src/emit/custom/customFlowPaths.js +149 -0
- package/src/emit/custom/customFlowS3.js +156 -0
- package/src/emit/custom/customFlowSteps.js +385 -0
- package/src/emit/custom/customFlowTemplates.js +28 -0
- package/src/emit/custom/customFlows.js +48 -19
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +57 -692
- package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +27 -25
- package/src/emit/rbac/generateCreateTargetRoleHandler.js +11 -13
- package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +14 -18
- package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +16 -19
- package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +19 -19
- package/src/emit/resource/dynamoResourceArtifacts.js +18 -0
- package/src/emit/resource/emitResourceArtifacts.js +13 -1247
- package/src/emit/resource/generateResourceArtifacts.js +20 -20
- package/src/emit/resource/iamResourceArtifacts.js +612 -0
- package/src/emit/resource/resourceState.js +564 -0
- package/src/emit/resource/resourceTemplate.js +30 -0
- package/src/emit/resource/s3ResourceArtifacts.js +14 -0
- package/src/emit/resource/sqsResourceArtifacts.js +113 -0
- package/src/emit/shared/runSubsystemGeneration.js +55 -0
- package/src/emit/system/emitSystemWebSocketArtifacts.js +2 -1
- package/test/crudApplicationArtifacts.test.js +72 -0
- package/test/customFlowApplicationArtifacts.test.js +98 -0
- package/test/resourceArtifacts.test.js +99 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { indentYaml, renderResourceTemplate } from './resourceTemplate.js';
|
|
2
|
+
|
|
3
|
+
export async function renderResourceGroup({
|
|
4
|
+
ownTopics = [],
|
|
5
|
+
sqsQueues = [],
|
|
6
|
+
dsqQueues = [],
|
|
7
|
+
webSocketSubscriptions = [],
|
|
8
|
+
s3Subscriptions = []
|
|
9
|
+
}) {
|
|
10
|
+
const hasResources =
|
|
11
|
+
ownTopics.length > 0 ||
|
|
12
|
+
sqsQueues.length > 0 ||
|
|
13
|
+
dsqQueues.length > 0 ||
|
|
14
|
+
webSocketSubscriptions.length > 0 ||
|
|
15
|
+
s3Subscriptions.length > 0;
|
|
16
|
+
if (!hasResources) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const chunks = await Promise.all([
|
|
21
|
+
...ownTopics.map((queueName) =>
|
|
22
|
+
renderResourceTemplate('ResourceYaml.ejs', { queueName })
|
|
23
|
+
),
|
|
24
|
+
...sqsQueues.map((queueName) =>
|
|
25
|
+
renderResourceTemplate('ResourceSqsYaml.ejs', { queueName })
|
|
26
|
+
),
|
|
27
|
+
...dsqQueues.map((queueName) =>
|
|
28
|
+
renderResourceTemplate('ResourceSqsYaml.ejs', { queueName })
|
|
29
|
+
)
|
|
30
|
+
]);
|
|
31
|
+
const wsSubs = await Promise.all(
|
|
32
|
+
webSocketSubscriptions.map((topicName) =>
|
|
33
|
+
renderWebSocketSubscription(topicName)
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
const s3Subs = await Promise.all(
|
|
37
|
+
s3Subscriptions.map(({ subscriptionName, topicName, queueName }) =>
|
|
38
|
+
renderResourceTemplate('S3Subscription_Yaml.ejs', {
|
|
39
|
+
subscriptionName,
|
|
40
|
+
topicName,
|
|
41
|
+
queueName
|
|
42
|
+
})
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
const parts = [chunks.join('\n')];
|
|
46
|
+
if (wsSubs.length > 0) {
|
|
47
|
+
parts.push(wsSubs.join('\n'));
|
|
48
|
+
}
|
|
49
|
+
if (s3Subs.length > 0) {
|
|
50
|
+
parts.push(s3Subs.join('\n'));
|
|
51
|
+
}
|
|
52
|
+
const body = parts.filter(Boolean).join('\n');
|
|
53
|
+
if (!body.trim()) {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
return `Resources:\n${indentYaml(body, 2)}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function renderCrudInSqs(state) {
|
|
60
|
+
return renderResourceGroup({
|
|
61
|
+
ownTopics: state.crudOwnTopics,
|
|
62
|
+
sqsQueues: state.crudSqsQueues
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function renderRelationshipInSqs(state) {
|
|
67
|
+
return renderResourceGroup({
|
|
68
|
+
ownTopics: state.relationshipOwnTopics,
|
|
69
|
+
sqsQueues: state.relationshipSqsQueues,
|
|
70
|
+
dsqQueues: state.relationshipDsqQueues
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function renderRbacInSqs(state) {
|
|
75
|
+
return renderResourceGroup({
|
|
76
|
+
ownTopics: state.rbacOwnTopics,
|
|
77
|
+
sqsQueues: state.rbacSqsQueues
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function renderCustomFlowInSqs(state) {
|
|
82
|
+
return renderResourceGroup({
|
|
83
|
+
ownTopics: state.customOwnTopics,
|
|
84
|
+
sqsQueues: state.customSqsQueues,
|
|
85
|
+
dsqQueues: state.customDsqQueues,
|
|
86
|
+
s3Subscriptions: state.s3Subscriptions
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function renderSystemInSqs(state) {
|
|
91
|
+
return renderResourceGroup({
|
|
92
|
+
ownTopics: state.systemOwnTopics,
|
|
93
|
+
sqsQueues: state.systemSqsQueues,
|
|
94
|
+
dsqQueues: state.systemDsqQueues,
|
|
95
|
+
webSocketSubscriptions: state.webSocketSubscriptions
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export async function renderOut(state) {
|
|
100
|
+
const renderedTopics = await Promise.all(
|
|
101
|
+
state.outTopics.map((topicName) =>
|
|
102
|
+
renderResourceTemplate('FlowOut_Yaml.ejs', { topicName })
|
|
103
|
+
)
|
|
104
|
+
);
|
|
105
|
+
const body = renderedTopics.join('\n');
|
|
106
|
+
return `Resources:\n${indentYaml(body, 2)}`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function renderWebSocketSubscription(topicName) {
|
|
110
|
+
return renderResourceTemplate('WebSocketSubscription_Yaml.ejs', {
|
|
111
|
+
topicName
|
|
112
|
+
});
|
|
113
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { compileProject } from '../../compile/compileProject.js';
|
|
2
|
+
import { buildGenerationPlan } from '../../plan/buildGenerationPlan.js';
|
|
3
|
+
import { commitArtifacts } from '../../output/commitArtifacts.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Common pipeline runner for emitting and committing subsystem artifacts.
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} params
|
|
9
|
+
* @param {string} params.rootPath Root path of the service project.
|
|
10
|
+
* @param {Object} [params.options={}] Options passed to compile and load.
|
|
11
|
+
* @param {Function} [params.loadInputs] Function to load schemas or inputs.
|
|
12
|
+
* @param {Function} params.emitArtifacts Function to emit artifacts.
|
|
13
|
+
* @param {string} params.managedScope Scope identifier for generation plan.
|
|
14
|
+
* @param {Array<string>|Function} params.resolveManagedPaths Managed paths.
|
|
15
|
+
* @returns {Promise<{ project: Object, files: Array<string> }>}
|
|
16
|
+
*/
|
|
17
|
+
export async function runSubsystemGeneration({
|
|
18
|
+
rootPath,
|
|
19
|
+
options = {},
|
|
20
|
+
loadInputs,
|
|
21
|
+
emitArtifacts,
|
|
22
|
+
managedScope,
|
|
23
|
+
resolveManagedPaths
|
|
24
|
+
}) {
|
|
25
|
+
const project = compileProject({ ...options, rootPath });
|
|
26
|
+
|
|
27
|
+
let inputs = {};
|
|
28
|
+
if (typeof loadInputs === 'function') {
|
|
29
|
+
inputs = await loadInputs(project, options);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const artifacts = await emitArtifacts({
|
|
33
|
+
project,
|
|
34
|
+
options,
|
|
35
|
+
...inputs
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
let managedPaths = resolveManagedPaths;
|
|
39
|
+
if (typeof resolveManagedPaths === 'function') {
|
|
40
|
+
managedPaths = await resolveManagedPaths({
|
|
41
|
+
project,
|
|
42
|
+
options,
|
|
43
|
+
artifacts,
|
|
44
|
+
...inputs
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const plan = buildGenerationPlan(project, artifacts, {
|
|
49
|
+
managedPaths,
|
|
50
|
+
managedScope
|
|
51
|
+
});
|
|
52
|
+
const files = await commitArtifacts(plan);
|
|
53
|
+
|
|
54
|
+
return { project, files };
|
|
55
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import ejsLib from 'ejs';
|
|
3
|
+
import { flowHasOwnTopic } from '../custom/customFlows.js';
|
|
3
4
|
|
|
4
5
|
const TEMPLATE_URL = new URL('./templates/', import.meta.url);
|
|
5
6
|
const SOURCE = 'app/src/generatedCode/SystemFlowSchemas/WebSocketMain/source';
|
|
@@ -126,7 +127,7 @@ export function hasSystemWebSocket(
|
|
|
126
127
|
Array.isArray(flow?.event) &&
|
|
127
128
|
(flow.event.includes('s3') ||
|
|
128
129
|
(includeRelationshipOwnTopic &&
|
|
129
|
-
flow
|
|
130
|
+
flowHasOwnTopic(flow) &&
|
|
130
131
|
(flow.initiateBy === 'user' || flow.initiateBy === 'systemWithUser')))
|
|
131
132
|
)
|
|
132
133
|
);
|
|
@@ -1388,6 +1388,78 @@ test('emits autoProvisionOwnerTargetRole in CreateNodeCallback when service has
|
|
|
1388
1388
|
);
|
|
1389
1389
|
});
|
|
1390
1390
|
|
|
1391
|
+
test('emits synchronous before-hook invocation in Create_Main when event is generateCode and invocationType is lambdaSyncInv', async () => {
|
|
1392
|
+
const rootPath = await createProject(true);
|
|
1393
|
+
const schemas = join(rootPath, 'app/src/schemas');
|
|
1394
|
+
await writeFile(
|
|
1395
|
+
join(schemas, 'FlowSchemas/ValidateBeforeCreateSync.js'),
|
|
1396
|
+
"export default { flowTag: 'validateBeforeCreateSync', event: ['generateCode'], generatedCodeConfig: { generateCodeTag: 'create', codeHookTag: 'before', invocationType: 'lambdaSyncInv' }, objType: { objectType: 'order' } };\n"
|
|
1397
|
+
);
|
|
1398
|
+
await generateCrudApplicationArtifacts(rootPath, {
|
|
1399
|
+
serviceTag: 'orders'
|
|
1400
|
+
});
|
|
1401
|
+
|
|
1402
|
+
const createMain = await readFile(
|
|
1403
|
+
join(
|
|
1404
|
+
rootPath,
|
|
1405
|
+
'app/src/generatedCode/FlowObjects/Create/source/Create_Main.js'
|
|
1406
|
+
),
|
|
1407
|
+
'utf8'
|
|
1408
|
+
);
|
|
1409
|
+
assert.match(
|
|
1410
|
+
createMain,
|
|
1411
|
+
/lambda\.invokeSync\(\s*_izContext,\s*await lambdaSharedLib\.lambdaFunctionName\(\s*_izContext,\s*'validateBeforeCreateSync'\s*\)/
|
|
1412
|
+
);
|
|
1413
|
+
assert.match(createMain, /Hook validateBeforeCreateSync failed/);
|
|
1414
|
+
|
|
1415
|
+
execFileSync(
|
|
1416
|
+
process.execPath,
|
|
1417
|
+
[
|
|
1418
|
+
'--check',
|
|
1419
|
+
join(
|
|
1420
|
+
rootPath,
|
|
1421
|
+
'app/src/generatedCode/FlowObjects/Create/source/Create_Main.js'
|
|
1422
|
+
)
|
|
1423
|
+
],
|
|
1424
|
+
{ stdio: 'inherit' }
|
|
1425
|
+
);
|
|
1426
|
+
});
|
|
1427
|
+
|
|
1428
|
+
test('emits async before-hook callback and SNS publish in Create_Main when event is generateCode and invocationType is ownTopic', async () => {
|
|
1429
|
+
const rootPath = await createProject(true);
|
|
1430
|
+
const schemas = join(rootPath, 'app/src/schemas');
|
|
1431
|
+
await writeFile(
|
|
1432
|
+
join(schemas, 'FlowSchemas/ValidateBeforeCreateAsync.js'),
|
|
1433
|
+
"export default { flowTag: 'validateBeforeCreateAsync', event: ['generateCode'], generatedCodeConfig: { generateCodeTag: 'create', codeHookTag: 'before', invocationType: 'ownTopic' }, objType: { objectType: 'order' } };\n"
|
|
1434
|
+
);
|
|
1435
|
+
await generateCrudApplicationArtifacts(rootPath, {
|
|
1436
|
+
serviceTag: 'orders'
|
|
1437
|
+
});
|
|
1438
|
+
|
|
1439
|
+
const createMain = await readFile(
|
|
1440
|
+
join(
|
|
1441
|
+
rootPath,
|
|
1442
|
+
'app/src/generatedCode/FlowObjects/Create/source/Create_Main.js'
|
|
1443
|
+
),
|
|
1444
|
+
'utf8'
|
|
1445
|
+
);
|
|
1446
|
+
assert.match(createMain, /sns\.publishAsync\(_izContext,/);
|
|
1447
|
+
assert.match(
|
|
1448
|
+
createMain,
|
|
1449
|
+
/snsTopicArnByFlowSchema\(\s*_izContext,\s*'validateBeforeCreateAsync_In'\s*\)/
|
|
1450
|
+
);
|
|
1451
|
+
assert.match(createMain, /CreateBeforeHookCallbackHdrSqs/);
|
|
1452
|
+
|
|
1453
|
+
const callbackHandler = await readFile(
|
|
1454
|
+
join(
|
|
1455
|
+
rootPath,
|
|
1456
|
+
'app/src/generatedCode/FlowObjects/Create/source/CreateBeforeHookCallback_HdrSqs.js'
|
|
1457
|
+
),
|
|
1458
|
+
'utf8'
|
|
1459
|
+
);
|
|
1460
|
+
assert.match(callbackHandler, /CreateBeforeHookCallback_Main/);
|
|
1461
|
+
});
|
|
1462
|
+
|
|
1391
1463
|
async function createProject(withCrudObject) {
|
|
1392
1464
|
const rootPath = await mkdtemp(
|
|
1393
1465
|
join(tmpdir(), 'generate-service-code-v2-crud-application-')
|
|
@@ -1173,3 +1173,101 @@ test('renders previousSteps extTopic subscriptions in InitialSetupConfig', async
|
|
|
1173
1173
|
/sqsEndpoint: 'OrderBuildOrderSellOfferLinkAndReserveOrderDataHdrSqs'/
|
|
1174
1174
|
);
|
|
1175
1175
|
});
|
|
1176
|
+
|
|
1177
|
+
test('emits handlers, YAML and templates for flow with event generateCode and invocationType ownTopic', async () => {
|
|
1178
|
+
const rootPath = await mkdtemp(
|
|
1179
|
+
join(tmpdir(), 'generate-service-code-v2-custom-gen-own-')
|
|
1180
|
+
);
|
|
1181
|
+
roots.add(rootPath);
|
|
1182
|
+
const schemaRoot = join(rootPath, 'app/src/schemas/FlowSchemas');
|
|
1183
|
+
await mkdir(schemaRoot, { recursive: true });
|
|
1184
|
+
await writeFile(
|
|
1185
|
+
join(schemaRoot, 'GenOwn.js'),
|
|
1186
|
+
`export default {
|
|
1187
|
+
flowTag: 'genOwn',
|
|
1188
|
+
event: ['generateCode'],
|
|
1189
|
+
generatedCodeConfig: {
|
|
1190
|
+
generateCodeTag: 'create',
|
|
1191
|
+
codeHookTag: 'before',
|
|
1192
|
+
invocationType: 'ownTopic'
|
|
1193
|
+
},
|
|
1194
|
+
flowSteps: [{ stepName: 'Start', properties: ['dummyId'] }],
|
|
1195
|
+
stepProperties: { dummyId: { type: 'string' } }
|
|
1196
|
+
};\n`
|
|
1197
|
+
);
|
|
1198
|
+
|
|
1199
|
+
await generateCustomFlowApplicationArtifacts(rootPath);
|
|
1200
|
+
|
|
1201
|
+
const mainPath = join(
|
|
1202
|
+
rootPath,
|
|
1203
|
+
'app/src/generatedCode/FlowSchemas/GenOwn/source/GenOwn_Main.js'
|
|
1204
|
+
);
|
|
1205
|
+
const hdrSqsPath = join(
|
|
1206
|
+
rootPath,
|
|
1207
|
+
'app/src/generatedCode/FlowSchemas/GenOwn/source/GenOwn_HdrSqs.js'
|
|
1208
|
+
);
|
|
1209
|
+
const wbsMainPath = join(
|
|
1210
|
+
rootPath,
|
|
1211
|
+
'app/src/generatedCode/FlowSchemas/GenOwn/source/GenOwn_WbsMain.js'
|
|
1212
|
+
);
|
|
1213
|
+
const hdrWbsPath = join(
|
|
1214
|
+
rootPath,
|
|
1215
|
+
'app/src/generatedCode/FlowSchemas/GenOwn/source/GenOwn_HdrWbs.js'
|
|
1216
|
+
);
|
|
1217
|
+
|
|
1218
|
+
assert.match(await readFile(mainPath, 'utf8'), /asyncFlowSharedLib/);
|
|
1219
|
+
assert.match(await readFile(hdrSqsPath, 'utf8'), /GenOwn_Main/);
|
|
1220
|
+
assert.match(await readFile(wbsMainPath, 'utf8'), /GenOwn_WbsMain/);
|
|
1221
|
+
assert.match(await readFile(hdrWbsPath, 'utf8'), /GenOwn_WbsMain/);
|
|
1222
|
+
|
|
1223
|
+
const yaml = await readFile(
|
|
1224
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-schema.yml'),
|
|
1225
|
+
'utf8'
|
|
1226
|
+
);
|
|
1227
|
+
assert.match(yaml, /GenOwnHdrWbs:/);
|
|
1228
|
+
assert.match(yaml, /GenOwnHdrSqs:/);
|
|
1229
|
+
});
|
|
1230
|
+
|
|
1231
|
+
test('emits handler and YAML for flow with event generateCode and invocationType lambdaSyncInv', async () => {
|
|
1232
|
+
const rootPath = await mkdtemp(
|
|
1233
|
+
join(tmpdir(), 'generate-service-code-v2-custom-gen-sync-')
|
|
1234
|
+
);
|
|
1235
|
+
roots.add(rootPath);
|
|
1236
|
+
const schemaRoot = join(rootPath, 'app/src/schemas/FlowSchemas');
|
|
1237
|
+
await mkdir(schemaRoot, { recursive: true });
|
|
1238
|
+
await writeFile(
|
|
1239
|
+
join(schemaRoot, 'GenSync.js'),
|
|
1240
|
+
`export default {
|
|
1241
|
+
flowTag: 'genSync',
|
|
1242
|
+
event: ['generateCode'],
|
|
1243
|
+
generatedCodeConfig: {
|
|
1244
|
+
generateCodeTag: 'create',
|
|
1245
|
+
codeHookTag: 'before',
|
|
1246
|
+
invocationType: 'lambdaSyncInv'
|
|
1247
|
+
},
|
|
1248
|
+
flowSteps: [{ stepName: 'Start', properties: ['dummyId'] }],
|
|
1249
|
+
stepProperties: { dummyId: { type: 'string' } }
|
|
1250
|
+
};\n`
|
|
1251
|
+
);
|
|
1252
|
+
|
|
1253
|
+
await generateCustomFlowApplicationArtifacts(rootPath);
|
|
1254
|
+
|
|
1255
|
+
const mainPath = join(
|
|
1256
|
+
rootPath,
|
|
1257
|
+
'app/src/generatedCode/FlowSchemas/GenSync/source/GenSync_Main.js'
|
|
1258
|
+
);
|
|
1259
|
+
const hdrInvPath = join(
|
|
1260
|
+
rootPath,
|
|
1261
|
+
'app/src/generatedCode/FlowSchemas/GenSync/source/GenSync_HdrInv.js'
|
|
1262
|
+
);
|
|
1263
|
+
|
|
1264
|
+
assert.match(await readFile(mainPath, 'utf8'), /export default async function GenSync/);
|
|
1265
|
+
assert.match(await readFile(hdrInvPath, 'utf8'), /GenSync_Main/);
|
|
1266
|
+
|
|
1267
|
+
const yaml = await readFile(
|
|
1268
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-schema.yml'),
|
|
1269
|
+
'utf8'
|
|
1270
|
+
);
|
|
1271
|
+
assert.match(yaml, /GenSyncHdrInv:/);
|
|
1272
|
+
});
|
|
1273
|
+
|
|
@@ -672,6 +672,105 @@ test('emits SQS queues and deduplicated IAM policies when generateCodeTag is an
|
|
|
672
672
|
assert.strictEqual(notifyTopicMatches?.length, 1);
|
|
673
673
|
});
|
|
674
674
|
|
|
675
|
+
test('rejects flow schema with event generateCode missing generatedCodeConfig', async () => {
|
|
676
|
+
const rootPath = await createProject();
|
|
677
|
+
const flowDirectory = join(rootPath, 'app/src/schemas/FlowSchemas');
|
|
678
|
+
await writeFile(
|
|
679
|
+
join(flowDirectory, 'MissingConfig.js'),
|
|
680
|
+
"export default { flowTag: 'missingConfig', event: ['generateCode'] };\n"
|
|
681
|
+
);
|
|
682
|
+
|
|
683
|
+
await assert.rejects(
|
|
684
|
+
generateResourceArtifacts(rootPath),
|
|
685
|
+
/flow with event 'generateCode' requires generatedCodeConfig/
|
|
686
|
+
);
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
test('rejects flow schema with event generateCode and invalid invocationType', async () => {
|
|
690
|
+
const rootPath = await createProject();
|
|
691
|
+
const flowDirectory = join(rootPath, 'app/src/schemas/FlowSchemas');
|
|
692
|
+
await writeFile(
|
|
693
|
+
join(flowDirectory, 'InvalidInvocation.js'),
|
|
694
|
+
"export default { flowTag: 'invalidInvocation', event: ['generateCode'], " +
|
|
695
|
+
"generatedCodeConfig: { invocationType: 'invalidType' } };\n"
|
|
696
|
+
);
|
|
697
|
+
|
|
698
|
+
await assert.rejects(
|
|
699
|
+
generateResourceArtifacts(rootPath),
|
|
700
|
+
/invocationType 'invalidType' is invalid/
|
|
701
|
+
);
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
test('emits SQS resources, SNS topics, and IAM role when flow has event generateCode with invocationType ownTopic', async () => {
|
|
705
|
+
const rootPath = await createProject();
|
|
706
|
+
const schemas = join(rootPath, 'app/src/schemas');
|
|
707
|
+
await writeFile(
|
|
708
|
+
join(schemas, 'FlowSchemas/GenOwnHook.js'),
|
|
709
|
+
"export default { flowTag: 'genOwnHook', event: ['generateCode'], " +
|
|
710
|
+
"generatedCodeConfig: { generateCodeTag: 'create', codeHookTag: 'before', " +
|
|
711
|
+
"invocationType: 'ownTopic' }, objType: { objectType: 'order' } };\n"
|
|
712
|
+
);
|
|
713
|
+
await generateResourceArtifacts(rootPath);
|
|
714
|
+
|
|
715
|
+
const crudResources = await readFile(
|
|
716
|
+
join(
|
|
717
|
+
rootPath,
|
|
718
|
+
'resource/sls_yaml/generatedCode/source/generated-sns-sqs-crud.yml'
|
|
719
|
+
),
|
|
720
|
+
'utf8'
|
|
721
|
+
);
|
|
722
|
+
assert.match(crudResources, /^ CreateBeforeHookCallbackHdrSqs:/m);
|
|
723
|
+
|
|
724
|
+
const customResources = await readFile(
|
|
725
|
+
join(
|
|
726
|
+
rootPath,
|
|
727
|
+
'resource/sls_yaml/generatedCode/source/generated-sns-sqs-custom-flows.yml'
|
|
728
|
+
),
|
|
729
|
+
'utf8'
|
|
730
|
+
);
|
|
731
|
+
assert.match(customResources, /^ GenOwnHookHdrSqs:/m);
|
|
732
|
+
assert.match(customResources, /^ InGenOwnHook:/m);
|
|
733
|
+
|
|
734
|
+
const iam = await readFile(
|
|
735
|
+
join(
|
|
736
|
+
rootPath,
|
|
737
|
+
'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
|
|
738
|
+
),
|
|
739
|
+
'utf8'
|
|
740
|
+
);
|
|
741
|
+
const flowRole = roleBlock(iam, 'FlowObjectsRole');
|
|
742
|
+
assert.match(flowRole, /CreateBeforeHookCallbackHdrSqs/);
|
|
743
|
+
assert.match(flowRole, /GenOwnHook_In/);
|
|
744
|
+
|
|
745
|
+
const customRole = roleBlock(iam, 'GenOwnHookRole');
|
|
746
|
+
assert.match(customRole, /GenOwnHookHdrSqs/);
|
|
747
|
+
assert.match(customRole, /GenOwnHook_In/);
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
test('emits lambda:InvokeFunction in FlowObjectsRole when flow has event generateCode with invocationType lambdaSyncInv', async () => {
|
|
751
|
+
const rootPath = await createProject();
|
|
752
|
+
const schemas = join(rootPath, 'app/src/schemas');
|
|
753
|
+
await writeFile(
|
|
754
|
+
join(schemas, 'FlowSchemas/GenSyncHook.js'),
|
|
755
|
+
"export default { flowTag: 'genSyncHook', event: ['generateCode'], " +
|
|
756
|
+
"generatedCodeConfig: { generateCodeTag: 'create', codeHookTag: 'before', " +
|
|
757
|
+
"invocationType: 'lambdaSyncInv' }, objType: { objectType: 'order' } };\n"
|
|
758
|
+
);
|
|
759
|
+
await generateResourceArtifacts(rootPath);
|
|
760
|
+
|
|
761
|
+
const iam = await readFile(
|
|
762
|
+
join(
|
|
763
|
+
rootPath,
|
|
764
|
+
'app/sls_yaml/generatedCode/source/generate-shared-resource.yml'
|
|
765
|
+
),
|
|
766
|
+
'utf8'
|
|
767
|
+
);
|
|
768
|
+
const role = roleBlock(iam, 'FlowObjectsRole');
|
|
769
|
+
assert.match(role, /lambda:InvokeFunction/);
|
|
770
|
+
assert.match(role, /GenSyncHook/);
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
|
|
675
774
|
function roleBlock(iam, roleName) {
|
|
676
775
|
const match = iam.match(
|
|
677
776
|
new RegExp(
|