@izara_project/izara-core-generate-service-code 1.0.76 → 1.0.78

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izara_project/izara-core-generate-service-code",
3
- "version": "1.0.76",
3
+ "version": "1.0.78",
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": {
@@ -42,6 +42,8 @@ Resources:
42
42
  Resource:
43
43
  - arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:${self:custom.iz_resourcePrefix}AddLinkCreateByRelHdrInv
44
44
  - arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:${self:custom.iz_resourcePrefix}AddLinkBelongToHdrInv
45
+ - arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:UserAccount${self:custom.iz_stage}AddLinkCreateByRelHdrInv
46
+ - arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:UserAccount${self:custom.iz_stage}AddLinkBelongToHdrInv
45
47
  - arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:GraphHandler${self:custom.iz_stage}CreateAllIndexSchemasHdrInv
46
48
  - arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:TranslateIds${self:custom.iz_stage}CreatePermissionHdrInv
47
49
  - arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:Translations${self:custom.iz_stage}AddLinkToTranslationLinksHdrInv
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
  import Logger from '@izara_project/izara-core-library-logger';
20
20
  import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
21
21
  import snsSharedLib from '@izara_project/izara-core-library-sns';
22
+ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
22
23
 
23
24
  const _izContext = { logger: Logger };
24
25
 
@@ -33,7 +33,7 @@ import {
33
33
 
34
34
  const { createObjType, firstLetterUpperCase } = utils;
35
35
 
36
- import { <%- flowTag %>MainLogical } from './Process<%- upperCaseFlowTag %>_Main.js';
36
+ import { <%- flowTag %>MainLogical } from './<%- upperCaseFlowTag %>_Main.js';
37
37
 
38
38
  //(<optionalRequire>)
39
39
  //(</optionalRequire>)
@@ -26,7 +26,7 @@ const CUSTOM_TEMPLATE_URL = new URL('./templates/', import.meta.url);
26
26
 
27
27
  export async function emitCustomFlowApplicationArtifacts(
28
28
  flows,
29
- { systemFunctions = [], objects = [] } = {}
29
+ { objects = [] } = {}
30
30
  ) {
31
31
  const customFlows = supportedCustomFlows(flows);
32
32
  const generatedRoots = generatedOwnTopicFlows(flows);
@@ -36,8 +36,7 @@ export async function emitCustomFlowApplicationArtifacts(
36
36
  customFlows.length === 0 &&
37
37
  generatedRoots.length === 0 &&
38
38
  steps.length === 0 &&
39
- dsqSteps.length === 0 &&
40
- systemFunctions.length === 0
39
+ dsqSteps.length === 0
41
40
  )
42
41
  return [];
43
42
 
@@ -57,20 +56,18 @@ export async function emitCustomFlowApplicationArtifacts(
57
56
  {
58
57
  path: YAML_PATH,
59
58
  content: [
60
- ...systemFunctions,
61
59
  ...emitted.flatMap((result) => result.functions),
62
60
  ...roots.flatMap((result) => result.functions),
63
61
  ...stepResults.flatMap((result) => result.functions),
64
62
  ...dsqStepResults.flatMap((result) => result.functions)
65
- ].join('\n')
63
+ ]
64
+ .filter(Boolean)
65
+ .join('\n\n')
66
66
  }
67
67
  ];
68
68
  }
69
69
 
