@izara_project/izara-core-generate-service-code 1.0.92 → 1.0.94

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.
@@ -26,6 +26,9 @@ import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
26
26
  <% if (typeof flow !== 'undefined' && flow.statusType === 'storedCache') { %>
27
27
  import storedCacheSharedLib from '@izara_project/izara-core-library-stored-cache';
28
28
  <% } %>
29
+ <% if (typeof flow !== 'undefined' && flow.statusType === 'triggerCache') { %>
30
+ import { triggeredCacheSharedLibV2 } from '@izara_project/izara-core-library-trigger-cache';
31
+ <% } %>
29
32
 
30
33
  //(<optionalImport>)
31
34
  import { getObjectSchema } from '@izara_project/izara-core-library-service-schemas';
@@ -73,6 +76,70 @@ export default async function <%- typeof functionName !== 'undefined' ? function
73
76
  callingFlowConfig
74
77
  );
75
78
 
79
+ <% if (typeof flow !== 'undefined' && flow.statusType === 'triggerCache') { -%>
80
+
81
+ //(<beforeCheckTriggeredCache>)
82
+ //(</beforeCheckTriggeredCache>)
83
+
84
+ const checkTriggerReseted =
85
+ await triggeredCacheSharedLibV2.checkTriggerResetedV2(
86
+ _izContext,
87
+ {
88
+ serviceTag: process.env.iz_serviceTag,
89
+ flowTag: '<%= flowTag %>'
90
+ },
91
+ //(<triggerCacheIdentifiers>)
92
+ {}
93
+ //(</triggerCacheIdentifiers>)
94
+ //(<triggerCacheUniqueRequestId>)
95
+ //(</triggerCacheUniqueRequestId>)
96
+ //(<triggerCacheSettings>)
97
+ //(</triggerCacheSettings>)
98
+ );
99
+
100
+ _izContext.logger.debug(
101
+ `[${process.env.iz_serviceTag}:<%-
102
+ typeof functionName !== 'undefined'
103
+ ? functionName
104
+ : upperCaseFlowTag
105
+ %>] checkTriggerReseted:`,
106
+ checkTriggerReseted
107
+ );
108
+
109
+ //(<afterCheckTriggerReseted>)
110
+ //(</afterCheckTriggerReseted>)
111
+
112
+ const triggeredCacheResult =
113
+ await triggeredCacheSharedLibV2.checkTriggeredCacheV2(
114
+ _izContext,
115
+ {
116
+ serviceTag: process.env.iz_serviceTag,
117
+ flowTag: '<%= flowTag %>'
118
+ },
119
+ //(<triggerCacheCheckIdentifiers>)
120
+ {}
121
+ //(</triggerCacheCheckIdentifiers>)
122
+ );
123
+
124
+ _izContext.logger.debug(
125
+ `[${process.env.iz_serviceTag}:<%-
126
+ typeof functionName !== 'undefined'
127
+ ? functionName
128
+ : upperCaseFlowTag
129
+ %>] triggeredCacheResult:`,
130
+ triggeredCacheResult
131
+ );
132
+
133
+ //(<afterCheckTriggeredCache>)
134
+ //(</afterCheckTriggeredCache>)
135
+
136
+ if (triggeredCacheResult?.hasPendingTasks) {
137
+ //(<dispatchTriggerFlowHook>)
138
+ //(</dispatchTriggerFlowHook>)
139
+ return triggeredCacheResult;
140
+ }
141
+
142
+ <% } -%>
76
143
  <% if (typeof flow !== 'undefined' && flow.statusType === 'storedCache') { -%>
77
144
 
78
145
  //(<beforeCheckCache>)
@@ -107,6 +174,12 @@ export default async function <%- typeof functionName !== 'undefined' ? function
107
174
 
108
175
  //(<checkStoredCacheHook>)
109
176
  //(</checkStoredCacheHook>)
177
+
178
+ if (cacheMainStatus === 'complete') {
179
+ //(<returnStoredCacheHit>)
180
+ return cacheMain;
181
+ //(</returnStoredCacheHit>)
182
+ }
110
183
  }
111
184
  <% } -%>
