@izara_project/izara-core-generate-service-code 1.0.85 → 1.0.86

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 (31) hide show
  1. package/package.json +1 -1
  2. package/src/compile/compileProject.js +1 -2
  3. package/src/compile/loadSchemas.js +29 -17
  4. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +1 -0
  5. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +15 -4
  6. package/src/emit/crud/emitCrudApplicationArtifacts.js +10 -4
  7. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +10 -4
  8. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +36 -4
  9. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +35 -3
  10. package/src/emit/crud/templates/UpdateLogicalLib.ejs +754 -353
  11. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +5 -2
  12. package/src/emit/rbac/emitRbacApplicationArtifacts.js +102 -6
  13. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +34 -4
  14. package/src/emit/rbac/templates/DeleteTargetRole_Main.ejs +96 -0
  15. package/src/emit/rbac/templates/GetMyPermissions_Main.ejs +106 -0
  16. package/src/emit/rbac/templates/GetTargetRole_Main.ejs +62 -0
  17. package/src/emit/rbac/templates/UpdateTargetRole_Main.ejs +107 -0
  18. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +12 -12
  19. package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +12 -0
  20. package/src/emit/resource/emitResourceArtifacts.js +43 -2
  21. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +4 -2
  22. package/src/emit/systemText/emitSystemTextSchemas.js +5 -2
  23. package/src/generate.js +18 -12
  24. package/src/generateResources/IntTest/generateResources/generateResources.js +1 -1
  25. package/src/generateResources/IntTest/generateTests/generateTemplate.js +1 -1
  26. package/src/generateResources/IntTest/upload/uploadIntTest.js +8 -2
  27. package/test/createTargetRoleHandler.test.js +42 -1
  28. package/test/crudApplicationArtifacts.test.js +53 -0
  29. package/test/dynamicRbacFlowSchemas.test.js +5 -2
  30. package/test/publicApi.test.js +18 -14
  31. package/test/resourceArtifacts.test.js +3 -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.85",
3
+ "version": "1.0.86",
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": {
@@ -1,4 +1,3 @@
1
- import Logger from '@izara_project/izara-core-library-logger';
2
1
  import { join, resolve } from 'node:path';
3
2
  import { readFileSync, existsSync } from 'node:fs';
4
3
  import { parse as parseYaml } from 'yaml';
@@ -33,7 +32,7 @@ export function compileProject(request = {}) {
33
32
  }
34
33
  }
35
34
  } catch (err) {
36
- Logger?.debug?.('Could not read serverless.config.yml', err);
35
+ console.log('Could not read serverless.config.yml', err);
37
36
  }
38
37
  }
39
38
 
@@ -7,9 +7,15 @@ import {
7
7
  } from '@izara_project/izara-core-library-service-schemas';
8
8
  import { basicValidatorSchema } from '@izara_project/izara-shared-service-schemas';
9
9
  import { s3 } from '@izara_project/izara-core-library-s3';
10
- import Logger from '@izara_project/izara-core-library-logger';
11
10
  import { validateFlowSchema } from './flowValidator.js';
12
11
 