70
- export function customFlowApplicationManagedPaths(
71
- flows,
72
- { includeYaml = false } = {}
73
- ) {
70
+ export function customFlowApplicationManagedPaths(flows) {
74
71
  return [
75
72
  ...supportedCustomFlows(flows).flatMap((flow) => flowPaths(flow)),
76
73
  ...generatedOwnTopicFlows(flows).flatMap(ownTopicRootPaths),
@@ -97,8 +94,7 @@ export function customFlowApplicationManagedPaths(
97
94
  generatedOwnTopicFlows(flows).length > 0 ||
98
95
  generatedDsqFlows(flows).length > 0 ||
99
96
  flowExtTopicSteps(flows).length > 0 ||
100
- flowDsqSteps(flows).length > 0 ||
101
- includeYaml
97
+ flowDsqSteps(flows).length > 0
102
98
  ? [YAML_PATH]
103
99
  : [])
104
100
  ];
@@ -40,6 +40,9 @@ import { utils } from '@izara_project/izara-core-library-service-schemas';
40
40
  const { createFlowTypeConcat } = utils;
41
41
  //(</optionalImport>)
42
42
 
43
+ //(<helperFunction>)
44
+ //(</helperFunction>)
45
+
43
46
  /**
44
47
  *
45
48
  *
@@ -70,7 +73,7 @@ export default async function <%- typeof functionName !== 'undefined' ? function
70
73
  callingFlowConfig
71
74
  );
72
75
 
73
- <% if (typeof flow !== 'undefined' && flow.statusType === 'storedCache') { %>
76
+ <% if (typeof flow !== 'undefined' && flow.statusType === 'storedCache') { -%>
74
77
 
75
78
  //(<beforeCheckCache>)
76
79
  //(</beforeCheckCache>)
@@ -105,9 +108,9 @@ export default async function <%- typeof functionName !== 'undefined' ? function
105
108
  //(<checkStoredCacheHook>)
106
109
  //(</checkStoredCacheHook>)
107
110
  }
108
- <% } %>
111
+ <% } -%>
112
+ <% if (typeof flow !== 'undefined' && flow.isRbac) { -%>
109
113
 
110
- <% if (typeof flow !== 'undefined' && flow.isRbac) { %>
111
114
  const { checkRbacPermission } =
112
115
  await import('@izara_project/izara-authorization');
113
116
 
@@ -139,11 +142,11 @@ export default async function <%- typeof functionName !== 'undefined' ? function
139
142
  )
140
143
  });
141
144
  }
142
-
143
- <% } %>
145
+ <% } -%>
144
146
 
145
147
  //(<endpointHook>)
146
148
  //(</endpointHook>)
149
+
147
150
  } catch (err) {
148
151
  _izContext.logger.error('error WebSocketInvoke: ', err);
149
152
  throw err;
@@ -13,8 +13,17 @@ export const dynamicRelationshipFlowSchemaPaths = ACTIONS.map(
13
13
  `app/src/schemas/FlowSchemas/generateCode/FlowRelationship/${action}.js`
14
14
  );
15
15
 
16
- export function emitDynamicRelationshipFlowSchemas() {
17
- // Keep legacy compatibility: relationship flow endpoints exist even before a relationship is declared.
16
+ export function dynamicRelationshipFlowSchemaManagedPaths(relationships = []) {
17
+ if (!Array.isArray(relationships) || relationships.length === 0) {
18
+ return [];
19
+ }
20
+ return dynamicRelationshipFlowSchemaPaths;
21
+ }
22
+
23
+ export function emitDynamicRelationshipFlowSchemas({ relationships = [] } = {}) {
24
+ if (!Array.isArray(relationships) || relationships.length === 0) {
25
+ return [];
26
+ }
18
27
  return ACTIONS.map((action, index) => ({
19
28
  path: dynamicRelationshipFlowSchemaPaths[index],
20
29
  content: _renderDynamicRelationshipFlowSchema(
@@ -3,7 +3,7 @@ import { commitArtifacts } from '../../output/commitArtifacts.js';
3
3
  import { compileProject } from '../../compile/compileProject.js';
4
4
  import { loadLocalSchemaDirectory } from '../../compile/loadSchemas.js';
5
5
  import {
6
- dynamicRelationshipFlowSchemaPaths,
6
+ dynamicRelationshipFlowSchemaManagedPaths,
7
7
  emitDynamicRelationshipFlowSchemas
8
8
  } from './emitDynamicRelationshipFlowSchemas.js';
9
9
 
@@ -12,14 +12,15 @@ export async function generateDynamicRelationshipFlowSchemas(
12
12
  options = {}
13
13
  ) {
14
14
  const project = compileProject({ ...options, rootPath });
15
- // The legacy generator creates these endpoints even with no relationships. Load now to
16
- // validate the V2 source-module contract before later slices consume relationship data.
17
- await loadLocalSchemaDirectory(project, 'RelationshipSchemas');
15
+ const relationships = await loadLocalSchemaDirectory(
16
+ project,
17
+ 'RelationshipSchemas'
18
+ );
18
19
  const plan = buildGenerationPlan(
19
20
  project,
20
- emitDynamicRelationshipFlowSchemas(),
21
+ emitDynamicRelationshipFlowSchemas({ relationships }),
21
22
  {
22
- managedPaths: dynamicRelationshipFlowSchemaPaths,
23
+ managedPaths: dynamicRelationshipFlowSchemaManagedPaths(relationships),
23
24
  managedScope: 'relationship-flow-schemas'
24
25
  }
25
26
  );
@@ -411,6 +411,9 @@ async function renderInSqs(state) {
411
411
  ? [
412
412
  render('ResourceSqsYaml.ejs', {
413
413
  queueName: 'WebSocketCompleteHdrSqs'
414
+ }),
415
+ render('ResourceSqsYaml.ejs', {
416
+ queueName: 'RegisterCompleteHdrSqs'
414
417
  })
415
418
  ]
416
419
  : [])
@@ -603,6 +606,12 @@ function roleQueueNames(state, roleName) {
603
606
  }
604
607
  return [];
605
608
  }
609
+ if (roleName === 'RegisterRole') {
610
+ if (state.websocket) {
611
+ return ['RegisterCompleteHdrSqs'];
612
+ }
613
+ return [];
614
+ }
606
615
  if (roleName === 'FlowObjectsRole') {
607
616
  return [
608
617
  ...CRUD_ACTIONS.map((action) => `${action}HdrSqs`),
@@ -40,7 +40,7 @@ function _hasStorageObjects(objects) {
40
40
 
41
41
  async function _emitSystemArtifacts(objects) {
42
42
  if (!_hasStorageObjects(objects)) {
43
- return [];
43
+ return { artifacts: [], functions: [] };
44
44
  }
45
45
 
46
46
  const hasFindDataEntries = buildFindDataEntries(objects).length > 0;
@@ -80,17 +80,16 @@ async function _emitSystemArtifacts(objects) {
80
80
  {
81
81
  path: `${PROCESS_LOGICAL_SOURCE}/PaginateProcessLogical_HdrSqs.js`,
82
82
  content: await render('PaginateProcessLogical_HdrSqs.ejs', {})
83
- },
84
- {
85
- path: YAML_PATH,
86
- content: renderSystemYaml()
87
83
  }
88
84
  );
89
85
 
90
- return artifacts;
86
+ return {
87
+ artifacts,
88
+ functions: renderSystemYamlFunctions()
89
+ };
91
90
  }
92
91
 
93
- function renderSystemYaml() {
92
+ function renderSystemYamlFunctions() {
94
93
  const findDataYaml = renderFindDataYaml();
95
94
  const processLogicalYaml = renderProcessLogicalYaml();
96
95
  const processLogicalPaginateDsqYaml = renderProcessLogicalPaginateDsqYaml();
@@ -100,7 +99,7 @@ function renderSystemYaml() {
100
99
  processLogicalYaml,
101
100
  processLogicalPaginateDsqYaml,
102
101
  processLogicalPaginateSqsYaml
103
- ].join('\n\n');
102
+ ];
104
103
  }
105
104
 
106
105
  function renderFindDataYaml() {
@@ -38,11 +38,11 @@ export async function emitSystemWebSocketArtifacts(
38
38
  );
39
39
  const registerCompleteHdrSqsContent = await _renderSystemTemplate(
40
40
  'RegisterComplete_HdrSqs.ejs',
41
- { queueName: 'RegisterComplete' }
41
+ { queueName: 'RegisterCompleteHdrSqs' }
42
42
  );
43
43
  const registerCompleteHdrDsqContent = await _renderSystemTemplate(
44
44
  'RegisterComplete_HdrSqs.ejs',
45
- { queueName: 'RegisterCompleteDLQ' }
45
+ { queueName: 'RegisterCompleteHdrSqsDLQ' }
46
46
  );
47
47
 
48
48
  const webSocketConnectYaml = await _renderSystemTemplate(
@@ -4,14 +4,14 @@ RegisterCompleteHdrSqs:
4
4
  role: RegisterRole
5
5
  events:
6
6
  - sqs:
7
- arn: arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}RegisterComplete
7
+ arn: arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}RegisterCompleteHdrSqs
8
8
  batchSize: 10
9
9
 
10
- RegisterCompleteDsq:
10
+ RegisterCompleteHdrDsq:
11
11
  handler: src/generatedCode/SystemFlowSchemas/Register/source/RegisterComplete_HdrDsq.main
12
- name: ${self:custom.iz_resourcePrefix}RegisterCompleteDsq
12
+ name: ${self:custom.iz_resourcePrefix}RegisterCompleteHdrDsq
13
13
  role: RegisterRole
14
14
  events:
15
15
  - sqs:
16
- arn: arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}RegisterCompleteDLQ
16
+ arn: arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}RegisterCompleteHdrSqsDLQ
17
17
  batchSize: 10
package/src/generate.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  rbacApplicationManagedPaths
23
23
  } from './emit/rbac/emitRbacApplicationArtifacts.js';
24
24
  import {
25
- dynamicRelationshipFlowSchemaPaths,
25
+ dynamicRelationshipFlowSchemaManagedPaths,
26
26
  emitDynamicRelationshipFlowSchemas
27
27
  } from './emit/relationship/emitDynamicRelationshipFlowSchemas.js';
28
28
  import {
@@ -139,10 +139,23 @@ async function _emitGroups({ project, objects, relationships, flows, objectGraph
139
139
  emitCoreFunctionArtifacts({ project, objects, relationships, flows, objectGraphServiceTags, relationshipGraphServiceTags })
140
140
  ]);
141
141
  const custom = await emitCustomFlowApplicationArtifacts(flows, {
142
- systemFunctions: system.functions,
143
142
  objects
144
143
  });
145
144
 
145
+ const systemFunctions = [
146
+ ...(system.functions ?? []),
147
+ ...(findData.functions ?? [])
148
+ ].filter(Boolean);
149
+
150
+ const findDataArtifacts = [...(findData.artifacts ?? [])];
151
+
152
+ if (systemFunctions.length > 0) {
153
+ findDataArtifacts.push({
154
+ path: 'app/sls_yaml/generatedCode/source/flow-system.yml',
155
+ content: systemFunctions.join('\n\n')
156
+ });
157
+ }
158
+
146
159
  let resolvedCoreFunctionManagedPaths = coreFunctionManagedPaths;
147
160
  if (typeof coreFunctionManagedPaths === 'function') {
148
161
  resolvedCoreFunctionManagedPaths = coreFunctionManagedPaths(
@@ -160,8 +173,8 @@ async function _emitGroups({ project, objects, relationships, flows, objectGraph
160
173
  },
161
174
  {
162
175
  scope: 'relationship-flow-schemas',
163
- managedPaths: dynamicRelationshipFlowSchemaPaths,
164
- artifacts: emitDynamicRelationshipFlowSchemas()
176
+ managedPaths: dynamicRelationshipFlowSchemaManagedPaths(relationships),
177
+ artifacts: emitDynamicRelationshipFlowSchemas({ relationships })
165
178
  },
166
179
  {
167
180
  scope: 'rbac-flow-schemas',
@@ -194,15 +207,11 @@ async function _emitGroups({ project, objects, relationships, flows, objectGraph
194
207
  {
195
208
  scope: 'system-find-data',
196
209
  managedPaths: findDataManagedPaths(),
197
- artifacts: findData
210
+ artifacts: findDataArtifacts
198
211
  },
199
212
  {
200
213
  scope: 'custom-flow-application',
201
- managedPaths: customFlowApplicationManagedPaths(flows, {
202
- includeYaml: hasSystemWebSocket(flows, {
203
- includeRelationshipOwnTopic: true
204
- })
205
- }),
214
+ managedPaths: customFlowApplicationManagedPaths(flows),
206
215
  artifacts: custom
207
216
  },
208
217
  {
@@ -25,7 +25,18 @@ after(async () => {
25
25
  );
26
26
  });
27
27
 
28
- test('generates dynamic relationship schemas even without declared relationships for legacy compatibility', async () => {
28
+ test('does not generate dynamic relationship schemas when no relationships exist', async () => {
29
+ const rootPath = await mkdtemp(
30
+ join(tmpdir(), 'generate-service-code-v2-relationship-empty-')
31
+ );
32
+ projectRoots.add(rootPath);
33
+
34
+ const result = await generateDynamicRelationshipFlowSchemas(rootPath);
35
+
36
+ assert.equal(result.files.length, 0);
37
+ });
38
+
39
+ test('generates dynamic relationship schemas when declared relationships exist', async () => {
29
40
  const rootPath = await createProject();
30
41
 
31
42
  const result = await generateDynamicRelationshipFlowSchemas(rootPath);
@@ -23,7 +23,7 @@ test('generate commits schemas, application artifacts, and resources in one publ
23
23
  const rootPath = await createCrudProject();
24
24
  const result = await generate(rootPath);
25
25
 
26
- assert.strictEqual(result.files.length, 63);
26
+ assert.strictEqual(result.files.length, 57);
27
27
  assert.equal(result.project.rootPath, rootPath);
28
28
  assert.match(
29
29
  await readFile(
@@ -129,14 +129,14 @@ test('generate commits the system WebSocket completion path for own-topic flows'
129
129
  );
130
130
  assert.match(
131
131
  await readFile(
132
- join(rootPath, 'app/sls_yaml/generatedCode/source/flow-schema.yml'),
132
+ join(rootPath, 'app/sls_yaml/generatedCode/source/flow-system.yml'),
133
133
  'utf8'
134
134
  ),
135
135
  /WebSocketConnect:[\s\S]*route: \$connect[\s\S]*WebSocketCompleteHdrSqs:/
136
136
  );
137
137
  assert.match(
138
138
  await readFile(
139
- join(rootPath, 'app/sls_yaml/generatedCode/source/flow-schema.yml'),
139
+ join(rootPath, 'app/sls_yaml/generatedCode/source/flow-system.yml'),
140
140
  'utf8'
141
141
  ),
142
142
  /filterPatterns:[\s\S]*WebSocketCompleteHdrSqs/
@@ -151,6 +151,16 @@ test('generate commits the system WebSocket completion path for own-topic flows'
151
151
  ),
152
152
  /WebSocketCompleteHdrSqs:[\s\S]*SubscriptionToOutTrackWebSocketComplete:/
153
153
  );
154
+ assert.match(
155
+ await readFile(
156
+ join(
157
+ rootPath,
158
+ 'resource/sls_yaml/generatedCode/source/generated-sns-in-sqs.yml'
159
+ ),
160
+ 'utf8'
161
+ ),
162
+ /RegisterCompleteHdrSqs:[\s\S]*RegisterCompleteHdrSqsDLQ:/
163
+ );
154
164
  assert.match(
155
165
  await readFile(
156
166
  join(
@@ -288,7 +298,7 @@ test('generate removes stale CRUD schemas and application artifacts', async () =
288
298
 
289
299
  const result = await generate(rootPath);
290
300
 
291
- assert.equal(result.files.length, 34);
301
+ assert.equal(result.files.length, 28);
292
302
  await assert.rejects(
293
303
  readFile(
294
304
  join(
@@ -386,14 +396,21 @@ test(
386
396
  assert.match(uploadSchemaMain, /\/\/\(<ignoreExternalServices>\)/);
387
397
  assert.match(uploadSchemaMain, /\/\/\(<\/ignoreExternalServices>\)/);
388
398
 
389
- const commandUploadSchema = await readFile(
399
+ const coreResource = await readFile(
390
400
  join(
391
401
  rootPath,
392
- 'app/initial_setup/generatedCode/source/commands/uploadSchema.js'
402
+ 'app/sls_yaml/generatedCode/source/core-resource.yml'
393
403
  ),
394
404
  'utf8'
395
405
  );
396
- assert.match(commandUploadSchema, /\/\/\(<ignoreExternalServices>\)/);
397
- assert.match(commandUploadSchema, /\/\/\(<\/ignoreExternalServices>\)/);
406
+ assert.match(
407
+ coreResource,
408
+ /UserAccount\$\{self:custom\.iz_stage\}AddLinkCreateByRelHdrInv/
409
+ );
410
+ assert.match(
411
+ coreResource,
412
+ /UserAccount\$\{self:custom\.iz_stage\}AddLinkBelongToHdrInv/
413
+ );
398
414
  }
399
415
  );
416
+
@@ -102,7 +102,8 @@ test('emits queues, topics, tables, and IAM roles from schema data', async () =>
102
102
  /Process(?:Create|Update|Delete|Get|Change|Move)Relationship/
103
103
  );
104
104
  assert.match(roleBlock(iam, 'RegisterRole'), /s3:GetObject/);
105
- assert.doesNotMatch(roleBlock(iam, 'RegisterRole'), /dynamodb:|sqs:|sns:/);
105
+ assert.match(roleBlock(iam, 'RegisterRole'), /RegisterComplete/);
106
+ assert.doesNotMatch(roleBlock(iam, 'RegisterRole'), /dynamodb:|sns:/);
106
107
  assert.doesNotMatch(
107
108
  iam,
108
109
  /s3:GetObjectVersion|s3:ListBucket|sqs:DeleteMessageBatch|sqs:GetQueueUrl/