@animus-ui/vite-plugin 0.1.16 → 0.1.18

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":"AAiBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;GAGG;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,CAkNf"}
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;;;GAGG;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,CAmNf"}
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 { ExcludeMatcher, ExternalPackageOutcome, ManifestDiagnostic, ManifestSheets, ProjectManifest, RawSourceEntry, SourceCorpus, SourceIngestionResult, SystemConfig } from '@animus-ui/extract/pipeline';
4
+ import type { ExcludeMatcher, ExternalPackageOutcome, ManifestSheets, ProjectManifest, RawSourceEntry, SourceCorpus, SourceIngestionResult, SystemConfig } from '@animus-ui/extract/pipeline';
5
5
  import type { Logger } from 'vite';
6
6
  /** Runs `task` after every analysis transaction already scheduled for this
7
7
  * context. Entry points only — a nested call waits on its own chain. */
@@ -18,6 +18,8 @@ export declare function pruneFileCache(cache: Map<string, {
18
18
  export declare class PluginContext {
19
19
  readonly options: AnimusExtractOptions;
20
20
  readonly verbose: boolean;
21
+ /** The higher tier: `verbose: 'trace'` or `ANIMUS_DEBUG=trace`. */
22
+ readonly tracing: boolean;
21
23
  readonly staticCssJson: string | null;
22
24
  isProd: boolean;
23
25
  /** Emission mode (the explicit `mode` option wins over the command); feeds
@@ -38,13 +40,11 @@ export declare class PluginContext {
38
40
  layerDeclaration: string;
39
41
  transformOutputHashes: Map<string, string>;
40
42
  recordTransformOutput(relativePath: string, code: string): void;
41
- /** Vocabulary witnesses from the sealed system, awaiting the next analysis.
42
- * Surfacing happens only inside `runProjectAnalysis`. */
43
- systemVocabularyDiagnostics: ManifestDiagnostic[];
44
43
  reverseProvenance: Record<string, string[]>;
45
44
  storedSystemPropMapJson: string;
46
45
  storedDynamicPropsJson: string;
47
- storedTransformsSource: string;
46
+ storedAdmittedTransformsJson: string;
47
+ storedTypedSystemPropsJson: string;
48
48
  readonly fileCache: ReadonlyMap<string, {
49
49
  hash: string;
50
50
  source: string;
@@ -62,8 +62,18 @@ export declare class PluginContext {
62
62
  * this corpus's published projection. */
63
63
  readonly corpus: SourceCorpus;
64
64
  rawExtensionFallbacks: Set<string>;
65
+ /** Original path → hash of bytes whose parse aborted in a rejected attempt;
66
+ * non-empty while that rejection holds publication. Those bytes are served
67
+ * raw so the host reports its own syntax error instead of receiving the
68
+ * previous module from the retained engine. */
69
+ readonly abortedParseHashes: Map<string, string>;
70
+ /** A system reload is pending: the next analysis attempt loads the latest
71
+ * system. A parse hold keeps it pending and the published system served;
72
+ * new dependency watch keys stay registered meanwhile. */
73
+ systemReloadOwed: boolean;
65
74
  /** The one mutator of a file's fallback state — every raw-serve exit of the
66
- * transform hook reports here. Production keeps the set empty. The
75
+ * transform hook reports here, except aborted bytes, which never execute.
76
+ * Production keeps the set empty. The
67
77
  * barrier's one-shot withhold release must not route through here: it
68
78
  * retires other files' records, no claim about their current serve. */
69
79
  recordFallbackState(relativePath: string, isFallback: boolean): void;
@@ -90,6 +100,9 @@ export declare class PluginContext {
90
100
  readonly engineApi: () => any;
91
101
  constructor(options: AnimusExtractOptions, engineApiOverride?: () => any);
92
102
  log(msg: string): void;
103
+ /** One line per item — a pruned option, a transformed file, an HMR
104
+ * decision — printed only at the trace tier. */
105
+ trace(msg: string): void;
93
106
  /** Logs whether or not `verbose` is on — for events a developer must see
94
107
  * without opting in. */
95
108
  info(msg: string): void;
@@ -107,13 +120,31 @@ export declare class PluginContext {
107
120
  }>): boolean;
108
121
  private assertRuntimeImportSuppliesTerminals;
109
122
  /** The one ingest → quarantine → analyze → publish transaction. The corpus
110
- * publishes only on success; `beforeAnalysis` runs after quarantine. */
123
+ * publishes only on success. `afterIngestion` runs after quarantine even
124
+ * when an aborted parse rejects the attempt; `beforeAnalysis` runs only
125
+ * once the attempt will analyze. A rejection names its aborted originals
126
+ * and holds publication: development callers keep their cache's latest
127
+ * sources, valid edits included, for the repair to publish together. In
128
+ * every strictness mode it fails a production build, which has no
129
+ * generation to keep, and only warns in development: the host reports the
130
+ * syntax error itself, and a throw would leave its client on the failed
131
+ * module. The publication that ends a hold invalidates the modules of
132
+ * every original whose admitted bytes changed meanwhile and returns them
133
+ * as `redeliver`, for a hot update to push to the client. An owed system
134
+ * reload loads the latest system for the attempt: a hold restores the
135
+ * published one and keeps the reload owed, any other outcome completes
136
+ * the reload's invalidation. */
111
137
  analyzeIngested(options?: {
112
138
  rawEntries?: readonly RawSourceEntry[];
139
+ afterIngestion?: (ingested: SourceIngestionResult) => void;
113
140
  beforeAnalysis?: (accepted: SourceIngestionResult) => void;
114
141
  }): Promise<{
115
142
  ok: boolean;
116
143
  accepted: SourceIngestionResult;
144
+ /** Original path → hash of the bytes whose parse aborted. */
145
+ abortedOriginals?: ReadonlyMap<string, string>;
146
+ endedHold: boolean;
147
+ redeliver: string[];
117
148
  }>;
118
149
  publishSourceIngestion(result: SourceIngestionResult): void;
119
150
  devFsUrl(absPath: string): string;
@@ -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/index.cjs CHANGED
@@ -75,7 +75,7 @@ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
75
75
  t0 = performance.now();
76
76
  await ctx.analyzeIngested({
77
77
  rawEntries,
78
- beforeAnalysis: (accepted) => {
78
+ afterIngestion: (accepted) => {
79
79
  if (!ctx.isProd) ctx.mutateFileCache((cache) => {
80
80
  cache.clear();
81
81
  for (const entry of accepted.originalEntries) cache.set(entry.path, {
@@ -109,8 +109,8 @@ async function runBuildStart(ctx, resolveSpecifier, emitAsset) {
109
109
  ctx.log(`Reconciliation: ${report.components_extracted} kept, ${report.variants_eliminated} variants pruned, ${report.states_eliminated} states pruned`);
110
110
  for (const d of report.eliminated_details) if (d.kind === "component") ctx.warn(`⚠ ${d.component} eliminated: ${d.reason}`);
111
111
  else if (d.kind === "prospective_component") ctx.warn(`⚠ ${d.component} would be eliminated in production: ${d.reason}`);
112
- else if (d.kind === "variant") ctx.warn(`⚠ ${d.component} variant '${d.name}' pruned: ${d.reason}`);
113
- else if (d.kind === "state") ctx.warn(`⚠ ${d.component} state '${d.name}' pruned: ${d.reason}`);
112
+ else if (d.kind === "variant") ctx.trace(`${d.component} variant '${d.name}' pruned: ${d.reason}`);
113
+ else if (d.kind === "state") ctx.trace(`${d.component} state '${d.name}' pruned: ${d.reason}`);
114
114
  ctx.log(`CSS: ${ctx.resolvedComponentCss.length} bytes (${Object.keys(ctx.storedManifest.components).length} components)`);
115
115
  if (!ctx.isProd && ctx.storedSheets) {
116
116
  const staticSize = (0, _animus_ui_extract_pipeline.assembleStylesheet)({
@@ -238,8 +238,9 @@ function eventKey(file, timestamp) {
238
238
  //#endregion
239
239
  //#region src/module-invalidation.ts
240
240
  /**
241
- * Completeness is load-bearing: the file-plan diff is the only invalidation
242
- * candidate source, so a node shape missed here stays stale for the session.
241
+ * Completeness is load-bearing: the file-plan diff and the sources re-delivered
242
+ * when a held publication ends are the only invalidation candidate sources, so
243
+ * a node shape missed here stays stale for the session.
243
244
  */
244
245
  function invalidateFileModules(ctx, relPaths) {
245
246
  const server = ctx.devServer;
@@ -260,7 +261,7 @@ function invalidateFileModules(ctx, relPaths) {
260
261
  fileCount++;
261
262
  }
262
263
  }
263
- if (fileCount > 0) ctx.log(`HMR invalidate: ${relPath} (plan changed, ${fileCount} nodes)`);
264
+ if (fileCount > 0) ctx.trace(`HMR invalidate: ${relPath} (plan changed, ${fileCount} nodes)`);
264
265
  total += fileCount;
265
266
  }
266
267
  return total;
@@ -336,7 +337,8 @@ function generateSystemPropsModule(ctx) {
336
337
  systemPropMapJson: ctx.storedSystemPropMapJson,
337
338
  groupRegistryJson: ctx.system.groupRegistryJson,
338
339
  dynamicProps: JSON.parse(ctx.storedDynamicPropsJson),
339
- transformsSource: ctx.storedTransformsSource
340
+ admittedTransforms: JSON.parse(ctx.storedAdmittedTransformsJson),
341
+ typedSystemProps: JSON.parse(ctx.storedTypedSystemPropsJson)
340
342
  });
341
343
  }
342
344
  /** Memoized on the inputs themselves, so no writer owes the memo a refresh
@@ -348,7 +350,8 @@ function systemPropsModuleKey(ctx) {
348
350
  ctx.storedSystemPropMapJson,
349
351
  ctx.system.groupRegistryJson,
350
352
  ctx.storedDynamicPropsJson,
351
- ctx.storedTransformsSource
353
+ ctx.storedAdmittedTransformsJson,
354
+ ctx.storedTypedSystemPropsJson
352
355
  ].join("\0");
353
356
  }
354
357
  /** The exact source `virtual:animus/system-props` serves now — one definition,
@@ -373,6 +376,8 @@ function pruneFileCache(cache, rootDir, absPath) {
373
376
  var PluginContext = class {
374
377
  options;
375
378
  verbose;
379
+ /** The higher tier: `verbose: 'trace'` or `ANIMUS_DEBUG=trace`. */
380
+ tracing;
376
381
  staticCssJson;
377
382
  isProd = false;
378
383
  /** Emission mode (the explicit `mode` option wins over the command); feeds
@@ -395,13 +400,11 @@ var PluginContext = class {
395
400
  recordTransformOutput(relativePath, code) {
396
401
  this.transformOutputHashes.set(relativePath, (0, _animus_ui_extract_pipeline.contentHash)(code));
397
402
  }
398
- /** Vocabulary witnesses from the sealed system, awaiting the next analysis.
399
- * Surfacing happens only inside `runProjectAnalysis`. */
400
- systemVocabularyDiagnostics = [];
401
403
  reverseProvenance = {};
402
404
  storedSystemPropMapJson = "{}";
403
405
  storedDynamicPropsJson = "{}";
404
- storedTransformsSource = "{}";
406
+ storedAdmittedTransformsJson = "{}";
407
+ storedTypedSystemPropsJson = "[]";
405
408
  fileCache = /* @__PURE__ */ new Map();
406
409
  /** Mutation attempts against `fileCache`, for memos that must not key on
407
410
  * `size` — a delete plus an unrelated create leaves it unchanged. */
@@ -423,8 +426,18 @@ var PluginContext = class {
423
426
  warn: (message) => this.warn(message)
424
427
  });
425
428
  rawExtensionFallbacks = /* @__PURE__ */ new Set();
429
+ /** Original path → hash of bytes whose parse aborted in a rejected attempt;
430
+ * non-empty while that rejection holds publication. Those bytes are served
431
+ * raw so the host reports its own syntax error instead of receiving the
432
+ * previous module from the retained engine. */
433
+ abortedParseHashes = /* @__PURE__ */ new Map();
434
+ /** A system reload is pending: the next analysis attempt loads the latest
435
+ * system. A parse hold keeps it pending and the published system served;
436
+ * new dependency watch keys stay registered meanwhile. */
437
+ systemReloadOwed = false;
426
438
  /** The one mutator of a file's fallback state — every raw-serve exit of the
427
- * transform hook reports here. Production keeps the set empty. The
439
+ * transform hook reports here, except aborted bytes, which never execute.
440
+ * Production keeps the set empty. The
428
441
  * barrier's one-shot withhold release must not route through here: it
429
442
  * retires other files' records, no claim about their current serve. */
430
443
  recordFallbackState(relativePath, isFallback) {
@@ -456,7 +469,9 @@ var PluginContext = class {
456
469
  constructor(options, engineApiOverride) {
457
470
  this.options = options;
458
471
  this.staticCssJson = (0, _animus_ui_extract_pipeline.serializeStaticCss)(options.staticCss);
459
- this.verbose = options.verbose || process.env.ANIMUS_DEBUG === "1" || process.env.ANIMUS_DEBUG === "true";
472
+ const verbosity = (0, _animus_ui_extract_pipeline.resolveVerbosity)(options.verbose, process.env.ANIMUS_DEBUG);
473
+ this.verbose = verbosity !== "quiet";
474
+ this.tracing = verbosity === "trace";
460
475
  this.extensionsSet = new Set(options.extensions ?? _animus_ui_extract_pipeline.DEFAULT_EXTENSIONS);
461
476
  this.excludeMatcher = (0, _animus_ui_extract_pipeline.createExcludeMatcher)(options.exclude);
462
477
  if (engineApiOverride) {
@@ -494,6 +509,11 @@ var PluginContext = class {
494
509
  log(msg) {
495
510
  if (this.verbose) (this.logger ?? console).info(`[animus] ${msg}`);
496
511
  }
512
+ /** One line per item — a pruned option, a transformed file, an HMR
513
+ * decision — printed only at the trace tier. */
514
+ trace(msg) {
515
+ if (this.tracing) (this.logger ?? console).info(`[animus] ${msg}`);
516
+ }
497
517
  /** Logs whether or not `verbose` is on — for events a developer must see
498
518
  * without opting in. */
499
519
  info(msg) {
@@ -527,7 +547,6 @@ var PluginContext = class {
527
547
  this.systemDependencyKeys = keys;
528
548
  this.systemDependencyPaths = deps;
529
549
  this.registerSystemWatchPaths();
530
- this.systemVocabularyDiagnostics = (0, _animus_ui_extract_pipeline.vocabularyWitnessDiagnostics)(this.system.vocabularyWitnessesJson);
531
550
  } catch (e) {
532
551
  if (this.options.strict) throw new Error(`[animus-extract] Failed to load system from ${this.resolvedSystemPath}: ${e}`, { cause: e });
533
552
  console.warn(`[animus-extract] Failed to load system from ${this.resolvedSystemPath}:`, e);
@@ -551,8 +570,7 @@ var PluginContext = class {
551
570
  externalDirs: this.externalPackageDirs.map((dir) => (0, path.relative)(this.rootDir, dir)),
552
571
  devMode: !this.emissionProd,
553
572
  warn: (m) => this.warn(m),
554
- strict: this.options.strict,
555
- extraDiagnostics: this.systemVocabularyDiagnostics
573
+ strict: this.options.strict
556
574
  });
557
575
  } catch (e) {
558
576
  if (this.options.strict) throw new Error(`[animus-extract] analyzeProject failed: ${e}`, { cause: e });
@@ -565,6 +583,8 @@ var PluginContext = class {
565
583
  this.storedManifestJson = result.manifestJson;
566
584
  this.storedSystemPropMapJson = JSON.stringify(result.manifest.system_prop_map);
567
585
  this.storedDynamicPropsJson = JSON.stringify(result.manifest.dynamic_props);
586
+ this.storedAdmittedTransformsJson = JSON.stringify(result.manifest.admitted_transforms);
587
+ this.storedTypedSystemPropsJson = JSON.stringify(result.manifest.typed_system_props);
568
588
  this.reverseProvenance = result.manifest.reverse_provenance;
569
589
  this.storedSheets = result.manifest.sheets;
570
590
  this.globalCss = result.globalCss;
@@ -582,19 +602,82 @@ var PluginContext = class {
582
602
  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().`);
583
603
  }
584
604
  /** The one ingest → quarantine → analyze → publish transaction. The corpus
585
- * publishes only on success; `beforeAnalysis` runs after quarantine. */
605
+ * publishes only on success. `afterIngestion` runs after quarantine even
606
+ * when an aborted parse rejects the attempt; `beforeAnalysis` runs only
607
+ * once the attempt will analyze. A rejection names its aborted originals
608
+ * and holds publication: development callers keep their cache's latest
609
+ * sources, valid edits included, for the repair to publish together. In
610
+ * every strictness mode it fails a production build, which has no
611
+ * generation to keep, and only warns in development: the host reports the
612
+ * syntax error itself, and a throw would leave its client on the failed
613
+ * module. The publication that ends a hold invalidates the modules of
614
+ * every original whose admitted bytes changed meanwhile and returns them
615
+ * as `redeliver`, for a hot update to push to the client. An owed system
616
+ * reload loads the latest system for the attempt: a hold restores the
617
+ * published one and keeps the reload owed, any other outcome completes
618
+ * the reload's invalidation. */
586
619
  async analyzeIngested(options) {
587
- const accepted = await this.corpus.prepare(options?.rawEntries ?? {
588
- fileCache: this.fileCache,
589
- externalFileOwners: this.externalFileOwners
590
- });
591
- options?.beforeAnalysis?.(accepted);
592
- const ok = this.runAnalysis(accepted.analysisEntries) !== false;
593
- if (ok) this.publishSourceIngestion(accepted);
594
- return {
595
- ok,
596
- accepted
597
- };
620
+ const holding = this.abortedParseHashes.size > 0;
621
+ const previous = this.corpus.published.ownership;
622
+ const reloadingSystem = this.systemReloadOwed;
623
+ const prevPlans = reloadingSystem ? (0, _animus_ui_extract_pipeline.snapshotFilePlans)(this.storedManifest) : null;
624
+ const publishedSystem = this.system;
625
+ let published = false;
626
+ try {
627
+ if (reloadingSystem) this.loadSystem();
628
+ const accepted = await this.corpus.prepare(options?.rawEntries ?? {
629
+ fileCache: this.fileCache,
630
+ externalFileOwners: this.externalFileOwners
631
+ });
632
+ options?.afterIngestion?.(accepted);
633
+ const rejection = this.corpus.rejection(accepted);
634
+ if (rejection) {
635
+ for (const [path$3, hash] of rejection.originals) this.abortedParseHashes.set(path$3, hash);
636
+ if (this.isProd) throw new Error(rejection.message);
637
+ this.warn(rejection.message);
638
+ return {
639
+ ok: false,
640
+ accepted,
641
+ abortedOriginals: rejection.originals,
642
+ endedHold: false,
643
+ redeliver: []
644
+ };
645
+ }
646
+ if (reloadingSystem) (0, _animus_ui_extract_pipeline.clearEngineCache)(this.engineApi);
647
+ options?.beforeAnalysis?.(accepted);
648
+ const ok = this.runAnalysis(accepted.analysisEntries) !== false;
649
+ if (!ok) return {
650
+ ok,
651
+ accepted,
652
+ endedHold: false,
653
+ redeliver: []
654
+ };
655
+ this.publishSourceIngestion(accepted);
656
+ published = true;
657
+ this.abortedParseHashes.clear();
658
+ if (!holding) return {
659
+ ok,
660
+ accepted,
661
+ endedHold: false,
662
+ redeliver: []
663
+ };
664
+ const redeliver = Object.values(accepted.ownership).filter((owner) => previous[owner.originalPath]?.originalHash !== owner.originalHash).map((owner) => owner.originalPath);
665
+ invalidateFileModules(this, redeliver);
666
+ return {
667
+ ok,
668
+ accepted,
669
+ endedHold: true,
670
+ redeliver
671
+ };
672
+ } finally {
673
+ const systemHeld = reloadingSystem && this.abortedParseHashes.size > 0;
674
+ if (systemHeld) this.system = publishedSystem;
675
+ else if (reloadingSystem) {
676
+ this.systemReloadOwed = false;
677
+ if (published && prevPlans) invalidateFileModules(this, (0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(this.storedManifest)));
678
+ }
679
+ if (reloadingSystem) this.invalidateSystemReloadModules(!systemHeld);
680
+ }
598
681
  }
599
682
  publishSourceIngestion(result) {
600
683
  this.corpus.publish(result);
@@ -651,18 +734,12 @@ var PluginContext = class {
651
734
  }
652
735
  async performSystemReloadExclusive() {
653
736
  const resetStart = performance.now();
654
- const prevPlans = (0, _animus_ui_extract_pipeline.snapshotFilePlans)(this.storedManifest);
655
- try {
656
- this.loadSystem();
657
- const { ok } = await this.analyzeIngested({ beforeAnalysis: () => (0, _animus_ui_extract_pipeline.clearEngineCache)(this.engineApi) });
658
- if (!ok) return;
659
- invalidateFileModules(this, (0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(this.storedManifest)));
660
- this.log(`HMR system reload complete: ${Math.round(performance.now() - resetStart)}ms`);
661
- } finally {
662
- this.invalidateSystemReloadModules();
663
- }
737
+ this.systemReloadOwed = true;
738
+ const { ok } = await this.analyzeIngested();
739
+ if (!ok) return;
740
+ this.log(`HMR system reload complete: ${Math.round(performance.now() - resetStart)}ms`);
664
741
  }
665
- invalidateSystemReloadModules() {
742
+ invalidateSystemReloadModules(reloadClient) {
666
743
  const server = this.devServer;
667
744
  if (!server) return;
668
745
  for (const moduleId of [
@@ -673,7 +750,7 @@ var PluginContext = class {
673
750
  const mod = server.moduleGraph.getModuleById(moduleId);
674
751
  if (mod) server.moduleGraph.invalidateModule(mod);
675
752
  }
676
- server.hot?.send({ type: "full-reload" });
753
+ if (reloadClient) server.hot?.send({ type: "full-reload" });
677
754
  }
678
755
  isSystemDependency(absFile) {
679
756
  return (0, _animus_ui_extract_pipeline.toWatchKeys)(absFile).some((key) => this.systemDependencyKeys.has(key));
@@ -802,10 +879,13 @@ async function reconcileSourceCorpus(ctx) {
802
879
  ctx.log(`rediscovery: folded ${folded.length} on-disk file(s) after unresolved-parent drop`);
803
880
  reanalyzed = true;
804
881
  let published = false;
882
+ let held = false;
805
883
  try {
806
- published = (await ctx.analyzeIngested()).ok;
884
+ const analysis = await ctx.analyzeIngested();
885
+ published = analysis.ok;
886
+ held = analysis.abortedOriginals !== void 0;
807
887
  } finally {
808
- if (!published) ctx.mutateFileCache((cache) => {
888
+ if (!published && !held) ctx.mutateFileCache((cache) => {
809
889
  for (const key of folded) cache.delete(key);
810
890
  });
811
891
  }
@@ -903,10 +983,12 @@ function applyDevBridgeImport(code) {
903
983
  const prologue = /^(?:(['"])use [a-z -]+\1;?\r?\n)*/.exec(code)?.[0] ?? "";
904
984
  return prologue + `import '${VIRTUAL_BRIDGE_ID}';\n` + code.slice(prologue.length);
905
985
  }
906
- function rawFallbackDescendants(ctx, relPath) {
986
+ /** The files defining a transitive extension of a component the given
987
+ * analysis paths define, from the published provenance. */
988
+ function extendingFiles(ctx, analysisPaths) {
907
989
  const manifest = ctx.storedManifest;
908
- const conflicted = /* @__PURE__ */ new Set();
909
- const queue = [...manifest?.files[relPath] ?? []];
990
+ const files = /* @__PURE__ */ new Set();
991
+ const queue = analysisPaths.flatMap((path$2) => manifest?.files[path$2] ?? []);
910
992
  const seen = new Set(queue);
911
993
  while (queue.length > 0) {
912
994
  const id = queue.shift();
@@ -915,10 +997,13 @@ function rawFallbackDescendants(ctx, relPath) {
915
997
  seen.add(childId);
916
998
  queue.push(childId);
917
999
  const childFile = manifest?.components[childId]?.file;
918
- if (childFile && childFile !== relPath && ctx.rawExtensionFallbacks.has(childFile)) conflicted.add(childFile);
1000
+ if (childFile) files.add(childFile);
919
1001
  }
920
1002
  }
921
- return [...conflicted].sort();
1003
+ return files;
1004
+ }
1005
+ function rawFallbackDescendants(ctx, relPath) {
1006
+ return [...extendingFiles(ctx, [relPath])].filter((file) => file !== relPath && ctx.rawExtensionFallbacks.has(file)).sort();
922
1007
  }
923
1008
  async function transformSource(ctx, code, id) {
924
1009
  if (!ctx.storedManifest) return null;
@@ -930,6 +1015,8 @@ async function transformSource(ctx, code, id) {
930
1015
  if (id.includes("node_modules")) return null;
931
1016
  if (!(0, _animus_ui_extract_pipeline.isPathWithinRoot)(ctx.rootDir, id)) return null;
932
1017
  }
1018
+ const abortedHash = ctx.abortedParseHashes.get(relativePath);
1019
+ if (abortedHash !== void 0 && abortedHash === (0, _animus_ui_extract_pipeline.contentHash)(code)) return null;
933
1020
  if (!ctx.storedManifest.files[relativePath]?.length) {
934
1021
  if (!ctx.isProd && !ctx.fileCache.has(relativePath)) await runExclusiveAnalysis(ctx, async () => {
935
1022
  if (ctx.fileCache.has(relativePath)) return;
@@ -944,10 +1031,13 @@ async function transformSource(ctx, code, id) {
944
1031
  }));
945
1032
  const prevPlans = (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest);
946
1033
  let analysisOk = false;
1034
+ let held = false;
947
1035
  try {
948
- analysisOk = (await ctx.analyzeIngested()).ok;
1036
+ const analysis = await ctx.analyzeIngested();
1037
+ analysisOk = analysis.ok;
1038
+ held = analysis.abortedOriginals !== void 0;
949
1039
  } finally {
950
- if (!analysisOk) ctx.mutateFileCache((cache) => cache.delete(relativePath));
1040
+ if (!analysisOk && !held) ctx.mutateFileCache((cache) => cache.delete(relativePath));
951
1041
  }
952
1042
  if (analysisOk) {
953
1043
  await reconcileSourceCorpus(ctx);
@@ -978,9 +1068,9 @@ async function transformSource(ctx, code, id) {
978
1068
  ctx.recordFallbackState(relativePath, true);
979
1069
  return null;
980
1070
  }
981
- if (ctx.verbose) {
1071
+ if (ctx.tracing) {
982
1072
  const compCount = ctx.storedManifest.files[relativePath]?.length ?? 0;
983
- ctx.log(`transform ${relativePath}: ${compCount} components`);
1073
+ ctx.trace(`transform ${relativePath}: ${compCount} components`);
984
1074
  }
985
1075
  let outputCode = result.code;
986
1076
  if (!ctx.isProd) {
@@ -1010,7 +1100,7 @@ async function handleHotUpdate(ctx, environment, options) {
1010
1100
  async function handleHotUpdateExclusive(ctx, environment, { type, file, timestamp, modules, read }) {
1011
1101
  const ownsEvent = ctx.hotUpdateEvents.claim(environment.name, file, timestamp);
1012
1102
  const absFile = (0, path.resolve)(file);
1013
- ctx.log(`hotUpdate ${type} ${(0, path.relative)(ctx.rootDir, absFile)} env=${environment.name} owns=${ownsEvent}`);
1103
+ ctx.trace(`hotUpdate ${type} ${(0, path.relative)(ctx.rootDir, absFile)} env=${environment.name} owns=${ownsEvent}`);
1014
1104
  if (ctx.isSystemDependency(absFile)) {
1015
1105
  if (ownsEvent) {
1016
1106
  await reconcileSourceEntry(ctx, absFile, type, read);
@@ -1083,7 +1173,7 @@ async function analyzeChangedFile(ctx, file, absFile, read) {
1083
1173
  const hash = (0, _animus_ui_extract_pipeline.contentHash)(source);
1084
1174
  const cached = ctx.fileCache.get(relPath);
1085
1175
  if (cached && cached.hash === hash) {
1086
- ctx.log(`HMR skip: ${relPath} (unchanged)`);
1176
+ ctx.trace(`HMR skip: ${relPath} (unchanged)`);
1087
1177
  return { kind: "unchanged" };
1088
1178
  }
1089
1179
  const priorExternalOwner = ctx.externalFileOwners[relPath];
@@ -1105,30 +1195,17 @@ async function analyzeChangedFile(ctx, file, absFile, read) {
1105
1195
  };
1106
1196
  const hmrStart = performance.now();
1107
1197
  const prevPlans = (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest);
1108
- const directComponentIds = (ctx.corpus.published.ownership[relPath]?.analysisPaths ?? [relPath]).flatMap((analysisPath) => ctx.storedManifest?.files[analysisPath] ?? []);
1109
- const invalidatedIds = new Set(directComponentIds);
1110
- const queue = [...directComponentIds];
1111
- while (queue.length > 0) {
1112
- const parentId = queue.shift();
1113
- const children = ctx.reverseProvenance[parentId];
1114
- if (children) {
1115
- for (const childId of children) if (!invalidatedIds.has(childId)) {
1116
- invalidatedIds.add(childId);
1117
- queue.push(childId);
1118
- }
1119
- }
1120
- }
1121
- if (ctx.verbose && invalidatedIds.size > directComponentIds.length) ctx.log(`HMR: ${directComponentIds.length} direct + ${invalidatedIds.size - directComponentIds.length} transitive components invalidated`);
1122
1198
  const analysisStart = performance.now();
1123
1199
  const systemPropsBefore = systemPropsModuleSource(ctx);
1124
- let analysisOk;
1200
+ let analysis;
1125
1201
  try {
1126
- analysisOk = (await ctx.analyzeIngested()).ok;
1202
+ analysis = await ctx.analyzeIngested();
1127
1203
  } catch (e) {
1128
1204
  restoreEntry();
1129
1205
  throw e;
1130
1206
  }
1131
- if (!analysisOk) {
1207
+ if (!analysis.ok) {
1208
+ if (analysis.abortedOriginals) return analysis.abortedOriginals.has(relPath) ? { kind: "ignored" } : { kind: "unchanged" };
1132
1209
  restoreEntry();
1133
1210
  return { kind: "ignored" };
1134
1211
  }
@@ -1140,9 +1217,14 @@ async function analyzeChangedFile(ctx, file, absFile, read) {
1140
1217
  }
1141
1218
  const systemPropsChanged = systemPropsModuleSource(ctx) !== systemPropsBefore;
1142
1219
  const analysisMs = Math.round(performance.now() - analysisStart);
1143
- 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);
1144
1220
  const nativeEntry = ctx.corpus.published.analysisEntries.get(relPath);
1145
- const presentationOnly = nativeEntry ? isPresentationOnlyEdit(ctx, relPath, nativeEntry.source) : false;
1221
+ const presentationOnly = nativeEntry && !analysis.endedHold ? isPresentationOnlyEdit(ctx, relPath, nativeEntry.source) : false;
1222
+ const redelivered = presentationOnly ? [] : [relPath, ...analysis.redeliver];
1223
+ const staleDefinitionFiles = [.../* @__PURE__ */ new Set([
1224
+ ...(0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest)),
1225
+ ...analysis.redeliver,
1226
+ ...extendingFiles(ctx, redelivered.flatMap((path$1) => ctx.corpus.published.ownership[path$1]?.analysisPaths ?? [path$1]))
1227
+ ])].filter((defFile) => (0, path.resolve)(ctx.rootDir, defFile) !== absFile);
1146
1228
  const hmrMs = Math.round(performance.now() - hmrStart);
1147
1229
  ctx.log(`HMR update: ${relPath} — analysis ${analysisMs}ms, total ${hmrMs}ms${presentationOnly ? " (presentation-only)" : ""}`);
1148
1230
  ctx.logTimingWaterfall(ctx.storedManifest?.timing ?? {});
@@ -1177,7 +1259,7 @@ async function pruneDeletedFile(ctx, absFile) {
1177
1259
  const prevPlans = (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest);
1178
1260
  const { ok } = await ctx.analyzeIngested();
1179
1261
  if (!ok) return;
1180
- ctx.log(`Deleted file pruned: ${(0, path.relative)(ctx.rootDir, absFile)}`);
1262
+ ctx.trace(`Deleted file pruned: ${(0, path.relative)(ctx.rootDir, absFile)}`);
1181
1263
  invalidateFileModules(ctx, (0, _animus_ui_extract_pipeline.diffFilePlans)(prevPlans, (0, _animus_ui_extract_pipeline.snapshotFilePlans)(ctx.storedManifest)));
1182
1264
  ctx.invalidateExtractedModules();
1183
1265
  }
@@ -1199,7 +1281,7 @@ function invalidateStaleModules(ctx, environment, modules, analyzed) {
1199
1281
  const absDefPath = (0, path.resolve)(ctx.rootDir, defFile);
1200
1282
  const defModule = graph.getModuleById(absDefPath) ?? graph.getModulesByFile(absDefPath)?.values().next().value;
1201
1283
  if (defModule) {
1202
- ctx.log(`HMR invalidate: ${defFile} (replacement changed)`);
1284
+ ctx.trace(`HMR invalidate: ${defFile} (re-delivered)`);
1203
1285
  graph.invalidateModule(defModule);
1204
1286
  modulesToUpdate.push(defModule);
1205
1287
  }
package/dist/index.d.ts CHANGED
@@ -19,15 +19,21 @@ export interface AnimusExtractOptions {
19
19
  * `@mdx-js/mdx` peer, or those files warn once and are skipped.
20
20
  */
21
21
  extensions?: string[];
22
- /** Extraction failures throw instead of warning. */
22
+ /**
23
+ * Error-severity diagnostics — lost configured inputs and classified
24
+ * unsupported Animus declarations — fail the build instead of warning.
25
+ * Omitted or `false` warns.
26
+ */
23
27
  strict?: boolean;
24
28
  /**
25
29
  * Run a structural self-check at the end of `buildStart`; failures throw
26
30
  * under `strict`, otherwise warn.
27
31
  */
28
32
  verify?: boolean;
29
- /** Verbose logging; also enabled by `ANIMUS_DEBUG=1`. */
30
- verbose?: boolean;
33
+ /** `true` logs phase checkpoints, summaries and timing (`ANIMUS_DEBUG=1`);
34
+ * `'trace'` also logs one line per pruned option, transformed file and
35
+ * HMR decision (`ANIMUS_DEBUG=trace`). */
36
+ verbose?: boolean | 'trace';
31
37
  /**
32
38
  * Browserslist queries for autoprefixing and syntax lowering; falls back
33
39
  * to the project's browserslist config, then to `defaults`.
@@ -1 +1 @@
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,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACpC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD;AAMD,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAsFnE;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,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;+CAE2C;IAC3C,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACpC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD;AAMD,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAsFnE;eAEc,aAAa"}
@@ -1,7 +1,8 @@
1
1
  import type { PluginContext } from './context';
2
2
  /**
3
- * Completeness is load-bearing: the file-plan diff is the only invalidation
4
- * candidate source, so a node shape missed here stays stale for the session.
3
+ * Completeness is load-bearing: the file-plan diff and the sources re-delivered
4
+ * when a held publication ends are the only invalidation candidate sources, so
5
+ * a node shape missed here stays stale for the session.
5
6
  */
6
7
  export declare function invalidateFileModules(ctx: PluginContext, relPaths: string[]): number;
7
8
  //# sourceMappingURL=module-invalidation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-invalidation.d.ts","sourceRoot":"","sources":["../src/module-invalidation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,CAmCR"}
1
+ {"version":3,"file":"module-invalidation.d.ts","sourceRoot":"","sources":["../src/module-invalidation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,CAqCR"}
@@ -1 +1 @@
1
- {"version":3,"file":"rediscovery.d.ts","sourceRoot":"","sources":["../src/rediscovery.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/C,UAAU,oBAAoB;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,GACjB,oBAAoB,EAAE,CAWxB;AAOD,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAa3E;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,OAAO,CAAC,CAqElB"}
1
+ {"version":3,"file":"rediscovery.d.ts","sourceRoot":"","sources":["../src/rediscovery.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/C,UAAU,oBAAoB;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,GACjB,oBAAoB,EAAE,CAWxB;AAOD,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAa3E;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,OAAO,CAAC,CAyElB"}
@@ -4,6 +4,9 @@ import type { PluginContext } from './context';
4
4
  * becomes an ordinary expression and the module loses its client marking.
5
5
  */
6
6
  export declare function applyDevBridgeImport(code: string): string;
7
+ /** The files defining a transitive extension of a component the given
8
+ * analysis paths define, from the published provenance. */
9
+ export declare function extendingFiles(ctx: PluginContext, analysisPaths: readonly string[]): Set<string>;
7
10
  export declare function transformSource(ctx: PluginContext, code: string, id: string): Promise<{
8
11
  code: string;
9
12
  map: null;
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKzD;AA4BD,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,CA2J7C"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED;4DAC4D;AAC5D,wBAAgB,cAAc,CAC5B,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,GAAG,CAAC,MAAM,CAAC,CAkBb;AAQD,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,CAuK7C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@animus-ui/vite-plugin",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Animus static CSS extraction Vite plugin",
5
5
  "keywords": [
6
6
  "animus",
@@ -39,12 +39,12 @@
39
39
  "compile": "tsc --noEmit"
40
40
  },
41
41
  "dependencies": {
42
- "@animus-ui/extract": "0.1.16",
42
+ "@animus-ui/extract": "0.1.18",
43
43
  "browserslist": "^4.28.8",
44
44
  "lightningcss": "^1.33.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@animus-ui/assertions": "0.1.16"
47
+ "@animus-ui/assertions": "0.1.18"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "@mdx-js/mdx": "^3.0.0",