@flighthq/requirement-codegen 0.5.1-edge.1692.64cda40 → 0.5.1-edge.1892.cbd15bd
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/README.md +2 -2
- package/dist/contract.d.ts +2 -2
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +2 -2
- package/dist/contract.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/requirementCodegen.d.ts.map +1 -1
- package/dist/requirementCodegen.js +46 -3
- package/dist/requirementCodegen.js.map +1 -1
- package/package.json +4 -4
- package/src/requirementCodegen.test.ts +126 -2
package/README.md
CHANGED
|
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/requirement-codegen`
|
|
|
13
13
|
This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
|
|
14
14
|
|
|
15
15
|
- [Flight project](https://github.com/flighthq/flight)
|
|
16
|
-
- [Source for @flighthq/requirement-codegen@0.5.1-edge.
|
|
17
|
-
- [License](https://github.com/flighthq/flight/blob/
|
|
16
|
+
- [Source for @flighthq/requirement-codegen@0.5.1-edge.1892.cbd15bd](https://github.com/flighthq/flight/tree/cbd15bd13373265e8f6dcf0cb057a16aee812919/packages/requirement-codegen)
|
|
17
|
+
- [License](https://github.com/flighthq/flight/blob/cbd15bd13373265e8f6dcf0cb057a16aee812919/LICENSE.md)
|
package/dist/contract.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './requirementCodegen';
|
|
2
|
-
export { initializeRequirementCodegenPlan } from './requirementCodegen';
|
|
1
|
+
export * from './requirementCodegen.ts';
|
|
2
|
+
export { initializeRequirementCodegenPlan } from './requirementCodegen.ts';
|
|
3
3
|
//# sourceMappingURL=contract.d.ts.map
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,gCAAgC,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/contract.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export { initializeRequirementCodegenPlan } from
|
|
1
|
+
export * from "./requirementCodegen.js";
|
|
2
|
+
export { initializeRequirementCodegenPlan } from "./requirementCodegen.js";
|
|
3
3
|
//# sourceMappingURL=contract.js.map
|
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,gCAAgC,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createRequirementCodegenPlan } from './requirementCodegen';
|
|
1
|
+
export { createRequirementCodegenPlan } from './requirementCodegen.ts';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createRequirementCodegenPlan } from
|
|
1
|
+
export { createRequirementCodegenPlan } from "./requirementCodegen.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirementCodegen.d.ts","sourceRoot":"","sources":["../src/requirementCodegen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,MAAM,EACN,kBAAkB,EAClB,kBAAkB,EAElB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"requirementCodegen.d.ts","sourceRoot":"","sources":["../src/requirementCodegen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,MAAM,EACN,kBAAkB,EAClB,kBAAkB,EAElB,sBAAsB,EAGtB,cAAc,EACf,MAAM,0BAA0B,CAAC;AAElC,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EACrC,YAAY,EAAE,QAAQ,CAAC,cAAc,CAAC,EACtC,OAAO,EAAE,MAAM,GACd,sBAAsB,GAAG,MAAM,CAIjC;AAID,wBAAgB,gCAAgC,CAC9C,GAAG,EAAE,kBAAkB,CAAC,sBAAsB,GAAG,MAAM,CAAC,EACxD,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EACrC,YAAY,EAAE,QAAQ,CAAC,cAAc,CAAC,EACtC,OAAO,EAAE,MAAM,GACd,IAAI,CAkCN"}
|
|
@@ -9,25 +9,68 @@ export function createRequirementCodegenPlan(catalog, requirements, backend) {
|
|
|
9
9
|
// is ruled; this kernel cannot encode that decision accidentally because it returns no source text.
|
|
10
10
|
export function initializeRequirementCodegenPlan(out, catalog, requirements, backend) {
|
|
11
11
|
const entries = [];
|
|
12
|
+
const declined = [];
|
|
12
13
|
const unresolved = [];
|
|
13
14
|
const seen = new Set();
|
|
14
|
-
for (const requirement of requirements.requirements) {
|
|
15
|
+
for (const requirement of expandRequirements(catalog, requirements.requirements)) {
|
|
15
16
|
const identity = requirementIdentity(requirement);
|
|
16
17
|
if (seen.has(identity))
|
|
17
18
|
continue;
|
|
18
19
|
seen.add(identity);
|
|
19
20
|
const matches = findRequirementCatalogEntries(catalog, backend, requirement.facet, requirement.key);
|
|
20
|
-
if (matches.length
|
|
21
|
+
if (matches.length > 0) {
|
|
22
|
+
entries.push(...matches);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
// Nothing satisfies it HERE. A disposition says that is deliberate for this exact backend, facet
|
|
26
|
+
// and kind, so the gap is recorded with its reason instead of reported as an oversight. Matched
|
|
27
|
+
// exactly and per backend: a decision canvas made says nothing about gl, which still reports.
|
|
28
|
+
const disposition = catalog.dispositions?.find((candidate) => candidate.backend === backend && candidate.facet === requirement.facet && candidate.kind === requirement.key);
|
|
29
|
+
if (disposition === undefined) {
|
|
21
30
|
unresolved.push({ facet: requirement.facet, key: requirement.key });
|
|
22
31
|
}
|
|
23
32
|
else {
|
|
24
|
-
|
|
33
|
+
declined.push({
|
|
34
|
+
reason: disposition.reason,
|
|
35
|
+
requirement: { facet: requirement.facet, key: requirement.key },
|
|
36
|
+
});
|
|
25
37
|
}
|
|
26
38
|
}
|
|
27
39
|
out.backend = backend;
|
|
40
|
+
out.declined = declined;
|
|
28
41
|
out.entries = entries;
|
|
29
42
|
out.unresolved = unresolved;
|
|
30
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Adds the render requirements a format requirement implies, so one pass resolves both halves.
|
|
46
|
+
*
|
|
47
|
+
* A `document.format` requirement names a TAG and a renderer is keyed by a NODE KIND, so without this
|
|
48
|
+
* a render backend resolves nothing and every fragment comes back empty while the parser fragment
|
|
49
|
+
* fills — which is exactly what the per-file manifest is supposed to prevent. Expansion is ADDITIVE:
|
|
50
|
+
* the original requirement stays, because the parser backend still has to resolve it.
|
|
51
|
+
*
|
|
52
|
+
* Two match shapes, both exact-string: a translation keyed on the full key applies to that requirement,
|
|
53
|
+
* and one keyed on a bare format namespace applies to every requirement in it. The namespace form is
|
|
54
|
+
* what carries the kinds a document produces regardless of its tags — a SWF's `MovieClip` root exists
|
|
55
|
+
* even in a file whose only tag is `SetBackgroundColor`, which no per-tag row could state.
|
|
56
|
+
*/
|
|
57
|
+
function expandRequirements(catalog, requirements) {
|
|
58
|
+
const translations = catalog.translations;
|
|
59
|
+
if (translations === undefined || translations.length === 0)
|
|
60
|
+
return requirements;
|
|
61
|
+
const expanded = [...requirements];
|
|
62
|
+
for (const requirement of requirements) {
|
|
63
|
+
const namespace = requirement.key.includes('.') ? requirement.key.slice(0, requirement.key.indexOf('.')) : null;
|
|
64
|
+
for (const translation of translations) {
|
|
65
|
+
if (translation.from.facet !== requirement.facet)
|
|
66
|
+
continue;
|
|
67
|
+
const matches = translation.from.key === requirement.key || (namespace !== null && translation.from.key === namespace);
|
|
68
|
+
if (matches)
|
|
69
|
+
expanded.push(...translation.to);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return expanded;
|
|
73
|
+
}
|
|
31
74
|
function requirementIdentity(requirement) {
|
|
32
75
|
return `${requirement.facet}\0${requirement.key}`;
|
|
33
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirementCodegen.js","sourceRoot":"","sources":["../src/requirementCodegen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"requirementCodegen.js","sourceRoot":"","sources":["../src/requirementCodegen.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/requirement-codegen",
|
|
3
|
-
"version": "0.5.1-edge.
|
|
3
|
+
"version": "0.5.1-edge.1892.cbd15bd",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/entity": "0.5.1-edge.
|
|
42
|
-
"@flighthq/requirement-catalog": "0.5.1-edge.
|
|
43
|
-
"@flighthq/types": "0.5.1-edge.
|
|
41
|
+
"@flighthq/entity": "0.5.1-edge.1892.cbd15bd",
|
|
42
|
+
"@flighthq/requirement-catalog": "0.5.1-edge.1892.cbd15bd",
|
|
43
|
+
"@flighthq/types": "0.5.1-edge.1892.cbd15bd"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"typescript": "^5.3.0"
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { allocateEntity, finishEntity } from '@flighthq/entity/contract';
|
|
2
2
|
import { createRequirementCatalog } from '@flighthq/requirement-catalog/contract';
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
Requirement,
|
|
5
|
+
RequirementCatalog,
|
|
6
|
+
RequirementCatalogEntry,
|
|
7
|
+
RequirementDisposition,
|
|
8
|
+
RequirementSet,
|
|
9
|
+
} from '@flighthq/types/contract';
|
|
4
10
|
import { EntityRuntimeKey, RequirementFacet } from '@flighthq/types/contract';
|
|
5
11
|
|
|
6
|
-
import { createRequirementCodegenPlan, initializeRequirementCodegenPlan } from './requirementCodegen';
|
|
12
|
+
import { createRequirementCodegenPlan, initializeRequirementCodegenPlan } from './requirementCodegen.ts';
|
|
7
13
|
|
|
8
14
|
const shapeRenderer: RequirementCatalogEntry = {
|
|
9
15
|
backend: 'webgl',
|
|
@@ -79,8 +85,126 @@ describe('createRequirementCodegenPlan', () => {
|
|
|
79
85
|
});
|
|
80
86
|
});
|
|
81
87
|
});
|
|
88
|
+
describe('createRequirementCodegenPlan with dispositions', () => {
|
|
89
|
+
it('routes a disposed requirement to declined rather than unresolved, carrying the reason', () => {
|
|
90
|
+
const plan = createRequirementCodegenPlan(
|
|
91
|
+
disposedCatalog([], [disposition('dom', 'Tilemap', 'no DOM tilemap path')]),
|
|
92
|
+
disposedSet([disposedRequirement('Tilemap')]),
|
|
93
|
+
'dom',
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(plan.unresolved).toEqual([]);
|
|
97
|
+
expect(plan.declined).toEqual([
|
|
98
|
+
{ reason: 'no DOM tilemap path', requirement: { facet: RequirementFacet.SceneNodeKind, key: 'Tilemap' } },
|
|
99
|
+
]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// The whole point: a decision and an oversight must not look alike.
|
|
103
|
+
it('leaves an undisposed gap in unresolved, so an oversight still reports', () => {
|
|
104
|
+
const plan = createRequirementCodegenPlan(
|
|
105
|
+
disposedCatalog([], []),
|
|
106
|
+
disposedSet([disposedRequirement('Tilemap')]),
|
|
107
|
+
'dom',
|
|
108
|
+
);
|
|
109
|
+
expect(plan.declined).toEqual([]);
|
|
110
|
+
expect(plan.unresolved).toEqual([{ facet: RequirementFacet.SceneNodeKind, key: 'Tilemap' }]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// ★ EXACTNESS, ONE AXIS AT A TIME. A disposition names one backend, one facet and one kind. If any
|
|
114
|
+
// of the three were matched loosely it would silence requirements nobody considered, which is the
|
|
115
|
+
// failure this feature exists to prevent rather than introduce.
|
|
116
|
+
it('does not apply to another backend', () => {
|
|
117
|
+
const c = disposedCatalog([], [disposition('dom', 'Tilemap', 'no DOM tilemap path')]);
|
|
118
|
+
expect(createRequirementCodegenPlan(c, disposedSet([disposedRequirement('Tilemap')]), 'canvas').unresolved).toEqual(
|
|
119
|
+
[{ facet: RequirementFacet.SceneNodeKind, key: 'Tilemap' }],
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('does not apply to another kind', () => {
|
|
124
|
+
const c = disposedCatalog([], [disposition('dom', 'Tilemap', 'no DOM tilemap path')]);
|
|
125
|
+
expect(createRequirementCodegenPlan(c, disposedSet([disposedRequirement('QuadBatch')]), 'dom').unresolved).toEqual([
|
|
126
|
+
{ facet: RequirementFacet.SceneNodeKind, key: 'QuadBatch' },
|
|
127
|
+
]);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('does not apply to another facet', () => {
|
|
131
|
+
const c = disposedCatalog(
|
|
132
|
+
[],
|
|
133
|
+
[{ ...disposition('dom', 'Tilemap', 'no DOM tilemap path'), facet: RequirementFacet.DocumentFormat }],
|
|
134
|
+
);
|
|
135
|
+
expect(createRequirementCodegenPlan(c, disposedSet([disposedRequirement('Tilemap')]), 'dom').unresolved).toEqual([
|
|
136
|
+
{ facet: RequirementFacet.SceneNodeKind, key: 'Tilemap' },
|
|
137
|
+
]);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('emits no entry for a declined requirement, so nothing is imported or registered for it', () => {
|
|
141
|
+
const plan = createRequirementCodegenPlan(
|
|
142
|
+
disposedCatalog([], [disposition('dom', 'Tilemap', 'no DOM tilemap path')]),
|
|
143
|
+
disposedSet([disposedRequirement('Tilemap')]),
|
|
144
|
+
'dom',
|
|
145
|
+
);
|
|
146
|
+
expect(plan.entries).toEqual([]);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// A disposition is a fallback for a gap, never an override: if the backend CAN satisfy it, it does.
|
|
150
|
+
it('never overrides a row that actually resolves', () => {
|
|
151
|
+
const plan = createRequirementCodegenPlan(
|
|
152
|
+
disposedCatalog([disposedEntry('dom', 'Tilemap')], [disposition('dom', 'Tilemap', 'stale decision')]),
|
|
153
|
+
disposedSet([disposedRequirement('Tilemap')]),
|
|
154
|
+
'dom',
|
|
155
|
+
);
|
|
156
|
+
expect(plan.entries.map((e) => e.implementationSymbol)).toEqual(['domTilemapRenderer']);
|
|
157
|
+
expect(plan.declined).toEqual([]);
|
|
158
|
+
expect(plan.unresolved).toEqual([]);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('reports one requirement declined and another missing in the same plan', () => {
|
|
162
|
+
const plan = createRequirementCodegenPlan(
|
|
163
|
+
disposedCatalog([], [disposition('dom', 'Tilemap', 'no DOM tilemap path')]),
|
|
164
|
+
disposedSet([disposedRequirement('Tilemap'), disposedRequirement('QuadBatch')]),
|
|
165
|
+
'dom',
|
|
166
|
+
);
|
|
167
|
+
expect(plan.declined.map((d) => d.requirement.key)).toEqual(['Tilemap']);
|
|
168
|
+
expect(plan.unresolved.map((r) => r.key)).toEqual(['QuadBatch']);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
82
172
|
describe('initializeRequirementCodegenPlan', () => {
|
|
83
173
|
it('is the construction initializer of createRequirementCodegenPlan', () => {
|
|
84
174
|
expect(typeof initializeRequirementCodegenPlan).toBe('function');
|
|
85
175
|
});
|
|
86
176
|
});
|
|
177
|
+
|
|
178
|
+
function disposedRequirement(kind: string): Requirement {
|
|
179
|
+
return { facet: RequirementFacet.SceneNodeKind, key: kind };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Built the way every other set in this file is built, so the test needs no dependency the package
|
|
183
|
+
// does not already declare.
|
|
184
|
+
function disposedSet(requirements: readonly Requirement[]): RequirementSet {
|
|
185
|
+
const out = allocateEntity<RequirementSet>();
|
|
186
|
+
out.covers = [RequirementFacet.SceneNodeKind];
|
|
187
|
+
out.requirements = [...requirements];
|
|
188
|
+
return finishEntity(out);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function disposition(backend: string, kind: string, reason: string): RequirementDisposition {
|
|
192
|
+
return { backend, facet: RequirementFacet.SceneNodeKind, kind, reason };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function disposedEntry(backend: string, kind: string): RequirementCatalogEntry {
|
|
196
|
+
return {
|
|
197
|
+
backend,
|
|
198
|
+
facet: RequirementFacet.SceneNodeKind,
|
|
199
|
+
implementationImport: '@flighthq/scene2d-dom',
|
|
200
|
+
implementationSymbol: `${backend}${kind}Renderer`,
|
|
201
|
+
kind,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function disposedCatalog(
|
|
206
|
+
entries: readonly RequirementCatalogEntry[],
|
|
207
|
+
dispositions: readonly RequirementDisposition[],
|
|
208
|
+
): RequirementCatalog {
|
|
209
|
+
return { dispositions: [...dispositions], entries: [...entries] };
|
|
210
|
+
}
|