@izara_project/izara-core-generate-service-code 1.0.77 → 1.0.79
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 +2 -2
- package/src/compile/flowValidator.js +163 -0
- package/src/compile/loadSchemas.js +15 -5
- package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +137 -7
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +132 -17
- package/src/emit/crud/crudActionPlan.js +82 -0
- package/src/emit/crud/emitCrudApplicationArtifacts.js +162 -112
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +43 -65
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +84 -512
- package/src/emit/crud/templates/CreateLogicalLib.ejs +536 -0
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +87 -202
- package/src/emit/crud/templates/DeleteLogicalLib.ejs +213 -0
- package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +217 -0
- package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
- package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +9 -2
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +87 -444
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +472 -0
- package/src/emit/custom/customFlows.js +27 -2
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +1 -2
- package/src/emit/custom/templates/FlowEndpoint_Main.ejs +10 -3
- package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
- package/src/emit/custom/templates/s3/CreateObject_Main.ejs +1 -1
- package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +2 -2
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +3 -9
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +21 -16
- package/src/emit/rbac/rbacFlowTag.js +2 -7
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +148 -21
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +4 -2
- package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/CreateRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/MoveRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +1 -1
- package/src/emit/resource/emitResourceArtifacts.js +85 -70
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +31 -5
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +21 -0
- package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
- package/src/emit/shared/templates/FlowHandler_HdrApi.ejs +1 -1
- package/src/emit/shared/templates/FlowHandler_HdrDsq.ejs +2 -2
- package/src/emit/shared/templates/FlowHandler_HdrInv.ejs +1 -1
- package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +2 -2
- package/src/emit/system/emitSystemWebSocketArtifacts.js +2 -2
- package/src/emit/system/templates/RegisterComplete_Yaml.ejs +4 -4
- package/src/emit/systemText/emitSystemTextSchemas.js +246 -0
- package/src/emit/systemText/templates/SystemTextSchemas.ejs +10 -0
- package/src/generate.js +55 -8
- package/test/crudApplicationArtifacts.test.js +147 -19
- package/test/customFlowApplicationArtifacts.test.js +308 -16
- package/test/dynamicCrudFlowSchemas.test.js +150 -14
- package/test/dynamicRbacFlowSchemas.test.js +2 -2
- package/test/dynamicRelationshipFlowSchemas.test.js +1 -1
- package/test/graphDrivenFlowSchema.test.js +257 -0
- package/test/publicApi.test.js +15 -6
- package/test/resourceArtifacts.test.js +25 -19
- package/test/systemTextSchemas.test.js +154 -0
- package/src/emit/crud/templates/CreateComplete_HdrSqs.ejs +0 -99
- package/src/emit/crud/templates/DeleteComplete_HdrSqs.ejs +0 -99
- package/src/emit/crud/templates/FlowEndpointBeforeLogical_Main.ejs +0 -174
- package/src/emit/crud/templates/FlowEndpointComplete_Main.ejs +0 -187
- package/src/emit/crud/templates/UpdateComplete_HdrSqs.ejs +0 -99
- package/src/emit/resource/templates/ResourceBeforeLogicalYaml.ejs +0 -47
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2020 Sven Mason <http: //izara.io>
|
|
3
|
+
|
|
4
|
+
This program is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU Affero General Public License as
|
|
6
|
+
published by the Free Software Foundation, either version 3 of the
|
|
7
|
+
License, or (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
This program is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU Affero General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
along with this program. If not, see
|
|
16
|
+
<http: //www.gnu.org/licenses />.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// ==================== Shared Core Utilities ====================
|
|
20
|
+
import {
|
|
21
|
+
objectHash as hash,
|
|
22
|
+
identifierUuid
|
|
23
|
+
} from '@izara_project/izara-shared-core';
|
|
24
|
+
import {
|
|
25
|
+
consts as coreConsts,
|
|
26
|
+
NoRetryError
|
|
27
|
+
} from '@izara_project/izara-core-library-core';
|
|
28
|
+
|
|
29
|
+
// ==================== Core Service Schemas ====================
|
|
30
|
+
import {
|
|
31
|
+
getObjectSchema,
|
|
32
|
+
consts,
|
|
33
|
+
utils,
|
|
34
|
+
identifiersObject,
|
|
35
|
+
dataDetailsLib,
|
|
36
|
+
uploadUseCase
|
|
37
|
+
} from '@izara_project/izara-core-library-service-schemas';
|
|
38
|
+
const { createObjType } = utils;
|
|
39
|
+
const { dynamoDbIdentifiersByStorageResource } = identifiersObject;
|
|
40
|
+
const { createUpdateDataDetail } = dataDetailsLib;
|
|
41
|
+
const { PREFIX, TOPIC_NAME_GENERATE_CODE, TOPIC_NAME_GRAPH_HANDLER } = consts;
|
|
42
|
+
|
|
43
|
+
// ==================== Shared Libraries ====================
|
|
44
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
45
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
46
|
+
import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
|
|
47
|
+
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
48
|
+
import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
|
|
49
|
+
|
|
50
|
+
// ==================== External Services ====================
|
|
51
|
+
import {
|
|
52
|
+
sns,
|
|
53
|
+
lambda
|
|
54
|
+
} from '@izara_project/izara-core-library-external-request';
|
|
55
|
+
|
|
56
|
+
//(<optionalRequire>)
|
|
57
|
+
//(</optionalRequire>)
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Core logical processing library
|
|
61
|
+
* @param {Object} _izContext - Context object with logger
|
|
62
|
+
* @param {Object} requestParams - { objectType, objInstanceFull, versionedDataIds, additionalParams }
|
|
63
|
+
* @param {Object} callingFlowConfig - Calling flow configuration
|
|
64
|
+
* @param {Object} phaseResults - Results from preceding phases
|
|
65
|
+
* @returns {Promise<Object>}
|
|
66
|
+
*/
|
|
67
|
+
export async function <%- flowTag %>LogicalLib(
|
|
68
|
+
_izContext,
|
|
69
|
+
requestParams,
|
|
70
|
+
callingFlowConfig = {},
|
|
71
|
+
errorsFound = [],
|
|
72
|
+
phaseResults = {}
|
|
73
|
+
) {
|
|
74
|
+
try {
|
|
75
|
+
_izContext.logger.debug('[<%- flowTag %>LogicalLib] started', {
|
|
76
|
+
requestParams,
|
|
77
|
+
callingFlowConfig,
|
|
78
|
+
phaseResults
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
//(<beforeUpdateMainLogical>)
|
|
82
|
+
//(</beforeUpdateMainLogical>)
|
|
83
|
+
|
|
84
|
+
// ── Settings ──────────────────────────────────────────────────────────────
|
|
85
|
+
const settings = requestParams.additionalParams?.settings ?? {};
|
|
86
|
+
const returnSystemFieldsName = settings.returnSystemFieldsName === true;
|
|
87
|
+
const returnOldData = settings.returnOldData === true;
|
|
88
|
+
|
|
89
|
+
const objType = createObjType(requestParams.objectType);
|
|
90
|
+
const identifiers = requestParams.objInstanceFull.identifiers;
|
|
91
|
+
const fields = requestParams.objInstanceFull.fields;
|
|
92
|
+
const versionedDataIds = requestParams.versionedDataIds ?? {};
|
|
93
|
+
const parentFlowId = identifierUuid();
|
|
94
|
+
// ── Load schema ───────────────────────────────────────────────────────────
|
|
95
|
+
const objectSchema = await getObjectSchema.getObjSchemaS3WithHierarchy(
|
|
96
|
+
_izContext,
|
|
97
|
+
objType
|
|
98
|
+
);
|
|
99
|
+
_izContext.logger.debug('objectSchema', objectSchema);
|
|
100
|
+
|
|
101
|
+
const objectSchemas =
|
|
102
|
+
await uploadUseCase.generateObjectSchemaForCombineFieldNames(
|
|
103
|
+
_izContext,
|
|
104
|
+
objectSchema
|
|
105
|
+
);
|
|
106
|
+
_izContext.logger.debug('objectSchemas', objectSchemas);
|
|
107
|
+
|
|
108
|
+
// ── Build updateDataDetails ───────────────────────────────────────────────
|
|
109
|
+
const updateDataDetails = await createUpdateDataDetail(
|
|
110
|
+
_izContext,
|
|
111
|
+
objectSchemas
|
|
112
|
+
);
|
|
113
|
+
_izContext.logger.debug('updateDataDetails', updateDataDetails);
|
|
114
|
+
|
|
115
|
+
const originTimestamp = Date.now();
|
|
116
|
+
|
|
117
|
+
// ── Validate versionedDataIds ─────────────────────────────────────────────
|
|
118
|
+
const haveVersionedDataIdsToUpdate =
|
|
119
|
+
Object.keys(versionedDataIds).length > 0;
|
|
120
|
+
if (haveVersionedDataIdsToUpdate) {
|
|
121
|
+
const updateMainNodeData = {};
|
|
122
|
+
const updateVersionedData = {};
|
|
123
|
+
|
|
124
|
+
for (const [fieldProp, fieldVal] of Object.entries(
|
|
125
|
+
requestParams.objInstanceFull.fields
|
|
126
|
+
)) {
|
|
127
|
+
const fieldSetting = objectSchema.fieldNames[fieldProp];
|
|
128
|
+
if (fieldSetting.hasOwnProperty('versionedDataLabel')) {
|
|
129
|
+
updateVersionedData[fieldSetting.versionedDataLabel] ??= {};
|
|
130
|
+
Object.assign(updateVersionedData[fieldSetting.versionedDataLabel], {
|
|
131
|
+
[fieldProp]: fieldVal
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
Object.assign(updateMainNodeData, { [fieldProp]: fieldVal });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
_izContext.logger.debug('updateMainNodeData::', updateMainNodeData);
|
|
139
|
+
_izContext.logger.debug('updateVersionedData::', updateVersionedData);
|
|
140
|
+
|
|
141
|
+
const versionedDataIdLabelKeys = Object.keys(versionedDataIds);
|
|
142
|
+
const updateVersionedDataLabelKeys = Object.keys(updateVersionedData);
|
|
143
|
+
|
|
144
|
+
const missingVersionedDataIdLabels = updateVersionedDataLabelKeys.filter(
|
|
145
|
+
(l) => !versionedDataIdLabelKeys.includes(l)
|
|
146
|
+
);
|
|
147
|
+
const missingDataVersionedDataLabels = versionedDataIdLabelKeys.filter(
|
|
148
|
+
(l) => !updateVersionedDataLabelKeys.includes(l)
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
if (missingVersionedDataIdLabels.length)
|
|
152
|
+
errorsFound.push(
|
|
153
|
+
`missing versionedDataIds of versionedDataLabel '${missingVersionedDataIdLabels.join(', ')}'`
|
|
154
|
+
);
|
|
155
|
+
if (missingDataVersionedDataLabels.length)
|
|
156
|
+
errorsFound.push(
|
|
157
|
+
`missing data of versionedDataLabels '${missingDataVersionedDataLabels.join(', ')}'`
|
|
158
|
+
);
|
|
159
|
+
if (Object.keys(updateMainNodeData).length)
|
|
160
|
+
errorsFound.push('cannot update mainNode if have versionedDataIds');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
//(<validateBeforeUpdate>)
|
|
164
|
+
//(</validateBeforeUpdate>)
|
|
165
|
+
|
|
166
|
+
// ── Early exit on errors ──────────────────────────────────────────────────
|
|
167
|
+
if (errorsFound.length) {
|
|
168
|
+
const updateNodeCompleteMessage =
|
|
169
|
+
callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
|
|
170
|
+
callingFlowConfig,
|
|
171
|
+
{
|
|
172
|
+
objType,
|
|
173
|
+
objInstanceFull: { identifiers, fields },
|
|
174
|
+
versionedDataIds,
|
|
175
|
+
status: 'error',
|
|
176
|
+
errorsFound
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
_izContext.logger.debug(
|
|
181
|
+
'messageParams OutUpdateNodeComplete:::',
|
|
182
|
+
updateNodeCompleteMessage
|
|
183
|
+
);
|
|
184
|
+
await sns.publishAsync(_izContext, {
|
|
185
|
+
Message: JSON.stringify(updateNodeCompleteMessage),
|
|
186
|
+
MessageAttributes: sns.createStringMessageAttributes(
|
|
187
|
+
_izContext,
|
|
188
|
+
callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
|
|
189
|
+
callingFlowConfig,
|
|
190
|
+
{}
|
|
191
|
+
)
|
|
192
|
+
),
|
|
193
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
194
|
+
_izContext,
|
|
195
|
+
TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
|
|
196
|
+
)
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return updateNodeCompleteMessage;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ── Helper: extract fields per storageTag ─────────────────────────────────
|
|
203
|
+
function createObjInstanceFullFieldsByStorageTag(
|
|
204
|
+
_izContext,
|
|
205
|
+
storageTag,
|
|
206
|
+
updateDataDetail
|
|
207
|
+
) {
|
|
208
|
+
const result = {};
|
|
209
|
+
for (const fieldName of Object.keys(
|
|
210
|
+
requestParams.objInstanceFull.fields
|
|
211
|
+
)) {
|
|
212
|
+
if (
|
|
213
|
+
updateDataDetails[storageTag].fieldNames.includes(fieldName) &&
|
|
214
|
+
updateDataDetail.fieldNames.includes(fieldName) &&
|
|
215
|
+
!identifiers.hasOwnProperty(fieldName) &&
|
|
216
|
+
!result.hasOwnProperty(fieldName)
|
|
217
|
+
) {
|
|
218
|
+
Object.assign(result, {
|
|
219
|
+
[fieldName]: requestParams.objInstanceFull.fields[fieldName]
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ── Helper: build objInstanceFull from updateItem ─────────────────────────
|
|
227
|
+
function createObjInstanceFullFromParams(object, requestParams) {
|
|
228
|
+
const objInstanceFull = { identifiers: {}, fields: {} };
|
|
229
|
+
for (const field of Object.keys(object)) {
|
|
230
|
+
if (requestParams.objInstanceFull.identifiers.hasOwnProperty(field)) {
|
|
231
|
+
Object.assign(objInstanceFull.identifiers, {
|
|
232
|
+
[field]: requestParams.objInstanceFull.identifiers[field]
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
if (requestParams.objInstanceFull.fields.hasOwnProperty(field)) {
|
|
236
|
+
Object.assign(objInstanceFull.fields, {
|
|
237
|
+
[field]: requestParams.objInstanceFull.fields[field]
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return objInstanceFull;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ── Process storage resources ─────────────────────────────────────────────
|
|
245
|
+
const awaitingStepIds = [];
|
|
246
|
+
const listOfRecords = [];
|
|
247
|
+
let updateItem;
|
|
248
|
+
|
|
249
|
+
await Promise.all(
|
|
250
|
+
Object.entries(updateDataDetails).map(
|
|
251
|
+
async ([storageTag, updateDataDetail]) => {
|
|
252
|
+
// ── Graph ─────────────────────────────────────────────────────────────
|
|
253
|
+
if (updateDataDetail.storageType === consts.STORAGE_TYPES.graph) {
|
|
254
|
+
//(<beforeUpdateGraph>)
|
|
255
|
+
//(</beforeUpdateGraph>)
|
|
256
|
+
|
|
257
|
+
const graphFields = createObjInstanceFullFieldsByStorageTag(
|
|
258
|
+
_izContext,
|
|
259
|
+
storageTag,
|
|
260
|
+
updateDataDetail
|
|
261
|
+
);
|
|
262
|
+
if (!Object.keys(graphFields).length) return;
|
|
263
|
+
|
|
264
|
+
//(<beforeUpdateNode>)
|
|
265
|
+
//(</beforeUpdateNode>)
|
|
266
|
+
|
|
267
|
+
//(<additionalAttributes>)
|
|
268
|
+
const additionalAttributes = {};
|
|
269
|
+
//(</additionalAttributes>)
|
|
270
|
+
|
|
271
|
+
const records = awaitingStepIds.length === 0 ? listOfRecords : [];
|
|
272
|
+
awaitingStepIds.push({
|
|
273
|
+
awaitingStepId: asyncFlowSharedLib.createAwaitingStepId(
|
|
274
|
+
parentFlowId,
|
|
275
|
+
PREFIX.updateNode
|
|
276
|
+
),
|
|
277
|
+
additionalAttributes: {
|
|
278
|
+
listOfRecords: records,
|
|
279
|
+
additionalAttributes: additionalAttributes
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
if (awaitingStepIds.length) {
|
|
284
|
+
const awaitingMultipleStep =
|
|
285
|
+
await asyncFlowSharedLib.createAwaitingMultipleSteps(
|
|
286
|
+
_izContext,
|
|
287
|
+
asyncFlowSharedLib.createPendingStepId(
|
|
288
|
+
_izContext.uniqueRequestId
|
|
289
|
+
),
|
|
290
|
+
awaitingStepIds
|
|
291
|
+
);
|
|
292
|
+
_izContext.logger.debug(
|
|
293
|
+
'awaitingMultipleStep',
|
|
294
|
+
awaitingMultipleStep
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
let updateNodeParams = {
|
|
299
|
+
objType,
|
|
300
|
+
objInstanceFull: { identifiers, fields: graphFields },
|
|
301
|
+
versionedDataIds,
|
|
302
|
+
originTimestamp,
|
|
303
|
+
settings: { returnSystemFieldsName, returnOldData },
|
|
304
|
+
parentFlowId
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
updateNodeParams =
|
|
308
|
+
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
309
|
+
updateNodeParams,
|
|
310
|
+
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
311
|
+
callingFlowConfig,
|
|
312
|
+
callingFlowSharedLib.createCallingFlowConfig(
|
|
313
|
+
//(<callingFlowProperties>)
|
|
314
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
315
|
+
_izContext,
|
|
316
|
+
TOPIC_NAME_GENERATE_CODE.updateNodeComplete
|
|
317
|
+
),
|
|
318
|
+
{}
|
|
319
|
+
//(</callingFlowProperties>)
|
|
320
|
+
)
|
|
321
|
+
)
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
_izContext.logger.debug(
|
|
325
|
+
'messageObject before send message:',
|
|
326
|
+
updateNodeParams
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
const resSNS = await sns.publishAsync(_izContext, {
|
|
330
|
+
Message: JSON.stringify(updateNodeParams),
|
|
331
|
+
MessageAttributes: sns.createStringMessageAttributes(
|
|
332
|
+
_izContext,
|
|
333
|
+
callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
|
|
334
|
+
callingFlowConfig,
|
|
335
|
+
{}
|
|
336
|
+
)
|
|
337
|
+
),
|
|
338
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
339
|
+
_izContext,
|
|
340
|
+
TOPIC_NAME_GRAPH_HANDLER.inUpdateNode,
|
|
341
|
+
storageTag
|
|
342
|
+
)
|
|
343
|
+
});
|
|
344
|
+
_izContext.logger.debug(
|
|
345
|
+
'resSNS send to topic InUpdateNode finish!',
|
|
346
|
+
resSNS
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
// ── DynamoDB ──────────────────────────────────────────────────────────
|
|
350
|
+
} else if (
|
|
351
|
+
updateDataDetail.storageType === consts.STORAGE_TYPES.dynamoDB
|
|
352
|
+
) {
|
|
353
|
+
const dynamoFields = createObjInstanceFullFieldsByStorageTag(
|
|
354
|
+
_izContext,
|
|
355
|
+
storageTag,
|
|
356
|
+
updateDataDetail
|
|
357
|
+
);
|
|
358
|
+
if (!Object.keys(dynamoFields).length) return;
|
|
359
|
+
|
|
360
|
+
//(<beforeUpdateDynamoDb>)
|
|
361
|
+
//(</beforeUpdateDynamoDb>)
|
|
362
|
+
|
|
363
|
+
const identifiersForUpdateData =
|
|
364
|
+
await dynamoDbIdentifiersByStorageResource(
|
|
365
|
+
_izContext,
|
|
366
|
+
objectSchema,
|
|
367
|
+
updateDataDetail,
|
|
368
|
+
identifiers
|
|
369
|
+
);
|
|
370
|
+
_izContext.logger.debug(
|
|
371
|
+
'identifiersForUpdateData',
|
|
372
|
+
identifiersForUpdateData
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
if (
|
|
376
|
+
Object.values(updateDataDetails).some(
|
|
377
|
+
(updateDataDetail) =>
|
|
378
|
+
updateDataDetail.storageType === consts.STORAGE_TYPES.graph
|
|
379
|
+
)
|
|
380
|
+
) {
|
|
381
|
+
_izContext.logger.debug('must process graph first');
|
|
382
|
+
listOfRecords.push({
|
|
383
|
+
[storageTag]: {
|
|
384
|
+
serviceTag: updateDataDetail.serviceTag,
|
|
385
|
+
tableName: updateDataDetail.tableName,
|
|
386
|
+
objInstanceFull: {
|
|
387
|
+
identifiers: identifiersForUpdateData,
|
|
388
|
+
fields: dynamoFields
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
} else {
|
|
393
|
+
_izContext.logger.debug('can process record dynamo');
|
|
394
|
+
updateItem = await dynamodbSharedLib.updateItem(
|
|
395
|
+
_izContext,
|
|
396
|
+
await dynamodbSharedLib.tableName(
|
|
397
|
+
_izContext,
|
|
398
|
+
updateDataDetail.tableName,
|
|
399
|
+
updateDataDetail.serviceTag
|
|
400
|
+
),
|
|
401
|
+
identifiersForUpdateData,
|
|
402
|
+
dynamoFields,
|
|
403
|
+
{ returnValues: 'ALL_NEW' }
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
_izContext.logger.debug('updateItem:', updateItem);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
)
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
// ── DynamoDB-only complete path ───────────────────────────────────────────
|
|
414
|
+
if (awaitingStepIds.length === 0) {
|
|
415
|
+
let messageObject = {
|
|
416
|
+
objType,
|
|
417
|
+
objInstanceFull: createObjInstanceFullFromParams(
|
|
418
|
+
updateItem,
|
|
419
|
+
requestParams
|
|
420
|
+
)
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
//(<additionalProperties>)
|
|
424
|
+
//(</additionalProperties>)
|
|
425
|
+
|
|
426
|
+
if (
|
|
427
|
+
callingFlowConfig[
|
|
428
|
+
callingFlowSharedLib.consts.CALLINGFLOWPROPERTIES_PROPERTYNAME
|
|
429
|
+
]
|
|
430
|
+
) {
|
|
431
|
+
_izContext.logger.debug('HAVE CALLING FLOW');
|
|
432
|
+
messageObject =
|
|
433
|
+
callingFlowSharedLib.addPassBackPropertiesToSnsResponseMessageObject(
|
|
434
|
+
callingFlowConfig,
|
|
435
|
+
messageObject
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
_izContext.logger.debug('after create callingFlow', messageObject);
|
|
439
|
+
await sns.publishAsync(_izContext, {
|
|
440
|
+
Message: JSON.stringify(messageObject),
|
|
441
|
+
MessageAttributes: sns.createStringMessageAttributes(
|
|
442
|
+
_izContext,
|
|
443
|
+
callingFlowSharedLib.addCallingFlowToSnsResponseMessageAttributes(
|
|
444
|
+
callingFlowConfig,
|
|
445
|
+
{}
|
|
446
|
+
)
|
|
447
|
+
),
|
|
448
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
449
|
+
_izContext,
|
|
450
|
+
TOPIC_NAME_GENERATE_CODE.outUpdateNodeComplete
|
|
451
|
+
)
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return {
|
|
457
|
+
returnValues: {
|
|
458
|
+
objType,
|
|
459
|
+
objInstanceFull: { identifiers, fields },
|
|
460
|
+
versionedDataIds
|
|
461
|
+
},
|
|
462
|
+
status: 'complete',
|
|
463
|
+
errorsFound
|
|
464
|
+
};
|
|
465
|
+
} catch (err) {
|
|
466
|
+
_izContext.logger.error('[<%- flowTag %>LogicalLib] error:', err);
|
|
467
|
+
throw err;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export const <%- flowTag %>MainLogical = <%- flowTag %>LogicalLib;
|
|
472
|
+
export default <%- flowTag %>LogicalLib;
|
|
@@ -198,10 +198,36 @@ export function customFlowNextSteps(flows) {
|
|
|
198
198
|
const roleName = upperFirst(flow.flowTag);
|
|
199
199
|
const steps = flow.flowSteps ?? [];
|
|
200
200
|
const nextStepsList = [];
|
|
201
|
+
const seenKeys = new Set();
|
|
201
202
|
for (const step of steps) {
|
|
202
203
|
const items = _stepNextSteps(step);
|
|
203
204
|
for (const item of items) {
|
|
204
|
-
|
|
205
|
+
const topicVal = item.topicName || item.topic;
|
|
206
|
+
const functionVal = item.functionName || item.topicName || item.topic;
|
|
207
|
+
const targetType = item.targetType || '';
|
|
208
|
+
const serviceTag = item.serviceTag || '';
|
|
209
|
+
let targetVal = '';
|
|
210
|
+
if (targetType === 'lambdaSyncInv') {
|
|
211
|
+
targetVal = functionVal;
|
|
212
|
+
} else if (targetType === 'extTopic' || targetType === 'ownTopic') {
|
|
213
|
+
targetVal = topicVal;
|
|
214
|
+
} else {
|
|
215
|
+
targetVal = topicVal || functionVal;
|
|
216
|
+
}
|
|
217
|
+
let typeCategory = targetType;
|
|
218
|
+
if (targetType === 'extTopic' || targetType === 'ownTopic') {
|
|
219
|
+
typeCategory = 'sns';
|
|
220
|
+
}
|
|
221
|
+
const dedupeKey = `${typeCategory}:${serviceTag}:${targetVal}`;
|
|
222
|
+
if (!seenKeys.has(dedupeKey)) {
|
|
223
|
+
seenKeys.add(dedupeKey);
|
|
224
|
+
nextStepsList.push({
|
|
225
|
+
...item,
|
|
226
|
+
topic: topicVal,
|
|
227
|
+
topicName: topicVal,
|
|
228
|
+
functionName: functionVal
|
|
229
|
+
});
|
|
230
|
+
}
|
|
205
231
|
}
|
|
206
232
|
}
|
|
207
233
|
if (nextStepsList.length > 0) {
|
|
@@ -214,4 +240,3 @@ export function customFlowNextSteps(flows) {
|
|
|
214
240
|
}
|
|
215
241
|
return results;
|
|
216
242
|
}
|
|
217
|
-
|
|
@@ -646,8 +646,7 @@ function _startConfig(flow) {
|
|
|
646
646
|
) ??
|
|
647
647
|
steps.find(
|
|
648
648
|
(s) =>
|
|
649
|
-
typeof s?.stepName === 'string' &&
|
|
650
|
-
s.stepName.toLowerCase() === 'start'
|
|
649
|
+
typeof s?.stepName === 'string' && s.stepName.toLowerCase() === 'start'
|
|
651
650
|
) ??
|
|
652
651
|
steps[0];
|
|
653
652
|
if (start) {
|
|
@@ -61,7 +61,7 @@ const { createFlowTypeConcat } = utils;
|
|
|
61
61
|
export default async function <%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %>(
|
|
62
62
|
_izContext,
|
|
63
63
|
requestParams,
|
|
64
|
-
callingFlowConfig = {}
|
|
64
|
+
callingFlowConfig = {},
|
|
65
65
|
//(<additionalParams>)
|
|
66
66
|
//(</additionalParams>)
|
|
67
67
|
) {
|
|
@@ -109,7 +109,7 @@ export default async function <%- typeof functionName !== 'undefined' ? function
|
|
|
109
109
|
//(</checkStoredCacheHook>)
|
|
110
110
|
}
|
|
111
111
|
<% } -%>
|
|
112
|
-
<% if (typeof flow !== 'undefined' && flow.isRbac) { -%>
|
|
112
|
+
<% if (typeof flow !== 'undefined' && flow.isRbac && !flow.generatedCodeConfig) { -%>
|
|
113
113
|
|
|
114
114
|
const { checkRbacPermission } =
|
|
115
115
|
await import('@izara_project/izara-authorization');
|
|
@@ -121,7 +121,14 @@ export default async function <%- typeof functionName !== 'undefined' ? function
|
|
|
121
121
|
const resultPermissionCheck = await checkRbacPermission(
|
|
122
122
|
_izContext,
|
|
123
123
|
{ flowTag: '<%- flow.flowTag %>', serviceTag: '<%- flow.serviceTag || (flow.objType ? flow.objType.serviceTag : "") %>' },
|
|
124
|
-
parameterGroups
|
|
124
|
+
parameterGroups,
|
|
125
|
+
{
|
|
126
|
+
rbacObjType: {
|
|
127
|
+
serviceTag: '<%- (flow.objType?.belongTo ? (Array.isArray(flow.objType.belongTo) ? flow.objType.belongTo[0]?.serviceTag : flow.objType.belongTo?.serviceTag) : null) || flow.serviceTag || (flow.objType ? flow.objType.serviceTag : "") %>'
|
|
128
|
+
},
|
|
129
|
+
requestParams: typeof requestParams !== 'undefined' ? requestParams : {},
|
|
130
|
+
nextFlowStepName: '<%- flow.flowTag %>RbacCallback'
|
|
131
|
+
}
|
|
125
132
|
);
|
|
126
133
|
|
|
127
134
|
_izContext.logger.debug(
|
|
@@ -37,7 +37,7 @@ import { identifierUuid } from '@izara_project/izara-shared-core';
|
|
|
37
37
|
export default async function <%= functionName %>(
|
|
38
38
|
_izContext,
|
|
39
39
|
requestParams,
|
|
40
|
-
callingFlowConfig = {}
|
|
40
|
+
callingFlowConfig = {},
|
|
41
41
|
//(<additionalParams>)
|
|
42
42
|
//(</additionalParams>)
|
|
43
43
|
) {
|
|
@@ -11,7 +11,7 @@ let perRecordsValidatorSchema = {
|
|
|
11
11
|
properties: {
|
|
12
12
|
<%_ startConfig.properties.forEach((prop, index) => { _%>
|
|
13
13
|
<%- /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(prop.propertyName) ? prop.propertyName : `'${prop.propertyName}'` %>: {
|
|
14
|
-
type:
|
|
14
|
+
type: <%- prop.type === 'mixed' ? "['string', 'number', 'integer', 'boolean', 'null', 'object', 'array']" : `'${prop.type || 'string'}'` %><% if (typeof prop.default !== 'undefined') { %>,
|
|
15
15
|
default: <%- typeof prop.default === 'string' ? `'${prop.default.replace(/'/g, "\\'")}'` : JSON.stringify(prop.default) %><% } %>
|
|
16
16
|
}<%- index < startConfig.properties.length - 1 ? ',' : '' %>
|
|
17
17
|
<%_ }) _%>
|
|
@@ -29,7 +29,7 @@ let messageAttributeValidatorSchema = {
|
|
|
29
29
|
type: 'object',
|
|
30
30
|
properties: {
|
|
31
31
|
Type: { type: 'string' },
|
|
32
|
-
Value: { type:
|
|
32
|
+
Value: { type: <%- prop.type === 'mixed' ? "['string', 'number', 'integer', 'boolean', 'null', 'object', 'array']" : `'${prop.type || 'string'}'` %> }
|
|
33
33
|
},
|
|
34
34
|
required: ['Type', 'Value']
|
|
35
35
|
}<%- index < startConfig.messageAttributes.length - 1 ? ',' : '' %>
|
|
@@ -74,13 +74,7 @@ function _hasSelfRbacAddOn(object) {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
function _hasRbacAddOn(object) {
|
|
77
|
-
|
|
78
|
-
const belongToHasRbac =
|
|
79
|
-
Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
|
|
80
|
-
object.belongToSchema.addOnDataStructure.some(
|
|
81
|
-
(addOn) => addOn?.type === 'rbac'
|
|
82
|
-
);
|
|
83
|
-
return selfHasRbac || belongToHasRbac;
|
|
77
|
+
return _hasSelfRbacAddOn(object);
|
|
84
78
|
}
|
|
85
79
|
|
|
86
80
|
async function _artifact(flowTag, flow) {
|
|
@@ -108,7 +102,7 @@ function _createSharedRbacFlow(flowTag, event) {
|
|
|
108
102
|
},
|
|
109
103
|
flowSteps: [
|
|
110
104
|
{
|
|
111
|
-
stepName: '
|
|
105
|
+
stepName: 'Start',
|
|
112
106
|
properties: [],
|
|
113
107
|
messageAttributes: [],
|
|
114
108
|
returnValues: {
|
|
@@ -135,7 +129,7 @@ function _createUserRbacFlow(flowTag, serviceTag, objectType) {
|
|
|
135
129
|
},
|
|
136
130
|
flowSteps: [
|
|
137
131
|
{
|
|
138
|
-
stepName: '
|
|
132
|
+
stepName: 'Start',
|
|
139
133
|
messageAttributes: ['userId', 'correlationId']
|
|
140
134
|
}
|
|
141
135
|
]
|