@izara_project/izara-core-generate-service-code 1.0.95 → 1.0.97

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 (210) hide show
  1. package/index.js +2 -2
  2. package/package.json +2 -1
  3. package/src/compile/loadSchemas.js +17 -318
  4. package/src/compile/loadSchemasRemote.js +195 -0
  5. package/src/compile/schemaValidatorSetup.js +143 -0
  6. package/src/emit/{crud → application/crud}/emitCrudApplicationArtifacts.js +2 -2
  7. package/src/emit/{crud → application/crud}/generateCrudApplicationArtifacts.js +2 -2
  8. package/src/emit/{crud → application/crud}/generateDynamicCrudFlowSchemas.js +2 -2
  9. package/src/emit/{custom → application/custom}/customFlowS3.js +1 -1
  10. package/src/emit/{custom → application/custom}/customFlowSteps.js +34 -5
  11. package/src/emit/{custom → application/custom}/customFlowTemplates.js +1 -1
  12. package/src/emit/{custom → application/custom}/emitCustomFlowApplicationArtifacts.js +1 -1
  13. package/src/emit/{custom → application/custom}/generateCustomFlowApplicationArtifacts.js +2 -2
  14. package/src/emit/{custom → application/custom}/templates/FlowEndpoint_Main.ejs +66 -4
  15. package/src/emit/{custom → application/custom}/templates/FlowStep_Main.ejs +27 -0
  16. package/src/emit/{rbac → application/rbac}/emitRbacApplicationArtifacts.js +2 -2
  17. package/src/emit/{rbac → application/rbac}/generateCreateTargetRoleHandler.js +2 -2
  18. package/src/emit/{rbac → application/rbac}/generateDynamicRbacFlowSchemas.js +2 -2
  19. package/src/emit/{relationship → application/relationship}/emitRelationshipApplicationArtifacts.js +3 -3
  20. package/src/emit/{relationship → application/relationship}/generateDynamicRelationshipFlowSchemas.js +2 -2
  21. package/src/emit/{relationship → application/relationship}/generateRelationshipApplicationArtifacts.js +2 -2
  22. package/src/emit/{system → application/system}/emitSystemFindDataArtifacts.js +1 -1
  23. package/src/emit/{resource → infrastructure/resources}/generateResourceArtifacts.js +2 -2
  24. package/src/emit/{resource → infrastructure/resources}/iamResourceArtifacts.js +2 -2
  25. package/src/emit/{resource → infrastructure/resources}/resourceState.js +4 -4
  26. package/src/emit/{attributeTree → schemas/attributeTree}/emitAttributeTreeSchemas.js +29 -48
  27. package/src/emit/schemas/attributeTree/emitAttributeTreeTargetSchemas.js +153 -0
  28. package/src/emit/schemas/attributeTree/resolveTargetServicePath.js +111 -0
  29. package/src/emit/schemas/ledger/emitLedgerSchemas.js +370 -0
  30. package/src/emit/{systemText → schemas/systemText}/emitSystemTextSchemas.js +1 -1
  31. package/src/generate.js +81 -240
  32. package/src/{generateIntTest.js → intTest/generateIntTest.js} +2 -2
  33. package/src/{generateResourceIntTest.js → intTest/generateResourceIntTest.js} +2 -2
  34. package/src/plan/domainRegistry.js +271 -0
  35. package/test/helpers/testProject.js +127 -0
  36. package/test/helpers/testProject.test.js +57 -0
  37. package/test/{core.test.js → integration/core.test.js} +3 -3
  38. package/test/{graphDrivenFlowSchema.test.js → integration/graphDrivenFlowSchema.test.js} +1 -1
  39. package/test/{intTestApi.test.js → integration/intTestApi.test.js} +1 -1
  40. package/test/{publicApi.test.js → integration/publicApi.test.js} +1 -1
  41. package/test/{createTargetRoleHandler.test.js → unit/application/createTargetRoleHandler.test.js} +1 -1
  42. package/test/{crudApplicationArtifacts.test.js → unit/application/crudApplicationArtifacts.test.js} +1 -1
  43. package/test/{customFlowApplicationArtifacts.test.js → unit/application/customFlowApplicationArtifacts.test.js} +139 -9
  44. package/test/{relationshipApplicationArtifacts.test.js → unit/application/relationshipApplicationArtifacts.test.js} +1 -1
  45. package/test/{systemFindDataArtifacts.test.js → unit/application/systemFindDataArtifacts.test.js} +1 -1
  46. package/test/{functionYamlArtifact.test.js → unit/infrastructure/functionYamlArtifact.test.js} +1 -1
  47. package/test/{resourceArtifacts.test.js → unit/infrastructure/resourceArtifacts.test.js} +1 -1
  48. package/test/{attributeTreeSchemas.test.js → unit/schemas/attributeTreeSchemas.test.js} +127 -50
  49. package/test/{dynamicCrudFlowSchemas.test.js → unit/schemas/dynamicCrudFlowSchemas.test.js} +2 -2
  50. package/test/{dynamicRbacFlowSchemas.test.js → unit/schemas/dynamicRbacFlowSchemas.test.js} +1 -1
  51. package/test/{dynamicRelationshipFlowSchemas.test.js → unit/schemas/dynamicRelationshipFlowSchemas.test.js} +11 -1
  52. package/test/{errorSchemas.test.js → unit/schemas/errorSchemas.test.js} +2 -2
  53. package/test/unit/schemas/ledgerSchemas.test.js +263 -0
  54. package/test/{systemTextSchemas.test.js → unit/schemas/systemTextSchemas.test.js} +24 -36
  55. package/src/emit/crud/loadLocalSchemaArrays.js +0 -4
  56. /package/src/emit/{coreFunction → application/coreFunction}/emitCoreFunctionArtifacts.js +0 -0
  57. /package/src/emit/{coreFunction → application/coreFunction}/templates/CoreFunction_Yaml.ejs +0 -0
  58. /package/src/emit/{coreFunction → application/coreFunction}/templates/CoreResource_Yaml.ejs +0 -0
  59. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataDynamo_HdrInv.ejs +0 -0
  60. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataDynamo_Main.ejs +0 -0
  61. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataGraphData_HdrInv.ejs +0 -0
  62. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataGraphData_Main.ejs +0 -0
  63. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataGraphSchema_HdrInv.ejs +0 -0
  64. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataGraphSchema_Main.ejs +0 -0
  65. /package/src/emit/{coreFunction → application/coreFunction}/templates/GeneratedGraphNodeSchemas.ejs +0 -0
  66. /package/src/emit/{coreFunction → application/coreFunction}/templates/GeneratedGraphRelSchemas.ejs +0 -0
  67. /package/src/emit/{coreFunction → application/coreFunction}/templates/GeneratedTableConfigs.ejs +0 -0
  68. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupConfig.ejs +0 -0
  69. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner.ejs +0 -0
  70. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_initialSetup.ejs +0 -0
  71. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_seedDynamo.ejs +0 -0
  72. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_seedGraph.ejs +0 -0
  73. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_seedRemove.ejs +0 -0
  74. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_uploadSchema.ejs +0 -0
  75. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetup_HdrInv.ejs +0 -0
  76. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetup_Main.ejs +0 -0
  77. /package/src/emit/{coreFunction → application/coreFunction}/templates/RemoveSeedDataDynamo_HdrInv.ejs +0 -0
  78. /package/src/emit/{coreFunction → application/coreFunction}/templates/RemoveSeedDataDynamo_Main.ejs +0 -0
  79. /package/src/emit/{coreFunction → application/coreFunction}/templates/UploadSchema_HdrInv.ejs +0 -0
  80. /package/src/emit/{coreFunction → application/coreFunction}/templates/UploadSchema_Main.ejs +0 -0
  81. /package/src/emit/{crud → application/crud}/crudActionPlan.js +0 -0
  82. /package/src/emit/{crud → application/crud}/dynamicCrudFlowSchemaTemplate.js +0 -0
  83. /package/src/emit/{crud → application/crud}/emitDynamicCrudFlowSchemas.js +0 -0
  84. /package/src/emit/{crud → application/crud}/templates/CreateAfterHookCallback_Main.ejs +0 -0
  85. /package/src/emit/{crud → application/crud}/templates/CreateBeforeHookCallback_Main.ejs +0 -0
  86. /package/src/emit/{crud → application/crud}/templates/CreateComplete_Main.ejs +0 -0
  87. /package/src/emit/{crud → application/crud}/templates/CreateConfirmComplete_Main.ejs +0 -0
  88. /package/src/emit/{crud → application/crud}/templates/CreateEndpoint_Main.ejs +0 -0
  89. /package/src/emit/{crud → application/crud}/templates/CreateLogicalLib.ejs +0 -0
  90. /package/src/emit/{crud → application/crud}/templates/CreateNodeCallback_Main.ejs +0 -0
  91. /package/src/emit/{crud → application/crud}/templates/DeleteAfterHookCallback_Main.ejs +0 -0
  92. /package/src/emit/{crud → application/crud}/templates/DeleteBeforeHookCallback_Main.ejs +0 -0
  93. /package/src/emit/{crud → application/crud}/templates/DeleteComplete_Main.ejs +0 -0
  94. /package/src/emit/{crud → application/crud}/templates/DeleteEndpoint_Main.ejs +0 -0
  95. /package/src/emit/{crud → application/crud}/templates/DeleteLogicalLib.ejs +0 -0
  96. /package/src/emit/{crud → application/crud}/templates/FlowEndpointRbacCallback_Main.ejs +0 -0
  97. /package/src/emit/{crud → application/crud}/templates/FlowEndpoint_HdrWbs.ejs +0 -0
  98. /package/src/emit/{crud → application/crud}/templates/FlowMain_Wbs.ejs +0 -0
  99. /package/src/emit/{crud → application/crud}/templates/GetEndpoint_Main.ejs +0 -0
  100. /package/src/emit/{crud → application/crud}/templates/GetRangeEndpoint_Main.ejs +0 -0
  101. /package/src/emit/{crud → application/crud}/templates/UpdateAfterHookCallback_Main.ejs +0 -0
  102. /package/src/emit/{crud → application/crud}/templates/UpdateBeforeHookCallback_Main.ejs +0 -0
  103. /package/src/emit/{crud → application/crud}/templates/UpdateComplete_Main.ejs +0 -0
  104. /package/src/emit/{crud → application/crud}/templates/UpdateEndpoint_Main.ejs +0 -0
  105. /package/src/emit/{crud → application/crud}/templates/UpdateLogicalLib.ejs +0 -0
  106. /package/src/emit/{custom → application/custom}/customFlowPaths.js +0 -0
  107. /package/src/emit/{custom → application/custom}/customFlows.js +0 -0
  108. /package/src/emit/{custom → application/custom}/templates/FlowEndpointRbacCallback_Main.ejs +0 -0
  109. /package/src/emit/{custom → application/custom}/templates/s3/ConfirmReserved_HdrSqs.ejs +0 -0
  110. /package/src/emit/{custom → application/custom}/templates/s3/ConfirmReserved_Main.ejs +0 -0
  111. /package/src/emit/{custom → application/custom}/templates/s3/CreateObject_HdrWbs.ejs +0 -0
  112. /package/src/emit/{custom → application/custom}/templates/s3/CreateObject_Main.ejs +0 -0
  113. /package/src/emit/{custom → application/custom}/templates/s3/CreatePreSignUrl_HdrSqs.ejs +0 -0
  114. /package/src/emit/{custom → application/custom}/templates/s3/CreatePreSignUrl_Main.ejs +0 -0
  115. /package/src/emit/{custom → application/custom}/templates/s3/FlowHandler_HdrS3.ejs +0 -0
  116. /package/src/emit/{custom → application/custom}/templates/s3/ProcessS3File_Main.ejs +0 -0
  117. /package/src/emit/{custom → application/custom}/templates/s3/ReservedLimit_HdrSqs.ejs +0 -0
  118. /package/src/emit/{custom → application/custom}/templates/s3/ReservedLimit_Main.ejs +0 -0
  119. /package/src/emit/{custom → application/custom}/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +0 -0
  120. /package/src/emit/{custom → application/custom}/templates/triggerCache/CheckTriggerCache_Main.ejs +0 -0
  121. /package/src/emit/{custom → application/custom}/templates/triggerCache/TriggerCacheComplete_Main.ejs +0 -0
  122. /package/src/emit/{custom → application/custom}/templates/triggerCache/TriggerCache_Main.ejs +0 -0
  123. /package/src/emit/{rbac → application/rbac}/emitDynamicRbacFlowSchemas.js +0 -0
  124. /package/src/emit/{rbac → application/rbac}/rbacFlowTag.js +0 -0
  125. /package/src/emit/{rbac → application/rbac}/templates/CancelUsage_Main.ejs +0 -0
  126. /package/src/emit/{rbac → application/rbac}/templates/ConfirmUsage_Main.ejs +0 -0
  127. /package/src/emit/{rbac → application/rbac}/templates/CreateTargetRole_HdrSqs.ejs +0 -0
  128. /package/src/emit/{rbac → application/rbac}/templates/CreateTargetRole_Main.ejs +0 -0
  129. /package/src/emit/{rbac → application/rbac}/templates/DeleteTargetRole_Main.ejs +0 -0
  130. /package/src/emit/{rbac → application/rbac}/templates/DynamicRbacFlowSchema.ejs +0 -0
  131. /package/src/emit/{rbac → application/rbac}/templates/GetMyPermissions_Main.ejs +0 -0
  132. /package/src/emit/{rbac → application/rbac}/templates/GetTargetRole_Main.ejs +0 -0
  133. /package/src/emit/{rbac → application/rbac}/templates/ListRbac_HdrApi.ejs +0 -0
  134. /package/src/emit/{rbac → application/rbac}/templates/ListRbac_HdrSqs.ejs +0 -0
  135. /package/src/emit/{rbac → application/rbac}/templates/ListRbac_Main.ejs +0 -0
  136. /package/src/emit/{rbac → application/rbac}/templates/RbacMutation_Main.ejs +0 -0
  137. /package/src/emit/{rbac → application/rbac}/templates/ReservedDynamicUsage_Main.ejs +0 -0
  138. /package/src/emit/{rbac → application/rbac}/templates/UpdateTargetRole_Main.ejs +0 -0
  139. /package/src/emit/{rbac → application/rbac}/templates/UserRbacFlow_HdrSqs.ejs +0 -0
  140. /package/src/emit/{rbac → application/rbac}/templates/UserRbacFlow_Main.ejs +0 -0
  141. /package/src/emit/{rbac → application/rbac}/templates/UserRoleMutation_Main.ejs +0 -0
  142. /package/src/emit/{relationship → application/relationship}/emitDynamicRelationshipFlowSchemas.js +0 -0
  143. /package/src/emit/{relationship → application/relationship}/templates/ChangeRelationshipComplete_HdrSqs.ejs +0 -0
  144. /package/src/emit/{relationship → application/relationship}/templates/ChangeRelationshipComplete_Main.ejs +0 -0
  145. /package/src/emit/{relationship → application/relationship}/templates/ChangeRelationship_Main.ejs +0 -0
  146. /package/src/emit/{relationship → application/relationship}/templates/CreateRelationshipComplete_HdrSqs.ejs +0 -0
  147. /package/src/emit/{relationship → application/relationship}/templates/CreateRelationshipComplete_Main.ejs +0 -0
  148. /package/src/emit/{relationship → application/relationship}/templates/CreateRelationship_Main.ejs +0 -0
  149. /package/src/emit/{relationship → application/relationship}/templates/DeleteRelationshipComplete_HdrSqs.ejs +0 -0
  150. /package/src/emit/{relationship → application/relationship}/templates/DeleteRelationshipComplete_Main.ejs +0 -0
  151. /package/src/emit/{relationship → application/relationship}/templates/DeleteRelationship_Main.ejs +0 -0
  152. /package/src/emit/{relationship → application/relationship}/templates/GetRelationshipComplete_HdrSqs.ejs +0 -0
  153. /package/src/emit/{relationship → application/relationship}/templates/GetRelationshipComplete_Main.ejs +0 -0
  154. /package/src/emit/{relationship → application/relationship}/templates/GetRelationship_Main.ejs +0 -0
  155. /package/src/emit/{relationship → application/relationship}/templates/MoveRelationshipComplete_HdrSqs.ejs +0 -0
  156. /package/src/emit/{relationship → application/relationship}/templates/MoveRelationshipComplete_Main.ejs +0 -0
  157. /package/src/emit/{relationship → application/relationship}/templates/MoveRelationship_Main.ejs +0 -0
  158. /package/src/emit/{relationship → application/relationship}/templates/UpdateRelationshipComplete_HdrSqs.ejs +0 -0
  159. /package/src/emit/{relationship → application/relationship}/templates/UpdateRelationshipComplete_Main.ejs +0 -0
  160. /package/src/emit/{relationship → application/relationship}/templates/UpdateRelationship_Main.ejs +0 -0
  161. /package/src/emit/{system → application/system}/emitSystemWebSocketArtifacts.js +0 -0
  162. /package/src/emit/{system → application/system}/templates/RegisterComplete_HdrSqs.ejs +0 -0
  163. /package/src/emit/{system → application/system}/templates/RegisterComplete_Main.ejs +0 -0
  164. /package/src/emit/{system → application/system}/templates/RegisterComplete_Yaml.ejs +0 -0
  165. /package/src/emit/{system → application/system}/templates/RegisterWbs_Yaml.ejs +0 -0
  166. /package/src/emit/{system → application/system}/templates/Register_HdrWbs.ejs +0 -0
  167. /package/src/emit/{system → application/system}/templates/Register_Main.ejs +0 -0
  168. /package/src/emit/{system → application/system}/templates/WebSocketComplete_HdrSqs.ejs +0 -0
  169. /package/src/emit/{system → application/system}/templates/WebSocketComplete_Main.ejs +0 -0
  170. /package/src/emit/{system → application/system}/templates/WebSocketComplete_Yaml.ejs +0 -0
  171. /package/src/emit/{system → application/system}/templates/WebSocketConnect.ejs +0 -0
  172. /package/src/emit/{system → application/system}/templates/WebSocketConnect_Yaml.ejs +0 -0
  173. /package/src/emit/{function → infrastructure/functions}/functionYamlArtifact.js +0 -0
  174. /package/src/emit/{function → infrastructure/functions}/templates/ApiFunction_Yaml.ejs +0 -0
  175. /package/src/emit/{function → infrastructure/functions}/templates/EventBridgeFunction_Yaml.ejs +0 -0
  176. /package/src/emit/{function → infrastructure/functions}/templates/InvFunction_Yaml.ejs +0 -0
  177. /package/src/emit/{function → infrastructure/functions}/templates/S3Function_Yaml.ejs +0 -0
  178. /package/src/emit/{function → infrastructure/functions}/templates/SqsFunction_Yaml.ejs +0 -0
  179. /package/src/emit/{function → infrastructure/functions}/templates/WbsFunction_Yaml.ejs +0 -0
  180. /package/src/emit/{resource → infrastructure/resources}/dynamoResourceArtifacts.js +0 -0
  181. /package/src/emit/{resource → infrastructure/resources}/emitResourceArtifacts.js +0 -0
  182. /package/src/emit/{resource → infrastructure/resources}/resourceTemplate.js +0 -0
  183. /package/src/emit/{resource → infrastructure/resources}/s3ResourceArtifacts.js +0 -0
  184. /package/src/emit/{resource → infrastructure/resources}/sqsResourceArtifacts.js +0 -0
  185. /package/src/emit/{resource → infrastructure/resources}/templates/DynamoDBTable_Yaml.ejs +0 -0
  186. /package/src/emit/{resource → infrastructure/resources}/templates/FlowOut_Yaml.ejs +0 -0
  187. /package/src/emit/{resource → infrastructure/resources}/templates/GeneratedLambdaRoleServiceConfig.ejs +0 -0
  188. /package/src/emit/{resource → infrastructure/resources}/templates/ResourceSqsYaml.ejs +0 -0
  189. /package/src/emit/{resource → infrastructure/resources}/templates/ResourceYaml.ejs +0 -0
  190. /package/src/emit/{resource → infrastructure/resources}/templates/S3Bucket_Yaml.ejs +0 -0
  191. /package/src/emit/{resource → infrastructure/resources}/templates/S3Subscription_Yaml.ejs +0 -0
  192. /package/src/emit/{resource → infrastructure/resources}/templates/SharedResource_Yaml.ejs +0 -0
  193. /package/src/emit/{resource → infrastructure/resources}/templates/SystemDynamoDB_Yaml.ejs +0 -0
  194. /package/src/emit/{resource → infrastructure/resources}/templates/WebSocketSubscription_Yaml.ejs +0 -0
  195. /package/src/emit/{error → schemas/error}/emitErrorSchemas.js +0 -0
  196. /package/src/emit/{error → schemas/error}/templates/errorSchema.ejs +0 -0
  197. /package/src/emit/{systemText → schemas/systemText}/templates/SystemTextSchemas.ejs +0 -0
  198. /package/src/{generateResources/IntTest → intTest/generators}/consts.js +0 -0
  199. /package/src/{generateResources/IntTest → intTest/generators}/generateResources/generateResources.js +0 -0
  200. /package/src/{generateResources/IntTest → intTest/generators}/generateResources/templateResources.ejs +0 -0
  201. /package/src/{generateResources/IntTest → intTest/generators}/generateTests/events/events.js +0 -0
  202. /package/src/{generateResources/IntTest → intTest/generators}/generateTests/events/templateEvents.ejs +0 -0
  203. /package/src/{generateResources/IntTest → intTest/generators}/generateTests/generateTemplate.js +0 -0
  204. /package/src/{generateResources/IntTest → intTest/generators}/generateTests/pathIntTest/pathIntTest.js +0 -0
  205. /package/src/{generateResources/IntTest → intTest/generators}/generateTests/pathIntTest/template.ejs +0 -0
  206. /package/src/{generateResources/IntTest → intTest/generators}/generateTests/tests/templateTests.ejs +0 -0
  207. /package/src/{generateResources/IntTest → intTest/generators}/generateTests/tests/tests.js +0 -0
  208. /package/src/{generateResources/IntTest → intTest/generators}/libs/IntTestGenerateLib.js +0 -0
  209. /package/src/{generateResources/IntTest → intTest/generators}/upload/uploadIntTest.js +0 -0
  210. /package/src/{intTestGeneratorShared.js → intTest/intTestGeneratorShared.js} +0 -0