12
+ const consoleLogger = {
13
+ debug: console.log,
14
+ info: console.log,
15
+ warn: console.log,
16
+ error: console.error
17
+ };
18
+
13
19
  const VALID_INITIATE_BY_ENUM = [
14
20
  'user',
15
21
  'systemWithUser',
@@ -66,7 +72,7 @@ export async function loadLocalSchemaDirectory(
66
72
  options = {}
67
73
  ) {
68
74
  const directoryPath = join(project.schemaRoot, directoryName);
69
- const logger = options.logger || Logger;
75
+ const logger = options.logger || consoleLogger;
70
76
  let entries;
71
77
  try {
72
78
  entries = await readdir(directoryPath, { withFileTypes: true });
@@ -229,8 +235,9 @@ export async function resolveExtendedObjectSchemas(
229
235
  let currentSchema = schema;
230
236
  if (currentSchema.hasOwnProperty('extendObjType')) {
231
237
  try {
232
- Logger.debug(
233
- `[DEBUG] [resolveExtendedObjectSchemas] Merging extendObjType for objectType=${currentSchema.objectType}`,
238
+ console.log(
239
+ `[DEBUG] [resolveExtendedObjectSchemas] Merging extendObjType ` +
240
+ `for objectType=${currentSchema.objectType}`,
234
241
  { extendObjType: currentSchema.extendObjType }
235
242
  );
236
243
  const initialResources = currentSchema.storageResources || {};
@@ -238,7 +245,7 @@ export async function resolveExtendedObjectSchemas(
238
245
  const parentServiceTag = currentSchema.extendObjType.serviceTag;
239
246
 
240
247
  const mergedSchema = await getObjectSchema.mergeExtendObjSchema(
241
- { logger: Logger },
248
+ { logger: consoleLogger },
242
249
  currentSchema,
243
250
  bucketName
244
251
  );
@@ -270,8 +277,9 @@ export async function resolveExtendedObjectSchemas(
270
277
 
271
278
  currentSchema = mergedSchema;
272
279
  } catch (error) {
273
- Logger.error(
274
- `[ERROR] [resolveExtendedObjectSchemas] Failed to merge extendObjType for objectType=${currentSchema.objectType}`,
280
+ console.log(
281
+ `[ERROR] [resolveExtendedObjectSchemas] Failed to merge ` +
282
+ `extendObjType for objectType=${currentSchema.objectType}`,
275
283
  { error }
276
284
  );
277
285
  throw error;
@@ -289,8 +297,9 @@ export async function resolveExtendedObjectSchemas(
289
297
  belongToTarget.objectType
290
298
  ) {
291
299
  try {
292
- Logger.debug(
293
- `[DEBUG] [resolveExtendedObjectSchemas] Fetching belongTo schema for objectType=${currentSchema.objectType}`,
300
+ console.log(
301
+ `[DEBUG] [resolveExtendedObjectSchemas] Fetching belongTo ` +
302
+ `schema for objectType=${currentSchema.objectType}`,
294
303
  { belongTo: belongToTarget }
295
304
  );
296
305
  const belongToObjType = {
@@ -298,19 +307,21 @@ export async function resolveExtendedObjectSchemas(
298
307
  objectType: belongToTarget.objectType
299
308
  };
300
309
  const belongToSchema = await getObjectSchema.getObjSchemaS3(
301
- { logger: Logger },
310
+ { logger: consoleLogger },
302
311
  belongToObjType,
303
312
  false,
304
313
  bucketName
305
314
  );
306
315
  currentSchema.belongToSchema = belongToSchema;
307
- Logger.debug(
308
- `[DEBUG] [resolveExtendedObjectSchemas] Successfully fetched belongTo schema for objectType=${currentSchema.objectType}`,
316
+ console.log(
317
+ `[DEBUG] [resolveExtendedObjectSchemas] Successfully fetched ` +
318
+ `belongTo schema for objectType=${currentSchema.objectType}`,
309
319
  { belongToObjectType: belongToSchema?.objectType }
310
320
  );
311
321
  } catch (error) {
312
- Logger.warn(
313
- `[WARN] [resolveExtendedObjectSchemas] Failed to fetch belongTo schema for objectType=${currentSchema.objectType}`,
322
+ console.log(
323
+ `[WARN] [resolveExtendedObjectSchemas] Failed to fetch ` +
324
+ `belongTo schema for objectType=${currentSchema.objectType}`,
314
325
  { error }
315
326
  );
316
327
  }
@@ -361,7 +372,7 @@ export async function resolveGraphServiceTags(
361
372
  let graphServerTagsMap = {};
362
373
  if (bucketName) {
363
374
  try {
364
- const _izContext = { logger: Logger };
375
+ const _izContext = { logger: consoleLogger };
365
376
  const s3Data = await s3.getObjectS3(_izContext, {
366
377
  Bucket: bucketName,
367
378
  Key: 'serviceConfig/GraphServerTags.json'
@@ -370,8 +381,9 @@ export async function resolveGraphServiceTags(
370
381
  graphServerTagsMap = s3Data;
371
382
  }
372
383
  } catch (error) {
373
- Logger.debug?.(
374
- `[DEBUG] [resolveGraphServiceTags] Could not fetch GraphServerTags.json from bucket=${bucketName}`,
384
+ console.log(
385
+ `[DEBUG] [resolveGraphServiceTags] Could not fetch ` +
386
+ `GraphServerTags.json from bucket=${bucketName}`,
375
387
  error
376
388
  );
377
389
  }
@@ -244,6 +244,7 @@ export async function emitCoreFunctionArtifacts({ project, objects = [], relatio
244
244
  const hasQuotaReservation = crudPlans?.Create?.hasQuotaReservation ?? false;
245
245
 
246
246
  const state = {
247
+ serviceTag: project?.serviceTag || '',
247
248
  project,
248
249
  objects,
249
250
  relationships,
@@ -179,9 +179,14 @@ const tableConfigs = {
179
179
  });
180
180
  });
181
181
 
182
+ const currentServiceTag = (typeof serviceTag !== 'undefined' && serviceTag) ? serviceTag : ((typeof project !== 'undefined' && project?.serviceTag) ? project.serviceTag : '');
182
183
  const rbacSubs = [];
183
184
  if (crud && rbac) {
184
- const allRbacTags = Array.from(new Set(['Rbac', ...(typeof rbacValidatorServiceTags !== 'undefined' && rbacValidatorServiceTags ? rbacValidatorServiceTags : [])]));
185
+ const allRbacTags = Array.from(new Set([
186
+ 'Rbac',
187
+ currentServiceTag,
188
+ ...(typeof rbacValidatorServiceTags !== 'undefined' && rbacValidatorServiceTags ? rbacValidatorServiceTags : [])
189
+ ])).filter(Boolean);
185
190
  const hasGraph = typeof objectGraphServiceTags !== 'undefined' && objectGraphServiceTags && objectGraphServiceTags.length > 0;
186
191
  const createEndpoint = hasGraph ? 'CreateRbacCallbackHdrSqs' : 'CreateCompleteHdrSqs';
187
192
  const updateEndpoint = hasGraph ? 'UpdateRbacCallbackHdrSqs' : 'UpdateCompleteHdrSqs';
@@ -198,7 +203,11 @@ const tableConfigs = {
198
203
  }
199
204
 
200
205
  if (typeof customRbacFlowTags !== 'undefined' && customRbacFlowTags && customRbacFlowTags.length > 0) {
201
- const allRbacTags = Array.from(new Set(['Rbac', ...(typeof rbacValidatorServiceTags !== 'undefined' ? rbacValidatorServiceTags : [])]));
206
+ const allRbacTags = Array.from(new Set([
207
+ 'Rbac',
208
+ currentServiceTag,
209
+ ...(typeof rbacValidatorServiceTags !== 'undefined' ? rbacValidatorServiceTags : [])
210
+ ])).filter(Boolean);
202
211
  customRbacFlowTags.forEach(function(flowTag) {
203
212
  const tagUpper = flowTag[0].toUpperCase() + flowTag.slice(1);
204
213
  allRbacTags.forEach(function(tag) {
@@ -316,7 +325,8 @@ function roleConfigs() {
316
325
  Resource: [
317
326
  `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}`,
318
327
  `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ConfirmUsage_In', 'Rbac')}`,
319
- `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'CancelUsage_In', 'Rbac')}`<% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
328
+ `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'CancelUsage_In', 'Rbac')}`<% if (rbac) { %>,
329
+ `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In')}`<% } %><% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
320
330
  `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', '<%= tag %>')}`<% }); %>
321
331
  ]
322
332
  },
@@ -335,7 +345,8 @@ function roleConfigs() {
335
345
  Effect: 'Allow',
336
346
  Action: ['sns:Publish'],
337
347
  Resource: [
338
- `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}`<% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
348
+ `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}`,
349
+ `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In')}`<% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
339
350
  `arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', '<%= tag %>')}`<% }); %>
340
351
  ]
341
352
  }
@@ -35,11 +35,17 @@ export async function emitCrudApplicationArtifacts({
35
35
  objectType: obj?.objectType ?? '(undefined)',
36
36
  generatedBy: obj?.generatedBy ?? '(missing)'
37
37
  }));
38
- logger?.warn?.(
39
- `[WARN] [CRUD Application] Skipped FlowObjects application artifacts generation: No valid CRUD ObjectSchema found. ` +
38
+ const warnMsg =
39
+ `[WARN] [CRUD Application] Skipped FlowObjects application artifacts ` +
40
+ `generation: No valid CRUD ObjectSchema found. ` +
40
41
  `Checked ${objects.length} object(s): ${JSON.stringify(summary)}. ` +
41
- `Expected "generatedBy" to be one of: ${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`
42
- );
42
+ `Expected "generatedBy" to be one of: ` +
43
+ `${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`;
44
+ if (logger?.warn) {
45
+ logger.warn(warnMsg);
46
+ } else {
47
+ console.log(warnMsg);
48
+ }
43
49
  }
44
50
  return [];
45
51
  }
@@ -29,11 +29,17 @@ export function emitDynamicCrudFlowSchemas({
29
29
  objectType: obj?.objectType ?? '(undefined)',
30
30
  generatedBy: obj?.generatedBy ?? '(missing)'
31
31
  }));
32
- logger?.warn?.(
33
- `[WARN] [CRUD FlowSchemas] Skipped FlowObjects FlowSchemas generation: No valid CRUD ObjectSchema found. ` +
32
+ const warnMsg =
33
+ `[WARN] [CRUD FlowSchemas] Skipped FlowObjects FlowSchemas ` +
34
+ `generation: No valid CRUD ObjectSchema found. ` +
34
35
  `Checked ${objects.length} object(s): ${JSON.stringify(summary)}. ` +
35
- `Expected "generatedBy" to be one of: ${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`
36
- );
36
+ `Expected "generatedBy" to be one of: ` +
37
+ `${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`;
38
+ if (logger?.warn) {
39
+ logger.warn(warnMsg);
40
+ } else {
41
+ console.log(warnMsg);
42
+ }
37
43
  }
38
44
  return [];
39
45
  }
@@ -85,6 +85,7 @@ export default async function <%- flowTag %>(
85
85
  _izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
86
86
 
87
87
  targetIdentifiers = requestParams.targetIdentifiers;
88
+ delete requestParams.targetIdentifiers;
88
89
 
89
90
  if (!targetIdentifiers && objectSchema.belongTo?.objectType === 'user' && submittedByUserId) {
90
91
  targetIdentifiers = { submittedByUserId };
@@ -99,12 +100,11 @@ export default async function <%- flowTag %>(
99
100
  if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
100
101
  targetIdentifiers.submittedByUserId = submittedByUserId;
101
102
  }
102
- requestParams.targetIdentifiers = targetIdentifiers;
103
103
  }
104
104
 
105
105
  _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
106
106
  submittedByUserId: requestParams.submittedByUserId,
107
- targetIdentifiers: requestParams.targetIdentifiers,
107
+ targetIdentifiers,
108
108
  belongTo: objectSchema.belongTo,
109
109
  generatedBy: objectSchema.generatedBy
110
110
  });
@@ -116,6 +116,37 @@ export default async function <%- flowTag %>(
116
116
  // ── Build identifiers used by asynchronous processing ────────────────────
117
117
  const identifiers = requestParams.identifiers;
118
118
 
119
+ if (!objectSchema.hasOwnProperty('belongTo')) {
120
+ if (!targetIdentifiers && identifiers) {
121
+ targetIdentifiers = { ...identifiers };
122
+ } else if (targetIdentifiers && identifiers) {
123
+ for (const [key, value] of Object.entries(identifiers)) {
124
+ if (targetIdentifiers[key] === undefined && value !== undefined) {
125
+ targetIdentifiers[key] = value;
126
+ }
127
+ }
128
+ }
129
+ if (targetIdentifiers) {
130
+ if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
131
+ targetIdentifiers.submittedByUserId = submittedByUserId;
132
+ }
133
+ }
134
+ }
135
+
136
+ if (targetIdentifiers && identifiers) {
137
+ for (const [key, value] of Object.entries(identifiers)) {
138
+ if (
139
+ targetIdentifiers[key] !== undefined &&
140
+ value !== undefined &&
141
+ targetIdentifiers[key] !== value
142
+ ) {
143
+ errorsFound.push(
144
+ `targetIdentifiers.${key} must match identifiers.${key}`
145
+ );
146
+ }
147
+ }
148
+ }
149
+
119
150
  if (errorsFound.length > 0)
120
151
  return await <%- flowTag %>LogicalLib(
121
152
  _izContext,
@@ -131,8 +162,8 @@ export default async function <%- flowTag %>(
131
162
  for (const o of rbacObjects) {
132
163
  const belongToTargets = o?.belongTo
133
164
  ? Array.isArray(o.belongTo)
134
- ? o.belongTo
135
- : [o.belongTo]
165
+ ? o.belongTo
166
+ : [o.belongTo]
136
167
  : [];
137
168
  if (belongToTargets.length > 0 && belongToTargets[0]?.serviceTag) {
138
169
  rbacServiceTagMap[o.objectType] = `'${belongToTargets[0].serviceTag}'`;
@@ -164,6 +195,7 @@ export default async function <%- flowTag %>(
164
195
  },
165
196
  parameterGroups,
166
197
  {
198
+ targetIdentifiers,
167
199
  rbacObjType: {
168
200
  serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
169
201
  },
@@ -99,6 +99,7 @@ export default async function <%- flowTag %>(
99
99
  _izContext.correlationIds?.get(coreConsts.SUBMITTED_BY_USER_ID);
100
100
 
101
101
  targetIdentifiers = requestParams.targetIdentifiers;
102
+ delete requestParams.targetIdentifiers;
102
103
 
103
104
  if (!targetIdentifiers && objectSchema.belongTo?.objectType === 'user' && submittedByUserId) {
104
105
  targetIdentifiers = { submittedByUserId };
@@ -113,12 +114,11 @@ export default async function <%- flowTag %>(
113
114
  if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
114
115
  targetIdentifiers.submittedByUserId = submittedByUserId;
115
116
  }
116
- requestParams.targetIdentifiers = targetIdentifiers;
117
117
  }
118
118
 
119
119
  _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
120
120
  submittedByUserId: requestParams.submittedByUserId,
121
- targetIdentifiers: requestParams.targetIdentifiers,
121
+ targetIdentifiers,
122
122
  belongTo: objectSchema.belongTo,
123
123
  generatedBy: objectSchema.generatedBy
124
124
  });
@@ -129,7 +129,38 @@ export default async function <%- flowTag %>(
129
129
  }
130
130
 
131
131
  // ── Build identifiers used by asynchronous processing ────────────────────
132
- const identifiers = requestParams.objInstanceFull.identifiers;
132
+ const identifiers = requestParams.objInstanceFull?.identifiers;
133
+
134
+ if (!objectSchema.hasOwnProperty('belongTo')) {
135
+ if (!targetIdentifiers && identifiers) {
136
+ targetIdentifiers = { ...identifiers };
137
+ } else if (targetIdentifiers && identifiers) {
138
+ for (const [key, value] of Object.entries(identifiers)) {
139
+ if (targetIdentifiers[key] === undefined && value !== undefined) {
140
+ targetIdentifiers[key] = value;
141
+ }
142
+ }
143
+ }
144
+ if (targetIdentifiers) {
145
+ if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
146
+ targetIdentifiers.submittedByUserId = submittedByUserId;
147
+ }
148
+ }
149
+ }
150
+
151
+ if (targetIdentifiers && identifiers) {
152
+ for (const [key, value] of Object.entries(identifiers)) {
153
+ if (
154
+ targetIdentifiers[key] !== undefined &&
155
+ value !== undefined &&
156
+ targetIdentifiers[key] !== value
157
+ ) {
158
+ errorsFound.push(
159
+ `targetIdentifiers.${key} must match objInstanceFull.identifiers.${key}`
160
+ );
161
+ }
162
+ }
163
+ }
133
164
 
134
165
  //(<validateBeforeUpdate>)
135
166
  //(</validateBeforeUpdate>)
@@ -182,6 +213,7 @@ export default async function <%- flowTag %>(
182
213
  },
183
214
  parameterGroups,
184
215
  {
216
+ targetIdentifiers,
185
217
  rbacObjType: {
186
218
  serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
187
219
  },