@animus-ui/vite-plugin 0.1.9 → 0.1.11

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.
@@ -1 +1 @@
1
- {"version":3,"file":"build-start.d.ts","sourceRoot":"","sources":["../src/build-start.ts"],"names":[],"mappings":"AAmBA,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,CA2Rf"}
1
+ {"version":3,"file":"build-start.d.ts","sourceRoot":"","sources":["../src/build-start.ts"],"names":[],"mappings":"AAiBA,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,CA8Pf"}
@@ -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,CAwDN"}
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,CAiEN"}
@@ -28,5 +28,5 @@ export declare const RESOLVED_BRIDGE_ID = "\0virtual:animus/hmr-bridge.js";
28
28
  export declare const BRIDGE_SCRIPT_SRC = "/@id/virtual:animus/hmr-bridge.js";
29
29
  export declare const VIRTUAL_SYSTEM_PROPS_ID = "virtual:animus/system-props";
30
30
  export declare const RESOLVED_SYSTEM_PROPS_ID = "\0virtual:animus/system-props";
31
- export declare const DEFAULT_EXCLUDE: string[];
31
+ export { DEFAULT_EXCLUDE } from '@animus-ui/extract/pipeline';
32
32
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
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"}
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;AAKvE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC"}
package/dist/context.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { HotUpdateEvents } from './hot-update-events';
2
2
  import type { LightningTargets } from './css';
3
3
  import type { AnimusExtractOptions } from './index';
4
- import type { ExternalPackageOutcome, ManifestDiagnostic, SystemConfig } from '@animus-ui/extract/pipeline';
4
+ import type { ExcludeMatcher, ExternalPackageOutcome, ManifestDiagnostic, RawSourceEntry, SourceEntryOwnership, SourceIngestionDiagnostic, SourceIngestionResult, SystemConfig } from '@animus-ui/extract/pipeline';
5
5
  import type { Logger } from 'vite';