@@ -0,0 +1,127 @@
1
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { dirname, join } from 'node:path';
4
+
5
+ const trackedRoots = new Set();
6
+
7
+ /**
8
+ * Creates a temporary project directory with standard Izara service structure.
9
+ *
10
+ * @param {Object} [options]
11
+ * @param {string} [options.rootPath] - Existing root path to re-use
12
+ * @param {string} [options.prefix] - Temp folder prefix (default: 'izara-test-')
13
+ * @param {string} [options.serviceName] - Service name in config
14
+ * @param {string} [options.serviceTag] - Custom serviceTag in config
15
+ * @param {string} [options.serverlessConfig] - Custom serverless.config.yml content
16
+ * @param {Object} [options.schemas] - Schemas map e.g. { ObjectSchemas: { 'Order.js': '...' } }
17
+ * @returns {Promise<string>} The project root path
18
+ */
19
+ export async function createTestProject({
20
+ rootPath: existingRoot,
21
+ prefix = 'izara-test-',
22
+ serviceName = 'TestService',
23
+ serviceTag = 'TestService',
24
+ serverlessConfig,
25
+ schemas = {}
26
+ } = {}) {
27
+ let rootPath = existingRoot;
28
+ if (!rootPath) {
29
+ rootPath = await mkdtemp(join(tmpdir(), prefix));
30
+ }
31
+ trackedRoots.add(rootPath);
32
+
33
+ const schemaRoot = join(rootPath, 'app/src/schemas');
34
+ await mkdir(join(schemaRoot, 'ObjectSchemas'), { recursive: true });
35
+ await mkdir(join(schemaRoot, 'RelationshipSchemas'), { recursive: true });
36
+ await mkdir(join(schemaRoot, 'FlowSchemas'), { recursive: true });
37
+ await mkdir(join(schemaRoot, 'ErrorSchemas'), { recursive: true });
38
+ await mkdir(join(rootPath, 'config'), { recursive: true });
39
+
40
+ let configContent = serverlessConfig;
41
+ if (!configContent) {
42
+ configContent =
43
+ `service: ${serviceName}\n` +
44
+ `custom:\n` +
45
+ ` serviceTag: ${serviceTag}\n`;
46
+ }
47
+ await writeFile(
48
+ join(rootPath, 'config/serverless.config.yml'),
49
+ configContent,
50
+ 'utf8'
51
+ );
52
+
53
+ const schemaCategories = [
54
+ 'ObjectSchemas',
55
+ 'RelationshipSchemas',
56
+ 'FlowSchemas',
57
+ 'ErrorSchemas'
58
+ ];
59
+
60
+ for (const category of schemaCategories) {
61
+ const files = schemas[category];
62
+ if (files && typeof files === 'object') {
63
+ for (const [filename, content] of Object.entries(files)) {
64
+ await writeProjectFile(
65
+ rootPath,
66
+ join('app/src/schemas', category, filename),
67
+ content
68
+ );
69
+ }
70
+ }
71
+ }
72
+
73
+ for (const [key, content] of Object.entries(schemas)) {
74
+ if (!schemaCategories.includes(key) && typeof content === 'string') {
75
+ await writeProjectFile(
76
+ rootPath,
77
+ join('app/src/schemas', key),
78
+ content
79
+ );
80
+ }
81
+ }
82
+
83
+ return rootPath;
84
+ }
85
+
86
+ /**
87
+ * Tracks an external directory path for cleanupTestProjects.
88
+ *
89
+ * @param {string} rootPath - Directory path to track
90
+ * @returns {string} The tracked path
91
+ */
92
+ export function trackTestProject(rootPath) {
93
+ trackedRoots.add(rootPath);
94
+ return rootPath;
95
+ }
96
+
97
+ /**
98
+ * Writes a file relative to the project root.
99
+ */
100
+ export async function writeProjectFile(rootPath, relativePath, content) {
101
+ const targetPath = join(rootPath, relativePath);
102
+ await mkdir(dirname(targetPath), { recursive: true });
103
+ await writeFile(targetPath, content, 'utf8');
104
+ return targetPath;
105
+ }
106
+
107
+ /**
108
+ * Reads a file relative to the project root.
109
+ */
110
+ export async function readProjectFile(rootPath, relativePath) {
111
+ return await readFile(join(rootPath, relativePath), 'utf8');
112
+ }
113
+
114
+ /**
115
+ * Cleans up all tracked temporary project directories.
116
+ */
117
+ export async function cleanupTestProjects() {
118
+ const roots = Array.from(trackedRoots);
119
+ trackedRoots.clear();
120
+ for (const root of roots) {
121
+ try {
122
+ await rm(root, { recursive: true, force: true });
123
+ } catch (err) {
124
+ // Ignore cleanup errors
125
+ }
126
+ }
127
+ }
@@ -0,0 +1,57 @@
1
+ import assert from 'node:assert/strict';
2
+ import { stat } from 'node:fs/promises';
3
+ import test, { after } from 'node:test';
4
+
5
+ import {
6
+ createTestProject,
7
+ writeProjectFile,
8
+ readProjectFile,
9
+ cleanupTestProjects
10
+ } from './testProject.js';
11
+
12
+ after(async () => {
13
+ await cleanupTestProjects();
14
+ });
15
+
16
+ test('createTestProject creates directories and serverless config', async () => {
17
+ const rootPath = await createTestProject({
18
+ serviceName: 'DemoService',
19
+ serviceTag: 'DemoTag'
20
+ });
21
+
22
+ const config = await readProjectFile(
23
+ rootPath,
24
+ 'config/serverless.config.yml'
25
+ );
26
+ assert.match(config, /service: DemoService/);
27
+ assert.match(config, /serviceTag: DemoTag/);
28
+
29
+ const customFile = 'app/src/schemas/ObjectSchemas/Demo.js';
30
+ await writeProjectFile(
31
+ rootPath,
32
+ customFile,
33
+ 'export default [{ objectType: "demo" }];'
34
+ );
35
+
36
+ const readBack = await readProjectFile(rootPath, customFile);
37
+ assert.match(readBack, /objectType: "demo"/);
38
+
39
+ const stats = await stat(rootPath);
40
+ assert.equal(stats.isDirectory(), true);
41
+ });
42
+
43
+ test('createTestProject populates initial schemas map', async () => {
44
+ const rootPath = await createTestProject({
45
+ schemas: {
46
+ ObjectSchemas: {
47
+ 'Item.js': 'export default [{ objectType: "item" }];'
48
+ }
49
+ }
50
+ });
51
+
52
+ const content = await readProjectFile(
53
+ rootPath,
54
+ 'app/src/schemas/ObjectSchemas/Item.js'
55
+ );
56
+ assert.match(content, /objectType: "item"/);
57
+ });
@@ -11,9 +11,9 @@ import { tmpdir } from 'node:os';
11
11
  import { dirname, join } from 'node:path';
