@izara_project/izara-core-generate-service-code 1.0.68 → 1.0.69
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 +1 -1
- package/scripts/format-ejs.js +1 -2
- package/src/compile/compileProject.js +26 -10
- package/src/compile/loadSchemas.js +47 -23
- package/src/emit/crud/emitCrudApplicationArtifacts.js +188 -41
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +34 -17
- package/src/emit/crud/generateCrudApplicationArtifacts.js +14 -6
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
- package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
- package/src/emit/custom/customFlows.js +23 -13
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +515 -113
- package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +28 -8
- package/src/emit/custom/templates/s3/FlowHandler_HdrS3.ejs +2 -2
- package/src/emit/custom/templates/s3/ReservedLimit_HdrSqs.ejs +1 -1
- package/src/emit/function/functionYamlArtifact.js +270 -97
- package/src/emit/function/templates/ApiFunction_Yaml.ejs +7 -0
- package/src/emit/function/templates/EventBridgeFunction_Yaml.ejs +6 -0
- package/src/emit/function/templates/InvFunction_Yaml.ejs +5 -0
- package/src/emit/function/templates/S3Function_Yaml.ejs +16 -0
- package/src/emit/function/templates/SqsFunction_Yaml.ejs +10 -0
- package/src/emit/function/templates/WbsFunction_Yaml.ejs +10 -0
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +28 -30
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +6 -6
- package/src/emit/rbac/generateCreateTargetRoleHandler.js +6 -4
- package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +8 -2
- package/src/emit/rbac/rbacFlowTag.js +3 -1
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +1 -1
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +26 -10
- package/src/emit/relationship/emitRelationshipApplicationArtifacts.js +179 -37
- package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +8 -2
- package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +15 -6
- package/src/emit/resource/emitResourceArtifacts.js +187 -114
- package/src/emit/resource/generateResourceArtifacts.js +15 -6
- package/src/emit/resource/templates/DynamoDBTable_Yaml.ejs +18 -18
- package/src/emit/resource/templates/FlowOut_Yaml.ejs +5 -5
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +10 -9
- package/src/emit/resource/templates/ResourceBeforeLogicalYaml.ejs +44 -44
- package/src/emit/resource/templates/ResourceSqsYaml.ejs +36 -36
- package/src/emit/resource/templates/ResourceYaml.ejs +48 -48
- package/src/emit/resource/templates/S3Subscription_Yaml.ejs +7 -0
- package/src/emit/resource/templates/SharedResource_Yaml.ejs +11 -11
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +105 -105
- package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
- package/src/emit/system/emitSystemWebSocketArtifacts.js +61 -165
- package/src/emit/system/templates/WebSocketComplete_HdrSqs.ejs +32 -0
- package/src/emit/system/templates/WebSocketComplete_Main.ejs +46 -0
- package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +19 -0
- package/src/emit/system/templates/WebSocketConnect.ejs +25 -0
- package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +11 -0
- package/src/generate.js +136 -33
- package/src/generateIntTest.js +76 -28
- package/src/generateResourceIntTest.js +35 -12
- package/src/generateResources/IntTest/generateResources/generateResources.js +5 -2
- package/src/generateResources/IntTest/generateResources/templateResources.ejs +18 -30
- package/src/generateResources/IntTest/generateTests/events/events.js +1 -1
- package/src/generateResources/IntTest/generateTests/events/templateEvents.ejs +13 -10
- package/src/generateResources/IntTest/generateTests/generateTemplate.js +2 -2
- package/src/generateResources/IntTest/generateTests/pathIntTest/pathIntTest.js +2 -1
- package/src/generateResources/IntTest/generateTests/pathIntTest/template.ejs +1 -3
- package/src/generateResources/IntTest/generateTests/tests/templateTests.ejs +1 -1
- package/src/generateResources/IntTest/generateTests/tests/tests.js +7 -3
- package/src/generateResources/IntTest/libs/{libs.js → IntTestGenerateLib.js} +34 -23
- package/src/generateResources/IntTest/upload/uploadIntTest.js +33 -19
- package/src/intTestGeneratorShared.js +15 -10
- package/src/output/commitArtifacts.js +99 -39
- package/src/output/mergeHooks.js +24 -10
- package/src/output/validateArtifacts.js +37 -27
- package/src/plan/buildGenerationPlan.js +24 -13
- package/test/core.test.js +116 -49
- package/test/createTargetRoleHandler.test.js +1 -1
- package/test/crudApplicationArtifacts.test.js +128 -23
- package/test/customFlowApplicationArtifacts.test.js +353 -71
- package/test/dynamicCrudFlowSchemas.test.js +74 -26
- package/test/dynamicRbacFlowSchemas.test.js +61 -14
- package/test/dynamicRelationshipFlowSchemas.test.js +65 -18
- package/test/functionYamlArtifact.test.js +67 -10
- package/test/intTestApi.test.js +9 -10
- package/test/publicApi.test.js +176 -34
- package/test/relationshipApplicationArtifacts.test.js +90 -19
- package/test/resourceArtifacts.test.js +172 -32
- package/src/emit/relationship/dynamicRelationshipFlowSchemaTemplate.js +0 -11
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ejsLib from 'ejs';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -92,7 +92,7 @@ export async function emitResourceArtifacts({
|
|
|
92
92
|
renderLambdaRoleConfig(state),
|
|
93
93
|
renderS3(state)
|
|
94
94
|
]);
|
|
95
|
-
|
|
95
|
+
const artifacts = [
|
|
96
96
|
{
|
|
97
97
|
path: `${RESOURCE_ROOT}/generated-sns-in-sqs.yml`,
|
|
98
98
|
content: normalizeYaml(inSqs)
|
|
@@ -105,10 +105,6 @@ export async function emitResourceArtifacts({
|
|
|
105
105
|
path: `${RESOURCE_ROOT}/generated-dynamoDB-table.yml`,
|
|
106
106
|
content: normalizeYaml(dynamo)
|
|
107
107
|
},
|
|
108
|
-
{
|
|
109
|
-
path: `${RESOURCE_ROOT}/generated-s3.yml`,
|
|
110
|
-
content: normalizeYaml(s3)
|
|
111
|
-
},
|
|
112
108
|
{
|
|
113
109
|
path: `${APP_ROOT}/generate-shared-resource.yml`,
|
|
114
110
|
content: normalizeYaml(iam)
|
|
@@ -118,6 +114,13 @@ export async function emitResourceArtifacts({
|
|
|
118
114
|
content: lambdaRoleConfig
|
|
119
115
|
}
|
|
120
116
|
];
|
|
117
|
+
if (state.s3Buckets.length > 0) {
|
|
118
|
+
artifacts.push({
|
|
119
|
+
path: `${RESOURCE_ROOT}/generated-s3.yml`,
|
|
120
|
+
content: normalizeYaml(s3)
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return artifacts;
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
export const resourceArtifactPaths = [
|
|
@@ -134,62 +137,60 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
134
137
|
const rbac = objects.some(hasRbacAddOn);
|
|
135
138
|
const ownTopics = new Set(
|
|
136
139
|
flows
|
|
137
|
-
.filter(flow => includesEvent(flow, 'ownTopic'))
|
|
138
|
-
.map(flow => upperFirst(flow.flowTag))
|
|
140
|
+
.filter((flow) => includesEvent(flow, 'ownTopic'))
|
|
141
|
+
.map((flow) => upperFirst(flow.flowTag))
|
|
139
142
|
);
|
|
140
143
|
const sqsQueues = new Set([
|
|
141
144
|
...LEGACY_PROCESS_QUEUES,
|
|
142
145
|
...flows
|
|
143
|
-
.filter(flow => includesEvent(flow, 'extTopic'))
|
|
144
|
-
.map(flow => `Process${upperFirst(flow.flowTag)}HdrSqs`)
|
|
146
|
+
.filter((flow) => includesEvent(flow, 'extTopic'))
|
|
147
|
+
.map((flow) => `Process${upperFirst(flow.flowTag)}HdrSqs`)
|
|
145
148
|
]);
|
|
146
|
-
|
|
147
|
-
sqsQueues.add(`${flowTag}${stepName}HdrSqs`)
|
|
148
|
-
|
|
149
|
-
flows
|
|
150
|
-
|
|
151
|
-
.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
sqsQueues.add(`${tag}ConfirmAfterUploadHdrSqs`);
|
|
156
|
-
});
|
|
149
|
+
for (const { flowTag, stepName } of flowExtTopicSteps(flows)) {
|
|
150
|
+
sqsQueues.add(`${flowTag}${stepName}HdrSqs`);
|
|
151
|
+
}
|
|
152
|
+
for (const flow of flows.filter((flow) => includesEvent(flow, 's3'))) {
|
|
153
|
+
const tag = upperFirst(flow.flowTag);
|
|
154
|
+
sqsQueues.add(`${tag}CreatePreSignUrlHdrSqs`);
|
|
155
|
+
sqsQueues.add(`${tag}ReservedLimitHdrSqs`);
|
|
156
|
+
sqsQueues.add(`${tag}ConfirmAfterUploadHdrSqs`);
|
|
157
|
+
}
|
|
157
158
|
const dsqQueues = new Set(
|
|
158
159
|
flows
|
|
159
|
-
.filter(flow => includesEvent(flow, 'dsq'))
|
|
160
|
-
.map(flow => `${upperFirst(flow.flowTag)}HdrDsq`)
|
|
161
|
-
);
|
|
162
|
-
flowDsqSteps(flows).forEach(({ flowTag, stepName }) =>
|
|
163
|
-
dsqQueues.add(`${flowTag}${stepName}HdrDsq`)
|
|
160
|
+
.filter((flow) => includesEvent(flow, 'dsq'))
|
|
161
|
+
.map((flow) => `${upperFirst(flow.flowTag)}HdrDsq`)
|
|
164
162
|
);
|
|
163
|
+
for (const { flowTag, stepName } of flowDsqSteps(flows)) {
|
|
164
|
+
dsqQueues.add(`${flowTag}${stepName}HdrDsq`);
|
|
165
|
+
}
|
|
165
166
|
if (crud) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
)
|
|
167
|
+
for (const action of CRUD_ACTIONS) {
|
|
168
|
+
ownTopics.add(action);
|
|
169
|
+
}
|
|
170
|
+
for (const action of ['Create', 'Update', 'Delete']) {
|
|
171
|
+
sqsQueues.add(`${action}CompleteHdrSqs`);
|
|
172
|
+
}
|
|
170
173
|
}
|
|
171
174
|
if (relationships.length > 0) {
|
|
172
|
-
|
|
175
|
+
for (const action of RELATIONSHIP_ACTIONS) {
|
|
173
176
|
ownTopics.add(action);
|
|
174
177
|
sqsQueues.add(`${action}CompleteHdrSqs`);
|
|
175
|
-
}
|
|
178
|
+
}
|
|
176
179
|
dsqQueues.add('GetRelationshipHdrDsq');
|
|
177
180
|
}
|
|
178
181
|
if (rbac) {
|
|
179
|
-
|
|
182
|
+
for (const action of RBAC_ACTIONS) {
|
|
180
183
|
ownTopics.add(action);
|
|
181
184
|
sqsQueues.add(`Process${action}HdrSqs`);
|
|
182
|
-
}
|
|
183
|
-
objects
|
|
184
|
-
.
|
|
185
|
-
.
|
|
186
|
-
|
|
187
|
-
ownTopics.add(flowTag);
|
|
188
|
-
});
|
|
185
|
+
}
|
|
186
|
+
for (const object of objects.filter(hasRbacAddOn)) {
|
|
187
|
+
const flowTag = upperFirst(object.objectType) + 'RbacFlow';
|
|
188
|
+
ownTopics.add(flowTag);
|
|
189
|
+
}
|
|
189
190
|
}
|
|
190
191
|
const beforeLogicalByAction = new Map();
|
|
191
192
|
for (const flow of flows.filter(
|
|
192
|
-
flow => flow?.generatedCodeConfig?.codeHookTag === 'beforeLogical'
|
|
193
|
+
(flow) => flow?.generatedCodeConfig?.codeHookTag === 'beforeLogical'
|
|
193
194
|
)) {
|
|
194
195
|
const action = upperFirst(flow.generatedCodeConfig.generatedCodeTag);
|
|
195
196
|
if (!action || !flow.flowTag) continue;
|
|
@@ -202,10 +203,10 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
202
203
|
);
|
|
203
204
|
const customRoles = [
|
|
204
205
|
...new Set([
|
|
205
|
-
...supportedCustomFlows(flows).map(flow =>
|
|
206
|
+
...supportedCustomFlows(flows).map((flow) =>
|
|
206
207
|
customFlowRoleName(flow.flowTag)
|
|
207
208
|
),
|
|
208
|
-
...generatedOwnTopicFlows(flows).map(flow =>
|
|
209
|
+
...generatedOwnTopicFlows(flows).map((flow) =>
|
|
209
210
|
customFlowRoleName(flow.flowTag)
|
|
210
211
|
),
|
|
211
212
|
...flowExtTopicSteps(flows).map(({ flow }) =>
|
|
@@ -217,21 +218,28 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
217
218
|
const websocket = hasSystemWebSocket(flows, {
|
|
218
219
|
includeRelationshipOwnTopic: true
|
|
219
220
|
});
|
|
220
|
-
const webSocketRoles = new Set(
|
|
221
|
+
const webSocketRoles = new Set();
|
|
222
|
+
if (websocket) {
|
|
223
|
+
webSocketRoles.add('WebSocketMainRole');
|
|
224
|
+
}
|
|
221
225
|
if (crud) webSocketRoles.add('FlowObjectsRole');
|
|
222
226
|
if (relationships.length > 0) webSocketRoles.add('FlowRelationshipRole');
|
|
223
227
|
if (rbac) webSocketRoles.add('FlowRbacRole');
|
|
224
|
-
[
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
228
|
+
const filteredWsFlows = [
|
|
229
|
+
...supportedCustomFlows(flows),
|
|
230
|
+
...generatedOwnTopicFlows(flows)
|
|
231
|
+
].filter(
|
|
232
|
+
(flow) => includesEvent(flow, 'ownTopic') || includesEvent(flow, 's3')
|
|
233
|
+
);
|
|
234
|
+
for (const flow of filteredWsFlows) {
|
|
235
|
+
webSocketRoles.add(customFlowRoleName(flow.flowTag));
|
|
236
|
+
}
|
|
229
237
|
const outTopics = new Set([
|
|
230
238
|
...ownTopics,
|
|
231
239
|
...beforeLogical.map(({ action }) => action),
|
|
232
240
|
...flows
|
|
233
|
-
.filter(flow => flow?.outputTopic && upperFirst(flow.flowTag))
|
|
234
|
-
.map(flow => upperFirst(flow.flowTag))
|
|
241
|
+
.filter((flow) => flow?.outputTopic && upperFirst(flow.flowTag))
|
|
242
|
+
.map((flow) => upperFirst(flow.flowTag))
|
|
235
243
|
]);
|
|
236
244
|
const objectTableNames = [...collectTables(objects).keys()];
|
|
237
245
|
const relationshipTableNames = [...collectTables(relationships).keys()];
|
|
@@ -240,15 +248,36 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
240
248
|
...collectTables(relationships)
|
|
241
249
|
]);
|
|
242
250
|
const externalDynamoTables = objects.flatMap(
|
|
243
|
-
object => object.externalDynamoResources ?? []
|
|
251
|
+
(object) => object.externalDynamoResources ?? []
|
|
244
252
|
);
|
|
245
253
|
const s3Buckets = flows
|
|
246
|
-
.filter(flow => includesEvent(flow, 's3') && flow.createBucket === true)
|
|
247
|
-
.map(flow => flow.bucketName)
|
|
254
|
+
.filter((flow) => includesEvent(flow, 's3') && flow.createBucket === true)
|
|
255
|
+
.map((flow) => flow.bucketName)
|
|
248
256
|
.filter(Boolean);
|
|
257
|
+
const s3FlowTags = flows
|
|
258
|
+
.filter((flow) => includesEvent(flow, 's3'))
|
|
259
|
+
.map((flow) => upperFirst(flow.flowTag));
|
|
260
|
+
const s3Subscriptions = flows
|
|
261
|
+
.filter((flow) => includesEvent(flow, 's3'))
|
|
262
|
+
.map((flow) => {
|
|
263
|
+
const tag = upperFirst(flow.flowTag);
|
|
264
|
+
const topicName = flow.outputTopic
|
|
265
|
+
? flow.outputTopic.startsWith('Out')
|
|
266
|
+
? flow.outputTopic
|
|
267
|
+
: `Out${upperFirst(flow.outputTopic)}`
|
|
268
|
+
: flow.s3Subscription?.topicName || 'OutCreate';
|
|
269
|
+
const queueName =
|
|
270
|
+
flow.s3Subscription?.queueName || `${tag}ReservedLimitHdrSqs`;
|
|
271
|
+
const subscriptionName =
|
|
272
|
+
flow.s3Subscription?.subscriptionName ||
|
|
273
|
+
`Subscription${topicName}To${queueName}`;
|
|
274
|
+
return { subscriptionName, topicName, queueName };
|
|
275
|
+
});
|
|
249
276
|
return {
|
|
250
277
|
crud,
|
|
251
278
|
rbac,
|
|
279
|
+
s3Subscriptions,
|
|
280
|
+
s3FlowTags,
|
|
252
281
|
relationships: relationships.length > 0,
|
|
253
282
|
ownTopics: [...ownTopics].filter(Boolean).sort(),
|
|
254
283
|
sqsQueues: [...sqsQueues].filter(Boolean).sort(),
|
|
@@ -260,9 +289,9 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
260
289
|
webSocketSubscriptions: websocket
|
|
261
290
|
? [...outTopics]
|
|
262
291
|
.filter(
|
|
263
|
-
topic =>
|
|
292
|
+
(topic) =>
|
|
264
293
|
flows.some(
|
|
265
|
-
flow =>
|
|
294
|
+
(flow) =>
|
|
266
295
|
(flow?.outputTopic ||
|
|
267
296
|
(includesEvent(flow, 'ownTopic') &&
|
|
268
297
|
flow.initiateBy === 'user')) &&
|
|
@@ -285,10 +314,10 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
285
314
|
externalDynamoTables,
|
|
286
315
|
objectTablesByType: new Map(
|
|
287
316
|
objects
|
|
288
|
-
.map(object => [
|
|
317
|
+
.map((object) => [
|
|
289
318
|
object.objectType,
|
|
290
319
|
Object.values(object.storageResources ?? {}).find(
|
|
291
|
-
resource => resource?.storageType === 'dynamoDB'
|
|
320
|
+
(resource) => resource?.storageType === 'dynamoDB'
|
|
292
321
|
)?.tableName
|
|
293
322
|
])
|
|
294
323
|
.filter(([, tableName]) => tableName)
|
|
@@ -300,22 +329,25 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
300
329
|
|
|
301
330
|
async function renderS3(state) {
|
|
302
331
|
if (state.s3Buckets.length === 0) return 'Resources:';
|
|
303
|
-
const template = await readFile(
|
|
332
|
+
const template = await readFile(
|
|
333
|
+
new URL('S3Bucket_Yaml.ejs', TEMPLATE_URL),
|
|
334
|
+
'utf8'
|
|
335
|
+
);
|
|
304
336
|
const chunks = await Promise.all(
|
|
305
|
-
state.s3Buckets.map(bucketName =>
|
|
337
|
+
state.s3Buckets.map((bucketName) => ejsLib.render(template, { bucketName }))
|
|
306
338
|
);
|
|
307
339
|
return `Resources:\n${chunks.join('\n')}`;
|
|
308
340
|
}
|
|
309
341
|
|
|
310
342
|
async function renderInSqs(state) {
|
|
311
343
|
const chunks = await Promise.all([
|
|
312
|
-
...state.ownTopics.map(queueName =>
|
|
344
|
+
...state.ownTopics.map((queueName) =>
|
|
313
345
|
render('ResourceYaml.ejs', { queueName })
|
|
314
346
|
),
|
|
315
|
-
...state.sqsQueues.map(queueName =>
|
|
347
|
+
...state.sqsQueues.map((queueName) =>
|
|
316
348
|
render('ResourceSqsYaml.ejs', { queueName })
|
|
317
349
|
),
|
|
318
|
-
...state.dsqQueues.map(queueName =>
|
|
350
|
+
...state.dsqQueues.map((queueName) =>
|
|
319
351
|
render('ResourceSqsYaml.ejs', { queueName })
|
|
320
352
|
),
|
|
321
353
|
...state.beforeLogical.map(({ action, flowTags }) =>
|
|
@@ -332,17 +364,39 @@ async function renderInSqs(state) {
|
|
|
332
364
|
]
|
|
333
365
|
: [])
|
|
334
366
|
]);
|
|
335
|
-
|
|
367
|
+
const webSocketSubscriptions = await Promise.all(
|
|
368
|
+
state.webSocketSubscriptions.map((topicName) =>
|
|
369
|
+
renderWebSocketSubscription(topicName)
|
|
370
|
+
)
|
|
371
|
+
);
|
|
372
|
+
const s3Subscriptions = await Promise.all(
|
|
373
|
+
(state.s3Subscriptions ?? []).map(
|
|
374
|
+
({ subscriptionName, topicName, queueName }) =>
|
|
375
|
+
render('S3Subscription_Yaml.ejs', {
|
|
376
|
+
subscriptionName,
|
|
377
|
+
topicName,
|
|
378
|
+
queueName
|
|
379
|
+
})
|
|
380
|
+
)
|
|
381
|
+
);
|
|
382
|
+
const parts = [chunks.join('\n')];
|
|
383
|
+
if (webSocketSubscriptions.length > 0) {
|
|
384
|
+
parts.push(webSocketSubscriptions.join('\n'));
|
|
385
|
+
}
|
|
386
|
+
if (s3Subscriptions.length > 0) {
|
|
387
|
+
parts.push(s3Subscriptions.join('\n'));
|
|
388
|
+
}
|
|
389
|
+
return `Resources:\n${parts.join('\n')}`;
|
|
336
390
|
}
|
|
337
391
|
|
|
338
392
|
async function renderOut(state) {
|
|
339
|
-
return `Resources:\n${(await Promise.all(state.outTopics.map(topicName => render('FlowOut_Yaml.ejs', { topicName })))).join('\n')}`;
|
|
393
|
+
return `Resources:\n${(await Promise.all(state.outTopics.map((topicName) => render('FlowOut_Yaml.ejs', { topicName })))).join('\n')}`;
|
|
340
394
|
}
|
|
341
395
|
|
|
342
396
|
async function renderDynamo(state) {
|
|
343
397
|
const [system, ...tables] = await Promise.all([
|
|
344
398
|
render('SystemDynamoDB_Yaml.ejs', {}),
|
|
345
|
-
...state.tables.map(table => render('DynamoDBTable_Yaml.ejs', table))
|
|
399
|
+
...state.tables.map((table) => render('DynamoDBTable_Yaml.ejs', table))
|
|
346
400
|
]);
|
|
347
401
|
return `${system}\n${tables.join('\n')}`;
|
|
348
402
|
}
|
|
@@ -355,7 +409,7 @@ async function renderIam(state) {
|
|
|
355
409
|
if (state.websocket) roles.push('WebSocketMainRole');
|
|
356
410
|
roles.push(...state.customRoles);
|
|
357
411
|
return render('SharedResource_Yaml.ejs', {
|
|
358
|
-
roles: roles.sort().map(roleName => ({
|
|
412
|
+
roles: roles.sort().map((roleName) => ({
|
|
359
413
|
roleName,
|
|
360
414
|
statements: roleStatements(state, roleName)
|
|
361
415
|
}))
|
|
@@ -364,8 +418,8 @@ async function renderIam(state) {
|
|
|
364
418
|
|
|
365
419
|
async function renderLambdaRoleConfig(state) {
|
|
366
420
|
const s3Flows = state.flows
|
|
367
|
-
.filter(flow => includesEvent(flow, 's3'))
|
|
368
|
-
.map(flow => ({
|
|
421
|
+
.filter((flow) => includesEvent(flow, 's3'))
|
|
422
|
+
.map((flow) => ({
|
|
369
423
|
roleName: upperFirst(flow.flowTag)
|
|
370
424
|
}));
|
|
371
425
|
return render('GeneratedLambdaRoleServiceConfig.ejs', {
|
|
@@ -385,14 +439,10 @@ function roleStatements(state, roleName) {
|
|
|
385
439
|
]
|
|
386
440
|
});
|
|
387
441
|
}
|
|
388
|
-
addStatement(
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
...dynamoArns(roleTableNames(state, roleName)),
|
|
393
|
-
...externalDynamoArns(roleExternalDynamoTables(state, roleName))
|
|
394
|
-
]
|
|
395
|
-
);
|
|
442
|
+
addStatement(statements, dynamoActionsForRole(roleName), [
|
|
443
|
+
...dynamoArns(roleTableNames(state, roleName)),
|
|
444
|
+
...externalDynamoArns(roleExternalDynamoTables(state, roleName))
|
|
445
|
+
]);
|
|
396
446
|
addStatement(
|
|
397
447
|
statements,
|
|
398
448
|
SQS_CONSUMER_ACTIONS,
|
|
@@ -452,7 +502,7 @@ function roleTableNames(state, roleName) {
|
|
|
452
502
|
'LogicalResultsData'
|
|
453
503
|
];
|
|
454
504
|
const flow = state.flows.find(
|
|
455
|
-
candidate => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
505
|
+
(candidate) => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
456
506
|
);
|
|
457
507
|
if (!flow) return [];
|
|
458
508
|
const tables = [];
|
|
@@ -477,68 +527,91 @@ function dynamoActionsForRole(roleName) {
|
|
|
477
527
|
}
|
|
478
528
|
|
|
479
529
|
function roleQueueNames(state, roleName) {
|
|
480
|
-
if (roleName === 'ProcFindDataRole')
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if (roleName === '
|
|
530
|
+
if (roleName === 'ProcFindDataRole') {
|
|
531
|
+
return LEGACY_PROCESS_QUEUES;
|
|
532
|
+
}
|
|
533
|
+
if (roleName === 'WebSocketMainRole') {
|
|
534
|
+
if (state.websocket) {
|
|
535
|
+
return ['WebSocketCompleteHdrSqs'];
|
|
536
|
+
}
|
|
537
|
+
return [];
|
|
538
|
+
}
|
|
539
|
+
if (roleName === 'FlowObjectsRole') {
|
|
484
540
|
return [
|
|
485
|
-
...CRUD_ACTIONS.map(action => `${action}HdrSqs`),
|
|
486
|
-
...CRUD_ACTIONS.filter(action => action !== 'Get').map(
|
|
487
|
-
action => `${action}CompleteHdrSqs`
|
|
541
|
+
...CRUD_ACTIONS.map((action) => `${action}HdrSqs`),
|
|
542
|
+
...CRUD_ACTIONS.filter((action) => action !== 'Get').map(
|
|
543
|
+
(action) => `${action}CompleteHdrSqs`
|
|
488
544
|
),
|
|
489
545
|
...state.beforeLogical
|
|
490
546
|
.filter(({ action }) => CRUD_ACTIONS.includes(action))
|
|
491
547
|
.map(({ action }) => `${action}BeforeLogicalHdrSqs`)
|
|
492
548
|
];
|
|
493
|
-
|
|
549
|
+
}
|
|
550
|
+
if (roleName === 'FlowRelationshipRole') {
|
|
494
551
|
return [
|
|
495
|
-
...RELATIONSHIP_ACTIONS.flatMap(action => [
|
|
552
|
+
...RELATIONSHIP_ACTIONS.flatMap((action) => [
|
|
496
553
|
`${action}HdrSqs`,
|
|
497
554
|
`${action}CompleteHdrSqs`
|
|
498
555
|
]),
|
|
499
556
|
'GetRelationshipHdrDsq'
|
|
500
557
|
];
|
|
501
|
-
|
|
502
|
-
|
|
558
|
+
}
|
|
559
|
+
if (roleName === 'FlowRbacRole') {
|
|
560
|
+
return RBAC_ACTIONS.flatMap((action) => [
|
|
503
561
|
`${action}HdrSqs`,
|
|
504
562
|
`Process${action}HdrSqs`
|
|
505
563
|
]);
|
|
564
|
+
}
|
|
506
565
|
const flow = state.flows.find(
|
|
507
|
-
candidate => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
566
|
+
(candidate) => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
508
567
|
);
|
|
509
|
-
if (!flow)
|
|
568
|
+
if (!flow) {
|
|
569
|
+
return [];
|
|
570
|
+
}
|
|
510
571
|
const tag = upperFirst(flow.flowTag);
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
572
|
+
const queueList = [];
|
|
573
|
+
if (includesEvent(flow, 'extTopic')) {
|
|
574
|
+
queueList.push(`${tag}HdrSqs`);
|
|
575
|
+
}
|
|
576
|
+
if (includesEvent(flow, 'ownTopic')) {
|
|
577
|
+
queueList.push(`${tag}HdrSqs`);
|
|
578
|
+
}
|
|
579
|
+
if (includesEvent(flow, 'dsq')) {
|
|
580
|
+
queueList.push(`${tag}HdrDsq`);
|
|
581
|
+
}
|
|
582
|
+
queueList.push(
|
|
515
583
|
...flowExtTopicSteps([flow]).map(
|
|
516
584
|
({ flowTag, stepName }) => `${flowTag}${stepName}HdrSqs`
|
|
517
|
-
)
|
|
585
|
+
)
|
|
586
|
+
);
|
|
587
|
+
queueList.push(
|
|
518
588
|
...flowDsqSteps([flow]).map(
|
|
519
589
|
({ flowTag, stepName }) => `${flowTag}${stepName}HdrDsq`
|
|
520
|
-
)
|
|
590
|
+
)
|
|
591
|
+
);
|
|
592
|
+
queueList.push(
|
|
521
593
|
...state.sqsQueues.filter(
|
|
522
|
-
queueName => includesEvent(flow, 's3') && queueName.startsWith(tag)
|
|
594
|
+
(queueName) => includesEvent(flow, 's3') && queueName.startsWith(tag)
|
|
523
595
|
)
|
|
524
|
-
|
|
596
|
+
);
|
|
597
|
+
return queueList;
|
|
525
598
|
}
|
|
526
599
|
|
|
527
600
|
function roleTopicNames(state, roleName) {
|
|
528
601
|
if (roleName === 'ProcFindDataRole') return [];
|
|
529
602
|
if (roleName === 'FlowObjectsRole')
|
|
530
|
-
return state.outTopics.filter(topic => CRUD_ACTIONS.includes(topic));
|
|
603
|
+
return state.outTopics.filter((topic) => CRUD_ACTIONS.includes(topic));
|
|
531
604
|
if (roleName === 'FlowRelationshipRole')
|
|
532
|
-
return state.outTopics.filter(topic =>
|
|
605
|
+
return state.outTopics.filter((topic) =>
|
|
533
606
|
RELATIONSHIP_ACTIONS.includes(topic)
|
|
534
607
|
);
|
|
535
608
|
if (roleName === 'FlowRbacRole')
|
|
536
|
-
return state.outTopics.filter(topic => RBAC_ACTIONS.includes(topic));
|
|
609
|
+
return state.outTopics.filter((topic) => RBAC_ACTIONS.includes(topic));
|
|
537
610
|
const flow = state.flows.find(
|
|
538
|
-
candidate => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
611
|
+
(candidate) => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
539
612
|
);
|
|
540
613
|
return flow
|
|
541
|
-
? state.outTopics.filter(topic => topic === upperFirst(flow.flowTag))
|
|
614
|
+
? state.outTopics.filter((topic) => topic === upperFirst(flow.flowTag))
|
|
542
615
|
: [];
|
|
543
616
|
}
|
|
544
617
|
|
|
@@ -546,7 +619,7 @@ function dynamoArns(tableNames) {
|
|
|
546
619
|
return [...new Set(tableNames)]
|
|
547
620
|
.sort()
|
|
548
621
|
.map(
|
|
549
|
-
tableName =>
|
|
622
|
+
(tableName) =>
|
|
550
623
|
`arn:aws:dynamodb:${'${self:custom.iz_region}'}:${'${self:custom.iz_accountId}'}:table/${'${self:custom.iz_resourcePrefix}'}${tableName}`
|
|
551
624
|
);
|
|
552
625
|
}
|
|
@@ -601,7 +674,7 @@ function queueArns(queueNames) {
|
|
|
601
674
|
return [...new Set(queueNames)]
|
|
602
675
|
.sort()
|
|
603
676
|
.map(
|
|
604
|
-
queueName =>
|
|
677
|
+
(queueName) =>
|
|
605
678
|
`arn:aws:sqs:${'${self:custom.iz_region}'}:${'${self:custom.iz_accountId}'}:${'${self:custom.iz_resourcePrefix}'}${queueName}`
|
|
606
679
|
);
|
|
607
680
|
}
|
|
@@ -610,13 +683,13 @@ function topicArns(topicNames) {
|
|
|
610
683
|
return [...new Set(topicNames)]
|
|
611
684
|
.sort()
|
|
612
685
|
.map(
|
|
613
|
-
topic =>
|
|
686
|
+
(topic) =>
|
|
614
687
|
`arn:aws:sns:${'${self:custom.iz_region}'}:${'${self:custom.iz_accountId}'}:${'${self:custom.iz_serviceTag}'}_${'${self:custom.iz_stage}'}_${topic}_Out`
|
|
615
688
|
);
|
|
616
689
|
}
|
|
617
690
|
|
|
618
691
|
function renderWebSocketSubscription(topicName) {
|
|
619
|
-
return
|
|
692
|
+
return render('WebSocketSubscription_Yaml.ejs', { topicName });
|
|
620
693
|
}
|
|
621
694
|
|
|
622
695
|
function collectTables(schemas) {
|
|
@@ -629,13 +702,13 @@ function collectTables(schemas) {
|
|
|
629
702
|
const pk =
|
|
630
703
|
keyName(
|
|
631
704
|
identifiers.find(
|
|
632
|
-
identifier =>
|
|
705
|
+
(identifier) =>
|
|
633
706
|
identifier.type === 'partitionKey' ||
|
|
634
707
|
identifier.type === 'identifier'
|
|
635
708
|
)
|
|
636
709
|
) ?? 'PK';
|
|
637
710
|
const sk = keyName(
|
|
638
|
-
identifiers.find(identifier => identifier.type === 'sortKey')
|
|
711
|
+
identifiers.find((identifier) => identifier.type === 'sortKey')
|
|
639
712
|
);
|
|
640
713
|
for (const resource of Object.values(schema.storageResources)) {
|
|
641
714
|
if (
|
|
@@ -650,13 +723,13 @@ function collectTables(schemas) {
|
|
|
650
723
|
}
|
|
651
724
|
|
|
652
725
|
function keyName(identifier) {
|
|
653
|
-
if (!identifier) return
|
|
726
|
+
if (!identifier) return null;
|
|
654
727
|
return (
|
|
655
728
|
identifier.name ??
|
|
656
729
|
identifier.fieldName ??
|
|
657
730
|
(Array.isArray(identifier.fieldNames)
|
|
658
731
|
? identifier.fieldNames.join(identifier.deliminator ?? '_')
|
|
659
|
-
:
|
|
732
|
+
: null)
|
|
660
733
|
);
|
|
661
734
|
}
|
|
662
735
|
|
|
@@ -669,7 +742,7 @@ function isCrudObject(object) {
|
|
|
669
742
|
function hasRbacAddOn(object) {
|
|
670
743
|
return (
|
|
671
744
|
Array.isArray(object?.addOnDataStructure) &&
|
|
672
|
-
object.addOnDataStructure.some(addOn => addOn?.type === 'rbac')
|
|
745
|
+
object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
|
|
673
746
|
);
|
|
674
747
|
}
|
|
675
748
|
function includesEvent(flow, event) {
|
|
@@ -684,7 +757,7 @@ function normalizeYaml(content) {
|
|
|
684
757
|
return `${content.trimEnd()}\n`;
|
|
685
758
|
}
|
|
686
759
|
async function render(templateName, data) {
|
|
687
|
-
return
|
|
760
|
+
return ejsLib.render(
|
|
688
761
|
await readFile(new URL(templateName, TEMPLATE_URL), 'utf8'),
|
|
689
762
|
{ resourceQueueName: data.queueName, ...data }
|
|
690
763
|
);
|
|
@@ -2,7 +2,10 @@ import { buildGenerationPlan } from '../../plan/buildGenerationPlan.js';
|
|
|
2
2
|
import { commitArtifacts } from '../../output/commitArtifacts.js';
|
|
3
3
|
import { compileProject } from '../../compile/compileProject.js';
|
|
4
4
|
import { loadLocalSchemaDirectory } from '../../compile/loadSchemas.js';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
emitResourceArtifacts,
|
|
7
|
+
resourceArtifactPaths
|
|
8
|
+
} from './emitResourceArtifacts.js';
|
|
6
9
|
|
|
7
10
|
export async function generateResourceArtifacts(rootPath, options = {}) {
|
|
8
11
|
const project = compileProject({ ...options, rootPath });
|
|
@@ -11,10 +14,16 @@ export async function generateResourceArtifacts(rootPath, options = {}) {
|
|
|
11
14
|
loadLocalSchemaDirectory(project, 'RelationshipSchemas'),
|
|
12
15
|
loadLocalSchemaDirectory(project, 'FlowSchemas')
|
|
13
16
|
]);
|
|
14
|
-
const artifacts = await emitResourceArtifacts({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
})
|
|
17
|
+
const artifacts = await emitResourceArtifacts({
|
|
18
|
+
objects,
|
|
19
|
+
relationships,
|
|
20
|
+
flows
|
|
21
|
+
});
|
|
22
|
+
const files = await commitArtifacts(
|
|
23
|
+
buildGenerationPlan(project, artifacts, {
|
|
24
|
+
managedPaths: resourceArtifactPaths,
|
|
25
|
+
managedScope: 'shared-resources'
|
|
26
|
+
})
|
|
27
|
+
);
|
|
19
28
|
return { project, files };
|
|
20
29
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
##===== [DynamoDB Table: <%- tableName %>]
|
|
2
|
-
<%- tableName %>Table:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
<%- tableName %>Table:
|
|
3
|
+
Type: AWS::DynamoDB::Table
|
|
4
|
+
Properties:
|
|
5
|
+
TableName: ${self:custom.iz_resourcePrefix}<%- tableName %>
|
|
6
|
+
BillingMode: PAY_PER_REQUEST
|
|
7
|
+
AttributeDefinitions:
|
|
8
|
+
- AttributeName: "<%- pk %>"
|
|
9
|
+
AttributeType: "S"
|
|
10
|
+
<% if (sk) { %>
|
|
11
|
+
- AttributeName: "<%- sk %>"
|
|
12
|
+
AttributeType: "S"
|
|
13
|
+
<% } %>
|
|
14
|
+
KeySchema:
|
|
15
|
+
- AttributeName: "<%- pk %>"
|
|
16
|
+
KeyType: "HASH"
|
|
17
|
+
<% if (sk) { %>
|
|
18
|
+
- AttributeName: "<%- sk %>"
|
|
19
|
+
KeyType: "RANGE"
|
|
20
20
|
<% } %>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
##===== [Topic Out]
|
|
2
|
-
Out<%- topicName %>:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
Out<%- topicName %>:
|
|
3
|
+
Type: AWS::SNS::Topic
|
|
4
|
+
Properties:
|
|
5
|
+
DisplayName: "SNS Message out"
|
|
6
|
+
TopicName: ${self:custom.iz_serviceTag}_${self:custom.iz_stage}_<%- topicName %>_Out
|