@flighthq/requirement-codegen 0.5.1-edge.1704.1832e8b → 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 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.1704.1832e8b](https://github.com/flighthq/flight/tree/1832e8b8f7a898d2b15ad3712c3262f0dbfddda1/packages/requirement-codegen)
17
- - [License](https://github.com/flighthq/flight/blob/1832e8b8f7a898d2b15ad3712c3262f0dbfddda1/LICENSE.md)
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)
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,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 './requirementCodegen';
2
- export { initializeRequirementCodegenPlan } from './requirementCodegen';
1
+ export * from "./requirementCodegen.js";
2
+ export { initializeRequirementCodegenPlan } from "./requirementCodegen.js";
3
3
  //# sourceMappingURL=contract.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC"}
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 './requirementCodegen';
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,sBAAsB,CAAC"}
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,EAEtB,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,CAkBN"}
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,6 +9,7 @@ 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
15
  for (const requirement of expandRequirements(catalog, requirements.requirements)) {
@@ -17,14 +18,26 @@ export function initializeRequirementCodegenPlan(out, catalog, requirements, bac
17
18
  continue;
18
19
  seen.add(identity);
19
20
  const matches = findRequirementCatalogEntries(catalog, backend, requirement.facet, requirement.key);
20
- if (matches.length === 0) {
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
- entries.push(...matches);
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"requirementCodegen.js","sourceRoot":"","sources":["../src/requirementCodegen.ts"],"names":[],"mappings":"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"}
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;AAYvF,MAAM,UAAU,4BAA4B,CAC1C,OAAqC,EACrC,YAAsC,EACtC,OAAe;IAEf,MAAM,GAAG,GAAG,cAAc,EAAmC,CAAC;IAC9D,gCAAgC,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IACtE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,wGAAwG;AACxG,oGAAoG;AACpG,MAAM,UAAU,gCAAgC,CAC9C,GAAwD,EACxD,OAAqC,EACrC,YAAsC,EACtC,OAAe;IAEf,MAAM,OAAO,GAA8B,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAA6B,EAAE,CAAC;IAC9C,MAAM,UAAU,GAAkB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,WAAW,IAAI,kBAAkB,CAAC,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC,EAAE,CAAC;QACjF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnB,MAAM,OAAO,GAAG,6BAA6B,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;QACpG,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;YACzB,SAAS;QACX,CAAC;QACD,iGAAiG;QACjG,gGAAgG;QAChG,8FAA8F;QAC9F,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,IAAI,CAC5C,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,OAAO,KAAK,OAAO,IAAI,SAAS,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK,IAAI,SAAS,CAAC,IAAI,KAAK,WAAW,CAAC,GAAG,CAC/G,CAAC;QACF,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,WAAW,CAAC,MAAM;gBAC1B,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,CAAC,GAAG,EAAE;aAChE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;IACtB,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACxB,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;IACtB,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC;AAC9B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,kBAAkB,CACzB,OAAqC,EACrC,YAA8C;IAE9C,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC1C,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,YAAY,CAAC;IACjF,MAAM,QAAQ,GAA4B,CAAC,GAAG,YAAY,CAAC,CAAC;IAC5D,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChH,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK;gBAAE,SAAS;YAC3D,MAAM,OAAO,GACX,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,WAAW,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;YACzG,IAAI,OAAO;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,mBAAmB,CAAC,WAAkC;IAC7D,OAAO,GAAG,WAAW,CAAC,KAAK,KAAK,WAAW,CAAC,GAAG,EAAE,CAAC;AACpD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/requirement-codegen",
3
- "version": "0.5.1-edge.1704.1832e8b",
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.1704.1832e8b",
42
- "@flighthq/requirement-catalog": "0.5.1-edge.1704.1832e8b",
43
- "@flighthq/types": "0.5.1-edge.1704.1832e8b"
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 { RequirementCatalogEntry, RequirementSet } from '@flighthq/types/contract';
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
+ }