@izara_project/izara-core-generate-service-code 1.0.99 → 1.0.100
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/compileProject.js +16 -5
- package/src/compile/flowValidator.js +3 -1
- package/src/compile/loadSchemas.js +18 -4
- package/src/compile/schemaValidatorSetup.js +16 -0
- package/src/emit/application/coreFunction/emitCoreFunctionArtifacts.js +108 -108
- package/src/emit/application/coreFunction/templates/InitialSetupRunner.ejs +2 -2
- package/src/emit/application/crud/templates/CreateComplete_Main.ejs +2 -0
- package/src/emit/application/crud/templates/CreateLogicalLib.ejs +14 -7
- package/src/emit/application/crud/templates/DeleteComplete_Main.ejs +2 -0
- package/src/emit/application/crud/templates/FlowEndpoint_HdrWbs.ejs +7 -5
- package/src/emit/application/crud/templates/UpdateComplete_Main.ejs +2 -0
- package/src/emit/application/custom/customFlowPaths.js +13 -16
- package/src/emit/application/custom/customFlowS3.js +274 -63
- package/src/emit/application/custom/customFlows.js +131 -0
- package/src/emit/application/custom/emitCustomFlowApplicationArtifacts.js +3 -1
- package/src/emit/application/custom/templates/s3/ConfirmAfterUpload_HdrSqs.ejs +110 -0
- package/src/emit/application/custom/templates/s3/ConfirmAfterUpload_Main.ejs +89 -0
- package/src/emit/application/custom/templates/s3/ConfirmComplete_HdrSqs.ejs +110 -0
- package/src/emit/application/custom/templates/s3/ConfirmComplete_Main.ejs +89 -0
- package/src/emit/application/custom/templates/s3/CreateObject_HdrWbs.ejs +2 -1
- package/src/emit/application/custom/templates/s3/CreateObject_Main.ejs +4 -0
- package/src/emit/application/custom/templates/s3/CreatePreSignUrl_HdrSqs.ejs +42 -0
- package/src/emit/application/custom/templates/s3/CreatePreSignUrl_Main.ejs +23 -0
- package/src/emit/application/custom/templates/s3/ProcessS3File_Main.ejs +135 -27
- package/src/emit/application/custom/templates/s3/Start_Main.ejs +197 -0
- package/src/emit/application/rbac/emitDynamicRbacFlowSchemas.js +5 -1
- package/src/emit/application/rbac/emitRbacApplicationArtifacts.js +67 -60
- package/src/emit/application/rbac/templates/ReservedDynamicUsage_Main.ejs +27 -9
- package/src/emit/application/rbac/templates/UserRbacFlow_Main.ejs +4 -3
- package/src/emit/application/system/templates/Register_HdrWbs.ejs +2 -1
- package/src/emit/infrastructure/functions/functionYamlArtifact.js +3 -8
- package/src/emit/infrastructure/functions/templates/S3Function_Yaml.ejs +2 -3
- package/src/emit/infrastructure/resources/iamResourceArtifacts.js +22 -0
- package/src/emit/infrastructure/resources/resourceState.js +15 -5
- package/src/emit/infrastructure/resources/s3ResourceArtifacts.js +19 -3
- package/src/emit/infrastructure/resources/templates/S3Bucket_Yaml.ejs +1 -1
- package/src/emit/infrastructure/resources/templates/SystemDynamoDB_Yaml.ejs +2 -2
- package/src/emit/schemas/error/emitErrorSchemas.js +120 -10
- package/src/emit/schemas/error/templates/errorConsts.ejs +12 -0
- package/src/generate.js +32 -30
- package/test/integration/publicApi.test.js +33 -24
- package/test/unit/application/createTargetRoleHandler.test.js +33 -10
- package/test/unit/application/customFlowApplicationArtifacts.test.js +6 -6
- package/test/unit/application/customFlowS3.test.js +730 -0
- package/test/unit/infrastructure/functionYamlArtifact.test.js +6 -4
- package/test/unit/infrastructure/resourceArtifacts.test.js +51 -0
- package/test/unit/schemas/dynamicRbacFlowSchemas.test.js +8 -6
- package/test/unit/schemas/dynamicRelationshipFlowSchemas.test.js +51 -0
- package/test/unit/schemas/errorSchemas.test.js +84 -5
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2026 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 <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
19
|
+
import { webSocket } from '@izara_project/izara-core-library-external-request';
|
|
20
|
+
const { postToConnection } = webSocket;
|
|
21
|
+
import { utils } from '@izara_project/izara-core-library-service-schemas';
|
|
22
|
+
const { createFlowTypeConcat } = utils;
|
|
23
|
+
|
|
24
|
+
//(<optionalRequired>)
|
|
25
|
+
//(</optionalRequired>)
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Step 3: ConfirmAfterUpload (Deferred-Node S3 Pipeline - ADR-016)
|
|
29
|
+
* SQS handler receiving objInstanceFull from OutCreate SNS topic.
|
|
30
|
+
* Confirms storage quota, queries WebSocketTask, and notifies client via WebSocket.
|
|
31
|
+
*
|
|
32
|
+
* @param {Object} _izContext
|
|
33
|
+
* @param {Object} objType
|
|
34
|
+
* @param {Object} objInstanceFull
|
|
35
|
+
* @param {Object} passBackProperties
|
|
36
|
+
* @returns {Promise<Object>}
|
|
37
|
+
*/
|
|
38
|
+
export default async function <%- functionName %>(
|
|
39
|
+
_izContext,
|
|
40
|
+
objType,
|
|
41
|
+
objInstanceFull,
|
|
42
|
+
//(<additionalProperties>)
|
|
43
|
+
//(</additionalProperties>)
|
|
44
|
+
passBackProperties = {}
|
|
45
|
+
) {
|
|
46
|
+
try {
|
|
47
|
+
_izContext.logger.debug('----- <%- functionName %> started -----', {
|
|
48
|
+
objType,
|
|
49
|
+
objInstanceFull,
|
|
50
|
+
passBackProperties
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const targetId =
|
|
54
|
+
objInstanceFull.identifiers?.<%- objectType %>Id ||
|
|
55
|
+
Object.values(objInstanceFull.identifiers || {})[0];
|
|
56
|
+
|
|
57
|
+
//(<confirmUsageHook>)
|
|
58
|
+
//(</confirmUsageHook>)
|
|
59
|
+
|
|
60
|
+
const taskKey = `${createFlowTypeConcat(_izContext, { flowTag: '<%- flowTag %>', serviceTag: process.env.iz_serviceTag })}${targetId}`;
|
|
61
|
+
const taskRecord = await dynamodbSharedLib.getItem(
|
|
62
|
+
_izContext,
|
|
63
|
+
await dynamodbSharedLib.tableName(_izContext, 'WebSocketTask'),
|
|
64
|
+
{ taskKey: taskKey }
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if (taskRecord && taskRecord.connectionId) {
|
|
68
|
+
await postToConnection(
|
|
69
|
+
_izContext,
|
|
70
|
+
{
|
|
71
|
+
status: 'completed',
|
|
72
|
+
data: {
|
|
73
|
+
<%- objectType %>Id: targetId,
|
|
74
|
+
objInstanceFull: objInstanceFull
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
taskRecord.connectionId
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
status: 'completed',
|
|
83
|
+
objInstanceFull: objInstanceFull
|
|
84
|
+
};
|
|
85
|
+
} catch (err) {
|
|
86
|
+
_izContext.logger.error('Error in <%- functionName %>: ', err);
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2026 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 <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { middlewareHandler as middleware } from '@izara_project/izara-middleware';
|
|
19
|
+
import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
|
|
20
|
+
import Logger from '@izara_project/izara-core-library-logger';
|
|
21
|
+
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
22
|
+
|
|
23
|
+
import <%= functionName %> from './<%= functionName %>_Main.js';
|
|
24
|
+
|
|
25
|
+
middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
|
|
26
|
+
|
|
27
|
+
let perRecordsValidatorSchema = {
|
|
28
|
+
type: 'object',
|
|
29
|
+
required: ['objType', 'objInstanceFull'],
|
|
30
|
+
properties: {
|
|
31
|
+
objType: {
|
|
32
|
+
type: 'object',
|
|
33
|
+
required: ['objectType', 'serviceTag'],
|
|
34
|
+
properties: {
|
|
35
|
+
objectType: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
pattern: '^[a-zA-Z0-9_-]+$'
|
|
38
|
+
},
|
|
39
|
+
serviceTag: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
pattern: '^[a-zA-Z0-9_-]+$'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
objInstanceFull: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
identifiers: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
minProperties: 1
|
|
51
|
+
},
|
|
52
|
+
fields: {
|
|
53
|
+
type: 'object'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
perRecordsValidatorSchema =
|
|
61
|
+
callingFlowSharedLib.addOptionalPassBackPropertiesToValidatorSchema(
|
|
62
|
+
perRecordsValidatorSchema
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
export const main = middleware.wrap(async (event, context) => {
|
|
66
|
+
try {
|
|
67
|
+
let recordPromises = [];
|
|
68
|
+
|
|
69
|
+
await Promise.all(
|
|
70
|
+
event.Records.map(async (record) => {
|
|
71
|
+
let passOnProperties = [];
|
|
72
|
+
record._izContext.logger.debug('record <%= functionName %><%= handlerType %>', record);
|
|
73
|
+
|
|
74
|
+
await recordHandlerSharedLib.validateRecord(
|
|
75
|
+
record,
|
|
76
|
+
'<%= functionName %><%= handlerType %>',
|
|
77
|
+
perRecordsValidatorSchema
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
passOnProperties.push(record.body.Message.objType);
|
|
81
|
+
passOnProperties.push(record.body.Message.objInstanceFull);
|
|
82
|
+
//(<additionalProperties>)
|
|
83
|
+
//(</additionalProperties>)
|
|
84
|
+
passOnProperties.push(
|
|
85
|
+
callingFlowSharedLib.addPassBackPropertiesToPassOnProperties(
|
|
86
|
+
record.body.Message
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
record._izContext.logger.debug(
|
|
91
|
+
'passOnProperties in <%= functionName %><%= handlerType %>',
|
|
92
|
+
passOnProperties
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
let returnPromise = await recordHandlerSharedLib.recordHandler(
|
|
96
|
+
record,
|
|
97
|
+
<%= functionName %>,
|
|
98
|
+
passOnProperties
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
recordPromises.push(returnPromise);
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
return await Promise.all(recordPromises);
|
|
106
|
+
} catch (err) {
|
|
107
|
+
Logger.error('Error <%= functionName %><%= handlerType %>: ', err);
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2026 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 <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
19
|
+
import { webSocket } from '@izara_project/izara-core-library-external-request';
|
|
20
|
+
const { postToConnection } = webSocket;
|
|
21
|
+
import { utils } from '@izara_project/izara-core-library-service-schemas';
|
|
22
|
+
const { createFlowTypeConcat } = utils;
|
|
23
|
+
|
|
24
|
+
//(<optionalRequired>)
|
|
25
|
+
//(</optionalRequired>)
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Step 3: ConfirmComplete (Deferred-Node S3 Pipeline - ADR-016)
|
|
29
|
+
* SQS handler receiving objInstanceFull from OutCreate SNS topic.
|
|
30
|
+
* Confirms storage quota, queries WebSocketTask, and notifies client via WebSocket.
|
|
31
|
+
*
|
|
32
|
+
* @param {Object} _izContext
|
|
33
|
+
* @param {Object} objType
|
|
34
|
+
* @param {Object} objInstanceFull
|
|
35
|
+
* @param {Object} passBackProperties
|
|
36
|
+
* @returns {Promise<Object>}
|
|
37
|
+
*/
|
|
38
|
+
export default async function <%- functionName %>(
|
|
39
|
+
_izContext,
|
|
40
|
+
objType,
|
|
41
|
+
objInstanceFull,
|
|
42
|
+
//(<additionalProperties>)
|
|
43
|
+
//(</additionalProperties>)
|
|
44
|
+
passBackProperties = {}
|
|
45
|
+
) {
|
|
46
|
+
try {
|
|
47
|
+
_izContext.logger.debug('----- <%- functionName %> started -----', {
|
|
48
|
+
objType,
|
|
49
|
+
objInstanceFull,
|
|
50
|
+
passBackProperties
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const targetId =
|
|
54
|
+
objInstanceFull.identifiers?.<%- objectType %>Id ||
|
|
55
|
+
Object.values(objInstanceFull.identifiers || {})[0];
|
|
56
|
+
|
|
57
|
+
//(<confirmUsageHook>)
|
|
58
|
+
//(</confirmUsageHook>)
|
|
59
|
+
|
|
60
|
+
const taskKey = `${createFlowTypeConcat(_izContext, { flowTag: '<%- flowTag %>', serviceTag: process.env.iz_serviceTag })}${targetId}`;
|
|
61
|
+
const taskRecord = await dynamodbSharedLib.getItem(
|
|
62
|
+
_izContext,
|
|
63
|
+
await dynamodbSharedLib.tableName(_izContext, 'WebSocketTask'),
|
|
64
|
+
{ taskKey: taskKey }
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if (taskRecord && taskRecord.connectionId) {
|
|
68
|
+
await postToConnection(
|
|
69
|
+
_izContext,
|
|
70
|
+
{
|
|
71
|
+
status: 'completed',
|
|
72
|
+
data: {
|
|
73
|
+
<%- objectType %>Id: targetId,
|
|
74
|
+
objInstanceFull: objInstanceFull
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
taskRecord.connectionId
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
status: 'completed',
|
|
83
|
+
objInstanceFull: objInstanceFull
|
|
84
|
+
};
|
|
85
|
+
} catch (err) {
|
|
86
|
+
_izContext.logger.error('Error in <%- functionName %>: ', err);
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -57,7 +57,8 @@ export const main = middleware.wrap(async (event, context) => {
|
|
|
57
57
|
),
|
|
58
58
|
{
|
|
59
59
|
taskKey: `${createFlowTypeConcat(event._izContext, { flowTag: '<%- route %>', serviceTag: process.env.iz_serviceTag })}${identifiers}`,
|
|
60
|
-
connectionId: connectionId
|
|
60
|
+
connectionId: connectionId,
|
|
61
|
+
expirationTime: Math.floor(Date.now() / 1000) + 7200
|
|
61
62
|
}
|
|
62
63
|
);
|
|
63
64
|
|
|
@@ -127,7 +127,11 @@ export default async function createObject(
|
|
|
127
127
|
callingFlowSharedLib.createCallingFlowConfig(
|
|
128
128
|
await lambdaSharedLib.lambdaFunctionName(
|
|
129
129
|
_izContext,
|
|
130
|
+
<% if (typeof nextStepFunctionName === 'string' && nextStepFunctionName) { -%>
|
|
131
|
+
'<%- nextStepFunctionName %>'
|
|
132
|
+
<% } else { -%>
|
|
130
133
|
TOPIC_NAME_GENERATE_CODE.createNodeComplete
|
|
134
|
+
<% } -%>
|
|
131
135
|
),
|
|
132
136
|
{}
|
|
133
137
|
)
|
|
@@ -26,6 +26,40 @@ import <%= functionName %> from './<%= functionName %>_Main.js';
|
|
|
26
26
|
middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
|
|
27
27
|
|
|
28
28
|
// set schema for record.body.Message
|
|
29
|
+
<% if (isSimplifiedS3) { -%>
|
|
30
|
+
let perRecordsValidatorSchema = {
|
|
31
|
+
type: 'object',
|
|
32
|
+
required: ['objType', 'objInstanceFull'],
|
|
33
|
+
properties: {
|
|
34
|
+
objType: {
|
|
35
|
+
type: 'object',
|
|
36
|
+
required: ['objectType', 'serviceTag'],
|
|
37
|
+
properties: {
|
|
38
|
+
objectType: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
pattern: '^[a-zA-Z0-9_-]+$'
|
|
41
|
+
},
|
|
42
|
+
serviceTag: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
pattern: '^[a-zA-Z0-9_-]+$'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
objInstanceFull: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
identifiers: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
minProperties: 1
|
|
54
|
+
},
|
|
55
|
+
fields: {
|
|
56
|
+
type: 'object'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
<% } else { -%>
|
|
29
63
|
let perRecordsValidatorSchema = {
|
|
30
64
|
type: 'object',
|
|
31
65
|
required: ['returnMessage', 'foundErrors', 'passStatus'],
|
|
@@ -41,6 +75,7 @@ let perRecordsValidatorSchema = {
|
|
|
41
75
|
}
|
|
42
76
|
}
|
|
43
77
|
};
|
|
78
|
+
<% } -%>
|
|
44
79
|
|
|
45
80
|
// set schema for record.body.MessageAttributes
|
|
46
81
|
// const messageAttributeValidatorSchema = {
|
|
@@ -82,9 +117,16 @@ export const main = middleware.wrap(async (event, context) => {
|
|
|
82
117
|
);
|
|
83
118
|
|
|
84
119
|
// add argument (to invoke lambda) to passOnProperties[]
|
|
120
|
+
<% if (isSimplifiedS3) { -%>
|
|
121
|
+
passOnProperties.push(record.body.Message.objType);
|
|
122
|
+
passOnProperties.push(record.body.Message.objInstanceFull);
|
|
123
|
+
passOnProperties.push(record.body.Message.status || 'complete');
|
|
124
|
+
passOnProperties.push(record.body.Message.foundErrors || []);
|
|
125
|
+
<% } else { -%>
|
|
85
126
|
passOnProperties.push(record.body.Message.returnMessage);
|
|
86
127
|
passOnProperties.push(record.body.Message.foundErrors);
|
|
87
128
|
passOnProperties.push(record.body.Message.passStatus);
|
|
129
|
+
<% } -%>
|
|
88
130
|
//(<additionalProperties>)
|
|
89
131
|
//(</additionalProperties>)
|
|
90
132
|
passOnProperties.push(
|
|
@@ -60,14 +60,30 @@ const { createFlowTypeConcat } = utils;
|
|
|
60
60
|
|
|
61
61
|
export default async function createPreSignUrl(
|
|
62
62
|
_izContext,
|
|
63
|
+
<% if (isSimplifiedS3) { -%>
|
|
64
|
+
objType,
|
|
65
|
+
objInstanceFull,
|
|
66
|
+
status = 'complete',
|
|
67
|
+
foundErrors = [],
|
|
68
|
+
<% } else { -%>
|
|
63
69
|
returnMessage,
|
|
64
70
|
foundErrors,
|
|
65
71
|
passStatus,
|
|
72
|
+
<% } -%>
|
|
66
73
|
//(<additionalProperties>)
|
|
67
74
|
//(</additionalProperties>)
|
|
68
75
|
passBackProperties = {}
|
|
69
76
|
) {
|
|
70
77
|
try {
|
|
78
|
+
<% if (isSimplifiedS3) { -%>
|
|
79
|
+
_izContext.logger.debug('----- createPreSignUrl event params -----', {
|
|
80
|
+
objType: objType,
|
|
81
|
+
objInstanceFull: objInstanceFull,
|
|
82
|
+
status: status,
|
|
83
|
+
foundErrors: foundErrors,
|
|
84
|
+
passBackProperties: passBackProperties
|
|
85
|
+
});
|
|
86
|
+
<% } else { -%>
|
|
71
87
|
_izContext.logger.debug('----- createPreSignUrl event params -----', {
|
|
72
88
|
returnMessage: returnMessage,
|
|
73
89
|
foundErrors: foundErrors,
|
|
@@ -80,6 +96,7 @@ export default async function createPreSignUrl(
|
|
|
80
96
|
const reservedDataId =
|
|
81
97
|
passBackProperties.passBackProperties.identifier.reservedDataId;
|
|
82
98
|
const objType = passBackProperties.passBackProperties.objType;
|
|
99
|
+
<% } -%>
|
|
83
100
|
|
|
84
101
|
const correlationId = _izContext.correlationIds.get(
|
|
85
102
|
consts.X_CORRELATION_ID
|
|
@@ -100,6 +117,7 @@ export default async function createPreSignUrl(
|
|
|
100
117
|
//(<afterGetResult>)
|
|
101
118
|
//(</afterGetResult>)
|
|
102
119
|
|
|
120
|
+
<% if (!isSimplifiedS3) { -%>
|
|
103
121
|
let uniqueIdentify = getNestObject(_izContext, returnMessage, [
|
|
104
122
|
'limitFound',
|
|
105
123
|
'runningTotal',
|
|
@@ -194,6 +212,7 @@ export default async function createPreSignUrl(
|
|
|
194
212
|
|
|
195
213
|
return 'reserved not pass';
|
|
196
214
|
}
|
|
215
|
+
<% } -%>
|
|
197
216
|
|
|
198
217
|
//(<createKeyForUploadFile>)
|
|
199
218
|
const Key = `${fileName}.${importType}`;
|
|
@@ -250,7 +269,11 @@ export default async function createPreSignUrl(
|
|
|
250
269
|
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
251
270
|
messageObject,
|
|
252
271
|
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
272
|
+
<% if (isSimplifiedS3) { -%>
|
|
273
|
+
passBackProperties,
|
|
274
|
+
<% } else { -%>
|
|
253
275
|
returnMessage, // resive parent callingFlowConfig.
|
|
276
|
+
<% } -%>
|
|
254
277
|
callingFlowSharedLib.createCallingFlowConfig(
|
|
255
278
|
// calling flow own service
|
|
256
279
|
await lambdaSharedLib.lambdaFunctionName(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright (C)
|
|
2
|
+
Copyright (C) 2026 Sven Mason <http://izara.io>
|
|
3
3
|
|
|
4
4
|
This program is free software: you can redistribute it and/or modify
|
|
5
5
|
it under the terms of the GNU Affero General Public License as
|
|
@@ -8,42 +8,40 @@ License, or (at your option) any later version.
|
|
|
8
8
|
|
|
9
9
|
This program is distributed in the hope that it will be useful,
|
|
10
10
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
12
|
GNU Affero General Public License for more details.
|
|
13
13
|
|
|
14
14
|
You should have received a copy of the GNU Affero General Public License
|
|
15
|
-
along with this program.
|
|
15
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import {
|
|
19
19
|
S3Client,
|
|
20
20
|
GetObjectCommand,
|
|
21
|
-
|
|
22
|
-
PutObjectCommand,
|
|
23
|
-
CopyObjectCommand
|
|
21
|
+
HeadObjectCommand
|
|
24
22
|
} from '@aws-sdk/client-s3';
|
|
25
23
|
const s3 = new S3Client({ region: process.env.AWS_REGION });
|
|
26
24
|
|
|
25
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
26
|
+
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
27
|
+
import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
|
|
28
|
+
import { sns } from '@izara_project/izara-core-library-external-request';
|
|
29
|
+
|
|
27
30
|
//(<optionalRequired>)
|
|
28
31
|
//(</optionalRequired>)
|
|
29
32
|
|
|
30
33
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* @param {Logger} _izContext.logger - property of _izContext
|
|
35
|
-
* @param {Logger} _izContext.logger.debug - property of _izContext
|
|
36
|
-
* @param {Object} bucket - bucket's data
|
|
37
|
-
* @param {Array} field - image's data
|
|
38
|
-
* @param {Array} importBy - 'webSocket' || 'importData'
|
|
39
|
-
* @param {Array} imageImportId - from importData
|
|
40
|
-
* @param {Array} realImageSize - from importData
|
|
41
|
-
* @param {Array} passBackProperties - from importData
|
|
34
|
+
* Step 2: ProcessAfterUpload (Deferred-Node S3 Pipeline - ADR-016)
|
|
35
|
+
* Triggered by S3 ObjectCreated event. Inspects file, prepares entity payload,
|
|
36
|
+
* and publishes to Create_In SNS topic with callingFlow targeting ConfirmAfterUpload.
|
|
42
37
|
*
|
|
43
|
-
* @
|
|
38
|
+
* @param {Object} _izContext
|
|
39
|
+
* @param {Object} bucket - S3 bucket record
|
|
40
|
+
* @param {Object} field - S3 object record ({ key, size, eTag })
|
|
41
|
+
* @param {Object} passBackProperties
|
|
42
|
+
* @returns {Promise<Object>}
|
|
44
43
|
*/
|
|
45
|
-
|
|
46
|
-
export default async function processAfterUpload(
|
|
44
|
+
export default async function <%- functionName %>(
|
|
47
45
|
_izContext,
|
|
48
46
|
bucket,
|
|
49
47
|
field,
|
|
@@ -52,18 +50,128 @@ export default async function processAfterUpload(
|
|
|
52
50
|
passBackProperties = {}
|
|
53
51
|
) {
|
|
54
52
|
try {
|
|
55
|
-
_izContext.logger.debug('-----
|
|
56
|
-
bucket
|
|
57
|
-
field
|
|
58
|
-
|
|
59
|
-
//(</loggerAdditionalParams>)
|
|
60
|
-
passBackProperties: passBackProperties
|
|
53
|
+
_izContext.logger.debug('----- <%- functionName %> started -----', {
|
|
54
|
+
bucket,
|
|
55
|
+
field,
|
|
56
|
+
passBackProperties
|
|
61
57
|
});
|
|
62
58
|
|
|
59
|
+
const s3Key = field.key;
|
|
60
|
+
const actualByteSize = field.size;
|
|
61
|
+
const actualSizeMb = actualByteSize / (1024 * 1024);
|
|
62
|
+
|
|
63
|
+
let s3Metadata = {};
|
|
64
|
+
try {
|
|
65
|
+
const headResult = await s3.send(
|
|
66
|
+
new HeadObjectCommand({
|
|
67
|
+
Bucket: bucket.name,
|
|
68
|
+
Key: s3Key
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
s3Metadata = headResult.Metadata || {};
|
|
72
|
+
} catch (headErr) {
|
|
73
|
+
_izContext.logger.warn('Could not retrieve S3 object metadata via HeadObjectCommand:', {
|
|
74
|
+
bucket: bucket.name,
|
|
75
|
+
key: s3Key,
|
|
76
|
+
error: headErr.message
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//(<extractIdentifiersFromKeyOrMetadata>)
|
|
81
|
+
const keyParts = s3Key.split('/');
|
|
82
|
+
let fileNameWithExt = '';
|
|
83
|
+
if (keyParts.length > 0) {
|
|
84
|
+
fileNameWithExt = keyParts[keyParts.length - 1];
|
|
85
|
+
}
|
|
86
|
+
const rawId = fileNameWithExt.split('.')[0];
|
|
87
|
+
let parentId = '';
|
|
88
|
+
if (keyParts.length > 2) {
|
|
89
|
+
parentId = keyParts[keyParts.length - 2];
|
|
90
|
+
}
|
|
91
|
+
<% if (typeof parentIdKeys !== 'undefined' && parentIdKeys && parentIdKeys.length > 1) { -%>
|
|
92
|
+
<% for (let i = 1; i < parentIdKeys.length; i++) { -%>
|
|
93
|
+
let <%- parentIdKeys[i] %> = '';
|
|
94
|
+
if (keyParts.length > <%- 2 + i %>) {
|
|
95
|
+
<%- parentIdKeys[i] %> = keyParts[keyParts.length - <%- 2 + i %>];
|
|
96
|
+
}
|
|
97
|
+
<% } -%>
|
|
98
|
+
<% } -%>
|
|
99
|
+
//(</extractIdentifiersFromKeyOrMetadata>)
|
|
100
|
+
|
|
63
101
|
//(<endpointHook>)
|
|
64
102
|
//(</endpointHook>)
|
|
103
|
+
|
|
104
|
+
<% if (typeof nextStepFunctionName === 'string' && nextStepFunctionName) { -%>
|
|
105
|
+
const metaUserId =
|
|
106
|
+
s3Metadata.submittedbyuserid ||
|
|
107
|
+
s3Metadata.submittedByUserId ||
|
|
108
|
+
s3Metadata.userid ||
|
|
109
|
+
s3Metadata.userId ||
|
|
110
|
+
_izContext.userId ||
|
|
111
|
+
'';
|
|
112
|
+
let messageObject = {
|
|
113
|
+
objectType: '<%- objectType %>',
|
|
114
|
+
submittedByUserId: metaUserId,
|
|
115
|
+
identifiers: {
|
|
116
|
+
<%- objectType %>Id: rawId
|
|
117
|
+
},
|
|
118
|
+
<% if (typeof parentIdKeys !== 'undefined' && parentIdKeys && parentIdKeys.length > 1) { -%>
|
|
119
|
+
targetIdentifiers: {
|
|
120
|
+
<%- parentIdKeys[0] %>: parentId,
|
|
121
|
+
<% for (let i = 1; i < parentIdKeys.length; i++) { -%>
|
|
122
|
+
<%- parentIdKeys[i] %>: <%- parentIdKeys[i] %><%- i < parentIdKeys.length - 1 ? ',' : '' %>
|
|
123
|
+
<% } -%>
|
|
124
|
+
},
|
|
125
|
+
<% } else if (typeof parentIdKey !== 'undefined' && parentIdKey) { -%>
|
|
126
|
+
targetIdentifiers: {
|
|
127
|
+
<%- parentIdKey %>: parentId
|
|
128
|
+
},
|
|
129
|
+
<% } -%>
|
|
130
|
+
fieldNames: {
|
|
131
|
+
//(<fieldNamesHook>)
|
|
132
|
+
//(</fieldNamesHook>)
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
messageObject =
|
|
137
|
+
callingFlowSharedLib.addCallingFlowToSnsRequestMessageObject(
|
|
138
|
+
messageObject,
|
|
139
|
+
callingFlowSharedLib.addParentCallingFlowConfig(
|
|
140
|
+
passBackProperties,
|
|
141
|
+
callingFlowSharedLib.createCallingFlowConfig(
|
|
142
|
+
await lambdaSharedLib.lambdaFunctionName(
|
|
143
|
+
_izContext,
|
|
144
|
+
'<%- nextStepFunctionName %>'
|
|
145
|
+
),
|
|
146
|
+
{}
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
let sendMessageToCreateEndpoint = {
|
|
152
|
+
Message: JSON.stringify(messageObject),
|
|
153
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(_izContext, 'Create_In')
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
_izContext.logger.debug(
|
|
157
|
+
'sendMessageToCreateEndpoint',
|
|
158
|
+
sendMessageToCreateEndpoint
|
|
159
|
+
);
|
|
160
|
+
await sns.publishAsync(_izContext, sendMessageToCreateEndpoint);
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
status: 'dispatched',
|
|
164
|
+
s3Key,
|
|
165
|
+
messageObject
|
|
166
|
+
};
|
|
167
|
+
<% } else { -%>
|
|
168
|
+
return {
|
|
169
|
+
status: 'processed',
|
|
170
|
+
s3Key
|
|
171
|
+
};
|
|
172
|
+
<% } -%>
|
|
65
173
|
} catch (err) {
|
|
66
|
-
_izContext.logger.error('
|
|
174
|
+
_izContext.logger.error('Error in <%- functionName %>: ', err);
|
|
67
175
|
throw err;
|
|
68
176
|
}
|
|
69
177
|
}
|