@izara_project/izara-core-generate-service-code 1.0.69 → 1.0.71

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.
Files changed (67) hide show
  1. package/package.json +1 -1
  2. package/scripts/format-ejs.js +35 -30
  3. package/src/compile/loadSchemas.js +84 -45
  4. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +163 -0
  5. package/src/emit/coreFunction/templates/CoreFunction_Yaml.ejs +38 -0
  6. package/src/emit/coreFunction/templates/CoreResource_Yaml.ejs +235 -0
  7. package/src/emit/coreFunction/templates/GenerateSeedDataDynamo_HdrInv.ejs +16 -0
  8. package/src/emit/coreFunction/templates/GenerateSeedDataDynamo_Main.ejs +38 -0
  9. package/src/emit/coreFunction/templates/GenerateSeedDataGraphData_HdrInv.ejs +16 -0
  10. package/src/emit/coreFunction/templates/GenerateSeedDataGraphData_Main.ejs +32 -0
  11. package/src/emit/coreFunction/templates/GenerateSeedDataGraphSchema_HdrInv.ejs +16 -0
  12. package/src/emit/coreFunction/templates/GenerateSeedDataGraphSchema_Main.ejs +71 -0
  13. package/src/emit/coreFunction/templates/GeneratedGraphNodeSchemas.ejs +47 -0
  14. package/src/emit/coreFunction/templates/GeneratedGraphRelSchemas.ejs +27 -0
  15. package/src/emit/coreFunction/templates/GeneratedTableConfigs.ejs +34 -0
  16. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +108 -0
  17. package/src/emit/coreFunction/templates/InitialSetup_HdrInv.ejs +12 -0
  18. package/src/emit/coreFunction/templates/InitialSetup_Main.ejs +51 -0
  19. package/src/emit/coreFunction/templates/RemoveSeedDataDynamo_HdrInv.ejs +16 -0
  20. package/src/emit/coreFunction/templates/RemoveSeedDataDynamo_Main.ejs +31 -0
  21. package/src/emit/coreFunction/templates/UploadSchema_HdrInv.ejs +37 -0
  22. package/src/emit/coreFunction/templates/UploadSchema_Main.ejs +52 -0
  23. package/src/emit/crud/emitCrudApplicationArtifacts.js +12 -6
  24. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +1 -1
  25. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +1 -1
  26. package/src/emit/crud/templates/GetEndpoint_Main.ejs +1 -1
  27. package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +1 -1
  28. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +1 -1
  29. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +30 -11
  30. package/src/emit/custom/templates/FlowEndpoint_Main.ejs +2 -2
  31. package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
  32. package/src/emit/custom/templates/s3/CreateObject_Main.ejs +1 -1
  33. package/src/emit/custom/templates/s3/ReservedLimit_Main.ejs +1 -1
  34. package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +4 -4
  35. package/src/emit/function/functionYamlArtifact.js +5 -2
  36. package/src/emit/relationship/emitRelationshipApplicationArtifacts.js +13 -3
  37. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +1 -1
  38. package/src/emit/relationship/templates/CreateRelationship_Main.ejs +1 -1
  39. package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +1 -1
  40. package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
  41. package/src/emit/relationship/templates/MoveRelationship_Main.ejs +1 -1
  42. package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +1 -1
  43. package/src/emit/resource/emitResourceArtifacts.js +71 -15
  44. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +17 -0
  45. package/src/emit/shared/templates/FindData_HdrSqs.ejs +120 -0
  46. package/src/emit/shared/templates/FindData_Main.ejs +345 -0
  47. package/src/emit/{crud → shared}/templates/FlowHandler_HdrApi.ejs +1 -1
  48. package/src/emit/{relationship → shared}/templates/FlowHandler_HdrDsq.ejs +4 -4
  49. package/src/emit/{crud → shared}/templates/FlowHandler_HdrInv.ejs +1 -1
  50. package/src/emit/{crud → shared}/templates/FlowHandler_HdrSqs.ejs +4 -4
  51. package/src/emit/shared/templates/PaginateProcessLogical_HdrDsq.ejs +162 -0
  52. package/src/emit/shared/templates/PaginateProcessLogical_HdrSqs.ejs +140 -0
  53. package/src/emit/shared/templates/PaginateProcessLogical_Main.ejs +268 -0
  54. package/src/emit/{relationship/templates/FlowHandler_HdrSqs.ejs → shared/templates/ProcessLogical_HdrSqs.ejs} +40 -55
  55. package/src/emit/shared/templates/ProcessLogical_Main.ejs +448 -0
  56. package/src/emit/system/emitSystemFindDataArtifacts.js +266 -0
  57. package/src/emit/system/templates/WebSocketComplete_HdrSqs.ejs +27 -11
  58. package/src/emit/system/templates/WebSocketComplete_Main.ejs +63 -18
  59. package/src/emit/system/templates/WebSocketConnect.ejs +26 -6
  60. package/src/generate.js +31 -4
  61. package/src/output/mergeHooks.js +18 -19
  62. package/test/core.test.js +4 -12
  63. package/test/crudApplicationArtifacts.test.js +14 -18
  64. package/test/publicApi.test.js +2 -2
  65. package/test/resourceArtifacts.test.js +1 -1
  66. package/src/emit/relationship/templates/FlowHandler_HdrApi.ejs +0 -59
  67. package/src/emit/relationship/templates/FlowHandler_HdrInv.ejs +0 -47
