@izara_project/izara-core-generate-service-code 1.0.96 → 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 +1 -1
  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/{rbac → application/rbac}/emitRbacApplicationArtifacts.js +2 -2
  15. package/src/emit/{rbac → application/rbac}/generateCreateTargetRoleHandler.js +2 -2
  16. package/src/emit/{rbac → application/rbac}/generateDynamicRbacFlowSchemas.js +2 -2
  17. package/src/emit/{relationship → application/relationship}/emitRelationshipApplicationArtifacts.js +3 -3
  18. package/src/emit/{relationship → application/relationship}/generateDynamicRelationshipFlowSchemas.js +2 -2
  19. package/src/emit/{relationship → application/relationship}/generateRelationshipApplicationArtifacts.js +2 -2
  20. package/src/emit/{system → application/system}/emitSystemFindDataArtifacts.js +1 -1
  21. package/src/emit/{resource → infrastructure/resources}/generateResourceArtifacts.js +2 -2
  22. package/src/emit/{resource → infrastructure/resources}/iamResourceArtifacts.js +2 -2
  23. package/src/emit/{resource → infrastructure/resources}/resourceState.js +4 -4
  24. package/src/emit/schemas/ledger/emitLedgerSchemas.js +370 -0
  25. package/src/emit/{systemText → schemas/systemText}/emitSystemTextSchemas.js +1 -1
  26. package/src/generate.js +46 -261
  27. package/src/{generateIntTest.js → intTest/generateIntTest.js} +2 -2
  28. package/src/{generateResourceIntTest.js → intTest/generateResourceIntTest.js} +2 -2
  29. package/src/plan/domainRegistry.js +271 -0
  30. package/test/helpers/testProject.js +127 -0
  31. package/test/helpers/testProject.test.js +57 -0
  32. package/test/{core.test.js → integration/core.test.js} +3 -3
  33. package/test/{graphDrivenFlowSchema.test.js → integration/graphDrivenFlowSchema.test.js} +1 -1
  34. package/test/{intTestApi.test.js → integration/intTestApi.test.js} +1 -1
  35. package/test/{publicApi.test.js → integration/publicApi.test.js} +1 -1
  36. package/test/{createTargetRoleHandler.test.js → unit/application/createTargetRoleHandler.test.js} +1 -1
  37. package/test/{crudApplicationArtifacts.test.js → unit/application/crudApplicationArtifacts.test.js} +1 -1
  38. package/test/{customFlowApplicationArtifacts.test.js → unit/application/customFlowApplicationArtifacts.test.js} +9 -9
  39. package/test/{relationshipApplicationArtifacts.test.js → unit/application/relationshipApplicationArtifacts.test.js} +1 -1
  40. package/test/{systemFindDataArtifacts.test.js → unit/application/systemFindDataArtifacts.test.js} +1 -1
  41. package/test/{functionYamlArtifact.test.js → unit/infrastructure/functionYamlArtifact.test.js} +1 -1
  42. package/test/{resourceArtifacts.test.js → unit/infrastructure/resourceArtifacts.test.js} +1 -1
  43. package/test/{attributeTreeSchemas.test.js → unit/schemas/attributeTreeSchemas.test.js} +41 -46
  44. package/test/{dynamicCrudFlowSchemas.test.js → unit/schemas/dynamicCrudFlowSchemas.test.js} +2 -2
  45. package/test/{dynamicRbacFlowSchemas.test.js → unit/schemas/dynamicRbacFlowSchemas.test.js} +1 -1
  46. package/test/{dynamicRelationshipFlowSchemas.test.js → unit/schemas/dynamicRelationshipFlowSchemas.test.js} +11 -1
  47. package/test/{errorSchemas.test.js → unit/schemas/errorSchemas.test.js} +2 -2
  48. package/test/unit/schemas/ledgerSchemas.test.js +263 -0
  49. package/test/{systemTextSchemas.test.js → unit/schemas/systemTextSchemas.test.js} +24 -36
  50. package/src/emit/crud/loadLocalSchemaArrays.js +0 -4
  51. /package/src/emit/{coreFunction → application/coreFunction}/emitCoreFunctionArtifacts.js +0 -0
  52. /package/src/emit/{coreFunction → application/coreFunction}/templates/CoreFunction_Yaml.ejs +0 -0
  53. /package/src/emit/{coreFunction → application/coreFunction}/templates/CoreResource_Yaml.ejs +0 -0
  54. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataDynamo_HdrInv.ejs +0 -0
  55. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataDynamo_Main.ejs +0 -0
  56. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataGraphData_HdrInv.ejs +0 -0
  57. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataGraphData_Main.ejs +0 -0
  58. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataGraphSchema_HdrInv.ejs +0 -0
  59. /package/src/emit/{coreFunction → application/coreFunction}/templates/GenerateSeedDataGraphSchema_Main.ejs +0 -0
  60. /package/src/emit/{coreFunction → application/coreFunction}/templates/GeneratedGraphNodeSchemas.ejs +0 -0
  61. /package/src/emit/{coreFunction → application/coreFunction}/templates/GeneratedGraphRelSchemas.ejs +0 -0
  62. /package/src/emit/{coreFunction → application/coreFunction}/templates/GeneratedTableConfigs.ejs +0 -0
  63. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupConfig.ejs +0 -0
  64. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner.ejs +0 -0
  65. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_initialSetup.ejs +0 -0
  66. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_seedDynamo.ejs +0 -0
  67. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_seedGraph.ejs +0 -0
  68. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_seedRemove.ejs +0 -0
  69. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetupRunner_uploadSchema.ejs +0 -0
  70. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetup_HdrInv.ejs +0 -0
  71. /package/src/emit/{coreFunction → application/coreFunction}/templates/InitialSetup_Main.ejs +0 -0
  72. /package/src/emit/{coreFunction → application/coreFunction}/templates/RemoveSeedDataDynamo_HdrInv.ejs +0 -0
  73. /package/src/emit/{coreFunction → application/coreFunction}/templates/RemoveSeedDataDynamo_Main.ejs +0 -0
  74. /package/src/emit/{coreFunction → application/coreFunction}/templates/UploadSchema_HdrInv.ejs +0 -0
  75. /package/src/emit/{coreFunction → application/coreFunction}/templates/UploadSchema_Main.ejs +0 -0
  76. /package/src/emit/{crud → application/crud}/crudActionPlan.js +0 -0
  77. /package/src/emit/{crud → application/crud}/dynamicCrudFlowSchemaTemplate.js +0 -0
  78. /package/src/emit/{crud → application/crud}/emitDynamicCrudFlowSchemas.js +0 -0
  79. /package/src/emit/{crud → application/crud}/templates/CreateAfterHookCallback_Main.ejs +0 -0
  80. /package/src/emit/{crud → application/crud}/templates/CreateBeforeHookCallback_Main.ejs +0 -0
  81. /package/src/emit/{crud → application/crud}/templates/CreateComplete_Main.ejs +0 -0
  82. /package/src/emit/{crud → application/crud}/templates/CreateConfirmComplete_Main.ejs +0 -0
  83. /package/src/emit/{crud → application/crud}/templates/CreateEndpoint_Main.ejs +0 -0
  84. /package/src/emit/{crud → application/crud}/templates/CreateLogicalLib.ejs +0 -0
  85. /package/src/emit/{crud → application/crud}/templates/CreateNodeCallback_Main.ejs +0 -0
  86. /package/src/emit/{crud → application/crud}/templates/DeleteAfterHookCallback_Main.ejs +0 -0
  87. /package/src/emit/{crud → application/crud}/templates/DeleteBeforeHookCallback_Main.ejs +0 -0
  88. /package/src/emit/{crud → application/crud}/templates/DeleteComplete_Main.ejs +0 -0
  89. /package/src/emit/{crud → application/crud}/templates/DeleteEndpoint_Main.ejs +0 -0
  90. /package/src/emit/{crud → application/crud}/templates/DeleteLogicalLib.ejs +0 -0
  91. /package/src/emit/{crud → application/crud}/templates/FlowEndpointRbacCallback_Main.ejs +0 -0
  92. /package/src/emit/{crud → application/crud}/templates/FlowEndpoint_HdrWbs.ejs +0 -0
  93. /package/src/emit/{crud → application/crud}/templates/FlowMain_Wbs.ejs +0 -0
  94. /package/src/emit/{crud → application/crud}/templates/GetEndpoint_Main.ejs +0 -0
  95. /package/src/emit/{crud → application/crud}/templates/GetRangeEndpoint_Main.ejs +0 -0
  96. /package/src/emit/{crud → application/crud}/templates/UpdateAfterHookCallback_Main.ejs +0 -0
  97. /package/src/emit/{crud → application/crud}/templates/UpdateBeforeHookCallback_Main.ejs +0 -0
  98. /package/src/emit/{crud → application/crud}/templates/UpdateComplete_Main.ejs +0 -0
  99. /package/src/emit/{crud → application/crud}/templates/UpdateEndpoint_Main.ejs +0 -0
  100. /package/src/emit/{crud → application/crud}/templates/UpdateLogicalLib.ejs +0 -0
  101. /package/src/emit/{custom → application/custom}/customFlowPaths.js +0 -0
  102. /package/src/emit/{custom → application/custom}/customFlows.js +0 -0
  103. /package/src/emit/{custom → application/custom}/templates/FlowEndpointRbacCallback_Main.ejs +0 -0
  104. /package/src/emit/{custom → application/custom}/templates/FlowEndpoint_Main.ejs +0 -0
  105. /package/src/emit/{custom → application/custom}/templates/FlowStep_Main.ejs +0 -0
  106. /package/src/emit/{custom → application/custom}/templates/s3/ConfirmReserved_HdrSqs.ejs +0 -0
  107. /package/src/emit/{custom → application/custom}/templates/s3/ConfirmReserved_Main.ejs +0 -0
  108. /package/src/emit/{custom → application/custom}/templates/s3/CreateObject_HdrWbs.ejs +0 -0
  109. /package/src/emit/{custom → application/custom}/templates/s3/CreateObject_Main.ejs +0 -0
  110. /package/src/emit/{custom → application/custom}/templates/s3/CreatePreSignUrl_HdrSqs.ejs +0 -0
  111. /package/src/emit/{custom → application/custom}/templates/s3/CreatePreSignUrl_Main.ejs +0 -0
  112. /package/src/emit/{custom → application/custom}/templates/s3/FlowHandler_HdrS3.ejs +0 -0
  113. /package/src/emit/{custom → application/custom}/templates/s3/ProcessS3File_Main.ejs +0 -0
  114. /package/src/emit/{custom → application/custom}/templates/s3/ReservedLimit_HdrSqs.ejs +0 -0
  115. /package/src/emit/{custom → application/custom}/templates/s3/ReservedLimit_Main.ejs +0 -0
  116. /package/src/emit/{custom → application/custom}/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +0 -0
  117. /package/src/emit/{custom → application/custom}/templates/triggerCache/CheckTriggerCache_Main.ejs +0 -0
  118. /package/src/emit/{custom → application/custom}/templates/triggerCache/TriggerCacheComplete_Main.ejs +0 -0
  119. /package/src/emit/{custom → application/custom}/templates/triggerCache/TriggerCache_Main.ejs +0 -0
  120. /package/src/emit/{rbac → application/rbac}/emitDynamicRbacFlowSchemas.js +0 -0
  121. /package/src/emit/{rbac → application/rbac}/rbacFlowTag.js +0 -0
  122. /package/src/emit/{rbac → application/rbac}/templates/CancelUsage_Main.ejs +0 -0
  123. /package/src/emit/{rbac → application/rbac}/templates/ConfirmUsage_Main.ejs +0 -0
  124. /package/src/emit/{rbac → application/rbac}/templates/CreateTargetRole_HdrSqs.ejs +0 -0
  125. /package/src/emit/{rbac → application/rbac}/templates/CreateTargetRole_Main.ejs +0 -0
  126. /package/src/emit/{rbac → application/rbac}/templates/DeleteTargetRole_Main.ejs +0 -0
  127. /package/src/emit/{rbac → application/rbac}/templates/DynamicRbacFlowSchema.ejs +0 -0
  128. /package/src/emit/{rbac → application/rbac}/templates/GetMyPermissions_Main.ejs +0 -0
  129. /package/src/emit/{rbac → application/rbac}/templates/GetTargetRole_Main.ejs +0 -0
  130. /package/src/emit/{rbac → application/rbac}/templates/ListRbac_HdrApi.ejs +0 -0
  131. /package/src/emit/{rbac → application/rbac}/templates/ListRbac_HdrSqs.ejs +0 -0
  132. /package/src/emit/{rbac → application/rbac}/templates/ListRbac_Main.ejs +0 -0
  133. /package/src/emit/{rbac → application/rbac}/templates/RbacMutation_Main.ejs +0 -0
  134. /package/src/emit/{rbac → application/rbac}/templates/ReservedDynamicUsage_Main.ejs +0 -0
  135. /package/src/emit/{rbac → application/rbac}/templates/UpdateTargetRole_Main.ejs +0 -0
  136. /package/src/emit/{rbac → application/rbac}/templates/UserRbacFlow_HdrSqs.ejs +0 -0
  137. /package/src/emit/{rbac → application/rbac}/templates/UserRbacFlow_Main.ejs +0 -0
  138. /package/src/emit/{rbac → application/rbac}/templates/UserRoleMutation_Main.ejs +0 -0
  139. /package/src/emit/{relationship → application/relationship}/emitDynamicRelationshipFlowSchemas.js +0 -0
  140. /package/src/emit/{relationship → application/relationship}/templates/ChangeRelationshipComplete_HdrSqs.ejs +0 -0
  141. /package/src/emit/{relationship → application/relationship}/templates/ChangeRelationshipComplete_Main.ejs +0 -0
  142. /package/src/emit/{relationship → application/relationship}/templates/ChangeRelationship_Main.ejs +0 -0
  143. /package/src/emit/{relationship → application/relationship}/templates/CreateRelationshipComplete_HdrSqs.ejs +0 -0
  144. /package/src/emit/{relationship → application/relationship}/templates/CreateRelationshipComplete_Main.ejs +0 -0
  145. /package/src/emit/{relationship → application/relationship}/templates/CreateRelationship_Main.ejs +0 -0
  146. /package/src/emit/{relationship → application/relationship}/templates/DeleteRelationshipComplete_HdrSqs.ejs +0 -0
  147. /package/src/emit/{relationship → application/relationship}/templates/DeleteRelationshipComplete_Main.ejs +0 -0
  148. /package/src/emit/{relationship → application/relationship}/templates/DeleteRelationship_Main.ejs +0 -0
  149. /package/src/emit/{relationship → application/relationship}/templates/GetRelationshipComplete_HdrSqs.ejs +0 -0
  150. /package/src/emit/{relationship → application/relationship}/templates/GetRelationshipComplete_Main.ejs +0 -0
  151. /package/src/emit/{relationship → application/relationship}/templates/GetRelationship_Main.ejs +0 -0
  152. /package/src/emit/{relationship → application/relationship}/templates/MoveRelationshipComplete_HdrSqs.ejs +0 -0
  153. /package/src/emit/{relationship → application/relationship}/templates/MoveRelationshipComplete_Main.ejs +0 -0
  154. /package/src/emit/{relationship → application/relationship}/templates/MoveRelationship_Main.ejs +0 -0
  155. /package/src/emit/{relationship → application/relationship}/templates/UpdateRelationshipComplete_HdrSqs.ejs +0 -0
  156. /package/src/emit/{relationship → application/relationship}/templates/UpdateRelationshipComplete_Main.ejs +0 -0
  157. /package/src/emit/{relationship → application/relationship}/templates/UpdateRelationship_Main.ejs +0 -0
  158. /package/src/emit/{system → application/system}/emitSystemWebSocketArtifacts.js +0 -0
  159. /package/src/emit/{system → application/system}/templates/RegisterComplete_HdrSqs.ejs +0 -0
  160. /package/src/emit/{system → application/system}/templates/RegisterComplete_Main.ejs +0 -0
  161. /package/src/emit/{system → application/system}/templates/RegisterComplete_Yaml.ejs +0 -0
  162. /package/src/emit/{system → application/system}/templates/RegisterWbs_Yaml.ejs +0 -0
  163. /package/src/emit/{system → application/system}/templates/Register_HdrWbs.ejs +0 -0
  164. /package/src/emit/{system → application/system}/templates/Register_Main.ejs +0 -0
  165. /package/src/emit/{system → application/system}/templates/WebSocketComplete_HdrSqs.ejs +0 -0
  166. /package/src/emit/{system → application/system}/templates/WebSocketComplete_Main.ejs +0 -0
  167. /package/src/emit/{system → application/system}/templates/WebSocketComplete_Yaml.ejs +0 -0
  168. /package/src/emit/{system → application/system}/templates/WebSocketConnect.ejs +0 -0
  169. /package/src/emit/{system → application/system}/templates/WebSocketConnect_Yaml.ejs +0 -0
  170. /package/src/emit/{function → infrastructure/functions}/functionYamlArtifact.js +0 -0
  171. /package/src/emit/{function → infrastructure/functions}/templates/ApiFunction_Yaml.ejs +0 -0
  172. /package/src/emit/{function → infrastructure/functions}/templates/EventBridgeFunction_Yaml.ejs +0 -0
  173. /package/src/emit/{function → infrastructure/functions}/templates/InvFunction_Yaml.ejs +0 -0
  174. /package/src/emit/{function → infrastructure/functions}/templates/S3Function_Yaml.ejs +0 -0
  175. /package/src/emit/{function → infrastructure/functions}/templates/SqsFunction_Yaml.ejs +0 -0
  176. /package/src/emit/{function → infrastructure/functions}/templates/WbsFunction_Yaml.ejs +0 -0
  177. /package/src/emit/{resource → infrastructure/resources}/dynamoResourceArtifacts.js +0 -0
  178. /package/src/emit/{resource → infrastructure/resources}/emitResourceArtifacts.js +0 -0
  179. /package/src/emit/{resource → infrastructure/resources}/resourceTemplate.js +0 -0
  180. /package/src/emit/{resource → infrastructure/resources}/s3ResourceArtifacts.js +0 -0
  181. /package/src/emit/{resource → infrastructure/resources}/sqsResourceArtifacts.js +0 -0
  182. /package/src/emit/{resource → infrastructure/resources}/templates/DynamoDBTable_Yaml.ejs +0 -0
  183. /package/src/emit/{resource → infrastructure/resources}/templates/FlowOut_Yaml.ejs +0 -0
  184. /package/src/emit/{resource → infrastructure/resources}/templates/GeneratedLambdaRoleServiceConfig.ejs +0 -0
  185. /package/src/emit/{resource → infrastructure/resources}/templates/ResourceSqsYaml.ejs +0 -0
  186. /package/src/emit/{resource → infrastructure/resources}/templates/ResourceYaml.ejs +0 -0
  187. /package/src/emit/{resource → infrastructure/resources}/templates/S3Bucket_Yaml.ejs +0 -0
  188. /package/src/emit/{resource → infrastructure/resources}/templates/S3Subscription_Yaml.ejs +0 -0
  189. /package/src/emit/{resource → infrastructure/resources}/templates/SharedResource_Yaml.ejs +0 -0
  190. /package/src/emit/{resource → infrastructure/resources}/templates/SystemDynamoDB_Yaml.ejs +0 -0
  191. /package/src/emit/{resource → infrastructure/resources}/templates/WebSocketSubscription_Yaml.ejs +0 -0
  192. /package/src/emit/{attributeTree → schemas/attributeTree}/emitAttributeTreeSchemas.js +0 -0
  193. /package/src/emit/{attributeTree → schemas/attributeTree}/emitAttributeTreeTargetSchemas.js +0 -0
  194. /package/src/emit/{attributeTree → schemas/attributeTree}/resolveTargetServicePath.js +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
  );
