@izara_project/izara-core-generate-service-code 1.0.75 → 1.0.77
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/src/compile/loadSchemas.js +36 -30
- package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +2 -4
- package/src/emit/coreFunction/templates/CoreResource_Yaml.ejs +2 -0
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +13 -2
- package/src/emit/coreFunction/templates/InitialSetupRunner.ejs +5 -3
- package/src/emit/coreFunction/templates/InitialSetupRunner_uploadSchema.ejs +13 -6
- package/src/emit/coreFunction/templates/InitialSetup_HdrInv.ejs +1 -1
- package/src/emit/crud/templates/FlowEndpointBeforeLogical_Main.ejs +1 -1
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +7 -11
- package/src/emit/custom/templates/FlowEndpoint_Main.ejs +8 -5
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +20 -5
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +58 -43
- package/src/emit/rbac/templates/CreateTargetRole_HdrSqs.ejs +68 -20
- package/src/emit/rbac/templates/ListRbac_HdrSqs.ejs +69 -20
- package/src/emit/rbac/templates/UserRbacFlow_HdrSqs.ejs +69 -20
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +11 -2
- package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +7 -6
- package/src/emit/resource/emitResourceArtifacts.js +22 -2
- package/src/emit/system/emitSystemFindDataArtifacts.js +7 -8
- package/src/generate.js +19 -10
- package/src/output/mergeHooks.js +4 -3
- package/test/dynamicRelationshipFlowSchemas.test.js +12 -1
- package/test/publicApi.test.js +25 -8
- package/test/resourceArtifacts.test.js +2 -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.77",
|
|
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": {
|
|
@@ -159,41 +159,47 @@ export async function resolveExtendedObjectSchemas(
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
/*
|
|
163
162
|
if (
|
|
164
163
|
currentSchema.hasOwnProperty('belongTo') &&
|
|
165
|
-
currentSchema.belongTo
|
|
166
|
-
currentSchema.belongTo.serviceTag &&
|
|
167
|
-
currentSchema.belongTo.objectType
|
|
164
|
+
currentSchema.belongTo
|
|
168
165
|
) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
166
|
+
const belongToTarget = Array.isArray(currentSchema.belongTo)
|
|
167
|
+
? currentSchema.belongTo[0]
|
|
168
|
+
: currentSchema.belongTo;
|
|
169
|
+
|
|
170
|
+
if (
|
|
171
|
+
belongToTarget &&
|
|
172
|
+
belongToTarget.serviceTag &&
|
|
173
|
+
belongToTarget.objectType
|
|
174
|
+
) {
|
|
175
|
+
try {
|
|
176
|
+
Logger.debug(
|
|
177
|
+
`[DEBUG] [resolveExtendedObjectSchemas] Fetching belongTo schema for objectType=${currentSchema.objectType}`,
|
|
178
|
+
{ belongTo: belongToTarget }
|
|
179
|
+
);
|
|
180
|
+
const belongToObjType = {
|
|
181
|
+
serviceTag: belongToTarget.serviceTag,
|
|
182
|
+
objectType: belongToTarget.objectType
|
|
183
|
+
};
|
|
184
|
+
const belongToSchema = await getObjectSchema.getObjSchemaS3(
|
|
185
|
+
{ logger: Logger },
|
|
186
|
+
belongToObjType,
|
|
187
|
+
false,
|
|
188
|
+
bucketName
|
|
189
|
+
);
|
|
190
|
+
currentSchema.belongToSchema = belongToSchema;
|
|
191
|
+
Logger.debug(
|
|
192
|
+
`[DEBUG] [resolveExtendedObjectSchemas] Successfully fetched belongTo schema for objectType=${currentSchema.objectType}`,
|
|
193
|
+
{ belongToObjectType: belongToSchema?.objectType }
|
|
194
|
+
);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
Logger.warn(
|
|
197
|
+
`[WARN] [resolveExtendedObjectSchemas] Failed to fetch belongTo schema for objectType=${currentSchema.objectType}`,
|
|
198
|
+
{ error }
|
|
199
|
+
);
|
|
200
|
+
}
|
|
194
201
|
}
|
|
195
202
|
}
|
|
196
|
-
*/
|
|
197
203
|
|
|
198
204
|
resolvedSchemas.push(currentSchema);
|
|
199
205
|
}
|
|
@@ -210,13 +210,11 @@ export async function emitCoreFunctionArtifacts({ project, objects = [], relatio
|
|
|
210
210
|
},
|
|
211
211
|
{
|
|
212
212
|
path: `${SRC_ROOT}/InitialSetupConfig.js`,
|
|
213
|
-
content: initialSetupConfig
|
|
214
|
-
writeWhenFileExist: false
|
|
213
|
+
content: initialSetupConfig
|
|
215
214
|
},
|
|
216
215
|
{
|
|
217
216
|
path: `${INITIAL_SETUP_ROOT}/InitialSetupConfig.js`,
|
|
218
|
-
content: initialSetupConfig
|
|
219
|
-
writeWhenFileExist: false // Don't overwrite the file that dev modifies
|
|
217
|
+
content: initialSetupConfig
|
|
220
218
|
},
|
|
221
219
|
{
|
|
222
220
|
path: `${INITIAL_SETUP_ROOT}/runner.js`,
|
|
@@ -42,6 +42,8 @@ Resources:
|
|
|
42
42
|
Resource:
|
|
43
43
|
- arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:${self:custom.iz_resourcePrefix}AddLinkCreateByRelHdrInv
|
|
44
44
|
- arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:${self:custom.iz_resourcePrefix}AddLinkBelongToHdrInv
|
|
45
|
+
- arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:UserAccount${self:custom.iz_stage}AddLinkCreateByRelHdrInv
|
|
46
|
+
- arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:UserAccount${self:custom.iz_stage}AddLinkBelongToHdrInv
|
|
45
47
|
- arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:GraphHandler${self:custom.iz_stage}CreateAllIndexSchemasHdrInv
|
|
46
48
|
- arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:TranslateIds${self:custom.iz_stage}CreatePermissionHdrInv
|
|
47
49
|
- arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:Translations${self:custom.iz_stage}AddLinkToTranslationLinksHdrInv
|
|
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
19
19
|
import Logger from '@izara_project/izara-core-library-logger';
|
|
20
20
|
import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
|
|
21
21
|
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
22
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
22
23
|
|
|
23
24
|
const _izContext = { logger: Logger };
|
|
24
25
|
|
|
@@ -49,21 +50,31 @@ const externalServices = {
|
|
|
49
50
|
-%>
|
|
50
51
|
const tableConfigs = {
|
|
51
52
|
prod: {
|
|
52
|
-
Config: {
|
|
53
|
+
Config: {
|
|
54
|
+
// <#InitialSetupConfig_Prod_Config_TableConfig#>
|
|
55
|
+
// <#/InitialSetupConfig_Prod_Config_TableConfig#>
|
|
56
|
+
},
|
|
53
57
|
<% dynamoTableNames.forEach(tableName => { -%>
|
|
54
|
-
<%= tableName %>: {
|
|
58
|
+
<%= tableName %>: {
|
|
59
|
+
// <#InitialSetupConfig_Prod_<%= tableName %>_TableConfig#>
|
|
60
|
+
// <#/InitialSetupConfig_Prod_<%= tableName %>_TableConfig#>
|
|
61
|
+
},
|
|
55
62
|
<% }); -%>
|
|
56
63
|
// <#InitialSetupConfig_ExtraProdTableConfigs#>
|
|
57
64
|
// <#/InitialSetupConfig_ExtraProdTableConfigs#>
|
|
58
65
|
},
|
|
59
66
|
test: {
|
|
60
67
|
Config: {
|
|
68
|
+
// <#InitialSetupConfig_Test_Config_TableConfig#>
|
|
61
69
|
clearDataWhenRefresh: true,
|
|
62
70
|
rawSource: false
|
|
71
|
+
// <#/InitialSetupConfig_Test_Config_TableConfig#>
|
|
63
72
|
},
|
|
64
73
|
<% dynamoTableNames.forEach(tableName => { -%>
|
|
65
74
|
<%= tableName %>: {
|
|
75
|
+
// <#InitialSetupConfig_Test_<%= tableName %>_TableConfig#>
|
|
66
76
|
clearDataWhenRefresh: true
|
|
77
|
+
// <#/InitialSetupConfig_Test_<%= tableName %>_TableConfig#>
|
|
67
78
|
},
|
|
68
79
|
<% }); -%>
|
|
69
80
|
// <#InitialSetupConfig_ExtraTestTableConfigs#>
|
|
@@ -40,6 +40,8 @@ if (fs.existsSync(configPath)) {
|
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
process.env.LOG_LEVEL = process.env.LOG_LEVEL || 'INFO';
|
|
44
|
+
|
|
43
45
|
// 2. Dynamic import to ensure SDKs use the injected process.env
|
|
44
46
|
const { default: initialSetupSharedLib } =
|
|
45
47
|
await import('@izara_project/izara-core-library-initial-setup');
|
|
@@ -96,15 +98,15 @@ const commands = {
|
|
|
96
98
|
},
|
|
97
99
|
uploadSchema: async (_izContext) => {
|
|
98
100
|
const { default: fn } = await import('./commands/uploadSchema.js');
|
|
99
|
-
await fn(_izContext);
|
|
101
|
+
await fn(_izContext, initialSetupSharedLib);
|
|
100
102
|
},
|
|
101
103
|
'uploadSchema:test': async (_izContext) => {
|
|
102
104
|
const { default: fn } = await import('./commands/uploadSchema.js');
|
|
103
|
-
await fn(_izContext);
|
|
105
|
+
await fn(_izContext, initialSetupSharedLib);
|
|
104
106
|
},
|
|
105
107
|
'uploadSchema:prod': async (_izContext) => {
|
|
106
108
|
const { default: fn } = await import('./commands/uploadSchema.js');
|
|
107
|
-
await fn(_izContext);
|
|
109
|
+
await fn(_izContext, initialSetupSharedLib);
|
|
108
110
|
}
|
|
109
111
|
};
|
|
110
112
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import initialSetupLib from '@izara_project/izara-core-library-initial-setup';
|
|
2
2
|
|
|
3
3
|
const SERVICE_TAG = {
|
|
4
4
|
TRANSLATIONS: 'Translations',
|
|
@@ -18,18 +18,25 @@ const ignoreExternalServices = {
|
|
|
18
18
|
};
|
|
19
19
|
//(</ignoreExternalServices>)
|
|
20
20
|
|
|
21
|
-
export default async function uploadSchema(_izContext) {
|
|
21
|
+
export default async function uploadSchema(_izContext, initialSetupSharedLib = initialSetupLib) {
|
|
22
22
|
console.log('======== UploadSchema ========');
|
|
23
23
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
await uploadObjSchema.uploadObjectSchemaByUseCase(_izContext, {
|
|
24
|
+
const libToUse = initialSetupSharedLib || initialSetupLib;
|
|
25
|
+
await libToUse.uploadObjectSchema(_izContext, {
|
|
27
26
|
ignoreExternalServices: ignoreExternalServices
|
|
28
27
|
});
|
|
29
28
|
console.log('-------- Finish UploadSchema --------');
|
|
30
29
|
return 'upload successfully';
|
|
31
30
|
} catch (err) {
|
|
32
|
-
|
|
31
|
+
let errorDetails = err.message || String(err);
|
|
32
|
+
if (errorDetails.includes('errorMessage:')) {
|
|
33
|
+
const match = errorDetails.match(/functionName:\s*([^,]+),errorMessage:(.*)/);
|
|
34
|
+
if (match) {
|
|
35
|
+
errorDetails = `Lambda [${match[1].trim()}] failed: ${match[2].trim()}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
_izContext.logger.error(`[uploadSchema] ❌ ${errorDetails}`);
|
|
33
39
|
throw err;
|
|
34
40
|
}
|
|
35
41
|
}
|
|
42
|
+
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
|
|
34
34
|
const { createObjType, firstLetterUpperCase } = utils;
|
|
35
35
|
|
|
36
|
-
import { <%- flowTag %>MainLogical } from '
|
|
36
|
+
import { <%- flowTag %>MainLogical } from './<%- upperCaseFlowTag %>_Main.js';
|
|
37
37
|
|
|
38
38
|
//(<optionalRequire>)
|
|
39
39
|
//(</optionalRequire>)
|
|
@@ -26,7 +26,7 @@ const CUSTOM_TEMPLATE_URL = new URL('./templates/', import.meta.url);
|
|
|
26
26
|
|
|
27
27
|
export async function emitCustomFlowApplicationArtifacts(
|
|
28
28
|
flows,
|
|
29
|
-
{
|
|
29
|
+
{ objects = [] } = {}
|
|
30
30
|
) {
|
|
31
31
|
const customFlows = supportedCustomFlows(flows);
|
|
32
32
|
const generatedRoots = generatedOwnTopicFlows(flows);
|
|
@@ -36,8 +36,7 @@ export async function emitCustomFlowApplicationArtifacts(
|
|
|
36
36
|
customFlows.length === 0 &&
|
|
37
37
|
generatedRoots.length === 0 &&
|
|
38
38
|
steps.length === 0 &&
|
|
39
|
-
dsqSteps.length === 0
|
|
40
|
-
systemFunctions.length === 0
|
|
39
|
+
dsqSteps.length === 0
|
|
41
40
|
)
|
|
42
41
|
return [];
|
|
43
42
|
|
|
@@ -57,20 +56,18 @@ export async function emitCustomFlowApplicationArtifacts(
|
|
|
57
56
|
{
|
|
58
57
|
path: YAML_PATH,
|
|
59
58
|
content: [
|
|
60
|
-
...systemFunctions,
|
|
61
59
|
...emitted.flatMap((result) => result.functions),
|
|
62
60
|
...roots.flatMap((result) => result.functions),
|
|
63
61
|
...stepResults.flatMap((result) => result.functions),
|
|
64
62
|
...dsqStepResults.flatMap((result) => result.functions)
|
|
65
|
-
]
|
|
63
|
+
]
|
|
64
|
+
.filter(Boolean)
|
|
65
|
+
.join('\n\n')
|
|
66
66
|
}
|
|
67
67
|
];
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
export function customFlowApplicationManagedPaths(
|
|
71
|
-
flows,
|
|
72
|
-
{ includeYaml = false } = {}
|
|
73
|
-
) {
|
|
70
|
+
export function customFlowApplicationManagedPaths(flows) {
|
|
74
71
|
return [
|
|
75
72
|
...supportedCustomFlows(flows).flatMap((flow) => flowPaths(flow)),
|
|
76
73
|
...generatedOwnTopicFlows(flows).flatMap(ownTopicRootPaths),
|
|
@@ -97,8 +94,7 @@ export function customFlowApplicationManagedPaths(
|
|
|
97
94
|
generatedOwnTopicFlows(flows).length > 0 ||
|
|
98
95
|
generatedDsqFlows(flows).length > 0 ||
|
|
99
96
|
flowExtTopicSteps(flows).length > 0 ||
|
|
100
|
-
flowDsqSteps(flows).length > 0
|
|
101
|
-
includeYaml
|
|
97
|
+
flowDsqSteps(flows).length > 0
|
|
102
98
|
? [YAML_PATH]
|
|
103
99
|
: [])
|
|
104
100
|
];
|
|
@@ -40,6 +40,9 @@ import { utils } from '@izara_project/izara-core-library-service-schemas';
|
|
|
40
40
|
const { createFlowTypeConcat } = utils;
|
|
41
41
|
//(</optionalImport>)
|
|
42
42
|
|
|
43
|
+
//(<helperFunction>)
|
|
44
|
+
//(</helperFunction>)
|
|
45
|
+
|
|
43
46
|
/**
|
|
44
47
|
*
|
|
45
48
|
*
|
|
@@ -70,7 +73,7 @@ export default async function <%- typeof functionName !== 'undefined' ? function
|
|
|
70
73
|
callingFlowConfig
|
|
71
74
|
);
|
|
72
75
|
|
|
73
|
-
|
|
76
|
+
<% if (typeof flow !== 'undefined' && flow.statusType === 'storedCache') { -%>
|
|
74
77
|
|
|
75
78
|
//(<beforeCheckCache>)
|
|
76
79
|
//(</beforeCheckCache>)
|
|
@@ -105,9 +108,9 @@ export default async function <%- typeof functionName !== 'undefined' ? function
|
|
|
105
108
|
//(<checkStoredCacheHook>)
|
|
106
109
|
//(</checkStoredCacheHook>)
|
|
107
110
|
}
|
|
108
|
-
|
|
111
|
+
<% } -%>
|
|
112
|
+
<% if (typeof flow !== 'undefined' && flow.isRbac) { -%>
|
|
109
113
|
|
|
110
|
-
<% if (typeof flow !== 'undefined' && flow.isRbac) { %>
|
|
111
114
|
const { checkRbacPermission } =
|
|
112
115
|
await import('@izara_project/izara-authorization');
|
|
113
116
|
|
|
@@ -139,11 +142,11 @@ export default async function <%- typeof functionName !== 'undefined' ? function
|
|
|
139
142
|
)
|
|
140
143
|
});
|
|
141
144
|
}
|
|
142
|
-
|
|
143
|
-
<% } %>
|
|
145
|
+
<% } -%>
|
|
144
146
|
|
|
145
147
|
//(<endpointHook>)
|
|
146
148
|
//(</endpointHook>)
|
|
149
|
+
|
|
147
150
|
} catch (err) {
|
|
148
151
|
_izContext.logger.error('error WebSocketInvoke: ', err);
|
|
149
152
|
throw err;
|
|
@@ -29,7 +29,9 @@ export function rbacFlowSchemaManagedPaths(objects = []) {
|
|
|
29
29
|
(object) =>
|
|
30
30
|
`app/src/schemas/FlowSchemas/generateCode/FlowRbac/${rbacFlowTag(object)}.js`
|
|
31
31
|
);
|
|
32
|
-
|
|
32
|
+
const hasSelfRbac = objects.some(_hasSelfRbacAddOn);
|
|
33
|
+
const dynamicPaths = hasSelfRbac ? dynamicRbacFlowSchemaPaths : [];
|
|
34
|
+
return [...dynamicPaths, ...rbacPaths];
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
export async function emitDynamicRbacFlowSchemas({ objects, serviceTag }) {
|
|
@@ -47,9 +49,12 @@ export async function emitDynamicRbacFlowSchemas({ objects, serviceTag }) {
|
|
|
47
49
|
);
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
const hasSelfRbac = objects.some(_hasSelfRbacAddOn);
|
|
53
|
+
const sharedArtifacts = hasSelfRbac
|
|
54
|
+
? RBAC_FLOW_DEFINITIONS.map(({ flowTag, event }) =>
|
|
55
|
+
_artifact(flowTag, _createSharedRbacFlow(flowTag, event))
|
|
56
|
+
)
|
|
57
|
+
: [];
|
|
53
58
|
const userArtifacts = rbacObjects.map((object) => {
|
|
54
59
|
const flowTag = rbacFlowTag(object);
|
|
55
60
|
return _artifact(
|
|
@@ -61,13 +66,23 @@ export async function emitDynamicRbacFlowSchemas({ objects, serviceTag }) {
|
|
|
61
66
|
return Promise.all([...sharedArtifacts, ...userArtifacts]);
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
function
|
|
69
|
+
function _hasSelfRbacAddOn(object) {
|
|
65
70
|
return (
|
|
66
71
|
Array.isArray(object?.addOnDataStructure) &&
|
|
67
72
|
object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
|
|
68
73
|
);
|
|
69
74
|
}
|
|
70
75
|
|
|
76
|
+
function _hasRbacAddOn(object) {
|
|
77
|
+
const selfHasRbac = _hasSelfRbacAddOn(object);
|
|
78
|
+
const belongToHasRbac =
|
|
79
|
+
Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
|
|
80
|
+
object.belongToSchema.addOnDataStructure.some(
|
|
81
|
+
(addOn) => addOn?.type === 'rbac'
|
|
82
|
+
);
|
|
83
|
+
return selfHasRbac || belongToHasRbac;
|
|
84
|
+
}
|
|
85
|
+
|
|
71
86
|
async function _artifact(flowTag, flow) {
|
|
72
87
|
return {
|
|
73
88
|
path: `app/src/schemas/FlowSchemas/generateCode/FlowRbac/${flowTag}.js`,
|
|
@@ -21,11 +21,16 @@ export async function emitRbacApplicationArtifacts(objects) {
|
|
|
21
21
|
return [];
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
const hasSelfRbac = objects.some(hasSelfRbacAddOn);
|
|
24
25
|
const handlers = await Promise.all([
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
...(hasSelfRbac
|
|
27
|
+
? [
|
|
28
|
+
createTargetRoleHandler(),
|
|
29
|
+
...LIST_DEFINITIONS.map(createListHandler),
|
|
30
|
+
...MUTATION_DEFINITIONS.map(createMutationHandler),
|
|
31
|
+
...USER_ROLE_MUTATIONS.map(createUserRoleMutationHandler)
|
|
32
|
+
]
|
|
33
|
+
: []),
|
|
29
34
|
...objects.filter(hasRbacAddOn).map(createUserRbacFlowHandler)
|
|
30
35
|
]);
|
|
31
36
|
return [
|
|
@@ -83,49 +88,42 @@ const USER_ROLE_MUTATIONS = [
|
|
|
83
88
|
{ flowTag: 'DeleteUserFromRole', operation: 'Delete' }
|
|
84
89
|
];
|
|
85
90
|
|
|
91
|
+
const STATIC_RBAC_APPLICATION_PATHS = [
|
|
92
|
+
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_Main.js',
|
|
93
|
+
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrSqs.js',
|
|
94
|
+
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_WbsMain.js',
|
|
95
|
+
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrWbs.js',
|
|
96
|
+
...LIST_DEFINITIONS.flatMap(({ flowTag }) => [
|
|
97
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
|
|
98
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
|
|
99
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrApi.js`
|
|
100
|
+
]),
|
|
101
|
+
...MUTATION_DEFINITIONS.flatMap(({ flowTag }) => [
|
|
102
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
|
|
103
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
|
|
104
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_WbsMain.js`,
|
|
105
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
|
|
106
|
+
]),
|
|
107
|
+
...USER_ROLE_MUTATIONS.flatMap(({ flowTag }) => [
|
|
108
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
|
|
109
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
|
|
110
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_WbsMain.js`,
|
|
111
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
|
|
112
|
+
]),
|
|
113
|
+
FLOW_RBAC_YAML_PATH
|
|
114
|
+
];
|
|
115
|
+
|
|
86
116
|
export function rbacApplicationManagedPaths(objects = []) {
|
|
87
117
|
if (!Array.isArray(objects)) {
|
|
88
118
|
throw new TypeError('objects must be an array');
|
|
89
119
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
|
|
98
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrApi.js`
|
|
99
|
-
]),
|
|
100
|
-
...MUTATION_DEFINITIONS.flatMap(({ flowTag }) => [
|
|
101
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
|
|
102
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
|
|
103
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_WbsMain.js`,
|
|
104
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
|
|
105
|
-
]),
|
|
106
|
-
...USER_ROLE_MUTATIONS.flatMap(({ flowTag }) => [
|
|
107
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_Main.js`,
|
|
108
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrSqs.js`,
|
|
109
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_WbsMain.js`,
|
|
110
|
-
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
|
|
111
|
-
]),
|
|
112
|
-
...objects.filter(hasRbacAddOn).flatMap((object) => {
|
|
113
|
-
const flowTag = rbacFlowTag(object);
|
|
114
|
-
const sourcePath = `app/src/generatedCode/FlowRbac/${flowTag}/source`;
|
|
115
|
-
return [
|
|
116
|
-
`${sourcePath}/${flowTag}_Main.js`,
|
|
117
|
-
`${sourcePath}/${flowTag}_HdrSqs.js`
|
|
118
|
-
];
|
|
119
|
-
}),
|
|
120
|
-
FLOW_RBAC_YAML_PATH
|
|
121
|
-
];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function hasRbacAddOn(object) {
|
|
125
|
-
return (
|
|
126
|
-
Array.isArray(object?.addOnDataStructure) &&
|
|
127
|
-
object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
|
|
128
|
-
);
|
|
120
|
+
const rbacObjects = objects.filter(hasRbacAddOn);
|
|
121
|
+
const sourcePaths = rbacObjects.flatMap((object) => {
|
|
122
|
+
const flowTag = rbacFlowTag(object);
|
|
123
|
+
const sourcePath = `app/src/generatedCode/FlowRbac/${flowTag}/source`;
|
|
124
|
+
return [`${sourcePath}/${flowTag}_Main.js`, `${sourcePath}/${flowTag}_HdrSqs.js`];
|
|
125
|
+
});
|
|
126
|
+
return [...STATIC_RBAC_APPLICATION_PATHS, ...sourcePaths];
|
|
129
127
|
}
|
|
130
128
|
|
|
131
129
|
async function createTargetRoleHandler() {
|
|
@@ -367,3 +365,20 @@ async function renderTemplate(templateUrl, templateName, data) {
|
|
|
367
365
|
data
|
|
368
366
|
);
|
|
369
367
|
}
|
|
368
|
+
|
|
369
|
+
function hasSelfRbacAddOn(object) {
|
|
370
|
+
return (
|
|
371
|
+
Array.isArray(object?.addOnDataStructure) &&
|
|
372
|
+
object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function hasRbacAddOn(object) {
|
|
377
|
+
const selfHasRbac = hasSelfRbacAddOn(object);
|
|
378
|
+
const belongToHasRbac =
|
|
379
|
+
Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
|
|
380
|
+
object.belongToSchema.addOnDataStructure.some(
|
|
381
|
+
(addOn) => addOn?.type === 'rbac'
|
|
382
|
+
);
|
|
383
|
+
return selfHasRbac || belongToHasRbac;
|
|
384
|
+
}
|
|
@@ -15,33 +15,81 @@ You should have received a copy of the GNU Affero General Public License
|
|
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
middlewareHandler as middleware,
|
|
20
|
+
validatorSchema
|
|
21
|
+
} from '@izara_project/izara-middleware';
|
|
19
22
|
import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
|
|
23
|
+
import Logger from '@izara_project/izara-core-library-logger';
|
|
20
24
|
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
25
|
+
|
|
21
26
|
import CreateTargetRole from './CreateTargetRole_Main.js';
|
|
22
27
|
|
|
28
|
+
// validate event properties in body.Message of sqs event
|
|
23
29
|
middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
let perRecordsValidatorSchema = {
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: {}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const main = middleware.wrap(async (event, context) => {
|
|
37
|
+
try {
|
|
38
|
+
let recordPromises = [];
|
|
39
|
+
|
|
40
|
+
// loop each record and send to mainFunction
|
|
41
|
+
await Promise.all(
|
|
42
|
+
event.Records.map(async (record) => {
|
|
43
|
+
// promise.all for map() function
|
|
44
|
+
|
|
45
|
+
let passOnProperties = [];
|
|
46
|
+
record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
|
|
47
|
+
|
|
48
|
+
// validate message (and MessageAttributes)
|
|
49
|
+
await recordHandlerSharedLib.validateRecord(
|
|
50
|
+
record, // one record will send to mainFunction
|
|
51
|
+
'CreateTargetRoleHdrSqs', // queue name that need to retry or send to dlq
|
|
52
|
+
perRecordsValidatorSchema // schema for record.Message
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// add argument (to invoke lambda) to passOnProperties[]
|
|
56
|
+
passOnProperties.push(record.body.Message);
|
|
57
|
+
passOnProperties.push(
|
|
40
58
|
callingFlowSharedLib.addCallingFlowToPassOnProperties(
|
|
41
59
|
record.body.Message
|
|
42
60
|
)
|
|
43
|
-
|
|
61
|
+
);
|
|
62
|
+
record._izContext.logger.debug(
|
|
63
|
+
'passOnProperties in handler',
|
|
64
|
+
passOnProperties
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)
|
|
68
|
+
let recordPromise = recordHandlerSharedLib.recordHandler(
|
|
69
|
+
record, // one record will send to mainFunction
|
|
70
|
+
CreateTargetRole, // mainFunction that need to invoke.
|
|
71
|
+
'CreateTargetRoleHdrSqs', // queue name that need to retry or send to dlq
|
|
72
|
+
passOnProperties // all parameters that mainFunction needed.
|
|
73
|
+
);
|
|
74
|
+
record._izContext.logger.debug('after recordPromise in handler');
|
|
75
|
+
recordPromises.push(recordPromise); // push promise to recordPromises
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
Logger.debug('before Promise.all(recordPromises) in handler');
|
|
80
|
+
try {
|
|
81
|
+
// --- main await all promises
|
|
82
|
+
await Promise.all(recordPromises); // await all promises
|
|
83
|
+
|
|
84
|
+
return event.Records; // return all for local testing
|
|
85
|
+
} catch {
|
|
86
|
+
Logger.debug(
|
|
87
|
+
'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
|
|
44
88
|
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
)
|
|
89
|
+
}
|
|
90
|
+
Logger.debug('after Promise.all(recordPromises) in handler');
|
|
91
|
+
} catch (err) {
|
|
92
|
+
Logger.error('Unhandled Error, LambdaFunctionHdrSqs: ', err);
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
@@ -15,32 +15,81 @@ You should have received a copy of the GNU Affero General Public License
|
|
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
middlewareHandler as middleware,
|
|
20
|
+
validatorSchema
|
|
21
|
+
} from '@izara_project/izara-middleware';
|
|
19
22
|
import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
|
|
23
|
+
import Logger from '@izara_project/izara-core-library-logger';
|
|
20
24
|
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
25
|
+
|
|
21
26
|
import <%- flowTag %> from './<%- flowTag %>_Main.js';
|
|
22
27
|
|
|
28
|
+
// validate event properties in body.Message of sqs event
|
|
23
29
|
middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
|
|
31
|
+
let perRecordsValidatorSchema = {
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: {}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const main = middleware.wrap(async (event, context) => {
|
|
37
|
+
try {
|
|
38
|
+
let recordPromises = [];
|
|
39
|
+
|
|
40
|
+
// loop each record and send to mainFunction
|
|
41
|
+
await Promise.all(
|
|
42
|
+
event.Records.map(async (record) => {
|
|
43
|
+
// promise.all for map() function
|
|
44
|
+
|
|
45
|
+
let passOnProperties = [];
|
|
46
|
+
record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
|
|
47
|
+
|
|
48
|
+
// validate message (and MessageAttributes)
|
|
49
|
+
await recordHandlerSharedLib.validateRecord(
|
|
50
|
+
record, // one record will send to mainFunction
|
|
51
|
+
'<%- flowTag %>HdrSqs', // queue name that need to retry or send to dlq
|
|
52
|
+
perRecordsValidatorSchema // schema for record.Message
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// add argument (to invoke lambda) to passOnProperties[]
|
|
56
|
+
passOnProperties.push(record.body.Message);
|
|
57
|
+
passOnProperties.push(
|
|
39
58
|
callingFlowSharedLib.addCallingFlowToPassOnProperties(
|
|
40
59
|
record.body.Message
|
|
41
60
|
)
|
|
42
|
-
|
|
61
|
+
);
|
|
62
|
+
record._izContext.logger.debug(
|
|
63
|
+
'passOnProperties in handler',
|
|
64
|
+
passOnProperties
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)
|
|
68
|
+
let recordPromise = recordHandlerSharedLib.recordHandler(
|
|
69
|
+
record, // one record will send to mainFunction
|
|
70
|
+
<%- flowTag %>, // mainFunction that need to invoke.
|
|
71
|
+
'<%- flowTag %>HdrSqs', // queue name that need to retry or send to dlq
|
|
72
|
+
passOnProperties // all parameters that mainFunction needed.
|
|
73
|
+
);
|
|
74
|
+
record._izContext.logger.debug('after recordPromise in handler');
|
|
75
|
+
recordPromises.push(recordPromise); // push promise to recordPromises
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
Logger.debug('before Promise.all(recordPromises) in handler');
|
|
80
|
+
try {
|
|
81
|
+
// --- main await all promises
|
|
82
|
+
await Promise.all(recordPromises); // await all promises
|
|
83
|
+
|
|
84
|
+
return event.Records; // return all for local testing
|
|
85
|
+
} catch {
|
|
86
|
+
Logger.debug(
|
|
87
|
+
'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
|
|
43
88
|
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
)
|
|
89
|
+
}
|
|
90
|
+
Logger.debug('after Promise.all(recordPromises) in handler');
|
|
91
|
+
} catch (err) {
|
|
92
|
+
Logger.error('Unhandled Error, LambdaFunctionHdrSqs: ', err);
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
@@ -15,32 +15,81 @@ You should have received a copy of the GNU Affero General Public License
|
|
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
middlewareHandler as middleware,
|
|
20
|
+
validatorSchema
|
|
21
|
+
} from '@izara_project/izara-middleware';
|
|
19
22
|
import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
|
|
23
|
+
import Logger from '@izara_project/izara-core-library-logger';
|
|
20
24
|
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
25
|
+
|
|
21
26
|
import <%- flowTag %> from './<%- flowTag %>_Main.js';
|
|
22
27
|
|
|
28
|
+
// validate event properties in body.Message of sqs event
|
|
23
29
|
middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
|
|
31
|
+
let perRecordsValidatorSchema = {
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: {}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const main = middleware.wrap(async (event, context) => {
|
|
37
|
+
try {
|
|
38
|
+
let recordPromises = [];
|
|
39
|
+
|
|
40
|
+
// loop each record and send to mainFunction
|
|
41
|
+
await Promise.all(
|
|
42
|
+
event.Records.map(async (record) => {
|
|
43
|
+
// promise.all for map() function
|
|
44
|
+
|
|
45
|
+
let passOnProperties = [];
|
|
46
|
+
record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
|
|
47
|
+
|
|
48
|
+
// validate message (and MessageAttributes)
|
|
49
|
+
await recordHandlerSharedLib.validateRecord(
|
|
50
|
+
record, // one record will send to mainFunction
|
|
51
|
+
'<%- flowTag %>HdrSqs', // queue name that need to retry or send to dlq
|
|
52
|
+
perRecordsValidatorSchema // schema for record.Message
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// add argument (to invoke lambda) to passOnProperties[]
|
|
56
|
+
passOnProperties.push(record.body.Message);
|
|
57
|
+
passOnProperties.push(
|
|
39
58
|
callingFlowSharedLib.addCallingFlowToPassOnProperties(
|
|
40
59
|
record.body.Message
|
|
41
60
|
)
|
|
42
|
-
|
|
61
|
+
);
|
|
62
|
+
record._izContext.logger.debug(
|
|
63
|
+
'passOnProperties in handler',
|
|
64
|
+
passOnProperties
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)
|
|
68
|
+
let recordPromise = recordHandlerSharedLib.recordHandler(
|
|
69
|
+
record, // one record will send to mainFunction
|
|
70
|
+
<%- flowTag %>, // mainFunction that need to invoke.
|
|
71
|
+
'<%- flowTag %>HdrSqs', // queue name that need to retry or send to dlq
|
|
72
|
+
passOnProperties // all parameters that mainFunction needed.
|
|
73
|
+
);
|
|
74
|
+
record._izContext.logger.debug('after recordPromise in handler');
|
|
75
|
+
recordPromises.push(recordPromise); // push promise to recordPromises
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
Logger.debug('before Promise.all(recordPromises) in handler');
|
|
80
|
+
try {
|
|
81
|
+
// --- main await all promises
|
|
82
|
+
await Promise.all(recordPromises); // await all promises
|
|
83
|
+
|
|
84
|
+
return event.Records; // return all for local testing
|
|
85
|
+
} catch {
|
|
86
|
+
Logger.debug(
|
|
87
|
+
'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
|
|
43
88
|
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
)
|
|
89
|
+
}
|
|
90
|
+
Logger.debug('after Promise.all(recordPromises) in handler');
|
|
91
|
+
} catch (err) {
|
|
92
|
+
Logger.error('Unhandled Error, LambdaFunctionHdrSqs: ', err);
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
@@ -13,8 +13,17 @@ export const dynamicRelationshipFlowSchemaPaths = ACTIONS.map(
|
|
|
13
13
|
`app/src/schemas/FlowSchemas/generateCode/FlowRelationship/${action}.js`
|
|
14
14
|
);
|
|
15
15
|
|
|
16
|
-
export function
|
|
17
|
-
|
|
16
|
+
export function dynamicRelationshipFlowSchemaManagedPaths(relationships = []) {
|
|
17
|
+
if (!Array.isArray(relationships) || relationships.length === 0) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
return dynamicRelationshipFlowSchemaPaths;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function emitDynamicRelationshipFlowSchemas({ relationships = [] } = {}) {
|
|
24
|
+
if (!Array.isArray(relationships) || relationships.length === 0) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
18
27
|
return ACTIONS.map((action, index) => ({
|
|
19
28
|
path: dynamicRelationshipFlowSchemaPaths[index],
|
|
20
29
|
content: _renderDynamicRelationshipFlowSchema(
|
|
@@ -3,7 +3,7 @@ import { commitArtifacts } from '../../output/commitArtifacts.js';
|
|
|
3
3
|
import { compileProject } from '../../compile/compileProject.js';
|
|
4
4
|
import { loadLocalSchemaDirectory } from '../../compile/loadSchemas.js';
|
|
5
5
|
import {
|
|
6
|
-
|
|
6
|
+
dynamicRelationshipFlowSchemaManagedPaths,
|
|
7
7
|
emitDynamicRelationshipFlowSchemas
|
|
8
8
|
} from './emitDynamicRelationshipFlowSchemas.js';
|
|
9
9
|
|
|
@@ -12,14 +12,15 @@ export async function generateDynamicRelationshipFlowSchemas(
|
|
|
12
12
|
options = {}
|
|
13
13
|
) {
|
|
14
14
|
const project = compileProject({ ...options, rootPath });
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const relationships = await loadLocalSchemaDirectory(
|
|
16
|
+
project,
|
|
17
|
+
'RelationshipSchemas'
|
|
18
|
+
);
|
|
18
19
|
const plan = buildGenerationPlan(
|
|
19
20
|
project,
|
|
20
|
-
emitDynamicRelationshipFlowSchemas(),
|
|
21
|
+
emitDynamicRelationshipFlowSchemas({ relationships }),
|
|
21
22
|
{
|
|
22
|
-
managedPaths:
|
|
23
|
+
managedPaths: dynamicRelationshipFlowSchemaManagedPaths(relationships),
|
|
23
24
|
managedScope: 'relationship-flow-schemas'
|
|
24
25
|
}
|
|
25
26
|
);
|
|
@@ -148,6 +148,7 @@ export const resourceArtifactPaths = [
|
|
|
148
148
|
|
|
149
149
|
function createResourceState({ objects, relationships, flows }) {
|
|
150
150
|
const crud = objects.some(isCrudObject);
|
|
151
|
+
const selfRbac = objects.some(hasSelfRbacAddOn);
|
|
151
152
|
const rbac = objects.some(hasRbacAddOn);
|
|
152
153
|
const ownTopics = new Set([
|
|
153
154
|
'ProcessLogical',
|
|
@@ -195,11 +196,13 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
195
196
|
}
|
|
196
197
|
dsqQueues.add('GetRelationshipHdrDsq');
|
|
197
198
|
}
|
|
198
|
-
if (
|
|
199
|
+
if (selfRbac) {
|
|
199
200
|
for (const action of RBAC_ACTIONS) {
|
|
200
201
|
ownTopics.add(action);
|
|
201
202
|
sqsQueues.add(`Process${action}HdrSqs`);
|
|
202
203
|
}
|
|
204
|
+
}
|
|
205
|
+
if (rbac) {
|
|
203
206
|
for (const object of objects.filter(hasRbacAddOn)) {
|
|
204
207
|
const flowTag = upperFirst(object.objectType) + 'RbacFlow';
|
|
205
208
|
ownTopics.add(flowTag);
|
|
@@ -408,6 +411,9 @@ async function renderInSqs(state) {
|
|
|
408
411
|
? [
|
|
409
412
|
render('ResourceSqsYaml.ejs', {
|
|
410
413
|
queueName: 'WebSocketCompleteHdrSqs'
|
|
414
|
+
}),
|
|
415
|
+
render('ResourceSqsYaml.ejs', {
|
|
416
|
+
queueName: 'RegisterComplete'
|
|
411
417
|
})
|
|
412
418
|
]
|
|
413
419
|
: [])
|
|
@@ -600,6 +606,12 @@ function roleQueueNames(state, roleName) {
|
|
|
600
606
|
}
|
|
601
607
|
return [];
|
|
602
608
|
}
|
|
609
|
+
if (roleName === 'RegisterRole') {
|
|
610
|
+
if (state.websocket) {
|
|
611
|
+
return ['RegisterComplete'];
|
|
612
|
+
}
|
|
613
|
+
return [];
|
|
614
|
+
}
|
|
603
615
|
if (roleName === 'FlowObjectsRole') {
|
|
604
616
|
return [
|
|
605
617
|
...CRUD_ACTIONS.map((action) => `${action}HdrSqs`),
|
|
@@ -816,13 +828,21 @@ function isCrudObject(object) {
|
|
|
816
828
|
object?.generatedBy === 'systemGenerated'
|
|
817
829
|
);
|
|
818
830
|
}
|
|
819
|
-
function
|
|
831
|
+
function hasSelfRbacAddOn(object) {
|
|
820
832
|
return (
|
|
821
833
|
Array.isArray(object?.addOnDataStructure) &&
|
|
822
834
|
object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
|
|
823
835
|
);
|
|
824
836
|
}
|
|
825
837
|
|
|
838
|
+
function hasRbacAddOn(object) {
|
|
839
|
+
const selfHasRbac = hasSelfRbacAddOn(object);
|
|
840
|
+
const belongToHasRbac =
|
|
841
|
+
Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
|
|
842
|
+
object.belongToSchema.addOnDataStructure.some((addOn) => addOn?.type === 'rbac');
|
|
843
|
+
return selfHasRbac || belongToHasRbac;
|
|
844
|
+
}
|
|
845
|
+
|
|
826
846
|
/**
|
|
827
847
|
* Returns the per-object RBAC flow queues (e.g. UserRbacFlowHdrSqs)
|
|
828
848
|
* created for objects with an 'rbac' add-on. These are consumed by the
|
|
@@ -40,7 +40,7 @@ function _hasStorageObjects(objects) {
|
|
|
40
40
|
|
|
41
41
|
async function _emitSystemArtifacts(objects) {
|
|
42
42
|
if (!_hasStorageObjects(objects)) {
|
|
43
|
-
return [];
|
|
43
|
+
return { artifacts: [], functions: [] };
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const hasFindDataEntries = buildFindDataEntries(objects).length > 0;
|
|
@@ -80,17 +80,16 @@ async function _emitSystemArtifacts(objects) {
|
|
|
80
80
|
{
|
|
81
81
|
path: `${PROCESS_LOGICAL_SOURCE}/PaginateProcessLogical_HdrSqs.js`,
|
|
82
82
|
content: await render('PaginateProcessLogical_HdrSqs.ejs', {})
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
path: YAML_PATH,
|
|
86
|
-
content: renderSystemYaml()
|
|
87
83
|
}
|
|
88
84
|
);
|
|
89
85
|
|
|
90
|
-
return
|
|
86
|
+
return {
|
|
87
|
+
artifacts,
|
|
88
|
+
functions: renderSystemYamlFunctions()
|
|
89
|
+
};
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
function
|
|
92
|
+
function renderSystemYamlFunctions() {
|
|
94
93
|
const findDataYaml = renderFindDataYaml();
|
|
95
94
|
const processLogicalYaml = renderProcessLogicalYaml();
|
|
96
95
|
const processLogicalPaginateDsqYaml = renderProcessLogicalPaginateDsqYaml();
|
|
@@ -100,7 +99,7 @@ function renderSystemYaml() {
|
|
|
100
99
|
processLogicalYaml,
|
|
101
100
|
processLogicalPaginateDsqYaml,
|
|
102
101
|
processLogicalPaginateSqsYaml
|
|
103
|
-
]
|
|
102
|
+
];
|
|
104
103
|
}
|
|
105
104
|
|
|
106
105
|
function renderFindDataYaml() {
|
package/src/generate.js
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
rbacApplicationManagedPaths
|
|
23
23
|
} from './emit/rbac/emitRbacApplicationArtifacts.js';
|
|
24
24
|
import {
|
|
25
|
-
|
|
25
|
+
dynamicRelationshipFlowSchemaManagedPaths,
|
|
26
26
|
emitDynamicRelationshipFlowSchemas
|
|
27
27
|
} from './emit/relationship/emitDynamicRelationshipFlowSchemas.js';
|
|
28
28
|
import {
|
|
@@ -139,10 +139,23 @@ async function _emitGroups({ project, objects, relationships, flows, objectGraph
|
|
|
139
139
|
emitCoreFunctionArtifacts({ project, objects, relationships, flows, objectGraphServiceTags, relationshipGraphServiceTags })
|
|
140
140
|
]);
|
|
141
141
|
const custom = await emitCustomFlowApplicationArtifacts(flows, {
|
|
142
|
-
systemFunctions: system.functions,
|
|
143
142
|
objects
|
|
144
143
|
});
|
|
145
144
|
|
|
145
|
+
const systemFunctions = [
|
|
146
|
+
...(system.functions ?? []),
|
|
147
|
+
...(findData.functions ?? [])
|
|
148
|
+
].filter(Boolean);
|
|
149
|
+
|
|
150
|
+
const findDataArtifacts = [...(findData.artifacts ?? [])];
|
|
151
|
+
|
|
152
|
+
if (systemFunctions.length > 0) {
|
|
153
|
+
findDataArtifacts.push({
|
|
154
|
+
path: 'app/sls_yaml/generatedCode/source/flow-system.yml',
|
|
155
|
+
content: systemFunctions.join('\n\n')
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
146
159
|
let resolvedCoreFunctionManagedPaths = coreFunctionManagedPaths;
|
|
147
160
|
if (typeof coreFunctionManagedPaths === 'function') {
|
|
148
161
|
resolvedCoreFunctionManagedPaths = coreFunctionManagedPaths(
|
|
@@ -160,8 +173,8 @@ async function _emitGroups({ project, objects, relationships, flows, objectGraph
|
|
|
160
173
|
},
|
|
161
174
|
{
|
|
162
175
|
scope: 'relationship-flow-schemas',
|
|
163
|
-
managedPaths:
|
|
164
|
-
artifacts: emitDynamicRelationshipFlowSchemas()
|
|
176
|
+
managedPaths: dynamicRelationshipFlowSchemaManagedPaths(relationships),
|
|
177
|
+
artifacts: emitDynamicRelationshipFlowSchemas({ relationships })
|
|
165
178
|
},
|
|
166
179
|
{
|
|
167
180
|
scope: 'rbac-flow-schemas',
|
|
@@ -194,15 +207,11 @@ async function _emitGroups({ project, objects, relationships, flows, objectGraph
|
|
|
194
207
|
{
|
|
195
208
|
scope: 'system-find-data',
|
|
196
209
|
managedPaths: findDataManagedPaths(),
|
|
197
|
-
artifacts:
|
|
210
|
+
artifacts: findDataArtifacts
|
|
198
211
|
},
|
|
199
212
|
{
|
|
200
213
|
scope: 'custom-flow-application',
|
|
201
|
-
managedPaths: customFlowApplicationManagedPaths(flows,
|
|
202
|
-
includeYaml: hasSystemWebSocket(flows, {
|
|
203
|
-
includeRelationshipOwnTopic: true
|
|
204
|
-
})
|
|
205
|
-
}),
|
|
214
|
+
managedPaths: customFlowApplicationManagedPaths(flows),
|
|
206
215
|
artifacts: custom
|
|
207
216
|
},
|
|
208
217
|
{
|
package/src/output/mergeHooks.js
CHANGED
|
@@ -39,7 +39,8 @@ async function mergeHook(outputRoot, artifact) {
|
|
|
39
39
|
|
|
40
40
|
return artifact.content.replace(
|
|
41
41
|
matchers.anyTag,
|
|
42
|
-
(_match,
|
|
42
|
+
(_match, p1, _body1, p2) => {
|
|
43
|
+
const tagName = p1 || p2;
|
|
43
44
|
const hookBlock = sourceContent.match(matchers.tagPattern(tagName))?.[0];
|
|
44
45
|
return hookBlock ?? _match;
|
|
45
46
|
}
|
|
@@ -49,10 +50,10 @@ async function mergeHook(outputRoot, artifact) {
|
|
|
49
50
|
function hookMatchers(filePath) {
|
|
50
51
|
if (filePath.endsWith('.js')) {
|
|
51
52
|
return {
|
|
52
|
-
anyTag:
|
|
53
|
+
anyTag: /(?:\/\/\(<(\w+)>\)([\s\S]*?)\/\/\(<\/\1>\)|\/\/\s*<#(\w+)#>([\s\S]*?)\/\/\s*<#\/\3#>)/gm,
|
|
53
54
|
tagPattern: (name) =>
|
|
54
55
|
new RegExp(
|
|
55
|
-
|
|
56
|
+
`(?:\\/\\/\\(<${name}>\\)([\\s\\S]*?)\\/\\/\\(<\\/${name}>\\)|\\/\\/\\s*<#${name}#>([\\s\\S]*?)\\/\\/\\s*<#\\/${name}#>)`,
|
|
56
57
|
'gm'
|
|
57
58
|
)
|
|
58
59
|
};
|
|
@@ -25,7 +25,18 @@ after(async () => {
|
|
|
25
25
|
);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
test('
|
|
28
|
+
test('does not generate dynamic relationship schemas when no relationships exist', async () => {
|
|
29
|
+
const rootPath = await mkdtemp(
|
|
30
|
+
join(tmpdir(), 'generate-service-code-v2-relationship-empty-')
|
|
31
|
+
);
|
|
32
|
+
projectRoots.add(rootPath);
|
|
33
|
+
|
|
34
|
+
const result = await generateDynamicRelationshipFlowSchemas(rootPath);
|
|
35
|
+
|
|
36
|
+
assert.equal(result.files.length, 0);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('generates dynamic relationship schemas when declared relationships exist', async () => {
|
|
29
40
|
const rootPath = await createProject();
|
|
30
41
|
|
|
31
42
|
const result = await generateDynamicRelationshipFlowSchemas(rootPath);
|
package/test/publicApi.test.js
CHANGED
|
@@ -23,7 +23,7 @@ test('generate commits schemas, application artifacts, and resources in one publ
|
|
|
23
23
|
const rootPath = await createCrudProject();
|
|
24
24
|
const result = await generate(rootPath);
|
|
25
25
|
|
|
26
|
-
assert.strictEqual(result.files.length,
|
|
26
|
+
assert.strictEqual(result.files.length, 57);
|
|
27
27
|
assert.equal(result.project.rootPath, rootPath);
|
|
28
28
|
assert.match(
|
|
29
29
|
await readFile(
|
|
@@ -129,14 +129,14 @@ test('generate commits the system WebSocket completion path for own-topic flows'
|
|
|
129
129
|
);
|
|
130
130
|
assert.match(
|
|
131
131
|
await readFile(
|
|
132
|
-
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-
|
|
132
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-system.yml'),
|
|
133
133
|
'utf8'
|
|
134
134
|
),
|
|
135
135
|
/WebSocketConnect:[\s\S]*route: \$connect[\s\S]*WebSocketCompleteHdrSqs:/
|
|
136
136
|
);
|
|
137
137
|
assert.match(
|
|
138
138
|
await readFile(
|
|
139
|
-
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-
|
|
139
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-system.yml'),
|
|
140
140
|
'utf8'
|
|
141
141
|
),
|
|
142
142
|
/filterPatterns:[\s\S]*WebSocketCompleteHdrSqs/
|
|
@@ -151,6 +151,16 @@ test('generate commits the system WebSocket completion path for own-topic flows'
|
|
|
151
151
|
),
|
|
152
152
|
/WebSocketCompleteHdrSqs:[\s\S]*SubscriptionToOutTrackWebSocketComplete:/
|
|
153
153
|
);
|
|
154
|
+
assert.match(
|
|
155
|
+
await readFile(
|
|
156
|
+
join(
|
|
157
|
+
rootPath,
|
|
158
|
+
'resource/sls_yaml/generatedCode/source/generated-sns-in-sqs.yml'
|
|
159
|
+
),
|
|
160
|
+
'utf8'
|
|
161
|
+
),
|
|
162
|
+
/RegisterComplete:[\s\S]*RegisterCompleteDLQ:/
|
|
163
|
+
);
|
|
154
164
|
assert.match(
|
|
155
165
|
await readFile(
|
|
156
166
|
join(
|
|
@@ -288,7 +298,7 @@ test('generate removes stale CRUD schemas and application artifacts', async () =
|
|
|
288
298
|
|
|
289
299
|
const result = await generate(rootPath);
|
|
290
300
|
|
|
291
|
-
assert.equal(result.files.length,
|
|
301
|
+
assert.equal(result.files.length, 28);
|
|
292
302
|
await assert.rejects(
|
|
293
303
|
readFile(
|
|
294
304
|
join(
|
|
@@ -386,14 +396,21 @@ test(
|
|
|
386
396
|
assert.match(uploadSchemaMain, /\/\/\(<ignoreExternalServices>\)/);
|
|
387
397
|
assert.match(uploadSchemaMain, /\/\/\(<\/ignoreExternalServices>\)/);
|
|
388
398
|
|
|
389
|
-
const
|
|
399
|
+
const coreResource = await readFile(
|
|
390
400
|
join(
|
|
391
401
|
rootPath,
|
|
392
|
-
'app/
|
|
402
|
+
'app/sls_yaml/generatedCode/source/core-resource.yml'
|
|
393
403
|
),
|
|
394
404
|
'utf8'
|
|
395
405
|
);
|
|
396
|
-
assert.match(
|
|
397
|
-
|
|
406
|
+
assert.match(
|
|
407
|
+
coreResource,
|
|
408
|
+
/UserAccount\$\{self:custom\.iz_stage\}AddLinkCreateByRelHdrInv/
|
|
409
|
+
);
|
|
410
|
+
assert.match(
|
|
411
|
+
coreResource,
|
|
412
|
+
/UserAccount\$\{self:custom\.iz_stage\}AddLinkBelongToHdrInv/
|
|
413
|
+
);
|
|
398
414
|
}
|
|
399
415
|
);
|
|
416
|
+
|
|
@@ -102,7 +102,8 @@ test('emits queues, topics, tables, and IAM roles from schema data', async () =>
|
|
|
102
102
|
/Process(?:Create|Update|Delete|Get|Change|Move)Relationship/
|
|
103
103
|
);
|
|
104
104
|
assert.match(roleBlock(iam, 'RegisterRole'), /s3:GetObject/);
|
|
105
|
-
assert.
|
|
105
|
+
assert.match(roleBlock(iam, 'RegisterRole'), /RegisterComplete/);
|
|
106
|
+
assert.doesNotMatch(roleBlock(iam, 'RegisterRole'), /dynamodb:|sns:/);
|
|
106
107
|
assert.doesNotMatch(
|
|
107
108
|
iam,
|
|
108
109
|
/s3:GetObjectVersion|s3:ListBucket|sqs:DeleteMessageBatch|sqs:GetQueueUrl/
|