@izara_project/izara-core-generate-service-code 1.0.60 → 1.0.62
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 +11 -8
- 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 +12 -22
- 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 +3 -2
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/RbacFlowGenerator.js +4 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowRelationships/RelationshipFlowGenerator.js +2 -1
- 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/FlowSchemas/templates/step/FlowEndpointComplete_Main.ejs +11 -12
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseDsqHandler.js +55 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseSqsHandler.js +20 -21
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/__tests__/BaseDsqHandler.test.js +93 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/dsq.js +5 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/lambdaSyncApi.js +10 -19
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/lambdaSyncInv.js +10 -19
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/ownTopic.js +16 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/registry.js +3 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrApi.ejs +3 -3
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrDsq.ejs +137 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrInv.ejs +3 -3
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/handlers/FlowHandler_HdrSqs.ejs +62 -51
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/eventTypes.js +2 -2
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowEntryPointBase.js +8 -4
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowMainFunctionBase.js +28 -36
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowNaming.js +16 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowSelection.js +0 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepBase.js +11 -5
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepNormalizer.js +48 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowValidator.js +7 -21
- 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/app/src/generatedCode/libs/templates/Consts.ejs +10 -10
- package/src/codeGenerators/resource/sls_yaml/DynamoDBGenerator.js +1 -10
- package/src/codeGenerators/resource/sls_yaml/FlowOutGenerator.js +1 -10
- package/src/codeGenerators/resource/sls_yaml/FlowResourceYamlGenerator.js +3 -12
- package/src/core/validate.js +9 -5
- package/src/generate.js +1 -1
- package/src/generateCode.js +90 -24
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/FlowSchemaGenerator.js +0 -43
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/DynamicFlowSchemaTemplate.ejs +3 -3
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/DynamicRbacFlowSchemaTemplate.ejs +1 -1
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/RelationshipFlowSchemaTemplate.ejs +2 -2
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/UserRbacFlowSchemaTemplate.ejs +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@izara_project/izara-core-generate-service-code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.62",
|
|
4
4
|
"description": "Code for locally generating per service files",
|
|
5
5
|
"homepage": "https://bitbucket.org/izara-core-support-services/izara-core-support-services-generate-service-code#readme",
|
|
6
6
|
"repository": {
|
|
@@ -18,19 +18,22 @@
|
|
|
18
18
|
"testEnvironment": "node"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@izara_project/izara-attribute-tree": "^1.0.15",
|
|
22
21
|
"@izara_project/izara-core-library-core": "^1.0.32",
|
|
23
22
|
"@izara_project/izara-core-library-logger": "^1.0.9",
|
|
24
|
-
"@izara_project/izara-core-library-s3": "^1.0.10",
|
|
25
|
-
"@izara_project/izara-core-library-service-schemas": "^1.0.155",
|
|
26
|
-
"@izara_project/izara-property-nodes": "^1.0.16",
|
|
27
23
|
"@izara_project/izara-shared-core": "^1.0.12",
|
|
28
|
-
"@izara_project/izara-shared-service-schemas": "^1.0.64",
|
|
29
24
|
"ejs": "^5.0.1",
|
|
30
|
-
"js-beautify": "^
|
|
31
|
-
"yaml": "^2.9.0"
|
|
25
|
+
"js-beautify": "^2.0.3",
|
|
26
|
+
"yaml": "^2.9.0",
|
|
27
|
+
"@izara_project/izara-property-nodes": "^1.0.16",
|
|
28
|
+
"@izara_project/izara-attribute-tree": "^1.0.15"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@izara_project/izara-core-library-service-schemas": "^1.0.157",
|
|
32
|
+
"@izara_project/izara-shared-service-schemas": "^1.0.65"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
35
|
+
"@izara_project/izara-core-library-service-schemas": "^1.0.157",
|
|
36
|
+
"@izara_project/izara-shared-service-schemas": "^1.0.65",
|
|
34
37
|
"jest": "^30.4.2"
|
|
35
38
|
}
|
|
36
39
|
}
|
|
@@ -2,146 +2,27 @@ import path from 'path';
|
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
3
|
import ejs from 'ejs';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
detectRoleNames,
|
|
7
|
+
FLOW_OBJECTS_ROLE,
|
|
8
|
+
PROC_FIND_DATA_ROLE,
|
|
9
|
+
FLOW_RELATIONSHIP_ROLE
|
|
10
|
+
} from '../src/generatedCode/Flow/_shared/shared/roleNameDetection.js';
|
|
6
11
|
|
|
7
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
13
|
const __dirname = path.dirname(__filename);
|
|
9
14
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
'DeleteUserFromRole'
|
|
22
|
-
]);
|
|
23
|
-
const REL_FLOW_TAGS = new Set([
|
|
24
|
-
'CreateRelationship',
|
|
25
|
-
'UpdateRelationship',
|
|
26
|
-
'DeleteRelationship',
|
|
27
|
-
'GetRelationship',
|
|
28
|
-
'ChangeRelationship',
|
|
29
|
-
'MoveRelationship'
|
|
30
|
-
]);
|
|
31
|
-
|
|
32
|
-
function upperCase(str) {
|
|
33
|
-
if (!str) return str;
|
|
34
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function detectRoleNames(allSchemas) {
|
|
38
|
-
const flows = getFlowsForGeneration(allSchemas);
|
|
39
|
-
const roleNames = new Set(['ProcFindDataRole']);
|
|
40
|
-
|
|
41
|
-
for (const flow of flows) {
|
|
42
|
-
if (!flow.flowTag) continue;
|
|
43
|
-
|
|
44
|
-
const upperFlowTag = upperCase(flow.flowTag);
|
|
45
|
-
|
|
46
|
-
if (CRUD_FLOW_TAGS.has(upperFlowTag)) {
|
|
47
|
-
roleNames.add(FLOW_OBJECTS_ROLE);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (RBAC_FLOW_TAGS.has(upperFlowTag) || upperFlowTag.endsWith('RbacFlow')) {
|
|
52
|
-
roleNames.add('FlowRbacRole');
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (REL_FLOW_TAGS.has(upperFlowTag)) {
|
|
57
|
-
roleNames.add('FlowRelationshipRole');
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if ((flow.event || []).includes('ownTopic')) {
|
|
62
|
-
roleNames.add('WebSocketMainRole');
|
|
63
|
-
// ponytail: removed continue; so custom flows with ownTopic get their own specific role
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
roleNames.add(`${upperFlowTag}Role`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return { flows, roleNames };
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export async function generateInitialSetup(allSchemas, options) {
|
|
73
|
-
console.log(' [InitialSetupGenerator] Generating Initial Setup Scripts...');
|
|
74
|
-
|
|
75
|
-
const { flows, roleNames } = detectRoleNames(allSchemas);
|
|
76
|
-
const setupDir = path.join(options.outputPath, 'app', 'initial_setup');
|
|
77
|
-
const sourceDir = path.join(setupDir, 'generatedCode', 'source');
|
|
78
|
-
const hookDir = path.join(setupDir, 'generatedCode', 'hook');
|
|
79
|
-
|
|
80
|
-
await fs.mkdir(sourceDir, { recursive: true });
|
|
81
|
-
await fs.mkdir(hookDir, { recursive: true });
|
|
82
|
-
|
|
83
|
-
const tableNames = new Set();
|
|
84
|
-
const tableNameTpl = await fs.readFile(
|
|
85
|
-
path.join(__dirname, 'templates', 'InitialSetup_TableName.ejs'),
|
|
86
|
-
'utf-8'
|
|
87
|
-
);
|
|
88
|
-
const tableNameContent = ejs.render(tableNameTpl, {
|
|
89
|
-
tableNames: Array.from(tableNames)
|
|
90
|
-
});
|
|
91
|
-
await fs.writeFile(
|
|
92
|
-
path.join(sourceDir, 'generatedTableNameConfig.js'),
|
|
93
|
-
tableNameContent,
|
|
94
|
-
'utf-8'
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const hardcodedSubscriptions = [
|
|
98
|
-
{
|
|
99
|
-
serviceTag: 'GraphHandler',
|
|
100
|
-
topicName: 'UpdateRelationship_Out',
|
|
101
|
-
sqsEndpoint: 'UpdateRelationshipComplete'
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
serviceTag: 'GraphHandler',
|
|
105
|
-
topicName: 'CreateRelationship_Out',
|
|
106
|
-
sqsEndpoint: 'CreateRelationshipComplete'
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
serviceTag: 'GraphHandler',
|
|
110
|
-
topicName: 'DeleteRelationship_Out',
|
|
111
|
-
sqsEndpoint: 'DeleteRelationshipComplete'
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
serviceTag: 'GraphHandler',
|
|
115
|
-
topicName: 'UpdateNode_Out',
|
|
116
|
-
sqsEndpoint: 'UpdateComplete'
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
serviceTag: 'GraphHandler',
|
|
120
|
-
topicName: 'CreateNode_Out',
|
|
121
|
-
sqsEndpoint: 'CreateComplete'
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
serviceTag: 'GraphHandler',
|
|
125
|
-
topicName: 'ChangeRelationshipType_Out',
|
|
126
|
-
sqsEndpoint: 'ChangeRelationshipComplete'
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
serviceTag: 'GraphHandler',
|
|
130
|
-
topicName: 'MoveRelationship_Out',
|
|
131
|
-
sqsEndpoint: 'MoveRelationshipComplete'
|
|
132
|
-
}
|
|
133
|
-
];
|
|
134
|
-
const snsTpl = await fs.readFile(
|
|
135
|
-
path.join(__dirname, 'templates', 'InitialSetup_SnsService.ejs'),
|
|
136
|
-
'utf-8'
|
|
137
|
-
);
|
|
138
|
-
const snsContent = ejs.render(snsTpl, { subscriptions: hardcodedSubscriptions });
|
|
139
|
-
await fs.writeFile(
|
|
140
|
-
path.join(sourceDir, 'generatedSnsServiceConfig.js'),
|
|
141
|
-
snsContent,
|
|
142
|
-
'utf-8'
|
|
143
|
-
);
|
|
144
|
-
|
|
15
|
+
const HARDCODED_SUBSCRIPTIONS = [
|
|
16
|
+
{ serviceTag: 'GraphHandler', topicName: 'UpdateRelationship_Out', sqsEndpoint: 'UpdateRelationshipCompleteHdrSqs' },
|
|
17
|
+
{ serviceTag: 'GraphHandler', topicName: 'CreateRelationship_Out', sqsEndpoint: 'CreateRelationshipCompleteHdrSqs' },
|
|
18
|
+
{ serviceTag: 'GraphHandler', topicName: 'DeleteRelationship_Out', sqsEndpoint: 'DeleteRelationshipCompleteHdrSqs' },
|
|
19
|
+
{ serviceTag: 'GraphHandler', topicName: 'UpdateNode_Out', sqsEndpoint: 'UpdateCompleteHdrSqs' },
|
|
20
|
+
{ serviceTag: 'GraphHandler', topicName: 'CreateNode_Out', sqsEndpoint: 'CreateCompleteHdrSqs' },
|
|
21
|
+
{ serviceTag: 'GraphHandler', topicName: 'ChangeRelationshipType_Out', sqsEndpoint: 'ChangeRelationshipCompleteHdrSqs' },
|
|
22
|
+
{ serviceTag: 'GraphHandler', topicName: 'MoveRelationship_Out', sqsEndpoint: 'MoveRelationshipCompleteHdrSqs' }
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
function buildLambdaRoles(flows, roleNames) {
|
|
145
26
|
const lambdaRoles = [
|
|
146
27
|
{
|
|
147
28
|
objectType: FLOW_OBJECTS_ROLE,
|
|
@@ -170,7 +51,7 @@ export async function generateInitialSetup(allSchemas, options) {
|
|
|
170
51
|
]
|
|
171
52
|
},
|
|
172
53
|
{
|
|
173
|
-
objectType:
|
|
54
|
+
objectType: PROC_FIND_DATA_ROLE,
|
|
174
55
|
additionalResourcePermission: [
|
|
175
56
|
{
|
|
176
57
|
effect: 'Allow',
|
|
@@ -222,18 +103,37 @@ export async function generateInitialSetup(allSchemas, options) {
|
|
|
222
103
|
});
|
|
223
104
|
}
|
|
224
105
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
106
|
+
if (roleNames && roleNames.has(FLOW_RELATIONSHIP_ROLE)) {
|
|
107
|
+
lambdaRoles.push({
|
|
108
|
+
objectType: FLOW_RELATIONSHIP_ROLE,
|
|
109
|
+
additionalResourcePermission: [
|
|
110
|
+
{
|
|
111
|
+
effect: 'Allow',
|
|
112
|
+
action: { lambda: ['InvokeFunction'] },
|
|
113
|
+
resource: [
|
|
114
|
+
'arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, "GetRelationshipHdrInv" ,"GraphHandler")}'
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
effect: 'Allow',
|
|
119
|
+
action: { sns: ['Publish'] },
|
|
120
|
+
resource: [
|
|
121
|
+
'arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, "CreateRelationship_In", "GraphHandler")}',
|
|
122
|
+
'arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, "UpdateRelationship_In", "GraphHandler")}',
|
|
123
|
+
'arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, "DeleteRelationship_In", "GraphHandler")}',
|
|
124
|
+
'arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, "ChangeRelationship_In", "GraphHandler")}',
|
|
125
|
+
'arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, "MoveRelationship_In", "GraphHandler")}'
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
});
|
|
130
|
+
}
|
|
235
131
|
|
|
236
|
-
|
|
132
|
+
return lambdaRoles;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function buildRoleNameConfigContent(roleNames) {
|
|
136
|
+
return `export function generatedIntTestRoleNameConfig() {
|
|
237
137
|
let roleNameConfigIntTest = [
|
|
238
138
|
${Array.from(roleNames)
|
|
239
139
|
.sort()
|
|
@@ -243,7 +143,57 @@ ${Array.from(roleNames)
|
|
|
243
143
|
return roleNameConfigIntTest;
|
|
244
144
|
}
|
|
245
145
|
`;
|
|
246
|
-
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export async function generateInitialSetup(allSchemas, options) {
|
|
149
|
+
console.log(' [InitialSetupGenerator] Generating Initial Setup Scripts...');
|
|
150
|
+
|
|
151
|
+
const { flows, roleNames } = detectRoleNames(allSchemas);
|
|
152
|
+
const setupDir = path.join(options.outputPath, 'app', 'initial_setup');
|
|
153
|
+
const sourceDir = path.join(setupDir, 'generatedCode', 'source');
|
|
154
|
+
const hookDir = path.join(setupDir, 'generatedCode', 'hook');
|
|
155
|
+
|
|
156
|
+
await fs.mkdir(sourceDir, { recursive: true });
|
|
157
|
+
await fs.mkdir(hookDir, { recursive: true });
|
|
158
|
+
|
|
159
|
+
const tableNameTpl = await fs.readFile(
|
|
160
|
+
path.join(__dirname, 'templates', 'InitialSetup_TableName.ejs'),
|
|
161
|
+
'utf-8'
|
|
162
|
+
);
|
|
163
|
+
const tableNameContent = ejs.render(tableNameTpl, { tableNames: [] });
|
|
164
|
+
await fs.writeFile(
|
|
165
|
+
path.join(sourceDir, 'generatedTableNameConfig.js'),
|
|
166
|
+
tableNameContent,
|
|
167
|
+
'utf-8'
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const snsTpl = await fs.readFile(
|
|
171
|
+
path.join(__dirname, 'templates', 'InitialSetup_SnsService.ejs'),
|
|
172
|
+
'utf-8'
|
|
173
|
+
);
|
|
174
|
+
const snsContent = ejs.render(snsTpl, { subscriptions: HARDCODED_SUBSCRIPTIONS });
|
|
175
|
+
await fs.writeFile(
|
|
176
|
+
path.join(sourceDir, 'generatedSnsServiceConfig.js'),
|
|
177
|
+
snsContent,
|
|
178
|
+
'utf-8'
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const lambdaTpl = await fs.readFile(
|
|
182
|
+
path.join(__dirname, 'templates', 'InitialSetup_LambdaRole.ejs'),
|
|
183
|
+
'utf-8'
|
|
184
|
+
);
|
|
185
|
+
const lambdaContent = ejs.render(lambdaTpl, { datas: buildLambdaRoles(flows, roleNames) });
|
|
186
|
+
await fs.writeFile(
|
|
187
|
+
path.join(sourceDir, 'generatedLambdaRoleServiceConfig.js'),
|
|
188
|
+
lambdaContent,
|
|
189
|
+
'utf-8'
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
await fs.writeFile(
|
|
193
|
+
path.join(sourceDir, 'RoleNameConfig.js'),
|
|
194
|
+
buildRoleNameConfigContent(roleNames),
|
|
195
|
+
'utf-8'
|
|
196
|
+
);
|
|
247
197
|
|
|
248
|
-
console.log(`
|
|
198
|
+
console.log(` [InitialSetupGenerator] Wrote initial_setup scripts to ${sourceDir}`);
|
|
249
199
|
}
|
|
@@ -8,33 +8,40 @@ const _izContext = { logger: Logger };
|
|
|
8
8
|
|
|
9
9
|
export function generatedLambdaRole() {
|
|
10
10
|
const externalLambdaRole = [
|
|
11
|
-
<% datas.forEach((data) => {
|
|
11
|
+
<% datas.forEach((data, dataIdx) => { -%>
|
|
12
12
|
{
|
|
13
|
-
roleName:
|
|
13
|
+
roleName: '<%- data.objectType %>',
|
|
14
14
|
statement: [
|
|
15
|
-
<% data.additionalResourcePermission.forEach((resourcePermission, resourceIdx) => {
|
|
15
|
+
<% data.additionalResourcePermission.forEach((resourcePermission, resourceIdx) => { -%>
|
|
16
16
|
{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
Sid: '<%- data.objectType %>Test<%- resourceIdx %>',
|
|
18
|
+
Effect: '<%- resourcePermission.effect %>',
|
|
19
|
+
Action: [<%
|
|
20
|
+
const actions = [];
|
|
21
|
+
Object.keys(resourcePermission.action).forEach((service) => {
|
|
22
|
+
resourcePermission.action[service].forEach((act) => {
|
|
23
|
+
actions.push(`'${service}:${act}'`);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
%><%- actions.join(', ') %>],
|
|
27
|
+
Resource: [
|
|
28
|
+
<%
|
|
29
|
+
const resources = [];
|
|
30
|
+
resourcePermission.resource.forEach((res) => {
|
|
31
|
+
const formattedRes = res.replace(/"/g, "'");
|
|
32
|
+
resources.push(` \`${formattedRes}\``);
|
|
33
|
+
});
|
|
34
|
+
%><%- resources.join(',\n') %>
|
|
30
35
|
]
|
|
31
|
-
}
|
|
32
|
-
<% })
|
|
36
|
+
}<%= (resourceIdx === data.additionalResourcePermission.length - 1) ? '' : ',\n\n' -%>
|
|
37
|
+
<% }) -%>
|
|
38
|
+
|
|
33
39
|
//(<create<%- data.objectType.replace(/Role$/, '') %>Role>)
|
|
34
40
|
//(</create<%- data.objectType.replace(/Role$/, '') %>Role>)
|
|
35
41
|
]
|
|
36
|
-
}
|
|
37
|
-
<% })
|
|
42
|
+
}<%= (dataIdx === datas.length - 1) ? '' : ',\n\n' -%>
|
|
43
|
+
<% }) -%>
|
|
44
|
+
|
|
38
45
|
//(<additionalRole>)
|
|
39
46
|
//(</additionalRole>)
|
|
40
47
|
];
|
|
@@ -3,13 +3,17 @@ import path from 'path';
|
|
|
3
3
|
import ejs from 'ejs';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { getFlowsForGeneration } from '../src/generatedCode/Flow/_shared/shared/flowSelection.js';
|
|
6
|
-
import { isRbacFlow } from '../src/generatedCode/Flow/_shared/shared/flowClassifier.js';
|
|
6
|
+
import { isCrudFlow, isRbacFlow, isRelationshipFlow } from '../src/generatedCode/Flow/_shared/shared/flowClassifier.js';
|
|
7
7
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
11
|
export async function generateFunctionYaml(allSchemas, options) {
|
|
12
12
|
console.log(' [FunctionYamlGenerator] Generating Function YAMLs...');
|
|
13
|
+
const serviceName = options.serviceName;
|
|
14
|
+
if (!serviceName) {
|
|
15
|
+
throw new Error('[Developer Error] serviceName is missing in FunctionYamlGenerator. Ensure serverless.config.yml has main_config.iz_serviceName.');
|
|
16
|
+
}
|
|
13
17
|
|
|
14
18
|
const slsYamlDir = path.join(
|
|
15
19
|
options.outputPath,
|
|
@@ -44,15 +48,6 @@ export async function generateFunctionYaml(allSchemas, options) {
|
|
|
44
48
|
};
|
|
45
49
|
const flows = getFlowsForGeneration(allSchemas);
|
|
46
50
|
|
|
47
|
-
const CRUD_FLOW_TAGS = ['Create', 'Update', 'Delete', 'Get'];
|
|
48
|
-
const REL_FLOW_TAGS = [
|
|
49
|
-
'createRelationship',
|
|
50
|
-
'updateRelationship',
|
|
51
|
-
'deleteRelationship',
|
|
52
|
-
'getRelationship',
|
|
53
|
-
'changeRelationship',
|
|
54
|
-
'moveRelationship'
|
|
55
|
-
];
|
|
56
51
|
|
|
57
52
|
let perActionYaml = '';
|
|
58
53
|
let relActionYaml = '';
|
|
@@ -123,12 +118,8 @@ export async function generateFunctionYaml(allSchemas, options) {
|
|
|
123
118
|
const handlerBaseName = splitFileName[0]; // e.g. ProcessCreate or CreateComplete
|
|
124
119
|
const handlerSuffix = splitFileName[1]; // e.g. HdrSqs, HdrApi, HdrInv
|
|
125
120
|
|
|
126
|
-
const isCrud =
|
|
127
|
-
|
|
128
|
-
);
|
|
129
|
-
const isRel = REL_FLOW_TAGS.map(t => t.toLowerCase()).includes(
|
|
130
|
-
flowTag.toLowerCase()
|
|
131
|
-
);
|
|
121
|
+
const isCrud = isCrudFlow(flowTag);
|
|
122
|
+
const isRel = isRelationshipFlow(flowTag);
|
|
132
123
|
const isRbac =
|
|
133
124
|
isRbacFlow(flowTag) ||
|
|
134
125
|
String(flowTag || '')
|
|
@@ -163,15 +154,14 @@ export async function generateFunctionYaml(allSchemas, options) {
|
|
|
163
154
|
functionNameConfig = `${upperCase(flowTag).replace('Relationship', 'Rel')}${suffixType}`;
|
|
164
155
|
}
|
|
165
156
|
if (handlerBaseName.endsWith('Complete')) {
|
|
166
|
-
// e.g.
|
|
157
|
+
// e.g. CreateCompleteHdrSqs or CreateCompleteSqs
|
|
167
158
|
if (isCrud) {
|
|
168
|
-
// Legacy:
|
|
159
|
+
// Legacy: DeleteCompleteHdrSqs, UpdateCompleteHdrSqs, CreateCompleteHdrSqs
|
|
169
160
|
const crudType = upperCase(flowTag);
|
|
170
|
-
|
|
171
|
-
else functionNameConfig = `${crudType}NodeComp`;
|
|
161
|
+
functionNameConfig = `${crudType}CompleteHdrSqs`;
|
|
172
162
|
} else if (isRel) {
|
|
173
163
|
// Legacy: UpdateRelComp
|
|
174
|
-
functionNameConfig = `${upperCase(flowTag)
|
|
164
|
+
functionNameConfig = `${upperCase(flowTag)}CompleteHdrSqs`;
|
|
175
165
|
} else {
|
|
176
166
|
functionNameConfig = `${handlerBaseName}${suffixType}`;
|
|
177
167
|
}
|
|
@@ -211,7 +201,7 @@ export async function generateFunctionYaml(allSchemas, options) {
|
|
|
211
201
|
const routesList = isCrud ? crudApiRoutes : isRel ? relApiRoutes : [];
|
|
212
202
|
const actionPath = flowTag.toLowerCase().replace('relationship', '');
|
|
213
203
|
apiRoutes = routesList.map(r => ({
|
|
214
|
-
path:
|
|
204
|
+
path: `/${serviceName}/${r.objectName}/${actionPath}`,
|
|
215
205
|
upperName: r.upperName
|
|
216
206
|
}));
|
|
217
207
|
}
|
|
@@ -2,40 +2,19 @@ import fs from 'fs/promises';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import ejs from 'ejs';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
-
import {
|
|
5
|
+
import { detectRoleNames } from '../src/generatedCode/Flow/_shared/shared/roleNameDetection.js';
|
|
6
6
|
|
|
7
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
8
|
const __dirname = path.dirname(__filename);
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
'DeleteTargetRole',
|
|
16
|
-
'CreateRolePermissions',
|
|
17
|
-
'ListRolePermissions',
|
|
18
|
-
'DeleteRolePermissions',
|
|
19
|
-
'CreateUserRole',
|
|
20
|
-
'ListUserInRoles',
|
|
21
|
-
'DeleteUserFromRole'
|
|
22
|
-
]);
|
|
23
|
-
const REL_FLOW_TAGS = new Set([
|
|
24
|
-
'CreateRelationship',
|
|
25
|
-
'UpdateRelationship',
|
|
26
|
-
'DeleteRelationship',
|
|
27
|
-
'GetRelationship',
|
|
28
|
-
'ChangeRelationship',
|
|
29
|
-
'MoveRelationship'
|
|
30
|
-
]);
|
|
31
|
-
|
|
32
|
-
function upperCase(str) {
|
|
33
|
-
if (!str) return str;
|
|
34
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
35
|
-
}
|
|
10
|
+
const FALLBACK_TEMPLATE = `# createIamRole
|
|
11
|
+
<% roleNameConfigs.forEach(function(roleNameConfig){ _%>
|
|
12
|
+
- arn:aws:iam::\${self:custom.iz_accountId}:role/\${self:custom.iz_resourcePrefix}<%- roleNameConfig %>
|
|
13
|
+
<% }) _%>
|
|
14
|
+
`;
|
|
36
15
|
|
|
37
16
|
export async function generateRoleNameConfig(allSchemas, options) {
|
|
38
|
-
console.log('
|
|
17
|
+
console.log(' [RoleNameConfigGenerator] Generating IAM Role Configurations...');
|
|
39
18
|
|
|
40
19
|
const resourceYamlDir = path.join(
|
|
41
20
|
options.outputPath,
|
|
@@ -46,62 +25,24 @@ export async function generateRoleNameConfig(allSchemas, options) {
|
|
|
46
25
|
);
|
|
47
26
|
await fs.mkdir(resourceYamlDir, { recursive: true });
|
|
48
27
|
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
for (const flow of flows) {
|
|
53
|
-
if (!flow.flowTag) continue;
|
|
54
|
-
|
|
55
|
-
const upperFlowTag = upperCase(flow.flowTag);
|
|
56
|
-
|
|
57
|
-
if (CRUD_FLOW_TAGS.has(upperFlowTag)) {
|
|
58
|
-
roleNameConfigs.add(FLOW_OBJECTS_ROLE);
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (RBAC_FLOW_TAGS.has(upperFlowTag) || upperFlowTag.endsWith('RbacFlow')) {
|
|
63
|
-
roleNameConfigs.add('FlowRbacRole');
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (REL_FLOW_TAGS.has(upperFlowTag)) {
|
|
68
|
-
roleNameConfigs.add('FlowRelationshipRole');
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if ((flow.event || []).includes('ownTopic')) {
|
|
73
|
-
roleNameConfigs.add('WebSocketMainRole');
|
|
74
|
-
// ponytail: removed continue; so custom flows with ownTopic get their own specific role
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
roleNameConfigs.add(`${upperFlowTag}Role`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
roleNameConfigs.add('ProcFindDataRole');
|
|
81
|
-
|
|
28
|
+
const { roleNames } = detectRoleNames(allSchemas);
|
|
29
|
+
const roleNameConfigs = Array.from(roleNames);
|
|
82
30
|
const templatePath = path.join(__dirname, 'templates', 'RoleNameConfig_Yaml.ejs');
|
|
83
|
-
let templateString;
|
|
84
31
|
|
|
32
|
+
let templateString;
|
|
85
33
|
try {
|
|
86
34
|
templateString = await fs.readFile(templatePath, 'utf-8');
|
|
87
35
|
} catch {
|
|
88
|
-
templateString =
|
|
89
|
-
<% roleNameConfigs.forEach(function(roleNameConfig){ _%>
|
|
90
|
-
- arn:aws:iam::\${self:custom.iz_accountId}:role/\${self:custom.iz_resourcePrefix}<%- roleNameConfig %>
|
|
91
|
-
<% }) _%>
|
|
92
|
-
`;
|
|
36
|
+
templateString = FALLBACK_TEMPLATE;
|
|
93
37
|
await fs.mkdir(path.dirname(templatePath), { recursive: true });
|
|
94
38
|
await fs.writeFile(templatePath, templateString, 'utf-8');
|
|
95
39
|
}
|
|
96
40
|
|
|
97
|
-
const fileContent = ejs.render(templateString, {
|
|
98
|
-
roleNameConfigs: Array.from(roleNameConfigs)
|
|
99
|
-
});
|
|
100
|
-
|
|
41
|
+
const fileContent = ejs.render(templateString, { roleNameConfigs });
|
|
101
42
|
const outputPath = path.join(resourceYamlDir, 'role-name-config.yml');
|
|
102
43
|
await fs.writeFile(outputPath, fileContent, 'utf-8');
|
|
103
44
|
|
|
104
45
|
console.log(
|
|
105
|
-
`
|
|
46
|
+
` [RoleNameConfigGenerator] Wrote ${roleNameConfigs.length} role configs to ${outputPath}`
|
|
106
47
|
);
|
|
107
48
|
}
|
|
@@ -36,8 +36,9 @@ export async function emitManagedPolicies(registry, options) {
|
|
|
36
36
|
const tpl = await fs.readFile(templatePath, 'utf8');
|
|
37
37
|
|
|
38
38
|
for (const [roleName, { statements }] of Object.entries(grouped)) {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
39
|
+
const policyName = roleName.replace(/role$/i, '');
|
|
40
|
+
const content = ejs.render(tpl, { roleName, policyName, statements });
|
|
41
|
+
const outFile = path.join(outDir, `${policyName}Policy.yml`);
|
|
41
42
|
await fs.writeFile(outFile, content, 'utf8');
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -18,7 +18,7 @@ describe('emitManagedPolicies', () => {
|
|
|
18
18
|
reg.add('RegisterRole', 'dynamodb:GetItem', 'arn:aws:dynamodb:*:*:table/x');
|
|
19
19
|
await emitManagedPolicies(reg, { outputPath: tmpDir });
|
|
20
20
|
const files = await fs.readdir(path.join(tmpDir, 'app', 'sls_yaml', 'generatedCode', 'source', 'iam-managed-policies'));
|
|
21
|
-
expect(files.sort()).toEqual(['
|
|
21
|
+
expect(files.sort()).toEqual(['FindDataPolicy.yml', 'RegisterPolicy.yml']);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
it('emits empty dir + no files when registry is empty', async () => {
|
|
@@ -34,7 +34,7 @@ describe('emitManagedPolicies', () => {
|
|
|
34
34
|
reg.add('FindDataRole', 's3:GetObject', 'arn:aws:s3:::a/*');
|
|
35
35
|
await emitManagedPolicies(reg, { outputPath: tmpDir });
|
|
36
36
|
const content = await fs.readFile(
|
|
37
|
-
path.join(tmpDir, 'app', 'sls_yaml', 'generatedCode', 'source', 'iam-managed-policies', '
|
|
37
|
+
path.join(tmpDir, 'app', 'sls_yaml', 'generatedCode', 'source', 'iam-managed-policies', 'FindDataPolicy.yml'),
|
|
38
38
|
'utf8'
|
|
39
39
|
);
|
|
40
40
|
expect(content).toContain('Type: AWS::IAM::ManagedPolicy');
|
|
@@ -47,7 +47,7 @@ describe('emitManagedPolicies', () => {
|
|
|
47
47
|
reg.add('FindDataRole', 's3:GetObject', 'arn:aws:s3:::${self:custom.iz_serviceSchemaBucketName}/*');
|
|
48
48
|
await emitManagedPolicies(reg, { outputPath: tmpDir });
|
|
49
49
|
const content = await fs.readFile(
|
|
50
|
-
path.join(tmpDir, 'app', 'sls_yaml', 'generatedCode', 'source', 'iam-managed-policies', '
|
|
50
|
+
path.join(tmpDir, 'app', 'sls_yaml', 'generatedCode', 'source', 'iam-managed-policies', 'FindDataPolicy.yml'),
|
|
51
51
|
'utf8'
|
|
52
52
|
);
|
|
53
53
|
expect(content).toContain('${self:custom.iz_serviceSchemaBucketName}');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Resources:
|
|
2
|
-
<%-
|
|
2
|
+
<%- policyName %>Policy:
|
|
3
3
|
Type: AWS::IAM::ManagedPolicy
|
|
4
4
|
Properties:
|
|
5
|
-
ManagedPolicyName: ${self:custom.iz_resourcePrefix}<%-
|
|
5
|
+
ManagedPolicyName: ${self:custom.iz_resourcePrefix}<%- policyName %>Policy
|
|
6
6
|
Description: "Managed policy for <%- roleName %> (auto-generated by PolicyEmitter)"
|
|
7
7
|
PolicyDocument:
|
|
8
8
|
Version: "2012-10-17"
|
|
@@ -18,7 +18,7 @@ Resources:
|
|
|
18
18
|
#<#<%- roleName %>ManagedPolicyArns#>
|
|
19
19
|
#<#/<%- roleName %>ManagedPolicyArns#>
|
|
20
20
|
Policies:
|
|
21
|
-
- PolicyName: ${self:custom.iz_resourcePrefix}<%- roleName %>Policy
|
|
21
|
+
- PolicyName: ${self:custom.iz_resourcePrefix}<%- roleName.replace(/role$/i, '') %>Policy
|
|
22
22
|
PolicyDocument:
|
|
23
23
|
Version: "2012-10-17"
|
|
24
24
|
Statement:
|
|
@@ -27,6 +27,7 @@ export async function generateEndpointsFlow(allSchemas, options) {
|
|
|
27
27
|
|
|
28
28
|
const sharedTemplates = {
|
|
29
29
|
sqs: await fs.readFile(path.join(__dirname, '..', '_shared', 'handlers', 'FlowHandler_HdrSqs.ejs'), 'utf-8'),
|
|
30
|
+
dsq: await fs.readFile(path.join(__dirname, '..', '_shared', 'handlers', 'FlowHandler_HdrDsq.ejs'), 'utf-8'),
|
|
30
31
|
api: await fs.readFile(path.join(__dirname, '..', '_shared', 'handlers', 'FlowHandler_HdrApi.ejs'), 'utf-8'),
|
|
31
32
|
inv: await fs.readFile(path.join(__dirname, '..', '_shared', 'handlers', 'FlowHandler_HdrInv.ejs'), 'utf-8'),
|
|
32
33
|
wbsMain: await fs.readFile(path.join(__dirname, '..', 'FlowSchemas', 'templates', 'endpoint', 'FlowMain_Wbs.ejs'), 'utf-8').catch(() => ''),
|
|
@@ -70,7 +71,7 @@ export async function generateEndpointsFlow(allSchemas, options) {
|
|
|
70
71
|
topicArn: `${upperAction}_In`,
|
|
71
72
|
generateCode: generateCode,
|
|
72
73
|
flow: mockFlow,
|
|
73
|
-
|
|
74
|
+
startConfig: null
|
|
74
75
|
});
|
|
75
76
|
await fs.writeFile(path.join(flowOutputDir, `${mainFileName}.js`), mainContent, 'utf-8');
|
|
76
77
|
generatedCount++;
|
|
@@ -88,7 +89,7 @@ export async function generateEndpointsFlow(allSchemas, options) {
|
|
|
88
89
|
upperCaseFlowTag: upperAction,
|
|
89
90
|
generateCode: generateCode,
|
|
90
91
|
flow: mockFlow,
|
|
91
|
-
|
|
92
|
+
startConfig: null
|
|
92
93
|
});
|
|
93
94
|
await fs.writeFile(path.join(flowOutputDir, `${beforeLogicalFileName}.js`), beforeLogicalContent, 'utf-8');
|
|
94
95
|
generatedCount++;
|