12
12
  import test from 'node:test';
13
13
 
14
- import { buildGenerationPlan } from '../src/plan/buildGenerationPlan.js';
15
- import { commitArtifacts } from '../src/output/commitArtifacts.js';
16
- import { compileProject } from '../src/compile/compileProject.js';
14
+ import { buildGenerationPlan } from '../../src/plan/buildGenerationPlan.js';
15
+ import { commitArtifacts } from '../../src/output/commitArtifacts.js';
16
+ import { compileProject } from '../../src/compile/compileProject.js';
17
17
 
18
18
  test('compiles a request and commits only declared relative artifacts', async () => {
19
19
  const outputPath = await mkdtemp(join(tmpdir(), 'generate-service-code-v2-'));
@@ -1,6 +1,6 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { validateFlowSchema } from '../src/compile/flowValidator.js';
3
+ import { validateFlowSchema } from '../../src/compile/flowValidator.js';
4
4
 
5
5
  test('validateFlowSchema passes for valid Graph-Driven FlowSchema', () => {
6
6
  const validSchema = {
@@ -4,7 +4,7 @@ import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import test from 'node:test';
6
6
 
7
- import { generateIntTest, generateResourceIntTest } from '../index.js';
7
+ import { generateIntTest, generateResourceIntTest } from '../../index.js';
8
8
 
9
9
  test('exports IntTest generators and requires a service tag', async () => {
10
10
  const rootPath = await mkdtemp(
@@ -7,7 +7,7 @@ import test from 'node:test';
7
7
 
8
8
  process.env.NODE_ENV = 'test';
9
9
 
10
- import * as publicApi from '../index.js';
10
+ import * as publicApi from '../../index.js';
11
11
 
12
12
  const { generate } = publicApi;
13
13
 
@@ -4,7 +4,7 @@ import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import test, { after } from 'node:test';
6
6
 
7
- import { generateCreateTargetRoleHandler } from '../src/emit/rbac/generateCreateTargetRoleHandler.js';
7
+ import { generateCreateTargetRoleHandler } from '../../../src/emit/application/rbac/generateCreateTargetRoleHandler.js';
8
8
 
9
9
  const roots = new Set();
10
10
  const OWN_TOPIC_FLOWS = [
@@ -7,7 +7,7 @@ import test, { after } from 'node:test';
7
7
 
8
8
  process.env.NODE_ENV = 'test';
9
9
 
10
- import { generateCrudApplicationArtifacts } from '../src/emit/crud/generateCrudApplicationArtifacts.js';
10
+ import { generateCrudApplicationArtifacts } from '../../../src/emit/application/crud/generateCrudApplicationArtifacts.js';
11
11
 
12
12
  const roots = new Set();
13
13
  after(() =>
@@ -13,10 +13,10 @@ import { dirname, join, resolve } from 'node:path';
13
13
  import { promisify } from 'node:util';
14
14
  import test, { after } from 'node:test';
15
15
 
16
- import { generate } from '../src/generate.js';
17
- import { generateCustomFlowApplicationArtifacts } from '../src/emit/custom/generateCustomFlowApplicationArtifacts.js';
18
- import { generateResourceArtifacts } from '../src/emit/resource/generateResourceArtifacts.js';
19
- import { renderEventBridgeFunctionYaml } from '../src/emit/function/functionYamlArtifact.js';
16
+ import { generate } from '../../../src/generate.js';
17
+ import { generateCustomFlowApplicationArtifacts } from '../../../src/emit/application/custom/generateCustomFlowApplicationArtifacts.js';
18
+ import { generateResourceArtifacts } from '../../../src/emit/infrastructure/resources/generateResourceArtifacts.js';
19
+ import { renderEventBridgeFunctionYaml } from '../../../src/emit/infrastructure/functions/functionYamlArtifact.js';
20
20
 
21
21
  const roots = new Set();
22
22
  const execFileAsync = promisify(execFile);
@@ -865,7 +865,7 @@ test(
865
865
  );
866
866
 
867
867
  test('renders nextSteps IAM permissions in InitialSetupConfig', async () => {
868
- const { generate } = await import('../src/generate.js');
868
+ const { generate } = await import('../../../src/generate.js');
869
869
  const rootPath = await mkdtemp(
870
870
  join(tmpdir(), 'generate-service-code-v2-nextsteps-')
871
871
  );
@@ -935,7 +935,7 @@ test('renders nextSteps IAM permissions in InitialSetupConfig', async () => {
935
935
  });
936
936
 
937
937
  test('registers SQS queue, SNS subscription, and SNS out topic for custom flowSchema with outputTopic set to true', async () => {
938
- const { generate } = await import('../src/generate.js');
938
+ const { generate } = await import('../../../src/generate.js');
939
939
  const rootPath = await mkdtemp(
940
940
  join(tmpdir(), 'generate-service-code-v2-outputtopic-')
941
941
  );
@@ -1030,7 +1030,7 @@ test('uses synchronous RBAC without obsolete callback SQS subscriptions in Initi
1030
1030
  });
1031
1031
 
1032
1032
  test('deduplicates duplicate nextSteps topics across flowSteps in InitialSetupConfig', async () => {
1033
- const { generate } = await import('../src/generate.js');
1033
+ const { generate } = await import('../../../src/generate.js');
1034
1034
  const rootPath = await mkdtemp(
1035
1035
  join(tmpdir(), 'generate-service-code-v2-dedupe-nextsteps-')
1036
1036
  );
@@ -1421,8 +1421,52 @@ test('emits early return cacheMain on cache hit in FlowEndpoint_Main for storedC
1421
1421
  await parseAsEsm(mainPath);
1422
1422
  });
1423
1423
 
1424
+ test('emits canonical checkStatusField and hooks in FlowEndpoint_Main for statusField', async () => {
1425
+ const rootPath = await createProject();
1426
+ await writeFile(
1427
+ join(rootPath, 'app/src/schemas/FlowSchemas/StatusFieldFlow.js'),
1428
+ `export default {
1429
+ flowTag: 'statusFieldOrder',
1430
+ event: ['ownTopic'],
1431
+ statusType: 'statusField',
1432
+ objType: { objectType: 'order', serviceTag: 'Current' },
1433
+ flowSteps: [{ stepName: 'Start' }]
1434
+ };\n`
1435
+ );
1436
+
1437
+ await generateCustomFlowApplicationArtifacts(rootPath);
1438
+
1439
+ const mainPath = join(
1440
+ rootPath,
1441
+ 'app/src/generatedCode/FlowSchemas/StatusFieldOrder/source/StatusFieldOrder_Main.js'
1442
+ );
1443
+ const mainContent = await readFile(mainPath, 'utf8');
1444
+ assert.match(
1445
+ mainContent,
1446
+ /import statusFieldSharedLib from '@izara_project\/izara-core-library-status-field';/
1447
+ );
1448
+ assert.match(mainContent, /statusFieldSharedLib\.checkStatusField/);
1449
+ assert.match(mainContent, /\/\/\(<beforeCheckedStatusField>\)/);
1450
+ assert.match(mainContent, /\/\/\(<identifiers>\)/);
1451
+ assert.match(mainContent, /\/\/\(<overwriteUniqueRequestId>\)/);
1452
+ assert.match(mainContent, /\/\/\(<afterCheckStatusField>\)/);
1453
+ assert.match(mainContent, /\/\/\(<afterValidateStatusField>\)/);
1454
+ assert.match(mainContent, /\/\/\(<checkStatusFieldHook>\)/);
1455
+ assert.match(mainContent, /\/\/\(<endpointHook>\)/);
1456
+ assert.match(mainContent, /\/\/\(<beforeCompleteStatusField>\)/);
1457
+ assert.match(mainContent, /statusFieldSharedLib\.completeStatusField/);
1458
+ assert.match(mainContent, /\/\/\(<statusField>\)/);
1459
+ assert.match(mainContent, /\/\/\(<errorFounds>\)/);
1460
+ assert.match(mainContent, /\/\/\(<afterCompleteStatusField>\)/);
1461
+ assert.match(
1462
+ mainContent,
1463
+ /_izContext\.logger\.debug\('\[StatusFieldOrder_Main\] started', \{\s*requestParams,\s*callingFlowConfig\s*\}\);/
1464
+ );
1465
+ await parseAsEsm(mainPath);
1466
+ });
1467
+
1424
1468
  test('does not emit RbacCallback artifacts or duplicate artifact paths for custom flow with RBAC', async () => {
1425
- const { generate } = await import('../src/generate.js');
1469
+ const { generate } = await import('../../../src/generate.js');
1426
1470
  const rootPath = await createProject();
1427
1471
  await writeFile(
1428
1472
  join(rootPath, 'app/src/schemas/ObjectSchemas/ComAcc.js'),
@@ -1495,7 +1539,7 @@ test('does not emit RbacCallback artifacts or duplicate artifact paths for custo
1495
1539
  });
1496
1540
 
1497
1541
  test('skips checkRbacPermission in FlowEndpoint_Main when initiateBy is systemNoUser', async () => {
1498
- const { generate } = await import('../src/generate.js');
1542
+ const { generate } = await import('../../../src/generate.js');
1499
1543
  const rootPath = await createProject();
1500
1544
  await writeFile(
1501
1545
  join(rootPath, 'app/src/schemas/ObjectSchemas/ComAcc.js'),
@@ -1538,4 +1582,90 @@ test('skips checkRbacPermission in FlowEndpoint_Main when initiateBy is systemNo
1538
1582
  await parseAsEsm(mainPath);
1539
1583
  });
1540
1584
 
1585
+ test('emits completeStatusField only in the final flowStep for statusType statusField', async () => {
1586
+ const rootPath = await createProject();
1587
+ await writeFile(
1588
+ join(rootPath, 'app/src/schemas/FlowSchemas/MultiStepStatus.js'),
1589
+ `export default {
1590
+ flowTag: 'multiStepStatus',
1591
+ event: ['ownTopic'],
1592
+ statusType: 'statusField',
1593
+ objType: { objectType: 'order', serviceTag: 'Current' },
1594
+ flowSteps: [
1595
+ {
1596
+ stepName: 'Start',
1597
+ nextSteps: [
1598
+ {
1599
+ targetType: 'extTopic',
1600
+ serviceTag: 'PaymentService',
1601
+ topicName: 'Process_In',
1602
+ toStepNames: ['Process']
1603
+ }
1604
+ ]
1605
+ },
1606
+ {
1607
+ stepName: 'Process',
1608
+ event: ['extTopic'],
1609
+ previousSteps: [{ sourceType: 'ownTopic', stepName: 'Start' }],
1610
+ nextSteps: [
1611
+ {
1612
+ targetType: 'extTopic',
1613
+ serviceTag: 'PaymentService',
1614
+ topicName: 'Finalize_In',
1615
+ toStepNames: ['Finalize']
1616
+ }
1617
+ ]
1618
+ },
1619
+ {
1620
+ stepName: 'Finalize',
1621
+ event: ['extTopic'],
1622
+ previousSteps: [{ sourceType: 'extTopic', serviceTag: 'PaymentService', topicName: 'Process_Out', fromStepNames: ['Process'] }]
1623
+ }
1624
+ ]
1625
+ };\n`
1626
+ );
1627
+
1628
+ await generateCustomFlowApplicationArtifacts(rootPath);
1629
+
1630
+ // 1. Start step (FlowEndpoint_Main) has checkStatusField, NOT completeStatusField
1631
+ const startPath = join(
1632
+ rootPath,
1633
+ 'app/src/generatedCode/FlowSchemas/MultiStepStatus/source/MultiStepStatus_Main.js'
1634
+ );
1635
+ const startContent = await readFile(startPath, 'utf8');
1636
+ assert.match(startContent, /statusFieldSharedLib\.checkStatusField/);
1637
+ assert.doesNotMatch(startContent, /completeStatusField/);
1638
+ await parseAsEsm(startPath);
1639
+
1640
+ // 2. Middle step (Process) is not the last step, so NO completeStatusField
1641
+ const processPath = join(
1642
+ rootPath,
1643
+ 'app/src/generatedCode/FlowSchemas/MultiStepStatus/source/MultiStepStatusProcess_Main.js'
1644
+ );
1645
+ const processContent = await readFile(processPath, 'utf8');
1646
+ assert.doesNotMatch(processContent, /statusFieldSharedLib/);
1647
+ assert.doesNotMatch(processContent, /completeStatusField/);
1648
+ await parseAsEsm(processPath);
1649
+
1650
+ // 3. Final step (Finalize) IS the last step, so it has completeStatusField and canonical hooks
1651
+ const finalizePath = join(
1652
+ rootPath,
1653
+ 'app/src/generatedCode/FlowSchemas/MultiStepStatus/source/MultiStepStatusFinalize_Main.js'
1654
+ );
1655
+ const finalizeContent = await readFile(finalizePath, 'utf8');
1656
+ assert.match(
1657
+ finalizeContent,
1658
+ /import statusFieldSharedLib from '@izara_project\/izara-core-library-status-field';/
1659
+ );
1660
+ assert.match(finalizeContent, /\/\/\(<beforeCompleteStatusField>\)/);
1661
+ assert.match(finalizeContent, /statusFieldSharedLib\.completeStatusField/);
1662
+ assert.match(finalizeContent, /flowTag:\s*'multiStepStatus'/);
1663
+ assert.match(finalizeContent, /\/\/\(<identifiers>\)/);
1664
+ assert.match(finalizeContent, /\/\/\(<statusField>\)/);
1665
+ assert.match(finalizeContent, /\/\/\(<errorFounds>\)/);
1666
+ assert.match(finalizeContent, /\/\/\(<afterCompleteStatusField>\)/);
1667
+ await parseAsEsm(finalizePath);
1668
+ });
1669
+
1670
+
1541
1671
 
@@ -4,7 +4,7 @@ import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import test, { after } from 'node:test';
6
6
 
7
- import { generateRelationshipApplicationArtifacts } from '../src/emit/relationship/generateRelationshipApplicationArtifacts.js';
7
+ import { generateRelationshipApplicationArtifacts } from '../../../src/emit/application/relationship/generateRelationshipApplicationArtifacts.js';
8
8
 
9
9
  const roots = new Set();
10
10
  after(() =>
@@ -1,7 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import test from 'node:test';
3
3
 
4
- import { emitSystemFindDataArtifacts } from '../src/emit/system/emitSystemFindDataArtifacts.js';
4
+ import { emitSystemFindDataArtifacts } from '../../../src/emit/application/system/emitSystemFindDataArtifacts.js';
5
5
 
6
6
  test('emitSystemFindDataArtifacts returns empty when no objects have storage resources', async () => {
7
7
  const result = await emitSystemFindDataArtifacts([
@@ -7,7 +7,7 @@ import {
7
7
  renderInvFunctionYaml,
8
8
  renderSqsFunctionYaml,
9
9
  renderWbsFunctionYaml
10
- } from '../src/emit/function/functionYamlArtifact.js';
10
+ } from '../../../src/emit/infrastructure/functions/functionYamlArtifact.js';
11
11
 
12
12
  test('renders function-setting hooks for every function transport', () => {
13
13
  const functions = [
@@ -6,7 +6,7 @@ import test, { after } from 'node:test';
6
6
 
7
7
  process.env.NODE_ENV = 'test';
8
8
 
9
- import { generateResourceArtifacts } from '../src/emit/resource/generateResourceArtifacts.js';
9
+ import { generateResourceArtifacts } from '../../../src/emit/infrastructure/resources/generateResourceArtifacts.js';
10
10
 
11
11
  const roots = new Set();
12
12
  after(() =>