6
6
  /**
7
7
  * Structured per-layer CSS sheets from the Rust crate (dev split delivery).
@@ -18,21 +18,19 @@ export interface CssSheets {
18
18
  system: string;
19
19
  custom: string;
20
20
  }
21
- /**
22
- * Reconstruct file entries from cache, including content hashes.
23
- * For unchanged files (hash matches changedPath), sends empty source
24
- * to avoid serializing full source text across the NAPI boundary.
25
- * The engine adapter's `rehydrateFilesJson` refills empty sources from
26
- * this same cache before analyze.
27
- */
28
- export declare function buildFileEntriesFromCache(cache: Map<string, {
21
+ /** Full raw originals for one adaptation attempt. */
22
+ export declare function buildRawEntriesFromCache(cache: Map<string, {
29
23
  hash: string;
30
24
  source: string;
31
- }>, changedPath?: string): Array<{
25
+ }>): Array<{
32
26
  path: string;
33
27
  source: string;
34
28
  hash: string;
35
29
  }>;
30
+ /** Run `task` after every previously scheduled analysis transaction for
31
+ * this context. Entry points only (transform detection, hot update,
32
+ * geological reset); helpers they call internally must stay unlocked. */
33
+ export declare function runExclusiveAnalysis<T>(ctx: object, task: () => Promise<T>): Promise<T>;
36
34
  /**
37
35
  * The exact source `virtual:animus/system-props` serves for the current state.
38
36
  * One definition, so the served bytes and the change decision below can never
@@ -45,12 +43,10 @@ export declare function buildFileEntriesFromCache(cache: Map<string, {
45
43
  */
46
44
  export declare function systemPropsModuleSource(ctx: PluginContext): string;
47
45
  /**
48
- * Drop a deleted (or renamed-away) file from the dev file cache so its
49
- * last-known source stops riding along as a ghost entry on every later
50
- * re-analysis. Both key forms are tried: the plain rootDir-relative path, and
51
- * the `.tsx` suffix MDX sources carry after preprocessing. External package
52
- * entries are rootDir-relative too (with leading `..` segments) and prune the
53
- * same way. Returns whether an entry was actually removed.
46
+ * Drop a deleted (or renamed-away) raw original from the dev file cache.
47
+ * Generated MDX/Svelte children live in `analysisEntryCache` and disappear
48
+ * atomically when the next source-ingestion result publishes. External
49
+ * package entries are rootDir-relative too (with leading `..` segments).
54
50
  */
55
51
  export declare function pruneFileCache(cache: Map<string, {
56
52
  hash: string;
@@ -72,6 +68,10 @@ export declare class PluginContext {
72
68
  /** Serialized staticCss forced-emission declarations (stable key order). */
73
69
  readonly staticCssJson: string | null;
74
70
  isProd: boolean;
71
+ /** Emission-mode signal (explicit `mode` option wins over the command);
72
+ * feeds engine devMode and the minify default. Lifecycle stays on
73
+ * `isProd`. */
74
+ emissionProd: boolean;
75
75
  rootDir: string;
76
76
  logger: Logger | null;
77
77
  /** System-derived config (shared SystemConfig shape). */
@@ -79,6 +79,7 @@ export declare class PluginContext {
79
79
  lcssTargets: LightningTargets;
80
80
  pathAliasesJson: string | null;
81
81
  extensionsSet: ReadonlySet<string>;
82
+ excludeMatcher: ExcludeMatcher;
82
83
  storedManifest: any;
83
84
  storedManifestJson: string;
84
85
  globalCss: string;
@@ -117,6 +118,12 @@ export declare class PluginContext {
117
118
  hash: string;
118
119
  source: string;
119
120
  }>;
121
+ analysisEntryCache: Map<string, {
122
+ hash: string;
123
+ source: string;
124
+ }>;
125
+ sourceOwnership: Record<string, SourceEntryOwnership>;
126
+ analysisOwnerByPath: Map<string, string>;
120
127
  rawExtensionFallbacks: Set<string>;
121
128
  readonly hotUpdateEvents: HotUpdateEvents;
122
129
  private pendingReloadTimer;
@@ -171,6 +178,46 @@ export declare class PluginContext {
171
178
  source: string;
172
179
  hash?: string;
173
180
  }>): boolean;
181
+ /**
182
+ * `runtimeImport` swaps ONE module specifier under every generated
183
+ * factory import, and the engine performs no export validation — an
184
+ * override that supplies only `createClassResolver` (the documented
185
+ * class-resolver entry contract) breaks the bundle at LOAD the moment any
186
+ * non-`.asClass()` terminal exists, with the error pointing at generated
187
+ * code. Guaranteed-broken output escalates in every mode, exactly like
188
+ * error diagnostics (extraction-diagnostics §Error diagnostics fail the
189
+ * build), naming the offending components instead of the import site.
190
+ */
191
+ private assertRuntimeImportSuppliesTerminals;
192
+ /** The shared ingestion policy point — capability guard, facts memo, and
193
+ * warn-dedupe lifecycle all live in the pipeline, not per host. */
194
+ private sourceIngestor;
195
+ /** Prepare one raw-source corpus through the shared adaptation boundary. */
196
+ ingestRawSources(fileEntries: readonly RawSourceEntry[]): Promise<SourceIngestionResult>;
197
+ /** Surface adapter diagnostics under the shared strict/warn policy. */
198
+ surfaceSourceDiagnostics(diagnostics: readonly SourceIngestionDiagnostic[]): Set<string>;
199
+ /**
200
+ * The one ingest → quarantine → analyze → publish transaction, shared by
201
+ * buildStart and every incremental path. Per-file quarantine: one invalid
202
+ * original warns and drops without aborting the rest of the corpus
203
+ * (strict mode throws from the shared policy). `runAnalysis(...) !==
204
+ * false` is the documented success contract (a `void` behavioral test
205
+ * double reads as success), and the accepted corpus publishes only on
206
+ * success. `beforeAnalysis` runs between quarantine and analysis for the
207
+ * two sites with a documented ordering constraint: buildStart's dev-cache
208
+ * seed must survive a strict analysis throw, and the geological reset
209
+ * clears the engine cache only after strict ingestion diagnostics had
210
+ * their chance to throw.
211
+ */
212
+ analyzeIngested(options?: {
213
+ rawEntries?: readonly RawSourceEntry[];
214
+ beforeAnalysis?: (accepted: SourceIngestionResult) => void;
215
+ }): Promise<{
216
+ ok: boolean;
217
+ accepted: SourceIngestionResult;
218
+ }>;
219
+ /** Publish every parser child and ownership edge atomically after analysis. */
220
+ publishSourceIngestion(result: SourceIngestionResult): void;
174
221
  /** Base-prefixed dev URL for an absolute file (Vite mounts /@fs under base). */
175
222
  devFsUrl(absPath: string): string;
176
223
  /**
@@ -211,7 +258,9 @@ export declare class PluginContext {
211
258
  * sources, then invalidate the static/component/system-prop virtual
212
259
  * modules and reload the client.
213
260
  */
214
- performGeologicalReset(): void;
261
+ performGeologicalReset(): Promise<void>;
262
+ private performGeologicalResetExclusive;
263
+ private invalidateGeologicalResetModules;
215
264
  /**
216
265
  * True when the file is a member of the system's evaluated module-file
217
266
  * set. Tested BEFORE component-scan exclude filters: a system dependency
@@ -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, read }: HotUpdateOptions): Promise<EnvironmentModuleNode[] | void>;
22
+ export declare function handleHotUpdate(ctx: PluginContext, environment: DevEnvironment, options: 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":"AAwBA,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,CA8EzC"}
1
+ {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"AAmBA,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,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,qBAAqB,EAAE,GAAG,IAAI,CAAC,CAUzC"}
package/dist/index.cjs CHANGED
@@ -6,44 +6,6 @@ let _animus_ui_extract_pipeline = require("@animus-ui/extract/pipeline");
6
6
  let fs = require("fs");
7
7
  let path = require("path");
8
8
  let crypto = require("crypto");
9
- //#region src/constants.ts
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}`;
40
- const DEFAULT_EXCLUDE = [
41
- "node_modules",
42
- "dist",
43
- ".test.",
44
- ".spec."
45
- ];
46
- //#endregion
47
9
  //#region src/build-start.ts
48
10
  /**
49
11
  * buildStart: load the system, discover and ingest sources (local +
@@ -70,51 +32,22 @@ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
70
32
  ctx.log(`System loaded: ${propCount} props, ${groupCount} groups (${Math.round(performance.now() - t0)}ms)`);
71
33
  }
72
34
  t0 = performance.now();
73
- const excludePatterns = ctx.options.exclude ?? DEFAULT_EXCLUDE;
35
+ ctx.excludeMatcher = (0, _animus_ui_extract_pipeline.createExcludeMatcher)(ctx.options.exclude);
36
+ const excludePatterns = ctx.excludeMatcher;
74
37
  ctx.extensionsSet = new Set(ctx.options.extensions ?? _animus_ui_extract_pipeline.DEFAULT_EXTENSIONS);
75
- const shouldHandleMdx = ctx.extensionsSet.has(".mdx");
76
- let mdxMissingDepWarned = false;
77
- const preprocessMdxEntry = async (source, relPath) => {
78
- const result = await (0, _animus_ui_extract_pipeline.preprocessMdx)(source, relPath);
79
- if (result.kind === "missing-dep") {
80
- if (!mdxMissingDepWarned) {
81
- ctx.warn("⚠ .mdx in extensions but @mdx-js/mdx not installed; MDX files skipped");
82
- mdxMissingDepWarned = true;
83
- }
84
- return null;
85
- }
86
- if (result.kind === "error") {
87
- ctx.warn(`⚠ MDX preprocessing failed for ${relPath}: ${result.error}`);
88
- return null;
89
- }
90
- return {
91
- source: result.source,
92
- relPath: relPath + ".tsx"
93
- };
94
- };
95
38
  const filePaths = (0, _animus_ui_extract_pipeline.discoverFiles)(ctx.rootDir, ctx.rootDir, excludePatterns, ctx.extensionsSet);
96
- const fileEntries = [];
39
+ const rawEntries = [];
97
40
  for (const filePath of filePaths) try {
98
- let source = (0, fs.readFileSync)(filePath, "utf-8");
99
- let relPath = (0, path.relative)(ctx.rootDir, filePath);
100
- if (shouldHandleMdx && (0, path.extname)(filePath) === ".mdx") {
101
- const processed = await preprocessMdxEntry(source, relPath);
102
- if (!processed) continue;
103
- source = processed.source;
104
- relPath = processed.relPath;
105
- }
41
+ const source = (0, fs.readFileSync)(filePath, "utf-8");
42
+ const relPath = (0, path.relative)(ctx.rootDir, filePath);
106
43
  const hash = !ctx.isProd ? (0, _animus_ui_extract_pipeline.contentHash)(source) : void 0;
107
- fileEntries.push({
44
+ rawEntries.push({
108
45
  path: relPath,
109
46
  source,
110
47
  hash
111
48
  });
112
- if (!ctx.isProd && hash) ctx.fileCache.set(relPath, {
113
- hash,
114
- source
115
- });
116
49
  } catch {}
117
- const localFileCount = fileEntries.length;
50
+ const localFileCount = rawEntries.length;
118
51
  const packageSpecifiers = (0, _animus_ui_extract_pipeline.extractSystemFilePackages)(ctx.resolvedSystemPath);
119
52
  ctx.externalSourceEntries.clear();
120
53
  ctx.externalKeyframesScanEntries.clear();
@@ -123,14 +56,7 @@ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
123
56
  resolveSpecifier,
124
57
  rootDir: ctx.rootDir,
125
58
  extensionsSet: ctx.extensionsSet,
126
- hasEntry: (relPath) => fileEntries.some((e) => e.path === relPath),
127
- preprocessFile: async (source, relPath, absPath) => {
128
- if (shouldHandleMdx && (0, path.extname)(absPath) === ".mdx") return preprocessMdxEntry(source, relPath);
129
- return {
130
- source,
131
- relPath
132
- };
133
- },
59
+ hasEntry: (relPath) => rawEntries.some((entry) => entry.path === relPath),
134
60
  onUnreadable: (relPath, err) => ctx.warn(`skipped unreadable package file ${relPath}: ${String(err)}`)
135
61
  });
136
62
  ctx.packageMap = collected.packageMap;
@@ -142,23 +68,27 @@ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
142
68
  for (const [specifier, scanEntry] of collected.keyframesScanEntries) ctx.externalKeyframesScanEntries.set(specifier, scanEntry);
143
69
  for (const entry of collected.entries) {
144
70
  const hash = !ctx.isProd ? (0, _animus_ui_extract_pipeline.contentHash)(entry.source) : void 0;
145
- fileEntries.push({
71
+ rawEntries.push({
146
72
  path: entry.path,
147
73
  source: entry.source,
148
74
  hash
149
75
  });
150
- if (!ctx.isProd && hash) ctx.fileCache.set(entry.path, {
151
- hash,
152
- source: entry.source
153
- });
154
76
  }
155
77
  ctx.externalPackageDirs = collected.packageDirs;
156
78
  ctx.registerSystemWatchPaths();
157
79
  ctx.applyExternalKeyframes();
158
- const packageFileCount = fileEntries.length - localFileCount;
159
- ctx.log(`Discovered ${fileEntries.length} files (${packageFileCount} from packages) (${Math.round(performance.now() - t0)}ms)`);
80
+ const packageFileCount = rawEntries.length - localFileCount;
81
+ ctx.log(`Discovered ${rawEntries.length} files (${packageFileCount} from packages) (${Math.round(performance.now() - t0)}ms)`);
160
82
  t0 = performance.now();
161
- ctx.runAnalysis(fileEntries);
83
+ await ctx.analyzeIngested({
84
+ rawEntries,
85
+ beforeAnalysis: (accepted) => {
86
+ if (!ctx.isProd) ctx.fileCache = new Map(accepted.originalEntries.map((entry) => [entry.path, {
87
+ hash: entry.hash,
88
+ source: entry.source
89
+ }]));
90
+ }
91
+ });
162
92
  const assetSpecifiers = (0, _animus_ui_extract_pipeline.findAssetSpecifiers)(ctx.globalCss);
163
93
  for (const specifier of assetSpecifiers) {
164
94
  const resolvedPath = await resolveSpecifier(specifier);
@@ -217,6 +147,7 @@ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
217
147
  */
218
148
  function applyResolvedConfig(ctx, config) {
219
149
  ctx.isProd = config.command === "build";
150
+ ctx.emissionProd = (0, _animus_ui_extract_pipeline.resolveMode)(ctx.options.mode, () => config.command === "build" ? "production" : "development").mode === "production";
220
151
  ctx.rootDir = config.root;
221
152
  ctx.logger = config.logger;
222
153
  ctx.base = config.base ?? "/";
@@ -245,6 +176,38 @@ function applyResolvedConfig(ctx, config) {
245
176
  }
246
177
  }
247
178
  //#endregion
179
+ //#region src/constants.ts
180
+ /**
181
+ * The namespace every virtual module this plugin owns lives under. Exported so
182
+ * the `transform` guard that keeps those modules out of source-file handling
183
+ * matches on the same string the ids are built from — a rename of the
184
+ * namespace cannot leave the guard behind.
185
+ */
186
+ const VIRTUAL_PREFIX = "virtual:animus/";
187
+ const VIRTUAL_CSS_ID = `${VIRTUAL_PREFIX}styles.css`;
188
+ const RESOLVED_CSS_ID = `\0${VIRTUAL_CSS_ID}`;
189
+ const VIRTUAL_COMPONENTS_ID = `${VIRTUAL_PREFIX}components.js`;
190
+ const RESOLVED_COMPONENTS_ID = `\0${VIRTUAL_COMPONENTS_ID}`;
191
+ const VIRTUAL_BRIDGE_ID = `${VIRTUAL_PREFIX}hmr-bridge.js`;
192
+ const RESOLVED_BRIDGE_ID = `\0${VIRTUAL_BRIDGE_ID}`;
193
+ /**
194
+ * Browser-addressable URL for the bridge, used as the `src` of the dev
195
+ * `<script type="module">` (see index-html.ts). THE explanation of the `/@id/`
196
+ * convention lives here; everything else points at it.
197
+ *
198
+ * Vite reserves `/@id/` for module ids that are not file paths. Its transform
199
+ * middleware normalizes such a URL before serving it (`unwrapId`): strip the
200
+ * prefix, then decode the `__x00__` placeholder back to a NUL byte. The
201
+ * UNPREFIXED specifier is what travels here — `resolveVirtualId` is the hook
202
+ * that answers it, and it answers with the `\0` form. (Vite's own `wrapId`
203
+ * encodes an already-`\0`-prefixed id as `__x00__`; that form resolves too, but
204
+ * it leans on the placeholder convention rather than on this plugin's own
205
+ * `resolveId` contract.)
206
+ */
207
+ const BRIDGE_SCRIPT_SRC = `/@id/${VIRTUAL_BRIDGE_ID}`;
208
+ const VIRTUAL_SYSTEM_PROPS_ID = `${VIRTUAL_PREFIX}system-props`;
209
+ const RESOLVED_SYSTEM_PROPS_ID = `\0${VIRTUAL_SYSTEM_PROPS_ID}`;
210
+ //#endregion
248
211
  //#region src/hot-update-events.ts
249
212
  /**
250
213
  * Once-per-file-event coordination across the `hotUpdate` dispatches.
@@ -298,6 +261,44 @@ function eventKey(file, timestamp) {
298
261
  return `${file}\u0000${timestamp}`;
299
262
  }
300
263
  //#endregion
264
+ //#region src/module-invalidation.ts
265
+ /**
266
+ * Evict every module node the dev server holds for each file — every
267
+ * environment graph (client, ssr, and any custom environment), by-file node
268
+ * sets (covers query-suffixed variants), plus the absolute-path id lookup.
269
+ * Falls back to the mixed compat graph for hosts without environment
270
+ * graphs. Returns the number of nodes invalidated.
271
+ *
272
+ * Completeness here is load-bearing: the file-plan diff is the ONLY
273
+ * invalidation candidate source, so a node shape this enumeration misses
274
+ * stays stale for the life of the server (openspec: dev-transform-coherence,
275
+ * "Client and SSR nodes are both evicted").
276
+ */
277
+ function invalidateFileModules(ctx, relPaths) {
278
+ const server = ctx.devServer;
279
+ if (!server || relPaths.length === 0) return 0;
280
+ const graphs = server.environments ? Object.values(server.environments).map((env) => env?.moduleGraph).filter(Boolean) : [server.moduleGraph].filter(Boolean);
281
+ let total = 0;
282
+ for (const relPath of relPaths) {
283
+ const absPath = (0, path.resolve)(ctx.rootDir, relPath);
284
+ let fileCount = 0;
285
+ for (const graph of graphs) {
286
+ const nodes = /* @__PURE__ */ new Set();
287
+ const byFile = graph.getModulesByFile?.(absPath);
288
+ if (byFile) for (const mod of byFile) nodes.add(mod);
289
+ const byId = graph.getModuleById?.(absPath);
290
+ if (byId) nodes.add(byId);
291
+ for (const mod of nodes) {
292
+ graph.invalidateModule(mod);
293
+ fileCount++;
294
+ }
295
+ }
296
+ if (fileCount > 0) ctx.log(`HMR invalidate: ${relPath} (plan changed, ${fileCount} nodes)`);
297
+ total += fileCount;
298
+ }
299
+ return total;
300
+ }
301
+ //#endregion
301
302
  //#region src/reset-coalescer.ts
302
303
  /**
303
304
  * Coalesces bursts of system-dependency events into single geological
@@ -326,11 +327,12 @@ var ResetCoalescer = class {
326
327
  return;
327
328
  }
328
329
  if (this.timer !== null) this.cancel(this.timer);
329
- this.timer = this.schedule(() => {
330
+ this.timer = this.schedule(async () => {
330
331
  this.timer = null;
331
332
  this.running = true;
332
333
  try {
333
- this.run();
334
+ const result = this.run();
335
+ if (result instanceof Promise) await result;
334
336
  } catch (err) {
335
337
  this.onError(err);
336
338
  } finally {
@@ -359,21 +361,22 @@ function emptySystemConfig() {
359
361
  keyframesJson: null
360
362
  };
361
363
  }
362
- /**
363
- * Reconstruct file entries from cache, including content hashes.
364
- * For unchanged files (hash matches changedPath), sends empty source
365
- * to avoid serializing full source text across the NAPI boundary.
366
- * The engine adapter's `rehydrateFilesJson` refills empty sources from
367
- * this same cache before analyze.
368
- */
369
- function buildFileEntriesFromCache(cache, changedPath) {
370
- const entries = [];
371
- for (const [path$1, { hash, source }] of cache) entries.push({
364
+ /** Full raw originals for one adaptation attempt. */
365
+ function buildRawEntriesFromCache(cache) {
366
+ return [...cache].map(([path$1, { hash, source }]) => ({
372
367
  path: path$1,
373
- source: path$1 === changedPath ? source : "",
368
+ source,
374
369
  hash
375
- });
376
- return entries;
370
+ }));
371
+ }
372
+ const analysisChains = /* @__PURE__ */ new WeakMap();
373
+ /** Run `task` after every previously scheduled analysis transaction for
374
+ * this context. Entry points only (transform detection, hot update,
375
+ * geological reset); helpers they call internally must stay unlocked. */
376
+ function runExclusiveAnalysis(ctx, task) {
377
+ const result = (analysisChains.get(ctx) ?? Promise.resolve()).then(task);
378
+ analysisChains.set(ctx, result.then(() => void 0, () => void 0));
379
+ return result;
377
380
  }
378
381
  /** Generate the module from the four inputs the context currently holds. */
379
382
  function generateSystemPropsModule(ctx) {
@@ -398,16 +401,14 @@ function systemPropsModuleSource(ctx) {
398
401
  return ctx.systemPropsModuleMemo ??= generateSystemPropsModule(ctx);
399
402
  }
400
403
  /**
401
- * Drop a deleted (or renamed-away) file from the dev file cache so its
402
- * last-known source stops riding along as a ghost entry on every later
403
- * re-analysis. Both key forms are tried: the plain rootDir-relative path, and
404
- * the `.tsx` suffix MDX sources carry after preprocessing. External package
405
- * entries are rootDir-relative too (with leading `..` segments) and prune the
406
- * same way. Returns whether an entry was actually removed.
404
+ * Drop a deleted (or renamed-away) raw original from the dev file cache.
405
+ * Generated MDX/Svelte children live in `analysisEntryCache` and disappear
406
+ * atomically when the next source-ingestion result publishes. External
407
+ * package entries are rootDir-relative too (with leading `..` segments).
407
408
  */
408
409
  function pruneFileCache(cache, rootDir, absPath) {
409
410
  const rel = (0, path.relative)(rootDir, (0, path.resolve)(absPath));
410
- return cache.delete(rel) || cache.delete(rel + ".tsx");
411
+ return cache.delete(rel);
411
412
  }
412
413
  /**
413
414
  * Per-plugin-instance state and the pipeline operations over it. Hook
@@ -425,6 +426,10 @@ var PluginContext = class {
425
426
  /** Serialized staticCss forced-emission declarations (stable key order). */
426
427
  staticCssJson;
427
428
  isProd = false;
429
+ /** Emission-mode signal (explicit `mode` option wins over the command);
430
+ * feeds engine devMode and the minify default. Lifecycle stays on
431
+ * `isProd`. */
432
+ emissionProd = false;
428
433
  rootDir = "";
429
434
  logger = null;
430
435
  /** System-derived config (shared SystemConfig shape). */
@@ -432,6 +437,7 @@ var PluginContext = class {
432
437
  lcssTargets = {};
433
438
  pathAliasesJson = null;
434
439
  extensionsSet;
440
+ excludeMatcher;
435
441
  storedManifest = null;
436
442
  storedManifestJson = "";
437
443
  globalCss = "";
@@ -478,6 +484,9 @@ var PluginContext = class {
478
484
  storedTransformsSource = "{}";
479
485
  systemPropsModuleMemo = null;
480
486
  fileCache = /* @__PURE__ */ new Map();
487
+ analysisEntryCache = /* @__PURE__ */ new Map();
488
+ sourceOwnership = {};
489
+ analysisOwnerByPath = /* @__PURE__ */ new Map();
481
490
  rawExtensionFallbacks = /* @__PURE__ */ new Set();
482
491
  hotUpdateEvents = new HotUpdateEvents();
483
492
  pendingReloadTimer = null;
@@ -506,6 +515,7 @@ var PluginContext = class {
506
515
  this.staticCssJson = (0, _animus_ui_extract_pipeline.serializeStaticCss)(options.staticCss);
507
516
  this.verbose = options.verbose || process.env.ANIMUS_DEBUG === "1" || process.env.ANIMUS_DEBUG === "true";
508
517
  this.extensionsSet = new Set(options.extensions ?? _animus_ui_extract_pipeline.DEFAULT_EXTENSIONS);
518
+ this.excludeMatcher = (0, _animus_ui_extract_pipeline.createExcludeMatcher)(options.exclude);
509
519
  if (engineApiOverride) {
510
520
  this.engineApi = engineApiOverride;
511
521
  return;
@@ -518,7 +528,7 @@ var PluginContext = class {
518
528
  rehydrateFilesJson: (filesJsonRaw) => {
519
529
  if (!filesJsonRaw.includes("\"source\":\"\"")) return filesJsonRaw;
520
530
  const entries = JSON.parse(filesJsonRaw);
521
- for (const entry of entries) if (entry.source === "") entry.source = this.fileCache.get(entry.path)?.source ?? "";
531
+ for (const entry of entries) if (entry.source === "") entry.source = this.analysisEntryCache.get(entry.path)?.source ?? "";
522
532
  return JSON.stringify(entries);
523
533
  },
524
534
  store: {
@@ -605,13 +615,13 @@ var PluginContext = class {
605
615
  packageMap: this.packageMap,
606
616
  system: this.system,
607
617
  emitter: {
608
- runtimeImport: "@animus-ui/system",
618
+ runtimeImport: this.options.runtimeImport ?? "@animus-ui/system",
609
619
  cssModuleId: VIRTUAL_CSS_ID
610
620
  },
611
621
  pathAliasesJson: this.pathAliasesJson,
612
622
  staticCssJson: this.staticCssJson,
613
623
  externalDirs: this.externalPackageDirs.map((dir) => (0, path.relative)(this.rootDir, dir)),
614
- devMode: !this.isProd,
624
+ devMode: !this.emissionProd,
615
625
  warn: (m) => this.warn(m),
616
626
  strict: this.options.strict,
617
627
  extraDiagnostics: this.externalKeyframesDiagnostics
@@ -622,6 +632,7 @@ var PluginContext = class {
622
632
  return false;
623
633
  }
624
634
  (0, _animus_ui_extract_pipeline.assertNoErrorDiagnostics)(result.manifest?.diagnostics);
635
+ this.assertRuntimeImportSuppliesTerminals(result.manifest);
625
636
  this.storedManifest = result.manifest;
626
637
  this.storedManifestJson = result.manifestJson;
627
638
  this.storedSystemPropMapJson = JSON.stringify(result.manifest?.system_prop_map ?? {});
@@ -632,9 +643,88 @@ var PluginContext = class {
632
643
  this.resolvedComponentCss = result.componentCss;
633
644
  this.systemPropsModuleMemo = generateSystemPropsModule(this);
634
645
  this.applyAssetSubstitutions();
635
- this.enforceExternalTokenContracts();
636
646
  return true;
637
647
  }
648
+ /**
649
+ * `runtimeImport` swaps ONE module specifier under every generated
650
+ * factory import, and the engine performs no export validation — an
651
+ * override that supplies only `createClassResolver` (the documented
652
+ * class-resolver entry contract) breaks the bundle at LOAD the moment any
653
+ * non-`.asClass()` terminal exists, with the error pointing at generated
654
+ * code. Guaranteed-broken output escalates in every mode, exactly like
655
+ * error diagnostics (extraction-diagnostics §Error diagnostics fail the
656
+ * build), naming the offending components instead of the import site.
657
+ */
658
+ assertRuntimeImportSuppliesTerminals(manifest) {
659
+ const override = this.options.runtimeImport;
660
+ if (!override || override === "@animus-ui/system") return;
661
+ const offenders = [];
662
+ for (const [id, descriptor] of Object.entries(manifest?.components ?? {})) {
663
+ const replacement = String(descriptor?.replacement ?? "");
664
+ if (/\bcreateComponent\(|\bcreateComposedFamily\(/.test(replacement)) offenders.push(id);
665
+ }
666
+ if (offenders.length === 0) return;
667
+ const shown = offenders.slice(0, 5).join(", ");
668
+ throw new Error(`[animus-extract] runtimeImport '${override}' is valid only when every extracted terminal is .asClass(), but ${offenders.length} component(s) need createComponent/createComposedFamily from the default '@animus-ui/system' runtime: ${shown}` + (offenders.length > 5 ? ", …" : "") + `. Remove the override or convert these terminals to .asClass().`);
669
+ }
670
+ /** The shared ingestion policy point — capability guard, facts memo, and
671
+ * warn-dedupe lifecycle all live in the pipeline, not per host. */
672
+ sourceIngestor = (0, _animus_ui_extract_pipeline.createSourceIngestor)({
673
+ engineApi: () => this.engineApi(),
674
+ prefix: "[animus-extract]",
675
+ strict: () => !!this.options.strict,
676
+ warn: (message) => this.warn(message)
677
+ });
678
+ /** Prepare one raw-source corpus through the shared adaptation boundary. */
679
+ async ingestRawSources(fileEntries) {
680
+ return this.sourceIngestor.ingest(fileEntries);
681
+ }
682
+ /** Surface adapter diagnostics under the shared strict/warn policy. */
683
+ surfaceSourceDiagnostics(diagnostics) {
684
+ return this.sourceIngestor.surfaceDiagnostics(diagnostics);
685
+ }
686
+ /**
687
+ * The one ingest → quarantine → analyze → publish transaction, shared by
688
+ * buildStart and every incremental path. Per-file quarantine: one invalid
689
+ * original warns and drops without aborting the rest of the corpus
690
+ * (strict mode throws from the shared policy). `runAnalysis(...) !==
691
+ * false` is the documented success contract (a `void` behavioral test
692
+ * double reads as success), and the accepted corpus publishes only on
693
+ * success. `beforeAnalysis` runs between quarantine and analysis for the
694
+ * two sites with a documented ordering constraint: buildStart's dev-cache
695
+ * seed must survive a strict analysis throw, and the geological reset
696
+ * clears the engine cache only after strict ingestion diagnostics had
697
+ * their chance to throw.
698
+ */
699
+ async analyzeIngested(options) {
700
+ const ingested = await this.ingestRawSources(options?.rawEntries ?? buildRawEntriesFromCache(this.fileCache));
701
+ const accepted = (0, _animus_ui_extract_pipeline.withoutInvalidOriginals)(ingested, this.surfaceSourceDiagnostics(ingested.diagnostics));
702
+ options?.beforeAnalysis?.(accepted);
703
+ const ok = this.runAnalysis(accepted.analysisEntries) !== false;
704
+ if (ok) this.publishSourceIngestion(accepted);
705
+ return {
706
+ ok,
707
+ accepted
708
+ };
709
+ }
710
+ /** Publish every parser child and ownership edge atomically after analysis. */
711
+ publishSourceIngestion(result) {
712
+ this.sourceIngestor.markPublished(result);
713
+ const priorAnalysisPaths = new Set(this.analysisOwnerByPath.keys());
714
+ this.analysisEntryCache = new Map(result.analysisEntries.map((entry) => [entry.path, {
715
+ hash: entry.hash,
716
+ source: entry.source
717
+ }]));
718
+ this.sourceOwnership = result.ownership;
719
+ this.analysisOwnerByPath = /* @__PURE__ */ new Map();
720
+ for (const owner of Object.values(result.ownership)) for (const analysisPath of owner.analysisPaths) {
721
+ this.analysisOwnerByPath.set(analysisPath, owner.originalPath);
722
+ const externalOwner = this.externalFileOwners[owner.originalPath];
723
+ if (externalOwner) this.externalFileOwners[analysisPath] = externalOwner;
724
+ }
725
+ for (const stalePath of priorAnalysisPaths) if (!this.analysisOwnerByPath.has(stalePath)) delete this.externalFileOwners[stalePath];
726
+ this.enforceExternalTokenContracts();
727
+ }
638
728
  /** Base-prefixed dev URL for an absolute file (Vite mounts /@fs under base). */
639
729
  devFsUrl(absPath) {
640
730
  return `${this.base.endsWith("/") ? this.base.slice(0, -1) : this.base}/@fs${absPath}`;
@@ -677,7 +767,7 @@ var PluginContext = class {
677
767
  */
678
768
  requestGeologicalReset(trigger) {
679
769
  this.log(`HMR geological reset scheduled: ${trigger}`);
680
- this.resetCoalescer ??= new ResetCoalescer(() => this.performGeologicalReset(), (err) => this.geologicalResetFailed(err));
770
+ this.resetCoalescer ??= new ResetCoalescer(async () => this.performGeologicalReset(), (err) => this.geologicalResetFailed(err));
681
771
  this.resetCoalescer.request();
682
772
  }
683
773
  /**
@@ -707,18 +797,23 @@ var PluginContext = class {
707
797
  * sources, then invalidate the static/component/system-prop virtual
708
798
  * modules and reload the client.
709
799
  */
710
- performGeologicalReset() {
800
+ async performGeologicalReset() {
801
+ return runExclusiveAnalysis(this, () => this.performGeologicalResetExclusive());
802
+ }
803
+ async performGeologicalResetExclusive() {
711
804
  const resetStart = performance.now();
712
- this.loadSystem();
713
- (0, _animus_ui_extract_pipeline.clearEngineCache)(this.engineApi);
714
- const fileEntries = [];
715
- for (const [path$2, { hash, source }] of this.fileCache) fileEntries.push({
716
- path: path$2,
717
- source,
718
- hash
719
- });
720
- this.runAnalysis(fileEntries);
721
- this.log(`HMR geological reset complete: ${Math.round(performance.now() - resetStart)}ms`);
805
+ const prevPlans = (0, _animus_ui_extract_pipeline.snapshotFilePlans)(this.storedManifest);
806
+ try {
807
+ this.loadSystem();
808
+ const { ok } = await this.analyzeIngested({ beforeAnalysis: () => (0, _animus_ui_extract_pipeline.clearEngineCache)(this.engineApi) });
809
+ if (!ok) return;
810
+ invalidateFileModules(this, (0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(this.storedManifest)));
811
+ this.log(`HMR geological reset complete: ${Math.round(performance.now() - resetStart)}ms`);
812
+ } finally {
813
+ this.invalidateGeologicalResetModules();
814
+ }
815
+ }
816
+ invalidateGeologicalResetModules() {
722
817
  const server = this.devServer;
723
818
  if (!server) return;
724
819
  for (const moduleId of [
@@ -824,23 +919,14 @@ var PluginContext = class {
824
919
  });
825
920
  }
826
921
  runSelfVerify() {
827
- const failures = [];
828
- if (Object.keys(this.storedManifest?.components ?? {}).length === 0) failures.push("No component CSS produced — check the system file and its includes list");
829
- for (const { specifier, outcome } of this.externalPackageOutcomes) if (outcome === "empty") failures.push(`include '${specifier}' resolved but discovered no component sources`);
830
- else if (outcome === "unresolvable") failures.push(`include '${specifier}' could not be resolved`);
831
- if (!this.system.variableCss.includes(":root")) failures.push("No :root variable block found in variable CSS");
832
- if (`${this.system.variableCss}\n${this.globalCss}\n${this.resolvedComponentCss}`.includes("__TRANSFORM__")) failures.push("Unresolved __TRANSFORM__ placeholders found in CSS output");
833
- if (this.storedManifest && this.resolvedComponentCss.length > 0) {
834
- const assembled = (0, _animus_ui_extract_pipeline.assembleStylesheet)({
835
- layers: this.options.layers,
836
- variableCss: this.system.variableCss,
837
- globalCss: this.globalCss,
838
- componentCss: this.resolvedComponentCss
839
- });
840
- const baseIdx = assembled.search(/@layer\s+anm-base\s*\{/);
841
- const variantsIdx = assembled.search(/@layer\s+anm-variants\s*\{/);
842
- if (baseIdx !== -1 && variantsIdx !== -1 && baseIdx >= variantsIdx) failures.push(`CSS layer ordering violated — @layer anm-base (offset ${baseIdx}) must precede @layer anm-variants (offset ${variantsIdx})`);
843
- }
922
+ const failures = (0, _animus_ui_extract_pipeline.runStructuralSelfCheck)({
923
+ componentCount: Object.keys(this.storedManifest?.components ?? {}).length,
924
+ variableCss: this.system.variableCss,
925
+ globalCss: this.globalCss,
926
+ componentCss: this.resolvedComponentCss,
927
+ layers: this.options.layers,
928
+ externalOutcomes: this.externalPackageOutcomes
929
+ });
844
930
  for (const message of failures) {
845
931
  const line = `[animus:verify] ${message}`;
846
932
  if (this.options.strict) throw new Error(line);
@@ -851,44 +937,6 @@ var PluginContext = class {
851
937
  }
852
938
  };
853
939
  //#endregion
854
- //#region src/module-invalidation.ts
855
- /**
856
- * Evict every module node the dev server holds for each file — every
857
- * environment graph (client, ssr, and any custom environment), by-file node
858
- * sets (covers query-suffixed variants), plus the absolute-path id lookup.
859
- * Falls back to the mixed compat graph for hosts without environment
860
- * graphs. Returns the number of nodes invalidated.
861
- *
862
- * Completeness here is load-bearing: the file-plan diff is the ONLY
863
- * invalidation candidate source, so a node shape this enumeration misses
864
- * stays stale for the life of the server (openspec: dev-transform-coherence,
865
- * "Client and SSR nodes are both evicted").
866
- */
867
- function invalidateFileModules(ctx, relPaths) {
868
- const server = ctx.devServer;
869
- if (!server || relPaths.length === 0) return 0;
870
- const graphs = server.environments ? Object.values(server.environments).map((env) => env?.moduleGraph).filter(Boolean) : [server.moduleGraph].filter(Boolean);
871
- let total = 0;
872
- for (const relPath of relPaths) {
873
- const absPath = (0, path.resolve)(ctx.rootDir, relPath);
874
- let fileCount = 0;
875
- for (const graph of graphs) {
876
- const nodes = /* @__PURE__ */ new Set();
877
- const byFile = graph.getModulesByFile?.(absPath);
878
- if (byFile) for (const mod of byFile) nodes.add(mod);
879
- const byId = graph.getModuleById?.(absPath);
880
- if (byId) nodes.add(byId);
881
- for (const mod of nodes) {
882
- graph.invalidateModule(mod);
883
- fileCount++;
884
- }
885
- }
886
- if (fileCount > 0) ctx.log(`HMR invalidate: ${relPath} (plan changed, ${fileCount} nodes)`);
887
- total += fileCount;
888
- }
889
- return total;
890
- }
891
- //#endregion
892
940
  //#region src/rediscovery.ts
893
941
  /** The current manifest's unresolved-parent drops, parsed from diagnostics
894
942
  * (shared Rust-mirror matcher — the regex lives in manifest-diagnostics). */
@@ -934,15 +982,11 @@ function unresolvedDropFiles(ctx) {
934
982
  * walk actually folded something (a changed discovery domain). The
935
983
  * iteration cap is containment, not semantics.
936
984
  *
937
- * Synchronous by design — it runs inside the sync `transform` hook. `.mdx`
938
- * sources need async preprocessing and are not folded here (they ingest on
939
- * their first watcher edit).
940
- *
941
985
  * Returns whether any re-analysis ran (callers diff plans across the WHOLE
942
986
  * transaction, so a fold-and-reanalyze is invisible to them beyond the
943
987
  * final manifest).
944
988
  */
945
- function stabilizeSourceUniverse(ctx) {
989
+ async function stabilizeSourceUniverse(ctx) {
946
990
  if (ctx.isProd) return false;
947
991
  let reanalyzed = false;
948
992
  for (let iteration = 0; iteration < 3; iteration++) {
@@ -968,7 +1012,7 @@ function stabilizeSourceUniverse(ctx) {
968
1012
  reanalyzed = true;
969
1013
  let published = false;
970
1014
  try {
971
- published = ctx.runAnalysis(buildFileEntriesFromCache(ctx.fileCache)) !== false;
1015
+ published = (await ctx.analyzeIngested()).ok;
972
1016
  } finally {
973
1017
  if (!published) for (const key of folded) ctx.fileCache.delete(key);
974
1018
  }
@@ -987,8 +1031,8 @@ function stabilizeSourceUniverse(ctx) {
987
1031
  * restore it, or the content-hash gate suppresses the equal-content retry
988
1032
  * forever. */
989
1033
  function foldUndiscoveredFiles(ctx) {
990
- const excludePatterns = ctx.options.exclude ?? DEFAULT_EXCLUDE;
991
- const filePaths = (0, _animus_ui_extract_pipeline.discoverFiles)(ctx.rootDir, ctx.rootDir, excludePatterns, ctx.extensionsSet);
1034
+ const excludeMatcher = ctx.excludeMatcher;
1035
+ const filePaths = (0, _animus_ui_extract_pipeline.discoverFiles)(ctx.rootDir, ctx.rootDir, excludeMatcher, ctx.extensionsSet);
992
1036
  const folded = [];
993
1037
  for (const filePath of filePaths) {
994
1038
  if ((0, path.extname)(filePath) === ".mdx") continue;
@@ -1031,7 +1075,7 @@ const PARENT_PROBE_EXTENSIONS = new Set([
1031
1075
  * engine's own diagnostic.
1032
1076
  */
1033
1077
  function warnInadmissibleParents(ctx, drops) {
1034
- const excludePatterns = ctx.options.exclude ?? DEFAULT_EXCLUDE;
1078
+ const excludeMatcher = ctx.excludeMatcher;
1035
1079
  let warned = warnedVerdicts.get(ctx);
1036
1080
  if (!warned) {
1037
1081
  warned = /* @__PURE__ */ new Set();
@@ -1047,7 +1091,7 @@ function warnInadmissibleParents(ctx, drops) {
1047
1091
  const resolved = (0, _animus_ui_extract_pipeline.resolveAbsolutePathSpecifier)((0, path.resolve)(ctx.rootDir, (0, path.dirname)(drop.file), specifier), PARENT_PROBE_EXTENSIONS);
1048
1092
  if (!resolved) continue;
1049
1093
  const relPath = (0, path.relative)(ctx.rootDir, resolved);
1050
- const excludedBy = excludePatterns.find((pattern) => resolved.includes(pattern) || relPath.includes(pattern));
1094
+ const excludedBy = excludeMatcher.explain(resolved, relPath);
1051
1095
  const reason = excludedBy ? `which is excluded by pattern '${excludedBy}'. Include that file in the extraction universe or remove this extension.` : !(0, _animus_ui_extract_pipeline.isPathWithinRoot)(ctx.rootDir, resolved) ? "outside the extraction root. Declare its package in the system includes or move it under the project root." : !ctx.extensionsSet.has((0, path.extname)(resolved)) ? `whose extension is not in the configured source extensions.` : null;
1052
1096
  if (reason === null) continue;
1053
1097
  const verdictKey = `${drop.file}\0${drop.parent}\0${reason}`;
@@ -1111,7 +1155,7 @@ function rawFallbackDescendants(ctx, relPath) {
1111
1155
  * dev-stylesheet-management, "HMR bridge auto-injected in dev mode"; "Transform
1112
1156
  * emitter unchanged" forbids the emitter importing it).
1113
1157
  */
1114
- function transformSource(ctx, code, id) {
1158
+ async function transformSource(ctx, code, id) {
1115
1159
  if (!ctx.storedManifest) return null;
1116
1160
  if (id.startsWith("\0") || id.startsWith("virtual:animus/")) return null;
1117
1161
  const isExternalPkg = ctx.externalPackageDirs.some((dir) => (0, _animus_ui_extract_pipeline.isPathWithinRoot)(dir, id));
@@ -1122,7 +1166,8 @@ function transformSource(ctx, code, id) {
1122
1166
  if (!(0, _animus_ui_extract_pipeline.isPathWithinRoot)(ctx.rootDir, id)) return null;
1123
1167
  }
1124
1168
  if (!ctx.storedManifest.files?.[relativePath]?.length) {
1125
- if (!ctx.isProd && !ctx.fileCache.has(relativePath)) {
1169
+ if (!ctx.isProd && !ctx.fileCache.has(relativePath)) await runExclusiveAnalysis(ctx, async () => {
1170
+ if (ctx.fileCache.has(relativePath)) return;
1126
1171
  if (isExternalPkg) {
1127
1172
  const owner = Object.entries(ctx.externalDirOwners).find(([dir]) => (0, _animus_ui_extract_pipeline.isPathWithinRoot)(dir, id));
1128
1173
  if (owner) ctx.externalFileOwners[relativePath] = owner[1];
@@ -1133,21 +1178,20 @@ function transformSource(ctx, code, id) {
1133
1178
  source: code
1134
1179
  });
1135
1180
  const prevPlans = (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest);
1136
- const fileEntries = buildFileEntriesFromCache(ctx.fileCache, relativePath);
1137
1181
  let analysisOk = false;
1138
1182
  try {
1139
- analysisOk = ctx.runAnalysis(fileEntries) !== false;
1183
+ analysisOk = (await ctx.analyzeIngested()).ok;
1140
1184
  } finally {
1141
1185
  if (!analysisOk) ctx.fileCache.delete(relativePath);
1142
1186
  }
1143
1187
  if (analysisOk) {
1144
- stabilizeSourceUniverse(ctx);
1188
+ await stabilizeSourceUniverse(ctx);
1145
1189
  invalidateFileModules(ctx, (0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest), { exclude: relativePath }));
1146
1190
  const compCount = ctx.storedManifest.files?.[relativePath]?.length ?? 0;
1147
1191
  ctx.info(`New file detected: ${relativePath} — ${compCount ? `${compCount} components extracted` : "no components"}`);
1148
1192
  ctx.invalidateExtractedModules();
1149
1193
  }
1150
- }
1194
+ });
1151
1195
  if (!ctx.storedManifest.files?.[relativePath]?.length) {
1152
1196
  if (!ctx.isProd) if (unresolvedDropFiles(ctx).has(relativePath)) ctx.rawExtensionFallbacks.add(relativePath);
1153
1197
  else ctx.rawExtensionFallbacks.delete(relativePath);
@@ -1208,8 +1252,11 @@ function transformSource(ctx, code, id) {
1208
1252
  * graph, so system dependencies registered through `watcher.add` outside the
1209
1253
  * root still reach the reset branch, with an empty `modules` list.
1210
1254
  */
1211
- async function handleHotUpdate(ctx, environment, { type, file, timestamp, modules, read }) {
1255
+ async function handleHotUpdate(ctx, environment, options) {
1212
1256
  if (ctx.isProd) return;
1257
+ return runExclusiveAnalysis(ctx, () => handleHotUpdateExclusive(ctx, environment, options));
1258
+ }
1259
+ async function handleHotUpdateExclusive(ctx, environment, { type, file, timestamp, modules, read }) {
1213
1260
  const ownsEvent = ctx.hotUpdateEvents.claim(environment.name, file, timestamp);
1214
1261
  const absFile = (0, path.resolve)(file);
1215
1262
  ctx.log(`hotUpdate ${type} ${(0, path.relative)(ctx.rootDir, absFile)} env=${environment.name} owns=${ownsEvent}`);
@@ -1221,7 +1268,7 @@ async function handleHotUpdate(ctx, environment, { type, file, timestamp, module
1221
1268
  return [];
1222
1269
  }
1223
1270
  if (type === "delete") {
1224
- if (ownsEvent) pruneDeletedFile(ctx, absFile);
1271
+ if (ownsEvent) await pruneDeletedFile(ctx, absFile);
1225
1272
  return;
1226
1273
  }
1227
1274
  if (ownsEvent) ctx.hotUpdateEvents.record(file, timestamp, await analyzeChangedFile(ctx, file, absFile, read));
@@ -1292,9 +1339,9 @@ async function reconcileSourceEntry(ctx, absFile, type, read) {
1292
1339
  async function analyzeChangedFile(ctx, file, absFile, read) {
1293
1340
  const ext = (0, path.extname)(file);
1294
1341
  if (!ctx.extensionsSet.has(ext)) return { kind: "ignored" };
1295
- const excludePatterns = ctx.options.exclude ?? DEFAULT_EXCLUDE;
1342
+ const excludeMatcher = ctx.excludeMatcher;
1296
1343
  const isExternalPkg = ctx.externalPackageDirs.some((dir) => (0, _animus_ui_extract_pipeline.isPathWithinRoot)(dir, file));
1297
- if (!isExternalPkg && excludePatterns.some((pattern) => file.includes(pattern) || (0, path.relative)(ctx.rootDir, file).includes(pattern))) return { kind: "ignored" };
1344
+ if (!isExternalPkg && excludeMatcher.matches(file, (0, path.relative)(ctx.rootDir, file))) return { kind: "ignored" };
1298
1345
  const relPath = (0, path.relative)(ctx.rootDir, absFile);
1299
1346
  let source;
1300
1347
  try {
@@ -1302,41 +1349,30 @@ async function analyzeChangedFile(ctx, file, absFile, read) {
1302
1349
  } catch {
1303
1350
  return { kind: "ignored" };
1304
1351
  }
1305
- let scannerRelPath = relPath;
1306
- if (ext === ".mdx") {
1307
- const result = await (0, _animus_ui_extract_pipeline.preprocessMdx)(source, relPath);
1308
- if (result.kind === "missing-dep") {
1309
- ctx.warn("⚠ .mdx HMR skipped: @mdx-js/mdx not installed; restart dev server after installing");
1310
- return { kind: "ignored" };
1311
- }
1312
- if (result.kind === "error") {
1313
- ctx.warn(`⚠ MDX preprocessing failed for ${relPath}: ${result.error}`);
1314
- return { kind: "ignored" };
1315
- }
1316
- source = result.source;
1317
- scannerRelPath = relPath + ".tsx";
1318
- }
1319
1352
  const hash = (0, _animus_ui_extract_pipeline.contentHash)(source);
1320
- const cached = ctx.fileCache.get(scannerRelPath);
1353
+ const cached = ctx.fileCache.get(relPath);
1321
1354
  if (cached && cached.hash === hash) {
1322
- ctx.log(`HMR skip: ${scannerRelPath} (unchanged)`);
1355
+ ctx.log(`HMR skip: ${relPath} (unchanged)`);
1323
1356
  return { kind: "unchanged" };
1324
1357
  }
1325
- if (isExternalPkg && !ctx.externalFileOwners[scannerRelPath]) {
1358
+ const priorExternalOwner = ctx.externalFileOwners[relPath];
1359
+ if (isExternalPkg && !priorExternalOwner) {
1326
1360
  const owner = Object.entries(ctx.externalDirOwners).find(([dir]) => (0, _animus_ui_extract_pipeline.isPathWithinRoot)(dir, absFile));
1327
- if (owner) ctx.externalFileOwners[scannerRelPath] = owner[1];
1361
+ if (owner) ctx.externalFileOwners[relPath] = owner[1];
1328
1362
  }
1329
- ctx.fileCache.set(scannerRelPath, {
1363
+ ctx.fileCache.set(relPath, {
1330
1364
  hash,
1331
1365
  source
1332
1366
  });
1333
1367
  const restoreEntry = () => {
1334
- if (cached) ctx.fileCache.set(scannerRelPath, cached);
1335
- else ctx.fileCache.delete(scannerRelPath);
1368
+ if (cached) ctx.fileCache.set(relPath, cached);
1369
+ else ctx.fileCache.delete(relPath);
1370
+ if (priorExternalOwner) ctx.externalFileOwners[relPath] = priorExternalOwner;
1371
+ else delete ctx.externalFileOwners[relPath];
1336
1372
  };
1337
1373
  const hmrStart = performance.now();
1338
1374
  const prevPlans = (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest);
1339
- const directComponentIds = ctx.storedManifest?.files?.[scannerRelPath] ?? [];
1375
+ const directComponentIds = (ctx.sourceOwnership[relPath]?.analysisPaths ?? [relPath]).flatMap((analysisPath) => ctx.storedManifest?.files?.[analysisPath] ?? []);
1340
1376
  const invalidatedIds = new Set(directComponentIds);
1341
1377
  const queue = [...directComponentIds];
1342
1378
  while (queue.length > 0) {
@@ -1351,11 +1387,10 @@ async function analyzeChangedFile(ctx, file, absFile, read) {
1351
1387
  }
1352
1388
  if (ctx.verbose && invalidatedIds.size > directComponentIds.length) ctx.log(`HMR: ${directComponentIds.length} direct + ${invalidatedIds.size - directComponentIds.length} transitive components invalidated`);
1353
1389
  const analysisStart = performance.now();
1354
- const fileEntries = buildFileEntriesFromCache(ctx.fileCache, relPath);
1355
1390
  const systemPropsBefore = systemPropsModuleSource(ctx);
1356
1391
  let analysisOk;
1357
1392
  try {
1358
- analysisOk = ctx.runAnalysis(fileEntries) !== false;
1393
+ analysisOk = (await ctx.analyzeIngested()).ok;
1359
1394
  } catch (e) {
1360
1395
  restoreEntry();
1361
1396
  throw e;
@@ -1365,7 +1400,7 @@ async function analyzeChangedFile(ctx, file, absFile, read) {
1365
1400
  return { kind: "ignored" };
1366
1401
  }
1367
1402
  try {
1368
- stabilizeSourceUniverse(ctx);
1403
+ await stabilizeSourceUniverse(ctx);
1369
1404
  } catch (e) {
1370
1405
  restoreEntry();
1371
1406
  throw e;
@@ -1373,7 +1408,8 @@ async function analyzeChangedFile(ctx, file, absFile, read) {
1373
1408
  const systemPropsChanged = systemPropsModuleSource(ctx) !== systemPropsBefore;
1374
1409
  const analysisMs = Math.round(performance.now() - analysisStart);
1375
1410
  const staleDefinitionFiles = (0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest)).filter((defFile) => (0, path.resolve)(ctx.rootDir, defFile) !== absFile);
1376
- const presentationOnly = isPresentationOnlyEdit(ctx, scannerRelPath, source);
1411
+ const nativeEntry = ctx.analysisEntryCache.get(relPath);
1412
+ const presentationOnly = nativeEntry ? isPresentationOnlyEdit(ctx, relPath, nativeEntry.source) : false;
1377
1413
  const hmrMs = Math.round(performance.now() - hmrStart);
1378
1414
  ctx.log(`HMR update: ${relPath} — analysis ${analysisMs}ms, total ${hmrMs}ms${presentationOnly ? " (presentation-only)" : ""}`);
1379
1415
  ctx.logTimingWaterfall(ctx.storedManifest?.timing ?? {});
@@ -1414,16 +1450,18 @@ function isPresentationOnlyEdit(ctx, scannerRelPath, source) {
1414
1450
  * Reconcile a deleted file in dev.
1415
1451
  *
1416
1452
  * Without this the removed file's last-known source stays in `ctx.fileCache`,
1417
- * and `buildFileEntriesFromCache` re-feeds that ghost entry to the engine on
1453
+ * and shared source ingestion re-feeds that ghost original to the engine on
1418
1454
  * every later re-analysis — the deleted component's CSS survives for the life
1419
1455
  * of the process.
1420
1456
  */
1421
- function pruneDeletedFile(ctx, absFile) {
1422
- if (!pruneFileCache(ctx.fileCache, ctx.rootDir, absFile)) return;
1457
+ async function pruneDeletedFile(ctx, absFile) {
1458
+ const relPath = (0, path.relative)(ctx.rootDir, absFile);
1459
+ if (!ctx.fileCache.get(relPath) || !pruneFileCache(ctx.fileCache, ctx.rootDir, absFile)) return;
1423
1460
  const prevPlans = (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest);
1424
- const ok = ctx.runAnalysis(buildFileEntriesFromCache(ctx.fileCache)) !== false;
1461
+ const { ok } = await ctx.analyzeIngested();
1462
+ if (!ok) return;
1425
1463
  ctx.log(`Deleted file pruned: ${(0, path.relative)(ctx.rootDir, absFile)}`);
1426
- if (ok) invalidateFileModules(ctx, (0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest)));
1464
+ invalidateFileModules(ctx, (0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest)));
1427
1465
  ctx.invalidateExtractedModules();
1428
1466
  }
1429
1467
  /**
@@ -1533,7 +1571,7 @@ function resolveVirtualId(ctx, id) {
1533
1571
  * system-props modules from manifest-derived state. */
1534
1572
  function loadVirtualModule(ctx, id) {
1535
1573
  const lcssOpts = {
1536
- minify: ctx.options.minify ?? ctx.isProd,
1574
+ minify: ctx.options.minify ?? ctx.emissionProd,
1537
1575
  targets: ctx.lcssTargets,
1538
1576
  warnFn: (msg) => ctx.warn(msg)
1539
1577
  };
@@ -1618,12 +1656,20 @@ if (import.meta.hot) {
1618
1656
  */
1619
1657
  function animusExtract(options) {
1620
1658
  (0, _animus_ui_extract_pipeline.assertNoRetiredEngineSelection)(options.engine);
1659
+ (0, _animus_ui_extract_pipeline.assertKnownOptionKeys)(options, ["verify", "appearanceBootstrap"], [{
1660
+ key: "root",
1661
+ reason: "the Vite driver derives its root from the resolved Vite config"
1662
+ }], {
1663
+ onUnknownKey: "warn",
1664
+ warn: (message) => console.warn(`[animus-extract] ${message}`)
1665
+ });
1621
1666
  const ctx = new PluginContext(options);
1622
1667
  return {
1623
1668
  name: "animus-extract",
1624
1669
  enforce: "pre",
1625
1670
  config(_config, env) {
1626
- return { define: { __ANIMUS_DEV__: env.command !== "build" } };
1671
+ const { mode } = (0, _animus_ui_extract_pipeline.resolveMode)(options.mode, () => env.command === "build" ? "production" : "development");
1672
+ return { define: { __ANIMUS_DEV__: mode === "development" } };
1627
1673
  },
1628
1674
  configureServer(server) {
1629
1675
  ctx.devServer = server;
package/dist/index.d.ts CHANGED
@@ -9,7 +9,22 @@ export interface AnimusExtractOptions {
9
9
  * and global styles — everything the extraction pipeline needs.
10
10
  */
11
11
  system: string;
12
- /** Glob patterns to exclude. */
12
+ /**
13
+ * Module specifier injected for extracted runtime factories.
14
+ *
15
+ * The default preserves the full `@animus-ui/system` runtime. Override this
16
+ * only when the selected entry supplies every terminal present in the
17
+ * analyzed consumer (for example, the framework-neutral class-resolver
18
+ * entry for a consumer containing only `.asClass()` definitions).
19
+ *
20
+ * @default '@animus-ui/system'
21
+ */
22
+ runtimeImport?: string;
23
+ /**
24
+ * Exclusion patterns (substrings, or globs when `*`/`?` present). When
25
+ * set, REPLACES the replaceable defaults (`dist`, `.test.`, `.spec.`);
26
+ * `node_modules`, `.next`, and `.animus` are always excluded.
27
+ */
13
28
  exclude?: string[];
14
29
  /**
15
30
  * File extensions to scan for component definitions and JSX usages.
@@ -46,6 +61,12 @@ export interface AnimusExtractOptions {
46
61
  * - `undefined` (default): minify in prod only
47
62
  */
48
63
  minify?: boolean;
64
+ /**
65
+ * Explicit dev/prod emission mode. Wins over the Vite command signal.
66
+ * When absent, the documented default applies: production when
67
+ * `config.command === 'build'`, development otherwise.
68
+ */
69
+ mode?: 'development' | 'production';
49
70
  /**
50
71
  * Namespace prefix for CSS variables and class names, applied to the
51
72
  * variable map/css (and theme + contextual vars) at system load.
@@ -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,CA0EnE;eAEc,aAAa"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,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;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,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;;;;OAIG;IACH,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACpC;;;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,CAoGnE;eAEc,aAAa"}
@@ -27,14 +27,10 @@ export declare function unresolvedDropFiles(ctx: PluginContext): ReadonlySet<str
27
27
  * walk actually folded something (a changed discovery domain). The
28
28
  * iteration cap is containment, not semantics.
29
29
  *
30
- * Synchronous by design — it runs inside the sync `transform` hook. `.mdx`
31
- * sources need async preprocessing and are not folded here (they ingest on
32
- * their first watcher edit).
33
- *
34
30
  * Returns whether any re-analysis ran (callers diff plans across the WHOLE
35
31
  * transaction, so a fold-and-reanalyze is invisible to them beyond the
36
32
  * final manifest).
37
33
  */
38
- export declare function stabilizeSourceUniverse(ctx: PluginContext): boolean;
34
+ export declare function stabilizeSourceUniverse(ctx: PluginContext): Promise<boolean>;
39
35
  export {};
40
36
  //# sourceMappingURL=rediscovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rediscovery.d.ts","sourceRoot":"","sources":["../src/rediscovery.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,UAAU,oBAAoB;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;8EAC8E;AAC9E,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,GACjB,oBAAoB,EAAE,CAcxB;AASD;gEACgE;AAChE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAc3E;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CA2EnE"}
1
+ {"version":3,"file":"rediscovery.d.ts","sourceRoot":"","sources":["../src/rediscovery.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,UAAU,oBAAoB;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;8EAC8E;AAC9E,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,GACjB,oBAAoB,EAAE,CAcxB;AASD;gEACgE;AAChE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAc3E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,OAAO,CAAC,CA4ElB"}
@@ -16,7 +16,7 @@ export declare class ResetCoalescer {
16
16
  private timer;
17
17
  private running;
18
18
  private dirty;
19
- constructor(run: () => void, onError: (err: unknown) => void, quietMs?: number, schedule?: (fn: () => void, ms: number) => unknown, cancel?: (timer: unknown) => void);
19
+ constructor(run: () => void | Promise<void>, onError: (err: unknown) => void, quietMs?: number, schedule?: (fn: () => void, ms: number) => unknown, cancel?: (timer: unknown) => void);
20
20
  /** Ask for a reset; bursts within the quiescence window collapse. */
21
21
  request(): void;
22
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;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
+ {"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,GAAG,OAAO,CAAC,IAAI,CAAC,EAK/B,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,CAsBd;CACF"}
@@ -18,8 +18,8 @@ export declare function applyDevBridgeImport(code: string): string;
18
18
  * dev-stylesheet-management, "HMR bridge auto-injected in dev mode"; "Transform
19
19
  * emitter unchanged" forbids the emitter importing it).
20
20
  */
21
- export declare function transformSource(ctx: PluginContext, code: string, id: string): {
21
+ export declare function transformSource(ctx: PluginContext, code: string, id: string): Promise<{
22
22
  code: string;
23
23
  map: null;
24
- } | null;
24
+ } | null>;
25
25
  //# sourceMappingURL=transform.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKzD;AAiCD;;;;;;;;;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,CA4LpC"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKzD;AAiCD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CAAC,CAkM7C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@animus-ui/vite-plugin",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
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.9",
42
+ "@animus-ui/extract": "0.1.11",
43
43
  "browserslist": "^4.24.0",
44
44
  "lightningcss": "^1.29.0"
45
45
  },
@@ -51,5 +51,8 @@
51
51
  "@mdx-js/mdx": {
52
52
  "optional": true
53
53
  }
54
+ },
55
+ "engines": {
56
+ "node": ">=22.12.0"
54
57
  }
55
58
  }