@animus-ui/vite-plugin 0.1.3 → 0.1.5

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
@@ -50,9 +50,9 @@ import { createAppearanceBootstrap } from '@animus-ui/system/bootstrap';
50
50
  import { animusExtract } from '@animus-ui/vite-plugin';
51
51
  import { defineConfig } from 'vite';
52
52
 
53
- import { tokens } from './src/ds';
53
+ import { theme } from './src/ds';
54
54
 
55
- const appearanceBootstrap = createAppearanceBootstrap(tokens);
55
+ const appearanceBootstrap = createAppearanceBootstrap(theme);
56
56
 
57
57
  export default defineConfig({
58
58
  plugins: [animusExtract({ system: './src/ds.ts', appearanceBootstrap })],
@@ -3,7 +3,9 @@ import type { PluginContext } from './context';
3
3
  * buildStart: load the system, discover and ingest sources (local +
4
4
  * external packages), run whole-project analysis, and log the report.
5
5
  * `resolveSpecifier` is the bundler seam — Vite's `this.resolve` mapped to
6
- * an absolute id.
6
+ * an absolute id. `emitAsset` (build mode only) is Rollup's `this.emitFile`
7
+ * for `asset()` placeholder substitution; absent in dev, where resolved
8
+ * files are served via base + `/@fs/` instead.
7
9
  */
8
- export declare function runBuildStart(ctx: PluginContext, resolveSpecifier: (specifier: string) => Promise<string | null>): Promise<void>;
10
+ export declare function runBuildStart(ctx: PluginContext, resolveSpecifier: (specifier: string) => Promise<string | null>, emitAsset?: (fileName: string, source: Uint8Array) => string): Promise<void>;
9
11
  //# sourceMappingURL=build-start.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-start.d.ts","sourceRoot":"","sources":["../src/build-start.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAC9D,OAAO,CAAC,IAAI,CAAC,CAsNf"}
1
+ {"version":3,"file":"build-start.d.ts","sourceRoot":"","sources":["../src/build-start.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,EAC/D,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,MAAM,GAC3D,OAAO,CAAC,IAAI,CAAC,CAkRf"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,cAAc,GACrB,IAAI,CAqDN"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,cAAc,GACrB,IAAI,CAwDN"}
@@ -1,9 +1,31 @@
1
+ /**
2
+ * The namespace every virtual module this plugin owns lives under. Exported so
3
+ * the `transform` guard that keeps those modules out of source-file handling
4
+ * matches on the same string the ids are built from — a rename of the
5
+ * namespace cannot leave the guard behind.
6
+ */
7
+ export declare const VIRTUAL_PREFIX = "virtual:animus/";
1
8
  export declare const VIRTUAL_CSS_ID = "virtual:animus/styles.css";
2
9
  export declare const RESOLVED_CSS_ID = "\0virtual:animus/styles.css";
3
10
  export declare const VIRTUAL_COMPONENTS_ID = "virtual:animus/components.js";
4
11
  export declare const RESOLVED_COMPONENTS_ID = "\0virtual:animus/components.js";
5
12
  export declare const VIRTUAL_BRIDGE_ID = "virtual:animus/hmr-bridge.js";
6
13
  export declare const RESOLVED_BRIDGE_ID = "\0virtual:animus/hmr-bridge.js";
14
+ /**
15
+ * Browser-addressable URL for the bridge, used as the `src` of the dev
16
+ * `<script type="module">` (see index-html.ts). THE explanation of the `/@id/`
17
+ * convention lives here; everything else points at it.
18
+ *
19
+ * Vite reserves `/@id/` for module ids that are not file paths. Its transform
20
+ * middleware normalizes such a URL before serving it (`unwrapId`): strip the
21
+ * prefix, then decode the `__x00__` placeholder back to a NUL byte. The
22
+ * UNPREFIXED specifier is what travels here — `resolveVirtualId` is the hook
23
+ * that answers it, and it answers with the `\0` form. (Vite's own `wrapId`
24
+ * encodes an already-`\0`-prefixed id as `__x00__`; that form resolves too, but
25
+ * it leans on the placeholder convention rather than on this plugin's own
26
+ * `resolveId` contract.)
27
+ */
28
+ export declare const BRIDGE_SCRIPT_SRC = "/@id/virtual:animus/hmr-bridge.js";
7
29
  export declare const VIRTUAL_SYSTEM_PROPS_ID = "virtual:animus/system-props";
8
30
  export declare const RESOLVED_SYSTEM_PROPS_ID = "\0virtual:animus/system-props";
9
31
  export declare const DEFAULT_EXCLUDE: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,8BAA8B,CAAC;AAC1D,eAAO,MAAM,eAAe,gCAAgC,CAAC;AAE7D,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AACpE,eAAO,MAAM,sBAAsB,mCAAmC,CAAC;AAEvE,eAAO,MAAM,iBAAiB,iCAAiC,CAAC;AAChE,eAAO,MAAM,kBAAkB,mCAAmC,CAAC;AAEnE,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AACrE,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AAExE,eAAO,MAAM,eAAe,UAA+C,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,eAAO,MAAM,cAAc,8BAAgC,CAAC;AAC5D,eAAO,MAAM,eAAe,gCAAwB,CAAC;AAErD,eAAO,MAAM,qBAAqB,iCAAmC,CAAC;AACtE,eAAO,MAAM,sBAAsB,mCAA+B,CAAC;AAEnE,eAAO,MAAM,iBAAiB,iCAAmC,CAAC;AAClE,eAAO,MAAM,kBAAkB,mCAA2B,CAAC;AAE3D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,sCAA8B,CAAC;AAE7D,eAAO,MAAM,uBAAuB,gCAAkC,CAAC;AACvE,eAAO,MAAM,wBAAwB,kCAAiC,CAAC;AAEvE,eAAO,MAAM,eAAe,UAA+C,CAAC"}
package/dist/context.d.ts CHANGED
@@ -33,6 +33,45 @@ export declare function buildFileEntriesFromCache(cache: Map<string, {
33
33
  source: string;
34
34
  hash: string;
35
35
  }>;
36
+ /**
37
+ * The exact source `virtual:animus/system-props` serves for the current state.
38
+ * One definition, so the served bytes and the change decision below can never
39
+ * be computed from different inputs.
40
+ *
41
+ * A real context carries the module already generated (`systemPropsModuleMemo`,
42
+ * refreshed wherever the four inputs move), so serving it and deciding whether
43
+ * it changed are both reads. Contexts that publish those inputs by hand — the
44
+ * behavioral test doubles — carry no memo and generate here instead.
45
+ */
46
+ export declare function systemPropsModuleSource(ctx: PluginContext): string;
47
+ /**
48
+ * Run project analysis and report whether the served system-props module
49
+ * CHANGED.
50
+ *
51
+ * The module is imported by every module that renders a system prop, so
52
+ * re-delivering it pushes an update through all of them; every analysis
53
+ * republishes its inputs whether or not they moved, so a new analysis is not
54
+ * itself an admissible trigger (openspec: vite-extraction-plugin, "System prop
55
+ * map HMR invalidation").
56
+ *
57
+ * The comparison is over the GENERATED MODULE, not over the prop map alone.
58
+ * The map is one of four inputs, and they move independently: widening a
59
+ * component's `.system({ ... })` opt-in adds a `dynamicPropConfig` entry while
60
+ * minting no new utility class, so a map-only comparison reports "unchanged"
61
+ * and the client is left with a config missing the new prop — permanently,
62
+ * since Vite keeps serving the module's cached transform result across full
63
+ * page reloads. Comparing the artifact itself needs no argument about which
64
+ * inputs are volatile this month.
65
+ *
66
+ * A free function rather than a method: the comparison must run for real
67
+ * against any context the caller holds, including the behavioral test doubles
68
+ * that stand in for the engine.
69
+ */
70
+ export declare function runAnalysisTrackingSystemProps(ctx: PluginContext, fileEntries: Array<{
71
+ path: string;
72
+ source: string;
73
+ hash?: string;
74
+ }>): boolean;
36
75
  /**
37
76
  * Drop a deleted (or renamed-away) file from the dev file cache so its
38
77
  * last-known source stops riding along as a ghost entry on every later
@@ -84,17 +123,23 @@ export declare class PluginContext {
84
123
  storedSystemPropMapJson: string;
85
124
  storedDynamicPropsJson: string;
86
125
  storedTransformsSource: string;
126
+ systemPropsModuleMemo: string | null;
87
127
  fileCache: Map<string, {
88
128
  hash: string;
89
129
  source: string;
90
130
  }>;
91
131
  readonly hotUpdateEvents: HotUpdateEvents;
92
132
  packageMap: Record<string, string>;
133
+ base: string;
134
+ assetUrlBySpecifier: Map<string, string>;
135
+ assetResolutionFailures: Set<string>;
136
+ assetPassComplete: boolean;
93
137
  externalPackageDirs: string[];
138
+ externalDirOwners: Record<string, string>;
139
+ externalFileOwners: Record<string, string>;
94
140
  externalSourceEntries: Map<string, string>;
95
141
  externalPackageOutcomes: ExternalPackageOutcome[];
96
142
  devServer: any;
97
- bridgeInjected: boolean;
98
143
  resolvedSystemPath: string | null;
99
144
  systemDependencyKeys: Set<string>;
100
145
  systemDependencyPaths: string[];
@@ -103,8 +148,15 @@ export declare class PluginContext {
103
148
  private v2DriftWarned;
104
149
  /** Single engine choke-point for every native extraction call. */
105
150
  readonly engineApi: () => any;
106
- constructor(options: AnimusExtractOptions);
151
+ constructor(options: AnimusExtractOptions, engineApiOverride?: () => any);
107
152
  log(msg: string): void;
153
+ /**
154
+ * Standard-level information — emitted whether or not `verbose` is on.
155
+ * Reserved for events a developer must see without opting in, e.g. a file
156
+ * created after buildStart being folded into the analysis (openspec:
157
+ * hmr-new-file-detection, "New file detection logging").
158
+ */
159
+ info(msg: string): void;
108
160
  warn(msg: string): void;
109
161
  logTimingWaterfall(timing: Record<string, number>): void;
110
162
  /**
@@ -122,6 +174,24 @@ export declare class PluginContext {
122
174
  source: string;
123
175
  hash?: string;
124
176
  }>): void;
177
+ /** Base-prefixed dev URL for an absolute file (Vite mounts /@fs under base). */
178
+ devFsUrl(absPath: string): string;
179
+ /**
180
+ * The shared unresolvable-asset policy: fail the build under `strict`,
181
+ * else warn and record the identity mapping so the specifier emits
182
+ * literally.
183
+ */
184
+ assetFallback(specifier: string, message: string, cause?: unknown): void;
185
+ /**
186
+ * The one asset-substitution pass per analysis. In dev, a specifier not
187
+ * already mapped by buildStart's bundler-resolved pass (a geological
188
+ * reset regenerates globalCss from an edited system, which may reference
189
+ * NEW assets) is resolved Node-side first — host aliases, then Node,
190
+ * then package root; bundler-only resolutions can differ, since the
191
+ * plugin hook context is unavailable on this path. Strict semantics
192
+ * match buildStart.
193
+ */
194
+ private applyAssetSubstitutions;
125
195
  private resetCoalescer;
126
196
  /**
127
197
  * Schedule a geological reset through the burst coalescer. N dependency
@@ -129,6 +199,15 @@ export declare class PluginContext {
129
199
  * running reset produce exactly one follow-up.
130
200
  */
131
201
  requestGeologicalReset(trigger: string): void;
202
+ /**
203
+ * A failed reset must surface without killing the server: the coalescer
204
+ * fires from a bare timer, OUTSIDE Vite's handleHMRUpdate catch, so a
205
+ * strict-mode throw (asset resolution, token contracts, system load)
206
+ * would otherwise be an unhandled exception that exits the process.
207
+ * Strict-in-dev means the error overlay, matching the transform/HMR
208
+ * strict paths that Vite itself catches.
209
+ */
210
+ private geologicalResetFailed;
132
211
  /**
133
212
  * The geological reset: reload the system (refreshing the dependency
134
213
  * set), clear the Rust per-file cache, re-analyze everything with full
@@ -164,6 +243,13 @@ export declare class PluginContext {
164
243
  * `getModuleById` searches the client AND ssr environment graphs and its
165
244
  * `invalidateModule` invalidates both instances behind the returned node,
166
245
  * which is exactly the reach this path wants. It stays the seam here.
246
+ *
247
+ * Both modules are invalidated unconditionally, and deliberately so: the
248
+ * appearance or disappearance of a whole component file is not the
249
+ * steady-state edit the change-gated path governs, and a client reload does
250
+ * NOT rescue a module that was never invalidated — Vite keeps serving its
251
+ * cached transform result across reloads (openspec: hmr-new-file-detection,
252
+ * "CSS invalidation after new file analysis").
167
253
  */
168
254
  invalidateExtractedModules(): void;
169
255
  /**
@@ -171,9 +257,21 @@ export declare class PluginContext {
171
257
  * (external-package-file-discovery: silence is never an outcome). An
172
258
  * unresolvable `.includes()` specifier warns in non-strict mode and FAILS
173
259
  * the build under `strict: true`, naming every offending specifier —
174
- * a typo'd include must not ship a build missing its component CSS.
260
+ * a typo'd include must not ship a build missing its component CSS. A
261
+ * stale dist entry under an extended package (first-class-extension D13)
262
+ * rides the same seam: a merge against it would silently skew registry
263
+ * content the discovered sources no longer match.
175
264
  */
176
265
  enforceIncludeResolution(): void;
266
+ /**
267
+ * The post-analysis gate over cross-source token contracts
268
+ * (extraction-diagnostics): a discovered component referencing a token its
269
+ * OWN package defines but the consumer theme does not gets the teaching
270
+ * error naming the token, component, source package, and the missing
271
+ * `createTheme().extend(...)`. Wiring and severity routing live in the
272
+ * shared pipeline gate (next-plugin parity by construction).
273
+ */
274
+ enforceExternalTokenContracts(): void;
177
275
  runSelfVerify(): void;
178
276
  }
179
277
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/hmr.d.ts CHANGED
@@ -19,5 +19,5 @@ import type { DevEnvironment, EnvironmentModuleNode, HotUpdateOptions } from 'vi
19
19
  * graph, so system dependencies registered through `watcher.add` outside the
20
20
  * root still reach the reset branch, with an empty `modules` list.
21
21
  */
22
- export declare function handleHotUpdate(ctx: PluginContext, environment: DevEnvironment, { type, file, timestamp, modules }: HotUpdateOptions): Promise<EnvironmentModuleNode[] | void>;
22
+ export declare function handleHotUpdate(ctx: PluginContext, environment: DevEnvironment, { type, file, timestamp, modules, read }: HotUpdateOptions): Promise<EnvironmentModuleNode[] | void>;
23
23
  //# sourceMappingURL=hmr.d.ts.map
package/dist/hmr.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,MAAM,CAAC;AAEd;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,WAAW,EAAE,cAAc,EAC3B,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,gBAAgB,GACnD,OAAO,CAAC,qBAAqB,EAAE,GAAG,IAAI,CAAC,CAgEzC"}
1
+ {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,MAAM,CAAC;AAEd;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,WAAW,EAAE,cAAc,EAC3B,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,gBAAgB,GACzD,OAAO,CAAC,qBAAqB,EAAE,GAAG,IAAI,CAAC,CAmEzC"}
@@ -9,7 +9,10 @@
9
9
  * - `analyzed` — re-analysis ran; every environment invalidates the affected
10
10
  * modules in its own graph. `staleDefinitionFiles` are rootDir-relative
11
11
  * definition files whose component replacement changed (the changed file
12
- * itself is never listed).
12
+ * itself is never listed). `systemPropsChanged` reports whether the served
13
+ * system-props module moved (see `runAnalysisTrackingSystemProps` in
14
+ * context.ts) — only the owning dispatch holds the before/after values, so
15
+ * it travels with the decision rather than being re-derived per environment.
13
16
  */
14
17
  export type HotUpdateResult = {
15
18
  kind: 'ignored';
@@ -18,6 +21,7 @@ export type HotUpdateResult = {
18
21
  } | {
19
22
  kind: 'analyzed';
20
23
  staleDefinitionFiles: string[];
24
+ systemPropsChanged: boolean;
21
25
  };
22
26
  /**
23
27
  * Once-per-file-event coordination across the `hotUpdate` dispatches.
@@ -1 +1 @@
1
- {"version":3,"file":"hot-update-events.d.ts","sourceRoot":"","sources":["../src/hot-update-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,oBAAoB,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAe;IAGd,OAAO,CAAC,QAAQ,CAAC,YAAY;IAFzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;IAE9D,YAA6B,YAAY,SAAK,EAAI;IAElD,0EAA0E;IAC1E,KAAK,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAUvE;IAED,wEAAwE;IACxE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAErE;IAED,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CAEzD;CACF"}
1
+ {"version":3,"file":"hot-update-events.d.ts","sourceRoot":"","sources":["../src/hot-update-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEN;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAe;IAGd,OAAO,CAAC,QAAQ,CAAC,YAAY;IAFzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;IAE9D,YAA6B,YAAY,SAAK,EAAI;IAElD,0EAA0E;IAC1E,KAAK,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAUvE;IAED,wEAAwE;IACxE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAErE;IAED,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CAEzD;CACF"}
@@ -3,16 +3,18 @@ import type { HtmlTagDescriptor } from 'vite';
3
3
  /**
4
4
  * transformIndexHtml: build the head-prepend tag set.
5
5
  *
6
- * Two independent tags, both delivery-only:
6
+ * Three independent tags, all delivery-only:
7
7
  * - the appearance bootstrap script, when the host build passed a
8
8
  * pre-generated artifact via `appearanceBootstrap` (absent otherwise);
9
- * - the `@layer` declaration style, when `buildStart` computed one.
9
+ * - the `@layer` declaration style, when `buildStart` computed one;
10
+ * - the HMR bridge module script, in dev only.
10
11
  *
11
- * Both branches are guarded on non-empty CONTENT, not on mere presence: an
12
- * artifact whose `code` is empty is a caller defect, and emitting
12
+ * The two build-time branches are guarded on non-empty CONTENT, not on mere
13
+ * presence: an artifact whose `code` is empty is a caller defect, and emitting
13
14
  * `<script data-animus-bootstrap></script>` for it would break the
14
15
  * unconfigured-parity contract in spirit (a tag that does nothing) while
15
- * hiding the defect. Symmetric with `layerDeclaration`.
16
+ * hiding the defect. Symmetric with `layerDeclaration`. The bridge has no
17
+ * content of its own — it is a `src` reference — so its only guard is the mode.
16
18
  *
17
19
  * Ordering: every descriptor rides the same `head-prepend` bucket, which Vite
18
20
  * serializes in array order (`serializeTags`) and splices in immediately after
@@ -20,8 +22,8 @@ import type { HtmlTagDescriptor } from 'vite';
20
22
  * before the layer declaration and — since built stylesheet links are appended
21
23
  * at `</head>` — before any stylesheet reference.
22
24
  *
23
- * When neither input is set the array is empty, so an unconfigured build emits
24
- * no tag, attribute, or whitespace of its own.
25
+ * With neither build-time input set, a production build emits no tag,
26
+ * attribute, or whitespace of its own.
25
27
  */
26
28
  export declare function buildIndexHtmlTags(ctx: PluginContext): HtmlTagDescriptor[];
27
29
  //# sourceMappingURL=index-html.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-html.d.ts","sourceRoot":"","sources":["../src/index-html.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,iBAAiB,EAAE,CAuB1E"}
1
+ {"version":3,"file":"index-html.d.ts","sourceRoot":"","sources":["../src/index-html.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,iBAAiB,EAAE,CAyD1E"}
package/dist/index.cjs CHANGED
@@ -7,13 +7,36 @@ let fs = require("fs");
7
7
  let path = require("path");
8
8
  let crypto = require("crypto");
9
9
  //#region src/constants.ts
10
- const VIRTUAL_CSS_ID = "virtual:animus/styles.css";
11
- const RESOLVED_CSS_ID = "\0virtual:animus/styles.css";
12
- const VIRTUAL_COMPONENTS_ID = "virtual:animus/components.js";
13
- const RESOLVED_COMPONENTS_ID = "\0virtual:animus/components.js";
14
- const VIRTUAL_BRIDGE_ID = "virtual:animus/hmr-bridge.js";
15
- const RESOLVED_BRIDGE_ID = "\0virtual:animus/hmr-bridge.js";
16
- const RESOLVED_SYSTEM_PROPS_ID = "\0virtual:animus/system-props";
10
+ /**
11
+ * The namespace every virtual module this plugin owns lives under. Exported so
12
+ * the `transform` guard that keeps those modules out of source-file handling
13
+ * matches on the same string the ids are built from — a rename of the
14
+ * namespace cannot leave the guard behind.
15
+ */
16
+ const VIRTUAL_PREFIX = "virtual:animus/";
17
+ const VIRTUAL_CSS_ID = `${VIRTUAL_PREFIX}styles.css`;
18
+ const RESOLVED_CSS_ID = `\0${VIRTUAL_CSS_ID}`;
19
+ const VIRTUAL_COMPONENTS_ID = `${VIRTUAL_PREFIX}components.js`;
20
+ const RESOLVED_COMPONENTS_ID = `\0${VIRTUAL_COMPONENTS_ID}`;
21
+ const VIRTUAL_BRIDGE_ID = `${VIRTUAL_PREFIX}hmr-bridge.js`;
22
+ const RESOLVED_BRIDGE_ID = `\0${VIRTUAL_BRIDGE_ID}`;
23
+ /**
24
+ * Browser-addressable URL for the bridge, used as the `src` of the dev
25
+ * `<script type="module">` (see index-html.ts). THE explanation of the `/@id/`
26
+ * convention lives here; everything else points at it.
27
+ *
28
+ * Vite reserves `/@id/` for module ids that are not file paths. Its transform
29
+ * middleware normalizes such a URL before serving it (`unwrapId`): strip the
30
+ * prefix, then decode the `__x00__` placeholder back to a NUL byte. The
31
+ * UNPREFIXED specifier is what travels here — `resolveVirtualId` is the hook
32
+ * that answers it, and it answers with the `\0` form. (Vite's own `wrapId`
33
+ * encodes an already-`\0`-prefixed id as `__x00__`; that form resolves too, but
34
+ * it leans on the placeholder convention rather than on this plugin's own
35
+ * `resolveId` contract.)
36
+ */
37
+ const BRIDGE_SCRIPT_SRC = `/@id/${VIRTUAL_BRIDGE_ID}`;
38
+ const VIRTUAL_SYSTEM_PROPS_ID = `${VIRTUAL_PREFIX}system-props`;
39
+ const RESOLVED_SYSTEM_PROPS_ID = `\0${VIRTUAL_SYSTEM_PROPS_ID}`;
17
40
  const DEFAULT_EXCLUDE = [
18
41
  "node_modules",
19
42
  "dist",
@@ -26,10 +49,15 @@ const DEFAULT_EXCLUDE = [
26
49
  * buildStart: load the system, discover and ingest sources (local +
27
50
  * external packages), run whole-project analysis, and log the report.
28
51
  * `resolveSpecifier` is the bundler seam — Vite's `this.resolve` mapped to
29
- * an absolute id.
52
+ * an absolute id. `emitAsset` (build mode only) is Rollup's `this.emitFile`
53
+ * for `asset()` placeholder substitution; absent in dev, where resolved
54
+ * files are served via base + `/@fs/` instead.
30
55
  */
31
- async function runBuildStart(ctx, resolveSpecifier) {
56
+ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
32
57
  (0, _animus_ui_extract_pipeline.clearEngineCache)(ctx.engineApi);
58
+ ctx.assetPassComplete = false;
59
+ ctx.assetUrlBySpecifier.clear();
60
+ ctx.assetResolutionFailures.clear();
33
61
  let t0 = performance.now();
34
62
  ctx.loadSystem();
35
63
  if (ctx.options.layers) {
@@ -106,6 +134,8 @@ async function runBuildStart(ctx, resolveSpecifier) {
106
134
  });
107
135
  ctx.packageMap = collected.packageMap;
108
136
  ctx.externalPackageOutcomes = collected.outcomes;
137
+ ctx.externalDirOwners = collected.dirOwners;
138
+ ctx.externalFileOwners = collected.fileOwners;
109
139
  ctx.enforceIncludeResolution();
110
140
  for (const [specifier, srcEntry] of collected.sourceEntries) ctx.externalSourceEntries.set(specifier, srcEntry);
111
141
  for (const entry of collected.entries) {
@@ -126,6 +156,23 @@ async function runBuildStart(ctx, resolveSpecifier) {
126
156
  ctx.log(`Discovered ${fileEntries.length} files (${packageFileCount} from packages) (${Math.round(performance.now() - t0)}ms)`);
127
157
  t0 = performance.now();
128
158
  ctx.runAnalysis(fileEntries);
159
+ const assetSpecifiers = (0, _animus_ui_extract_pipeline.findAssetSpecifiers)(ctx.globalCss);
160
+ for (const specifier of assetSpecifiers) {
161
+ const resolvedPath = await resolveSpecifier(specifier);
162
+ if (!resolvedPath) {
163
+ ctx.assetFallback(specifier, `[animus-extract] unresolvable asset() specifier: ${specifier}`);
164
+ continue;
165
+ }
166
+ if (emitAsset) try {
167
+ const referenceId = emitAsset((0, path.basename)(resolvedPath), (0, fs.readFileSync)(resolvedPath));
168
+ ctx.assetUrlBySpecifier.set(specifier, `__VITE_ASSET__${referenceId}__`);
169
+ } catch (err) {
170
+ ctx.assetFallback(specifier, `[animus-extract] failed to emit asset() specifier ${specifier}: ${String(err)}`, err);
171
+ }
172
+ else ctx.assetUrlBySpecifier.set(specifier, ctx.devFsUrl(resolvedPath));
173
+ }
174
+ ctx.globalCss = (0, _animus_ui_extract_pipeline.substituteAssetPlaceholders)(ctx.globalCss, ctx.assetUrlBySpecifier);
175
+ ctx.assetPassComplete = true;
129
176
  if (ctx.storedManifest) {
130
177
  const report = ctx.storedManifest.report;
131
178
  if (report) {
@@ -169,6 +216,7 @@ function applyResolvedConfig(ctx, config) {
169
216
  ctx.isProd = config.command === "build";
170
217
  ctx.rootDir = config.root;
171
218
  ctx.logger = config.logger;
219
+ ctx.base = config.base ?? "/";
172
220
  ctx.lcssTargets = (0, _animus_ui_extract_pipeline.resolveLightningTargets)(ctx.options.targets, ctx.rootDir);
173
221
  ctx.log(`Lightning CSS targets resolved (${Object.keys(ctx.lcssTargets).length} browsers)`);
174
222
  const rawAlias = config.resolve?.alias;
@@ -261,8 +309,9 @@ var ResetCoalescer = class {
261
309
  timer = null;
262
310
  running = false;
263
311
  dirty = false;
264
- constructor(run, quietMs = 60, schedule = (fn, ms) => setTimeout(fn, ms), cancel = (timer) => clearTimeout(timer)) {
312
+ constructor(run, onError, quietMs = 60, schedule = (fn, ms) => setTimeout(fn, ms), cancel = (timer) => clearTimeout(timer)) {
265
313
  this.run = run;
314
+ this.onError = onError;
266
315
  this.quietMs = quietMs;
267
316
  this.schedule = schedule;
268
317
  this.cancel = cancel;
@@ -279,6 +328,8 @@ var ResetCoalescer = class {
279
328
  this.running = true;
280
329
  try {
281
330
  this.run();
331
+ } catch (err) {
332
+ this.onError(err);
282
333
  } finally {
283
334
  this.running = false;
284
335
  if (this.dirty) {
@@ -321,6 +372,56 @@ function buildFileEntriesFromCache(cache, changedPath) {
321
372
  });
322
373
  return entries;
323
374
  }
375
+ /** Generate the module from the four inputs the context currently holds. */
376
+ function generateSystemPropsModule(ctx) {
377
+ return (0, _animus_ui_extract_pipeline.buildSystemPropsModule)({
378
+ systemPropMapJson: ctx.storedSystemPropMapJson,
379
+ groupRegistryJson: ctx.system.groupRegistryJson,
380
+ dynamicProps: JSON.parse(ctx.storedDynamicPropsJson),
381
+ transformsSource: ctx.storedTransformsSource
382
+ });
383
+ }
384
+ /**
385
+ * The exact source `virtual:animus/system-props` serves for the current state.
386
+ * One definition, so the served bytes and the change decision below can never
387
+ * be computed from different inputs.
388
+ *
389
+ * A real context carries the module already generated (`systemPropsModuleMemo`,
390
+ * refreshed wherever the four inputs move), so serving it and deciding whether
391
+ * it changed are both reads. Contexts that publish those inputs by hand — the
392
+ * behavioral test doubles — carry no memo and generate here instead.
393
+ */
394
+ function systemPropsModuleSource(ctx) {
395
+ return ctx.systemPropsModuleMemo ??= generateSystemPropsModule(ctx);
396
+ }
397
+ /**
398
+ * Run project analysis and report whether the served system-props module
399
+ * CHANGED.
400
+ *
401
+ * The module is imported by every module that renders a system prop, so
402
+ * re-delivering it pushes an update through all of them; every analysis
403
+ * republishes its inputs whether or not they moved, so a new analysis is not
404
+ * itself an admissible trigger (openspec: vite-extraction-plugin, "System prop
405
+ * map HMR invalidation").
406
+ *
407
+ * The comparison is over the GENERATED MODULE, not over the prop map alone.
408
+ * The map is one of four inputs, and they move independently: widening a
409
+ * component's `.system({ ... })` opt-in adds a `dynamicPropConfig` entry while
410
+ * minting no new utility class, so a map-only comparison reports "unchanged"
411
+ * and the client is left with a config missing the new prop — permanently,
412
+ * since Vite keeps serving the module's cached transform result across full
413
+ * page reloads. Comparing the artifact itself needs no argument about which
414
+ * inputs are volatile this month.
415
+ *
416
+ * A free function rather than a method: the comparison must run for real
417
+ * against any context the caller holds, including the behavioral test doubles
418
+ * that stand in for the engine.
419
+ */
420
+ function runAnalysisTrackingSystemProps(ctx, fileEntries) {
421
+ const before = systemPropsModuleSource(ctx);
422
+ ctx.runAnalysis(fileEntries);
423
+ return systemPropsModuleSource(ctx) !== before;
424
+ }
324
425
  /**
325
426
  * Drop a deleted (or renamed-away) file from the dev file cache so its
326
427
  * last-known source stops riding along as a ghost entry on every later
@@ -367,14 +468,20 @@ var PluginContext = class {
367
468
  storedSystemPropMapJson = "{}";
368
469
  storedDynamicPropsJson = "{}";
369
470
  storedTransformsSource = "{}";
471
+ systemPropsModuleMemo = null;
370
472
  fileCache = /* @__PURE__ */ new Map();
371
473
  hotUpdateEvents = new HotUpdateEvents();
372
474
  packageMap = {};
475
+ base = "/";
476
+ assetUrlBySpecifier = /* @__PURE__ */ new Map();
477
+ assetResolutionFailures = /* @__PURE__ */ new Set();
478
+ assetPassComplete = false;
373
479
  externalPackageDirs = [];
480
+ externalDirOwners = {};
481
+ externalFileOwners = {};
374
482
  externalSourceEntries = /* @__PURE__ */ new Map();
375
483
  externalPackageOutcomes = [];
376
484
  devServer;
377
- bridgeInjected = false;
378
485
  resolvedSystemPath = null;
379
486
  systemDependencyKeys = /* @__PURE__ */ new Set();
380
487
  systemDependencyPaths = [];
@@ -383,11 +490,15 @@ var PluginContext = class {
383
490
  v2DriftWarned = false;
384
491
  /** Single engine choke-point for every native extraction call. */
385
492
  engineApi;
386
- constructor(options) {
493
+ constructor(options, engineApiOverride) {
387
494
  this.options = options;
388
495
  this.staticCssJson = (0, _animus_ui_extract_pipeline.serializeStaticCss)(options.staticCss);
389
496
  this.verbose = options.verbose || process.env.ANIMUS_DEBUG === "1" || process.env.ANIMUS_DEBUG === "true";
390
497
  this.extensionsSet = new Set(options.extensions ?? _animus_ui_extract_pipeline.DEFAULT_EXTENSIONS);
498
+ if (engineApiOverride) {
499
+ this.engineApi = engineApiOverride;
500
+ return;
501
+ }
391
502
  const engineModuleId = "@animus-ui/extract";
392
503
  this.engineApi = (0, _animus_ui_extract_pipeline.createV2EngineApi)({
393
504
  label: "animus-extract",
@@ -418,6 +529,15 @@ var PluginContext = class {
418
529
  log(msg) {
419
530
  if (this.verbose) (this.logger ?? console).info(`[animus] ${msg}`);
420
531
  }
532
+ /**
533
+ * Standard-level information — emitted whether or not `verbose` is on.
534
+ * Reserved for events a developer must see without opting in, e.g. a file
535
+ * created after buildStart being folded into the analysis (openspec:
536
+ * hmr-new-file-detection, "New file detection logging").
537
+ */
538
+ info(msg) {
539
+ (this.logger ?? console).info(`[animus] ${msg}`);
540
+ }
421
541
  warn(msg) {
422
542
  (this.logger ?? console).warn(`[animus] ${msg}`);
423
543
  }
@@ -453,6 +573,7 @@ var PluginContext = class {
453
573
  if (this.options.strict) throw new Error(`[animus-extract] Failed to load system from ${this.resolvedSystemPath}: ${e}`, { cause: e });
454
574
  console.warn(`[animus-extract] Failed to load system from ${this.resolvedSystemPath}:`, e);
455
575
  }
576
+ this.systemPropsModuleMemo = generateSystemPropsModule(this);
456
577
  }
457
578
  /**
458
579
  * Run project analysis via the shared `runProjectAnalysis` and update
@@ -470,6 +591,7 @@ var PluginContext = class {
470
591
  },
471
592
  pathAliasesJson: this.pathAliasesJson,
472
593
  staticCssJson: this.staticCssJson,
594
+ externalDirs: this.externalPackageDirs.map((dir) => (0, path.relative)(this.rootDir, dir)),
473
595
  devMode: !this.isProd,
474
596
  warn: (m) => this.warn(m)
475
597
  });
@@ -477,7 +599,6 @@ var PluginContext = class {
477
599
  this.storedManifestJson = result.manifestJson;
478
600
  this.storedSystemPropMapJson = JSON.stringify(result.manifest?.system_prop_map ?? {});
479
601
  this.storedDynamicPropsJson = JSON.stringify(result.manifest?.dynamic_props ?? {});
480
- this.bridgeInjected = false;
481
602
  const newFragments = result.manifest?.component_fragments;
482
603
  if (newFragments && typeof newFragments === "object") {
483
604
  this.fragmentCache.clear();
@@ -490,7 +611,45 @@ var PluginContext = class {
490
611
  } catch (e) {
491
612
  if (this.options.strict) throw new Error(`[animus-extract] analyzeProject failed: ${e}`, { cause: e });
492
613
  console.warn("[animus-extract] analyzeProject failed:", e);
614
+ return;
615
+ }
616
+ this.systemPropsModuleMemo = generateSystemPropsModule(this);
617
+ this.applyAssetSubstitutions();
618
+ this.enforceExternalTokenContracts();
619
+ }
620
+ /** Base-prefixed dev URL for an absolute file (Vite mounts /@fs under base). */
621
+ devFsUrl(absPath) {
622
+ return `${this.base.endsWith("/") ? this.base.slice(0, -1) : this.base}/@fs${absPath}`;
623
+ }
624
+ /**
625
+ * The shared unresolvable-asset policy: fail the build under `strict`,
626
+ * else warn and record the identity mapping so the specifier emits
627
+ * literally.
628
+ */
629
+ assetFallback(specifier, message, cause) {
630
+ if (this.options.strict) throw new Error(message, cause === void 0 ? void 0 : { cause });
631
+ this.warn(message);
632
+ this.assetUrlBySpecifier.set(specifier, specifier);
633
+ this.assetResolutionFailures.add(specifier);
634
+ }
635
+ /**
636
+ * The one asset-substitution pass per analysis. In dev, a specifier not
637
+ * already mapped by buildStart's bundler-resolved pass (a geological
638
+ * reset regenerates globalCss from an edited system, which may reference
639
+ * NEW assets) is resolved Node-side first — host aliases, then Node,
640
+ * then package root; bundler-only resolutions can differ, since the
641
+ * plugin hook context is unavailable on this path. Strict semantics
642
+ * match buildStart.
643
+ */
644
+ applyAssetSubstitutions() {
645
+ if (!this.isProd && this.assetPassComplete) for (const specifier of (0, _animus_ui_extract_pipeline.findAssetSpecifiers)(this.globalCss)) {
646
+ if (this.assetResolutionFailures.delete(specifier)) this.assetUrlBySpecifier.delete(specifier);
647
+ if (this.assetUrlBySpecifier.has(specifier)) continue;
648
+ const resolved = (0, _animus_ui_extract_pipeline.resolveAssetFile)(specifier, this.rootDir, this.pathAliasesJson);
649
+ if (resolved) this.assetUrlBySpecifier.set(specifier, this.devFsUrl(resolved));
650
+ else this.assetFallback(specifier, `[animus-extract] unresolvable asset() specifier: ${specifier}`);
493
651
  }
652
+ this.globalCss = (0, _animus_ui_extract_pipeline.substituteAssetPlaceholders)(this.globalCss, this.assetUrlBySpecifier);
494
653
  }
495
654
  resetCoalescer = null;
496
655
  /**
@@ -500,10 +659,31 @@ var PluginContext = class {
500
659
  */
501
660
  requestGeologicalReset(trigger) {
502
661
  this.log(`HMR geological reset scheduled: ${trigger}`);
503
- this.resetCoalescer ??= new ResetCoalescer(() => this.performGeologicalReset());
662
+ this.resetCoalescer ??= new ResetCoalescer(() => this.performGeologicalReset(), (err) => this.geologicalResetFailed(err));
504
663
  this.resetCoalescer.request();
505
664
  }
506
665
  /**
666
+ * A failed reset must surface without killing the server: the coalescer
667
+ * fires from a bare timer, OUTSIDE Vite's handleHMRUpdate catch, so a
668
+ * strict-mode throw (asset resolution, token contracts, system load)
669
+ * would otherwise be an unhandled exception that exits the process.
670
+ * Strict-in-dev means the error overlay, matching the transform/HMR
671
+ * strict paths that Vite itself catches.
672
+ */
673
+ geologicalResetFailed(err) {
674
+ this.warn(`[animus-extract] geological reset failed: ${err}`);
675
+ const message = err instanceof Error ? err.message : String(err);
676
+ const stack = err instanceof Error ? err.stack ?? "" : "";
677
+ this.devServer?.hot?.send({
678
+ type: "error",
679
+ err: {
680
+ message,
681
+ stack,
682
+ plugin: "animus-extract"
683
+ }
684
+ });
685
+ }
686
+ /**
507
687
  * The geological reset: reload the system (refreshing the dependency
508
688
  * set), clear the Rust per-file cache, re-analyze everything with full
509
689
  * sources, then invalidate the static/component/system-prop virtual
@@ -568,6 +748,13 @@ var PluginContext = class {
568
748
  * `getModuleById` searches the client AND ssr environment graphs and its
569
749
  * `invalidateModule` invalidates both instances behind the returned node,
570
750
  * which is exactly the reach this path wants. It stays the seam here.
751
+ *
752
+ * Both modules are invalidated unconditionally, and deliberately so: the
753
+ * appearance or disappearance of a whole component file is not the
754
+ * steady-state edit the change-gated path governs, and a client reload does
755
+ * NOT rescue a module that was never invalidated — Vite keeps serving its
756
+ * cached transform result across reloads (openspec: hmr-new-file-detection,
757
+ * "CSS invalidation after new file analysis").
571
758
  */
572
759
  invalidateExtractedModules() {
573
760
  const server = this.devServer;
@@ -585,13 +772,36 @@ var PluginContext = class {
585
772
  * (external-package-file-discovery: silence is never an outcome). An
586
773
  * unresolvable `.includes()` specifier warns in non-strict mode and FAILS
587
774
  * the build under `strict: true`, naming every offending specifier —
588
- * a typo'd include must not ship a build missing its component CSS.
775
+ * a typo'd include must not ship a build missing its component CSS. A
776
+ * stale dist entry under an extended package (first-class-extension D13)
777
+ * rides the same seam: a merge against it would silently skew registry
778
+ * content the discovered sources no longer match.
589
779
  */
590
780
  enforceIncludeResolution() {
591
- const message = (0, _animus_ui_extract_pipeline.unresolvableIncludesMessage)(this.externalPackageOutcomes);
592
- if (message === null) return;
593
- if (this.options.strict) throw new Error(message);
594
- this.warn(message);
781
+ for (const message of [(0, _animus_ui_extract_pipeline.unresolvableIncludesMessage)(this.externalPackageOutcomes), (0, _animus_ui_extract_pipeline.staleDistIncludesMessage)(this.externalPackageOutcomes)]) {
782
+ if (message === null) continue;
783
+ if (this.options.strict) throw new Error(message);
784
+ this.warn(message);
785
+ }
786
+ }
787
+ /**
788
+ * The post-analysis gate over cross-source token contracts
789
+ * (extraction-diagnostics): a discovered component referencing a token its
790
+ * OWN package defines but the consumer theme does not gets the teaching
791
+ * error naming the token, component, source package, and the missing
792
+ * `createTheme().extend(...)`. Wiring and severity routing live in the
793
+ * shared pipeline gate (next-plugin parity by construction).
794
+ */
795
+ enforceExternalTokenContracts() {
796
+ (0, _animus_ui_extract_pipeline.enforceExternalTokenContracts)({
797
+ diagnostics: this.storedManifest?.diagnostics,
798
+ fileOwners: this.externalFileOwners,
799
+ dirOwners: this.externalDirOwners,
800
+ sourceThemeManifestsJson: this.system.sourceThemeManifestsJson,
801
+ strict: this.options.strict,
802
+ prefix: "[animus-extract]",
803
+ warn: (message) => this.warn(message)
804
+ });
595
805
  }
596
806
  runSelfVerify() {
597
807
  const failures = [];
@@ -641,13 +851,16 @@ var PluginContext = class {
641
851
  * graph, so system dependencies registered through `watcher.add` outside the
642
852
  * root still reach the reset branch, with an empty `modules` list.
643
853
  */
644
- async function handleHotUpdate(ctx, environment, { type, file, timestamp, modules }) {
854
+ async function handleHotUpdate(ctx, environment, { type, file, timestamp, modules, read }) {
645
855
  if (ctx.isProd) return;
646
856
  const ownsEvent = ctx.hotUpdateEvents.claim(environment.name, file, timestamp);
647
857
  const absFile = (0, path.resolve)(file);
648
858
  ctx.log(`hotUpdate ${type} ${(0, path.relative)(ctx.rootDir, absFile)} env=${environment.name} owns=${ownsEvent}`);
649
859
  if (ctx.isSystemDependency(absFile)) {
650
- if (ownsEvent) ctx.requestGeologicalReset((0, path.relative)(ctx.rootDir, absFile));
860
+ if (ownsEvent) {
861
+ await reconcileSourceEntry(ctx, absFile, type, read);
862
+ ctx.requestGeologicalReset((0, path.relative)(ctx.rootDir, absFile));
863
+ }
651
864
  return [];
652
865
  }
653
866
  if (type === "create") return;
@@ -655,18 +868,69 @@ async function handleHotUpdate(ctx, environment, { type, file, timestamp, module
655
868
  if (ownsEvent) pruneDeletedFile(ctx, absFile);
656
869
  return;
657
870
  }
658
- if (ownsEvent) ctx.hotUpdateEvents.record(file, timestamp, await analyzeChangedFile(ctx, file, absFile));
871
+ if (ownsEvent) ctx.hotUpdateEvents.record(file, timestamp, await analyzeChangedFile(ctx, file, absFile, read));
659
872
  const result = ctx.hotUpdateEvents.resultOf(file, timestamp);
660
873
  if (result.kind === "ignored") return;
661
874
  if (result.kind === "unchanged") return [];
662
- return invalidateStaleModules(ctx, environment, modules, result.staleDefinitionFiles);
875
+ return invalidateStaleModules(ctx, environment, modules, result);
876
+ }
877
+ /**
878
+ * The changed file's text.
879
+ *
880
+ * Editors save atomically — truncate, then rewrite — so a watcher event can
881
+ * arrive while the path is momentarily EMPTY. Vite's `read()` helper retries on
882
+ * empty content for exactly that reason; reading the path directly at the same
883
+ * moment yields `''`, and since the corrective content produces no second
884
+ * event, that empty source would be cached permanently.
885
+ *
886
+ * Vite always supplies `read`, so the direct read is NOT a fallback for Vite:
887
+ * it exists for hosts that drive this hook without one. The dev-lane's adapter
888
+ * contract is deliberately bundler-neutral, and a second runtime satisfying it
889
+ * must not be forced to fabricate a helper to get correct behavior.
890
+ */
891
+ async function readChangedSource(absFile, read) {
892
+ return read ? await read() : (0, fs.readFileSync)(absFile, "utf-8");
893
+ }
894
+ /**
895
+ * Reconcile the `fileCache` entry of a file that is BOTH a system dependency
896
+ * and a discovered component source, since the dependency branch is terminal —
897
+ * neither the edit path's cache write nor `pruneDeletedFile` runs for it.
898
+ *
899
+ * An edit refreshes the entry: `performGeologicalReset` rebuilds its
900
+ * full-source analysis from this cache, so a stale entry would be re-analyzed
901
+ * on every later reset. A delete prunes it, exactly as the ordinary delete path
902
+ * would (openspec: hmr-new-file-detection, "Watcher deletion pruning") — a
903
+ * surviving entry is a ghost source no watcher event can ever name again.
904
+ *
905
+ * Dependency-only files have no entry: `pruneFileCache` no-ops for them, and
906
+ * the edit path must not create one — the cache is the component-source set,
907
+ * and a phantom entry would feed the engine a file it never discovered.
908
+ */
909
+ async function reconcileSourceEntry(ctx, absFile, type, read) {
910
+ if (type === "delete") {
911
+ pruneFileCache(ctx.fileCache, ctx.rootDir, absFile);
912
+ return;
913
+ }
914
+ const relPath = (0, path.relative)(ctx.rootDir, absFile);
915
+ if (!ctx.fileCache.has(relPath)) return;
916
+ let source;
917
+ try {
918
+ source = await readChangedSource(absFile, read);
919
+ } catch {
920
+ ctx.warn(`could not re-read ${relPath} after a system-dependency edit — geological resets will analyze its pre-edit text until a later edit is read successfully`);
921
+ return;
922
+ }
923
+ ctx.fileCache.set(relPath, {
924
+ hash: (0, _animus_ui_extract_pipeline.contentHash)(source),
925
+ source
926
+ });
663
927
  }
664
928
  /**
665
929
  * The once-per-event analysis half: gate the file, diff its content hash,
666
930
  * refresh the cache, and re-run project analysis. The returned result is what
667
931
  * the remaining environments act on.
668
932
  */
669
- async function analyzeChangedFile(ctx, file, absFile) {
933
+ async function analyzeChangedFile(ctx, file, absFile, read) {
670
934
  const ext = (0, path.extname)(file);
671
935
  if (!ctx.extensionsSet.has(ext)) return { kind: "ignored" };
672
936
  const excludePatterns = ctx.options.exclude ?? DEFAULT_EXCLUDE;
@@ -674,7 +938,7 @@ async function analyzeChangedFile(ctx, file, absFile) {
674
938
  const relPath = (0, path.relative)(ctx.rootDir, absFile);
675
939
  let source;
676
940
  try {
677
- source = (0, fs.readFileSync)(absFile, "utf-8");
941
+ source = await readChangedSource(absFile, read);
678
942
  } catch {
679
943
  return { kind: "ignored" };
680
944
  }
@@ -720,8 +984,7 @@ async function analyzeChangedFile(ctx, file, absFile) {
720
984
  }
721
985
  if (ctx.verbose && invalidatedIds.size > directComponentIds.length) ctx.log(`HMR: ${directComponentIds.length} direct + ${invalidatedIds.size - directComponentIds.length} transitive components invalidated`);
722
986
  const analysisStart = performance.now();
723
- const fileEntries = buildFileEntriesFromCache(ctx.fileCache, relPath);
724
- ctx.runAnalysis(fileEntries);
987
+ const systemPropsChanged = runAnalysisTrackingSystemProps(ctx, buildFileEntriesFromCache(ctx.fileCache, relPath));
725
988
  const analysisMs = Math.round(performance.now() - analysisStart);
726
989
  const staleDefinitionFiles = [];
727
990
  if (ctx.storedManifest?.components) {
@@ -737,7 +1000,8 @@ async function analyzeChangedFile(ctx, file, absFile) {
737
1000
  ctx.logTimingWaterfall(ctx.storedManifest?.timing ?? {});
738
1001
  return {
739
1002
  kind: "analyzed",
740
- staleDefinitionFiles
1003
+ staleDefinitionFiles,
1004
+ systemPropsChanged
741
1005
  };
742
1006
  }
743
1007
  /**
@@ -760,17 +1024,19 @@ function pruneDeletedFile(ctx, absFile) {
760
1024
  * (virtual:animus/styles.css) is NOT invalidated here — it only changes on a
761
1025
  * geological reset (vars/globals are stable during dev).
762
1026
  */
763
- function invalidateStaleModules(ctx, environment, modules, staleDefinitionFiles) {
1027
+ function invalidateStaleModules(ctx, environment, modules, analyzed) {
764
1028
  const graph = environment.moduleGraph;
765
1029
  const modulesToUpdate = [...modules];
766
- for (const moduleId of [RESOLVED_COMPONENTS_ID, RESOLVED_SYSTEM_PROPS_ID]) {
1030
+ const moduleIds = [RESOLVED_COMPONENTS_ID];
1031
+ if (analyzed.systemPropsChanged) moduleIds.push(RESOLVED_SYSTEM_PROPS_ID);
1032
+ for (const moduleId of moduleIds) {
767
1033
  const mod = graph.getModuleById(moduleId);
768
1034
  if (mod) {
769
1035
  graph.invalidateModule(mod);
770
1036
  modulesToUpdate.push(mod);
771
1037
  }
772
1038
  }
773
- for (const defFile of staleDefinitionFiles) {
1039
+ for (const defFile of analyzed.staleDefinitionFiles) {
774
1040
  const absDefPath = (0, path.resolve)(ctx.rootDir, defFile);
775
1041
  const defModule = graph.getModuleById(absDefPath) ?? graph.getModulesByFile(absDefPath)?.values().next().value;
776
1042
  if (defModule) {
@@ -790,16 +1056,18 @@ function invalidateStaleModules(ctx, environment, modules, staleDefinitionFiles)
790
1056
  /**
791
1057
  * transformIndexHtml: build the head-prepend tag set.
792
1058
  *
793
- * Two independent tags, both delivery-only:
1059
+ * Three independent tags, all delivery-only:
794
1060
  * - the appearance bootstrap script, when the host build passed a
795
1061
  * pre-generated artifact via `appearanceBootstrap` (absent otherwise);
796
- * - the `@layer` declaration style, when `buildStart` computed one.
1062
+ * - the `@layer` declaration style, when `buildStart` computed one;
1063
+ * - the HMR bridge module script, in dev only.
797
1064
  *
798
- * Both branches are guarded on non-empty CONTENT, not on mere presence: an
799
- * artifact whose `code` is empty is a caller defect, and emitting
1065
+ * The two build-time branches are guarded on non-empty CONTENT, not on mere
1066
+ * presence: an artifact whose `code` is empty is a caller defect, and emitting
800
1067
  * `<script data-animus-bootstrap><\/script>` for it would break the
801
1068
  * unconfigured-parity contract in spirit (a tag that does nothing) while
802
- * hiding the defect. Symmetric with `layerDeclaration`.
1069
+ * hiding the defect. Symmetric with `layerDeclaration`. The bridge has no
1070
+ * content of its own — it is a `src` reference — so its only guard is the mode.
803
1071
  *
804
1072
  * Ordering: every descriptor rides the same `head-prepend` bucket, which Vite
805
1073
  * serializes in array order (`serializeTags`) and splices in immediately after
@@ -807,8 +1075,8 @@ function invalidateStaleModules(ctx, environment, modules, staleDefinitionFiles)
807
1075
  * before the layer declaration and — since built stylesheet links are appended
808
1076
  * at `</head>` — before any stylesheet reference.
809
1077
  *
810
- * When neither input is set the array is empty, so an unconfigured build emits
811
- * no tag, attribute, or whitespace of its own.
1078
+ * With neither build-time input set, a production build emits no tag,
1079
+ * attribute, or whitespace of its own.
812
1080
  */
813
1081
  function buildIndexHtmlTags(ctx) {
814
1082
  const tags = [];
@@ -825,24 +1093,45 @@ function buildIndexHtmlTags(ctx) {
825
1093
  children: ctx.layerDeclaration,
826
1094
  injectTo: "head-prepend"
827
1095
  });
1096
+ if (!ctx.isProd) tags.push({
1097
+ tag: "script",
1098
+ attrs: {
1099
+ type: "module",
1100
+ src: BRIDGE_SCRIPT_SRC,
1101
+ "data-animus-bridge": ""
1102
+ },
1103
+ injectTo: "head-prepend"
1104
+ });
828
1105
  return tags;
829
1106
  }
830
1107
  //#endregion
831
1108
  //#region src/transform.ts
832
1109
  /**
833
1110
  * transform: replace builder chains with `createComponent()` calls using
834
- * the pre-built manifest; inject the HMR bridge import once in dev; detect
835
- * files created after buildStart and fold them into the analysis.
1111
+ * the pre-built manifest; detect files created after buildStart and fold
1112
+ * them into the analysis.
1113
+ *
1114
+ * The HMR bridge is NOT injected here — `transformIndexHtml` delivers it as a
1115
+ * `<script type="module">` per served document (openspec:
1116
+ * dev-stylesheet-management, "HMR bridge auto-injected in dev mode"; "Transform
1117
+ * emitter unchanged" forbids the emitter importing it).
836
1118
  */
837
1119
  function transformSource(ctx, code, id) {
838
1120
  if (!ctx.storedManifest) return null;
839
- if (!ctx.externalPackageDirs.some((dir) => id.startsWith(dir + path.sep) || id === dir)) {
1121
+ if (id.startsWith("\0") || id.startsWith("virtual:animus/")) return null;
1122
+ const isExternalPkg = ctx.externalPackageDirs.some((dir) => id.startsWith(dir + path.sep) || id === dir);
1123
+ const relativePath = (0, path.relative)(ctx.rootDir, id);
1124
+ if (!isExternalPkg) {
840
1125
  if (!/\.[jt]sx?$/.test(id)) return null;
841
1126
  if (id.includes("node_modules")) return null;
1127
+ if (relativePath.startsWith("..") || (0, path.isAbsolute)(relativePath)) return null;
842
1128
  }
843
- const relativePath = (0, path.relative)(ctx.rootDir, id);
844
1129
  if (!ctx.storedManifest.files?.[relativePath]?.length) {
845
1130
  if (!ctx.isProd && !ctx.fileCache.has(relativePath)) {
1131
+ if (isExternalPkg) {
1132
+ const owner = Object.entries(ctx.externalDirOwners).find(([dir]) => id === dir || id.startsWith(dir + path.sep));
1133
+ if (owner) ctx.externalFileOwners[relativePath] = owner[1];
1134
+ }
846
1135
  const hash = (0, _animus_ui_extract_pipeline.contentHash)(code);
847
1136
  ctx.fileCache.set(relativePath, {
848
1137
  hash,
@@ -851,8 +1140,8 @@ function transformSource(ctx, code, id) {
851
1140
  const fileEntries = buildFileEntriesFromCache(ctx.fileCache, relativePath);
852
1141
  ctx.runAnalysis(fileEntries);
853
1142
  const compCount = ctx.storedManifest.files?.[relativePath]?.length ?? 0;
854
- ctx.log(`New file detected: ${relativePath} — ${compCount ? `${compCount} components extracted` : "no components"}`);
855
- if (compCount) ctx.invalidateExtractedModules();
1143
+ ctx.info(`New file detected: ${relativePath} — ${compCount ? `${compCount} components extracted` : "no components"}`);
1144
+ ctx.invalidateExtractedModules();
856
1145
  }
857
1146
  if (!ctx.storedManifest.files?.[relativePath]?.length) return null;
858
1147
  }
@@ -860,18 +1149,17 @@ function transformSource(ctx, code, id) {
860
1149
  const { transformFile } = ctx.engineApi();
861
1150
  const result = transformFile(code, relativePath, ctx.storedManifestJson);
862
1151
  if (!result.hasComponents) return null;
863
- let transformedCode = result.code;
864
- if (!ctx.isProd && !ctx.bridgeInjected && ctx.storedSheets) {
865
- transformedCode = `import '${VIRTUAL_BRIDGE_ID}';\n${transformedCode}`;
866
- ctx.bridgeInjected = true;
867
- ctx.log("HMR bridge injected via transform");
868
- }
869
1152
  if (ctx.verbose) {
870
1153
  const compCount = ctx.storedManifest.files?.[relativePath]?.length ?? 0;
871
1154
  ctx.log(`transform ${relativePath}: ${compCount} components`);
872
1155
  }
1156
+ let outputCode = result.code;
1157
+ if (!ctx.isProd) {
1158
+ const prologue = /^(?:(['"])use [a-z -]+\1;?\r?\n)*/.exec(result.code)?.[0] ?? "";
1159
+ outputCode = prologue + `import '${VIRTUAL_BRIDGE_ID}';\n` + result.code.slice(prologue.length);
1160
+ }
873
1161
  return {
874
- code: transformedCode,
1162
+ code: outputCode,
875
1163
  map: null
876
1164
  };
877
1165
  } catch (e) {
@@ -884,10 +1172,10 @@ function transformSource(ctx, code, id) {
884
1172
  //#region src/virtual-modules.ts
885
1173
  /** resolveId: map virtual ids and redirect external DS package imports. */
886
1174
  function resolveVirtualId(ctx, id) {
887
- if (id === "virtual:animus/styles.css") return RESOLVED_CSS_ID;
888
- if (id === "virtual:animus/components.js") return RESOLVED_COMPONENTS_ID;
889
- if (id === "virtual:animus/hmr-bridge.js") return RESOLVED_BRIDGE_ID;
890
- if (id === "virtual:animus/system-props") return RESOLVED_SYSTEM_PROPS_ID;
1175
+ if (id === VIRTUAL_CSS_ID) return RESOLVED_CSS_ID;
1176
+ if (id === VIRTUAL_COMPONENTS_ID) return RESOLVED_COMPONENTS_ID;
1177
+ if (id === VIRTUAL_BRIDGE_ID) return RESOLVED_BRIDGE_ID;
1178
+ if (id === VIRTUAL_SYSTEM_PROPS_ID) return RESOLVED_SYSTEM_PROPS_ID;
891
1179
  const srcEntry = ctx.externalSourceEntries.get(id);
892
1180
  if (srcEntry) return srcEntry;
893
1181
  return null;
@@ -900,7 +1188,7 @@ function loadVirtualModule(ctx, id) {
900
1188
  targets: ctx.lcssTargets,
901
1189
  warnFn: (msg) => ctx.warn(msg)
902
1190
  };
903
- if (id === "\0virtual:animus/styles.css") {
1191
+ if (id === RESOLVED_CSS_ID) {
904
1192
  if (!ctx.isProd && ctx.storedSheets) {
905
1193
  const { variables, body } = (0, _animus_ui_extract_pipeline.assembleStylesheet)({
906
1194
  layers: ctx.options.layers,
@@ -922,36 +1210,44 @@ function loadVirtualModule(ctx, id) {
922
1210
  });
923
1211
  return [variables, (0, _animus_ui_extract_pipeline.postProcessCss)(body, lcssOpts)].filter(Boolean).join("\n");
924
1212
  }
925
- if (id === "\0virtual:animus/components.js") return `export default \`${(0, _animus_ui_extract_pipeline.postProcessCss)((0, _animus_ui_extract_pipeline.stripLeadingLayerDeclaration)(ctx.resolvedComponentCss || ""), {
1213
+ if (id === RESOLVED_COMPONENTS_ID) return `export default \`${(0, _animus_ui_extract_pipeline.postProcessCss)((0, _animus_ui_extract_pipeline.stripLeadingLayerDeclaration)(ctx.resolvedComponentCss || ""), {
926
1214
  ...lcssOpts,
927
1215
  minify: false
928
1216
  }).replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$")}\`;`;
929
- if (id === "\0virtual:animus/hmr-bridge.js") return `
1217
+ if (id === RESOLVED_BRIDGE_ID) return `
930
1218
  import css from '${VIRTUAL_COMPONENTS_ID}';
931
1219
 
932
1220
  const GLOBAL_KEY = '__animus_sheet_${(0, crypto.createHash)("md5").update(ctx.options.system).digest("hex").slice(0, 8)}__';
933
1221
  let sheet = globalThis[GLOBAL_KEY] || null;
934
1222
 
935
- if (typeof CSSStyleSheet !== 'undefined' && 'adoptedStyleSheets' in document) {
936
- if (!sheet) {
937
- sheet = new CSSStyleSheet();
938
- globalThis[GLOBAL_KEY] = sheet;
939
- document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
940
- }
941
- sheet.replaceSync(css);
942
- } else {
943
- // Fallback: inject or update <style> tag
944
- let el = document.querySelector('style[data-animus-components]');
945
- if (!el) {
946
- el = document.createElement('style');
947
- el.setAttribute('data-animus-components', '');
948
- document.head.appendChild(el);
1223
+ // Server evaluation is a no-op: SSR hosts reach this module through the
1224
+ // bridge import prepended to transformed component modules, and only the
1225
+ // browser pass owns a document.
1226
+ if (typeof document !== 'undefined') {
1227
+ if (typeof CSSStyleSheet !== 'undefined' && 'adoptedStyleSheets' in document) {
1228
+ if (!sheet) {
1229
+ sheet = new CSSStyleSheet();
1230
+ globalThis[GLOBAL_KEY] = sheet;
1231
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
1232
+ }
1233
+ sheet.replaceSync(css);
1234
+ } else {
1235
+ // Fallback: inject or update <style> tag
1236
+ let el = document.querySelector('style[data-animus-components]');
1237
+ if (!el) {
1238
+ el = document.createElement('style');
1239
+ el.setAttribute('data-animus-components', '');
1240
+ document.head.appendChild(el);
1241
+ }
1242
+ el.textContent = css;
949
1243
  }
950
- el.textContent = css;
951
1244
  }
952
1245
 
953
1246
  if (import.meta.hot) {
954
1247
  import.meta.hot.accept('${VIRTUAL_COMPONENTS_ID}', (newModule) => {
1248
+ // The server module runner has a hot channel too; only the browser
1249
+ // pass owns a document to update.
1250
+ if (typeof document === 'undefined') return;
955
1251
  if (sheet) {
956
1252
  sheet.replaceSync(newModule.default);
957
1253
  } else {
@@ -961,12 +1257,7 @@ if (import.meta.hot) {
961
1257
  });
962
1258
  }
963
1259
  `;
964
- if (id === "\0virtual:animus/system-props") return (0, _animus_ui_extract_pipeline.buildSystemPropsModule)({
965
- systemPropMapJson: ctx.storedSystemPropMapJson,
966
- groupRegistryJson: ctx.system.groupRegistryJson,
967
- dynamicProps: JSON.parse(ctx.storedDynamicPropsJson),
968
- transformsSource: ctx.storedTransformsSource
969
- });
1260
+ if (id === RESOLVED_SYSTEM_PROPS_ID) return systemPropsModuleSource(ctx);
970
1261
  return null;
971
1262
  }
972
1263
  //#endregion
@@ -982,6 +1273,9 @@ function animusExtract(options) {
982
1273
  return {
983
1274
  name: "animus-extract",
984
1275
  enforce: "pre",
1276
+ config(_config, env) {
1277
+ return { define: { __ANIMUS_DEV__: env.command !== "build" } };
1278
+ },
985
1279
  configureServer(server) {
986
1280
  ctx.devServer = server;
987
1281
  ctx.registerSystemWatchPaths();
@@ -992,7 +1286,11 @@ function animusExtract(options) {
992
1286
  async buildStart() {
993
1287
  await runBuildStart(ctx, async (specifier) => {
994
1288
  return (await this.resolve(specifier))?.id ?? null;
995
- });
1289
+ }, ctx.isProd ? (fileName, source) => this.emitFile({
1290
+ type: "asset",
1291
+ name: fileName,
1292
+ source
1293
+ }) : void 0);
996
1294
  },
997
1295
  resolveId(id) {
998
1296
  return resolveVirtualId(ctx, id);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,qGAAqG;IACrG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC;IACd;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CA0DnE;eAEc,aAAa"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,qGAAqG;IACrG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC;IACd;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CA0EnE;eAEc,aAAa"}
@@ -9,13 +9,14 @@
9
9
  */
10
10
  export declare class ResetCoalescer {
11
11
  private readonly run;
12
+ private readonly onError;
12
13
  private readonly quietMs;
13
14
  private readonly schedule;
14
15
  private readonly cancel;
15
16
  private timer;
16
17
  private running;
17
18
  private dirty;
18
- constructor(run: () => void, quietMs?: number, schedule?: (fn: () => void, ms: number) => unknown, cancel?: (timer: unknown) => void);
19
+ constructor(run: () => void, onError: (err: unknown) => void, quietMs?: number, schedule?: (fn: () => void, ms: number) => unknown, cancel?: (timer: unknown) => void);
19
20
  /** Ask for a reset; bursts within the quiescence window collapse. */
20
21
  request(): void;
21
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"reset-coalescer.d.ts","sourceRoot":"","sources":["../src/reset-coalescer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,qBAAa,cAAc;IAMvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAIzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAXzB,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;IAEtB,YACmB,GAAG,EAAE,MAAM,IAAI,EACf,OAAO,SAAK,EACZ,QAAQ,GAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAGpC,EACN,MAAM,GAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IACS,EACpD;IAEJ,qEAAqE;IACrE,OAAO,IAAI,IAAI,CAmBd;CACF"}
1
+ {"version":3,"file":"reset-coalescer.d.ts","sourceRoot":"","sources":["../src/reset-coalescer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,qBAAa,cAAc;IAMvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAKpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAIzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAhBzB,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;IAEtB,YACmB,GAAG,EAAE,MAAM,IAAI,EAKf,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,EAC/B,OAAO,SAAK,EACZ,QAAQ,GAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAGpC,EACN,MAAM,GAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IACS,EACpD;IAEJ,qEAAqE;IACrE,OAAO,IAAI,IAAI,CAqBd;CACF"}
@@ -1,8 +1,13 @@
1
1
  import type { PluginContext } from './context';
2
2
  /**
3
3
  * transform: replace builder chains with `createComponent()` calls using
4
- * the pre-built manifest; inject the HMR bridge import once in dev; detect
5
- * files created after buildStart and fold them into the analysis.
4
+ * the pre-built manifest; detect files created after buildStart and fold
5
+ * them into the analysis.
6
+ *
7
+ * The HMR bridge is NOT injected here — `transformIndexHtml` delivers it as a
8
+ * `<script type="module">` per served document (openspec:
9
+ * dev-stylesheet-management, "HMR bridge auto-injected in dev mode"; "Transform
10
+ * emitter unchanged" forbids the emitter importing it).
6
11
  */
7
12
  export declare function transformSource(ctx: PluginContext, code: string, id: string): {
8
13
  code: string;
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CA4EpC"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CA0HpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-modules.d.ts","sourceRoot":"","sources":["../src/virtual-modules.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GACT,MAAM,GAAG,IAAI,CAYf;AAED;wDACwD;AACxD,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GACT,MAAM,GAAG,IAAI,CAyGf"}
1
+ {"version":3,"file":"virtual-modules.d.ts","sourceRoot":"","sources":["../src/virtual-modules.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GACT,MAAM,GAAG,IAAI,CAYf;AAED;wDACwD;AACxD,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GACT,MAAM,GAAG,IAAI,CA8Gf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@animus-ui/vite-plugin",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Animus static CSS extraction Vite plugin",
5
5
  "keywords": [
6
6
  "animus",
@@ -39,7 +39,7 @@
39
39
  "compile": "tsc --noEmit"
40
40
  },
41
41
  "dependencies": {
42
- "@animus-ui/extract": "0.1.3",
42
+ "@animus-ui/extract": "0.1.5",
43
43
  "browserslist": "^4.24.0",
44
44
  "lightningcss": "^1.29.0"
45
45
  },