@izara_project/izara-core-generate-service-code 1.0.79 → 1.0.81
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 +4 -4
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +47 -3
- package/src/emit/crud/emitCrudApplicationArtifacts.js +12 -5
- package/src/emit/crud/templates/CreateComplete_Main.ejs +8 -3
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +6 -1
- package/src/emit/crud/templates/CreateLogicalLib.ejs +6 -1
- package/src/emit/crud/templates/DeleteComplete_Main.ejs +8 -3
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +7 -2
- package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +111 -37
- package/src/emit/crud/templates/UpdateComplete_Main.ejs +8 -3
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +7 -2
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +6 -1
- package/src/emit/relationship/templates/ChangeRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +5 -1
- package/src/emit/relationship/templates/CreateRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/CreateRelationship_Main.ejs +5 -1
- package/src/emit/relationship/templates/DeleteRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +5 -1
- package/src/emit/relationship/templates/MoveRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/MoveRelationship_Main.ejs +5 -1
- package/src/emit/relationship/templates/UpdateRelationshipComplete_Main.ejs +7 -2
- package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +5 -1
- package/src/emit/resource/emitResourceArtifacts.js +66 -11
- package/src/emit/resource/templates/DynamoDBTable_Yaml.ejs +4 -4
- package/test/crudApplicationArtifacts.test.js +11 -0
- package/test/customFlowApplicationArtifacts.test.js +59 -3
- package/test/resourceArtifacts.test.js +41 -0
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.81",
|
|
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": {
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"@izara_project/izara-shared-core": "^1.0.13",
|
|
27
27
|
"ejs": "^6.0.1",
|
|
28
28
|
"js-beautify": "^2.0.3",
|
|
29
|
-
"ws": "^8.21.
|
|
29
|
+
"ws": "^8.21.3",
|
|
30
30
|
"yaml": "^2.9.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@izara_project/izara-core-library-logger": "^1.0.11",
|
|
34
|
-
"@izara_project/izara-core-library-service-schemas": "1.0.
|
|
35
|
-
"@izara_project/izara-shared-service-schemas": "^1.0.
|
|
34
|
+
"@izara_project/izara-core-library-service-schemas": "1.0.162",
|
|
35
|
+
"@izara_project/izara-shared-service-schemas": "^1.0.71",
|
|
36
36
|
"jest": "^30.4.2",
|
|
37
37
|
"prettier": "^3.9.6",
|
|
38
38
|
"prettier-plugin-ejs": "^1.0.3"
|
|
@@ -146,13 +146,44 @@ const tableConfigs = {
|
|
|
146
146
|
}
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
+
const stepSubs = [];
|
|
150
|
+
const seenStepSubs = new Set();
|
|
151
|
+
(flows || []).forEach(function(flow) {
|
|
152
|
+
const flowTag = flow?.flowTag ? flow.flowTag[0].toUpperCase() + flow.flowTag.slice(1) : '';
|
|
153
|
+
(flow?.flowSteps || []).forEach(function(step) {
|
|
154
|
+
if (Array.isArray(step?.previousSteps)) {
|
|
155
|
+
const stepName = step?.stepName ? step.stepName[0].toUpperCase() + step.stepName.slice(1) : '';
|
|
156
|
+
const functionName = stepName.startsWith(flowTag) ? stepName : `${flowTag}${stepName}`;
|
|
157
|
+
const queueName = `${functionName}HdrSqs`;
|
|
158
|
+
step.previousSteps.forEach(function(prev) {
|
|
159
|
+
if (prev && prev.sourceType === 'extTopic' && prev.serviceTag && prev.topicName) {
|
|
160
|
+
const key = `${prev.serviceTag}:${prev.topicName}:${queueName}`;
|
|
161
|
+
if (!seenStepSubs.has(key)) {
|
|
162
|
+
seenStepSubs.add(key);
|
|
163
|
+
stepSubs.push({
|
|
164
|
+
serviceTag: prev.serviceTag,
|
|
165
|
+
topicName: prev.topicName,
|
|
166
|
+
sqsEndpoint: queueName
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
149
175
|
const rbacSubs = [];
|
|
150
176
|
if (crud && typeof rbacValidatorServiceTags !== 'undefined' && rbacValidatorServiceTags && rbacValidatorServiceTags.length > 0) {
|
|
151
177
|
const allRbacTags = Array.from(new Set(['Rbac', ...rbacValidatorServiceTags]));
|
|
178
|
+
const hasGraph = typeof objectGraphServiceTags !== 'undefined' && objectGraphServiceTags && objectGraphServiceTags.length > 0;
|
|
179
|
+
const updateEndpoint = hasGraph ? 'UpdateRbacCallbackHdrSqs' : 'UpdateCompleteHdrSqs';
|
|
180
|
+
const deleteEndpoint = hasGraph ? 'DeleteRbacCallbackHdrSqs' : 'DeleteCompleteHdrSqs';
|
|
152
181
|
allRbacTags.forEach(function(tag) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
182
|
+
if (!hasGraph) {
|
|
183
|
+
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
|
|
184
|
+
}
|
|
185
|
+
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: updateEndpoint });
|
|
186
|
+
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: deleteEndpoint });
|
|
156
187
|
});
|
|
157
188
|
}
|
|
158
189
|
-%>
|
|
@@ -195,6 +226,19 @@ const snsTopicSubscriptions = [
|
|
|
195
226
|
},
|
|
196
227
|
<% }); -%>
|
|
197
228
|
<% } -%>
|
|
229
|
+
<% if (stepSubs.length > 0) { -%>
|
|
230
|
+
|
|
231
|
+
// ------------------------------------------------------------
|
|
232
|
+
// Step Subscriptions (from previousSteps)
|
|
233
|
+
// ------------------------------------------------------------
|
|
234
|
+
<% stepSubs.forEach(function(sub, idx) { -%>
|
|
235
|
+
{
|
|
236
|
+
serviceTag: '<%= sub.serviceTag %>',
|
|
237
|
+
topicName: '<%= sub.topicName %>',
|
|
238
|
+
sqsEndpoint: '<%= sub.sqsEndpoint %>'
|
|
239
|
+
},
|
|
240
|
+
<% }); -%>
|
|
241
|
+
<% } -%>
|
|
198
242
|
<% if (rbacSubs.length > 0) { -%>
|
|
199
243
|
|
|
200
244
|
// ------------------------------------------------------------
|
|
@@ -89,7 +89,8 @@ async function emitAction(action, objects, serviceTag) {
|
|
|
89
89
|
startConfig: null,
|
|
90
90
|
objects: action === 'Create' ? [] : objects,
|
|
91
91
|
isCrudObject,
|
|
92
|
-
hasRbacAddOn: (object) => hasRbacAddOn(object, objects)
|
|
92
|
+
hasRbacAddOn: (object) => hasRbacAddOn(object, objects),
|
|
93
|
+
plan
|
|
93
94
|
};
|
|
94
95
|
const artifacts = [
|
|
95
96
|
{
|
|
@@ -276,13 +277,19 @@ async function emitAction(action, objects, serviceTag) {
|
|
|
276
277
|
|
|
277
278
|
if (plan.hasComplete) {
|
|
278
279
|
const completeMain = `${action}Complete_Main`;
|
|
280
|
+
const templateName =
|
|
281
|
+
plan.hasRbac && !plan.hasGraph
|
|
282
|
+
? 'FlowEndpointRbacCallback_Main.ejs'
|
|
283
|
+
: `${action}Complete_Main.ejs`;
|
|
284
|
+
const templateContext =
|
|
285
|
+
plan.hasRbac && !plan.hasGraph
|
|
286
|
+
? shared
|
|
287
|
+
: { action, ...shared };
|
|
288
|
+
|
|
279
289
|
artifacts.push(
|
|
280
290
|
{
|
|
281
291
|
path: `${source}/${completeMain}.js`,
|
|
282
|
-
content: await render(
|
|
283
|
-
plan.hasRbac ? 'FlowEndpointRbacCallback_Main.ejs' : `${action}Complete_Main.ejs`,
|
|
284
|
-
plan.hasRbac ? shared : { action }
|
|
285
|
-
)
|
|
292
|
+
content: await render(templateName, templateContext)
|
|
286
293
|
},
|
|
287
294
|
{
|
|
288
295
|
path: `${source}/${action}Complete_HdrSqs.js`,
|
|
@@ -118,8 +118,10 @@ export default async function CreateComplete(
|
|
|
118
118
|
}
|
|
119
119
|
: null;
|
|
120
120
|
if (status === 'complete') {
|
|
121
|
+
const listOfRecords =
|
|
122
|
+
result?.additionalAttributes?.listOfRecords ?? [];
|
|
121
123
|
await Promise.all(
|
|
122
|
-
(
|
|
124
|
+
(listOfRecords ?? []).flatMap((records) =>
|
|
123
125
|
Object.values(records).map(async (record) =>
|
|
124
126
|
dynamodbSharedLib.putItem(
|
|
125
127
|
_izContext,
|
|
@@ -137,9 +139,12 @@ export default async function CreateComplete(
|
|
|
137
139
|
)
|
|
138
140
|
);
|
|
139
141
|
}
|
|
142
|
+
const callingFlowConfig =
|
|
143
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
144
|
+
passBackProperties;
|
|
140
145
|
const message =
|
|
141
146
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
142
|
-
|
|
147
|
+
callingFlowConfig,
|
|
143
148
|
{
|
|
144
149
|
objType: returnValue.requestParams.objType,
|
|
145
150
|
objInstanceFull: node.objInstanceFull,
|
|
@@ -152,7 +157,7 @@ export default async function CreateComplete(
|
|
|
152
157
|
);
|
|
153
158
|
const messageAttributes =
|
|
154
159
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
155
|
-
|
|
160
|
+
callingFlowConfig,
|
|
156
161
|
{}
|
|
157
162
|
);
|
|
158
163
|
const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
|
|
@@ -375,7 +375,12 @@ export default async function <%- flowTag %>(
|
|
|
375
375
|
_izContext.uniqueRequestId,
|
|
376
376
|
'logical_<%= objectType %>'
|
|
377
377
|
),
|
|
378
|
-
awaitingMultipleStepIds
|
|
378
|
+
awaitingMultipleStepIds,
|
|
379
|
+
{
|
|
380
|
+
additionalAttributes: {
|
|
381
|
+
callingFlowConfig
|
|
382
|
+
}
|
|
383
|
+
}
|
|
379
384
|
);
|
|
380
385
|
|
|
381
386
|
//(<beforePublish_<%= objectType %>>)
|
|
@@ -364,7 +364,12 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
364
364
|
_izContext.uniqueRequestId,
|
|
365
365
|
PREFIX.CREATE_OBJECT_ASYNC_COMPLETE
|
|
366
366
|
),
|
|
367
|
-
allAwaitingStepsId
|
|
367
|
+
allAwaitingStepsId,
|
|
368
|
+
{
|
|
369
|
+
additionalAttributes: {
|
|
370
|
+
callingFlowConfig
|
|
371
|
+
}
|
|
372
|
+
}
|
|
368
373
|
);
|
|
369
374
|
}
|
|
370
375
|
|
|
@@ -118,8 +118,10 @@ export default async function DeleteComplete(
|
|
|
118
118
|
}
|
|
119
119
|
: null;
|
|
120
120
|
if (status === 'complete') {
|
|
121
|
+
const listOfRecords =
|
|
122
|
+
result?.additionalAttributes?.listOfRecords ?? [];
|
|
121
123
|
await Promise.all(
|
|
122
|
-
(
|
|
124
|
+
(listOfRecords ?? []).flatMap((records) =>
|
|
123
125
|
Object.values(records).map(async (record) =>
|
|
124
126
|
dynamodbSharedLib.putItem(
|
|
125
127
|
_izContext,
|
|
@@ -137,9 +139,12 @@ export default async function DeleteComplete(
|
|
|
137
139
|
)
|
|
138
140
|
);
|
|
139
141
|
}
|
|
142
|
+
const callingFlowConfig =
|
|
143
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
144
|
+
passBackProperties;
|
|
140
145
|
const message =
|
|
141
146
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
142
|
-
|
|
147
|
+
callingFlowConfig,
|
|
143
148
|
{
|
|
144
149
|
objType: returnValue.requestParams.objType,
|
|
145
150
|
objInstanceFull: node.objInstanceFull,
|
|
@@ -152,7 +157,7 @@ export default async function DeleteComplete(
|
|
|
152
157
|
);
|
|
153
158
|
const messageAttributes =
|
|
154
159
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
155
|
-
|
|
160
|
+
callingFlowConfig,
|
|
156
161
|
{}
|
|
157
162
|
);
|
|
158
163
|
const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
|
|
@@ -141,7 +141,7 @@ export default async function <%- flowTag %>(
|
|
|
141
141
|
serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
|
|
142
142
|
},
|
|
143
143
|
requestParams: requestParams,
|
|
144
|
-
nextFlowStepName: '<%- flowTag %>
|
|
144
|
+
nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>'
|
|
145
145
|
}
|
|
146
146
|
);
|
|
147
147
|
|
|
@@ -250,7 +250,12 @@ export default async function <%- flowTag %>(
|
|
|
250
250
|
_izContext.uniqueRequestId,
|
|
251
251
|
'logical_<%= objectType %>'
|
|
252
252
|
),
|
|
253
|
-
awaitingMultipleStepIds
|
|
253
|
+
awaitingMultipleStepIds,
|
|
254
|
+
{
|
|
255
|
+
additionalAttributes: {
|
|
256
|
+
callingFlowConfig
|
|
257
|
+
}
|
|
258
|
+
}
|
|
254
259
|
);
|
|
255
260
|
|
|
256
261
|
//(<beforePublish_<%= objectType %>>)
|
|
@@ -36,7 +36,7 @@ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
|
36
36
|
/**
|
|
37
37
|
* Gets a range of objects by processing DynamoDB query
|
|
38
38
|
* @param {Object} _izContext - Context object with logger
|
|
39
|
-
* @param {Object} requestParams - { objectType, pk, sk, itemNum, additionalParams }
|
|
39
|
+
* @param {Object} requestParams - { objectType, identifierField, pk, startKey, sk, itemNumber, itemNum, additionalParams }
|
|
40
40
|
* @param {Object} callingFlowConfig - Calling flow configuration
|
|
41
41
|
* @returns {Promise<Object>} DynamoDB query result (Items, LastEvaluatedKey, etc.)
|
|
42
42
|
*/
|
|
@@ -63,22 +63,50 @@ export default async function <%- mainFileName %>(
|
|
|
63
63
|
const getDataDetails = await createGetDataDetails(_izContext, objectSchema);
|
|
64
64
|
_izContext.logger.debug('getDataDetails:', getDataDetails);
|
|
65
65
|
|
|
66
|
-
const {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
const {
|
|
67
|
+
identifierField,
|
|
68
|
+
pk,
|
|
69
|
+
startKey,
|
|
70
|
+
sk,
|
|
71
|
+
itemNumber,
|
|
72
|
+
itemNum
|
|
73
|
+
} = requestParams;
|
|
74
|
+
|
|
75
|
+
let partitionKeyValue = {};
|
|
76
|
+
if (
|
|
77
|
+
identifierField &&
|
|
78
|
+
typeof identifierField === 'object' &&
|
|
79
|
+
Object.keys(identifierField).length > 0
|
|
80
|
+
) {
|
|
81
|
+
partitionKeyValue = identifierField;
|
|
82
|
+
} else if (pk) {
|
|
83
|
+
const pkIdentifier = objectSchema.identifiers?.find(
|
|
84
|
+
(id) => id.type === 'partitionKey'
|
|
85
|
+
);
|
|
86
|
+
const pkName =
|
|
87
|
+
pkIdentifier?.fieldName ||
|
|
88
|
+
pkIdentifier?.name ||
|
|
89
|
+
'pk';
|
|
90
|
+
partitionKeyValue = { [pkName]: pk };
|
|
91
|
+
} else {
|
|
92
|
+
throw new Error('Partition key (identifierField or pk) is required for getRange');
|
|
70
93
|
}
|
|
71
94
|
|
|
72
95
|
const queryElements = {};
|
|
73
|
-
|
|
74
|
-
|
|
96
|
+
const limitVal = itemNumber || itemNum;
|
|
97
|
+
if (limitVal) {
|
|
98
|
+
queryElements.limit = parseInt(limitVal, 10);
|
|
75
99
|
}
|
|
76
100
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
const effectiveStartKey = startKey || sk;
|
|
102
|
+
if (effectiveStartKey) {
|
|
103
|
+
if (typeof effectiveStartKey === 'object') {
|
|
104
|
+
queryElements.exclusiveStartKey = effectiveStartKey;
|
|
80
105
|
} else {
|
|
81
|
-
queryElements.exclusiveStartKey = {
|
|
106
|
+
queryElements.exclusiveStartKey = {
|
|
107
|
+
...partitionKeyValue,
|
|
108
|
+
sk: effectiveStartKey
|
|
109
|
+
};
|
|
82
110
|
}
|
|
83
111
|
}
|
|
84
112
|
|
|
@@ -86,17 +114,22 @@ export default async function <%- mainFileName %>(
|
|
|
86
114
|
//(</beforeQuery>)
|
|
87
115
|
|
|
88
116
|
// ── Process storage resources (DynamoDB only for getRange) ────────────────
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
117
|
+
const queryResults = [];
|
|
118
|
+
|
|
119
|
+
for (const [, getDataDetail] of Object.entries(getDataDetails)) {
|
|
120
|
+
if (getDataDetail.storageType !== consts.STORAGE_TYPES.graph) {
|
|
121
|
+
const tableName = await dynamodbSharedLib.tableName(
|
|
122
|
+
_izContext,
|
|
123
|
+
getDataDetail.tableName,
|
|
124
|
+
getDataDetail.serviceTag
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
let queryPartitionKeyValue = partitionKeyValue;
|
|
128
|
+
if (
|
|
129
|
+
!identifierField ||
|
|
130
|
+
typeof identifierField !== 'object' ||
|
|
131
|
+
Object.keys(identifierField).length === 0
|
|
132
|
+
) {
|
|
100
133
|
const pkIdentifier = objectSchema.identifiers?.find(
|
|
101
134
|
(id) => id.type === 'partitionKey'
|
|
102
135
|
);
|
|
@@ -105,26 +138,67 @@ export default async function <%- mainFileName %>(
|
|
|
105
138
|
pkIdentifier?.fieldName ||
|
|
106
139
|
pkIdentifier?.name ||
|
|
107
140
|
'pk';
|
|
108
|
-
|
|
141
|
+
queryPartitionKeyValue = { [pkName]: pk };
|
|
142
|
+
}
|
|
109
143
|
|
|
110
|
-
|
|
111
|
-
|
|
144
|
+
//(<beforeGetRangeDynamoDb>)
|
|
145
|
+
//(</beforeGetRangeDynamoDb>)
|
|
112
146
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
147
|
+
const dataFromDynamoDb = await dynamodbSharedLib.query(
|
|
148
|
+
_izContext,
|
|
149
|
+
tableName,
|
|
150
|
+
queryPartitionKeyValue,
|
|
151
|
+
queryElements
|
|
152
|
+
);
|
|
153
|
+
_izContext.logger.debug('dataFromDynamoDb:', dataFromDynamoDb);
|
|
154
|
+
|
|
155
|
+
queryResults.push(dataFromDynamoDb);
|
|
120
156
|
|
|
121
|
-
|
|
157
|
+
//(<afterGetRangeDynamoDb>)
|
|
158
|
+
//(</afterGetRangeDynamoDb>)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let queryResult = null;
|
|
163
|
+
if (queryResults.length === 1) {
|
|
164
|
+
queryResult = queryResults[0];
|
|
165
|
+
} else if (queryResults.length > 1) {
|
|
166
|
+
const mergedItemsMap = new Map();
|
|
167
|
+
const sortKeyIdentifier = objectSchema.identifiers?.find(
|
|
168
|
+
(id) => id.type === 'sortKey'
|
|
169
|
+
);
|
|
170
|
+
const skField =
|
|
171
|
+
sortKeyIdentifier?.fieldName ||
|
|
172
|
+
sortKeyIdentifier?.name ||
|
|
173
|
+
'sk';
|
|
174
|
+
|
|
175
|
+
for (const res of queryResults) {
|
|
176
|
+
let items = [];
|
|
177
|
+
if (Array.isArray(res)) {
|
|
178
|
+
items = res;
|
|
179
|
+
} else if (res && res.Items) {
|
|
180
|
+
items = res.Items;
|
|
181
|
+
}
|
|
122
182
|
|
|
123
|
-
|
|
124
|
-
|
|
183
|
+
for (const item of items) {
|
|
184
|
+
let key = item[skField];
|
|
185
|
+
if (typeof key === 'undefined' || key === null) {
|
|
186
|
+
key = JSON.stringify(item);
|
|
187
|
+
}
|
|
188
|
+
if (mergedItemsMap.has(key)) {
|
|
189
|
+
mergedItemsMap.set(key, { ...mergedItemsMap.get(key), ...item });
|
|
190
|
+
} else {
|
|
191
|
+
mergedItemsMap.set(key, { ...item });
|
|
192
|
+
}
|
|
125
193
|
}
|
|
126
|
-
}
|
|
127
|
-
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
queryResult = {
|
|
197
|
+
Items: Array.from(mergedItemsMap.values()),
|
|
198
|
+
Count: mergedItemsMap.size,
|
|
199
|
+
queryResults: queryResults
|
|
200
|
+
};
|
|
201
|
+
}
|
|
128
202
|
|
|
129
203
|
return queryResult;
|
|
130
204
|
} catch (err) {
|
|
@@ -118,8 +118,10 @@ export default async function UpdateComplete(
|
|
|
118
118
|
}
|
|
119
119
|
: null;
|
|
120
120
|
if (status === 'complete') {
|
|
121
|
+
const listOfRecords =
|
|
122
|
+
result?.additionalAttributes?.listOfRecords ?? [];
|
|
121
123
|
await Promise.all(
|
|
122
|
-
(
|
|
124
|
+
(listOfRecords ?? []).flatMap((records) =>
|
|
123
125
|
Object.values(records).map(async (record) =>
|
|
124
126
|
dynamodbSharedLib.putItem(
|
|
125
127
|
_izContext,
|
|
@@ -137,9 +139,12 @@ export default async function UpdateComplete(
|
|
|
137
139
|
)
|
|
138
140
|
);
|
|
139
141
|
}
|
|
142
|
+
const callingFlowConfig =
|
|
143
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
144
|
+
passBackProperties;
|
|
140
145
|
const message =
|
|
141
146
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
142
|
-
|
|
147
|
+
callingFlowConfig,
|
|
143
148
|
{
|
|
144
149
|
objType: returnValue.requestParams.objType,
|
|
145
150
|
objInstanceFull: node.objInstanceFull,
|
|
@@ -152,7 +157,7 @@ export default async function UpdateComplete(
|
|
|
152
157
|
);
|
|
153
158
|
const messageAttributes =
|
|
154
159
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
155
|
-
|
|
160
|
+
callingFlowConfig,
|
|
156
161
|
{}
|
|
157
162
|
);
|
|
158
163
|
const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
|
|
@@ -137,7 +137,7 @@ export default async function <%- flowTag %>(
|
|
|
137
137
|
serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
|
|
138
138
|
},
|
|
139
139
|
requestParams: requestParams,
|
|
140
|
-
nextFlowStepName: '<%- flowTag %>
|
|
140
|
+
nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>'
|
|
141
141
|
}
|
|
142
142
|
);
|
|
143
143
|
|
|
@@ -246,7 +246,12 @@ export default async function <%- flowTag %>(
|
|
|
246
246
|
_izContext.uniqueRequestId,
|
|
247
247
|
'logical_<%= objectType %>'
|
|
248
248
|
),
|
|
249
|
-
awaitingMultipleStepIds
|
|
249
|
+
awaitingMultipleStepIds,
|
|
250
|
+
{
|
|
251
|
+
additionalAttributes: {
|
|
252
|
+
callingFlowConfig
|
|
253
|
+
}
|
|
254
|
+
}
|
|
250
255
|
);
|
|
251
256
|
|
|
252
257
|
//(<beforePublish_<%= objectType %>>)
|
|
@@ -287,7 +287,12 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
287
287
|
asyncFlowSharedLib.createPendingStepId(
|
|
288
288
|
_izContext.uniqueRequestId
|
|
289
289
|
),
|
|
290
|
-
awaitingStepIds
|
|
290
|
+
awaitingStepIds,
|
|
291
|
+
{
|
|
292
|
+
additionalAttributes: {
|
|
293
|
+
callingFlowConfig
|
|
294
|
+
}
|
|
295
|
+
}
|
|
291
296
|
);
|
|
292
297
|
_izContext.logger.debug(
|
|
293
298
|
'awaitingMultipleStep',
|
|
@@ -110,9 +110,14 @@ export default async function changeRelationshipComplete(
|
|
|
110
110
|
errorsFound: errorsFound
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
+
const callingFlowConfig =
|
|
114
|
+
pending?.additionalAttributes?.callingFlowConfig ||
|
|
115
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
116
|
+
passBackProperties;
|
|
117
|
+
|
|
113
118
|
changeRelCompleteMsg =
|
|
114
119
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
115
|
-
|
|
120
|
+
callingFlowConfig,
|
|
116
121
|
changeRelCompleteMsg
|
|
117
122
|
);
|
|
118
123
|
_izContext.logger.debug(
|
|
@@ -122,7 +127,7 @@ export default async function changeRelationshipComplete(
|
|
|
122
127
|
|
|
123
128
|
let messageAttributes =
|
|
124
129
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
125
|
-
|
|
130
|
+
callingFlowConfig,
|
|
126
131
|
{}
|
|
127
132
|
);
|
|
128
133
|
_izContext.logger.debug(
|
|
@@ -421,7 +421,11 @@ export default async function <%- functionName %>(
|
|
|
421
421
|
PREFIX.changeRel // prefix, use constant further
|
|
422
422
|
),
|
|
423
423
|
awaitingStepIds,
|
|
424
|
-
{
|
|
424
|
+
{
|
|
425
|
+
additionalAttributes: {
|
|
426
|
+
callingFlowConfig
|
|
427
|
+
}
|
|
428
|
+
}
|
|
425
429
|
);
|
|
426
430
|
|
|
427
431
|
// prepare message body
|
|
@@ -109,9 +109,14 @@ export default async function createRelationshipComplete(
|
|
|
109
109
|
errorsFound: errorsFound
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
+
const callingFlowConfig =
|
|
113
|
+
pending?.additionalAttributes?.callingFlowConfig ||
|
|
114
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
115
|
+
passBackProperties;
|
|
116
|
+
|
|
112
117
|
createCompleteMsg =
|
|
113
118
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
114
|
-
|
|
119
|
+
callingFlowConfig,
|
|
115
120
|
createCompleteMsg
|
|
116
121
|
);
|
|
117
122
|
_izContext.logger.debug(
|
|
@@ -121,7 +126,7 @@ export default async function createRelationshipComplete(
|
|
|
121
126
|
|
|
122
127
|
let messageAttributes =
|
|
123
128
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
124
|
-
|
|
129
|
+
callingFlowConfig,
|
|
125
130
|
{}
|
|
126
131
|
);
|
|
127
132
|
_izContext.logger.debug(
|
|
@@ -449,7 +449,11 @@ export default async function createRelationship(
|
|
|
449
449
|
PREFIX.createRel // prefix, use constant further
|
|
450
450
|
),
|
|
451
451
|
awaitingStepIds,
|
|
452
|
-
{
|
|
452
|
+
{
|
|
453
|
+
additionalAttributes: {
|
|
454
|
+
callingFlowConfig
|
|
455
|
+
}
|
|
456
|
+
}
|
|
453
457
|
);
|
|
454
458
|
|
|
455
459
|
// prepare message body
|
|
@@ -107,9 +107,14 @@ export default async function deleteRelationshipComplete(
|
|
|
107
107
|
errorsFound: errorsFound
|
|
108
108
|
};
|
|
109
109
|
|
|
110
|
+
const callingFlowConfig =
|
|
111
|
+
pending?.additionalAttributes?.callingFlowConfig ||
|
|
112
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
113
|
+
passBackProperties;
|
|
114
|
+
|
|
110
115
|
deleteRelComp =
|
|
111
116
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
112
|
-
|
|
117
|
+
callingFlowConfig,
|
|
113
118
|
deleteRelComp
|
|
114
119
|
);
|
|
115
120
|
_izContext.logger.debug(
|
|
@@ -119,7 +124,7 @@ export default async function deleteRelationshipComplete(
|
|
|
119
124
|
|
|
120
125
|
let messageAttributes =
|
|
121
126
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
122
|
-
|
|
127
|
+
callingFlowConfig,
|
|
123
128
|
{}
|
|
124
129
|
);
|
|
125
130
|
_izContext.logger.debug(
|
|
@@ -332,7 +332,11 @@ export default async function deleteRelationship(
|
|
|
332
332
|
PREFIX.deleteRel // prefix, use constant further
|
|
333
333
|
),
|
|
334
334
|
awaitingStepIds,
|
|
335
|
-
{
|
|
335
|
+
{
|
|
336
|
+
additionalAttributes: {
|
|
337
|
+
callingFlowConfig
|
|
338
|
+
}
|
|
339
|
+
}
|
|
336
340
|
);
|
|
337
341
|
|
|
338
342
|
// prepare message body
|
|
@@ -112,9 +112,14 @@ export default async function <%- functionName %>(
|
|
|
112
112
|
errorsFound: errorsFound
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
+
const callingFlowConfig =
|
|
116
|
+
pending?.additionalAttributes?.callingFlowConfig ||
|
|
117
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
118
|
+
passBackProperties;
|
|
119
|
+
|
|
115
120
|
moveRelCompleteMsg =
|
|
116
121
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
117
|
-
|
|
122
|
+
callingFlowConfig,
|
|
118
123
|
moveRelCompleteMsg
|
|
119
124
|
);
|
|
120
125
|
_izContext.logger.debug(
|
|
@@ -124,7 +129,7 @@ export default async function <%- functionName %>(
|
|
|
124
129
|
|
|
125
130
|
let messageAttributes =
|
|
126
131
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
127
|
-
|
|
132
|
+
callingFlowConfig,
|
|
128
133
|
{}
|
|
129
134
|
);
|
|
130
135
|
_izContext.logger.debug(
|
|
@@ -109,9 +109,14 @@ export default async function updateRelationshipComplete(
|
|
|
109
109
|
//(</inUpdateCompleteMsg>)
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
+
const callingFlowConfig =
|
|
113
|
+
pending?.additionalAttributes?.callingFlowConfig ||
|
|
114
|
+
result?.additionalAttributes?.callingFlowConfig ||
|
|
115
|
+
passBackProperties;
|
|
116
|
+
|
|
112
117
|
updateCompleteMsg =
|
|
113
118
|
callingFlowSharedLib.addParentPassBackPropertiesToSnsResponseMessageObject(
|
|
114
|
-
|
|
119
|
+
callingFlowConfig,
|
|
115
120
|
updateCompleteMsg
|
|
116
121
|
);
|
|
117
122
|
_izContext.logger.debug(
|
|
@@ -121,7 +126,7 @@ export default async function updateRelationshipComplete(
|
|
|
121
126
|
|
|
122
127
|
let messageAttributes =
|
|
123
128
|
callingFlowSharedLib.addParentPassBackCallingFlowToSnsResponseMessageAttributes(
|
|
124
|
-
|
|
129
|
+
callingFlowConfig,
|
|
125
130
|
{}
|
|
126
131
|
);
|
|
127
132
|
_izContext.logger.debug(
|
|
@@ -407,7 +407,11 @@ export default async function updateRelationship(
|
|
|
407
407
|
PREFIX.updateRel // prefix, use constant further
|
|
408
408
|
),
|
|
409
409
|
awaitingStepIds,
|
|
410
|
-
{
|
|
410
|
+
{
|
|
411
|
+
additionalAttributes: {
|
|
412
|
+
callingFlowConfig
|
|
413
|
+
}
|
|
414
|
+
}
|
|
411
415
|
);
|
|
412
416
|
|
|
413
417
|
// prepare message body
|
|
@@ -808,17 +808,18 @@ function collectTables(schemas) {
|
|
|
808
808
|
const identifiers = Array.isArray(schema.identifiers)
|
|
809
809
|
? schema.identifiers
|
|
810
810
|
: [];
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
identifier.type === 'partitionKey' ||
|
|
816
|
-
identifier.type === 'identifier'
|
|
817
|
-
)
|
|
818
|
-
) ?? 'PK';
|
|
819
|
-
const sk = keyName(
|
|
820
|
-
identifiers.find((identifier) => identifier.type === 'sortKey')
|
|
811
|
+
const pkIdentifier = identifiers.find(
|
|
812
|
+
(identifier) =>
|
|
813
|
+
identifier.type === 'partitionKey' ||
|
|
814
|
+
identifier.type === 'identifier'
|
|
821
815
|
);
|
|
816
|
+
const skIdentifier = identifiers.find(
|
|
817
|
+
(identifier) => identifier.type === 'sortKey'
|
|
818
|
+
);
|
|
819
|
+
const pk = keyName(pkIdentifier) ?? 'PK';
|
|
820
|
+
const sk = keyName(skIdentifier);
|
|
821
|
+
const pkType = keyAttributeType(pkIdentifier, schema);
|
|
822
|
+
const skType = keyAttributeType(skIdentifier, schema);
|
|
822
823
|
for (const resource of Object.values(schema.storageResources)) {
|
|
823
824
|
if (
|
|
824
825
|
(resource?.storageType === 'dynamo' ||
|
|
@@ -827,12 +828,66 @@ function collectTables(schemas) {
|
|
|
827
828
|
resource.tableName &&
|
|
828
829
|
!tables.has(resource.tableName)
|
|
829
830
|
)
|
|
830
|
-
tables.set(resource.tableName, { pk, sk });
|
|
831
|
+
tables.set(resource.tableName, { pk, sk, pkType, skType });
|
|
831
832
|
}
|
|
832
833
|
}
|
|
833
834
|
return tables;
|
|
834
835
|
}
|
|
835
836
|
|
|
837
|
+
function keyAttributeType(identifier, schema) {
|
|
838
|
+
if (!identifier) return 'S';
|
|
839
|
+
if (identifier.attributeType) {
|
|
840
|
+
return identifier.attributeType;
|
|
841
|
+
}
|
|
842
|
+
if (identifier.dataType) {
|
|
843
|
+
return mapTypeToAttributeType(identifier.dataType);
|
|
844
|
+
}
|
|
845
|
+
if (identifier.fieldType) {
|
|
846
|
+
return mapTypeToAttributeType(identifier.fieldType);
|
|
847
|
+
}
|
|
848
|
+
const fieldName = identifier.fieldName ?? identifier.name;
|
|
849
|
+
if (fieldName && schema) {
|
|
850
|
+
let fieldDef =
|
|
851
|
+
schema.fieldNames?.[fieldName] ?? schema.properties?.[fieldName];
|
|
852
|
+
if (!fieldDef && Array.isArray(schema.addOnDataStructure)) {
|
|
853
|
+
for (const addOn of schema.addOnDataStructure) {
|
|
854
|
+
if (addOn?.fieldNames?.[fieldName]) {
|
|
855
|
+
fieldDef = addOn.fieldNames[fieldName];
|
|
856
|
+
break;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
if (fieldDef?.attributeType) {
|
|
861
|
+
return fieldDef.attributeType;
|
|
862
|
+
}
|
|
863
|
+
const type = fieldDef?.type ?? fieldDef?.dataType;
|
|
864
|
+
if (type) {
|
|
865
|
+
return mapTypeToAttributeType(type);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
return 'S';
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
function mapTypeToAttributeType(type) {
|
|
872
|
+
if (typeof type !== 'string') return 'S';
|
|
873
|
+
const lower = type.toLowerCase();
|
|
874
|
+
if (
|
|
875
|
+
lower === 'number' ||
|
|
876
|
+
lower === 'numeric' ||
|
|
877
|
+
lower === 'integer' ||
|
|
878
|
+
lower === 'float' ||
|
|
879
|
+
lower === 'int' ||
|
|
880
|
+
lower === 'double' ||
|
|
881
|
+
lower === 'n'
|
|
882
|
+
) {
|
|
883
|
+
return 'N';
|
|
884
|
+
}
|
|
885
|
+
if (lower === 'binary' || lower === 'b') {
|
|
886
|
+
return 'B';
|
|
887
|
+
}
|
|
888
|
+
return 'S';
|
|
889
|
+
}
|
|
890
|
+
|
|
836
891
|
function keyName(identifier) {
|
|
837
892
|
if (!identifier) return null;
|
|
838
893
|
return (
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
BillingMode: PAY_PER_REQUEST
|
|
7
7
|
AttributeDefinitions:
|
|
8
8
|
- AttributeName: '<%- pk %>'
|
|
9
|
-
AttributeType: 'S'
|
|
9
|
+
AttributeType: '<%- pkType || 'S' %>'
|
|
10
10
|
<% if (sk) { %>
|
|
11
11
|
- AttributeName: '<%- sk %>'
|
|
12
|
-
AttributeType: 'S'
|
|
12
|
+
AttributeType: '<%- skType || 'S' %>'
|
|
13
13
|
<% } %>
|
|
14
14
|
KeySchema:
|
|
15
15
|
- AttributeName: '<%- pk %>'
|
|
@@ -18,6 +18,6 @@
|
|
|
18
18
|
- AttributeName: '<%- sk %>'
|
|
19
19
|
KeyType: 'RANGE'
|
|
20
20
|
<% } %>
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
#<#<%- tableName %>TableSetting#>
|
|
22
|
+
#<#/<%- tableName %>TableSetting#>
|
|
23
23
|
|
|
@@ -282,6 +282,17 @@ test('emits GetRangeHdrApi when an object defines a sortKey identifier', async (
|
|
|
282
282
|
);
|
|
283
283
|
assert.match(yaml, /GetRangeHdrApi:/);
|
|
284
284
|
assert.match(yaml, /path: \/orders\/order\/getRange/);
|
|
285
|
+
const getRangeMain = await readFile(
|
|
286
|
+
join(
|
|
287
|
+
rootPath,
|
|
288
|
+
'app/src/generatedCode/FlowObjects/Get/source/GetRange_Main.js'
|
|
289
|
+
),
|
|
290
|
+
'utf8'
|
|
291
|
+
);
|
|
292
|
+
assert.match(getRangeMain, /identifierField/);
|
|
293
|
+
assert.match(getRangeMain, /startKey/);
|
|
294
|
+
assert.match(getRangeMain, /itemNumber/);
|
|
295
|
+
assert.match(getRangeMain, /queryResults/);
|
|
285
296
|
});
|
|
286
297
|
|
|
287
298
|
test('removes managed CRUD artifacts when no applicable object remains', async () => {
|
|
@@ -914,9 +914,8 @@ test('renders RBAC Validator subscriptions in InitialSetupConfig when object has
|
|
|
914
914
|
);
|
|
915
915
|
assert.match(initialSetupConfigContent, /serviceTag: 'UserAccount'/);
|
|
916
916
|
assert.match(initialSetupConfigContent, /topicName: 'ValidatorRbac_Out'/);
|
|
917
|
-
assert.match(initialSetupConfigContent, /sqsEndpoint: '
|
|
918
|
-
assert.match(initialSetupConfigContent, /sqsEndpoint: '
|
|
919
|
-
assert.match(initialSetupConfigContent, /sqsEndpoint: 'DeleteCompleteHdrSqs'/);
|
|
917
|
+
assert.match(initialSetupConfigContent, /sqsEndpoint: 'UpdateRbacCallbackHdrSqs'/);
|
|
918
|
+
assert.match(initialSetupConfigContent, /sqsEndpoint: 'DeleteRbacCallbackHdrSqs'/);
|
|
920
919
|
});
|
|
921
920
|
|
|
922
921
|
test('deduplicates duplicate nextSteps topics across flowSteps in InitialSetupConfig', async () => {
|
|
@@ -1111,3 +1110,60 @@ test('renders multi-type array for mixed property and messageAttribute type in h
|
|
|
1111
1110
|
/Value:\s*\{\s*type:\s*\['string',\s*'number',\s*'integer',\s*'boolean',\s*'null',\s*'object',\s*'array'\]/
|
|
1112
1111
|
);
|
|
1113
1112
|
});
|
|
1113
|
+
|
|
1114
|
+
test('renders previousSteps extTopic subscriptions in InitialSetupConfig', async () => {
|
|
1115
|
+
const rootPath = await mkdtemp(
|
|
1116
|
+
join(tmpdir(), 'generate-service-code-v2-prevsteps-')
|
|
1117
|
+
);
|
|
1118
|
+
roots.add(rootPath);
|
|
1119
|
+
const schemas = join(rootPath, 'app/src/schemas/FlowSchemas');
|
|
1120
|
+
await mkdir(schemas, { recursive: true });
|
|
1121
|
+
await writeFile(
|
|
1122
|
+
join(schemas, 'Order.js'),
|
|
1123
|
+
`export default [
|
|
1124
|
+
{
|
|
1125
|
+
flowTag: 'order',
|
|
1126
|
+
event: ['ownTopic'],
|
|
1127
|
+
flowSteps: [
|
|
1128
|
+
{
|
|
1129
|
+
stepName: 'Start'
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
stepName: 'BuildOrderSellOfferLinkAndReserveOrderData',
|
|
1133
|
+
properties: ['returnValue', 'parentFlowId', 'status'],
|
|
1134
|
+
messageAttributes: [],
|
|
1135
|
+
event: ['extTopic'],
|
|
1136
|
+
previousSteps: [
|
|
1137
|
+
{
|
|
1138
|
+
sourceType: 'extTopic',
|
|
1139
|
+
serviceTag: 'GraphHandler',
|
|
1140
|
+
topicName: 'CreateNode_Out',
|
|
1141
|
+
fromStepNames: ['start']
|
|
1142
|
+
}
|
|
1143
|
+
]
|
|
1144
|
+
}
|
|
1145
|
+
]
|
|
1146
|
+
}
|
|
1147
|
+
];\n`
|
|
1148
|
+
);
|
|
1149
|
+
|
|
1150
|
+
const result = await generate(rootPath, {
|
|
1151
|
+
serviceTag: 'Order'
|
|
1152
|
+
});
|
|
1153
|
+
assert.ok(result);
|
|
1154
|
+
|
|
1155
|
+
const initialSetupConfigContent = await readFile(
|
|
1156
|
+
join(
|
|
1157
|
+
rootPath,
|
|
1158
|
+
'app/src/generatedCode/CoreFunctions/InitialSetupConfig.js'
|
|
1159
|
+
),
|
|
1160
|
+
'utf8'
|
|
1161
|
+
);
|
|
1162
|
+
|
|
1163
|
+
assert.match(initialSetupConfigContent, /serviceTag: 'GraphHandler'/);
|
|
1164
|
+
assert.match(initialSetupConfigContent, /topicName: 'CreateNode_Out'/);
|
|
1165
|
+
assert.match(
|
|
1166
|
+
initialSetupConfigContent,
|
|
1167
|
+
/sqsEndpoint: 'OrderBuildOrderSellOfferLinkAndReserveOrderDataHdrSqs'/
|
|
1168
|
+
);
|
|
1169
|
+
});
|
|
@@ -244,6 +244,47 @@ test('emits DynamoDB tables and hooks defined in flowSchemas storageResources',
|
|
|
244
244
|
assert.match(dynamoYaml, /#<#\/FlowCustomTableTableSetting#>/);
|
|
245
245
|
});
|
|
246
246
|
|
|
247
|
+
test('emits DynamoDB table with number sortKey attribute type when field type is number', async () => {
|
|
248
|
+
const rootPath = await createProject();
|
|
249
|
+
await writeFile(
|
|
250
|
+
join(rootPath, 'app/src/schemas/ObjectSchemas/CartOrder.js'),
|
|
251
|
+
"export default { " +
|
|
252
|
+
"objectType: 'cartOrder', " +
|
|
253
|
+
"generatedBy: 'userGenerated', " +
|
|
254
|
+
"fieldNames: { " +
|
|
255
|
+
" cartId: { type: 'string' }, " +
|
|
256
|
+
" sortId: { type: 'number' } " +
|
|
257
|
+
"}, " +
|
|
258
|
+
"identifiers: [ " +
|
|
259
|
+
" { type: 'partitionKey', fieldName: 'cartId' }, " +
|
|
260
|
+
" { type: 'sortKey', fieldName: 'sortId' } " +
|
|
261
|
+
"], " +
|
|
262
|
+
"storageResources: { " +
|
|
263
|
+
" main: { storageType: 'dynamoDB', tableName: 'CartOrders' } " +
|
|
264
|
+
"} " +
|
|
265
|
+
"};\n"
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
await generateResourceArtifacts(rootPath);
|
|
269
|
+
|
|
270
|
+
const dynamoYaml = await readFile(
|
|
271
|
+
join(
|
|
272
|
+
rootPath,
|
|
273
|
+
'resource/sls_yaml/generatedCode/source/generated-dynamoDB-table.yml'
|
|
274
|
+
),
|
|
275
|
+
'utf8'
|
|
276
|
+
);
|
|
277
|
+
assert.match(dynamoYaml, /CartOrdersTable:/);
|
|
278
|
+
assert.match(
|
|
279
|
+
dynamoYaml,
|
|
280
|
+
/AttributeName:\s*'cartId'[\s\S]*?AttributeType:\s*'S'/
|
|
281
|
+
);
|
|
282
|
+
assert.match(
|
|
283
|
+
dynamoYaml,
|
|
284
|
+
/AttributeName:\s*'sortId'[\s\S]*?AttributeType:\s*'N'/
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
|
|
247
288
|
test('emits IAM role for generated DSQ flows in generate-shared-resource.yml', async () => {
|
|
248
289
|
const rootPath = await createProject();
|
|
249
290
|
const schemas = join(rootPath, 'app/src/schemas');
|