112
185
  <% if (typeof flow !== 'undefined' && flow.isRbac && !flow.generatedCodeConfig) { -%>
@@ -0,0 +1,73 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import ejsLib from 'ejs';
3
+
4
+ const TEMPLATE_URL = new URL('./templates/', import.meta.url);
5
+ export const ERROR_SCHEMA_PATH =
6
+ 'app/src/schemas/ErrorSchemas/generateCode/errorSchema.js';
7
+
8
+ export function errorSchemaManagedPaths(errors = []) {
9
+ if (!errors || errors.length === 0) {
10
+ return [];
11
+ }
12
+ return [ERROR_SCHEMA_PATH];
13
+ }
14
+
15
+ /**
16
+ * Emits errorSchema.js artifact based on loaded ErrorSchemas
17
+ *
18
+ * @param {Object} params
19
+ * @param {Object} params.project
20
+ * @param {Array} [params.errors=[]]
21
+ * @param {Array} [params.objectGraphServiceTags=[]]
22
+ * @returns {Promise<Array<{path: string, content: string}>>}
23
+ */
24
+ export async function emitErrorSchemas({
25
+ project = {},
26
+ errors = [],
27
+ objectGraphServiceTags = []
28
+ } = {}) {
29
+ const safeErrors = Array.isArray(errors) ? errors : [];
30
+ if (safeErrors.length === 0) {
31
+ return [];
32
+ }
33
+
34
+ const defaultGraphServiceTag =
35
+ objectGraphServiceTags[0] || 'GraphHandler';
36
+ const defaultServiceTag = project?.serviceTag || '';
37
+
38
+ const errorTypes = {};
39
+ for (const item of safeErrors) {
40
+ if (!item || typeof item !== 'object' || !item.errorTag) {
41
+ continue;
42
+ }
43
+ const errorTag = item.errorTag;
44
+ const serviceTag = item.serviceTag || defaultServiceTag;
45
+ errorTypes[errorTag] = {
46
+ errorTag,
47
+ serviceTag
48
+ };
49
+ }
50
+
51
+ const sortedKeys = Object.keys(errorTypes).sort();
52
+ if (sortedKeys.length === 0) {
53
+ return [];
54
+ }
55
+
56
+ const sortedErrorTypes = {};
57
+ for (const key of sortedKeys) {
58
+ sortedErrorTypes[key] = errorTypes[key];
59
+ }
60
+
61
+ const templatePath = new URL('errorSchema.ejs', TEMPLATE_URL);
62
+ const template = await readFile(templatePath, 'utf8');
63
+ const content = ejsLib.render(template, {
64
+ errorTypes: sortedErrorTypes
65
+ });
66
+
67
+ return [
68
+ {
69
+ path: ERROR_SCHEMA_PATH,
70
+ content
71
+ }
72
+ ];
73
+ }
@@ -0,0 +1,8 @@
1
+ export const ERROR_TYPES = {
2
+ <% Object.keys(errorTypes).forEach((key, index, arr) => { -%>
3
+ <%- key %>: {
4
+ errorTag: '<%- errorTypes[key].errorTag %>',
5
+ serviceTag: '<%- errorTypes[key].serviceTag %>'
6
+ }<%= index < arr.length - 1 ? ',' : '' %>
7
+ <% }); -%>
8
+ };
@@ -242,7 +242,11 @@ export function roleTableNames(state, roleName) {
242
242
  tables.push('UserUploadRecords', 'ReservedDataMain');
243
243
  }
244
244
  if (flow.statusType === 'storedCache') {
245
- const object = state.objectTablesByType.get(flow.objType?.objectType);
245
+ const targetObjectType =
246
+ typeof flow.objType === 'string'
247
+ ? flow.objType
248
+ : flow.objType?.objectType;
249
+ const object = state.objectTablesByType.get(targetObjectType);
246
250
  if (object) {
247
251
  tables.push(object);
248
252
  }
@@ -43,13 +43,14 @@ async function _emitSystemArtifacts(objects) {
43
43
  return { artifacts: [], functions: [] };
44
44
  }
45
45
 
46
- const hasFindDataEntries = buildFindDataEntries(objects).length > 0;
46
+ const findDataEntries = buildFindDataEntries(objects);
47
+ const hasFindDataEntries = findDataEntries.length > 0;
47
48
 
48
49
  const artifacts = [];
49
50
 
50
51
  if (hasFindDataEntries) {
51
52
  const findDataMain = await render('FindData_Main.ejs', {
52
- datas: buildFindDataEntries(objects)
53
+ datas: findDataEntries
53
54
  });
54
55
  artifacts.push(
55
56
  { path: `${FIND_DATA_SOURCE}/FindData_Main.js`, content: findDataMain },
@@ -85,21 +86,21 @@ async function _emitSystemArtifacts(objects) {
85
86
 
86
87
  return {
87
88
  artifacts,
88
- functions: renderSystemYamlFunctions()
89
+ functions: renderSystemYamlFunctions(hasFindDataEntries)
89
90
  };
90
91
  }
91
92
 
92
- function renderSystemYamlFunctions() {
93
- const findDataYaml = renderFindDataYaml();
94
- const processLogicalYaml = renderProcessLogicalYaml();
95
- const processLogicalPaginateDsqYaml = renderProcessLogicalPaginateDsqYaml();
96
- const processLogicalPaginateSqsYaml = renderProcessLogicalPaginateSqsYaml();
97
- return [
98
- findDataYaml,
99
- processLogicalYaml,
100
- processLogicalPaginateDsqYaml,
101
- processLogicalPaginateSqsYaml
102
- ];
93
+ function renderSystemYamlFunctions(hasFindDataEntries = true) {
94
+ const functions = [];
95
+ if (hasFindDataEntries) {
96
+ functions.push(renderFindDataYaml());
97
+ }
98
+ functions.push(
99
+ renderProcessLogicalYaml(),
100
+ renderProcessLogicalPaginateDsqYaml(),
101
+ renderProcessLogicalPaginateSqsYaml()
102
+ );
103
+ return functions;
103
104
  }
104
105
 
105
106
  function renderFindDataYaml() {
package/src/generate.js CHANGED
@@ -61,6 +61,10 @@ import {
61
61
  attributeTreeObjectSchemaManagedPaths,
62
62
  attributeTreeRelationshipSchemaManagedPaths
63
63
  } from './emit/attributeTree/emitAttributeTreeSchemas.js';
64
+ import {
65
+ emitErrorSchemas,
66
+ errorSchemaManagedPaths
67
+ } from './emit/error/emitErrorSchemas.js';
64
68
 
65
69
  export async function generate(rootPath, options = {}) {
66
70
  const startedAt = Date.now();
@@ -70,11 +74,18 @@ export async function generate(rootPath, options = {}) {
70
74
  const schemaLoadOptions = {
71
75
  skipValidation: options.skipValidation
72
76
  };
73
- const [rawObjects, relationships, flows, notifications] = await Promise.all([
77
+ const [
78
+ rawObjects,
79
+ relationships,
80
+ flows,
81
+ notifications,
82
+ errors
83
+ ] = await Promise.all([
74
84
  loadLocalSchemaDirectory(project, 'ObjectSchemas', schemaLoadOptions),
75
85
  loadLocalSchemaDirectory(project, 'RelationshipSchemas', schemaLoadOptions),
76
86
  loadLocalSchemaDirectory(project, 'FlowSchemas', schemaLoadOptions),
77
- loadLocalSchemaDirectory(project, 'NotificationSchemas', schemaLoadOptions)
87
+ loadLocalSchemaDirectory(project, 'NotificationSchemas', schemaLoadOptions),
88
+ loadLocalSchemaDirectory(project, 'ErrorSchemas', schemaLoadOptions)
78
89
  ]);
79
90
  const schemaBucketName =
80
91
  options.schemaBucketName || process.env.iz_serviceSchemaBucketName;
@@ -93,14 +104,24 @@ export async function generate(rootPath, options = {}) {
93
104
  console.log(
94
105
  `[DEBUG] [Generate] STATUS=SCHEMAS_LOADED | ` +
95
106
  `objects=${objects.length} ` +
96
- `relationships=${relationships.length} flows=${flows.length}`
107
+ `relationships=${relationships.length} flows=${flows.length} ` +
108
+ `notifications=${notifications.length} ` +
109
+ `errors=${errors.length}`
97
110
  );
111
+ for (const objectSchema of objects) {
112
+ const objectType = objectSchema.objectType || 'unknown';
113
+ console.log(
114
+ `[DEBUG] [Generate] OBJECT_SCHEMA | objectType=${objectType}\n` +
115
+ JSON.stringify(objectSchema, null, 2)
116
+ );
117
+ }
98
118
  const groups = await _emitGroups({
99
119
  project,
100
120
  objects,
101
121
  relationships,
102
122
  flows,
103
123
  notifications,
124
+ errors,
104
125
  objectGraphServiceTags,
105
126
  relationshipGraphServiceTags,
106
127
  logger: options.logger
@@ -149,6 +170,7 @@ async function _emitGroups({
149
170
  relationships,
150
171
  flows,
151
172
  notifications,
173
+ errors,
152
174
  objectGraphServiceTags,
153
175
  relationshipGraphServiceTags,
154
176
  logger
@@ -161,7 +183,8 @@ async function _emitGroups({
161
183
  findData,
162
184
  resource,
163
185
  coreFunction,
164
- systemText
186
+ systemText,
187
+ errorSchemas
165
188
  ] = await Promise.all([
166
189
  emitCrudApplicationArtifacts({
167
190
  objects,
@@ -196,6 +219,11 @@ async function _emitGroups({
196
219
  relationships,
197
220
  flows,
198
221
  notifications
222
+ }),
223
+ emitErrorSchemas({
224
+ project,
225
+ errors,
226
+ objectGraphServiceTags
199
227
  })
200
228
  ]);
201
229
  const custom = await emitCustomFlowApplicationArtifacts(flows, {
@@ -307,6 +335,11 @@ async function _emitGroups({
307
335
  scope: 'system-text-schemas',
308
336
  managedPaths: systemTextSchemaManagedPaths(),
309
337
  artifacts: systemText
338
+ },
339
+ {
340
+ scope: 'error-schemas',
341
+ managedPaths: errorSchemaManagedPaths(errors),
342
+ artifacts: errorSchemas
310
343
  }
311
344
  ];
312
345
  }
package/test/core.test.js CHANGED
@@ -34,6 +34,19 @@ test('compiles a request and commits only declared relative artifacts', async ()
34
34
  test('rejects invalid generation inputs before writing files', async () => {
35
35
  assert.throws(() => compileProject({}), /rootPath/);
36
36
 
37
+ const corruptPath = await mkdtemp(
38
+ join(tmpdir(), 'generate-service-code-v2-corrupt-yml-')
39
+ );
40
+ await mkdir(join(corruptPath, 'config'), { recursive: true });
41
+ await writeFile(
42
+ join(corruptPath, 'config/serverless.config.yml'),
43
+ 'main_config: [unbalanced brackets:'
44
+ );
45
+ assert.throws(
46
+ () => compileProject({ rootPath: corruptPath }),
47
+ /Failed to read or parse configuration at/
48
+ );
49
+
37
50
  const outputPath = await mkdtemp(
38
51
  join(tmpdir(), 'generate-service-code-v2-invalid-')
39
52
  );
@@ -254,7 +254,7 @@ test('removes only V2-owned custom-flow application artifacts when supported eve
254
254
  await generateCustomFlowApplicationArtifacts(rootPath);
255
255
  await writeFile(
256
256
  join(rootPath, 'app/src/schemas/FlowSchemas/Flows.js'),
257
- "export default [{ flowTag: 'later', event: ['unsupported'] }];\n"
257
+ "export default [];\n"
258
258
  );
259
259
 
260
260
  assert.deepEqual(
@@ -469,6 +469,53 @@ test('emits and removes the trigger-cache artifact suite when triggerFlowTypes i
469
469
  );
470
470
  });
471
471
 
472
+ test('triggerCache entrypoint Cart_Main.js contains correct library import and logic', async () => {
473
+ const rootPath = await createTriggerCacheProject(['OrderCheckout']);
474
+ await generateCustomFlowApplicationArtifacts(rootPath);
475
+
476
+ const source = 'app/src/generatedCode/FlowSchemas/Cart/source';
477
+ const mainContent = await readFile(
478
+ join(rootPath, `${source}/Cart_Main.js`),
479
+ 'utf8'
480
+ );
481
+
482
+ assert.match(
483
+ mainContent,
484
+ /import \{ triggeredCacheSharedLibV2 \} from '@izara_project\/izara-core-library-trigger-cache'/,
485
+ 'should import triggeredCacheSharedLibV2'
486
+ );
487
+ assert.match(
488
+ mainContent,
489
+ /triggeredCacheSharedLibV2\.checkTriggerResetedV2/,
490
+ 'should call checkTriggerResetedV2'
491
+ );
492
+ assert.match(
493
+ mainContent,
494
+ /triggeredCacheSharedLibV2\.checkTriggeredCacheV2/,
495
+ 'should call checkTriggeredCacheV2'
496
+ );
497
+ assert.match(
498
+ mainContent,
499
+ /\/\/\(<beforeCheckTriggeredCache>\)/,
500
+ 'should have beforeCheckTriggeredCache hook'
501
+ );
502
+ assert.match(
503
+ mainContent,
504
+ /\/\/\(<dispatchTriggerFlowHook>\)/,
505
+ 'should have dispatchTriggerFlowHook hook'
506
+ );
507
+ assert.match(
508
+ mainContent,
509
+ /if \(triggeredCacheResult\?\.hasPendingTasks\)/,
510
+ 'should guard dispatch with hasPendingTasks check'
511
+ );
512
+ assert.doesNotMatch(
513
+ mainContent,
514
+ /checkStoredCacheStatus/,
515
+ 'should not contain storedCache logic'
516
+ );
517
+ });
518
+
472
519
  test('uses custom CheckTrigger step if provided by developer in flowSteps', async () => {
473
520
  const rootPath = await mkdtemp(
474
521
  join(tmpdir(), 'generate-service-code-v2-trigger-cache-custom-')
@@ -494,28 +541,77 @@ test('uses custom CheckTrigger step if provided by developer in flowSteps', asyn
494
541
  assert.match(flowYaml, /^CartCheckTriggerCustomStepHdrSqs:/m);
495
542
  });
496
543
 
497
- test('does not emit check trigger-cache artifacts when triggerFlowTypes is empty, null, undefined, or missing', async () => {
544
+ test('uses full {flowTag}{stepName} queue name when stepName starts with flowTag', async () => {
545
+ const rootPath = await createTriggerCacheProject(['OrderCheckout']);
546
+ await writeFile(
547
+ join(rootPath, 'app/src/schemas/FlowSchemas/Cart.js'),
548
+ "export default { flowTag: 'cart', event: ['ownTopic'], statusType: 'triggerCache', triggerFlowTypes: ['OrderCheckout'], objType: { serviceTag: 'Order' }, flowSteps: [{ stepName: 'start' }, { stepName: 'CartCheckX', event: ['extTopic'] }] };\n"
549
+ );
550
+ await generateCustomFlowApplicationArtifacts(rootPath);
551
+ await generateResourceArtifacts(rootPath);
552
+
553
+ const source = 'app/src/generatedCode/FlowSchemas/Cart/source';
554
+ for (const fileName of [
555
+ 'CartCartCheckX_Main.js',
556
+ 'CartCartCheckX_HdrSqs.js'
557
+ ]) {
558
+ const path = join(rootPath, source, fileName);
559
+ await access(path);
560
+ await parseAsEsm(path);
561
+ }
562
+
563
+ const flowYaml = await readFile(
564
+ join(rootPath, 'app/sls_yaml/generatedCode/source/flow-schema.yml'),
565
+ 'utf8'
566
+ );
567
+ assert.match(flowYaml, /^CartCartCheckXHdrSqs:/m);
568
+ assert.match(
569
+ await readFile(join(rootPath, `${source}/CartCartCheckX_HdrSqs.js`), 'utf8'),
570
+ /CartCartCheckXHdrSqs/
571
+ );
572
+
573
+ const resources = await readFile(
574
+ join(
575
+ rootPath,
576
+ 'resource/sls_yaml/generatedCode/source/generated-sns-sqs-custom-flows.yml'
577
+ ),
578
+ 'utf8'
579
+ );
580
+ assert.match(
581
+ resources,
582
+ new RegExp(
583
+ 'QueueName: \\$\\{self:custom\\.iz_resourcePrefix\\}CartCartCheckXHdrSqs'
584
+ )
585
+ );
586
+ });
587
+
588
+ test('rejects when statusType triggerCache has triggerFlowTypes empty, null, undefined, or missing', async () => {
498
589
  for (const emptyTriggerFlowTypes of [[], null, undefined]) {
499
590
  const rootPath = await createTriggerCacheProject(emptyTriggerFlowTypes);
500
- await generateCustomFlowApplicationArtifacts(rootPath);
501
- await generateResourceArtifacts(rootPath);
502
-
503
- const source = 'app/src/generatedCode/FlowSchemas/Cart/source';
504
- await assert.rejects(
505
- readFile(join(rootPath, `${source}/CartCheckTriggerFlows_Main.js`))
506
- );
507
591
  await assert.rejects(
508
- readFile(join(rootPath, `${source}/CartCheckTriggerFlows_HdrSqs.js`))
592
+ generateCustomFlowApplicationArtifacts(rootPath),
593
+ /FlowSchema validation error.*triggerCache.*requires a non-empty 'triggerFlowTypes' array/
509
594
  );
510
-
511
- const flowYaml = await readFile(
512
- join(rootPath, 'app/sls_yaml/generatedCode/source/flow-schema.yml'),
513
- 'utf8'
514
- );
515
- assert.doesNotMatch(flowYaml, /CartCheckTriggerFlowsHdrSqs/);
516
595
  }
517
596
  });
518
597
 
598
+ test('rejects when statusType storedCache cannot resolve DynamoDB table from objType', async () => {
599
+ const rootPath = await mkdtemp(
600
+ join(tmpdir(), 'generate-service-code-v2-stored-cache-err-')
601
+ );
602
+ roots.add(rootPath);
603
+ const schemaRoot = join(rootPath, 'app/src/schemas/FlowSchemas');
604
+ await mkdir(schemaRoot, { recursive: true });
605
+ await writeFile(
606
+ join(schemaRoot, 'CacheFlow.js'),
607
+ "export default { flowTag: 'cacheFlow', event: ['ownTopic'], statusType: 'storedCache', objType: { objectType: 'missingObj' }, flowSteps: [{ stepName: 'Start' }] };\n"
608
+ );
609
+ await assert.rejects(
610
+ generateCustomFlowApplicationArtifacts(rootPath),
611
+ /FlowSchema validation error.*storedCache.*cannot resolve DynamoDB tableName/
612
+ );
613
+ });
614
+
519
615
  test('rejects an EventBridge schedule without a deployable name and rate', () => {
520
616
  assert.throws(
521
617
  () =>
@@ -565,7 +661,7 @@ export default [
565
661
  { ...base, flowTag: 'cache', event: ['ownTopic'], statusType: 'storedCache', objType: { objectType: 'order', serviceTag: 'Current' } },
566
662
  { ...base, flowTag: 'mixed', event: ['ownTopic', 'extTopic'] },
567
663
  { ...base, flowTag: 'generated', event: ['ownTopic'], generatedCodeConfig: { generatedCodeTag: 'create' } },
568
- { ...base, flowTag: 'upload', event: ['s3'] }
664
+ { ...base, flowTag: 'upload', event: ['s3'], bucketName: 'UploadBucket' }
569
665
  ];
570
666
  `
571
667
  );
@@ -1271,3 +1367,49 @@ test('emits handler and YAML for flow with event generateCode and invocationType
1271
1367
  assert.match(yaml, /GenSyncHdrInv:/);
1272
1368
  });
1273
1369
 
1370
+ test('rejects FlowSchema with event storedCache at loader', async () => {
1371
+ const rootPath = await createProject();
1372
+ await writeFile(
1373
+ join(rootPath, 'app/src/schemas/FlowSchemas/BadEvent.js'),
1374
+ `export default {
1375
+ flowTag: 'badEvent',
1376
+ event: ['storedCache'],
1377
+ statusType: 'storedCache',
1378
+ objType: { objectType: 'order' },
1379
+ flowSteps: [{ stepName: 'Start' }]
1380
+ };\n`
1381
+ );
1382
+
1383
+ await assert.rejects(
1384
+ () => generateCustomFlowApplicationArtifacts(rootPath),
1385
+ /Flow 'badEvent' event\[0\] 'storedCache' is invalid\. Must be one of/
1386
+ );
1387
+ });
1388
+
1389
+ test('emits early return cacheMain on cache hit in FlowEndpoint_Main for storedCache', async () => {
1390
+ const rootPath = await createProject();
1391
+ await writeFile(
1392
+ join(rootPath, 'app/src/schemas/FlowSchemas/CacheFlow.js'),
1393
+ `export default {
1394
+ flowTag: 'cacheOrder',
1395
+ event: ['ownTopic'],
1396
+ statusType: 'storedCache',
1397
+ objType: { objectType: 'order', serviceTag: 'Current' },
1398
+ flowSteps: [{ stepName: 'Start' }]
1399
+ };\n`
1400
+ );
1401
+
1402
+ await generateCustomFlowApplicationArtifacts(rootPath);
1403
+
1404
+ const mainPath = join(
1405
+ rootPath,
1406
+ 'app/src/generatedCode/FlowSchemas/CacheOrder/source/CacheOrder_Main.js'
1407
+ );
1408
+ const mainContent = await readFile(mainPath, 'utf8');
1409
+ assert.match(mainContent, /checkStoredCacheStatus/);
1410
+ assert.match(mainContent, /if \(cacheMainStatus === 'complete'\) \{/);
1411
+ assert.match(mainContent, /return cacheMain;/);
1412
+ await parseAsEsm(mainPath);
1413
+ });
1414
+
1415
+