@@ -1466,7 +1466,7 @@ test('emits canonical checkStatusField and hooks in FlowEndpoint_Main for status
1466
1466
  });
1467
1467
 
1468
1468
  test('does not emit RbacCallback artifacts or duplicate artifact paths for custom flow with RBAC', async () => {
1469
- const { generate } = await import('../src/generate.js');
1469
+ const { generate } = await import('../../../src/generate.js');
1470
1470
  const rootPath = await createProject();
1471
1471
  await writeFile(
1472
1472
  join(rootPath, 'app/src/schemas/ObjectSchemas/ComAcc.js'),
@@ -1539,7 +1539,7 @@ test('does not emit RbacCallback artifacts or duplicate artifact paths for custo
1539
1539
  });
1540
1540
 
1541
1541
  test('skips checkRbacPermission in FlowEndpoint_Main when initiateBy is systemNoUser', async () => {
1542
- const { generate } = await import('../src/generate.js');
1542
+ const { generate } = await import('../../../src/generate.js');
1543
1543
  const rootPath = await createProject();
1544
1544
  await writeFile(
1545
1545
  join(rootPath, 'app/src/schemas/ObjectSchemas/ComAcc.js'),
@@ -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(() =>
@@ -1,5 +1,5 @@
1
1
  import assert from 'node:assert/strict';
2
- import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { mkdir, mkdtemp } from 'node:fs/promises';
3
3
  import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import test, { after } from 'node:test';
@@ -11,17 +11,18 @@ import {
11
11
  attributeTreeRelationshipSchemaManagedPaths,
12
12
  resolveTargetServicePath,
13
13
  emitAttributeTreeTargetSchemas
14
- } from '../src/emit/attributeTree/emitAttributeTreeSchemas.js';
15
- import { generate } from '../src/generate.js';
16
-
17
- const projectRoots = new Set();
14
+ } from '../../../src/emit/schemas/attributeTree/emitAttributeTreeSchemas.js';
15
+ import { generate } from '../../../src/generate.js';
16
+ import {
17
+ createTestProject,
18
+ readProjectFile,
19
+ writeProjectFile,
20
+ cleanupTestProjects,
21
+ trackTestProject
22
+ } from '../../helpers/testProject.js';
18
23
 
19
24
  after(async () => {
20
- await Promise.all(
21
- [...projectRoots].map((rootPath) =>
22
- rm(rootPath, { recursive: true, force: true })
23
- )
24
- );
25
+ await cleanupTestProjects();
25
26
  });
26
27
 
27
28
  test('emitAttributeTreeObjectSchemas returns 3 object schemas per attributeTree tag', () => {
@@ -149,23 +150,19 @@ test('managed paths return empty array when no attributeTree is present', () =>
149
150
 
150
151
  test('generate commits and cleans up attributeTree dynamic schemas', async () => {
151
152
  const rootPath = await createProjectWithAttributeTree({ hasAddOn: true });
152
- const result = await generate(rootPath);
153
+ await generate(rootPath);
153
154
 
154
- const expectedObjectPath = join(
155
- rootPath,
156
- 'app/src/schemas/ObjectSchemas/generatedAttributeTree/sellOfferTermLink.js'
157
- );
158
- const expectedRelPath = join(
159
- rootPath,
160
- 'app/src/schemas/RelationshipSchemas/generatedAttributeTree/hasSellOfferTermLink.js'
161
- );
155
+ const objectRelPath =
156
+ 'app/src/schemas/ObjectSchemas/generatedAttributeTree/sellOfferTermLink.js';
157
+ const relRelPath =
158
+ 'app/src/schemas/RelationshipSchemas/generatedAttributeTree/hasSellOfferTermLink.js';
162
159
 
163
- const objectContent = await readFile(expectedObjectPath, 'utf8');
160
+ const objectContent = await readProjectFile(rootPath, objectRelPath);
164
161
  assert.match(objectContent, /sellOfferTermLink/);
165
162
  assert.match(objectContent, /GraphHandler/);
166
163
  assert.doesNotMatch(objectContent, /dynamoDB/);
167
164
 
168
- const relContent = await readFile(expectedRelPath, 'utf8');
165
+ const relContent = await readProjectFile(rootPath, relRelPath);
169
166
  assert.match(relContent, /hasSellOfferTermLink/);
170
167
  assert.match(relContent, /sellOfferTermLink/);
171
168
 
@@ -173,10 +170,10 @@ test('generate commits and cleans up attributeTree dynamic schemas', async () =>
173
170
  await createProjectWithAttributeTree({ rootPath, hasAddOn: false });
174
171
  await generate(rootPath);
175
172
 
176
- await assert.rejects(readFile(expectedObjectPath, 'utf8'), {
173
+ await assert.rejects(readProjectFile(rootPath, objectRelPath), {
177
174
  code: 'ENOENT'
178
175
  });
179
- await assert.rejects(readFile(expectedRelPath, 'utf8'), {
176
+ await assert.rejects(readProjectFile(rootPath, relRelPath), {
180
177
  code: 'ENOENT'
181
178
  });
182
179
  });
@@ -185,21 +182,6 @@ async function createProjectWithAttributeTree({
185
182
  rootPath: existingRoot,
186
183
  hasAddOn = true
187
184
  } = {}) {
188
- const rootPath =
189
- existingRoot || (await mkdtemp(join(tmpdir(), 'izara-attr-tree-test-')));
190
- projectRoots.add(rootPath);
191
-
192
- const schemaRoot = join(rootPath, 'app/src/schemas');
193
- await mkdir(join(schemaRoot, 'ObjectSchemas'), { recursive: true });
194
- await mkdir(join(schemaRoot, 'RelationshipSchemas'), { recursive: true });
195
- await mkdir(join(schemaRoot, 'FlowSchemas'), { recursive: true });
196
- await mkdir(join(rootPath, 'config'), { recursive: true });
197
-
198
- await writeFile(
199
- join(rootPath, 'config/serverless.config.yml'),
200
- 'service: SellOfferManager\ncustom:\n serviceTag: SellOfferManager\n'
201
- );
202
-
203
185
  const addOnContent = hasAddOn
204
186
  ? `
205
187
  addOnDataStructure: [
@@ -210,9 +192,7 @@ async function createProjectWithAttributeTree({
210
192
  ],`
211
193
  : ' addOnDataStructure: [],';
212
194
 
213
- await writeFile(
214
- join(schemaRoot, 'ObjectSchemas/SellOffer.js'),
215
- `export default [
195
+ const schemaContent = `export default [
216
196
  {
217
197
  objectType: 'sellOffer',
218
198
  canDelete: false,
@@ -244,15 +224,30 @@ async function createProjectWithAttributeTree({
244
224
  ]
245
225
  }
246
226
  ];
247
- `
248
- );
227
+ `;
228
+
229
+ if (existingRoot) {
230
+ await writeProjectFile(
231
+ existingRoot,
232
+ 'app/src/schemas/ObjectSchemas/SellOffer.js',
233
+ schemaContent
234
+ );
235
+ return existingRoot;
236
+ }
249
237
 
250
- return rootPath;
238
+ return await createTestProject({
239
+ prefix: 'izara-attr-tree-test-',
240
+ serviceTag: 'SellOfferManager',
241
+ schemas: {
242
+ 'ObjectSchemas/SellOffer.js': schemaContent
243
+ }
244
+ });
251
245
  }
252
246
 
253
247
  test('resolveTargetServicePath prioritizes dev suffix and matches attributeTag', async () => {
254
- const tmpRoot = await mkdtemp(join(tmpdir(), 'izara-services-test-'));
255
- projectRoots.add(tmpRoot);
248
+ const tmpRoot = trackTestProject(
249
+ await mkdtemp(join(tmpdir(), 'izara-services-test-'))
250
+ );
256
251
 
257
252
  const currentServiceDir = join(
258
253
  tmpRoot,
@@ -5,8 +5,8 @@ import { join } from 'node:path';
5
5
  import test from 'node:test';
6
6
  import { pathToFileURL } from 'node:url';
7
7
 
8
- import { generateDynamicCrudFlowSchemas } from '../src/emit/crud/generateDynamicCrudFlowSchemas.js';
9
- import { createCrudActionPlans } from '../src/emit/crud/crudActionPlan.js';
8
+ import { generateDynamicCrudFlowSchemas } from '../../../src/emit/application/crud/generateDynamicCrudFlowSchemas.js';
9
+ import { createCrudActionPlans } from '../../../src/emit/application/crud/crudActionPlan.js';
10
10
 
11
11
  test('generates dynamic CRUD schemas from local schema modules', async () => {
12
12
  const rootPath = await createProject({
@@ -5,7 +5,7 @@ import { join } from 'node:path';
5
5
  import test, { after } from 'node:test';
6
6
  import { pathToFileURL } from 'node:url';
7
7
 
8
- import { generateDynamicRbacFlowSchemas } from '../src/emit/rbac/generateDynamicRbacFlowSchemas.js';
8
+ import { generateDynamicRbacFlowSchemas } from '../../../src/emit/application/rbac/generateDynamicRbacFlowSchemas.js';
9
9
 
10
10
  const projectRoots = new Set();
11
11
  const STATIC_RBAC_ACTIONS = [
@@ -5,7 +5,7 @@ import { join } from 'node:path';
5
5
  import test, { after } from 'node:test';
6
6
  import { pathToFileURL } from 'node:url';
7
7
 
8
- import { generateDynamicRelationshipFlowSchemas } from '../src/emit/relationship/generateDynamicRelationshipFlowSchemas.js';
8
+ import { generateDynamicRelationshipFlowSchemas } from '../../../src/emit/application/relationship/generateDynamicRelationshipFlowSchemas.js';
9
9
 
10
10
  const RELATIONSHIP_ACTIONS = [
11
11
  'CreateRelationship',
@@ -60,6 +60,16 @@ test('generates dynamic relationship schemas when declared relationships exist',
60
60
  'userId',
61
61
  'correlationId'
62
62
  ]);
63
+ const completeStep = create.flowSteps.find(
64
+ (step) => step.stepName === 'Complete'
65
+ );
66
+ assert.deepEqual(completeStep.properties, [
67
+ 'returnValue',
68
+ 'parentFlowId',
69
+ 'status',
70
+ 'foundErrors',
71
+ 'graphServiceTag'
72
+ ]);
63
73
  assert.deepEqual(get.event, [
64
74
  'lambdaSyncInv',
65
75
  'lambdaSyncApi',
@@ -8,8 +8,8 @@ import {
8
8
  emitErrorSchemas,
9
9
  errorSchemaManagedPaths,
10
10
  ERROR_SCHEMA_PATH
11
- } from '../src/emit/error/emitErrorSchemas.js';
12
- import { generate } from '../src/generate.js';
11
+ } from '../../../src/emit/schemas/error/emitErrorSchemas.js';
12
+ import { generate } from '../../../src/generate.js';
13
13
 
14
14
  const roots = new Set();
15
15
  after(() =>