@izara_project/izara-core-generate-service-code 1.0.65 → 1.0.67

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 (257) hide show
  1. package/README.md +73 -11
  2. package/docs/TriggeredCache Flow.drawio +193 -0
  3. package/docs/test.mmd +47 -0
  4. package/docs/test.png +0 -0
  5. package/index.js +0 -5
  6. package/package.json +7 -6
  7. package/src/compile/compileProject.js +26 -0
  8. package/src/compile/loadSchemas.js +50 -0
  9. package/src/emit/crud/dynamicCrudFlowSchemaTemplate.js +11 -0
  10. package/src/emit/crud/emitCrudApplicationArtifacts.js +161 -0
  11. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +84 -0
  12. package/src/emit/crud/generateCrudApplicationArtifacts.js +16 -0
  13. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +21 -0
  14. package/src/emit/crud/loadLocalSchemaArrays.js +8 -0
  15. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/crud → emit/crud/templates}/CreateEndpoint_Main.ejs +6 -6
  16. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/crud → emit/crud/templates}/DeleteEndpoint_Main.ejs +6 -6
  17. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/step → emit/crud/templates}/FlowEndpointBeforeLogical_Main.ejs +2 -2
  18. package/src/emit/crud/templates/FlowEndpointComplete_Main.ejs +96 -0
  19. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint → emit/crud/templates}/FlowEndpoint_HdrWbs.ejs +1 -1
  20. package/src/emit/crud/templates/FlowHandler_HdrApi.ejs +69 -0
  21. package/src/{codeGenerators/app/src/generatedCode/ProcessLogical/templates/ProcessLogical_HdrSqs.ejs → emit/crud/templates/FlowHandler_HdrSqs.ejs} +52 -56
  22. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint → emit/crud/templates}/FlowMain_Wbs.ejs +1 -3
  23. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/crud → emit/crud/templates}/GetEndpoint_Main.ejs +2 -2
  24. package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +127 -0
  25. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/crud → emit/crud/templates}/UpdateEndpoint_Main.ejs +11 -9
  26. package/src/emit/custom/customFlows.js +121 -0
  27. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +325 -0
  28. package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +22 -0
  29. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint → emit/custom/templates}/FlowEndpoint_Main.ejs +5 -5
  30. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/step → emit/custom/templates}/FlowStep_Main.ejs +1 -1
  31. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/ConfirmReserved_Main.ejs +5 -5
  32. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/CreateObject_HdrWbs.ejs +1 -1
  33. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/CreateObject_Main.ejs +3 -3
  34. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/CreatePreSignUrl_Main.ejs +4 -5
  35. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/FlowHandler_HdrS3.ejs +2 -8
  36. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/ProcessS3File_Main.ejs +1 -1
  37. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/ReservedLimit_Main.ejs +5 -6
  38. package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +32 -0
  39. package/src/emit/custom/templates/triggerCache/CheckTriggerCache_Main.ejs +63 -0
  40. package/src/emit/custom/templates/triggerCache/TriggerCacheComplete_Main.ejs +35 -0
  41. package/src/emit/custom/templates/triggerCache/TriggerCache_Main.ejs +16 -0
  42. package/src/emit/function/functionYamlArtifact.js +125 -0
  43. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +117 -0
  44. package/src/emit/rbac/emitRbacApplicationArtifacts.js +270 -0
  45. package/src/emit/rbac/generateCreateTargetRoleHandler.js +19 -0
  46. package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +21 -0
  47. package/src/emit/rbac/rbacFlowTag.js +7 -0
  48. package/src/emit/rbac/templates/CreateTargetRole_HdrSqs.ejs +24 -0
  49. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +25 -0
  50. package/src/emit/rbac/templates/DynamicRbacFlowSchema.ejs +5 -0
  51. package/src/emit/rbac/templates/ListRbac_HdrApi.ejs +17 -0
  52. package/src/emit/rbac/templates/ListRbac_HdrSqs.ejs +13 -0
  53. package/src/emit/rbac/templates/ListRbac_Main.ejs +29 -0
  54. package/src/emit/rbac/templates/RbacMutation_Main.ejs +22 -0
  55. package/src/emit/rbac/templates/UserRbacFlow_HdrInv.ejs +10 -0
  56. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +44 -0
  57. package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +33 -0
  58. package/src/emit/relationship/dynamicRelationshipFlowSchemaTemplate.js +11 -0
  59. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +66 -0
  60. package/src/emit/relationship/emitRelationshipApplicationArtifacts.js +148 -0
  61. package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +23 -0
  62. package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +22 -0
  63. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessChangeRelationshipComplete_Main.ejs → emit/relationship/templates/ChangeRelationshipComplete_Main.ejs} +1 -1
  64. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessChangeRelationship_Main.ejs → emit/relationship/templates/ChangeRelationship_Main.ejs} +12 -4
  65. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessCreateRelationshipComplete_Main.ejs → emit/relationship/templates/CreateRelationshipComplete_Main.ejs} +1 -1
  66. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessCreateRelationship_Main.ejs → emit/relationship/templates/CreateRelationship_Main.ejs} +1 -1
  67. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessDeleteRelationshipComplete_Main.ejs → emit/relationship/templates/DeleteRelationshipComplete_Main.ejs} +1 -1
  68. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessDeleteRelationship_Main.ejs → emit/relationship/templates/DeleteRelationship_Main.ejs} +1 -1
  69. package/src/{codeGenerators/app/src/generatedCode/Flow/_shared/handlers → emit/relationship/templates}/FlowHandler_HdrDsq.ejs +1 -1
  70. package/src/emit/relationship/templates/FlowHandler_HdrInv.ejs +45 -0
  71. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessGetRelationshipComplete_Main.ejs → emit/relationship/templates/GetRelationshipComplete_Main.ejs} +1 -1
  72. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessGetRelationship_Main.ejs → emit/relationship/templates/GetRelationship_Main.ejs} +1 -1
  73. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessMoveRelationship_Main.ejs → emit/relationship/templates/MoveRelationship_Main.ejs} +9 -1
  74. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessUpdateRelationshipComplete_Main.ejs → emit/relationship/templates/UpdateRelationshipComplete_Main.ejs} +1 -1
  75. package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessUpdateRelationship_Main.ejs → emit/relationship/templates/UpdateRelationship_Main.ejs} +1 -1
  76. package/src/emit/resource/emitResourceArtifacts.js +595 -0
  77. package/src/emit/resource/generateResourceArtifacts.js +20 -0
  78. package/src/{codeGenerators/resource/sls_yaml/templates/crud → emit/resource/templates}/ResourceBeforeLogicalYaml.ejs +1 -1
  79. package/src/{codeGenerators/resource/sls_yaml/templates/crud → emit/resource/templates}/ResourceSqsYaml.ejs +6 -6
  80. package/src/{codeGenerators/app/sls_yaml → emit/resource}/templates/SharedResource_Yaml.ejs +8 -8
  81. package/src/emit/system/emitSystemWebSocketArtifacts.js +183 -0
  82. package/src/generate.js +60 -126
  83. package/src/output/commitArtifacts.js +213 -0
  84. package/src/output/mergeHooks.js +55 -0
  85. package/src/output/validateArtifacts.js +62 -0
  86. package/src/plan/buildGenerationPlan.js +50 -0
  87. package/test/core.test.js +159 -0
  88. package/test/createTargetRoleHandler.test.js +68 -0
  89. package/test/crudApplicationArtifacts.test.js +107 -0
  90. package/test/customFlowApplicationArtifacts.test.js +297 -0
  91. package/test/dynamicCrudFlowSchemas.test.js +136 -0
  92. package/test/dynamicRbacFlowSchemas.test.js +101 -0
  93. package/test/dynamicRelationshipFlowSchemas.test.js +99 -0
  94. package/test/functionYamlArtifact.test.js +34 -0
  95. package/test/intTestApi.test.js +29 -0
  96. package/test/publicApi.test.js +209 -0
  97. package/test/relationshipApplicationArtifacts.test.js +68 -0
  98. package/test/resourceArtifacts.test.js +121 -0
  99. package/jsconfig.json +0 -9
  100. package/src/__tests__/getIntTestConfig.test.js +0 -51
  101. package/src/__tests__/intTestGeneratorShared.test.cjs +0 -169
  102. package/src/__tests__/pathIntTest.test.js +0 -103
  103. package/src/codeGenerators/app/initial_setup/InitialSetupGenerator.js +0 -199
  104. package/src/codeGenerators/app/initial_setup/templates/InitialSetup_LambdaRole.ejs +0 -50
  105. package/src/codeGenerators/app/initial_setup/templates/InitialSetup_SnsService.ejs +0 -15
  106. package/src/codeGenerators/app/initial_setup/templates/InitialSetup_TableName.ejs +0 -9
  107. package/src/codeGenerators/app/sls_yaml/FindDataYamlGenerator.js +0 -23
  108. package/src/codeGenerators/app/sls_yaml/FunctionYamlGenerator.js +0 -332
  109. package/src/codeGenerators/app/sls_yaml/ProcessLogicalYamlGenerator.js +0 -21
  110. package/src/codeGenerators/app/sls_yaml/RoleNameConfigGenerator.js +0 -48
  111. package/src/codeGenerators/app/sls_yaml/SharedResourceYamlGenerator.js +0 -503
  112. package/src/codeGenerators/app/sls_yaml/__tests__/SharedResourceYamlGenerator.test.js +0 -235
  113. package/src/codeGenerators/app/sls_yaml/_policy/PolicyRegistry.js +0 -56
  114. package/src/codeGenerators/app/sls_yaml/_policy/__tests__/PolicyRegistry.test.js +0 -33
  115. package/src/codeGenerators/app/sls_yaml/renderYamlTemplate.js +0 -13
  116. package/src/codeGenerators/app/sls_yaml/templates/FindData_Yaml.ejs +0 -10
  117. package/src/codeGenerators/app/sls_yaml/templates/FunctionYaml_Api.ejs +0 -21
  118. package/src/codeGenerators/app/sls_yaml/templates/FunctionYaml_EventBridge.ejs +0 -14
  119. package/src/codeGenerators/app/sls_yaml/templates/FunctionYaml_Inv.ejs +0 -6
  120. package/src/codeGenerators/app/sls_yaml/templates/FunctionYaml_Sqs.ejs +0 -11
  121. package/src/codeGenerators/app/sls_yaml/templates/FunctionYaml_Wbs.ejs +0 -11
  122. package/src/codeGenerators/app/sls_yaml/templates/ProcessLogical_Yaml.ejs +0 -32
  123. package/src/codeGenerators/app/sls_yaml/templates/RoleNameConfig_Yaml.ejs +0 -5
  124. package/src/codeGenerators/app/src/generatedCode/FindData/FindDataGenerator.js +0 -238
  125. package/src/codeGenerators/app/src/generatedCode/FindData/templates/FindData_HdrSqs.ejs +0 -87
  126. package/src/codeGenerators/app/src/generatedCode/FindData/templates/FindData_Main.ejs +0 -108
  127. package/src/codeGenerators/app/src/generatedCode/FindData/templates/GetByStorage/getByDynamo.ejs +0 -32
  128. package/src/codeGenerators/app/src/generatedCode/FindData/templates/GetByStorage/getByGraph.ejs +0 -87
  129. package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/.gitkeep +0 -0
  130. package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/EndpointsGenerator.js +0 -120
  131. package/src/codeGenerators/app/src/generatedCode/Flow/FlowObjects/templates/step/FlowEndpointComplete_Main.ejs +0 -313
  132. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/RbacFlowGenerator.js +0 -116
  133. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/CreateRolePermissions.ejs +0 -135
  134. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/CreateTargetRole.ejs +0 -131
  135. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/CreateUserRole.ejs +0 -150
  136. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/DeleteRolePermissions.ejs +0 -132
  137. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/DeleteTargetRole.ejs +0 -132
  138. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/DeleteUserFromRole.ejs +0 -150
  139. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/FlowRbac_Main.ejs +0 -252
  140. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/ListRolePermissions.ejs +0 -120
  141. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/ListTargetRole.ejs +0 -122
  142. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/ListUserInRoles.ejs +0 -117
  143. package/src/codeGenerators/app/src/generatedCode/Flow/FlowRelationships/RelationshipFlowGenerator.js +0 -148
  144. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/.gitkeep +0 -0
  145. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/StatusFieldGenerator.js +0 -109
  146. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/WebSocketGenerator.js +0 -122
  147. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/endpoint/FlowEntryPoint_Main.ejs +0 -38
  148. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/statusField/CompleteStatusFieldSns_Yaml.ejs +0 -52
  149. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/statusField/CompleteStatusField_HdrSqs.ejs +0 -84
  150. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/statusField/CompleteStatusField_Main.ejs +0 -78
  151. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/step/plugIns/FlowStep_ByConfig_Awaiting_Main.ejs +0 -123
  152. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/step/plugIns/FlowStep_ByConfig_Paginated_Main.ejs +0 -59
  153. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/step/plugIns/FlowStep_PlugIn_Main.ejs +0 -72
  154. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/step/plugIns/FlowStep_RecievePlugIn_Main.ejs +0 -76
  155. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/step/plugIns/templateAwaitingStep.ejs +0 -41
  156. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/step/plugIns/templateSendPlugin.ejs +0 -18
  157. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/webSocket/ProcessWebSocketFlow_Yaml.ejs +0 -26
  158. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/webSocket/ProcessWebSocketSub_Yaml.ejs +0 -7
  159. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/webSocket/ProcessWebSocket_HdrSqs.ejs +0 -66
  160. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/webSocket/ProcessWebSocket_Main.ejs +0 -115
  161. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/webSocket/ProcessWebSocket_Yaml.ejs +0 -36
  162. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/webSocket/WebSocketConnect_Main.ejs +0 -52
  163. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/webSocket/WebSocketConnect_Yaml.ejs +0 -13
  164. package/src/codeGenerators/app/src/generatedCode/Flow/FlowSchemas/templates/webSocket/WebSocketDynamoDb_Yaml.ejs +0 -28
  165. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseDsqHandler.js +0 -63
  166. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/BaseSqsHandler.js +0 -66
  167. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/__tests__/BaseDsqHandler.test.js +0 -94
  168. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/dsq.js +0 -5
  169. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/eventBridge.js +0 -33
  170. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/extTopic.js +0 -6
  171. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/lambdaSyncApi.js +0 -51
  172. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/lambdaSyncInv.js +0 -51
  173. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/ownTopic.js +0 -54
  174. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/registry.js +0 -17
  175. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/s3.js +0 -56
  176. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/s3Components/ConfirmAfterUploadS3Generator.js +0 -46
  177. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/s3Components/CreateObjectGenerator.js +0 -50
  178. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/s3Components/CreatePreSignUrlGenerator.js +0 -48
  179. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/s3Components/ProcessAfterUploadS3Generator.js +0 -49
  180. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/events/s3Components/ReservedLimitGenerator.js +0 -47
  181. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/eventTypes.js +0 -23
  182. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowClassifier.js +0 -50
  183. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowEntryPointBase.js +0 -106
  184. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowMainFunctionBase.js +0 -172
  185. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowNaming.js +0 -37
  186. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowSelection.js +0 -19
  187. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepBase.js +0 -235
  188. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowStepNormalizer.js +0 -75
  189. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowValidator.js +0 -267
  190. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/propertyNormalizer.js +0 -18
  191. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/registry.js +0 -7
  192. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/roleNameDetection.js +0 -49
  193. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/triggerCacheBase.js +0 -177
  194. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/triggerCache/CheckTriggerCache_HdrSqs.ejs +0 -89
  195. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/triggerCache/CheckTriggerCache_Main.ejs +0 -83
  196. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/triggerCache/ProcessTriggerCache_HdrSqs.ejs +0 -103
  197. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/triggerCache/ProcessTriggerCache_Main.ejs +0 -58
  198. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/triggerCache/TriggerCacheComplete_HdrDsq.ejs +0 -104
  199. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/triggerCache/TriggerCacheComplete_HdrSqs.ejs +0 -88
  200. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/triggerCache/TriggerCacheComplete_Main.ejs +0 -80
  201. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/triggerCache/TriggerCacheQueue_Yaml.ejs +0 -36
  202. package/src/codeGenerators/app/src/generatedCode/Flow/_shared/yaml/SharedFunctionSqs_Yaml.ejs +0 -13
  203. package/src/codeGenerators/app/src/generatedCode/ProcessLogical/ProcessLogicalGenerator.js +0 -29
  204. package/src/codeGenerators/app/src/generatedCode/ProcessLogical/templates/PaginateProcessLogical_HdrDsq.ejs +0 -177
  205. package/src/codeGenerators/app/src/generatedCode/ProcessLogical/templates/PaginateProcessLogical_HdrSqs.ejs +0 -155
  206. package/src/codeGenerators/app/src/generatedCode/ProcessLogical/templates/PaginateProcessLogical_Main.ejs +0 -268
  207. package/src/codeGenerators/app/src/generatedCode/ProcessLogical/templates/ProcessLogical_Main.ejs +0 -450
  208. package/src/codeGenerators/app/src/generatedCode/SystemFlowSchemas/RegisterGenerator.js +0 -149
  209. package/src/codeGenerators/app/src/generatedCode/SystemFlowSchemas/templates/register/RegisterComplete_HdrSqs.ejs +0 -85
  210. package/src/codeGenerators/app/src/generatedCode/SystemFlowSchemas/templates/register/RegisterComplete_Main.ejs +0 -176
  211. package/src/codeGenerators/app/src/generatedCode/SystemFlowSchemas/templates/register/Register_HdrWbs.ejs +0 -80
  212. package/src/codeGenerators/app/src/generatedCode/SystemFlowSchemas/templates/register/Register_Main.ejs +0 -164
  213. package/src/codeGenerators/app/src/generatedCode/libs/ConstsGenerator.js +0 -28
  214. package/src/codeGenerators/app/src/generatedCode/libs/GenerateCodeLibsGenerator.js +0 -28
  215. package/src/codeGenerators/app/src/generatedCode/libs/templates/Consts.ejs +0 -448
  216. package/src/codeGenerators/app/src/generatedCode/libs/templates/GenerateCodeLibs.ejs +0 -124
  217. package/src/codeGenerators/resource/sls_yaml/DynamoDBGenerator.js +0 -87
  218. package/src/codeGenerators/resource/sls_yaml/FlowOutGenerator.js +0 -70
  219. package/src/codeGenerators/resource/sls_yaml/FlowResourceYamlGenerator.js +0 -182
  220. package/src/core/renderTemplateFile.js +0 -22
  221. package/src/core/validate.js +0 -165
  222. package/src/generateCode.js +0 -357
  223. package/src/generateSchema.js +0 -123
  224. package/src/parsers/flowSchemaParser.js +0 -112
  225. package/src/parsers/objectSchemaParser.js +0 -39
  226. package/src/parsers/relationshipSchemaParser.js +0 -51
  227. package/src/schemaGenerators/app/src/schemas/FlowSchemas/FlowSchemaGenerator.js +0 -107
  228. package/src/schemaGenerators/app/src/schemas/FlowSchemas/RbacFlowSchemaGenerator.js +0 -98
  229. package/src/schemaGenerators/app/src/schemas/FlowSchemas/RelationshipFlowSchemaGenerator.js +0 -89
  230. package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/DynamicFlowSchemaTemplate.ejs +0 -41
  231. package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/DynamicRbacFlowSchemaTemplate.ejs +0 -20
  232. package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/RelationshipFlowSchemaTemplate.ejs +0 -33
  233. package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/UserRbacFlowSchemaTemplate.ejs +0 -22
  234. package/src/schemaGenerators/app/src/schemas/ObjectSchemas/AttributeTreeSchemaGenerator.js +0 -124
  235. package/src/schemaGenerators/app/src/schemas/ObjectSchemas/PropertyValueSchemaGenerator.js +0 -119
  236. package/src/schemaGenerators/app/src/schemas/ObjectSchemas/templates/DynamicAttributeTreeManagerSchemaTemplate.ejs +0 -14
  237. package/src/schemaGenerators/app/src/schemas/ObjectSchemas/templates/DynamicAttributeTreeStandardSchemaTemplate.ejs +0 -13
  238. package/src/schemaGenerators/app/src/schemas/ObjectSchemas/templates/DynamicPropertyValueSchemaTemplate.ejs +0 -15
  239. package/src/schemaGenerators/app/src/schemas/RelationshipSchemas/AttributeTreeRelationshipSchemaGenerator.js +0 -109
  240. package/src/schemaGenerators/app/src/schemas/RelationshipSchemas/PropertyValueRelationshipSchemaGenerator.js +0 -103
  241. package/src/schemaGenerators/app/src/schemas/RelationshipSchemas/__tests__/relationshipSchemaHelpers.test.js +0 -38
  242. package/src/schemaGenerators/app/src/schemas/RelationshipSchemas/relationshipSchemaHelpers.js +0 -40
  243. package/src/schemaGenerators/app/src/schemas/RelationshipSchemas/templates/DynamicAttributeTreeRelationshipSchemaTemplate.ejs +0 -7
  244. package/src/schemaGenerators/app/src/schemas/RelationshipSchemas/templates/DynamicPropertyValueRelationshipSchemaTemplate.ejs +0 -7
  245. package/src/schemaGenerators/app/src/schemas/SystemTextSchemas/SystemTextGenerator.js +0 -102
  246. package/src/schemaGenerators/app/src/schemas/SystemTextSchemas/templates/SystemText_Template.ejs +0 -10
  247. /package/src/{codeGenerators/app/src/generatedCode/Flow/_shared/handlers → emit/crud/templates}/FlowHandler_HdrInv.ejs +0 -0
  248. /package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/ConfirmReserved_HdrSqs.ejs +0 -0
  249. /package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/CreatePreSignUrl_HdrSqs.ejs +0 -0
  250. /package/src/{codeGenerators/app/src/generatedCode/Flow/FlowSchemas → emit/custom}/templates/s3/ReservedLimit_HdrSqs.ejs +0 -0
  251. /package/src/{codeGenerators/app/src/generatedCode/Flow/_shared/handlers → emit/relationship/templates}/FlowHandler_HdrApi.ejs +0 -0
  252. /package/src/{codeGenerators/app/src/generatedCode/Flow/_shared/handlers → emit/relationship/templates}/FlowHandler_HdrSqs.ejs +0 -0
  253. /package/src/{codeGenerators/app/src/generatedCode/Flow/FlowRelationships/templates/relationship/ProcessMoveRelationshipComplete_Main.ejs → emit/relationship/templates/MoveRelationshipComplete_Main.ejs} +0 -0
  254. /package/src/{codeGenerators/resource/sls_yaml → emit/resource}/templates/DynamoDBTable_Yaml.ejs +0 -0
  255. /package/src/{codeGenerators/resource/sls_yaml → emit/resource}/templates/FlowOut_Yaml.ejs +0 -0
  256. /package/src/{codeGenerators/resource/sls_yaml/templates/crud → emit/resource/templates}/ResourceYaml.ejs +0 -0
  257. /package/src/{codeGenerators/resource/sls_yaml → emit/resource}/templates/SystemDynamoDB_Yaml.ejs +0 -0
