@izara_project/izara-core-generate-service-code 1.0.97 → 1.0.99
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/flowValidator.js +45 -8
- package/src/compile/loadSchemas.js +26 -6
- package/src/emit/application/coreFunction/emitCoreFunctionArtifacts.js +15 -1
- package/src/emit/application/coreFunction/templates/InitialSetupConfig.ejs +8 -4
- package/src/emit/application/crud/templates/CreateEndpoint_Main.ejs +4 -4
- package/src/emit/application/crud/templates/CreateLogicalLib.ejs +60 -8
- package/src/emit/application/crud/templates/DeleteEndpoint_Main.ejs +4 -4
- package/src/emit/application/crud/templates/FlowEndpoint_HdrWbs.ejs +2 -2
- package/src/emit/application/crud/templates/FlowMain_Wbs.ejs +2 -2
- package/src/emit/application/crud/templates/UpdateEndpoint_Main.ejs +4 -4
- package/src/emit/application/custom/customFlowS3.js +4 -4
- package/src/emit/application/custom/templates/FlowEndpoint_Main.ejs +2 -2
- package/src/emit/application/custom/templates/s3/CreateObject_Main.ejs +5 -2
- package/src/emit/application/custom/templates/triggerCache/CheckTriggerCache_Main.ejs +2 -2
- package/src/emit/application/rbac/emitDynamicRbacFlowSchemas.js +4 -1
- package/src/emit/application/rbac/emitRbacApplicationArtifacts.js +76 -1
- package/src/emit/application/rbac/templates/ReservedDynamicUsage_Main.ejs +2 -0
- package/src/emit/application/rbac/templates/ReservedUsageTtlExpired_HdrDss.ejs +176 -0
- package/src/emit/application/relationship/templates/ChangeRelationship_Main.ejs +3 -2
- package/src/emit/application/relationship/templates/CreateRelationship_Main.ejs +3 -2
- package/src/emit/application/relationship/templates/DeleteRelationship_Main.ejs +3 -2
- package/src/emit/application/relationship/templates/GetRelationship_Main.ejs +3 -2
- package/src/emit/application/relationship/templates/MoveRelationship_Main.ejs +3 -2
- package/src/emit/application/relationship/templates/UpdateRelationship_Main.ejs +3 -2
- package/src/emit/application/system/templates/RegisterComplete_Main.ejs +6 -2
- package/src/emit/application/system/templates/Register_Main.ejs +6 -2
- package/src/emit/application/system/templates/WebSocketComplete_Main.ejs +3 -3
- package/src/emit/infrastructure/functions/functionYamlArtifact.js +28 -0
- package/src/emit/infrastructure/functions/templates/DssFunction_Yaml.ejs +21 -0
- package/src/emit/infrastructure/resources/iamResourceArtifacts.js +46 -6
- package/src/emit/infrastructure/resources/templates/GeneratedLambdaRoleServiceConfig.ejs +5 -3
- package/src/emit/schemas/attributeTree/emitAttributeTreeSchemas.js +75 -22
- package/src/emit/schemas/ledger/emitLedgerSchemas.js +33 -11
- package/src/emit/schemas/ledger/templates/LedgerObjectSchema.ejs +3 -0
- package/src/emit/schemas/ledger/templates/LedgerRelationshipSchema.ejs +1 -0
- package/src/emit/schemas/propertyValue/emitPropertyValueSchemas.js +329 -0
- package/src/generate.js +10 -73
- package/src/output/mergeHooks.js +169 -15
- package/src/plan/domainRegistry.js +31 -5
- package/task.md +76 -0
- package/test/integration/graphDrivenFlowSchema.test.js +58 -0
- package/test/integration/publicApi.test.js +54 -1
- package/test/unit/application/createTargetRoleHandler.test.js +70 -1
- package/test/unit/application/crudApplicationArtifacts.test.js +4 -0
- package/test/unit/application/customFlowApplicationArtifacts.test.js +9 -0
- package/test/unit/application/relationshipApplicationArtifacts.test.js +30 -0
- package/test/unit/infrastructure/resourceArtifacts.test.js +53 -0
- package/test/unit/output/mergeHooks.test.js +405 -0
- package/test/unit/schemas/attributeTreeSchemas.test.js +41 -63
- package/test/unit/schemas/attributeTreeSingleService.test.js +175 -0
- package/test/unit/schemas/ledgerSchemas.test.js +33 -7
- package/test/unit/schemas/propertyValueSchemas.test.js +265 -0
- package/test/unit/templates/hookTagsValidation.test.js +83 -0
- package/src/emit/schemas/attributeTree/emitAttributeTreeTargetSchemas.js +0 -153
- package/src/emit/schemas/attributeTree/resolveTargetServicePath.js +0 -111
|
@@ -8,9 +8,7 @@ import {
|
|
|
8
8
|
emitAttributeTreeObjectSchemas,
|
|
9
9
|
emitAttributeTreeRelationshipSchemas,
|
|
10
10
|
attributeTreeObjectSchemaManagedPaths,
|
|
11
|
-
attributeTreeRelationshipSchemaManagedPaths
|
|
12
|
-
resolveTargetServicePath,
|
|
13
|
-
emitAttributeTreeTargetSchemas
|
|
11
|
+
attributeTreeRelationshipSchemaManagedPaths
|
|
14
12
|
} from '../../../src/emit/schemas/attributeTree/emitAttributeTreeSchemas.js';
|
|
15
13
|
import { generate } from '../../../src/generate.js';
|
|
16
14
|
import {
|
|
@@ -25,7 +23,7 @@ after(async () => {
|
|
|
25
23
|
await cleanupTestProjects();
|
|
26
24
|
});
|
|
27
25
|
|
|
28
|
-
test('emitAttributeTreeObjectSchemas returns
|
|
26
|
+
test('emitAttributeTreeObjectSchemas returns 4 object schemas per attributeTree tag', () => {
|
|
29
27
|
const objects = [
|
|
30
28
|
{
|
|
31
29
|
objectType: 'sellOffer',
|
|
@@ -50,13 +48,14 @@ test('emitAttributeTreeObjectSchemas returns 3 object schemas per attributeTree
|
|
|
50
48
|
];
|
|
51
49
|
|
|
52
50
|
const artifacts = emitAttributeTreeObjectSchemas({ objects });
|
|
53
|
-
assert.equal(artifacts.length,
|
|
51
|
+
assert.equal(artifacts.length, 4);
|
|
54
52
|
|
|
55
53
|
const paths = artifacts.map((a) => a.path);
|
|
56
54
|
assert.deepEqual(paths, [
|
|
57
|
-
'app/src/schemas/ObjectSchemas/
|
|
58
|
-
'app/src/schemas/ObjectSchemas/
|
|
59
|
-
'app/src/schemas/ObjectSchemas/
|
|
55
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermLink.js',
|
|
56
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermValue.js',
|
|
57
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermLabel.js',
|
|
58
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermValueStandard.js'
|
|
60
59
|
]);
|
|
61
60
|
|
|
62
61
|
const valueArtifact = artifacts.find((a) =>
|
|
@@ -65,6 +64,26 @@ test('emitAttributeTreeObjectSchemas returns 3 object schemas per attributeTree
|
|
|
65
64
|
assert.match(valueArtifact.content, /"objectType": "sellOfferTermValue"/);
|
|
66
65
|
assert.match(valueArtifact.content, /"sellOfferTermValueId"/);
|
|
67
66
|
|
|
67
|
+
const valueStandardArtifact = artifacts.find((a) =>
|
|
68
|
+
a.path.endsWith('sellOfferTermValueStandard.js')
|
|
69
|
+
);
|
|
70
|
+
assert.match(
|
|
71
|
+
valueStandardArtifact.content,
|
|
72
|
+
/objectType:\s*['"]sellOfferTermValueStandard['"]/
|
|
73
|
+
);
|
|
74
|
+
assert.match(
|
|
75
|
+
valueStandardArtifact.content,
|
|
76
|
+
/sellOfferTermValueStandardId/
|
|
77
|
+
);
|
|
78
|
+
assert.match(
|
|
79
|
+
valueStandardArtifact.content,
|
|
80
|
+
/\/\/\(<addOnDataStructuresellOfferTermValueStandard>\)/
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const managedPaths = attributeTreeObjectSchemaManagedPaths(objects);
|
|
84
|
+
assert.equal(managedPaths.length, 4);
|
|
85
|
+
assert.deepEqual(managedPaths, paths);
|
|
86
|
+
|
|
68
87
|
for (const artifact of artifacts) {
|
|
69
88
|
assert.doesNotMatch(artifact.content, /dynamoDB/);
|
|
70
89
|
assert.match(artifact.content, /GraphHandler/);
|
|
@@ -103,10 +122,10 @@ test('emitAttributeTreeRelationshipSchemas returns 4 relationship schemas per at
|
|
|
103
122
|
|
|
104
123
|
const paths = artifacts.map((a) => a.path);
|
|
105
124
|
assert.deepEqual(paths, [
|
|
106
|
-
'app/src/schemas/RelationshipSchemas/
|
|
107
|
-
'app/src/schemas/RelationshipSchemas/
|
|
108
|
-
'app/src/schemas/RelationshipSchemas/
|
|
109
|
-
'app/src/schemas/RelationshipSchemas/
|
|
125
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/attributeTree/hasSellOfferTermLink.js',
|
|
126
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/attributeTree/disabledSellOfferTermLink.js',
|
|
127
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/attributeTree/isSellOfferTerm.js',
|
|
128
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/attributeTree/isSellOfferTermLabel.js'
|
|
110
129
|
]);
|
|
111
130
|
|
|
112
131
|
const hasRel = artifacts.find((a) => a.path.endsWith('hasSellOfferTermLink.js'));
|
|
@@ -153,15 +172,20 @@ test('generate commits and cleans up attributeTree dynamic schemas', async () =>
|
|
|
153
172
|
await generate(rootPath);
|
|
154
173
|
|
|
155
174
|
const objectRelPath =
|
|
156
|
-
'app/src/schemas/ObjectSchemas/
|
|
175
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermLink.js';
|
|
176
|
+
const valueStandardRelPath =
|
|
177
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermValueStandard.js';
|
|
157
178
|
const relRelPath =
|
|
158
|
-
'app/src/schemas/RelationshipSchemas/
|
|
179
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/attributeTree/hasSellOfferTermLink.js';
|
|
159
180
|
|
|
160
181
|
const objectContent = await readProjectFile(rootPath, objectRelPath);
|
|
161
182
|
assert.match(objectContent, /sellOfferTermLink/);
|
|
162
183
|
assert.match(objectContent, /GraphHandler/);
|
|
163
184
|
assert.doesNotMatch(objectContent, /dynamoDB/);
|
|
164
185
|
|
|
186
|
+
const valueStandardContent = await readProjectFile(rootPath, valueStandardRelPath);
|
|
187
|
+
assert.match(valueStandardContent, /sellOfferTermValueStandard/);
|
|
188
|
+
|
|
165
189
|
const relContent = await readProjectFile(rootPath, relRelPath);
|
|
166
190
|
assert.match(relContent, /hasSellOfferTermLink/);
|
|
167
191
|
assert.match(relContent, /sellOfferTermLink/);
|
|
@@ -173,6 +197,9 @@ test('generate commits and cleans up attributeTree dynamic schemas', async () =>
|
|
|
173
197
|
await assert.rejects(readProjectFile(rootPath, objectRelPath), {
|
|
174
198
|
code: 'ENOENT'
|
|
175
199
|
});
|
|
200
|
+
await assert.rejects(readProjectFile(rootPath, valueStandardRelPath), {
|
|
201
|
+
code: 'ENOENT'
|
|
202
|
+
});
|
|
176
203
|
await assert.rejects(readProjectFile(rootPath, relRelPath), {
|
|
177
204
|
code: 'ENOENT'
|
|
178
205
|
});
|
|
@@ -244,53 +271,4 @@ async function createProjectWithAttributeTree({
|
|
|
244
271
|
});
|
|
245
272
|
}
|
|
246
273
|
|
|
247
|
-
test('resolveTargetServicePath prioritizes dev suffix and matches attributeTag', async () => {
|
|
248
|
-
const tmpRoot = trackTestProject(
|
|
249
|
-
await mkdtemp(join(tmpdir(), 'izara-services-test-'))
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
const currentServiceDir = join(
|
|
253
|
-
tmpRoot,
|
|
254
|
-
'izara-market-products-sell-offer-manager-pong'
|
|
255
|
-
);
|
|
256
|
-
const targetWithSuffix = join(
|
|
257
|
-
tmpRoot,
|
|
258
|
-
'izara-market-products-sell-offer-term-pong'
|
|
259
|
-
);
|
|
260
|
-
const targetOtherDev = join(
|
|
261
|
-
tmpRoot,
|
|
262
|
-
'izara-market-products-sell-offer-term-alice'
|
|
263
|
-
);
|
|
264
|
-
const unrelatedService = join(
|
|
265
|
-
tmpRoot,
|
|
266
|
-
'izara-market-products-cart-pong'
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
await mkdir(join(currentServiceDir, 'app/src'), { recursive: true });
|
|
270
|
-
await mkdir(join(targetWithSuffix, 'app/src'), { recursive: true });
|
|
271
|
-
await mkdir(join(targetOtherDev, 'app/src'), { recursive: true });
|
|
272
|
-
await mkdir(join(unrelatedService, 'app/src'), { recursive: true });
|
|
273
|
-
|
|
274
|
-
const resolved = resolveTargetServicePath({
|
|
275
|
-
currentServiceRoot: currentServiceDir,
|
|
276
|
-
attributeTag: 'sellOfferTerm'
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
assert.equal(resolved, targetWithSuffix);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
test('emitAttributeTreeTargetSchemas produces expected standard schemas', () => {
|
|
283
|
-
const targetDir = '/dummy/path/izara-market-products-sellOfferTerm';
|
|
284
|
-
const artifacts = emitAttributeTreeTargetSchemas({
|
|
285
|
-
attributeTag: 'sellOfferTerm',
|
|
286
|
-
targetServiceRoot: targetDir
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
assert.equal(artifacts.length, 3);
|
|
290
|
-
const paths = artifacts.map((a) => a.path);
|
|
291
|
-
|
|
292
|
-
assert.ok(paths.some((p) => p.endsWith('sellOfferTermValueStandardPropertyLabel.js')));
|
|
293
|
-
assert.ok(paths.some((p) => p.endsWith('sellOfferTermValueStandardPropertyValue.js')));
|
|
294
|
-
assert.ok(paths.some((p) => p.endsWith('sellOfferTermValueStandard.js')));
|
|
295
|
-
});
|
|
296
274
|
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test, { after } from 'node:test';
|
|
3
|
+
import { generate } from '../../../src/generate.js';
|
|
4
|
+
import {
|
|
5
|
+
createTestProject,
|
|
6
|
+
readProjectFile,
|
|
7
|
+
writeProjectFile,
|
|
8
|
+
cleanupTestProjects
|
|
9
|
+
} from '../../helpers/testProject.js';
|
|
10
|
+
|
|
11
|
+
after(async () => {
|
|
12
|
+
await cleanupTestProjects();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('single-service attributeTree generation and propertyValue cascading', async () => {
|
|
16
|
+
const initialSchema = `export default [
|
|
17
|
+
{
|
|
18
|
+
objectType: 'sellOffer',
|
|
19
|
+
canDelete: false,
|
|
20
|
+
generatedBy: 'user',
|
|
21
|
+
addOnDataStructure: [
|
|
22
|
+
{
|
|
23
|
+
type: 'attributeTree',
|
|
24
|
+
attributeTreeTag: 'sellOfferTerm'
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
storageResources: {
|
|
28
|
+
dynamoDB: {
|
|
29
|
+
storageType: 'dynamoDB',
|
|
30
|
+
tableName: 'SellOfferRecords',
|
|
31
|
+
serviceTag: 'SellOfferManager'
|
|
32
|
+
},
|
|
33
|
+
myGraph: {
|
|
34
|
+
storageType: 'graph',
|
|
35
|
+
graphServerTag: 'GraphHandler'
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
fieldNames: {
|
|
39
|
+
sellOfferId: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
randomOnCreate: true,
|
|
42
|
+
canUpdate: false,
|
|
43
|
+
storageResourceTags: ['dynamoDB', 'myGraph']
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
identifiers: [
|
|
47
|
+
{
|
|
48
|
+
type: 'partitionKey',
|
|
49
|
+
fieldName: 'sellOfferId'
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const rootPath = await createTestProject({
|
|
57
|
+
prefix: 'izara-single-service-attr-tree-',
|
|
58
|
+
serviceTag: 'SellOfferManager',
|
|
59
|
+
schemas: {
|
|
60
|
+
'ObjectSchemas/SellOffer.js': initialSchema
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Phase 1: generate produces all 4 ObjectSchemas and 4 RelationshipSchemas
|
|
65
|
+
await generate(rootPath);
|
|
66
|
+
|
|
67
|
+
const linkPath =
|
|
68
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermLink.js';
|
|
69
|
+
const valuePath =
|
|
70
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermValue.js';
|
|
71
|
+
const labelPath =
|
|
72
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermLabel.js';
|
|
73
|
+
const valueStandardPath =
|
|
74
|
+
'app/src/schemas/ObjectSchemas/generatedCode/attributeTree/sellOfferTermValueStandard.js';
|
|
75
|
+
|
|
76
|
+
const linkContent = await readProjectFile(rootPath, linkPath);
|
|
77
|
+
assert.match(linkContent, /sellOfferTermLink/);
|
|
78
|
+
|
|
79
|
+
const valueContent = await readProjectFile(rootPath, valuePath);
|
|
80
|
+
assert.match(valueContent, /sellOfferTermValue/);
|
|
81
|
+
|
|
82
|
+
const labelContent = await readProjectFile(rootPath, labelPath);
|
|
83
|
+
assert.match(labelContent, /sellOfferTermLabel/);
|
|
84
|
+
|
|
85
|
+
const valueStandardContent = await readProjectFile(
|
|
86
|
+
rootPath,
|
|
87
|
+
valueStandardPath
|
|
88
|
+
);
|
|
89
|
+
assert.match(valueStandardContent, /sellOfferTermValueStandard/);
|
|
90
|
+
assert.match(
|
|
91
|
+
valueStandardContent,
|
|
92
|
+
/\/\/\(<addOnDataStructuresellOfferTermValueStandard>\)/
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// Check relationship schemas
|
|
96
|
+
const hasLinkRelPath =
|
|
97
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/attributeTree/hasSellOfferTermLink.js';
|
|
98
|
+
const hasLinkRel = await readProjectFile(rootPath, hasLinkRelPath);
|
|
99
|
+
assert.match(hasLinkRel, /hasSellOfferTermLink/);
|
|
100
|
+
|
|
101
|
+
// Phase 2: developer uncomments propertyValue addOn in ValueStandard
|
|
102
|
+
const modifiedValueStandard = valueStandardContent.replace(
|
|
103
|
+
'//(<addOnDataStructuresellOfferTermValueStandard>)\n // {\n // type: \'propertyValue\',\n // propertyValuePrefix: \'sellOfferTermValueStandard\'\n // }\n //(</addOnDataStructuresellOfferTermValueStandard>)',
|
|
104
|
+
'//(<addOnDataStructuresellOfferTermValueStandard>)\n {\n type: \'propertyValue\',\n propertyValuePrefix: \'sellOfferTermValueStandard\'\n }\n //(</addOnDataStructuresellOfferTermValueStandard>)'
|
|
105
|
+
);
|
|
106
|
+
await writeProjectFile(rootPath, valueStandardPath, modifiedValueStandard);
|
|
107
|
+
|
|
108
|
+
await generate(rootPath);
|
|
109
|
+
|
|
110
|
+
// Verify hook preservation
|
|
111
|
+
const reloadedValueStandard = await readProjectFile(
|
|
112
|
+
rootPath,
|
|
113
|
+
valueStandardPath
|
|
114
|
+
);
|
|
115
|
+
assert.match(reloadedValueStandard, /type:\s*'propertyValue'/);
|
|
116
|
+
|
|
117
|
+
// Verify cascading generation: propertyValue domain in the same repo
|
|
118
|
+
const propLabelPath =
|
|
119
|
+
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/sellOfferTermValueStandardPropertyLabel.js';
|
|
120
|
+
const propValuePath =
|
|
121
|
+
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/sellOfferTermValueStandardPropertyValue.js';
|
|
122
|
+
const hasPropRelPath =
|
|
123
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/hasSellOfferTermValueStandardPropertyValue.js';
|
|
124
|
+
const disPropRelPath =
|
|
125
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/disabledSellOfferTermValueStandardPropertyValue.js';
|
|
126
|
+
const isPropRelPath =
|
|
127
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/isSellOfferTermValueStandardPropertyLabel.js';
|
|
128
|
+
|
|
129
|
+
const propLabel = await readProjectFile(rootPath, propLabelPath);
|
|
130
|
+
assert.match(propLabel, /sellOfferTermValueStandardPropertyLabel/);
|
|
131
|
+
|
|
132
|
+
const propValue = await readProjectFile(rootPath, propValuePath);
|
|
133
|
+
assert.match(propValue, /sellOfferTermValueStandardPropertyValue/);
|
|
134
|
+
|
|
135
|
+
const hasPropRel = await readProjectFile(rootPath, hasPropRelPath);
|
|
136
|
+
assert.match(hasPropRel, /hasSellOfferTermValueStandardPropertyValue/);
|
|
137
|
+
|
|
138
|
+
const disPropRel = await readProjectFile(rootPath, disPropRelPath);
|
|
139
|
+
assert.match(disPropRel, /disabledSellOfferTermValueStandardPropertyValue/);
|
|
140
|
+
|
|
141
|
+
const isPropRel = await readProjectFile(rootPath, isPropRelPath);
|
|
142
|
+
assert.match(isPropRel, /isSellOfferTermValueStandardPropertyLabel/);
|
|
143
|
+
|
|
144
|
+
// Cleanup check: remove attributeTree addOn from base schema
|
|
145
|
+
const cleanSchema = `export default [
|
|
146
|
+
{
|
|
147
|
+
objectType: 'sellOffer',
|
|
148
|
+
canDelete: false,
|
|
149
|
+
generatedBy: 'user',
|
|
150
|
+
addOnDataStructure: [],
|
|
151
|
+
storageResources: {
|
|
152
|
+
myGraph: { storageType: 'graph', graphServerTag: 'GraphHandler' }
|
|
153
|
+
},
|
|
154
|
+
fieldNames: {
|
|
155
|
+
sellOfferId: { type: 'string', storageResourceTags: ['myGraph'] }
|
|
156
|
+
},
|
|
157
|
+
identifiers: [{ type: 'partitionKey', fieldName: 'sellOfferId' }]
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
`;
|
|
161
|
+
await writeProjectFile(
|
|
162
|
+
rootPath,
|
|
163
|
+
'app/src/schemas/ObjectSchemas/SellOffer.js',
|
|
164
|
+
cleanSchema
|
|
165
|
+
);
|
|
166
|
+
await generate(rootPath);
|
|
167
|
+
|
|
168
|
+
// All attributeTree schemas should be removed
|
|
169
|
+
await assert.rejects(readProjectFile(rootPath, linkPath), { code: 'ENOENT' });
|
|
170
|
+
await assert.rejects(readProjectFile(rootPath, valuePath), { code: 'ENOENT' });
|
|
171
|
+
await assert.rejects(readProjectFile(rootPath, labelPath), { code: 'ENOENT' });
|
|
172
|
+
await assert.rejects(readProjectFile(rootPath, valueStandardPath), {
|
|
173
|
+
code: 'ENOENT'
|
|
174
|
+
});
|
|
175
|
+
});
|
|
@@ -19,7 +19,7 @@ after(async () => {
|
|
|
19
19
|
await cleanupTestProjects();
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
test('emitLedgerObjectSchemas returns 1 object schema per ledger addOn', () => {
|
|
22
|
+
test('emitLedgerObjectSchemas returns 1 object schema per ledger addOn', async () => {
|
|
23
23
|
const objects = [
|
|
24
24
|
{
|
|
25
25
|
objectType: 'unitStandard',
|
|
@@ -61,7 +61,7 @@ test('emitLedgerObjectSchemas returns 1 object schema per ledger addOn', () => {
|
|
|
61
61
|
}
|
|
62
62
|
];
|
|
63
63
|
|
|
64
|
-
const artifacts = emitLedgerObjectSchemas({ objects });
|
|
64
|
+
const artifacts = await emitLedgerObjectSchemas({ objects });
|
|
65
65
|
assert.equal(artifacts.length, 2);
|
|
66
66
|
|
|
67
67
|
const paths = artifacts.map((a) => a.path);
|
|
@@ -81,7 +81,7 @@ test('emitLedgerObjectSchemas returns 1 object schema per ledger addOn', () => {
|
|
|
81
81
|
assert.match(entryArtifact.content, /GraphHandler/);
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
test('emitLedgerRelationshipSchemas returns current, old, and is relationship schemas per ledger addOn', () => {
|
|
84
|
+
test('emitLedgerRelationshipSchemas returns current, old, and is relationship schemas per ledger addOn', async () => {
|
|
85
85
|
const objects = [
|
|
86
86
|
{
|
|
87
87
|
objectType: 'unitStandard',
|
|
@@ -113,7 +113,7 @@ test('emitLedgerRelationshipSchemas returns current, old, and is relationship sc
|
|
|
113
113
|
}
|
|
114
114
|
];
|
|
115
115
|
|
|
116
|
-
const artifacts = emitLedgerRelationshipSchemas({
|
|
116
|
+
const artifacts = await emitLedgerRelationshipSchemas({
|
|
117
117
|
objects,
|
|
118
118
|
serviceTag: 'UnitStandard'
|
|
119
119
|
});
|
|
@@ -156,14 +156,40 @@ test('emitLedgerRelationshipSchemas returns current, old, and is relationship sc
|
|
|
156
156
|
assert.match(isRel.content, /"generatedBy": "systemNoUser"/);
|
|
157
157
|
assert.match(isRel.content, /"supplyLocation"/);
|
|
158
158
|
assert.match(isRel.content, /"unitPacking"/);
|
|
159
|
+
|
|
160
|
+
// 4. Verify requiredOnCreate is false in links
|
|
161
|
+
const _parseRel = (content) => {
|
|
162
|
+
const raw = content
|
|
163
|
+
.replace(/^export default\s+/, '')
|
|
164
|
+
.replace(/;\s*$/, '');
|
|
165
|
+
return JSON.parse(raw)[0];
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const currentRelData = Object.values(_parseRel(currentRel.content))[0];
|
|
169
|
+
for (const link of currentRelData.links) {
|
|
170
|
+
assert.equal(link.from.requiredOnCreate, false);
|
|
171
|
+
assert.equal(link.to.requiredOnCreate, false);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const oldRelData = Object.values(_parseRel(oldRel.content))[0];
|
|
175
|
+
for (const link of oldRelData.links) {
|
|
176
|
+
assert.equal(link.from.requiredOnCreate, false);
|
|
177
|
+
assert.equal(link.to.requiredOnCreate, false);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const isRelData = Object.values(_parseRel(isRel.content))[0];
|
|
181
|
+
for (const link of isRelData.links) {
|
|
182
|
+
assert.equal(link.from.requiredOnCreate, false);
|
|
183
|
+
assert.equal(link.to.requiredOnCreate, false);
|
|
184
|
+
}
|
|
159
185
|
});
|
|
160
186
|
|
|
161
|
-
test('managed paths return empty array when no ledger is present', () => {
|
|
187
|
+
test('managed paths return empty array when no ledger is present', async () => {
|
|
162
188
|
const objects = [{ objectType: 'user', addOnDataStructure: [] }];
|
|
163
189
|
assert.deepEqual(ledgerObjectSchemaManagedPaths(objects), []);
|
|
164
190
|
assert.deepEqual(ledgerRelationshipSchemaManagedPaths(objects), []);
|
|
165
|
-
assert.deepEqual(emitLedgerObjectSchemas({ objects }), []);
|
|
166
|
-
assert.deepEqual(emitLedgerRelationshipSchemas({ objects }), []);
|
|
191
|
+
assert.deepEqual(await emitLedgerObjectSchemas({ objects }), []);
|
|
192
|
+
assert.deepEqual(await emitLedgerRelationshipSchemas({ objects }), []);
|
|
167
193
|
});
|
|
168
194
|
|
|
169
195
|
test('generate commits and cleans up ledger dynamic schemas', async () => {
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test, { after } from 'node:test';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
emitPropertyValueObjectSchemas,
|
|
6
|
+
emitPropertyValueRelationshipSchemas,
|
|
7
|
+
propertyValueObjectSchemaManagedPaths,
|
|
8
|
+
propertyValueRelationshipSchemaManagedPaths
|
|
9
|
+
} from '../../../src/emit/schemas/propertyValue/emitPropertyValueSchemas.js';
|
|
10
|
+
import { generate } from '../../../src/generate.js';
|
|
11
|
+
import {
|
|
12
|
+
createTestProject,
|
|
13
|
+
readProjectFile,
|
|
14
|
+
writeProjectFile,
|
|
15
|
+
cleanupTestProjects
|
|
16
|
+
} from '../../helpers/testProject.js';
|
|
17
|
+
|
|
18
|
+
after(async () => {
|
|
19
|
+
await cleanupTestProjects();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('emitPropertyValueObjectSchemas returns 2 object schemas per propertyValue addOn', () => {
|
|
23
|
+
const objects = [
|
|
24
|
+
{
|
|
25
|
+
objectType: 'item',
|
|
26
|
+
serviceTag: 'ItemService',
|
|
27
|
+
storageResources: {
|
|
28
|
+
dynamoDB: {
|
|
29
|
+
storageType: 'dynamoDB',
|
|
30
|
+
tableName: 'ItemRecords'
|
|
31
|
+
},
|
|
32
|
+
myGraph: {
|
|
33
|
+
storageType: 'graph',
|
|
34
|
+
graphServerTag: 'GraphHandler'
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
addOnDataStructure: [
|
|
38
|
+
{
|
|
39
|
+
type: 'propertyValue',
|
|
40
|
+
propertyValuePrefix: 'itemProperty'
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
objectType: 'supplyNetwork',
|
|
46
|
+
serviceTag: 'SupplyService',
|
|
47
|
+
storageResources: {
|
|
48
|
+
myGraph: {
|
|
49
|
+
storageType: 'graph',
|
|
50
|
+
graphServerTag: 'GraphHandler'
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
addOnDataStructure: [
|
|
54
|
+
{
|
|
55
|
+
type: 'propertyValue'
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const artifacts = emitPropertyValueObjectSchemas({ objects });
|
|
62
|
+
assert.equal(artifacts.length, 4);
|
|
63
|
+
|
|
64
|
+
const paths = artifacts.map((a) => a.path);
|
|
65
|
+
assert.deepEqual(paths, [
|
|
66
|
+
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/itemPropertyPropertyLabel.js',
|
|
67
|
+
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/itemPropertyPropertyValue.js',
|
|
68
|
+
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/supplyNetworkPropertyLabel.js',
|
|
69
|
+
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/supplyNetworkPropertyValue.js'
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
const labelArtifact = artifacts[0];
|
|
73
|
+
assert.match(
|
|
74
|
+
labelArtifact.content,
|
|
75
|
+
/"objectType": "itemPropertyPropertyLabel"/
|
|
76
|
+
);
|
|
77
|
+
assert.match(labelArtifact.content, /"itemPropertyPropertyLabelId"/);
|
|
78
|
+
assert.match(labelArtifact.content, /"generatedBy": "user"/);
|
|
79
|
+
assert.match(labelArtifact.content, /"canDelete": true/);
|
|
80
|
+
assert.doesNotMatch(labelArtifact.content, /dynamoDB/);
|
|
81
|
+
assert.match(labelArtifact.content, /GraphHandler/);
|
|
82
|
+
|
|
83
|
+
const valueArtifact = artifacts[1];
|
|
84
|
+
assert.match(
|
|
85
|
+
valueArtifact.content,
|
|
86
|
+
/"objectType": "itemPropertyPropertyValue"/
|
|
87
|
+
);
|
|
88
|
+
assert.match(valueArtifact.content, /"itemPropertyPropertyValueId"/);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('emitPropertyValueRelationshipSchemas returns 3 relationship schemas per propertyValue addOn', () => {
|
|
92
|
+
const objects = [
|
|
93
|
+
{
|
|
94
|
+
objectType: 'item',
|
|
95
|
+
serviceTag: 'ItemService',
|
|
96
|
+
storageResources: {
|
|
97
|
+
myGraph: {
|
|
98
|
+
storageType: 'graph',
|
|
99
|
+
graphServerTag: 'GraphHandler'
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
addOnDataStructure: [
|
|
103
|
+
{
|
|
104
|
+
type: 'propertyValue',
|
|
105
|
+
propertyValuePrefix: 'item'
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
const artifacts = emitPropertyValueRelationshipSchemas({
|
|
112
|
+
objects,
|
|
113
|
+
serviceTag: 'ItemService'
|
|
114
|
+
});
|
|
115
|
+
assert.equal(artifacts.length, 3);
|
|
116
|
+
|
|
117
|
+
const paths = artifacts.map((a) => a.path);
|
|
118
|
+
assert.deepEqual(paths, [
|
|
119
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/hasItemPropertyValue.js',
|
|
120
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/disabledItemPropertyValue.js',
|
|
121
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/isItemPropertyLabel.js'
|
|
122
|
+
]);
|
|
123
|
+
|
|
124
|
+
// 1. hasItemPropertyValue
|
|
125
|
+
const hasRel = artifacts[0];
|
|
126
|
+
assert.match(hasRel.content, /"hasItemPropertyValue"/);
|
|
127
|
+
assert.match(hasRel.content, /"generatedBy": "user"/);
|
|
128
|
+
assert.match(hasRel.content, /"objectType": "item"/);
|
|
129
|
+
assert.match(hasRel.content, /"objectType": "itemPropertyValue"/);
|
|
130
|
+
assert.match(hasRel.content, /"linkType": "one"/);
|
|
131
|
+
assert.match(hasRel.content, /"linkType": "many"/);
|
|
132
|
+
|
|
133
|
+
// 2. disabledItemPropertyValue
|
|
134
|
+
const disabledRel = artifacts[1];
|
|
135
|
+
assert.match(disabledRel.content, /"disabledItemPropertyValue"/);
|
|
136
|
+
assert.match(disabledRel.content, /"generatedBy": "user"/);
|
|
137
|
+
|
|
138
|
+
// 3. isItemPropertyLabel
|
|
139
|
+
const isRel = artifacts[2];
|
|
140
|
+
assert.match(isRel.content, /"isItemPropertyLabel"/);
|
|
141
|
+
assert.match(isRel.content, /"generatedBy": "systemNoUser"/);
|
|
142
|
+
assert.match(isRel.content, /"objectType": "itemPropertyLabel"/);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('managed paths return empty array when no propertyValue is present', () => {
|
|
146
|
+
const objects = [{ objectType: 'user', addOnDataStructure: [] }];
|
|
147
|
+
assert.deepEqual(propertyValueObjectSchemaManagedPaths(objects), []);
|
|
148
|
+
assert.deepEqual(propertyValueRelationshipSchemaManagedPaths(objects), []);
|
|
149
|
+
assert.deepEqual(emitPropertyValueObjectSchemas({ objects }), []);
|
|
150
|
+
assert.deepEqual(emitPropertyValueRelationshipSchemas({ objects }), []);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('generate commits and cleans up propertyValue dynamic schemas', async () => {
|
|
154
|
+
const rootPath = await createProjectWithPropertyValue({ hasAddOn: true });
|
|
155
|
+
await generate(rootPath);
|
|
156
|
+
|
|
157
|
+
const labelPath =
|
|
158
|
+
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/itemPropertyLabel.js';
|
|
159
|
+
const valuePath =
|
|
160
|
+
'app/src/schemas/ObjectSchemas/generatedCode/propertyValue/itemPropertyValue.js';
|
|
161
|
+
const hasRelPath =
|
|
162
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/hasItemPropertyValue.js';
|
|
163
|
+
const disabledRelPath =
|
|
164
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/disabledItemPropertyValue.js';
|
|
165
|
+
const isRelPath =
|
|
166
|
+
'app/src/schemas/RelationshipSchemas/generatedCode/propertyValue/isItemPropertyLabel.js';
|
|
167
|
+
|
|
168
|
+
const labelContent = await readProjectFile(rootPath, labelPath);
|
|
169
|
+
assert.match(labelContent, /itemPropertyLabel/);
|
|
170
|
+
assert.match(labelContent, /GraphHandler/);
|
|
171
|
+
|
|
172
|
+
const valueContent = await readProjectFile(rootPath, valuePath);
|
|
173
|
+
assert.match(valueContent, /itemPropertyValue/);
|
|
174
|
+
|
|
175
|
+
const hasRelContent = await readProjectFile(rootPath, hasRelPath);
|
|
176
|
+
assert.match(hasRelContent, /hasItemPropertyValue/);
|
|
177
|
+
|
|
178
|
+
const disabledRelContent = await readProjectFile(rootPath, disabledRelPath);
|
|
179
|
+
assert.match(disabledRelContent, /disabledItemPropertyValue/);
|
|
180
|
+
|
|
181
|
+
const isRelContent = await readProjectFile(rootPath, isRelPath);
|
|
182
|
+
assert.match(isRelContent, /isItemPropertyLabel/);
|
|
183
|
+
|
|
184
|
+
// Re-run without addOn to verify stale file cleanup
|
|
185
|
+
await createProjectWithPropertyValue({ rootPath, hasAddOn: false });
|
|
186
|
+
await generate(rootPath);
|
|
187
|
+
|
|
188
|
+
await assert.rejects(readProjectFile(rootPath, labelPath), {
|
|
189
|
+
code: 'ENOENT'
|
|
190
|
+
});
|
|
191
|
+
await assert.rejects(readProjectFile(rootPath, valuePath), {
|
|
192
|
+
code: 'ENOENT'
|
|
193
|
+
});
|
|
194
|
+
await assert.rejects(readProjectFile(rootPath, hasRelPath), {
|
|
195
|
+
code: 'ENOENT'
|
|
196
|
+
});
|
|
197
|
+
await assert.rejects(readProjectFile(rootPath, disabledRelPath), {
|
|
198
|
+
code: 'ENOENT'
|
|
199
|
+
});
|
|
200
|
+
await assert.rejects(readProjectFile(rootPath, isRelPath), {
|
|
201
|
+
code: 'ENOENT'
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
async function createProjectWithPropertyValue({
|
|
206
|
+
rootPath: existingRoot,
|
|
207
|
+
hasAddOn = true
|
|
208
|
+
} = {}) {
|
|
209
|
+
let addOnContent = ' addOnDataStructure: [],';
|
|
210
|
+
if (hasAddOn) {
|
|
211
|
+
addOnContent = `
|
|
212
|
+
addOnDataStructure: [
|
|
213
|
+
{
|
|
214
|
+
type: 'propertyValue',
|
|
215
|
+
propertyValuePrefix: 'item'
|
|
216
|
+
}
|
|
217
|
+
],`;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const schemaContent = `export default [
|
|
221
|
+
{
|
|
222
|
+
objectType: 'item',
|
|
223
|
+
canDelete: false,
|
|
224
|
+
generatedBy: 'user',${addOnContent}
|
|
225
|
+
storageResources: {
|
|
226
|
+
graph: {
|
|
227
|
+
storageType: 'graph',
|
|
228
|
+
graphServerTag: 'GraphHandler'
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
fieldNames: {
|
|
232
|
+
itemId: {
|
|
233
|
+
type: 'string',
|
|
234
|
+
randomOnCreate: true,
|
|
235
|
+
canUpdate: false,
|
|
236
|
+
storageResourceTags: ['graph']
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
identifiers: [
|
|
240
|
+
{
|
|
241
|
+
type: 'partitionKey',
|
|
242
|
+
fieldName: 'itemId'
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
];
|
|
247
|
+
`;
|
|
248
|
+
|
|
249
|
+
if (existingRoot) {
|
|
250
|
+
await writeProjectFile(
|
|
251
|
+
existingRoot,
|
|
252
|
+
'app/src/schemas/ObjectSchemas/Item.js',
|
|
253
|
+
schemaContent
|
|
254
|
+
);
|
|
255
|
+
return existingRoot;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return await createTestProject({
|
|
259
|
+
prefix: 'izara-property-value-test-',
|
|
260
|
+
serviceTag: 'ItemService',
|
|
261
|
+
schemas: {
|
|
262
|
+
'ObjectSchemas/Item.js': schemaContent
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}
|