@flighthq/vite-plugin-manifest 0.5.1-next.1680.bdc44c6

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/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2013-2026 Joshua Granick and other contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # @flighthq/vite-plugin-manifest
2
+
3
+ Vite plugin serving generated Flight registration source from analyzed content
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm install @flighthq/vite-plugin-manifest
9
+ ```
10
+
11
+ Import the supported application-facing API from `@flighthq/vite-plugin-manifest`. The `@flighthq/vite-plugin-manifest/contract` export is the wider package-to-package contract used to compose Flight itself.
12
+
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
+
15
+ - [Flight project](https://github.com/flighthq/flight)
16
+ - [Source for @flighthq/vite-plugin-manifest@0.5.1-next.1680.bdc44c6](https://github.com/flighthq/flight/tree/bdc44c63675b7c50301154e66b79e2d29d6262da/packages/vite-plugin-manifest)
17
+ - [License](https://github.com/flighthq/flight/blob/bdc44c63675b7c50301154e66b79e2d29d6262da/LICENSE.md)
@@ -0,0 +1,18 @@
1
+ import type { RequirementSet } from '@flighthq/types/contract';
2
+ /**
3
+ * Reads one content file and reports what it requires.
4
+ *
5
+ * The plugin owns no format knowledge: an analyzer is a function the format package already exports,
6
+ * and this signature is only the shape they share. A new format is added by registering its analyzer
7
+ * here or by passing one in `analyzers`, never by teaching this package to read bytes.
8
+ */
9
+ export type ContentAnalyzer = (source: Uint8Array) => RequirementSet;
10
+ /**
11
+ * The formats Flight analyzes out of the box, keyed by lowercase file extension.
12
+ *
13
+ * These are the format packages' own exports called directly. Duplicating their logic here would let
14
+ * a build's idea of what a file needs drift from what the importer actually reads — the two must be
15
+ * the same walk or the manifest is a guess.
16
+ */
17
+ export declare const DEFAULT_CONTENT_ANALYZERS: Readonly<Record<string, ContentAnalyzer>>;
18
+ //# sourceMappingURL=contentAnalyzers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentAnalyzers.d.ts","sourceRoot":"","sources":["../src/contentAnalyzers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,cAAc,CAAC;AAErE;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAO9E,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { parseAwd2Requirements } from '@flighthq/scene3d-formats/contract';
2
+ import { parseSwfRequirements } from '@flighthq/swf/contract';
3
+ /**
4
+ * The formats Flight analyzes out of the box, keyed by lowercase file extension.
5
+ *
6
+ * These are the format packages' own exports called directly. Duplicating their logic here would let
7
+ * a build's idea of what a file needs drift from what the importer actually reads — the two must be
8
+ * the same walk or the manifest is a guess.
9
+ */
10
+ export const DEFAULT_CONTENT_ANALYZERS = Object.freeze({
11
+ // Away3D writes `.awd`; `.awd2` is accepted too because the format is AWD2 and projects name the
12
+ // file either way. Both resolve to the same analyzer, so the choice of suffix never changes what a
13
+ // build reads.
14
+ '.awd': (source) => parseAwd2Requirements(source, null, null),
15
+ '.awd2': (source) => parseAwd2Requirements(source, null, null),
16
+ '.swf': (source) => parseSwfRequirements(source, null, null),
17
+ });
18
+ //# sourceMappingURL=contentAnalyzers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentAnalyzers.js","sourceRoot":"","sources":["../src/contentAnalyzers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAY9D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAA8C,MAAM,CAAC,MAAM,CAAC;IAChG,iGAAiG;IACjG,mGAAmG;IACnG,eAAe;IACf,MAAM,EAAE,CAAC,MAAkB,EAAE,EAAE,CAAC,qBAAqB,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC;IACzE,OAAO,EAAE,CAAC,MAAkB,EAAE,EAAE,CAAC,qBAAqB,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC;IAC1E,MAAM,EAAE,CAAC,MAAkB,EAAE,EAAE,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC;CACzE,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './contentAnalyzers';
2
+ export * from './manifestPlugin';
3
+ export * from './manifestModuleSource';
4
+ export * from './requirementOptionFields';
5
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './contentAnalyzers';
2
+ export * from './manifestPlugin';
3
+ export * from './manifestModuleSource';
4
+ export * from './requirementOptionFields';
5
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './contentAnalyzers';
2
+ export * from './manifestPlugin';
3
+ export * from './manifestModuleSource';
4
+ export * from './requirementOptionFields';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './contentAnalyzers';
2
+ export * from './manifestPlugin';
3
+ export * from './manifestModuleSource';
4
+ export * from './requirementOptionFields';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { RequirementCatalogEntry } from '@flighthq/types/contract';
2
+ /** The backends a manifest module always exports a fragment for, and the export name each one uses. */
3
+ export declare const MANIFEST_BACKEND_EXPORTS: Readonly<Record<string, string>>;
4
+ /**
5
+ * The catalog backend whose rows become `parserOptions` rather than a render-state fragment.
6
+ *
7
+ * A row's DESTINATION is its backend, not its facet: the same `document.format` requirement resolves
8
+ * to a tag handler for the parser and to a node renderer for `canvas`, and only the catalog author
9
+ * knows which row is which. Routing by facet alone would send both to the same place.
10
+ */
11
+ export declare const MANIFEST_PARSER_BACKEND = "parser";
12
+ /** One resolved row: the catalog entry, and the requirement kind it satisfies. */
13
+ export interface ManifestModuleEntry {
14
+ readonly entry: Readonly<RequirementCatalogEntry>;
15
+ readonly kind: string;
16
+ }
17
+ /** What the emitter produced, and every row it could not place. */
18
+ export interface ManifestModuleResult {
19
+ /** Rows dropped with the reason, so a caller reports them instead of losing them silently. */
20
+ readonly problems: readonly string[];
21
+ readonly source: string;
22
+ }
23
+ /**
24
+ * Emits the per-file manifest module for one content file.
25
+ *
26
+ * Flat named exports — `canvasOptions`, `glOptions`, `wgpuOptions`, `domOptions`, `parserOptions` — so
27
+ * an application writes `import { glOptions } from './asset.swf?manifest'` and spreads it straight
28
+ * into `createGlRenderState`. Flat flat named bindings are what make the module shakable: a bundler
29
+ * that sees only `glOptions` imported can drop every other fragment AND the implementation modules
30
+ * only they referenced, which it could not do if the fragments hung off one default object.
31
+ *
32
+ * Every referenced symbol gets a precise named import from the module the catalog row names. There is
33
+ * no barrel import and no dynamic lookup, so the import graph states exactly which implementations
34
+ * this one file needs.
35
+ *
36
+ * Deterministic: imports are grouped by module with modules and symbols sorted, map entries are
37
+ * emitted in sorted kind order, and array entries keep catalog order. The same inputs always produce
38
+ * byte-identical source.
39
+ */
40
+ export declare function generateManifestModuleSource(rows: readonly ManifestModuleEntry[], extension: string): ManifestModuleResult;
41
+ //# sourceMappingURL=manifestModuleSource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifestModuleSource.d.ts","sourceRoot":"","sources":["../src/manifestModuleSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAIxE,uGAAuG;AACvG,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKpE,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAEhD,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACnC,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,SAAS,mBAAmB,EAAE,EACpC,SAAS,EAAE,MAAM,GAChB,oBAAoB,CAuDtB"}
@@ -0,0 +1,125 @@
1
+ import { BACKEND_OPTION_FIELDS, PARSER_HANDLER_FIELDS, REQUIREMENT_OPTION_FIELDS } from './requirementOptionFields';
2
+ /** The backends a manifest module always exports a fragment for, and the export name each one uses. */
3
+ export const MANIFEST_BACKEND_EXPORTS = Object.freeze({
4
+ canvas: 'canvasOptions',
5
+ dom: 'domOptions',
6
+ gl: 'glOptions',
7
+ wgpu: 'wgpuOptions',
8
+ });
9
+ /**
10
+ * The catalog backend whose rows become `parserOptions` rather than a render-state fragment.
11
+ *
12
+ * A row's DESTINATION is its backend, not its facet: the same `document.format` requirement resolves
13
+ * to a tag handler for the parser and to a node renderer for `canvas`, and only the catalog author
14
+ * knows which row is which. Routing by facet alone would send both to the same place.
15
+ */
16
+ export const MANIFEST_PARSER_BACKEND = 'parser';
17
+ /**
18
+ * Emits the per-file manifest module for one content file.
19
+ *
20
+ * Flat named exports — `canvasOptions`, `glOptions`, `wgpuOptions`, `domOptions`, `parserOptions` — so
21
+ * an application writes `import { glOptions } from './asset.swf?manifest'` and spreads it straight
22
+ * into `createGlRenderState`. Flat flat named bindings are what make the module shakable: a bundler
23
+ * that sees only `glOptions` imported can drop every other fragment AND the implementation modules
24
+ * only they referenced, which it could not do if the fragments hung off one default object.
25
+ *
26
+ * Every referenced symbol gets a precise named import from the module the catalog row names. There is
27
+ * no barrel import and no dynamic lookup, so the import graph states exactly which implementations
28
+ * this one file needs.
29
+ *
30
+ * Deterministic: imports are grouped by module with modules and symbols sorted, map entries are
31
+ * emitted in sorted kind order, and array entries keep catalog order. The same inputs always produce
32
+ * byte-identical source.
33
+ */
34
+ export function generateManifestModuleSource(rows, extension) {
35
+ const importsByModule = new Map();
36
+ const byBackend = new Map();
37
+ const parserRows = [];
38
+ const problems = [];
39
+ for (const row of rows) {
40
+ if (row.entry.backend === MANIFEST_PARSER_BACKEND) {
41
+ addImport(importsByModule, row.entry.implementationImport, row.entry.implementationSymbol);
42
+ parserRows.push(row);
43
+ continue;
44
+ }
45
+ // Two ways a render-backend row cannot be placed, and NEITHER is a silent skip. A facet with no
46
+ // render-state field at all (compression, physics, resource mime type) has nowhere to go; and a
47
+ // field this particular backend does not declare — blendRealizations on WGPU, say — would emit a
48
+ // fragment that spreads into nothing. Both are reported so the build can see what it lost.
49
+ const field = REQUIREMENT_OPTION_FIELDS[row.entry.facet];
50
+ if (field === undefined) {
51
+ problems.push(`facet ${row.entry.facet} has no render-state options field: dropped ${row.kind} for ${row.entry.backend}`);
52
+ continue;
53
+ }
54
+ const accepted = BACKEND_OPTION_FIELDS[row.entry.backend];
55
+ if (accepted === undefined) {
56
+ problems.push(`unknown backend ${row.entry.backend}: dropped ${row.entry.facet} ${row.kind}`);
57
+ continue;
58
+ }
59
+ if (!accepted.has(field)) {
60
+ problems.push(`backend ${row.entry.backend} has no ${field} field: dropped ${row.entry.facet} ${row.kind}`);
61
+ continue;
62
+ }
63
+ addImport(importsByModule, row.entry.implementationImport, row.entry.implementationSymbol);
64
+ let list = byBackend.get(row.entry.backend);
65
+ if (list === undefined) {
66
+ list = [];
67
+ byBackend.set(row.entry.backend, list);
68
+ }
69
+ list.push(row);
70
+ }
71
+ const lines = [
72
+ '// GENERATED by @flighthq/vite-plugin-manifest. Do not edit.',
73
+ `// Requirements of one ${extension} file, resolved for every backend in the catalog.`,
74
+ ];
75
+ const importLines = [...importsByModule.keys()]
76
+ .sort()
77
+ .map((module) => `import { ${[...importsByModule.get(module)].sort().join(', ')} } from '${module}';`);
78
+ if (importLines.length > 0)
79
+ lines.push('', ...importLines);
80
+ for (const backend of Object.keys(MANIFEST_BACKEND_EXPORTS).sort()) {
81
+ lines.push('', ...backendFragment(MANIFEST_BACKEND_EXPORTS[backend], byBackend.get(backend) ?? []));
82
+ }
83
+ lines.push('', ...parserFragment(parserRows, PARSER_HANDLER_FIELDS[extension] ?? 'handlers'));
84
+ return { problems, source: `${lines.join('\n')}\n` };
85
+ }
86
+ function addImport(importsByModule, module, symbol) {
87
+ let symbols = importsByModule.get(module);
88
+ if (symbols === undefined) {
89
+ symbols = new Set();
90
+ importsByModule.set(module, symbols);
91
+ }
92
+ symbols.add(symbol);
93
+ }
94
+ function backendFragment(exportName, rows) {
95
+ const byField = new Map();
96
+ for (const row of rows) {
97
+ const field = REQUIREMENT_OPTION_FIELDS[row.entry.facet];
98
+ let list = byField.get(field);
99
+ if (list === undefined) {
100
+ list = [];
101
+ byField.set(field, list);
102
+ }
103
+ list.push(row);
104
+ }
105
+ // An empty fragment is still exported. A backend this content needs nothing for must spread to
106
+ // nothing rather than fail to import, so an application can spread every fragment unconditionally.
107
+ if (byField.size === 0)
108
+ return [`export const ${exportName} = {};`];
109
+ const fields = [...byField.keys()].sort().map((field) => {
110
+ const entries = [...byField.get(field)]
111
+ .sort((a, b) => a.kind.localeCompare(b.kind))
112
+ .map((row) => ` ['${row.kind}', ${row.entry.implementationSymbol}],`);
113
+ return ` ${field}: new Map([\n${entries.join('\n')}\n ]),`;
114
+ });
115
+ return [`export const ${exportName} = {`, ...fields, '};'];
116
+ }
117
+ function parserFragment(rows, field) {
118
+ if (rows.length === 0)
119
+ return ['export const parserOptions = {};'];
120
+ // Catalog order is preserved rather than sorted: a handler list is ordered, and reordering it
121
+ // changes which handler claims a contested tag and whether AWD2's build phases see their inputs.
122
+ const handlers = rows.map((row) => ` ${row.entry.implementationSymbol},`);
123
+ return [`export const parserOptions = {`, ` ${field}: [`, ...handlers, ' ],', '};'];
124
+ }
125
+ //# sourceMappingURL=manifestModuleSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifestModuleSource.js","sourceRoot":"","sources":["../src/manifestModuleSource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { NonEntityCreateResult, RequirementCatalog } from '@flighthq/types/contract';
2
+ /** The import suffix that asks this plugin for a file's manifest instead of the file itself. */
3
+ export declare const MANIFEST_QUERY_SUFFIX = "?manifest";
4
+ /** What `createManifestPlugin` accepts. Every input is explicit; nothing is discovered by convention. */
5
+ export interface ManifestPluginOptions {
6
+ /** The catalog mapping a requirement to the implementation that satisfies it, for every backend. */
7
+ readonly catalog: Readonly<RequirementCatalog>;
8
+ /**
9
+ * Called for every unsupported format, unreadable file, analyzer failure and unresolved requirement.
10
+ * Defaults to a warning on the `flight-manifest` channel through `@flighthq/log`. A requirement the
11
+ * build cannot place is reported rather than skipped: silently dropping one is how a bundle ends up
12
+ * missing an implementation it needed.
13
+ */
14
+ readonly onDiagnostic?: (message: string) => void;
15
+ }
16
+ /** The subset of Vite's plugin surface this factory produces. Structural, so Vite is a peer, not a dep. */
17
+ export interface ManifestPlugin {
18
+ /**
19
+ * Runs in Vite's `pre` stage. Without it Vite's own asset handling claims `./asset.swf?manifest`
20
+ * first and hands rollup the binary to parse as JavaScript — the plugin must see the id before the
21
+ * default resolver treats the path as a file to serve.
22
+ */
23
+ readonly enforce: 'pre';
24
+ readonly handleHotUpdate: (context: {
25
+ readonly file: string;
26
+ }) => void;
27
+ readonly load: (id: string) => Promise<string | null>;
28
+ readonly name: string;
29
+ readonly resolveId: (id: string, importer?: string) => string | null;
30
+ }
31
+ /**
32
+ * Creates the plugin. Explicit factory, no default export and no module-level state: importing this
33
+ * package configures nothing.
34
+ *
35
+ * It intercepts a per-file import — `import { glOptions } from './asset.swf?manifest'` — reads THAT
36
+ * file, picks the analyzer by extension, resolves the requirements against the catalog for every
37
+ * backend, and serves a module of flat per-backend fragments. Per-file rather than project-wide
38
+ * because the import graph is then the truth: a document nothing imports contributes nothing, and a
39
+ * bundler can see which implementations each document actually pulled in.
40
+ *
41
+ * The pipeline is the SDK's own — `parse*Requirements` to read content, the catalog to resolve. This
42
+ * package contributes the Vite lifecycle and the module text, nothing else.
43
+ */
44
+ export declare function createManifestPlugin(options: Readonly<ManifestPluginOptions>): NonEntityCreateResult<ManifestPlugin, 'descriptor'>;
45
+ //# sourceMappingURL=manifestPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifestPlugin.d.ts","sourceRoot":"","sources":["../src/manifestPlugin.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAe,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAUvG,gGAAgG;AAChG,eAAO,MAAM,qBAAqB,cAAc,CAAC;AAEjD,yGAAyG;AACzG,MAAM,WAAW,qBAAqB;IACpC,oGAAoG;IACpG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC/C;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnD;AAED,2GAA2G;AAC3G,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvE,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GACvC,qBAAqB,CAAC,cAAc,EAAE,YAAY,CAAC,CAyErD"}
@@ -0,0 +1,102 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { dirname, extname, isAbsolute, resolve } from 'node:path';
3
+ import { logWarn } from '@flighthq/log/contract';
4
+ import { createRequirementCodegenPlan } from '@flighthq/requirement-codegen/contract';
5
+ import { DEFAULT_CONTENT_ANALYZERS } from './contentAnalyzers';
6
+ import { generateManifestModuleSource, MANIFEST_BACKEND_EXPORTS, MANIFEST_PARSER_BACKEND, } from './manifestModuleSource';
7
+ /** The import suffix that asks this plugin for a file's manifest instead of the file itself. */
8
+ export const MANIFEST_QUERY_SUFFIX = '?manifest';
9
+ /**
10
+ * Creates the plugin. Explicit factory, no default export and no module-level state: importing this
11
+ * package configures nothing.
12
+ *
13
+ * It intercepts a per-file import — `import { glOptions } from './asset.swf?manifest'` — reads THAT
14
+ * file, picks the analyzer by extension, resolves the requirements against the catalog for every
15
+ * backend, and serves a module of flat per-backend fragments. Per-file rather than project-wide
16
+ * because the import graph is then the truth: a document nothing imports contributes nothing, and a
17
+ * bundler can see which implementations each document actually pulled in.
18
+ *
19
+ * The pipeline is the SDK's own — `parse*Requirements` to read content, the catalog to resolve. This
20
+ * package contributes the Vite lifecycle and the module text, nothing else.
21
+ */
22
+ export function createManifestPlugin(options) {
23
+ const report = options.onDiagnostic ?? ((message) => logWarn(message, MANIFEST_LOG_CHANNEL));
24
+ // Keyed by the absolute content path, so invalidation is per imported source: editing one document
25
+ // rebuilds that document's module and leaves every other file's cached module untouched.
26
+ const sourceByPath = new Map();
27
+ async function build(path) {
28
+ const extension = extname(path).toLowerCase();
29
+ const analyze = DEFAULT_CONTENT_ANALYZERS[extension];
30
+ if (analyze === undefined) {
31
+ report(`unsupported content format, no analyzer for ${extension}: ${path}`);
32
+ return generateManifestModuleSource([], extension).source;
33
+ }
34
+ let requirements;
35
+ try {
36
+ requirements = analyze(new Uint8Array(await readFile(path)));
37
+ }
38
+ catch (error) {
39
+ report(`analyzer failed for ${path}: ${error.message}`);
40
+ return generateManifestModuleSource([], extension).source;
41
+ }
42
+ // Resolution is the codegen kernel's job, not this plugin's. Every backend is planned, not a
43
+ // configured one: the module exports a fragment per backend and the application's import decides
44
+ // which survive the bundle. The parser is planned alongside them because parserOptions is one of
45
+ // those exports.
46
+ const rows = [];
47
+ const unresolvedEverywhere = new Map();
48
+ const resolvedSomewhere = new Set();
49
+ for (const backend of MANIFEST_RESOLVED_BACKENDS) {
50
+ const plan = createRequirementCodegenPlan(options.catalog, requirements, backend);
51
+ for (const entry of plan.entries) {
52
+ rows.push({ entry, kind: entry.kind });
53
+ resolvedSomewhere.add(`${entry.facet}\u0000${entry.kind}`);
54
+ }
55
+ for (const requirement of plan.unresolved) {
56
+ unresolvedEverywhere.set(`${requirement.facet}\u0000${requirement.key}`, requirement);
57
+ }
58
+ }
59
+ // Reported only when NO backend could place it. A requirement satisfied by GL but absent from the
60
+ // WGPU catalog is a normal per-backend gap, not a hole in the content's coverage.
61
+ for (const [identity, requirement] of unresolvedEverywhere) {
62
+ if (resolvedSomewhere.has(identity))
63
+ continue;
64
+ report(`no catalog entry for ${requirement.facet} ${requirement.key}: ${path}`);
65
+ }
66
+ const generated = generateManifestModuleSource(rows, extension);
67
+ for (const problem of generated.problems)
68
+ report(`${problem}: ${path}`);
69
+ return generated.source;
70
+ }
71
+ return {
72
+ enforce: 'pre',
73
+ handleHotUpdate: (context) => {
74
+ sourceByPath.delete(context.file);
75
+ },
76
+ load: async (id) => {
77
+ if (!id.startsWith(MANIFEST_RESOLVED_PREFIX))
78
+ return null;
79
+ const path = id.slice(MANIFEST_RESOLVED_PREFIX.length);
80
+ let source = sourceByPath.get(path);
81
+ if (source === undefined) {
82
+ source = await build(path);
83
+ sourceByPath.set(path, source);
84
+ }
85
+ return source;
86
+ },
87
+ name: 'flight-manifest',
88
+ resolveId: (id, importer) => {
89
+ if (!id.endsWith(MANIFEST_QUERY_SUFFIX))
90
+ return null;
91
+ const request = id.slice(0, -MANIFEST_QUERY_SUFFIX.length);
92
+ const base = importer === undefined ? process.cwd() : dirname(importer);
93
+ return `${MANIFEST_RESOLVED_PREFIX}${isAbsolute(request) ? request : resolve(base, request)}`;
94
+ },
95
+ };
96
+ }
97
+ // Rollup treats a leading NUL as "this id belongs to a plugin", which keeps the resolved id out of
98
+ // filesystem resolution while still carrying the path the module was built from.
99
+ const MANIFEST_RESOLVED_PREFIX = '\0flight-manifest:';
100
+ const MANIFEST_LOG_CHANNEL = 'flight-manifest';
101
+ const MANIFEST_RESOLVED_BACKENDS = [...Object.keys(MANIFEST_BACKEND_EXPORTS), MANIFEST_PARSER_BACKEND].sort();
102
+ //# sourceMappingURL=manifestPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifestPlugin.js","sourceRoot":"","sources":["../src/manifestPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The render-state options field that collects each facet's implementations.
3
+ *
4
+ * A catalog row names a facet, a kind and an implementation, but not the options field that holds it —
5
+ * deliberately, because a row is a fact about ownership and should not encode one consumer's option
6
+ * shape. This table is where the plugin decides.
7
+ *
8
+ * `document.format` maps to `nodeRenderers` for a render backend: a document's content kinds are the
9
+ * nodes the importer produces, so that is the field a renderer needs them in.
10
+ */
11
+ export declare const REQUIREMENT_OPTION_FIELDS: Readonly<Record<string, string>>;
12
+ /**
13
+ * The kind-keyed fields each backend's options type ACTUALLY declares, taken from the types package.
14
+ *
15
+ * Backend sets are not interchangeable and the differences are real: `GlRenderStateOptions` has
16
+ * `blendRealizations`, `pbrExtensions` and `customEffectShaders`; `WgpuRenderStateOptions` has NONE of
17
+ * those three. Emitting one into the other would produce a fragment that typechecks nowhere and
18
+ * silently does nothing when spread, so routing is per backend and a row naming a field its backend
19
+ * does not accept is REPORTED rather than emitted.
20
+ *
21
+ * All four backends now take ONE options object, and every set below is derived from the options type
22
+ * that backend actually declares rather than from a guess about which fields it ought to have.
23
+ * `CanvasRenderStateOptions` carries the registries and texture resolvers directly, so a canvas
24
+ * fragment spreads into `createCanvasRenderState(options)` like every other backend's. DOM's registry
25
+ * fields are seeded into the runtime at construction. Neither canvas nor DOM declares
26
+ * `blendRealizations`, and DOM declares no material or effect tables, so a row naming one is reported
27
+ * rather than emitted into a field that does not exist.
28
+ */
29
+ export declare const BACKEND_OPTION_FIELDS: Readonly<Record<string, ReadonlySet<string>>>;
30
+ /** The parser options field each content format spreads its ordered handler list into. */
31
+ export declare const PARSER_HANDLER_FIELDS: Readonly<Record<string, string>>;
32
+ //# sourceMappingURL=requirementOptionFields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirementOptionFields.d.ts","sourceRoot":"","sources":["../src/requirementOptionFields.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQrE,CAAC;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CA+B9E,CAAC;AAEH,0FAA0F;AAC1F,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIjE,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { RequirementFacet } from '@flighthq/types/contract';
2
+ /**
3
+ * The render-state options field that collects each facet's implementations.
4
+ *
5
+ * A catalog row names a facet, a kind and an implementation, but not the options field that holds it —
6
+ * deliberately, because a row is a fact about ownership and should not encode one consumer's option
7
+ * shape. This table is where the plugin decides.
8
+ *
9
+ * `document.format` maps to `nodeRenderers` for a render backend: a document's content kinds are the
10
+ * nodes the importer produces, so that is the field a renderer needs them in.
11
+ */
12
+ export const REQUIREMENT_OPTION_FIELDS = Object.freeze({
13
+ [RequirementFacet.DocumentFormat]: 'nodeRenderers',
14
+ [RequirementFacet.SceneBlendMode]: 'blendRealizations',
15
+ [RequirementFacet.SceneMaterialKind]: 'materialRenderers',
16
+ [RequirementFacet.SceneModifierKind]: 'modifierSnippets',
17
+ [RequirementFacet.SceneNodeKind]: 'nodeRenderers',
18
+ [RequirementFacet.SceneShapeCommand]: 'canvasShapeCommands',
19
+ [RequirementFacet.SceneTextureSourceKind]: 'textureResolvers',
20
+ });
21
+ /**
22
+ * The kind-keyed fields each backend's options type ACTUALLY declares, taken from the types package.
23
+ *
24
+ * Backend sets are not interchangeable and the differences are real: `GlRenderStateOptions` has
25
+ * `blendRealizations`, `pbrExtensions` and `customEffectShaders`; `WgpuRenderStateOptions` has NONE of
26
+ * those three. Emitting one into the other would produce a fragment that typechecks nowhere and
27
+ * silently does nothing when spread, so routing is per backend and a row naming a field its backend
28
+ * does not accept is REPORTED rather than emitted.
29
+ *
30
+ * All four backends now take ONE options object, and every set below is derived from the options type
31
+ * that backend actually declares rather than from a guess about which fields it ought to have.
32
+ * `CanvasRenderStateOptions` carries the registries and texture resolvers directly, so a canvas
33
+ * fragment spreads into `createCanvasRenderState(options)` like every other backend's. DOM's registry
34
+ * fields are seeded into the runtime at construction. Neither canvas nor DOM declares
35
+ * `blendRealizations`, and DOM declares no material or effect tables, so a row naming one is reported
36
+ * rather than emitted into a field that does not exist.
37
+ */
38
+ export const BACKEND_OPTION_FIELDS = Object.freeze({
39
+ // Derived from the landed CanvasRenderStateOptions: it extends RenderStateOptions and
40
+ // CanvasRenderOptions and adds effects and materialRenderers, so these are its kind-keyed fields.
41
+ canvas: new Set(['canvasShapeCommands', 'effectPaddingResolvers', 'effects', 'materialRenderers', 'nodeRenderers']),
42
+ // D3: DomRenderOptions declares registry fields, seeded into the runtime at construction.
43
+ dom: new Set(['canvasShapeCommands', 'effectPaddingResolvers', 'nodeRenderers', 'textureResolvers']),
44
+ gl: new Set([
45
+ 'blendRealizations',
46
+ 'canvasShapeCommands',
47
+ 'customEffectShaders',
48
+ 'customMaterialShaders',
49
+ 'effectPaddingResolvers',
50
+ 'effects',
51
+ 'materialRenderers',
52
+ 'modifierSnippets',
53
+ 'nodeRenderers',
54
+ 'pbrExtensions',
55
+ 'textureResolvers',
56
+ 'velocityWriters',
57
+ ]),
58
+ wgpu: new Set([
59
+ 'canvasShapeCommands',
60
+ 'customMaterialShaders',
61
+ 'effectPaddingResolvers',
62
+ 'effects',
63
+ 'materialRenderers',
64
+ 'modifierSnippets',
65
+ 'nodeRenderers',
66
+ 'textureResolvers',
67
+ 'velocityWriters',
68
+ ]),
69
+ });
70
+ /** The parser options field each content format spreads its ordered handler list into. */
71
+ export const PARSER_HANDLER_FIELDS = Object.freeze({
72
+ '.awd': 'blocks',
73
+ '.awd2': 'blocks',
74
+ '.swf': 'tags',
75
+ });
76
+ //# sourceMappingURL=requirementOptionFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirementOptionFields.js","sourceRoot":"","sources":["../src/requirementOptionFields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAqC,MAAM,CAAC,MAAM,CAAC;IACvF,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAAE,eAAe;IAClD,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAAE,mBAAmB;IACtD,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,mBAAmB;IACzD,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,kBAAkB;IACxD,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,eAAe;IACjD,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,qBAAqB;IAC3D,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,EAAE,kBAAkB;CAC9D,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAkD,MAAM,CAAC,MAAM,CAAC;IAChG,sFAAsF;IACtF,kGAAkG;IAClG,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,SAAS,EAAE,mBAAmB,EAAE,eAAe,CAAC,CAAC;IACnH,0FAA0F;IAC1F,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,eAAe,EAAE,kBAAkB,CAAC,CAAC;IACpG,EAAE,EAAE,IAAI,GAAG,CAAC;QACV,mBAAmB;QACnB,qBAAqB;QACrB,qBAAqB;QACrB,uBAAuB;QACvB,wBAAwB;QACxB,SAAS;QACT,mBAAmB;QACnB,kBAAkB;QAClB,eAAe;QACf,eAAe;QACf,kBAAkB;QAClB,iBAAiB;KAClB,CAAC;IACF,IAAI,EAAE,IAAI,GAAG,CAAC;QACZ,qBAAqB;QACrB,uBAAuB;QACvB,wBAAwB;QACxB,SAAS;QACT,mBAAmB;QACnB,kBAAkB;QAClB,eAAe;QACf,kBAAkB;QAClB,iBAAiB;KAClB,CAAC;CACH,CAAC,CAAC;AAEH,0FAA0F;AAC1F,MAAM,CAAC,MAAM,qBAAqB,GAAqC,MAAM,CAAC,MAAM,CAAC;IACnF,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,MAAM;CACf,CAAC,CAAC"}