@@ -0,0 +1,183 @@
1
+ const SOURCE = 'app/src/generatedCode/SystemFlowSchemas/WebSocketMain/source';
2
+
3
+ export async function emitSystemWebSocketArtifacts(flows, { includeRelationshipOwnTopic = false } = {}) {
4
+ if (!hasSystemWebSocket(flows, { includeRelationshipOwnTopic })) return { artifacts: [], functions: [] };
5
+
6
+ return {
7
+ artifacts: [
8
+ { path: `${SOURCE}/WebSocketConnect.js`, content: webSocketConnect() },
9
+ { path: `${SOURCE}/WebSocketComplete_Main.js`, content: webSocketCompleteMain() },
10
+ { path: `${SOURCE}/WebSocketComplete_HdrSqs.js`, content: webSocketCompleteHandler() }
11
+ ],
12
+ functions: [
13
+ renderWebSocketConnectYaml(),
14
+ renderWebSocketCompleteYaml()
15
+ ]
16
+ };
17
+ }
18
+
19
+ export function systemWebSocketManagedPaths() {
20
+ return [
21
+ `${SOURCE}/WebSocketConnect.js`,
22
+ `${SOURCE}/WebSocketComplete_Main.js`,
23
+ `${SOURCE}/WebSocketComplete_HdrSqs.js`
24
+ ];
25
+ }
26
+
27
+ export function hasSystemWebSocket(flows, { includeRelationshipOwnTopic = false } = {}) {
28
+ // return true;
29
+ return Array.isArray(flows) && flows.some(flow => Array.isArray(flow?.event) && (flow.event.includes('s3') || (includeRelationshipOwnTopic && flow.event.includes('ownTopic') && flow.initiateBy === 'user')));
30
+ }
31
+
32
+ function renderWebSocketConnectYaml() {
33
+ return `WebSocketConnect:
34
+ handler: src/generatedCode/SystemFlowSchemas/WebSocketMain/source/WebSocketConnect.main
35
+ name: \${self:custom.iz_resourcePrefix}WebSocketConnect
36
+ role: WebSocketMainRole
37
+ events:
38
+ - websocket:
39
+ route: $connect
40
+ - websocket:
41
+ route: $disconnect
42
+ - websocket:
43
+ route: $default
44
+ `;
45
+ }
46
+
47
+ function renderWebSocketCompleteYaml() {
48
+ return `WebSocketCompleteHdrSqs:
49
+ handler: src/generatedCode/SystemFlowSchemas/WebSocketMain/source/WebSocketComplete_HdrSqs.main
50
+ name: \${self:custom.iz_resourcePrefix}WebSocketCompleteHdrSqs
51
+ role: WebSocketMainRole
52
+ events:
53
+ - sqs:
54
+ arn: arn:aws:sqs:\${self:custom.iz_region}:\${self:custom.iz_accountId}:\${self:custom.iz_resourcePrefix}WebSocketCompleteHdrSqs
55
+ batchSize: 10
56
+ filterPatterns:
57
+ - body:
58
+ MessageAttributes:
59
+ callingFlow:
60
+ Value:
61
+ - \${self:custom.iz_resourcePrefix}WebSocketCompleteHdrSqs
62
+ - body:
63
+ MessageAttributes:
64
+ callingFlow:
65
+ Value:
66
+ - exists: false
67
+ `;
68
+ }
69
+
70
+ function webSocketConnect() {
71
+ return `import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
72
+ import { middlewareHandler as middleware, response } from '@izara_project/izara-middleware';
73
+
74
+ export const main = middleware.wrap(async event => {
75
+ const { eventType, connectionId } = event.requestContext ?? {};
76
+ try {
77
+ event._izContext.logger.debug('Event:', event);
78
+ if (eventType === 'CONNECT') {
79
+ const { userId, submittedByUserId } = event.queryStringParameters ?? {};
80
+ await dynamodbSharedLib.putItem(event._izContext, await dynamodbSharedLib.tableName(event._izContext, 'UserUploadRecords'), {
81
+ connectionId, userId, submittedByUserId, expirationTime: Math.floor(Date.now() / 1000) + 7200
82
+ });
83
+ //(<webSocketConnect>)
84
+ //(</webSocketConnect>)
85
+ } else if (eventType === 'DISCONNECT') {
86
+ await dynamodbSharedLib.deleteItem(event._izContext, await dynamodbSharedLib.tableName(event._izContext, 'UserUploadRecords'), { connectionId });
87
+ //(<webSocketDisconnect>)
88
+ //(</webSocketDisconnect>)
89
+ }
90
+ return response.webSocketSuccess();
91
+ } catch (error) {
92
+ event._izContext.logger.error('Error, WebSocketConnect: ', error);
93
+ return response.failure(error);
94
+ }
95
+ });
96
+ `;
97
+ }
98
+
99
+ function webSocketCompleteMain() {
100
+ return `import { NoRetryError } from '@izara_project/izara-core-library-core';
101
+ import { consts } from '@izara_project/izara-middleware';
102
+ import { getObjectSchema, utils } from '@izara_project/izara-core-library-service-schemas';
103
+ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
104
+ import { webSocket } from '@izara_project/izara-core-library-external-request';
105
+
106
+ const { createFlowTypeConcat } = utils;
107
+ const { postToConnection } = webSocket;
108
+
109
+ export default async function WebSocketComplete(_izContext, topicArn, requestParams, callingFlowConfig = {}) {
110
+ try {
111
+ _izContext.logger.debug('WebSocketComplete _izContext', _izContext);
112
+ _izContext.logger.debug('WebSocketComplete requestParams', requestParams);
113
+ _izContext.logger.debug('WebSocketComplete callingFlowConfig', callingFlowConfig);
114
+ const correlationId = _izContext.correlationIds.get(consts.X_CORRELATION_ID);
115
+ if (!topicArn) throw new NoRetryError('not have TopicArn for get FlowSchemas');
116
+ const topicName = topicArn.split(':')[5].split('_');
117
+ let flowTag = topicName[2];
118
+ let flowSchema = await getObjectSchema.getFlowSchemaS3WithCache(_izContext, { flowTag, serviceTag: topicName[0] });
119
+ if (!flowSchema) {
120
+ if (!requestParams?.hasOwnProperty('flowTag')) throw new NoRetryError('Could not find flowSchema from topicArn or requestParams.flowTag');
121
+ flowTag = requestParams.flowTag;
122
+ flowSchema = await getObjectSchema.getFlowSchemaS3WithCache(_izContext, { flowTag, serviceTag: process.env.iz_serviceTag });
123
+ }
124
+ //(<createIdentifiersFlow>)
125
+ let identifiers;
126
+ //(</createIdentifiersFlow>)
127
+ let taskKey;
128
+ if (flowSchema.statusType === 'statusField' || flowSchema.statusType === 'storedCache' || flowSchema.statusType === 'triggerCache') {
129
+ taskKey = createFlowTypeConcat(_izContext, { flowTag, serviceTag: topicName[0] }) + identifiers;
130
+ } else if (flowSchema.statusType === 'none') {
131
+ taskKey = createFlowTypeConcat(_izContext, { flowTag, serviceTag: topicName[0] }) + correlationId;
132
+ }
133
+ if (!taskKey) return;
134
+ const tasks = await dynamodbSharedLib.query(_izContext, await dynamodbSharedLib.tableName(_izContext, 'WebSocketTask'), { taskKey });
135
+ await Promise.all((tasks.Items ?? []).map(async task => {
136
+ //(<beforePostMessage>)
137
+ //(</beforePostMessage>)
138
+ await postToConnection({ message: requestParams }, task.connectionId);
139
+ await dynamodbSharedLib.deleteItem(_izContext, await dynamodbSharedLib.tableName(_izContext, 'WebSocketTask'), { taskKey: task.taskKey, connectionId: task.connectionId });
140
+ }));
141
+ } catch (error) {
142
+ _izContext.logger.error('error WebSocketInvoke: ', error);
143
+ throw error;
144
+ }
145
+ }
146
+ `;
147
+ }
148
+
149
+ function webSocketCompleteHandler() {
150
+ return `import { middlewareHandler as middleware } from '@izara_project/izara-middleware';
151
+ import Logger from '@izara_project/izara-core-library-logger';
152
+ import { recordHandlerSharedLib } from '@izara_project/izara-core-library-record-handler';
153
+ import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
154
+ import WebSocketComplete from './WebSocketComplete_Main.js';
155
+
156
+ middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());
157
+ const perRecordsValidatorSchema = {};
158
+ export const main = middleware.wrap(async (event, context, callback) => {
159
+ try {
160
+ const recordPromises = [];
161
+ await Promise.all(event.Records.map(async record => {
162
+ record._izContext.logger.debug('record ReceiveMsgOutHdrSqs', record);
163
+ await recordHandlerSharedLib.validateRecord(record, 'WebSocketCompleteHdrSqs', perRecordsValidatorSchema);
164
+ recordPromises.push(recordHandlerSharedLib.recordHandler(
165
+ record,
166
+ WebSocketComplete,
167
+ 'WebSocketCompleteHdrSqs',
168
+ [record.body.TopicArn, record.body.Message, callingFlowSharedLib.addCallingFlowToPassOnProperties(record.body.Message)]
169
+ ));
170
+ }));
171
+ try {
172
+ await Promise.all(recordPromises);
173
+ return event.Records;
174
+ } catch {
175
+ Logger.debug('Promise.all(recordPromises) in handler threw error (at least one record did no resolve)');
176
+ }
177
+ } catch (error) {
178
+ Logger.error('Unhandled Error, WebSocketComplete_HdrSqs: ', error);
179
+ throw error;
180
+ }
181
+ });
182
+ `;
183
+ }
package/src/generate.js CHANGED
@@ -1,130 +1,64 @@
1
- /*
2
- Copyright (C) 2020 Sven Mason <http://izara.io>
3
-
4
- This program is free software: you can redistribute it and/or modify
5
- it under the terms of the GNU Affero General Public License as published by
6
- the Free Software Foundation, either version 3 of the License, or
7
- (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU Affero General Public License for more details.
13
-
14
- You should have received a copy of the GNU Affero General Public License
15
- along with this program. If not, see <http://www.gnu.org/licenses/>.
16
- */
17
-
18
- import { join } from 'path';
19
- import { validator } from '@izara_project/izara-core-library-service-schemas';
20
- import { basicValidatorSchema } from '@izara_project/izara-shared-service-schemas';
21
- import { generateCode } from './generateCode.js';
22
- import { generateSchema } from './generateSchema.js';
23
-
24
- const { validateLocalSchema } = validator;
25
-
26
- /**
27
- * High-level API to validate schemas and generate code.
28
- * Wires legacy Logger and validateLocalSchema.
29
- *
30
- * @param {string} rootPath - The root path of the project.
31
- * @param {object} [options={}] - Configuration options.
32
- * @param {object} [options.logger] - Logger instance.
33
- * @param {string} [options.configPath] - Path to the serverless configuration file.
34
- * @param {string} [options.outputPath] - Output directory path.
35
- * @param {boolean} [options.skipValidation=false] - Whether to skip schema validation.
36
- * @param {boolean} [options.skipGenerateSchema=false] - Whether to skip schema generation.
37
- * @param {boolean} [options.skipGenerateCode=false] - Whether to skip code generation.
38
- * @param {Array} [options.schemaTemplateConfig] - Schema template configuration.
39
- * @returns {Promise<{durationMs: number}>} Generation duration details.
40
- */
41
- async function generate(rootPath, options = {}) {
42
- const {
43
- logger = createSilentLogger(),
44
- configPath = join(rootPath, 'config', 'serverless.config.yml'),
45
- outputPath = rootPath,
46
- skipValidation = false,
47
- skipGenerateSchema = false,
48
- skipGenerateCode = false,
49
- schemaTemplateConfig
50
- } = options;
51
-
52
- const schemasPath = join(rootPath, 'app', 'src', 'schemas');
53
-
54
- if (!skipGenerateSchema) {
55
- await generateSchema(rootPath, {
56
- configPath,
57
- outputPath,
58
- schemaTemplateConfig
59
- });
60
- }
61
-
62
- if (!skipValidation) {
63
- patchFlowStepsValidationSchema();
64
-
65
- console.info('[INFO] [generate] STATUS=VALIDATING | local schemas...');
66
- const validateStartTime = Date.now();
67
- const result = await validateLocalSchema({ logger }, schemasPath, configPath);
68
- const validateDuration = Date.now() - validateStartTime;
69
-
70
- console.info(
71
- `[INFO] [generate] STATUS=VALIDATED | errors=${result.validateErrors.length} | elapsedMs=${validateDuration}`
72
- );
73
-
74
- if (result.validateErrors.length > 0) {
75
- logger.error(
76
- 'Validation failed with following errors:',
77
- result.validateErrors
78
- );
79
- const err = new Error('Schema validation failed');
80
- err.validateErrors = result.validateErrors;
81
- throw err;
82
- }
83
- }
84
-
85
- if (skipGenerateCode) {
86
- return { durationMs: 0 };
1
+ import { buildGenerationPlan } from './plan/buildGenerationPlan.js';
2
+ import { commitArtifacts } from './output/commitArtifacts.js';
3
+ import { compileProject } from './compile/compileProject.js';
4
+ import { crudApplicationManagedPaths, emitCrudApplicationArtifacts } from './emit/crud/emitCrudApplicationArtifacts.js';
5
+ import { dynamicCrudFlowSchemaPaths, emitDynamicCrudFlowSchemas } from './emit/crud/emitDynamicCrudFlowSchemas.js';
6
+ import { customFlowApplicationManagedPaths, emitCustomFlowApplicationArtifacts } from './emit/custom/emitCustomFlowApplicationArtifacts.js';
7
+ import { emitDynamicRbacFlowSchemas, rbacFlowSchemaManagedPaths } from './emit/rbac/emitDynamicRbacFlowSchemas.js';
8
+ import { emitRbacApplicationArtifacts, rbacApplicationManagedPaths } from './emit/rbac/emitRbacApplicationArtifacts.js';
9
+ import { dynamicRelationshipFlowSchemaPaths, emitDynamicRelationshipFlowSchemas } from './emit/relationship/emitDynamicRelationshipFlowSchemas.js';
10
+ import { emitRelationshipApplicationArtifacts, relationshipApplicationManagedPaths } from './emit/relationship/emitRelationshipApplicationArtifacts.js';
11
+ import { emitResourceArtifacts, resourceArtifactPaths } from './emit/resource/emitResourceArtifacts.js';
12
+ import { loadLocalSchemaDirectory } from './compile/loadSchemas.js';
13
+ import { emitSystemWebSocketArtifacts, hasSystemWebSocket, systemWebSocketManagedPaths } from './emit/system/emitSystemWebSocketArtifacts.js';
14
+
15
+ export async function generate(rootPath, options = {}) {
16
+ const startedAt = Date.now();
17
+ const logger = options.logger;
18
+ logger?.info?.(`[INFO] [Generate] STATUS=STARTED | rootPath=${rootPath}`);
19
+ try {
20
+ const project = compileProject({ ...options, rootPath });
21
+ const [objects, relationships, flows] = await Promise.all([
22
+ loadLocalSchemaDirectory(project, 'ObjectSchemas'),
23
+ loadLocalSchemaDirectory(project, 'RelationshipSchemas'),
24
+ loadLocalSchemaDirectory(project, 'FlowSchemas')
25
+ ]);
26
+ logger?.debug?.(`[DEBUG] [Generate] STATUS=SCHEMAS_LOADED | objects=${objects.length} relationships=${relationships.length} flows=${flows.length}`);
27
+ const groups = await emitGroups({ project, objects, relationships, flows });
28
+ logger?.debug?.(`[DEBUG] [Generate] STATUS=ARTIFACTS_EMITTED | ${groups.map(group => `${group.scope}=${group.artifacts.length}`).join(' ')}`);
29
+ const files = groups.length === 0
30
+ ? []
31
+ : await commitArtifacts(buildGenerationPlan(project, groups.flatMap(group => group.artifacts), {
32
+ managedScopes: Object.fromEntries(groups.map(group => [group.scope, group.managedPaths]))
33
+ }));
34
+ const durationMs = Date.now() - startedAt;
35
+ logger?.info?.(`[INFO] [Generate] STATUS=FINISHED | files=${files.length} durationMs=${durationMs}`);
36
+
37
+ return { project, durationMs, files };
38
+ } catch (error) {
39
+ logger?.error?.(`[ERROR] [Generate] STATUS=FAILED | durationMs=${Date.now() - startedAt}`, error);
40
+ throw error;
87
41
  }
88
-
89
- const startTime = Date.now();
90
- await generateCode(rootPath, { outputPath, configPath });
91
- return { durationMs: Date.now() - startTime };
92
42
  }
93
43
 
94
- function patchFlowStepsValidationSchema() {
95
- const flowStepsSchema = basicValidatorSchema.basicFlowSchema?.properties?.flowSteps;
96
- if (!flowStepsSchema || flowStepsSchema.oneOf || !flowStepsSchema.items) {
97
- return;
98
- }
99
-
100
- const objectStepSchema = {
101
- ...flowStepsSchema.items,
102
- required: (flowStepsSchema.items.required || []).filter(
103
- item => item !== 'stepName'
104
- )
105
- };
106
-
107
- basicValidatorSchema.basicFlowSchema.properties.flowSteps = {
108
- oneOf: [
109
- flowStepsSchema,
110
- {
111
- type: 'object',
112
- minProperties: 1,
113
- patternProperties: {
114
- [basicValidatorSchema.strNotEmptyRegex]: objectStepSchema
115
- }
116
- }
117
- ]
118
- };
44
+ async function emitGroups({ project, objects, relationships, flows }) {
45
+ const [crud, relationship, rbac, system, resource] = await Promise.all([
46
+ emitCrudApplicationArtifacts({ objects, flows, serviceTag: project.serviceTag }),
47
+ emitRelationshipApplicationArtifacts({ relationships, flows, serviceTag: project.serviceTag }),
48
+ emitRbacApplicationArtifacts(objects),
49
+ emitSystemWebSocketArtifacts(flows, { includeRelationshipOwnTopic: true }),
50
+ emitResourceArtifacts({ objects, relationships, flows })
51
+ ]);
52
+ const custom = await emitCustomFlowApplicationArtifacts(flows, { systemFunctions: system.functions, objects });
53
+ return [
54
+ { scope: 'crud-flow-schemas', managedPaths: dynamicCrudFlowSchemaPaths, artifacts: emitDynamicCrudFlowSchemas({ objects, flows }) },
55
+ { scope: 'relationship-flow-schemas', managedPaths: dynamicRelationshipFlowSchemaPaths, artifacts: emitDynamicRelationshipFlowSchemas() },
56
+ { scope: 'rbac-flow-schemas', managedPaths: rbacFlowSchemaManagedPaths(objects), artifacts: await emitDynamicRbacFlowSchemas({ objects, serviceTag: project.serviceTag }) },
57
+ { scope: 'crud-application', managedPaths: crudApplicationManagedPaths(), artifacts: crud },
58
+ { scope: 'relationship-application', managedPaths: relationshipApplicationManagedPaths(), artifacts: relationship },
59
+ { scope: 'rbac-application', managedPaths: rbacApplicationManagedPaths(objects), artifacts: rbac },
60
+ { scope: 'system-websocket', managedPaths: systemWebSocketManagedPaths(), artifacts: system.artifacts },
61
+ { scope: 'custom-flow-application', managedPaths: customFlowApplicationManagedPaths(flows, { includeYaml: hasSystemWebSocket(flows, { includeRelationshipOwnTopic: true }) }), artifacts: custom },
62
+ { scope: 'shared-resources', managedPaths: resourceArtifactPaths, artifacts: resource }
63
+ ];
119
64
  }
120
-
121
- function createSilentLogger() {
122
- return {
123
- debug: () => {},
124
- info: () => {},
125
- warn: () => {},
126
- error: () => {}
127
- };
128
- }
129
-
130
- export { generate };
@@ -0,0 +1,213 @@
1
+ import { constants } from 'node:fs';
2
+ import { copyFile, lstat, mkdir, mkdtemp, readFile, realpath, rename, rm, unlink, writeFile } from 'node:fs/promises';
3
+ import { dirname, join, relative, resolve, sep } from 'node:path';
4
+
5
+ import { normalizeArtifactPaths, validateArtifacts } from './validateArtifacts.js';
6
+ import { mergeHooks } from './mergeHooks.js';
7
+
8
+ const MANAGED_ARTIFACTS_PATH = '.generate-service-code-v2-managed.json';
9
+ const STAGING_PREFIX = '.generate-service-code-v2-stage-';
10
+
11
+ export async function commitArtifacts(plan) {
12
+ if (!plan?.project?.outputPath || !Array.isArray(plan.artifacts)) {
13
+ throw new TypeError('GenerationPlan must include project.outputPath and artifacts');
14
+ }
15
+
16
+ const outputRoot = resolve(plan.project.outputPath);
17
+ const artifacts = validateArtifacts(plan.artifacts);
18
+ await mkdir(outputRoot, { recursive: true });
19
+ const physicalOutputRoot = await realpath(outputRoot);
20
+ const manifestPath = await resolveSafeTarget(physicalOutputRoot, MANAGED_ARTIFACTS_PATH);
21
+ const managedArtifacts = await loadManagedArtifacts(manifestPath);
22
+ const managedScopes = normalizeManagedScopes(plan);
23
+ const stalePaths = staleManagedPaths(managedScopes, managedArtifacts, artifacts);
24
+ const mergedArtifacts = await mergeHooks(physicalOutputRoot, artifacts);
25
+ const stagedRoot = await mkdtemp(join(physicalOutputRoot, STAGING_PREFIX));
26
+
27
+ try {
28
+ const changes = await stageChanges({
29
+ outputRoot: physicalOutputRoot,
30
+ stagedRoot,
31
+ artifacts: mergedArtifacts,
32
+ stalePaths,
33
+ manifestPath,
34
+ manifestContent: managedScopes
35
+ ? managedManifestContent(managedScopes, managedArtifacts, mergedArtifacts)
36
+ : undefined
37
+ });
38
+ const snapshots = await snapshotChanges(changes, stagedRoot);
39
+ try {
40
+ await applyChanges(changes);
41
+ } catch (error) {
42
+ await rollbackChanges(changes, snapshots);
43
+ throw error;
44
+ }
45
+ } finally {
46
+ await rm(stagedRoot, { recursive: true, force: true });
47
+ }
48
+
49
+ return mergedArtifacts.map(({ path }) => ({ path }));
50
+ }
51
+
52
+ function normalizeManagedScopes(plan) {
53
+ if (plan.managedScopes !== undefined) {
54
+ return plan.managedScopes;
55
+ }
56
+ if (plan.managedScope === undefined) {
57
+ return undefined;
58
+ }
59
+ return { [plan.managedScope]: normalizeArtifactPaths(plan.managedPaths ?? []) };
60
+ }
61
+
62
+ function staleManagedPaths(managedScopes, managedArtifacts, artifacts) {
63
+ if (!managedScopes) {
64
+ return [];
65
+ }
66
+ const emittedPaths = new Set(artifacts.map(artifact => artifact.path));
67
+ const stalePaths = new Set();
68
+ for (const [scope, declaredPaths] of Object.entries(managedScopes)) {
69
+ if (!Object.hasOwn(managedArtifacts, scope)) {
70
+ continue;
71
+ }
72
+ for (const path of [...declaredPaths, ...managedArtifacts[scope]]) {
73
+ if (!emittedPaths.has(path)) {
74
+ stalePaths.add(path);
75
+ }
76
+ }
77
+ }
78
+ return [...stalePaths];
79
+ }
80
+
81
+ function managedManifestContent(managedScopes, managedArtifacts, artifacts) {
82
+ const emittedPaths = new Set(artifacts.map(artifact => artifact.path));
83
+ const nextManifest = { ...managedArtifacts };
84
+ for (const [scope, paths] of Object.entries(managedScopes)) {
85
+ nextManifest[scope] = paths.filter(path => emittedPaths.has(path));
86
+ }
87
+ return `${JSON.stringify(nextManifest, null, 2)}\n`;
88
+ }
89
+
90
+ async function stageChanges({ outputRoot, stagedRoot, artifacts, stalePaths, manifestPath, manifestContent }) {
91
+ const changes = [];
92
+ for (const artifact of artifacts) {
93
+ const targetPath = await resolveSafeTarget(outputRoot, artifact.path);
94
+ const stagedPath = await resolveSafeTarget(stagedRoot, artifact.path, { createDirectories: true });
95
+ await writeFile(stagedPath, artifact.content, { encoding: 'utf8', flag: constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_NOFOLLOW });
96
+ changes.push({ targetPath, stagedPath });
97
+ }
98
+ for (const path of stalePaths) {
99
+ changes.push({ targetPath: await resolveSafeTarget(outputRoot, path), delete: true });
100
+ }
101
+ if (manifestContent !== undefined) {
102
+ const stagedPath = await resolveSafeTarget(stagedRoot, MANAGED_ARTIFACTS_PATH, { createDirectories: true });
103
+ await writeFile(stagedPath, manifestContent, 'utf8');
104
+ changes.push({ targetPath: manifestPath, stagedPath });
105
+ }
106
+ return changes;
107
+ }
108
+
109
+ async function snapshotChanges(changes, stagedRoot) {
110
+ const snapshots = new Map();
111
+ for (const [index, change] of changes.entries()) {
112
+ try {
113
+ const details = await lstat(change.targetPath);
114
+ if (!details.isFile()) {
115
+ throw new Error(`Artifact target is not a file: ${change.targetPath}`);
116
+ }
117
+ const backupPath = join(stagedRoot, `backup-${index}`);
118
+ await copyFile(change.targetPath, backupPath, constants.COPYFILE_EXCL);
119
+ snapshots.set(change.targetPath, { backupPath });
120
+ } catch (error) {
121
+ if (error.code === 'ENOENT') {
122
+ snapshots.set(change.targetPath, null);
123
+ continue;
124
+ }
125
+ throw error;
126
+ }
127
+ }
128
+ return snapshots;
129
+ }
130
+
131
+ async function applyChanges(changes) {
132
+ for (const change of changes) {
133
+ if (change.delete) {
134
+ await unlink(change.targetPath).catch(ignoreMissingFile);
135
+ continue;
136
+ }
137
+ await mkdir(dirname(change.targetPath), { recursive: true });
138
+ await rename(change.stagedPath, change.targetPath);
139
+ }
140
+ }
141
+
142
+ async function rollbackChanges(changes, snapshots) {
143
+ for (const change of [...changes].reverse()) {
144
+ const snapshot = snapshots.get(change.targetPath);
145
+ if (!snapshot) {
146
+ await unlink(change.targetPath).catch(ignoreMissingFile);
147
+ continue;
148
+ }
149
+ await mkdir(dirname(change.targetPath), { recursive: true });
150
+ await copyFile(snapshot.backupPath, change.targetPath);
151
+ }
152
+ }
153
+
154
+ function ignoreMissingFile(error) {
155
+ if (error.code !== 'ENOENT') {
156
+ throw error;
157
+ }
158
+ }
159
+
160
+ async function loadManagedArtifacts(manifestPath) {
161
+ try {
162
+ const parsed = JSON.parse(await readFile(manifestPath, 'utf8'));
163
+ if (!parsed || Array.isArray(parsed) || typeof parsed !== 'object') {
164
+ throw new TypeError('Managed artifact manifest must be an object');
165
+ }
166
+ for (const paths of Object.values(parsed)) {
167
+ normalizeArtifactPaths(paths);
168
+ }
169
+ return parsed;
170
+ } catch (error) {
171
+ if (error.code === 'ENOENT') {
172
+ return {};
173
+ }
174
+ throw error;
175
+ }
176
+ }
177
+
178
+ async function resolveSafeTarget(outputRoot, artifactPath, { createDirectories = false } = {}) {
179
+ const targetPath = resolve(outputRoot, artifactPath);
180
+ if (relative(outputRoot, targetPath).startsWith('..')) {
181
+ throw new Error(`Artifact path escapes output root: ${artifactPath}`);
182
+ }
183
+
184
+ let currentPath = outputRoot;
185
+ for (const segment of dirname(artifactPath).split(sep).filter(Boolean)) {
186
+ currentPath = join(currentPath, segment);
187
+ try {
188
+ const details = await lstat(currentPath);
189
+ if (details.isSymbolicLink() || !details.isDirectory()) {
190
+ throw new Error(`Artifact path traverses a non-directory: ${artifactPath}`);
191
+ }
192
+ } catch (error) {
193
+ if (error.code !== 'ENOENT') {
194
+ throw error;
195
+ }
196
+ if (!createDirectories) {
197
+ break;
198
+ }
199
+ await mkdir(currentPath, { recursive: true });
200
+ }
201
+ }
202
+
203
+ try {
204
+ if ((await lstat(targetPath)).isSymbolicLink()) {
205
+ throw new Error(`Artifact path targets a symlink: ${artifactPath}`);
206
+ }
207
+ } catch (error) {
208
+ if (error.code !== 'ENOENT') {
209
+ throw error;
210
+ }
211
+ }
212
+ return targetPath;
213
+ }
@@ -0,0 +1,55 @@
1
+ import { lstat, readFile } from 'node:fs/promises';
2
+ import { join, sep } from 'node:path';
3
+
4
+ export async function mergeHooks(outputRoot, artifacts) {
5
+ return Promise.all(artifacts.map(async artifact => ({
6
+ ...artifact,
7
+ content: await mergeHook(outputRoot, artifact)
8
+ })));
9
+ }
10
+
11
+ async function mergeHook(outputRoot, artifact) {
12
+ const parts = artifact.path.split(sep);
13
+ const sourceIndex = parts.lastIndexOf('source');
14
+ if (sourceIndex < 0 || sourceIndex === parts.length - 1) {
15
+ return artifact.content;
16
+ }
17
+
18
+ const hookPath = join(outputRoot, ...parts.slice(0, sourceIndex), 'hook', ...parts.slice(sourceIndex + 1));
19
+ try {
20
+ if (!(await lstat(hookPath)).isFile()) {
21
+ return artifact.content;
22
+ }
23
+ } catch (error) {
24
+ if (error.code === 'ENOENT') {
25
+ return artifact.content;
26
+ }
27
+ throw error;
28
+ }
29
+
30
+ const matchers = hookMatchers(artifact.path);
31
+ if (!matchers) {
32
+ return artifact.content;
33
+ }
34
+
35
+ const hookContent = await readFile(hookPath, 'utf8');
36
+ return artifact.content.replace(matchers.anyTag, (match, tagName) => (
37
+ hookContent.match(matchers.tagPattern(tagName))?.[0] ?? match
38
+ ));
39
+ }
40
+
41
+ function hookMatchers(filePath) {
42
+ if (filePath.endsWith('.js')) {
43
+ return {
44
+ anyTag: /\/\/\(<(\w+)>\)([\s\S]*?)\/\/\(<\/\1>\)/gm,
45
+ tagPattern: name => new RegExp(`\\/\\/\\(<${name}>\\)([\\s\\S]*?)\\/\\/\\(<\\/${name}>\\)`, 'gm')
46
+ };
47
+ }
48
+ if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) {
49
+ return {
50
+ anyTag: /#<#(\w+)#>([\s\S]*?)#<#\/\1#>/gm,
51
+ tagPattern: name => new RegExp(`#<#${name}#>([\\s\\S]*?)#<#\\/${name}#>`, 'gm')
52
+ };
53
+ }
54
+ return null;
55
+ }