@izara_project/izara-core-generate-service-code 1.0.68 → 1.0.70
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/package.json +1 -1
- package/scripts/format-ejs.js +36 -32
- package/src/compile/compileProject.js +26 -10
- package/src/compile/loadSchemas.js +122 -59
- package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +163 -0
- package/src/emit/coreFunction/templates/CoreFunction_Yaml.ejs +38 -0
- package/src/emit/coreFunction/templates/CoreResource_Yaml.ejs +235 -0
- package/src/emit/coreFunction/templates/GenerateSeedDataDynamo_HdrInv.ejs +16 -0
- package/src/emit/coreFunction/templates/GenerateSeedDataDynamo_Main.ejs +38 -0
- package/src/emit/coreFunction/templates/GenerateSeedDataGraphData_HdrInv.ejs +16 -0
- package/src/emit/coreFunction/templates/GenerateSeedDataGraphData_Main.ejs +32 -0
- package/src/emit/coreFunction/templates/GenerateSeedDataGraphSchema_HdrInv.ejs +16 -0
- package/src/emit/coreFunction/templates/GenerateSeedDataGraphSchema_Main.ejs +71 -0
- package/src/emit/coreFunction/templates/GeneratedGraphNodeSchemas.ejs +47 -0
- package/src/emit/coreFunction/templates/GeneratedGraphRelSchemas.ejs +27 -0
- package/src/emit/coreFunction/templates/GeneratedTableConfigs.ejs +34 -0
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +108 -0
- package/src/emit/coreFunction/templates/InitialSetup_HdrInv.ejs +12 -0
- package/src/emit/coreFunction/templates/InitialSetup_Main.ejs +51 -0
- package/src/emit/coreFunction/templates/RemoveSeedDataDynamo_HdrInv.ejs +16 -0
- package/src/emit/coreFunction/templates/RemoveSeedDataDynamo_Main.ejs +31 -0
- package/src/emit/coreFunction/templates/UploadSchema_HdrInv.ejs +37 -0
- package/src/emit/coreFunction/templates/UploadSchema_Main.ejs +52 -0
- package/src/emit/crud/emitCrudApplicationArtifacts.js +194 -41
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +34 -17
- package/src/emit/crud/generateCrudApplicationArtifacts.js +14 -6
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +4 -1
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +1 -1
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +1 -1
- package/src/emit/crud/templates/GetEndpoint_Main.ejs +2 -2
- package/src/emit/crud/templates/GetRangeEndpoint_Main.ejs +1 -1
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +1 -1
- package/src/emit/custom/customFlows.js +23 -13
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +535 -114
- package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +28 -8
- package/src/emit/custom/templates/FlowEndpoint_Main.ejs +2 -2
- package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
- package/src/emit/custom/templates/s3/CreateObject_Main.ejs +1 -1
- package/src/emit/custom/templates/s3/FlowHandler_HdrS3.ejs +2 -2
- package/src/emit/custom/templates/s3/ReservedLimit_HdrSqs.ejs +1 -1
- package/src/emit/custom/templates/s3/ReservedLimit_Main.ejs +1 -1
- package/src/emit/custom/templates/triggerCache/CheckTriggerCache_HdrSqs.ejs +4 -4
- package/src/emit/function/functionYamlArtifact.js +273 -97
- 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 +28 -30
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +6 -6
- 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/UserRbacFlow_Main.ejs +1 -1
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +26 -10
- package/src/emit/relationship/emitRelationshipApplicationArtifacts.js +189 -37
- package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +8 -2
- package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +15 -6
- package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/CreateRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/GetRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/MoveRelationship_Main.ejs +1 -1
- package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +1 -1
- package/src/emit/resource/emitResourceArtifacts.js +249 -123
- package/src/emit/resource/generateResourceArtifacts.js +15 -6
- package/src/emit/resource/templates/DynamoDBTable_Yaml.ejs +18 -18
- package/src/emit/resource/templates/FlowOut_Yaml.ejs +5 -5
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +10 -9
- package/src/emit/resource/templates/ResourceBeforeLogicalYaml.ejs +44 -44
- package/src/emit/resource/templates/ResourceSqsYaml.ejs +36 -36
- package/src/emit/resource/templates/ResourceYaml.ejs +48 -48
- package/src/emit/resource/templates/S3Subscription_Yaml.ejs +7 -0
- package/src/emit/resource/templates/SharedResource_Yaml.ejs +11 -11
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +122 -105
- package/src/emit/resource/templates/WebSocketSubscription_Yaml.ejs +7 -0
- package/src/emit/shared/templates/FindData_HdrSqs.ejs +120 -0
- package/src/emit/shared/templates/FindData_Main.ejs +345 -0
- package/src/emit/{crud → shared}/templates/FlowHandler_HdrApi.ejs +1 -1
- package/src/emit/{relationship → shared}/templates/FlowHandler_HdrDsq.ejs +4 -4
- package/src/emit/{crud → shared}/templates/FlowHandler_HdrInv.ejs +1 -1
- package/src/emit/{crud → shared}/templates/FlowHandler_HdrSqs.ejs +4 -4
- package/src/emit/shared/templates/PaginateProcessLogical_HdrDsq.ejs +162 -0
- package/src/emit/shared/templates/PaginateProcessLogical_HdrSqs.ejs +140 -0
- package/src/emit/shared/templates/PaginateProcessLogical_Main.ejs +268 -0
- package/src/emit/{relationship/templates/FlowHandler_HdrSqs.ejs → shared/templates/ProcessLogical_HdrSqs.ejs} +40 -55
- package/src/emit/shared/templates/ProcessLogical_Main.ejs +448 -0
- package/src/emit/system/emitSystemFindDataArtifacts.js +266 -0
- package/src/emit/system/emitSystemWebSocketArtifacts.js +61 -165
- package/src/emit/system/templates/WebSocketComplete_HdrSqs.ejs +48 -0
- package/src/emit/system/templates/WebSocketComplete_Main.ejs +91 -0
- package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +19 -0
- package/src/emit/system/templates/WebSocketConnect.ejs +45 -0
- package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +11 -0
- package/src/generate.js +166 -36
- 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 +34 -21
- package/src/output/validateArtifacts.js +37 -27
- package/src/plan/buildGenerationPlan.js +24 -13
- package/test/core.test.js +117 -58
- package/test/createTargetRoleHandler.test.js +1 -1
- package/test/crudApplicationArtifacts.test.js +132 -31
- package/test/customFlowApplicationArtifacts.test.js +353 -71
- package/test/dynamicCrudFlowSchemas.test.js +74 -26
- package/test/dynamicRbacFlowSchemas.test.js +61 -14
- 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 +178 -36
- package/test/relationshipApplicationArtifacts.test.js +90 -19
- package/test/resourceArtifacts.test.js +173 -33
- package/src/emit/relationship/dynamicRelationshipFlowSchemaTemplate.js +0 -11
- package/src/emit/relationship/templates/FlowHandler_HdrApi.ejs +0 -59
- package/src/emit/relationship/templates/FlowHandler_HdrInv.ejs +0 -47
|
@@ -6,24 +6,32 @@ export function normalizeArtifacts(artifacts) {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
const paths = new Set();
|
|
9
|
-
return Object.freeze(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
9
|
+
return Object.freeze(
|
|
10
|
+
artifacts.map((artifact) => {
|
|
11
|
+
if (
|
|
12
|
+
!artifact ||
|
|
13
|
+
typeof artifact.path !== 'string' ||
|
|
14
|
+
artifact.path.trim() === ''
|
|
15
|
+
) {
|
|
16
|
+
throw new TypeError('Artifact.path must be a non-empty relative path');
|
|
17
|
+
}
|
|
18
|
+
if (isAbsolute(artifact.path)) {
|
|
19
|
+
throw new TypeError(`Artifact.path must be relative: ${artifact.path}`);
|
|
20
|
+
}
|
|
21
|
+
if (typeof artifact.content !== 'string') {
|
|
22
|
+
throw new TypeError(
|
|
23
|
+
`Artifact.content must be a string: ${artifact.path}`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const path = _normalizeArtifactPath(artifact.path);
|
|
28
|
+
if (paths.has(path)) {
|
|
29
|
+
throw new Error(`Duplicate artifact path: ${path}`);
|
|
30
|
+
}
|
|
31
|
+
paths.add(path);
|
|
32
|
+
return Object.freeze({ path, content: artifact.content });
|
|
33
|
+
})
|
|
34
|
+
);
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
export function validateArtifacts(artifacts) {
|
|
@@ -36,17 +44,19 @@ export function normalizeArtifactPaths(paths) {
|
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
const seenPaths = new Set();
|
|
39
|
-
return Object.freeze(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
return Object.freeze(
|
|
48
|
+
paths.map((path) => {
|
|
49
|
+
const normalizedPath = _normalizeArtifactPath(path);
|
|
50
|
+
if (seenPaths.has(normalizedPath)) {
|
|
51
|
+
throw new Error(`Duplicate artifact path: ${normalizedPath}`);
|
|
52
|
+
}
|
|
53
|
+
seenPaths.add(normalizedPath);
|
|
54
|
+
return normalizedPath;
|
|
55
|
+
})
|
|
56
|
+
);
|
|
47
57
|
}
|
|
48
58
|
|
|
49
|
-
function
|
|
59
|
+
function _normalizeArtifactPath(path) {
|
|
50
60
|
if (typeof path !== 'string' || path.trim() === '') {
|
|
51
61
|
throw new TypeError('Artifact.path must be a non-empty relative path');
|
|
52
62
|
}
|
|
@@ -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,100 @@ 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(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
await
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
145
|
+
const outputPath = await mkdtemp(
|
|
146
|
+
join(tmpdir(), 'generate-service-code-v2-hooks-')
|
|
147
|
+
);
|
|
148
|
+
const sourcePath = join(outputPath, 'app/generated/source/example.js');
|
|
149
|
+
await mkdir(dirname(sourcePath), { recursive: true });
|
|
150
|
+
await writeFile(sourcePath, '//(<hookCode>)\ncustom();\n//(</hookCode>)\n');
|
|
151
|
+
|
|
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
|
-
await readFile(
|
|
162
|
+
await readFile(sourcePath, 'utf8'),
|
|
109
163
|
'//(<hookCode>)\ncustom();\n//(</hookCode>)\n'
|
|
110
164
|
);
|
|
111
|
-
assert.equal(await readFile(hookPath, 'utf8'), '//(<hookCode>)\ncustom();\n//(</hookCode>)\n');
|
|
112
165
|
});
|
|
113
166
|
|
|
114
167
|
test('rejects an invalid rendered artifact before staging output', async () => {
|
|
115
|
-
const outputPath = await mkdtemp(
|
|
168
|
+
const outputPath = await mkdtemp(
|
|
169
|
+
join(tmpdir(), 'generate-service-code-v2-invalid-render-')
|
|
170
|
+
);
|
|
116
171
|
const sourcePath = join(outputPath, 'app/generated/source/example.js');
|
|
117
172
|
await mkdir(dirname(sourcePath), { recursive: true });
|
|
118
173
|
await writeFile(sourcePath, 'existing source\n');
|
|
@@ -126,33 +181,37 @@ test('rejects an invalid rendered artifact before staging output', async () => {
|
|
|
126
181
|
);
|
|
127
182
|
assert.equal(await readFile(sourcePath, 'utf8'), 'existing source\n');
|
|
128
183
|
assert.deepEqual(
|
|
129
|
-
(await readdir(outputPath)).filter(name =>
|
|
184
|
+
(await readdir(outputPath)).filter((name) =>
|
|
185
|
+
name.startsWith('.generate-service-code-v2-stage-')
|
|
186
|
+
),
|
|
130
187
|
[]
|
|
131
188
|
);
|
|
132
189
|
});
|
|
133
190
|
|
|
134
191
|
test('rejects a failed output transaction without partial files, hooks, or staging residue', async () => {
|
|
135
|
-
const outputPath = await mkdtemp(
|
|
192
|
+
const outputPath = await mkdtemp(
|
|
193
|
+
join(tmpdir(), 'generate-service-code-v2-transaction-')
|
|
194
|
+
);
|
|
136
195
|
const project = compileProject({ rootPath: outputPath });
|
|
137
196
|
const sourcePath = join(outputPath, 'app/generated/source/first.js');
|
|
138
|
-
const hookPath = join(outputPath, 'app/generated/hook/first.js');
|
|
139
197
|
await mkdir(dirname(sourcePath), { recursive: true });
|
|
140
|
-
await mkdir(dirname(hookPath), { recursive: true });
|
|
141
198
|
await writeFile(sourcePath, 'old source\n');
|
|
142
|
-
await writeFile(hookPath, 'custom hook\n');
|
|
143
199
|
await mkdir(join(outputPath, 'app/generated/source/second.js'));
|
|
144
200
|
|
|
145
201
|
await assert.rejects(
|
|
146
|
-
commitArtifacts(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
202
|
+
commitArtifacts(
|
|
203
|
+
buildGenerationPlan(project, [
|
|
204
|
+
{ path: 'app/generated/source/first.js', content: 'new source\n' },
|
|
205
|
+
{ path: 'app/generated/source/second.js', content: 'never committed\n' }
|
|
206
|
+
])
|
|
207
|
+
),
|
|
150
208
|
/not a file/
|
|
151
209
|
);
|
|
152
210
|
assert.equal(await readFile(sourcePath, 'utf8'), 'old source\n');
|
|
153
|
-
assert.equal(await readFile(hookPath, 'utf8'), 'custom hook\n');
|
|
154
211
|
assert.deepEqual(
|
|
155
|
-
(await readdir(outputPath)).filter(name =>
|
|
212
|
+
(await readdir(outputPath)).filter((name) =>
|
|
213
|
+
name.startsWith('.generate-service-code-v2-stage-')
|
|
214
|
+
),
|
|
156
215
|
[]
|
|
157
216
|
);
|
|
158
217
|
assert.equal((await readdir(outputPath)).includes('.bak'), false);
|
|
@@ -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,61 +57,139 @@ 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
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
hookPath,
|
|
57
|
-
' #<#CreateCompleteHdrSqsFunctionSetting#>\n memorySize: 512\n #<#/CreateCompleteHdrSqsFunctionSetting#>\n'
|
|
115
|
+
const yamlPath = join(
|
|
116
|
+
rootPath,
|
|
117
|
+
'app/sls_yaml/generatedCode/source/flow-objects.yml'
|
|
58
118
|
);
|
|
59
119
|
|
|
60
120
|
await generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' });
|
|
121
|
+
|
|
122
|
+
const hookCode =
|
|
123
|
+
' #<#CreateCompleteHdrSqsFunctionSetting#>\n memorySize: 512\n #<#/CreateCompleteHdrSqsFunctionSetting#>\n';
|
|
124
|
+
let yaml = await readFile(yamlPath, 'utf8');
|
|
125
|
+
const withHook = yaml.replace(
|
|
126
|
+
/ #<#CreateCompleteHdrSqsFunctionSetting#>[\s\S]*?#<#\/CreateCompleteHdrSqsFunctionSetting#>/,
|
|
127
|
+
hookCode.trim()
|
|
128
|
+
);
|
|
129
|
+
assert.notEqual(yaml, withHook, 'hook placeholder must exist in generated YAML');
|
|
130
|
+
await writeFile(yamlPath, withHook);
|
|
131
|
+
|
|
61
132
|
await generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' });
|
|
62
133
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
134
|
+
yaml = await readFile(yamlPath, 'utf8');
|
|
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(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
await readFile(hookPath, 'utf8'),
|
|
75
|
-
' #<#CreateCompleteHdrSqsFunctionSetting#>\n memorySize: 512\n #<#/CreateCompleteHdrSqsFunctionSetting#>\n'
|
|
147
|
+
await assert.rejects(
|
|
148
|
+
generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' }),
|
|
149
|
+
/not a file/
|
|
76
150
|
);
|
|
151
|
+
assert.equal(await readFile(yamlPath, 'utf8'), yaml);
|
|
77
152
|
});
|
|
78
153
|
|
|
79
154
|
test('removes managed CRUD artifacts when no applicable object remains', async () => {
|
|
80
155
|
const rootPath = await createProject(true);
|
|
81
156
|
await generateCrudApplicationArtifacts(rootPath, { serviceTag: 'orders' });
|
|
82
|
-
await writeFile(
|
|
157
|
+
await writeFile(
|
|
158
|
+
join(rootPath, 'app/src/schemas/ObjectSchemas/Order.js'),
|
|
159
|
+
"export default { objectType: 'order' };\n"
|
|
160
|
+
);
|
|
83
161
|
|
|
84
|
-
assert.deepEqual(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
162
|
+
assert.deepEqual(
|
|
163
|
+
(await generateCrudApplicationArtifacts(rootPath)).files,
|
|
164
|
+
[]
|
|
165
|
+
);
|
|
166
|
+
await assert.rejects(
|
|
167
|
+
readFile(
|
|
168
|
+
join(
|
|
169
|
+
rootPath,
|
|
170
|
+
'app/src/generatedCode/FlowObjects/Create/source/Create_Main.js'
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
await assert.rejects(
|
|
175
|
+
readFile(
|
|
176
|
+
join(
|
|
177
|
+
rootPath,
|
|
178
|
+
'app/src/generatedCode/FlowObjects/Create/source/CreateComplete_Main.js'
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
);
|
|
182
|
+
await assert.rejects(
|
|
183
|
+
readFile(
|
|
184
|
+
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-objects.yml')
|
|
185
|
+
)
|
|
186
|
+
);
|
|
88
187
|
});
|
|
89
188
|
|
|
90
189
|
async function createProject(withCrudObject) {
|
|
91
|
-
const rootPath = await mkdtemp(
|
|
190
|
+
const rootPath = await mkdtemp(
|
|
191
|
+
join(tmpdir(), 'generate-service-code-v2-crud-application-')
|
|
192
|
+
);
|
|
92
193
|
roots.add(rootPath);
|
|
93
194
|
const schemaRoot = join(rootPath, 'app/src/schemas');
|
|
94
195
|
await mkdir(join(schemaRoot, 'ObjectSchemas'), { recursive: true });
|