@izara_project/izara-core-generate-service-code 1.0.67 → 1.0.69
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.
- package/.prettierrc +11 -0
- package/package.json +16 -12
- package/scripts/format-ejs.js +104 -0
- package/src/compile/compileProject.js +40 -9
- package/src/compile/loadSchemas.js +120 -11
- package/src/emit/crud/emitCrudApplicationArtifacts.js +188 -41
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +34 -18
- package/src/emit/crud/generateCrudApplicationArtifacts.js +14 -6
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +296 -105
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +222 -144
- package/src/emit/crud/templates/FlowEndpointBeforeLogical_Main.ejs +22 -6
- package/src/emit/crud/templates/FlowEndpointComplete_Main.ejs +134 -43
- package/src/emit/crud/templates/FlowEndpoint_HdrWbs.ejs +51 -31
- package/src/emit/crud/templates/FlowHandler_HdrApi.ejs +53 -45
- package/src/emit/crud/templates/FlowHandler_HdrInv.ejs +28 -26
- package/src/emit/crud/templates/FlowHandler_HdrSqs.ejs +15 -11
- package/src/emit/crud/templates/FlowMain_Wbs.ejs +53 -38
- package/src/emit/crud/templates/GetEndpoint_Main.ejs +6 -3
- package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +2 -2
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +402 -249
- package/src/emit/custom/customFlows.js +68 -28
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +520 -123
- package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +28 -8
- package/src/emit/custom/templates/FlowEndpoint_Main.ejs +48 -36
- package/src/emit/custom/templates/FlowStep_Main.ejs +7 -9
- package/src/emit/custom/templates/s3/ConfirmReserved_HdrSqs.ejs +59 -54
- package/src/emit/custom/templates/s3/ConfirmReserved_Main.ejs +33 -23
- package/src/emit/custom/templates/s3/CreateObject_HdrWbs.ejs +30 -23
- package/src/emit/custom/templates/s3/CreateObject_Main.ejs +56 -39
- package/src/emit/custom/templates/s3/CreatePreSignUrl_HdrSqs.ejs +56 -51
- package/src/emit/custom/templates/s3/CreatePreSignUrl_Main.ejs +112 -75
- package/src/emit/custom/templates/s3/FlowHandler_HdrS3.ejs +14 -9
- package/src/emit/custom/templates/s3/ProcessS3File_Main.ejs +11 -8
- package/src/emit/custom/templates/s3/ReservedLimit_HdrSqs.ejs +65 -56
- package/src/emit/custom/templates/s3/ReservedLimit_Main.ejs +74 -52
- package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +58 -14
- package/src/emit/custom/templates/triggerCache/CheckTriggerCache_Main.ejs +12 -17
- package/src/emit/custom/templates/triggerCache/TriggerCacheComplete_Main.ejs +20 -13
- package/src/emit/custom/templates/triggerCache/TriggerCache_Main.ejs +4 -1
- package/src/emit/function/functionYamlArtifact.js +272 -79
- package/src/emit/function/templates/ApiFunction_Yaml.ejs +7 -0
- package/src/emit/function/templates/EventBridgeFunction_Yaml.ejs +6 -0
- package/src/emit/function/templates/InvFunction_Yaml.ejs +5 -0
- package/src/emit/function/templates/S3Function_Yaml.ejs +16 -0
- package/src/emit/function/templates/SqsFunction_Yaml.ejs +10 -0
- package/src/emit/function/templates/WbsFunction_Yaml.ejs +10 -0
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +40 -29
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +171 -72
- package/src/emit/rbac/generateCreateTargetRoleHandler.js +6 -4
- package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +8 -2
- package/src/emit/rbac/rbacFlowTag.js +3 -1
- package/src/emit/rbac/templates/CreateTargetRole_HdrSqs.ejs +41 -18
- package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +23 -3
- package/src/emit/rbac/templates/ListRbac_HdrApi.ejs +27 -5
- package/src/emit/rbac/templates/ListRbac_HdrSqs.ejs +41 -8
- package/src/emit/rbac/templates/ListRbac_Main.ejs +26 -6
- package/src/emit/rbac/templates/RbacMutation_Main.ejs +23 -3
- package/src/emit/rbac/templates/UserRbacFlow_HdrSqs.ejs +46 -0
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +152 -33
- package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +24 -4
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +26 -11
- package/src/emit/relationship/emitRelationshipApplicationArtifacts.js +179 -37
- package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +8 -2
- package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +15 -6
- package/src/emit/relationship/templates/ChangeRelationshipComplete_Main.ejs +64 -37
- package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +258 -142
- package/src/emit/relationship/templates/CreateRelationshipComplete_Main.ejs +68 -43
- package/src/emit/relationship/templates/CreateRelationship_Main.ejs +315 -171
- package/src/emit/relationship/templates/DeleteRelationshipComplete_Main.ejs +67 -41
- package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +226 -115
- package/src/emit/relationship/templates/FlowHandler_HdrApi.ejs +41 -33
- package/src/emit/relationship/templates/FlowHandler_HdrDsq.ejs +15 -11
- package/src/emit/relationship/templates/FlowHandler_HdrInv.ejs +28 -26
- package/src/emit/relationship/templates/FlowHandler_HdrSqs.ejs +15 -11
- package/src/emit/relationship/templates/GetRelationshipComplete_Main.ejs +46 -26
- package/src/emit/relationship/templates/GetRelationship_Main.ejs +233 -126
- package/src/emit/relationship/templates/MoveRelationshipComplete_Main.ejs +72 -44
- package/src/emit/relationship/templates/MoveRelationship_Main.ejs +266 -150
- package/src/emit/relationship/templates/UpdateRelationshipComplete_Main.ejs +74 -45
- package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +285 -152
- package/src/emit/resource/emitResourceArtifacts.js +274 -105
- package/src/emit/resource/generateResourceArtifacts.js +15 -6
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +139 -0
- package/src/emit/resource/templates/S3Bucket_Yaml.ejs +19 -0
- package/src/emit/resource/templates/S3Subscription_Yaml.ejs +7 -0
- package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
- package/src/emit/system/emitSystemWebSocketArtifacts.js +61 -165
- package/src/emit/system/templates/WebSocketComplete_HdrSqs.ejs +32 -0
- package/src/emit/system/templates/WebSocketComplete_Main.ejs +46 -0
- package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +19 -0
- package/src/emit/system/templates/WebSocketConnect.ejs +25 -0
- package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +11 -0
- package/src/generate.js +141 -34
- package/src/generateIntTest.js +76 -28
- package/src/generateResourceIntTest.js +35 -12
- package/src/generateResources/IntTest/generateResources/generateResources.js +5 -2
- package/src/generateResources/IntTest/generateResources/templateResources.ejs +18 -30
- package/src/generateResources/IntTest/generateTests/events/events.js +1 -1
- package/src/generateResources/IntTest/generateTests/events/templateEvents.ejs +13 -10
- package/src/generateResources/IntTest/generateTests/generateTemplate.js +2 -2
- package/src/generateResources/IntTest/generateTests/pathIntTest/pathIntTest.js +2 -1
- package/src/generateResources/IntTest/generateTests/pathIntTest/template.ejs +1 -3
- package/src/generateResources/IntTest/generateTests/tests/templateTests.ejs +1 -1
- package/src/generateResources/IntTest/generateTests/tests/tests.js +7 -3
- package/src/generateResources/IntTest/libs/{libs.js → IntTestGenerateLib.js} +34 -23
- package/src/generateResources/IntTest/upload/uploadIntTest.js +33 -19
- package/src/intTestGeneratorShared.js +15 -10
- package/src/output/commitArtifacts.js +99 -39
- package/src/output/mergeHooks.js +24 -10
- package/src/output/validateArtifacts.js +37 -27
- package/src/plan/buildGenerationPlan.js +24 -13
- package/test/core.test.js +116 -49
- package/test/createTargetRoleHandler.test.js +63 -14
- package/test/crudApplicationArtifacts.test.js +128 -23
- package/test/customFlowApplicationArtifacts.test.js +391 -84
- package/test/dynamicCrudFlowSchemas.test.js +74 -26
- package/test/dynamicRbacFlowSchemas.test.js +63 -20
- package/test/dynamicRelationshipFlowSchemas.test.js +65 -18
- package/test/functionYamlArtifact.test.js +67 -10
- package/test/intTestApi.test.js +9 -10
- package/test/publicApi.test.js +184 -44
- package/test/relationshipApplicationArtifacts.test.js +90 -19
- package/test/resourceArtifacts.test.js +183 -33
- package/docs/test.png +0 -0
- package/src/emit/rbac/templates/UserRbacFlow_HdrInv.ejs +0 -10
- package/src/emit/relationship/dynamicRelationshipFlowSchemaTemplate.js +0 -11
- /package/docs/{test.mmd → TriggeredCacheFlow.mmd} +0 -0
|
@@ -1,24 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
normalizeArtifactPaths,
|
|
3
|
+
validateArtifacts
|
|
4
|
+
} from '../output/validateArtifacts.js';
|
|
2
5
|
|
|
3
|
-
export function buildGenerationPlan(
|
|
6
|
+
export function buildGenerationPlan(
|
|
7
|
+
project,
|
|
8
|
+
artifacts = [],
|
|
9
|
+
{ managedPaths = [], managedScope, managedScopes } = {}
|
|
10
|
+
) {
|
|
4
11
|
if (!project?.rootPath || !project?.outputPath) {
|
|
5
12
|
throw new TypeError('ProjectModel must include rootPath and outputPath');
|
|
6
13
|
}
|
|
7
14
|
if (managedScope !== undefined && managedScopes !== undefined) {
|
|
8
|
-
throw new TypeError(
|
|
15
|
+
throw new TypeError(
|
|
16
|
+
'GenerationPlan must use managedScope or managedScopes, not both'
|
|
17
|
+
);
|
|
9
18
|
}
|
|
10
19
|
return Object.freeze({
|
|
11
20
|
project,
|
|
12
21
|
artifacts: validateArtifacts(artifacts),
|
|
13
22
|
managedPaths: normalizeArtifactPaths(managedPaths),
|
|
14
|
-
managedScope:
|
|
15
|
-
managedScopes:
|
|
23
|
+
managedScope: _normalizeManagedScope(managedScope),
|
|
24
|
+
managedScopes: _normalizeManagedScopes(managedScopes)
|
|
16
25
|
});
|
|
17
26
|
}
|
|
18
27
|
|
|
19
|
-
function
|
|
20
|
-
if (scope === undefined) {
|
|
21
|
-
return
|
|
28
|
+
function _normalizeManagedScope(scope) {
|
|
29
|
+
if (scope === undefined || scope === null) {
|
|
30
|
+
return null;
|
|
22
31
|
}
|
|
23
32
|
if (typeof scope !== 'string' || scope.trim() === '') {
|
|
24
33
|
throw new TypeError('managedScope must be a non-empty string');
|
|
@@ -26,9 +35,9 @@ function normalizeManagedScope(scope) {
|
|
|
26
35
|
return scope;
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
function
|
|
30
|
-
if (scopes === undefined) {
|
|
31
|
-
return
|
|
38
|
+
function _normalizeManagedScopes(scopes) {
|
|
39
|
+
if (scopes === undefined || scopes === null) {
|
|
40
|
+
return null;
|
|
32
41
|
}
|
|
33
42
|
if (!scopes || Array.isArray(scopes) || typeof scopes !== 'object') {
|
|
34
43
|
throw new TypeError('managedScopes must be an object of scope paths');
|
|
@@ -36,11 +45,13 @@ function normalizeManagedScopes(scopes) {
|
|
|
36
45
|
const seenPaths = new Set();
|
|
37
46
|
const normalized = {};
|
|
38
47
|
for (const [scope, paths] of Object.entries(scopes)) {
|
|
39
|
-
const scopeName =
|
|
48
|
+
const scopeName = _normalizeManagedScope(scope);
|
|
40
49
|
const normalizedPaths = normalizeArtifactPaths(paths);
|
|
41
50
|
for (const path of normalizedPaths) {
|
|
42
51
|
if (seenPaths.has(path)) {
|
|
43
|
-
throw new Error(
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Artifact path belongs to multiple managed scopes: ${path}`
|
|
54
|
+
);
|
|
44
55
|
}
|
|
45
56
|
seenPaths.add(path);
|
|
46
57
|
}
|
package/test/core.test.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
mkdir,
|
|
4
|
+
mkdtemp,
|
|
5
|
+
readFile,
|
|
6
|
+
readdir,
|
|
7
|
+
symlink,
|
|
8
|
+
writeFile
|
|
9
|
+
} from 'node:fs/promises';
|
|
3
10
|
import { tmpdir } from 'node:os';
|
|
4
11
|
import { dirname, join } from 'node:path';
|
|
5
12
|
import test from 'node:test';
|
|
@@ -15,7 +22,9 @@ test('compiles a request and commits only declared relative artifacts', async ()
|
|
|
15
22
|
{ path: 'app/generated/example.js', content: 'export default 1;\n' }
|
|
16
23
|
]);
|
|
17
24
|
|
|
18
|
-
assert.deepEqual(await commitArtifacts(plan), [
|
|
25
|
+
assert.deepEqual(await commitArtifacts(plan), [
|
|
26
|
+
{ path: 'app/generated/example.js' }
|
|
27
|
+
]);
|
|
19
28
|
assert.equal(
|
|
20
29
|
await readFile(join(outputPath, 'app/generated/example.js'), 'utf8'),
|
|
21
30
|
'export default 1;\n'
|
|
@@ -25,25 +34,35 @@ test('compiles a request and commits only declared relative artifacts', async ()
|
|
|
25
34
|
test('rejects invalid generation inputs before writing files', async () => {
|
|
26
35
|
assert.throws(() => compileProject({}), /rootPath/);
|
|
27
36
|
|
|
28
|
-
const outputPath = await mkdtemp(
|
|
37
|
+
const outputPath = await mkdtemp(
|
|
38
|
+
join(tmpdir(), 'generate-service-code-v2-invalid-')
|
|
39
|
+
);
|
|
29
40
|
const project = compileProject({ rootPath: outputPath });
|
|
30
41
|
await assert.rejects(
|
|
31
|
-
Promise.resolve().then(() =>
|
|
42
|
+
Promise.resolve().then(() =>
|
|
43
|
+
buildGenerationPlan(project, [{ path: '../outside.js', content: '' }])
|
|
44
|
+
),
|
|
32
45
|
/escapes output root/
|
|
33
46
|
);
|
|
34
47
|
await assert.rejects(
|
|
35
|
-
Promise.resolve().then(() =>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
Promise.resolve().then(() =>
|
|
49
|
+
buildGenerationPlan(project, [
|
|
50
|
+
{ path: 'same.js', content: '' },
|
|
51
|
+
{ path: 'same.js', content: '' }
|
|
52
|
+
])
|
|
53
|
+
),
|
|
39
54
|
/Duplicate artifact path/
|
|
40
55
|
);
|
|
41
56
|
await assert.rejects(readFile(join(outputPath, 'same.js')));
|
|
42
57
|
});
|
|
43
58
|
|
|
44
59
|
test('rejects a symlinked output directory', async () => {
|
|
45
|
-
const outputPath = await mkdtemp(
|
|
46
|
-
|
|
60
|
+
const outputPath = await mkdtemp(
|
|
61
|
+
join(tmpdir(), 'generate-service-code-v2-output-')
|
|
62
|
+
);
|
|
63
|
+
const outsidePath = await mkdtemp(
|
|
64
|
+
join(tmpdir(), 'generate-service-code-v2-outside-')
|
|
65
|
+
);
|
|
47
66
|
await symlink(outsidePath, join(outputPath, 'linked'));
|
|
48
67
|
|
|
49
68
|
const plan = buildGenerationPlan(compileProject({ rootPath: outputPath }), [
|
|
@@ -55,64 +74,104 @@ test('rejects a symlinked output directory', async () => {
|
|
|
55
74
|
});
|
|
56
75
|
|
|
57
76
|
test('does not delete a legacy file before a managed scope has established ownership', async () => {
|
|
58
|
-
const outputPath = await mkdtemp(
|
|
77
|
+
const outputPath = await mkdtemp(
|
|
78
|
+
join(tmpdir(), 'generate-service-code-v2-managed-scope-')
|
|
79
|
+
);
|
|
59
80
|
const project = compileProject({ rootPath: outputPath });
|
|
60
81
|
await writeFile(join(outputPath, 'legacy.js'), 'legacy\n');
|
|
61
82
|
|
|
62
|
-
await commitArtifacts(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
83
|
+
await commitArtifacts(
|
|
84
|
+
buildGenerationPlan(project, [], {
|
|
85
|
+
managedPaths: ['legacy.js'],
|
|
86
|
+
managedScope: 'example-scope'
|
|
87
|
+
})
|
|
88
|
+
);
|
|
89
|
+
assert.equal(
|
|
90
|
+
await readFile(join(outputPath, 'legacy.js'), 'utf8'),
|
|
91
|
+
'legacy\n'
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
await commitArtifacts(
|
|
95
|
+
buildGenerationPlan(project, [{ path: 'legacy.js', content: 'v2\n' }], {
|
|
96
|
+
managedPaths: ['legacy.js'],
|
|
97
|
+
managedScope: 'example-scope'
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
await commitArtifacts(
|
|
101
|
+
buildGenerationPlan(project, [], {
|
|
102
|
+
managedPaths: ['legacy.js'],
|
|
103
|
+
managedScope: 'example-scope'
|
|
104
|
+
})
|
|
105
|
+
);
|
|
76
106
|
await assert.rejects(readFile(join(outputPath, 'legacy.js')));
|
|
77
107
|
});
|
|
78
108
|
|
|
79
109
|
test('commits and cleans multiple managed scopes in one transaction', async () => {
|
|
80
|
-
const outputPath = await mkdtemp(
|
|
110
|
+
const outputPath = await mkdtemp(
|
|
111
|
+
join(tmpdir(), 'generate-service-code-v2-multi-scope-')
|
|
112
|
+
);
|
|
81
113
|
const project = compileProject({ rootPath: outputPath });
|
|
82
|
-
const managedScopes = {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
114
|
+
const managedScopes = {
|
|
115
|
+
schemas: ['schemas.js'],
|
|
116
|
+
application: ['application.js']
|
|
117
|
+
};
|
|
118
|
+
await commitArtifacts(
|
|
119
|
+
buildGenerationPlan(
|
|
120
|
+
project,
|
|
121
|
+
[
|
|
122
|
+
{ path: 'schemas.js', content: 'schema\n' },
|
|
123
|
+
{ path: 'application.js', content: 'application\n' }
|
|
124
|
+
],
|
|
125
|
+
{ managedScopes }
|
|
126
|
+
)
|
|
127
|
+
);
|
|
87
128
|
|
|
88
|
-
await commitArtifacts(
|
|
89
|
-
|
|
90
|
-
|
|
129
|
+
await commitArtifacts(
|
|
130
|
+
buildGenerationPlan(
|
|
131
|
+
project,
|
|
132
|
+
[{ path: 'application.js', content: 'application next\n' }],
|
|
133
|
+
{ managedScopes }
|
|
134
|
+
)
|
|
135
|
+
);
|
|
91
136
|
|
|
92
137
|
await assert.rejects(readFile(join(outputPath, 'schemas.js')));
|
|
93
|
-
assert.equal(
|
|
138
|
+
assert.equal(
|
|
139
|
+
await readFile(join(outputPath, 'application.js'), 'utf8'),
|
|
140
|
+
'application next\n'
|
|
141
|
+
);
|
|
94
142
|
});
|
|
95
143
|
|
|
96
144
|
test('merges preserved hook blocks into staged source without changing the hook', async () => {
|
|
97
|
-
const outputPath = await mkdtemp(
|
|
145
|
+
const outputPath = await mkdtemp(
|
|
146
|
+
join(tmpdir(), 'generate-service-code-v2-hooks-')
|
|
147
|
+
);
|
|
98
148
|
const hookPath = join(outputPath, 'app/generated/hook/example.js');
|
|
99
149
|
await mkdir(dirname(hookPath), { recursive: true });
|
|
100
150
|
await writeFile(hookPath, '//(<hookCode>)\ncustom();\n//(</hookCode>)\n');
|
|
101
151
|
|
|
102
|
-
await commitArtifacts(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
152
|
+
await commitArtifacts(
|
|
153
|
+
buildGenerationPlan(compileProject({ rootPath: outputPath }), [
|
|
154
|
+
{
|
|
155
|
+
path: 'app/generated/source/example.js',
|
|
156
|
+
content: '//(<hookCode>)\ndefault();\n//(</hookCode>)\n'
|
|
157
|
+
}
|
|
158
|
+
])
|
|
159
|
+
);
|
|
106
160
|
|
|
107
161
|
assert.equal(
|
|
108
162
|
await readFile(join(outputPath, 'app/generated/source/example.js'), 'utf8'),
|
|
109
163
|
'//(<hookCode>)\ncustom();\n//(</hookCode>)\n'
|
|
110
164
|
);
|
|
111
|
-
assert.equal(
|
|
165
|
+
assert.equal(
|
|
166
|
+
await readFile(hookPath, 'utf8'),
|
|
167
|
+
'//(<hookCode>)\ncustom();\n//(</hookCode>)\n'
|
|
168
|
+
);
|
|
112
169
|
});
|
|
113
170
|
|
|
114
171
|
test('rejects an invalid rendered artifact before staging output', async () => {
|
|
115
|
-
const outputPath = await mkdtemp(
|
|
172
|
+
const outputPath = await mkdtemp(
|
|
173
|
+
join(tmpdir(), 'generate-service-code-v2-invalid-render-')
|
|
174
|
+
);
|
|
116
175
|
const sourcePath = join(outputPath, 'app/generated/source/example.js');
|
|
117
176
|
await mkdir(dirname(sourcePath), { recursive: true });
|
|
118
177
|
await writeFile(sourcePath, 'existing source\n');
|
|
@@ -126,13 +185,17 @@ test('rejects an invalid rendered artifact before staging output', async () => {
|
|
|
126
185
|
);
|
|
127
186
|
assert.equal(await readFile(sourcePath, 'utf8'), 'existing source\n');
|
|
128
187
|
assert.deepEqual(
|
|
129
|
-
(await readdir(outputPath)).filter(name =>
|
|
188
|
+
(await readdir(outputPath)).filter((name) =>
|
|
189
|
+
name.startsWith('.generate-service-code-v2-stage-')
|
|
190
|
+
),
|
|
130
191
|
[]
|
|
131
192
|
);
|
|
132
193
|
});
|
|
133
194
|
|
|
134
195
|
test('rejects a failed output transaction without partial files, hooks, or staging residue', async () => {
|
|
135
|
-
const outputPath = await mkdtemp(
|
|
196
|
+
const outputPath = await mkdtemp(
|
|
197
|
+
join(tmpdir(), 'generate-service-code-v2-transaction-')
|
|
198
|
+
);
|
|
136
199
|
const project = compileProject({ rootPath: outputPath });
|
|
137
200
|
const sourcePath = join(outputPath, 'app/generated/source/first.js');
|
|
138
201
|
const hookPath = join(outputPath, 'app/generated/hook/first.js');
|
|
@@ -143,16 +206,20 @@ test('rejects a failed output transaction without partial files, hooks, or stagi
|
|
|
143
206
|
await mkdir(join(outputPath, 'app/generated/source/second.js'));
|
|
144
207
|
|
|
145
208
|
await assert.rejects(
|
|
146
|
-
commitArtifacts(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
209
|
+
commitArtifacts(
|
|
210
|
+
buildGenerationPlan(project, [
|
|
211
|
+
{ path: 'app/generated/source/first.js', content: 'new source\n' },
|
|
212
|
+
{ path: 'app/generated/source/second.js', content: 'never committed\n' }
|
|
213
|
+
])
|
|
214
|
+
),
|
|
150
215
|
/not a file/
|
|
151
216
|
);
|
|
152
217
|
assert.equal(await readFile(sourcePath, 'utf8'), 'old source\n');
|
|
153
218
|
assert.equal(await readFile(hookPath, 'utf8'), 'custom hook\n');
|
|
154
219
|
assert.deepEqual(
|
|
155
|
-
(await readdir(outputPath)).filter(name =>
|
|
220
|
+
(await readdir(outputPath)).filter((name) =>
|
|
221
|
+
name.startsWith('.generate-service-code-v2-stage-')
|
|
222
|
+
),
|
|
156
223
|
[]
|
|
157
224
|
);
|
|
158
225
|
assert.equal((await readdir(outputPath)).includes('.bak'), false);
|
|
@@ -15,27 +15,55 @@ const OWN_TOPIC_FLOWS = [
|
|
|
15
15
|
'CreateUserRole',
|
|
16
16
|
'DeleteUserFromRole'
|
|
17
17
|
];
|
|
18
|
-
after(() =>
|
|
18
|
+
after(() =>
|
|
19
|
+
Promise.all(
|
|
20
|
+
[...roots].map((root) => rm(root, { recursive: true, force: true }))
|
|
21
|
+
)
|
|
22
|
+
);
|
|
19
23
|
|
|
20
24
|
test('generates RBAC own-topic WebSocket entries alongside their SQS handlers', async () => {
|
|
21
25
|
const rootPath = await createProject(true);
|
|
22
26
|
const result = await generateCreateTargetRoleHandler(rootPath);
|
|
23
27
|
|
|
24
28
|
assert.equal(result.files.length, 36);
|
|
25
|
-
assert.match(await readFile(join(rootPath, result.files[0].path), 'utf8'), /ProcessCreateTargetRole/);
|
|
26
|
-
assert.match(await readFile(join(rootPath, result.files[1].path), 'utf8'), /ProcessCreateTargetRoleHdrSqs/);
|
|
27
29
|
assert.match(
|
|
28
|
-
await readFile(join(rootPath,
|
|
30
|
+
await readFile(join(rootPath, result.files[0].path), 'utf8'),
|
|
31
|
+
/CreateTargetRole/
|
|
32
|
+
);
|
|
33
|
+
assert.match(
|
|
34
|
+
await readFile(join(rootPath, result.files[1].path), 'utf8'),
|
|
35
|
+
/CreateTargetRoleHdrSqs/
|
|
36
|
+
);
|
|
37
|
+
assert.match(
|
|
38
|
+
await readFile(
|
|
39
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-rbac.yml'),
|
|
40
|
+
'utf8'
|
|
41
|
+
),
|
|
29
42
|
/FlowRbacRole/
|
|
30
43
|
);
|
|
31
44
|
assert.match(
|
|
32
|
-
await readFile(
|
|
33
|
-
|
|
45
|
+
await readFile(
|
|
46
|
+
join(
|
|
47
|
+
rootPath,
|
|
48
|
+
'app/src/generatedCode/FlowRbac/ListTargetRole/source/ListTargetRole_HdrApi.js'
|
|
49
|
+
),
|
|
50
|
+
'utf8'
|
|
51
|
+
),
|
|
52
|
+
/ListTargetRole/
|
|
53
|
+
);
|
|
54
|
+
const yaml = await readFile(
|
|
55
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-rbac.yml'),
|
|
56
|
+
'utf8'
|
|
34
57
|
);
|
|
35
|
-
const yaml = await readFile(join(rootPath, 'app/sls_yaml/generatedCode/source/flow-rbac.yml'), 'utf8');
|
|
36
58
|
for (const flowTag of OWN_TOPIC_FLOWS) {
|
|
37
59
|
assert.match(
|
|
38
|
-
await readFile(
|
|
60
|
+
await readFile(
|
|
61
|
+
join(
|
|
62
|
+
rootPath,
|
|
63
|
+
`app/src/generatedCode/FlowRbac/${flowTag}/source/${flowTag}_HdrWbs.js`
|
|
64
|
+
),
|
|
65
|
+
'utf8'
|
|
66
|
+
),
|
|
39
67
|
new RegExp(`import ${flowTag}`)
|
|
40
68
|
);
|
|
41
69
|
assert.match(yaml, new RegExp(`${flowTag}HdrWbs:\\n[\\s\\S]*websocket:`));
|
|
@@ -46,23 +74,44 @@ test('removes CreateTargetRole handler when RBAC is removed', async () => {
|
|
|
46
74
|
const rootPath = await createProject(true);
|
|
47
75
|
const objectPath = join(rootPath, 'app/src/schemas/ObjectSchemas/User.js');
|
|
48
76
|
await generateCreateTargetRoleHandler(rootPath);
|
|
49
|
-
await writeFile(
|
|
77
|
+
await writeFile(
|
|
78
|
+
objectPath,
|
|
79
|
+
"export default { objectType: 'user', addOnDataStructure: [] };\n"
|
|
80
|
+
);
|
|
50
81
|
|
|
51
82
|
assert.deepEqual((await generateCreateTargetRoleHandler(rootPath)).files, []);
|
|
52
|
-
await assert.rejects(
|
|
53
|
-
|
|
54
|
-
|
|
83
|
+
await assert.rejects(
|
|
84
|
+
readFile(
|
|
85
|
+
join(
|
|
86
|
+
rootPath,
|
|
87
|
+
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_Main.js'
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
await assert.rejects(
|
|
92
|
+
readFile(
|
|
93
|
+
join(
|
|
94
|
+
rootPath,
|
|
95
|
+
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrWbs.js'
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
);
|
|
99
|
+
await assert.rejects(
|
|
100
|
+
readFile(join(rootPath, 'app/sls_yaml/generatedCode/source/flow-rbac.yml'))
|
|
101
|
+
);
|
|
55
102
|
});
|
|
56
103
|
|
|
57
104
|
async function createProject(hasRbac) {
|
|
58
|
-
const rootPath = await mkdtemp(
|
|
105
|
+
const rootPath = await mkdtemp(
|
|
106
|
+
join(tmpdir(), 'generate-service-code-v2-rbac-handler-')
|
|
107
|
+
);
|
|
59
108
|
roots.add(rootPath);
|
|
60
109
|
const directory = join(rootPath, 'app/src/schemas/ObjectSchemas');
|
|
61
110
|
const addOns = hasRbac ? "[{ type: 'rbac' }]" : '[]';
|
|
62
111
|
await mkdir(directory, { recursive: true });
|
|
63
112
|
await writeFile(
|
|
64
113
|
join(directory, 'User.js'),
|
|
65
|
-
`export default { objectType: 'user', addOnDataStructure: ${addOns} };\n`
|
|
114
|
+
`export default { objectType: 'user', fieldNames: [], identifiers: [], addOnDataStructure: ${addOns} };\n`
|
|
66
115
|
);
|
|
67
116
|
return rootPath;
|
|
68
117
|
}
|
|
@@ -5,26 +5,49 @@ import { tmpdir } from 'node:os';
|
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import test, { after } from 'node:test';
|
|
7
7
|
|
|
8
|
+
process.env.NODE_ENV = 'test';
|
|
9
|
+
|
|
8
10
|
import { generateCrudApplicationArtifacts } from '../src/emit/crud/generateCrudApplicationArtifacts.js';
|
|
9
11
|
|
|
10
12
|
const roots = new Set();
|
|
11
|
-
after(() =>
|
|
13
|
+
after(() =>
|
|
14
|
+
Promise.all(
|
|
15
|
+
[...roots].map((root) => rm(root, { recursive: true, force: true }))
|
|
16
|
+
)
|
|
17
|
+
);
|
|
12
18
|
|
|
13
19
|
test('emits CRUD handlers and function YAML from schema data without reading generated output', async () => {
|
|
14
20
|
const rootPath = await createProject(true);
|
|
15
|
-
const result = await generateCrudApplicationArtifacts(rootPath, {
|
|
21
|
+
const result = await generateCrudApplicationArtifacts(rootPath, {
|
|
22
|
+
serviceTag: 'orders'
|
|
23
|
+
});
|
|
16
24
|
|
|
17
25
|
assert.equal(result.files.length, 26);
|
|
18
|
-
assert.ok(result.files.every(file => !file.path.includes('/Process')));
|
|
26
|
+
assert.ok(result.files.every((file) => !file.path.includes('/Process')));
|
|
19
27
|
assert.match(
|
|
20
|
-
await readFile(
|
|
28
|
+
await readFile(
|
|
29
|
+
join(
|
|
30
|
+
rootPath,
|
|
31
|
+
'app/src/generatedCode/FlowObjects/Get/source/Get_Main.js'
|
|
32
|
+
),
|
|
33
|
+
'utf8'
|
|
34
|
+
),
|
|
21
35
|
/dataFromGraphV2/
|
|
22
36
|
);
|
|
23
37
|
assert.match(
|
|
24
|
-
await readFile(
|
|
38
|
+
await readFile(
|
|
39
|
+
join(
|
|
40
|
+
rootPath,
|
|
41
|
+
'app/src/generatedCode/FlowObjects/Create/source/Create_Main.js'
|
|
42
|
+
),
|
|
43
|
+
'utf8'
|
|
44
|
+
),
|
|
25
45
|
/beforeLogical_order/
|
|
26
46
|
);
|
|
27
|
-
const yaml = await readFile(
|
|
47
|
+
const yaml = await readFile(
|
|
48
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-objects.yml'),
|
|
49
|
+
'utf8'
|
|
50
|
+
);
|
|
28
51
|
assert.match(yaml, /CreateHdrWbs:/);
|
|
29
52
|
assert.ok(yaml.indexOf('CreateHdrWbs:') < yaml.indexOf('CreateHdrSqs:'));
|
|
30
53
|
assert.doesNotMatch(yaml, /handler: .*\/Process/);
|
|
@@ -34,24 +57,68 @@ test('emits CRUD handlers and function YAML from schema data without reading gen
|
|
|
34
57
|
assert.match(yaml, /#<#CreateCompleteHdrSqsFunctionSetting#>/);
|
|
35
58
|
assert.match(yaml, /filterPatterns:[\s\S]*CreateCompleteHdrSqs/);
|
|
36
59
|
assert.match(
|
|
37
|
-
await readFile(
|
|
60
|
+
await readFile(
|
|
61
|
+
join(
|
|
62
|
+
rootPath,
|
|
63
|
+
'app/src/generatedCode/FlowObjects/Create/source/CreateComplete_Main.js'
|
|
64
|
+
),
|
|
65
|
+
'utf8'
|
|
66
|
+
),
|
|
38
67
|
/checkAllAwaitingStepsFinishedWithReturnParams/
|
|
39
68
|
);
|
|
40
69
|
assert.doesNotMatch(
|
|
41
|
-
await readFile(
|
|
70
|
+
await readFile(
|
|
71
|
+
join(
|
|
72
|
+
rootPath,
|
|
73
|
+
'app/src/generatedCode/FlowObjects/Create/source/Create_WbsMain.js'
|
|
74
|
+
),
|
|
75
|
+
'utf8'
|
|
76
|
+
),
|
|
42
77
|
/from '@izara_project\/izara-core-generate-service-code'/
|
|
43
78
|
);
|
|
44
|
-
await assert.rejects(
|
|
79
|
+
await assert.rejects(
|
|
80
|
+
readFile(
|
|
81
|
+
join(
|
|
82
|
+
rootPath,
|
|
83
|
+
'app/src/generatedCode/FlowObjects/Create/source/ProcessCreate_Main.js'
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
);
|
|
45
87
|
for (const action of ['Create', 'Update', 'Delete']) {
|
|
46
|
-
execFileSync(
|
|
47
|
-
|
|
88
|
+
execFileSync(
|
|
89
|
+
process.execPath,
|
|
90
|
+
[
|
|
91
|
+
'--check',
|
|
92
|
+
join(
|
|
93
|
+
rootPath,
|
|
94
|
+
`app/src/generatedCode/FlowObjects/${action}/source/${action}Complete_Main.js`
|
|
95
|
+
)
|
|
96
|
+
],
|
|
97
|
+
{ stdio: 'inherit' }
|
|
98
|
+
);
|
|
99
|
+
execFileSync(
|
|
100
|
+
process.execPath,
|
|
101
|
+
[
|
|
102
|
+
'--check',
|
|
103
|
+
join(
|
|
104
|
+
rootPath,
|
|
105
|
+
`app/src/generatedCode/FlowObjects/${action}/source/${action}Complete_HdrSqs.js`
|
|
106
|
+
)
|
|
107
|
+
],
|
|
108
|
+
{ stdio: 'inherit' }
|
|
109
|
+
);
|
|
48
110
|
}
|
|
49
111
|
});
|
|
50
112
|
|
|
51
113
|
test('preserves function-setting hooks across CRUD regeneration', async () => {
|
|
52
114
|
const rootPath = await createProject(true);
|
|
53
|
-
const hookPath = join(
|
|
54
|
-
|
|
115
|
+
const hookPath = join(
|
|
116
|
+
rootPath,
|
|
117
|
+
'app/sls_yaml/generatedCode/hook/flow-objects.yml'
|
|
118
|
+
);
|
|
119
|
+
await mkdir(join(rootPath, 'app/sls_yaml/generatedCode/hook'), {
|
|
120
|
+
recursive: true
|
|
121
|
+
});
|
|
55
122
|
await writeFile(
|
|
56
123
|
hookPath,
|
|
57
124
|
' #<#CreateCompleteHdrSqsFunctionSetting#>\n memorySize: 512\n #<#/CreateCompleteHdrSqsFunctionSetting#>\n'
|
|
@@ -60,15 +127,27 @@ test('preserves function-setting hooks across CRUD regeneration', async () => {
|
|
|
60
127
|
await generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' });
|
|
61
128
|
await generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' });
|
|
62
129
|
|
|
63
|
-
const yamlPath = join(
|
|
130
|
+
const yamlPath = join(
|
|
131
|
+
rootPath,
|
|
132
|
+
'app/sls_yaml/generatedCode/source/flow-objects.yml'
|
|
133
|
+
);
|
|
64
134
|
const yaml = await readFile(yamlPath, 'utf8');
|
|
65
|
-
assert.match(
|
|
135
|
+
assert.match(
|
|
136
|
+
yaml,
|
|
137
|
+
/#<#CreateCompleteHdrSqsFunctionSetting#>\n memorySize: 512\n #<#\/CreateCompleteHdrSqsFunctionSetting#>/
|
|
138
|
+
);
|
|
66
139
|
|
|
67
|
-
const conflictPath = join(
|
|
140
|
+
const conflictPath = join(
|
|
141
|
+
rootPath,
|
|
142
|
+
'app/src/generatedCode/FlowObjects/Create/source/Create_Main.js'
|
|
143
|
+
);
|
|
68
144
|
await rm(conflictPath);
|
|
69
145
|
await mkdir(conflictPath);
|
|
70
146
|
|
|
71
|
-
await assert.rejects(
|
|
147
|
+
await assert.rejects(
|
|
148
|
+
generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' }),
|
|
149
|
+
/not a file/
|
|
150
|
+
);
|
|
72
151
|
assert.equal(await readFile(yamlPath, 'utf8'), yaml);
|
|
73
152
|
assert.equal(
|
|
74
153
|
await readFile(hookPath, 'utf8'),
|
|
@@ -79,16 +158,42 @@ test('preserves function-setting hooks across CRUD regeneration', async () => {
|
|
|
79
158
|
test('removes managed CRUD artifacts when no applicable object remains', async () => {
|
|
80
159
|
const rootPath = await createProject(true);
|
|
81
160
|
await generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' });
|
|
82
|
-
await writeFile(
|
|
161
|
+
await writeFile(
|
|
162
|
+
join(rootPath, 'app/src/schemas/ObjectSchemas/Order.js'),
|
|
163
|
+
"export default { objectType: 'order' };\n"
|
|
164
|
+
);
|
|
83
165
|
|
|
84
|
-
assert.deepEqual(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
166
|
+
assert.deepEqual(
|
|
167
|
+
(await generateCrudApplicationArtifacts(rootPath)).files,
|
|
168
|
+
[]
|
|
169
|
+
);
|
|
170
|
+
await assert.rejects(
|
|
171
|
+
readFile(
|
|
172
|
+
join(
|
|
173
|
+
rootPath,
|
|
174
|
+
'app/src/generatedCode/FlowObjects/Create/source/Create_Main.js'
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
);
|
|
178
|
+
await assert.rejects(
|
|
179
|
+
readFile(
|
|
180
|
+
join(
|
|
181
|
+
rootPath,
|
|
182
|
+
'app/src/generatedCode/FlowObjects/Create/source/CreateComplete_Main.js'
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
);
|
|
186
|
+
await assert.rejects(
|
|
187
|
+
readFile(
|
|
188
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-objects.yml')
|
|
189
|
+
)
|
|
190
|
+
);
|
|
88
191
|
});
|
|
89
192
|
|
|
90
193
|
async function createProject(withCrudObject) {
|
|
91
|
-
const rootPath = await mkdtemp(
|
|
194
|
+
const rootPath = await mkdtemp(
|
|
195
|
+
join(tmpdir(), 'generate-service-code-v2-crud-application-')
|
|
196
|
+
);
|
|
92
197
|
roots.add(rootPath);
|
|
93
198
|
const schemaRoot = join(rootPath, 'app/src/schemas');
|
|
94
199
|
await mkdir(join(schemaRoot, 'ObjectSchemas'), { recursive: true });
|