@@ -0,0 +1,266 @@
1
+ import ejsLib from 'ejs';
2
+ import { readFile } from 'node:fs/promises';
3
+
4
+ const SHARED_TEMPLATE_URL = new URL('../shared/templates/', import.meta.url);
5
+ const FIND_DATA_SOURCE = 'app/src/generatedCode/FindData/source';
6
+ const FIND_DATA_HANDLER_ROOT = 'src/generatedCode/FindData/source';
7
+ const PROCESS_LOGICAL_SOURCE = 'app/src/generatedCode/ProcessLogical/source';
8
+ const PROCESS_LOGICAL_HANDLER_ROOT = 'src/generatedCode/ProcessLogical/source';
9
+ const YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-system.yml';
10
+
11
+ const STORAGE_TYPES = { dynamoDB: 'dynamoDB', graph: 'graph' };
12
+
13
+ export async function emitSystemFindDataArtifacts(objects) {
14
+ return _emitSystemArtifacts(objects);
15
+ }
16
+
17
+ export function findDataManagedPaths() {
18
+ return [
19
+ `${FIND_DATA_SOURCE}/FindData_Main.js`,
20
+ `${FIND_DATA_SOURCE}/FindData_HdrSqs.js`,
21
+ `${PROCESS_LOGICAL_SOURCE}/ProcessLogical_Main.js`,
22
+ `${PROCESS_LOGICAL_SOURCE}/ProcessLogical_HdrSqs.js`,
23
+ `${PROCESS_LOGICAL_SOURCE}/PaginateProcessLogical_Main.js`,
24
+ `${PROCESS_LOGICAL_SOURCE}/PaginateProcessLogical_HdrDsq.js`,
25
+ `${PROCESS_LOGICAL_SOURCE}/PaginateProcessLogical_HdrSqs.js`,
26
+ YAML_PATH
27
+ ];
28
+ }
29
+
30
+ function _hasStorageObjects(objects) {
31
+ if (!Array.isArray(objects) || objects.length === 0) {
32
+ return false;
33
+ }
34
+ return objects.some(
35
+ (object) =>
36
+ object.storageResources &&
37
+ Object.keys(object.storageResources).length > 0
38
+ );
39
+ }
40
+
41
+ async function _emitSystemArtifacts(objects) {
42
+ if (!_hasStorageObjects(objects)) {
43
+ return [];
44
+ }
45
+
46
+ const hasFindDataEntries = buildFindDataEntries(objects).length > 0;
47
+
48
+ const artifacts = [];
49
+
50
+ if (hasFindDataEntries) {
51
+ const findDataMain = await render('FindData_Main.ejs', {
52
+ datas: buildFindDataEntries(objects)
53
+ });
54
+ artifacts.push(
55
+ { path: `${FIND_DATA_SOURCE}/FindData_Main.js`, content: findDataMain },
56
+ {
57
+ path: `${FIND_DATA_SOURCE}/FindData_HdrSqs.js`,
58
+ content: await render('FindData_HdrSqs.ejs', {})
59
+ }
60
+ );
61
+ }
62
+
63
+ artifacts.push(
64
+ {
65
+ path: `${PROCESS_LOGICAL_SOURCE}/ProcessLogical_Main.js`,
66
+ content: await render('ProcessLogical_Main.ejs', {})
67
+ },
68
+ {
69
+ path: `${PROCESS_LOGICAL_SOURCE}/ProcessLogical_HdrSqs.js`,
70
+ content: await render('ProcessLogical_HdrSqs.ejs', {})
71
+ },
72
+ {
73
+ path: `${PROCESS_LOGICAL_SOURCE}/PaginateProcessLogical_Main.js`,
74
+ content: await render('PaginateProcessLogical_Main.ejs', {})
75
+ },
76
+ {
77
+ path: `${PROCESS_LOGICAL_SOURCE}/PaginateProcessLogical_HdrDsq.js`,
78
+ content: await render('PaginateProcessLogical_HdrDsq.ejs', {})
79
+ },
80
+ {
81
+ path: `${PROCESS_LOGICAL_SOURCE}/PaginateProcessLogical_HdrSqs.js`,
82
+ content: await render('PaginateProcessLogical_HdrSqs.ejs', {})
83
+ },
84
+ {
85
+ path: YAML_PATH,
86
+ content: renderSystemYaml()
87
+ }
88
+ );
89
+
90
+ return artifacts;
91
+ }
92
+
93
+ function renderSystemYaml() {
94
+ const findDataYaml = renderFindDataYaml();
95
+ const processLogicalYaml = renderProcessLogicalYaml();
96
+ const processLogicalPaginateDsqYaml = renderProcessLogicalPaginateDsqYaml();
97
+ const processLogicalPaginateSqsYaml = renderProcessLogicalPaginateSqsYaml();
98
+ return [
99
+ findDataYaml,
100
+ processLogicalYaml,
101
+ processLogicalPaginateDsqYaml,
102
+ processLogicalPaginateSqsYaml
103
+ ].join('\n\n');
104
+ }
105
+
106
+ function renderFindDataYaml() {
107
+ return _renderSqsYaml({
108
+ functionName: 'FindData',
109
+ handlerRoot: FIND_DATA_HANDLER_ROOT,
110
+ roleName: 'ProcFindDataRole'
111
+ });
112
+ }
113
+
114
+ function renderProcessLogicalYaml() {
115
+ return _renderSqsYaml({
116
+ functionName: 'ProcessLogical',
117
+ handlerRoot: PROCESS_LOGICAL_HANDLER_ROOT,
118
+ roleName: 'ProcFindDataRole'
119
+ });
120
+ }
121
+
122
+ function renderProcessLogicalPaginateDsqYaml() {
123
+ return _renderSqsYaml({
124
+ functionName: 'PaginateProcessLogical',
125
+ handlerType: 'HdrDsq',
126
+ handlerRoot: PROCESS_LOGICAL_HANDLER_ROOT,
127
+ roleName: 'ProcFindDataRole'
128
+ });
129
+ }
130
+
131
+ function renderProcessLogicalPaginateSqsYaml() {
132
+ return _renderSqsYaml({
133
+ functionName: 'PaginateProcessLogical',
134
+ handlerRoot: PROCESS_LOGICAL_HANDLER_ROOT,
135
+ roleName: 'ProcFindDataRole'
136
+ });
137
+ }
138
+
139
+ function _renderSqsYaml({
140
+ functionName,
141
+ handlerType = 'HdrSqs',
142
+ handlerRoot,
143
+ roleName
144
+ }) {
145
+ const upperHandlerType = handlerType;
146
+ const handlerPath = `${handlerRoot}/${functionName}_${upperHandlerType}.main`;
147
+ const name = `${functionName}${upperHandlerType}`;
148
+ return `${name}:
149
+ handler: ${handlerPath}
150
+ name: \${self:custom.iz_resourcePrefix}${name}
151
+ role: ${roleName}
152
+ #<#${name}FunctionSetting#>
153
+ #<#/${name}FunctionSetting#>
154
+ events:
155
+ - sqs:
156
+ arn: arn:aws:sqs:\${self:custom.iz_region}:\${self:custom.iz_accountId}:\${self:custom.iz_resourcePrefix}${name}
157
+ batchSize: 10`;
158
+ }
159
+
160
+ function buildFindDataEntries(objects) {
161
+ return objects
162
+ .filter(
163
+ (object) =>
164
+ object.storageResources &&
165
+ Object.keys(object.storageResources).length > 0
166
+ )
167
+ .map((object) => {
168
+ const objectType = object.objectType;
169
+ const storageResources = object.storageResources;
170
+ const fieldNames = object.fieldNames || {};
171
+ const identifiers = object.identifiers || [];
172
+ const identifierNames = new Set(
173
+ identifiers.map((id) => id.fieldName).filter(Boolean)
174
+ );
175
+
176
+ const fieldEntries = [];
177
+
178
+ for (const [field, schemas] of Object.entries(fieldNames)) {
179
+ if (schemas.type !== 'string' && schemas.type !== 'number') {
180
+ continue;
181
+ }
182
+
183
+ const storageResourceTags = schemas.storageResourceTags;
184
+ if (
185
+ !Array.isArray(storageResourceTags) ||
186
+ storageResourceTags.length === 0
187
+ ) {
188
+ continue;
189
+ }
190
+
191
+ const collectStorageDetail = {};
192
+ const getInIdentifiers = identifierNames.has(field);
193
+
194
+ for (const storageTag of storageResourceTags) {
195
+ const storageDetail = storageResources[storageTag];
196
+ if (!storageDetail) {
197
+ continue;
198
+ }
199
+
200
+ if (storageDetail.storageType === STORAGE_TYPES.graph) {
201
+ if (!collectStorageDetail[STORAGE_TYPES.graph]) {
202
+ collectStorageDetail[STORAGE_TYPES.graph] = {
203
+ graphServerTag: storageDetail.graphServerTag,
204
+ getInIdentifiers
205
+ };
206
+ }
207
+ } else if (storageDetail.storageType === STORAGE_TYPES.dynamoDB) {
208
+ if (!collectStorageDetail[STORAGE_TYPES.dynamoDB]) {
209
+ collectStorageDetail[STORAGE_TYPES.dynamoDB] = {
210
+ tableName: storageDetail.tableName
211
+ };
212
+ }
213
+ }
214
+ }
215
+
216
+ if (
217
+ collectStorageDetail[STORAGE_TYPES.graph] &&
218
+ collectStorageDetail[STORAGE_TYPES.dynamoDB]
219
+ ) {
220
+ delete collectStorageDetail[STORAGE_TYPES.graph];
221
+ }
222
+
223
+ if (Object.keys(collectStorageDetail).length > 0) {
224
+ fieldEntries.push({ [field]: collectStorageDetail });
225
+ }
226
+ }
227
+
228
+ if (Array.isArray(object.addOnDataStructure)) {
229
+ for (const versionedData of object.addOnDataStructure) {
230
+ if (versionedData.type === 'versionedData') {
231
+ const versionedStorageTag = versionedData.storageResourceTag;
232
+ const versionedFieldNames = versionedData.fieldNames || {};
233
+ const storageDetail = storageResources[versionedStorageTag];
234
+
235
+ if (
236
+ storageDetail &&
237
+ storageDetail.storageType === STORAGE_TYPES.graph
238
+ ) {
239
+ const versionedStorageDetail = {
240
+ [STORAGE_TYPES.graph]: {
241
+ graphServerTag: storageDetail.graphServerTag,
242
+ versionedDataLabel: versionedData.versionedDataLabel
243
+ }
244
+ };
245
+
246
+ for (const [key, value] of Object.entries(versionedFieldNames)) {
247
+ if (value.type === 'string' || value.type === 'number') {
248
+ fieldEntries.push({ [key]: versionedStorageDetail });
249
+ }
250
+ }
251
+ }
252
+ }
253
+ }
254
+ }
255
+
256
+ return { objectType, fieldNames: fieldEntries };
257
+ })
258
+ .filter((entry) => entry.fieldNames.length > 0);
259
+ }
260
+
261
+ async function render(templateName, data) {
262
+ return ejsLib.render(
263
+ await readFile(new URL(templateName, SHARED_TEMPLATE_URL), 'utf8'),
264
+ data
265
+ );
266
+ }
@@ -9,21 +9,37 @@ const perRecordsValidatorSchema = {};
9
9
  export const main = middleware.wrap(async (event, context, callback) => {
10
10
  try {
11
11
  const recordPromises = [];
12
- await Promise.all(event.Records.map(async record => {
13
- record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
14
- await recordHandlerSharedLib.validateRecord(record, 'WebSocketCompleteHdrSqs', perRecordsValidatorSchema);
15
- recordPromises.push(recordHandlerSharedLib.recordHandler(
16
- record,
17
- WebSocketComplete,
18
- 'WebSocketCompleteHdrSqs',
19
- [record.body.TopicArn, record.body.Message, callingFlowSharedLib.addCallingFlowToPassOnProperties(record.body.Message)]
20
- ));
21
- }));
12
+ await Promise.all(
13
+ event.Records.map(async (record) => {
14
+ record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
15
+ await recordHandlerSharedLib.validateRecord(
16
+ record,
17
+ 'WebSocketCompleteHdrSqs',
18
+ perRecordsValidatorSchema
19
+ );
20
+ recordPromises.push(
21
+ recordHandlerSharedLib.recordHandler(
22
+ record,
23
+ WebSocketComplete,
24
+ 'WebSocketCompleteHdrSqs',
25
+ [
26
+ record.body.TopicArn,
27
+ record.body.Message,
28
+ callingFlowSharedLib.addCallingFlowToPassOnProperties(
29
+ record.body.Message
30
+ )
31
+ ]
32
+ )
33
+ );
34
+ })
35
+ );
22
36
  try {
23
37
  await Promise.all(recordPromises);
24
38
  return event.Records;
25
39
  } catch {
26
- Logger.debug('Promise.all(recordPromises) in handler threw error (at least one record did no resolve)');
40
+ Logger.debug(
41
+ 'Promise.all(recordPromises) in handler threw error (at least one record did no resolve)'
42
+ );
27
43
  }
28
44
  } catch (error) {
29
45
  Logger.error('Unhandled Error, WebSocketComplete_HdrSqs: ', error);
@@ -1,44 +1,89 @@
1
1
  import { NoRetryError } from '@izara_project/izara-core-library-core';
2
2
  import { consts } from '@izara_project/izara-middleware';
3
- import { getObjectSchema, utils } from '@izara_project/izara-core-library-service-schemas';
3
+ import {
4
+ getObjectSchema,
5
+ utils
6
+ } from '@izara_project/izara-core-library-service-schemas';
4
7
  import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
5
8
  import { webSocket } from '@izara_project/izara-core-library-external-request';
6
9
 
7
10
  const { createFlowTypeConcat } = utils;
8
11
  const { postToConnection } = webSocket;
9
12
 
10
- export default async function WebSocketComplete(_izContext, topicArn, requestParams, callingFlowConfig = {}) {
13
+ export default async function WebSocketComplete(
14
+ _izContext,
15
+ topicArn,
16
+ requestParams,
17
+ callingFlowConfig = {}
18
+ ) {
11
19
  try {
12
20
  _izContext.logger.debug('WebSocketComplete _izContext', _izContext);
13
21
  _izContext.logger.debug('WebSocketComplete requestParams', requestParams);
14
- _izContext.logger.debug('WebSocketComplete callingFlowConfig', callingFlowConfig);
15
- const correlationId = _izContext.correlationIds.get(consts.X_CORRELATION_ID);
16
- if (!topicArn) throw new NoRetryError('not have TopicArn for get FlowSchemas');
22
+ _izContext.logger.debug(
23
+ 'WebSocketComplete callingFlowConfig',
24
+ callingFlowConfig
25
+ );
26
+ const correlationId = _izContext.correlationIds.get(
27
+ consts.X_CORRELATION_ID
28
+ );
29
+ if (!topicArn)
30
+ throw new NoRetryError('not have TopicArn for get FlowSchemas');
17
31
  const topicName = topicArn.split(':')[5].split('_');
18
32
  let flowTag = topicName[2];
19
- let flowSchema = await getObjectSchema.getFlowSchemaS3WithCache(_izContext, { flowTag, serviceTag: topicName[0] });
33
+ let flowSchema = await getObjectSchema.getFlowSchemaS3WithCache(
34
+ _izContext,
35
+ { flowTag, serviceTag: topicName[0] }
36
+ );
20
37
  if (!flowSchema) {
21
- if (!requestParams?.hasOwnProperty('flowTag')) throw new NoRetryError('Could not find flowSchema from topicArn or requestParams.flowTag');
38
+ if (!requestParams?.hasOwnProperty('flowTag'))
39
+ throw new NoRetryError(
40
+ 'Could not find flowSchema from topicArn or requestParams.flowTag'
41
+ );
22
42
  flowTag = requestParams.flowTag;
23
- flowSchema = await getObjectSchema.getFlowSchemaS3WithCache(_izContext, { flowTag, serviceTag: process.env.iz_serviceTag });
43
+ flowSchema = await getObjectSchema.getFlowSchemaS3WithCache(_izContext, {
44
+ flowTag,
45
+ serviceTag: process.env.iz_serviceTag
46
+ });
24
47
  }
25
48
  //(<createIdentifiersFlow>)
26
49
  let identifiers;
27
50
  //(</createIdentifiersFlow>)
28
51
  let taskKey;
29
- if (flowSchema.statusType === 'statusField' || flowSchema.statusType === 'storedCache' || flowSchema.statusType === 'triggerCache') {
30
- taskKey = createFlowTypeConcat(_izContext, { flowTag, serviceTag: topicName[0] }) + identifiers;
52
+ if (
53
+ flowSchema.statusType === 'statusField' ||
54
+ flowSchema.statusType === 'storedCache' ||
55
+ flowSchema.statusType === 'triggerCache'
56
+ ) {
57
+ taskKey =
58
+ createFlowTypeConcat(_izContext, {
59
+ flowTag,
60
+ serviceTag: topicName[0]
61
+ }) + identifiers;
31
62
  } else if (flowSchema.statusType === 'none') {
32
- taskKey = createFlowTypeConcat(_izContext, { flowTag, serviceTag: topicName[0] }) + correlationId;
63
+ taskKey =
64
+ createFlowTypeConcat(_izContext, {
65
+ flowTag,
66
+ serviceTag: topicName[0]
67
+ }) + correlationId;
33
68
  }
34
69
  if (!taskKey) return;
35
- const tasks = await dynamodbSharedLib.query(_izContext, await dynamodbSharedLib.tableName(_izContext, 'WebSocketTask'), { taskKey });
36
- await Promise.all((tasks.Items ?? []).map(async task => {
37
- //(<beforePostMessage>)
38
- //(</beforePostMessage>)
39
- await postToConnection({ message: requestParams }, task.connectionId);
40
- await dynamodbSharedLib.deleteItem(_izContext, await dynamodbSharedLib.tableName(_izContext, 'WebSocketTask'), { taskKey: task.taskKey, connectionId: task.connectionId });
41
- }));
70
+ const tasks = await dynamodbSharedLib.query(
71
+ _izContext,
72
+ await dynamodbSharedLib.tableName(_izContext, 'WebSocketTask'),
73
+ { taskKey }
74
+ );
75
+ await Promise.all(
76
+ (tasks.Items ?? []).map(async (task) => {
77
+ //(<beforePostMessage>)
78
+ //(</beforePostMessage>)
79
+ await postToConnection({ message: requestParams }, task.connectionId);
80
+ await dynamodbSharedLib.deleteItem(
81
+ _izContext,
82
+ await dynamodbSharedLib.tableName(_izContext, 'WebSocketTask'),
83
+ { taskKey: task.taskKey, connectionId: task.connectionId }
84
+ );
85
+ })
86
+ );
42
87
  } catch (error) {
43
88
  _izContext.logger.error('error WebSocketInvoke: ', error);
44
89
  throw error;
@@ -1,19 +1,39 @@
1
1
  import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
2
- import { middlewareHandler as middleware, response } from '@izara_project/izara-middleware';
2
+ import {
3
+ middlewareHandler as middleware,
4
+ response
5
+ } from '@izara_project/izara-middleware';
3
6
 
4
- export const main = middleware.wrap(async event => {
7
+ export const main = middleware.wrap(async (event) => {
5
8
  const { eventType, connectionId } = event.requestContext ?? {};
6
9
  try {
7
10
  event._izContext.logger.debug('Event:', event);
8
11
  if (eventType === 'CONNECT') {
9
12
  const { userId, submittedByUserId } = event.queryStringParameters ?? {};
10
- await dynamodbSharedLib.putItem(event._izContext, await dynamodbSharedLib.tableName(event._izContext, 'UserUploadRecords'), {
11
- connectionId, userId, submittedByUserId, expirationTime: Math.floor(Date.now() / 1000) + 7200
12
- });
13
+ await dynamodbSharedLib.putItem(
14
+ event._izContext,
15
+ await dynamodbSharedLib.tableName(
16
+ event._izContext,
17
+ 'UserUploadRecords'
18
+ ),
19
+ {
20
+ connectionId,
21
+ userId,
22
+ submittedByUserId,
23
+ expirationTime: Math.floor(Date.now() / 1000) + 7200
24
+ }
25
+ );
13
26
  //(<webSocketConnect>)
14
27
  //(</webSocketConnect>)
15
28
  } else if (eventType === 'DISCONNECT') {
16
- await dynamodbSharedLib.deleteItem(event._izContext, await dynamodbSharedLib.tableName(event._izContext, 'UserUploadRecords'), { connectionId });
29
+ await dynamodbSharedLib.deleteItem(
30
+ event._izContext,
31
+ await dynamodbSharedLib.tableName(
32
+ event._izContext,
33
+ 'UserUploadRecords'
34
+ ),
35
+ { connectionId }
36
+ );
17
37
  //(<webSocketDisconnect>)
18
38
  //(</webSocketDisconnect>)
19
39
  }
package/src/generate.js CHANGED
@@ -42,6 +42,14 @@ import {
42
42
  hasSystemWebSocket,
43
43
  systemWebSocketManagedPaths
44
44
  } from './emit/system/emitSystemWebSocketArtifacts.js';
45
+ import {
46
+ emitSystemFindDataArtifacts,
47
+ findDataManagedPaths
48
+ } from './emit/system/emitSystemFindDataArtifacts.js';
49
+ import {
50
+ emitCoreFunctionArtifacts,
51
+ coreFunctionManagedPaths
52
+ } from './emit/coreFunction/emitCoreFunctionArtifacts.js';
45
53
 
46
54
  export async function generate(rootPath, options = {}) {
47
55
  const startedAt = Date.now();
@@ -54,14 +62,21 @@ export async function generate(rootPath, options = {}) {
54
62
  loadLocalSchemaDirectory(project, 'RelationshipSchemas'),
55
63
  loadLocalSchemaDirectory(project, 'FlowSchemas')
56
64
  ]);
65
+ const schemaBucketName =
66
+ options.schemaBucketName || process.env.iz_serviceSchemaBucketName;
57
67
  const objects = await resolveExtendedObjectSchemas(
58
68
  rawObjects,
59
- options.schemaBucketName
69
+ schemaBucketName
60
70
  );
61
71
  logger?.debug?.(
62
72
  `[DEBUG] [Generate] STATUS=SCHEMAS_LOADED | objects=${objects.length} relationships=${relationships.length} flows=${flows.length}`
63
73
  );
64
- const groups = await _emitGroups({ project, objects, relationships, flows });
74
+ const groups = await _emitGroups({
75
+ project,
76
+ objects,
77
+ relationships,
78
+ flows
79
+ });
65
80
  logger?.debug?.(
66
81
  `[DEBUG] [Generate] STATUS=ARTIFACTS_EMITTED | ${groups.map((group) => `${group.scope}=${group.artifacts.length}`).join(' ')}`
67
82
  );
@@ -95,7 +110,7 @@ export async function generate(rootPath, options = {}) {
95
110
  }
96
111
 
97
112
  async function _emitGroups({ project, objects, relationships, flows }) {
98
- const [crud, relationship, rbac, system, resource] = await Promise.all([
113
+ const [crud, relationship, rbac, system, findData, resource, coreFunction] = await Promise.all([
99
114
  emitCrudApplicationArtifacts({
100
115
  objects,
101
116
  flows,
@@ -108,7 +123,9 @@ async function _emitGroups({ project, objects, relationships, flows }) {
108
123
  }),
109
124
  emitRbacApplicationArtifacts(objects),
110
125
  emitSystemWebSocketArtifacts(flows, { includeRelationshipOwnTopic: true }),
111
- emitResourceArtifacts({ objects, relationships, flows })
126
+ emitSystemFindDataArtifacts(objects),
127
+ emitResourceArtifacts({ objects, relationships, flows }),
128
+ emitCoreFunctionArtifacts({ project, objects, relationships })
112
129
  ]);
113
130
  const custom = await emitCustomFlowApplicationArtifacts(flows, {
114
131
  systemFunctions: system.functions,
@@ -153,6 +170,11 @@ async function _emitGroups({ project, objects, relationships, flows }) {
153
170
  managedPaths: systemWebSocketManagedPaths(),
154
171
  artifacts: system.artifacts
155
172
  },
173
+ {
174
+ scope: 'system-find-data',
175
+ managedPaths: findDataManagedPaths(),
176
+ artifacts: findData
177
+ },
156
178
  {
157
179
  scope: 'custom-flow-application',
158
180
  managedPaths: customFlowApplicationManagedPaths(flows, {
@@ -166,6 +188,11 @@ async function _emitGroups({ project, objects, relationships, flows }) {
166
188
  scope: 'shared-resources',
167
189
  managedPaths: resourceArtifactPaths,
168
190
  artifacts: resource
191
+ },
192
+ {
193
+ scope: 'core-function',
194
+ managedPaths: coreFunctionManagedPaths,
195
+ artifacts: coreFunction
169
196
  }
170
197
  ];
171
198
  }
@@ -1,5 +1,5 @@
1
1
  import { lstat, readFile } from 'node:fs/promises';
2
- import { join, sep } from 'node:path';
2
+ import { join } from 'node:path';
3
3
 
4
4
  export async function mergeHooks(outputRoot, artifacts) {
5
5
  return Promise.all(
@@ -11,39 +11,38 @@ export async function mergeHooks(outputRoot, artifacts) {
11
11
  }
12
12
 
13
13
  async function mergeHook(outputRoot, artifact) {
14
- const parts = artifact.path.split(sep);
15
- const sourceIndex = parts.lastIndexOf('source');
16
- if (sourceIndex < 0 || sourceIndex === parts.length - 1) {
14
+ const matchers = hookMatchers(artifact.path);
15
+ if (!matchers) {
17
16
  return artifact.content;
18
17
  }
19
18
 
20
- const hookPath = join(
21
- outputRoot,
22
- ...parts.slice(0, sourceIndex),
23
- 'hook',
24
- ...parts.slice(sourceIndex + 1)
25
- );
19
+ const targetPath = join(outputRoot, artifact.path);
20
+
21
+ let sourceContent;
26
22
  try {
27
- if (!(await lstat(hookPath)).isFile()) {
28
- return artifact.content;
23
+ if (!(await lstat(targetPath)).isFile()) {
24
+ sourceContent = '';
25
+ } else {
26
+ sourceContent = await readFile(targetPath, 'utf8');
29
27
  }
30
28
  } catch (error) {
31
29
  if (error.code === 'ENOENT') {
32
- return artifact.content;
30
+ sourceContent = '';
31
+ } else {
32
+ throw error;
33
33
  }
34
- throw error;
35
34
  }
36
35
 
37
- const matchers = hookMatchers(artifact.path);
38
- if (!matchers) {
36
+ if (!sourceContent) {
39
37
  return artifact.content;
40
38
  }
41
39
 
42
- const hookContent = await readFile(hookPath, 'utf8');
43
40
  return artifact.content.replace(
44
41
  matchers.anyTag,
45
- (match, tagName) =>
46
- hookContent.match(matchers.tagPattern(tagName))?.[0] ?? match
42
+ (_match, tagName) => {
43
+ const hookBlock = sourceContent.match(matchers.tagPattern(tagName))?.[0];
44
+ return hookBlock ?? _match;
45
+ }
47
46
  );
48
47
  }
49
48
 
package/test/core.test.js CHANGED
@@ -145,9 +145,9 @@ test('merges preserved hook blocks into staged source without changing the hook'
145
145
  const outputPath = await mkdtemp(
146
146
  join(tmpdir(), 'generate-service-code-v2-hooks-')
147
147
  );
148
- const hookPath = join(outputPath, 'app/generated/hook/example.js');
149
- await mkdir(dirname(hookPath), { recursive: true });
150
- await writeFile(hookPath, '//(<hookCode>)\ncustom();\n//(</hookCode>)\n');
148
+ const sourcePath = join(outputPath, 'app/generated/source/example.js');
149
+ await mkdir(dirname(sourcePath), { recursive: true });
150
+ await writeFile(sourcePath, '//(<hookCode>)\ncustom();\n//(</hookCode>)\n');
151
151
 
152
152
  await commitArtifacts(
153
153
  buildGenerationPlan(compileProject({ rootPath: outputPath }), [
@@ -159,11 +159,7 @@ test('merges preserved hook blocks into staged source without changing the hook'
159
159
  );
160
160
 
161
161
  assert.equal(
162
- await readFile(join(outputPath, 'app/generated/source/example.js'), 'utf8'),
163
- '//(<hookCode>)\ncustom();\n//(</hookCode>)\n'
164
- );
165
- assert.equal(
166
- await readFile(hookPath, 'utf8'),
162
+ await readFile(sourcePath, 'utf8'),
167
163
  '//(<hookCode>)\ncustom();\n//(</hookCode>)\n'
168
164
  );
169
165
  });
@@ -198,11 +194,8 @@ test('rejects a failed output transaction without partial files, hooks, or stagi
198
194
  );
199
195
  const project = compileProject({ rootPath: outputPath });
200
196
  const sourcePath = join(outputPath, 'app/generated/source/first.js');
201
- const hookPath = join(outputPath, 'app/generated/hook/first.js');
202
197
  await mkdir(dirname(sourcePath), { recursive: true });
203
- await mkdir(dirname(hookPath), { recursive: true });
204
198
  await writeFile(sourcePath, 'old source\n');
205
- await writeFile(hookPath, 'custom hook\n');
206
199
  await mkdir(join(outputPath, 'app/generated/source/second.js'));
207
200
 
208
201
  await assert.rejects(
@@ -215,7 +208,6 @@ test('rejects a failed output transaction without partial files, hooks, or stagi
215
208
  /not a file/
216
209
  );
217
210
  assert.equal(await readFile(sourcePath, 'utf8'), 'old source\n');
218
- assert.equal(await readFile(hookPath, 'utf8'), 'custom hook\n');
219
211
  assert.deepEqual(
220
212
  (await readdir(outputPath)).filter((name) =>
221
213
  name.startsWith('.generate-service-code-v2-stage-')