@izara_project/izara-core-generate-service-code 1.0.98 → 1.0.100
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/src/compile/compileProject.js +16 -5
- package/src/compile/flowValidator.js +47 -8
- package/src/compile/loadSchemas.js +18 -7
- package/src/compile/schemaValidatorSetup.js +16 -0
- package/src/emit/application/coreFunction/emitCoreFunctionArtifacts.js +123 -109
- package/src/emit/application/coreFunction/templates/InitialSetupConfig.ejs +8 -4
- package/src/emit/application/coreFunction/templates/InitialSetupRunner.ejs +2 -2
- package/src/emit/application/crud/templates/CreateComplete_Main.ejs +2 -0
- package/src/emit/application/crud/templates/CreateEndpoint_Main.ejs +4 -4
- package/src/emit/application/crud/templates/CreateLogicalLib.ejs +74 -15
- package/src/emit/application/crud/templates/DeleteComplete_Main.ejs +2 -0
- package/src/emit/application/crud/templates/DeleteEndpoint_Main.ejs +4 -4
- package/src/emit/application/crud/templates/FlowEndpoint_HdrWbs.ejs +7 -5
- package/src/emit/application/crud/templates/UpdateComplete_Main.ejs +2 -0
- package/src/emit/application/crud/templates/UpdateEndpoint_Main.ejs +4 -4
- package/src/emit/application/custom/customFlowPaths.js +13 -16
- package/src/emit/application/custom/customFlowS3.js +277 -66
- package/src/emit/application/custom/customFlows.js +131 -0
- package/src/emit/application/custom/emitCustomFlowApplicationArtifacts.js +3 -1
- package/src/emit/application/custom/templates/FlowEndpoint_Main.ejs +2 -2
- package/src/emit/application/custom/templates/s3/ConfirmAfterUpload_HdrSqs.ejs +110 -0
- package/src/emit/application/custom/templates/s3/ConfirmAfterUpload_Main.ejs +89 -0
- package/src/emit/application/custom/templates/s3/ConfirmComplete_HdrSqs.ejs +110 -0
- package/src/emit/application/custom/templates/s3/ConfirmComplete_Main.ejs +89 -0
- package/src/emit/application/custom/templates/s3/CreateObject_HdrWbs.ejs +2 -1
- package/src/emit/application/custom/templates/s3/CreateObject_Main.ejs +4 -0
- package/src/emit/application/custom/templates/s3/CreatePreSignUrl_HdrSqs.ejs +42 -0
- package/src/emit/application/custom/templates/s3/CreatePreSignUrl_Main.ejs +23 -0
- package/src/emit/application/custom/templates/s3/ProcessS3File_Main.ejs +135 -27
- package/src/emit/application/custom/templates/s3/Start_Main.ejs +197 -0
- package/src/emit/application/rbac/emitDynamicRbacFlowSchemas.js +8 -1
- package/src/emit/application/rbac/emitRbacApplicationArtifacts.js +107 -25
- package/src/emit/application/rbac/templates/ReservedDynamicUsage_Main.ejs +29 -9
- package/src/emit/application/rbac/templates/ReservedUsageTtlExpired_HdrDss.ejs +176 -0
- package/src/emit/application/rbac/templates/UserRbacFlow_Main.ejs +4 -3
- package/src/emit/application/system/templates/Register_HdrWbs.ejs +2 -1
- package/src/emit/infrastructure/functions/functionYamlArtifact.js +31 -8
- package/src/emit/infrastructure/functions/templates/DssFunction_Yaml.ejs +21 -0
- package/src/emit/infrastructure/functions/templates/S3Function_Yaml.ejs +2 -3
- package/src/emit/infrastructure/resources/iamResourceArtifacts.js +67 -5
- package/src/emit/infrastructure/resources/resourceState.js +15 -5
- package/src/emit/infrastructure/resources/s3ResourceArtifacts.js +19 -3
- package/src/emit/infrastructure/resources/templates/GeneratedLambdaRoleServiceConfig.ejs +5 -3
- package/src/emit/infrastructure/resources/templates/S3Bucket_Yaml.ejs +1 -1
- package/src/emit/infrastructure/resources/templates/SystemDynamoDB_Yaml.ejs +2 -2
- package/src/emit/schemas/attributeTree/emitAttributeTreeSchemas.js +62 -1
- package/src/emit/schemas/error/emitErrorSchemas.js +120 -10
- package/src/emit/schemas/error/templates/errorConsts.ejs +12 -0
- package/src/generate.js +32 -34
- package/src/output/mergeHooks.js +105 -5
- package/src/plan/domainRegistry.js +0 -10
- package/task.md +40 -96
- package/test/integration/graphDrivenFlowSchema.test.js +58 -0
- package/test/integration/publicApi.test.js +33 -24
- package/test/unit/application/createTargetRoleHandler.test.js +101 -9
- package/test/unit/application/crudApplicationArtifacts.test.js +4 -0
- package/test/unit/application/customFlowApplicationArtifacts.test.js +6 -6
- package/test/unit/application/customFlowS3.test.js +730 -0
- package/test/unit/infrastructure/functionYamlArtifact.test.js +6 -4
- package/test/unit/infrastructure/resourceArtifacts.test.js +103 -0
- package/test/unit/output/mergeHooks.test.js +137 -0
- package/test/unit/schemas/attributeTreeSchemas.test.js +32 -3
- package/test/unit/schemas/attributeTreeSingleService.test.js +175 -0
- package/test/unit/schemas/dynamicRbacFlowSchemas.test.js +8 -6
- package/test/unit/schemas/dynamicRelationshipFlowSchemas.test.js +51 -0
- package/test/unit/schemas/errorSchemas.test.js +84 -5
- package/test/unit/templates/hookTagsValidation.test.js +83 -0
- package/src/emit/schemas/attributeTree/emitAttributeTreeTargetValueStandard.js +0 -132
- package/test/unit/schemas/attributeTreeDirectives.test.js +0 -177
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
|
-
import { readFile, rm,
|
|
2
|
+
import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import test, { after } from 'node:test';
|
|
@@ -7,7 +7,10 @@ import test, { after } from 'node:test';
|
|
|
7
7
|
import {
|
|
8
8
|
emitErrorSchemas,
|
|
9
9
|
errorSchemaManagedPaths,
|
|
10
|
-
ERROR_SCHEMA_PATH
|
|
10
|
+
ERROR_SCHEMA_PATH,
|
|
11
|
+
SHARED_ERROR_PACKAGE_PATH,
|
|
12
|
+
SHARED_ERROR_INDEX_PATH,
|
|
13
|
+
SHARED_ERROR_CONSTS_PATH
|
|
11
14
|
} from '../../../src/emit/schemas/error/emitErrorSchemas.js';
|
|
12
15
|
import { generate } from '../../../src/generate.js';
|
|
13
16
|
|
|
@@ -49,7 +52,7 @@ test('emitErrorSchemas produces expected ERROR_TYPES for graph and general error
|
|
|
49
52
|
]
|
|
50
53
|
});
|
|
51
54
|
|
|
52
|
-
assert.equal(artifacts.length,
|
|
55
|
+
assert.equal(artifacts.length, 4);
|
|
53
56
|
assert.equal(artifacts[0].path, ERROR_SCHEMA_PATH);
|
|
54
57
|
|
|
55
58
|
const content = artifacts[0].content;
|
|
@@ -86,6 +89,31 @@ test('emitErrorSchemas produces expected ERROR_TYPES for graph and general error
|
|
|
86
89
|
assert.ok(customIdx < explicitIdx);
|
|
87
90
|
assert.ok(explicitIdx < invalidIdx);
|
|
88
91
|
assert.ok(invalidIdx < notFoundIdx);
|
|
92
|
+
|
|
93
|
+
// Shared library artifacts
|
|
94
|
+
assert.equal(artifacts[1].path, SHARED_ERROR_PACKAGE_PATH);
|
|
95
|
+
const parsedPkg = JSON.parse(artifacts[1].content);
|
|
96
|
+
assert.equal(
|
|
97
|
+
parsedPkg.name,
|
|
98
|
+
'@izara_project/izara-myservice-library-errorlib'
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
assert.equal(artifacts[2].path, SHARED_ERROR_INDEX_PATH);
|
|
102
|
+
assert.match(
|
|
103
|
+
artifacts[2].content,
|
|
104
|
+
/import \* as errorLib from '\.\/src\/errorConsts\.js';/
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
assert.equal(artifacts[3].path, SHARED_ERROR_CONSTS_PATH);
|
|
108
|
+
const sharedContent = artifacts[3].content;
|
|
109
|
+
assert.match(
|
|
110
|
+
sharedContent,
|
|
111
|
+
/\/\/ only generate error that sharedLibrary: true/
|
|
112
|
+
);
|
|
113
|
+
assert.match(sharedContent, /INVALID_GENERATED_BY:/);
|
|
114
|
+
assert.match(sharedContent, /NOT_FOUND_SCHEMA:/);
|
|
115
|
+
assert.doesNotMatch(sharedContent, /CUSTOM_INTERNAL_ERROR:/);
|
|
116
|
+
assert.doesNotMatch(sharedContent, /EXPLICIT_SERVICE_ERROR:/);
|
|
89
117
|
});
|
|
90
118
|
|
|
91
119
|
test('emitErrorSchemas returns empty array when no errors provided', async () => {
|
|
@@ -97,9 +125,18 @@ test('emitErrorSchemas returns empty array when no errors provided', async () =>
|
|
|
97
125
|
assert.deepEqual(artifacts, []);
|
|
98
126
|
assert.deepEqual(errorSchemaManagedPaths([]), []);
|
|
99
127
|
assert.deepEqual(errorSchemaManagedPaths(['someError']), [ERROR_SCHEMA_PATH]);
|
|
128
|
+
assert.deepEqual(
|
|
129
|
+
errorSchemaManagedPaths([{ errorTag: 'E1', sharedLibrary: true }]),
|
|
130
|
+
[
|
|
131
|
+
ERROR_SCHEMA_PATH,
|
|
132
|
+
SHARED_ERROR_PACKAGE_PATH,
|
|
133
|
+
SHARED_ERROR_INDEX_PATH,
|
|
134
|
+
SHARED_ERROR_CONSTS_PATH
|
|
135
|
+
]
|
|
136
|
+
);
|
|
100
137
|
});
|
|
101
138
|
|
|
102
|
-
test('generate creates
|
|
139
|
+
test('generate creates errorConsts.js and libs/errorLib when ErrorSchemas directory exists', async () => {
|
|
103
140
|
const rootPath = join(
|
|
104
141
|
tmpdir(),
|
|
105
142
|
`error-schema-test-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
@@ -141,7 +178,7 @@ test('generate creates errorSchema.js when ErrorSchemas directory exists', async
|
|
|
141
178
|
|
|
142
179
|
const targetFile = join(
|
|
143
180
|
rootPath,
|
|
144
|
-
'app/src/schemas/ErrorSchemas/generateCode/
|
|
181
|
+
'app/src/schemas/ErrorSchemas/generateCode/errorConsts.js'
|
|
145
182
|
);
|
|
146
183
|
const content = await readFile(targetFile, 'utf8');
|
|
147
184
|
|
|
@@ -151,4 +188,46 @@ test('generate creates errorSchema.js when ErrorSchemas directory exists', async
|
|
|
151
188
|
assert.match(content, /MISSING_USER_NODE:/);
|
|
152
189
|
assert.match(content, /serviceTag:\s*'CategoryTreeStandard'/);
|
|
153
190
|
assert.doesNotMatch(content, /export default/);
|
|
191
|
+
|
|
192
|
+
// Verify libs/errorLib files
|
|
193
|
+
const pkgFile = join(rootPath, 'libs/errorLib/package.json');
|
|
194
|
+
const pkgContent = JSON.parse(await readFile(pkgFile, 'utf8'));
|
|
195
|
+
assert.equal(
|
|
196
|
+
pkgContent.name,
|
|
197
|
+
'@izara_project/izara-categorytreestandard-library-errorlib'
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const indexFile = join(rootPath, 'libs/errorLib/index.js');
|
|
201
|
+
const indexContent = await readFile(indexFile, 'utf8');
|
|
202
|
+
assert.match(indexContent, /export { errorLib };/);
|
|
203
|
+
|
|
204
|
+
const sharedConstsFile = join(rootPath, 'libs/errorLib/src/errorConsts.js');
|
|
205
|
+
const sharedConstsContent = await readFile(sharedConstsFile, 'utf8');
|
|
206
|
+
assert.match(
|
|
207
|
+
sharedConstsContent,
|
|
208
|
+
/\/\/ only generate error that sharedLibrary: true/
|
|
209
|
+
);
|
|
210
|
+
assert.match(sharedConstsContent, /NOT_FOUND_SCHEMA:/);
|
|
211
|
+
assert.match(sharedConstsContent, /INVALID_GENERATED_BY:/);
|
|
212
|
+
assert.match(sharedConstsContent, /MISSING_USER_NODE:/);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('generate creates ErrorSchemas directory if it does not exist', async () => {
|
|
216
|
+
const rootPath = join(
|
|
217
|
+
tmpdir(),
|
|
218
|
+
`error-schema-dir-test-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
219
|
+
);
|
|
220
|
+
roots.add(rootPath);
|
|
221
|
+
await mkdir(join(rootPath, 'config'), { recursive: true });
|
|
222
|
+
|
|
223
|
+
await writeFile(
|
|
224
|
+
join(rootPath, 'config/serverless.config.yml'),
|
|
225
|
+
'main_config:\n iz_serviceTag: TestService\n'
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
await generate(rootPath);
|
|
229
|
+
|
|
230
|
+
const errorSchemasDir = join(rootPath, 'app/src/schemas/ErrorSchemas');
|
|
231
|
+
const dirStat = await stat(errorSchemasDir);
|
|
232
|
+
assert.ok(dirStat.isDirectory());
|
|
154
233
|
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import test from 'node:test';
|
|
5
|
+
|
|
6
|
+
async function getTemplateFiles(dir) {
|
|
7
|
+
let results = [];
|
|
8
|
+
const entries = await readdir(dir);
|
|
9
|
+
for (const entry of entries) {
|
|
10
|
+
const fullPath = join(dir, entry);
|
|
11
|
+
const entryStat = await stat(fullPath);
|
|
12
|
+
if (entryStat.isDirectory()) {
|
|
13
|
+
const subResults = await getTemplateFiles(fullPath);
|
|
14
|
+
results = results.concat(subResults);
|
|
15
|
+
} else if (entry.endsWith('.ejs') || entry.endsWith('.js')) {
|
|
16
|
+
results.push(fullPath);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return results;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
test('all template files have valid hook tag syntax and matching pairs', async () => {
|
|
23
|
+
const emitDir = join(process.cwd(), 'src/emit');
|
|
24
|
+
const templateFiles = await getTemplateFiles(emitDir);
|
|
25
|
+
assert.ok(templateFiles.length > 0, 'Should find template files in src/emit');
|
|
26
|
+
|
|
27
|
+
const syntaxErrors = [];
|
|
28
|
+
|
|
29
|
+
for (const filePath of templateFiles) {
|
|
30
|
+
const content = await readFile(filePath, 'utf8');
|
|
31
|
+
const lines = content.split('\n');
|
|
32
|
+
|
|
33
|
+
const openTags = [];
|
|
34
|
+
const closeTags = [];
|
|
35
|
+
|
|
36
|
+
lines.forEach((line, lineIndex) => {
|
|
37
|
+
// Mask EJS expressions to avoid evaluating dynamic tags
|
|
38
|
+
const stripped = line.replace(/<%[\s\S]*?%>/g, 'DYNAMIC');
|
|
39
|
+
|
|
40
|
+
// Check for malformed hook opening/closing missing '>' before ')'
|
|
41
|
+
// e.g. //(<foo) or //(</foo) without closing angle bracket
|
|
42
|
+
const malformedMatch = stripped.match(/\/\/\s*\(\s*<\/?[^>\n]*\)/);
|
|
43
|
+
if (malformedMatch) {
|
|
44
|
+
syntaxErrors.push({
|
|
45
|
+
file: filePath,
|
|
46
|
+
line: lineIndex + 1,
|
|
47
|
+
type: 'MISSING_CLOSING_ANGLE_BRACKET',
|
|
48
|
+
snippet: line.trim()
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Collect normalized hook tags for matching
|
|
53
|
+
const openMatches = stripped.matchAll(/\/\/\s*\(<\s*([\w.-]+)\s*>\)/g);
|
|
54
|
+
for (const m of openMatches) {
|
|
55
|
+
openTags.push({ tag: m[1], line: lineIndex + 1 });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const closeMatches = stripped.matchAll(/\/\/\s*\(<\/\s*([\w.-]+)\s*>\)/g);
|
|
59
|
+
for (const m of closeMatches) {
|
|
60
|
+
closeTags.push({ tag: m[1], line: lineIndex + 1 });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Check count of open and close tags
|
|
65
|
+
if (openTags.length !== closeTags.length) {
|
|
66
|
+
syntaxErrors.push({
|
|
67
|
+
file: filePath,
|
|
68
|
+
type: 'MISMATCHED_HOOK_PAIR_COUNT',
|
|
69
|
+
openCount: openTags.length,
|
|
70
|
+
closeCount: closeTags.length,
|
|
71
|
+
openTags: openTags.map((t) => t.tag),
|
|
72
|
+
closeTags: closeTags.map((t) => t.tag)
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
assert.deepEqual(
|
|
78
|
+
syntaxErrors,
|
|
79
|
+
[],
|
|
80
|
+
`Found ${syntaxErrors.length} template hook syntax error(s):\n` +
|
|
81
|
+
JSON.stringify(syntaxErrors, null, 2)
|
|
82
|
+
);
|
|
83
|
+
});
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Emits target ValueStandard ObjectSchema for attributeTreeTarget directives
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
function _extractTargetDirectives(directives = []) {
|
|
6
|
-
if (!Array.isArray(directives)) {
|
|
7
|
-
return [];
|
|
8
|
-
}
|
|
9
|
-
const results = [];
|
|
10
|
-
const seenTags = new Set();
|
|
11
|
-
|
|
12
|
-
for (const directive of directives) {
|
|
13
|
-
if (
|
|
14
|
-
directive?.type === 'attributeTreeTarget' &&
|
|
15
|
-
directive?.attributeTreeTag
|
|
16
|
-
) {
|
|
17
|
-
const tag = directive.attributeTreeTag;
|
|
18
|
-
if (seenTags.has(tag)) {
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
seenTags.add(tag);
|
|
22
|
-
results.push(directive);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return results;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function _extractStorageResources(directive) {
|
|
30
|
-
if (directive?.storageResources) {
|
|
31
|
-
return directive.storageResources;
|
|
32
|
-
}
|
|
33
|
-
return {
|
|
34
|
-
myGraph: {
|
|
35
|
-
storageType: 'graph',
|
|
36
|
-
graphServerTag: 'GraphHandler'
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function _renderTargetValueStandardSchema(tag, storageResources) {
|
|
42
|
-
const storageResourceTags = Object.keys(storageResources);
|
|
43
|
-
if (storageResourceTags.length === 0) {
|
|
44
|
-
storageResourceTags.push('myGraph');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const storageJson = JSON.stringify(storageResources, null, 2)
|
|
48
|
-
.replace(/\n/g, '\n ');
|
|
49
|
-
const tagsJson = JSON.stringify(storageResourceTags);
|
|
50
|
-
|
|
51
|
-
return `export default [
|
|
52
|
-
{
|
|
53
|
-
objectType: '${tag}ValueStandard',
|
|
54
|
-
canDelete: true,
|
|
55
|
-
generatedBy: 'user',
|
|
56
|
-
storageResources: ${storageJson},
|
|
57
|
-
addOnDataStructure: [
|
|
58
|
-
//(<addOnDataStructure${tag}ValueStandard>)
|
|
59
|
-
// {
|
|
60
|
-
// type: 'propertyValue',
|
|
61
|
-
// propertyValuePrefix: '${tag}ValueStandard'
|
|
62
|
-
// }
|
|
63
|
-
//(</addOnDataStructure${tag}ValueStandard>)
|
|
64
|
-
],
|
|
65
|
-
fieldNames: {
|
|
66
|
-
${tag}ValueStandardId: {
|
|
67
|
-
type: 'string',
|
|
68
|
-
randomOnCreate: true,
|
|
69
|
-
canUpdate: false,
|
|
70
|
-
storageResourceTags: ${tagsJson}
|
|
71
|
-
},
|
|
72
|
-
label: {
|
|
73
|
-
type: 'string',
|
|
74
|
-
canUpdate: true,
|
|
75
|
-
storageResourceTags: ${tagsJson}
|
|
76
|
-
},
|
|
77
|
-
value: {
|
|
78
|
-
type: 'string',
|
|
79
|
-
requiredOnCreate: true,
|
|
80
|
-
canUpdate: true,
|
|
81
|
-
storageResourceTags: ${tagsJson}
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
identifiers: [
|
|
85
|
-
{
|
|
86
|
-
type: 'identifier',
|
|
87
|
-
fieldName: '${tag}ValueStandardId'
|
|
88
|
-
}
|
|
89
|
-
]
|
|
90
|
-
}
|
|
91
|
-
];
|
|
92
|
-
`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function attributeTreeTargetValueStandardManagedPaths(directives = []) {
|
|
96
|
-
const targets = _extractTargetDirectives(directives);
|
|
97
|
-
const paths = [];
|
|
98
|
-
|
|
99
|
-
for (const directive of targets) {
|
|
100
|
-
const tag = directive.attributeTreeTag;
|
|
101
|
-
paths.push(
|
|
102
|
-
`app/src/schemas/ObjectSchemas/generatedCode/attributeTree/` +
|
|
103
|
-
`${tag}ValueStandard.js`
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return paths;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export function emitAttributeTreeTargetValueStandard({
|
|
111
|
-
directives = []
|
|
112
|
-
} = {}) {
|
|
113
|
-
const targets = _extractTargetDirectives(directives);
|
|
114
|
-
if (targets.length === 0) {
|
|
115
|
-
return [];
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const artifacts = [];
|
|
119
|
-
|
|
120
|
-
for (const directive of targets) {
|
|
121
|
-
const tag = directive.attributeTreeTag;
|
|
122
|
-
const storageResources = _extractStorageResources(directive);
|
|
123
|
-
artifacts.push({
|
|
124
|
-
path:
|
|
125
|
-
`app/src/schemas/ObjectSchemas/generatedCode/attributeTree/` +
|
|
126
|
-
`${tag}ValueStandard.js`,
|
|
127
|
-
content: _renderTargetValueStandardSchema(tag, storageResources)
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return artifacts;
|
|
132
|
-
}
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import test, { after } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
loadGenerateDirectives
|
|
6
|
-
} from '../../../src/compile/loadSchemas.js';
|
|
7
|
-
import {
|
|
8
|
-
emitAttributeTreeTargetValueStandard,
|
|
9
|
-
attributeTreeTargetValueStandardManagedPaths
|
|
10
|
-
} from '../../../src/emit/schemas/attributeTree/emitAttributeTreeTargetValueStandard.js';
|
|
11
|
-
import { generate } from '../../../src/generate.js';
|
|
12
|
-
import {
|
|
13
|
-
createTestProject,
|
|
14
|
-
readProjectFile,
|
|
15
|
-
writeProjectFile,
|
|
16
|
-
cleanupTestProjects
|
|
17
|
-
} from '../../helpers/testProject.js';
|
|
18
|
-
|
|
19
|
-
after(async () => {
|
|
20
|
-
await cleanupTestProjects();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('loadGenerateDirectives returns empty array when directory missing', async () => {
|
|
24
|
-
const rootPath = await createTestProject({
|
|
25
|
-
prefix: 'izara-no-directives-test-',
|
|
26
|
-
serviceTag: 'TestService'
|
|
27
|
-
});
|
|
28
|
-
const project = { schemaRoot: `${rootPath}/app/src/schemas` };
|
|
29
|
-
const directives = await loadGenerateDirectives(project);
|
|
30
|
-
assert.deepEqual(directives, []);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('loadGenerateDirectives loads directives from GenerateDirectives folder', async () => {
|
|
34
|
-
const rootPath = await createTestProject({
|
|
35
|
-
prefix: 'izara-directives-load-test-',
|
|
36
|
-
serviceTag: 'SellOfferTermManager',
|
|
37
|
-
schemas: {
|
|
38
|
-
'GenerateDirectives/sellOfferTermValueStandard.js': `export default {
|
|
39
|
-
type: 'attributeTreeTarget',
|
|
40
|
-
attributeTreeTag: 'sellOfferTerm'
|
|
41
|
-
};
|
|
42
|
-
`
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
const project = { schemaRoot: `${rootPath}/app/src/schemas` };
|
|
46
|
-
const directives = await loadGenerateDirectives(project);
|
|
47
|
-
assert.equal(directives.length, 1);
|
|
48
|
-
assert.equal(directives[0].type, 'attributeTreeTarget');
|
|
49
|
-
assert.equal(directives[0].attributeTreeTag, 'sellOfferTerm');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('emitAttributeTreeTargetValueStandard emits expected schema with hook', () => {
|
|
53
|
-
const directives = [
|
|
54
|
-
{
|
|
55
|
-
type: 'attributeTreeTarget',
|
|
56
|
-
attributeTreeTag: 'sellOfferTerm'
|
|
57
|
-
}
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
const managedPaths =
|
|
61
|
-
attributeTreeTargetValueStandardManagedPaths(directives);
|
|
62
|
-
assert.deepEqual(managedPaths, [
|
|
63
|
-
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermValueStandard.js'
|
|
64
|
-
]);
|
|
65
|
-
|
|
66
|
-
const artifacts = emitAttributeTreeTargetValueStandard({ directives });
|
|
67
|
-
assert.equal(artifacts.length, 1);
|
|
68
|
-
|
|
69
|
-
const artifact = artifacts[0];
|
|
70
|
-
assert.equal(
|
|
71
|
-
artifact.path,
|
|
72
|
-
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermValueStandard.js'
|
|
73
|
-
);
|
|
74
|
-
assert.match(
|
|
75
|
-
artifact.content,
|
|
76
|
-
/objectType:\s*['"]sellOfferTermValueStandard['"]/
|
|
77
|
-
);
|
|
78
|
-
assert.match(artifact.content, /sellOfferTermValueStandardId/);
|
|
79
|
-
assert.match(
|
|
80
|
-
artifact.content,
|
|
81
|
-
/\/\/\(<addOnDataStructuresellOfferTermValueStandard>\)/
|
|
82
|
-
);
|
|
83
|
-
assert.match(
|
|
84
|
-
artifact.content,
|
|
85
|
-
/\/\/\(<\/addOnDataStructuresellOfferTermValueStandard>\)/
|
|
86
|
-
);
|
|
87
|
-
assert.match(artifact.content, /propertyValue/);
|
|
88
|
-
assert.match(artifact.content, /GraphHandler/);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test('managed paths and emitter return empty when no matching directives', () => {
|
|
92
|
-
assert.deepEqual(attributeTreeTargetValueStandardManagedPaths([]), []);
|
|
93
|
-
assert.deepEqual(
|
|
94
|
-
attributeTreeTargetValueStandardManagedPaths([{ type: 'other' }]),
|
|
95
|
-
[]
|
|
96
|
-
);
|
|
97
|
-
assert.deepEqual(emitAttributeTreeTargetValueStandard({ directives: [] }), []);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test('generate commits and cleans up attributeTreeTarget dynamic schemas', async () => {
|
|
101
|
-
const rootPath = await createTestProject({
|
|
102
|
-
prefix: 'izara-directives-gen-test-',
|
|
103
|
-
serviceTag: 'SellOfferTermManager',
|
|
104
|
-
schemas: {
|
|
105
|
-
'GenerateDirectives/sellOfferTermValueStandard.js': `export default {
|
|
106
|
-
type: 'attributeTreeTarget',
|
|
107
|
-
attributeTreeTag: 'sellOfferTerm'
|
|
108
|
-
};
|
|
109
|
-
`
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
await generate(rootPath);
|
|
114
|
-
|
|
115
|
-
const targetRelPath =
|
|
116
|
-
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermValueStandard.js';
|
|
117
|
-
const content = await readProjectFile(rootPath, targetRelPath);
|
|
118
|
-
assert.match(content, /sellOfferTermValueStandard/);
|
|
119
|
-
assert.match(
|
|
120
|
-
content,
|
|
121
|
-
/\/\/\(<addOnDataStructuresellOfferTermValueStandard>\)/
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
// Regeneration preserves user changes inside the hook
|
|
125
|
-
const modifiedContent = content.replace(
|
|
126
|
-
'//(<addOnDataStructuresellOfferTermValueStandard>)\n // {\n // type: \'propertyValue\',\n // propertyValuePrefix: \'sellOfferTermValueStandard\'\n // }\n //(</addOnDataStructuresellOfferTermValueStandard>)',
|
|
127
|
-
'//(<addOnDataStructuresellOfferTermValueStandard>)\n {\n type: \'propertyValue\',\n propertyValuePrefix: \'sellOfferTermValueStandard\'\n }\n //(</addOnDataStructuresellOfferTermValueStandard>)'
|
|
128
|
-
);
|
|
129
|
-
await writeProjectFile(rootPath, targetRelPath, modifiedContent);
|
|
130
|
-
|
|
131
|
-
await generate(rootPath);
|
|
132
|
-
|
|
133
|
-
const regeneratedContent = await readProjectFile(rootPath, targetRelPath);
|
|
134
|
-
assert.match(
|
|
135
|
-
regeneratedContent,
|
|
136
|
-
/type:\s*'propertyValue'/
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
// Cascading verification: PropertyValue schemas generated in phase 2
|
|
140
|
-
const propLabelPath =
|
|
141
|
-
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/sellOfferTermValueStandardPropertyLabel.js';
|
|
142
|
-
const propValuePath =
|
|
143
|
-
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/sellOfferTermValueStandardPropertyValue.js';
|
|
144
|
-
const hasPropRelPath =
|
|
145
|
-
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/hasSellOfferTermValueStandardPropertyValue.js';
|
|
146
|
-
const disPropRelPath =
|
|
147
|
-
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/disabledSellOfferTermValueStandardPropertyValue.js';
|
|
148
|
-
const isPropRelPath =
|
|
149
|
-
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/isSellOfferTermValueStandardPropertyLabel.js';
|
|
150
|
-
|
|
151
|
-
const propLabelContent = await readProjectFile(rootPath, propLabelPath);
|
|
152
|
-
assert.match(propLabelContent, /sellOfferTermValueStandardPropertyLabel/);
|
|
153
|
-
|
|
154
|
-
const propValueContent = await readProjectFile(rootPath, propValuePath);
|
|
155
|
-
assert.match(propValueContent, /sellOfferTermValueStandardPropertyValue/);
|
|
156
|
-
|
|
157
|
-
const hasPropRelContent = await readProjectFile(rootPath, hasPropRelPath);
|
|
158
|
-
assert.match(hasPropRelContent, /hasSellOfferTermValueStandardPropertyValue/);
|
|
159
|
-
|
|
160
|
-
const disPropRelContent = await readProjectFile(rootPath, disPropRelPath);
|
|
161
|
-
assert.match(disPropRelContent, /disabledSellOfferTermValueStandardPropertyValue/);
|
|
162
|
-
|
|
163
|
-
const isPropRelContent = await readProjectFile(rootPath, isPropRelPath);
|
|
164
|
-
assert.match(isPropRelContent, /isSellOfferTermValueStandardPropertyLabel/);
|
|
165
|
-
|
|
166
|
-
// When directive removed, file is cleaned up
|
|
167
|
-
await writeProjectFile(
|
|
168
|
-
rootPath,
|
|
169
|
-
'app/src/schemas/GenerateDirectives/sellOfferTermValueStandard.js',
|
|
170
|
-
'export default { type: "disabled" };\n'
|
|
171
|
-
);
|
|
172
|
-
await generate(rootPath);
|
|
173
|
-
|
|
174
|
-
await assert.rejects(readProjectFile(rootPath, targetRelPath), {
|
|
175
|
-
code: 'ENOENT'
|
|
176
|
-
});
|
|
177
|
-
});
|