@animus-ui/extract 0.1.23 → 0.1.24

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.
Files changed (46) hide show
  1. package/crates/extract-v2/animus-extract-v2.darwin-arm64.node +0 -0
  2. package/crates/extract-v2/animus-extract-v2.linux-arm64-gnu.node +0 -0
  3. package/crates/extract-v2/animus-extract-v2.linux-x64-gnu.node +0 -0
  4. package/crates/extract-v2/index.d.ts +16 -3
  5. package/dist/index.cjs +11 -1
  6. package/dist/index.mjs +2 -2
  7. package/dist/pipeline/analyze-project-args.d.ts +5 -1
  8. package/dist/pipeline/analyze-project-args.d.ts.map +1 -1
  9. package/dist/pipeline/asset-placeholders.d.ts +4 -1
  10. package/dist/pipeline/asset-placeholders.d.ts.map +1 -1
  11. package/dist/pipeline/core-options.d.ts +13 -7
  12. package/dist/pipeline/core-options.d.ts.map +1 -1
  13. package/dist/pipeline/correlate-external-tokens.d.ts +3 -0
  14. package/dist/pipeline/correlate-external-tokens.d.ts.map +1 -1
  15. package/dist/pipeline/discover-packages.d.ts +89 -0
  16. package/dist/pipeline/discover-packages.d.ts.map +1 -1
  17. package/dist/pipeline/dynamic-prop-config.d.ts +13 -2
  18. package/dist/pipeline/dynamic-prop-config.d.ts.map +1 -1
  19. package/dist/pipeline/engine-adapter.d.ts +3 -1
  20. package/dist/pipeline/engine-adapter.d.ts.map +1 -1
  21. package/dist/pipeline/index.d.ts +5 -2
  22. package/dist/pipeline/index.d.ts.map +1 -1
  23. package/dist/pipeline/kit-descriptor.d.ts +44 -0
  24. package/dist/pipeline/kit-descriptor.d.ts.map +1 -0
  25. package/dist/pipeline/kit-publication.d.ts +15 -0
  26. package/dist/pipeline/kit-publication.d.ts.map +1 -0
  27. package/dist/pipeline/manifest-diagnostics.d.ts +32 -7
  28. package/dist/pipeline/manifest-diagnostics.d.ts.map +1 -1
  29. package/dist/pipeline/manifest-schema.d.ts +4 -0
  30. package/dist/pipeline/manifest-schema.d.ts.map +1 -1
  31. package/dist/pipeline/prefix.d.ts +14 -3
  32. package/dist/pipeline/prefix.d.ts.map +1 -1
  33. package/dist/pipeline/run-analysis.d.ts +13 -2
  34. package/dist/pipeline/run-analysis.d.ts.map +1 -1
  35. package/dist/pipeline/source-ingestion.d.ts +9 -2
  36. package/dist/pipeline/source-ingestion.d.ts.map +1 -1
  37. package/dist/pipeline/structural-self-check.d.ts.map +1 -1
  38. package/dist/pipeline/system-config.d.ts +6 -3
  39. package/dist/pipeline/system-config.d.ts.map +1 -1
  40. package/dist/{pipeline-kA3VEMgt.mjs → pipeline-Bl20tbu_.mjs} +994 -321
  41. package/dist/{pipeline-B3JzXiSY.cjs → pipeline-CAH9mxnK.cjs} +1036 -302
  42. package/dist/session/extraction-session.d.ts +17 -4
  43. package/dist/session/extraction-session.d.ts.map +1 -1
  44. package/dist/session.cjs +54 -19
  45. package/dist/session.mjs +54 -19
  46. package/package.json +4 -4
@@ -1,13 +1,14 @@
1
- import { createRequire } from "node:module";
2
- import path, { basename, dirname, join, normalize, posix } from "node:path";
1
+ import { createRequire, isBuiltin } from "node:module";
2
+ import path, { basename, dirname, extname, isAbsolute, join, normalize, posix, relative, resolve, sep } from "node:path";
3
3
  import { createHash } from "crypto";
4
4
  import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "fs";
5
- import { dirname as dirname$1, extname, isAbsolute, join as join$1, relative, resolve, sep } from "path";
6
- import { realpathSync as realpathSync$1 } from "node:fs";
5
+ import { dirname as dirname$1, extname as extname$1, isAbsolute as isAbsolute$1, join as join$1, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
6
+ import { existsSync as existsSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, statSync as statSync$1 } from "node:fs";
7
7
  import { createRequire as createRequire$1 } from "module";
8
8
  import browserslist from "browserslist";
9
9
  import { browserslistToTargets, transform } from "lightningcss";
10
10
  import { componentValues, dependsOnContext, foldInitialValue, identifierAt, isSpace, isUnitlessProperty, someValue, substitutesValue, tokenize, variableReads } from "@animus-ui/properties";
11
+ import { spawnSync } from "node:child_process";
11
12
  //#region \0rolldown/runtime.js
12
13
  var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
13
14
  //#endregion
@@ -90,8 +91,13 @@ function buildAnalyzeProjectArgs(inputs) {
90
91
  inputs.transformSourcesJson,
91
92
  inputs.transformProvenanceJson ?? null
92
93
  ];
93
- if (inputs.declarationScalesJson || inputs.analysisContextJson) args.push(inputs.declarationScalesJson);
94
- if (inputs.analysisContextJson) args.push(inputs.analysisContextJson);
94
+ const tail = [
95
+ inputs.declarationScalesJson,
96
+ inputs.analysisContextJson,
97
+ inputs.generatedNamesJson
98
+ ];
99
+ const last = tail.findLastIndex((slot) => slot !== void 0 && slot !== "");
100
+ for (const slot of tail.slice(0, last + 1)) args.push(slot || void 0);
95
101
  return args;
96
102
  }
97
103
  //#endregion
@@ -237,13 +243,17 @@ function substituteSheetAssets(sheets, urlBySpecifier) {
237
243
  }
238
244
  const UNSUBSTITUTED_ASSET_CODE = "animus.asset.unsubstituted-placeholder";
239
245
  /** A placeholder in emitted CSS is a broken URL in the browser: it fails a
240
- * strict build and warns otherwise. */
246
+ * strict build, strict development reports it, and it warns otherwise. */
241
247
  function reportSurvivingAssetPlaceholders(css, report) {
242
248
  const specifiers = placeholdersInAssetCalls(css);
243
249
  if (specifiers.length === 0) return;
244
250
  const message = `${report.prefix} asset() placeholders reached ${report.surface ?? "emitted CSS"} unsubstituted: ${specifiers.join(", ")} (${UNSUBSTITUTED_ASSET_CODE})`;
245
- if (report.strict) throw new Error(message);
246
- report.warn(message);
251
+ if (!report.strict) {
252
+ report.warn(message);
253
+ return;
254
+ }
255
+ if (!report.reportErrors) throw new Error(message);
256
+ report.reportErrors(message);
247
257
  }
248
258
  /**
249
259
  * The runtime code an analysis generates: each dynamic prop config, which the
@@ -272,6 +282,15 @@ function locatedPrefix(diagnostic) {
272
282
  function droppedSuffix(diagnostic) {
273
283
  return diagnostic.dropped && !diagnostic.message.includes(diagnostic.dropped) ? ` — dropped: ${diagnostic.dropped}` : "";
274
284
  }
285
+ /** The record's code, when its message does not already quote it. */
286
+ function codeSuffix(diagnostic) {
287
+ return diagnostic.code && !diagnostic.message.includes(diagnostic.code) ? ` [${diagnostic.code}]` : "";
288
+ }
289
+ /** A warn-kind record's line after its mark:
290
+ * `file:line:column: component: message [code]`. */
291
+ function warnLine(diagnostic) {
292
+ return `${locationOf(diagnostic)}: ${diagnostic.component}: ${diagnostic.message}${droppedSuffix(diagnostic)}${codeSuffix(diagnostic)}`;
293
+ }
275
294
  /** Stable code for selector forms with no substitutable subject; the
276
295
  * extraction engine mints the same string. */
277
296
  const SELECTOR_UNSUPPORTED_SUBJECT = "animus.selector.unsupported-subject";
@@ -290,10 +309,19 @@ const DIAGNOSTIC_LEVELS = /* @__PURE__ */ new Set([
290
309
  "warn",
291
310
  "error"
292
311
  ]);
312
+ /** A key that selects every record of a kind: `kind:bail`, `kind:skip`,
313
+ * `kind:warn` or `kind:error`. */
314
+ const KIND_KEY = "kind:";
315
+ const DIAGNOSTIC_KINDS = /* @__PURE__ */ new Set([
316
+ "bail",
317
+ "skip",
318
+ "warn",
319
+ "error"
320
+ ]);
293
321
  /** The level `levels` sets for `code`: its exact entry, else the entry of
294
322
  * the longest prefix it starts with. */
295
- function levelFor(code, levels) {
296
- if (code === void 0 || levels === void 0) return void 0;
323
+ function codeLevel(code, levels) {
324
+ if (code === void 0) return void 0;
297
325
  if (Object.hasOwn(levels, code)) return levels[code];
298
326
  let longest;
299
327
  for (const [key, level] of Object.entries(levels)) {
@@ -306,11 +334,19 @@ function levelFor(code, levels) {
306
334
  }
307
335
  return longest?.level;
308
336
  }
337
+ /** The level `levels` sets for a record: its code's level, else its kind's. */
338
+ function levelFor({ code, kind }, levels) {
339
+ if (levels === void 0) return void 0;
340
+ const kindKey = `${KIND_KEY}${kind}`;
341
+ return codeLevel(code, levels) ?? (Object.hasOwn(levels, kindKey) ? levels[kindKey] : void 0);
342
+ }
309
343
  /** The level a record prints at: the option's entry for its code, else
310
- * `error` for an error-severity record under `strict`, else its own. */
344
+ * `error` for a hard error (an `error`-kind record) or an error-severity
345
+ * record under `strict`, else its own. */
311
346
  function effectiveLevel(diagnostic, policy) {
312
- const level = levelFor(diagnostic.code, policy.levels);
347
+ const level = levelFor(diagnostic, policy.levels);
313
348
  if (level !== void 0) return level;
349
+ if (diagnostic.kind === "error") return "error";
314
350
  if (diagnostic.severity === "info") return "info";
315
351
  return policy.strict && diagnostic.severity === "error" ? "error" : "warn";
316
352
  }
@@ -329,6 +365,7 @@ function knownDiagnosticCodes(engineCodesJson) {
329
365
  /** The keys of `levels` that name no known code, exactly or as a prefix. */
330
366
  function unknownDiagnosticKeys(levels, known) {
331
367
  return Object.keys(levels).filter((key) => {
368
+ if (key.startsWith(KIND_KEY)) return !DIAGNOSTIC_KINDS.has(key.slice(5));
332
369
  if (!key.endsWith(".*")) return !known.has(key);
333
370
  const prefix = key.slice(0, -1);
334
371
  return ![...known].some((code) => code.startsWith(prefix));
@@ -383,9 +420,22 @@ function collectSelectorAliasDiagnostics(selectorAliasesJson) {
383
420
  const UNREADABLE_SOURCE_FILE = "animus.ingestion.unreadable-source-file";
384
421
  /** A kit the system extends resolved, yet discovery found none of its files. */
385
422
  const NO_KIT_FILES = "animus.discovery.no-kit-files";
423
+ /** A kit with no `animus` export condition: discovery guesses its source
424
+ * from `src/`. */
425
+ const KIT_WITHOUT_SOURCE_CONDITION = "animus.discovery.kit-without-source-condition";
426
+ /** A kit's `animus` export condition names a file that is missing or outside
427
+ * its package, so that entry is not read from source. */
428
+ const INVALID_KIT_SOURCE_CONDITION = "animus.discovery.invalid-source-condition";
429
+ /** A kit the application imports whose system the application's system
430
+ * does not include: its components are not extracted. */
431
+ const KIT_SYSTEM_NOT_INCLUDED = "animus.kit.system-not-included";
386
432
  /** A system file's `createSystem` binding that discovery could not follow to
387
433
  * Animus's factory, so it is no root. */
388
434
  const UNPROVEN_ROOT_BINDING = "animus.discovery.unproven-root-binding";
435
+ /** A system file calls `createSystem` with no import or local binding. The
436
+ * system loader evaluates the file without auto-imports, where the name is
437
+ * undefined, so the call is no root. */
438
+ const UNIMPORTED_CREATE_SYSTEM = "animus.discovery.unimported-create-system";
389
439
  /** What a skipped source file costs: the analysis never sees what it
390
440
  * renders. */
391
441
  const SKIPPED_SOURCE_COST = "skipped: its renders are not seen, so nothing is pruned and every component, variant option and state is kept until it is analyzed";
@@ -421,6 +471,11 @@ function noKitFilesDiagnostics(outcomes) {
421
471
  severity: severityFor(NO_KIT_FILES)
422
472
  }));
423
473
  }
474
+ /** A kit's descriptor declares a format this Animus does not read. */
475
+ const KIT_UNSUPPORTED_FORMAT = "animus.kit.unsupported-format";
476
+ /** A kit's descriptor records a definition its shipped source no longer
477
+ * declares. */
478
+ const KIT_STALE_DESCRIPTOR = "animus.kit.stale-descriptor";
424
479
  /** The collision entry code minted by the system package's merge. */
425
480
  const VOCABULARY_COLLISION = "animus.vocabulary.collision";
426
481
  /** A theme `@property` registration browsers would ignore; it is not emitted. */
@@ -446,9 +501,6 @@ const PROPERTY_FALLBACK_SELF_REFERENCE = "animus.property.fallback-self-referenc
446
501
  * another directly, so every property in the cycle is invalid at
447
502
  * computed-value time. */
448
503
  const PROPERTY_CURRENT_VAR_CYCLE = "animus.property.current-var-cycle";
449
- /** A prefix renamed contextual variables without `prefixContextualVars`, so
450
- * their declared names no longer resolve. */
451
- const PREFIX_CONTEXTUAL_VARS_UNPREFIXED = "animus.prefix.contextual-vars-unprefixed";
452
504
  /** Under `prefixContextualVars`, a final name that collides with a runtime
453
505
  * transport variable or a theme variable of the same spelling. */
454
506
  const PREFIX_NAME_CONFLICT = "animus.prefix.name-conflict";
@@ -462,7 +514,13 @@ const DIAGNOSTIC_SEVERITY = /* @__PURE__ */ new Map([
462
514
  [SELECTOR_UNSUPPORTED_SUBJECT, "error"],
463
515
  [UNREADABLE_SOURCE_FILE, "error"],
464
516
  [NO_KIT_FILES, "warn"],
517
+ [KIT_WITHOUT_SOURCE_CONDITION, "warn"],
518
+ [INVALID_KIT_SOURCE_CONDITION, "error"],
519
+ [KIT_SYSTEM_NOT_INCLUDED, "error"],
520
+ [KIT_UNSUPPORTED_FORMAT, "error"],
521
+ [KIT_STALE_DESCRIPTOR, "warn"],
465
522
  [UNPROVEN_ROOT_BINDING, "warn"],
523
+ [UNIMPORTED_CREATE_SYSTEM, "warn"],
466
524
  [VOCABULARY_COLLISION, "warn"],
467
525
  [VOCABULARY_LEGACY_VERB, "warn"],
468
526
  [INVALID_PROPERTY_REGISTRATION, "error"],
@@ -472,7 +530,6 @@ const DIAGNOSTIC_SEVERITY = /* @__PURE__ */ new Map([
472
530
  [PROPERTY_SELF_REFERENCE, "warn"],
473
531
  [PROPERTY_FALLBACK_SELF_REFERENCE, "warn"],
474
532
  [PROPERTY_CURRENT_VAR_CYCLE, "warn"],
475
- [PREFIX_CONTEXTUAL_VARS_UNPREFIXED, "warn"],
476
533
  [PREFIX_NAME_CONFLICT, "error"],
477
534
  [PROPERTY_LEGACY_TOKEN_COLLISION, "warn"],
478
535
  [PROPERTY_TOKEN_COLLISION, "error"]
@@ -527,15 +584,6 @@ function systemLoadDiagnostics(system) {
527
584
  code: INVALID_PROPERTY_REGISTRATION,
528
585
  severity: severityFor(INVALID_PROPERTY_REGISTRATION)
529
586
  }));
530
- const prefixed = system.legacyPrefixedContextualVars ?? [];
531
- const unprefixed = prefixed.length === 0 ? [] : [{
532
- file: "system",
533
- component: "prefix",
534
- kind: "warn",
535
- message: `the prefix renames the contextual variables ${prefixed.join(", ")}, but their declared names are still read and written as written, so scale reads of them fail and their writes miss. Set prefixContextualVars: true to resolve them under the prefix (${PREFIX_CONTEXTUAL_VARS_UNPREFIXED})`,
536
- code: PREFIX_CONTEXTUAL_VARS_UNPREFIXED,
537
- severity: severityFor(PREFIX_CONTEXTUAL_VARS_UNPREFIXED)
538
- }];
539
587
  const conflicts = (system.prefixNameConflicts ?? []).map(({ name, final, reason }) => ({
540
588
  file: "system",
541
589
  component: `--${name}`,
@@ -547,7 +595,6 @@ function systemLoadDiagnostics(system) {
547
595
  return [
548
596
  ...vocabularyWitnessDiagnostics(system.vocabularyWitnessesJson),
549
597
  ...registrations,
550
- ...unprefixed,
551
598
  ...conflicts,
552
599
  ...tokenCollisionDiagnostics(system)
553
600
  ];
@@ -583,13 +630,14 @@ function tokenCollisionDiagnostics(system) {
583
630
  }
584
631
  /**
585
632
  * The single strict-escalation policy point for both extraction plugins:
586
- * error-severity diagnostics throw together under `strict`, else warn.
633
+ * error-severity diagnostics throw together under `strict`, else warn. A
634
+ * development session reports them through `reportErrors` instead.
587
635
  */
588
636
  function surfaceManifestDiagnostics(manifest, warn, policy = {}) {
589
- const errors = [];
637
+ const errors = /* @__PURE__ */ new Set();
590
638
  if (policy.levels && policy.knownCodes && !checkedLevels.has(policy.levels)) {
591
639
  checkedLevels.add(policy.levels);
592
- for (const key of unknownDiagnosticKeys(policy.levels, policy.knownCodes)) warn(`⚠ diagnostics option: '${key}' matches no Animus diagnostic code — check its spelling (a code the system package mints at run time is known only once it is reported)`);
640
+ for (const key of unknownDiagnosticKeys(policy.levels, policy.knownCodes)) warn(key.startsWith(KIND_KEY) ? `⚠ diagnostics option: '${key}' names no diagnostic kind — use kind:bail, kind:skip, kind:warn or kind:error` : `⚠ diagnostics option: '${key}' matches no Animus diagnostic code — check its spelling (a code the system package mints at run time is known only once it is reported)`);
593
641
  }
594
642
  const diagnostics = policy.prepend?.length ? [...policy.prepend, ...manifest.diagnostics ?? []] : manifest.diagnostics ?? [];
595
643
  for (const diagnostic of diagnostics) {
@@ -598,22 +646,28 @@ function surfaceManifestDiagnostics(manifest, warn, policy = {}) {
598
646
  let line = null;
599
647
  const mark = level === "info" ? "ℹ" : "⚠";
600
648
  const message = `${diagnostic.message}${droppedSuffix(diagnostic)}`;
601
- if (diagnostic.kind === "bail") line = `${mark} ${locatedPrefix(diagnostic)}${diagnostic.component} not extracted: ${message}`;
602
- else if (diagnostic.kind === "skip") line = `${mark} ${locatedPrefix(diagnostic)}${diagnostic.component}: skipped ${message}`;
603
- else if (diagnostic.kind === "warn") line = `${mark} ${locationOf(diagnostic)}: ${diagnostic.component}: ${message}`;
649
+ if (diagnostic.kind === "bail") line = `${mark} ${locatedPrefix(diagnostic)}${diagnostic.component} not extracted: ${message}${codeSuffix(diagnostic)}`;
650
+ else if (diagnostic.kind === "skip") line = `${mark} ${locatedPrefix(diagnostic)}${diagnostic.component}: skipped ${message}${codeSuffix(diagnostic)}`;
651
+ else if (diagnostic.kind === "warn" || diagnostic.kind === "error") line = `${mark} ${warnLine(diagnostic)}`;
604
652
  if (line === null) continue;
605
- if (diagnostic.code && !diagnostic.message.includes(diagnostic.code)) line += ` [${diagnostic.code}]`;
606
653
  if (level === "info") {
607
654
  policy.info?.(line);
608
655
  continue;
609
656
  }
610
657
  if (level === "error") {
611
- errors.push(`${diagnostic.code ?? "error"} — ${locatedPrefix(diagnostic)}${diagnostic.component}: ${message}`);
658
+ const subject = diagnostic.kind === "warn" || diagnostic.kind === "error" ? `${locationOf(diagnostic)}: ` : locatedPrefix(diagnostic);
659
+ errors.add(`${diagnostic.code ?? "error"} — ${subject}${diagnostic.component}: ${message}`);
612
660
  continue;
613
661
  }
614
662
  warn(line);
615
663
  }
616
- if (errors.length > 0) throw new DiagnosticFailure(`[animus] strict: ${errors.length} error diagnostic(s):\n${errors.join("\n")}`);
664
+ if (errors.size === 0) return;
665
+ const message = `[animus] strict: ${errors.size} error diagnostic(s):\n${[...errors].join("\n")}`;
666
+ if (policy.reportErrors) {
667
+ policy.reportErrors(message);
668
+ return;
669
+ }
670
+ throw new DiagnosticFailure(message);
617
671
  }
618
672
  //#endregion
619
673
  //#region pipeline/mdx-preprocessor.ts
@@ -1580,7 +1634,8 @@ function createSourceIngestor(host) {
1580
1634
  const fatal = diagnostics.filter((diagnostic) => !isAdvisorySourceDiagnostic(diagnostic));
1581
1635
  const invalidOriginals = new Set(fatal.map((diagnostic) => diagnostic.originalPath));
1582
1636
  if (diagnostics.length === 0) return invalidOriginals;
1583
- if (host.strict() && fatal.length > 0) {
1637
+ const reportError = host.strict() ? host.reportErrors?.() : void 0;
1638
+ if (host.strict() && fatal.length > 0 && !reportError) {
1584
1639
  const lines = fatal.map((diagnostic) => `${diagnostic.code} ${diagnostic.originalPath}: ${diagnostic.message} (${SKIPPED_SOURCE_COST})`);
1585
1640
  throw new Error(`${host.prefix} ${lines.join(`\n${host.prefix} `)}`);
1586
1641
  }
@@ -1594,7 +1649,8 @@ function createSourceIngestor(host) {
1594
1649
  }
1595
1650
  if (warned.has(line)) continue;
1596
1651
  warned.add(line);
1597
- host.warn(`${host.prefix} ${line}`);
1652
+ if (reportError && skipped) reportError(`${host.prefix} ${line}`);
1653
+ else host.warn(`${host.prefix} ${line}`);
1598
1654
  }
1599
1655
  return invalidOriginals;
1600
1656
  },
@@ -1621,8 +1677,9 @@ function createV2EngineApi(deps) {
1621
1677
  return {
1622
1678
  loadSystemModule: (...args) => native.loadSystemModule(...args),
1623
1679
  extractFacts: (filesJson) => native.extractFacts(filesJson),
1680
+ moduleSpecifiers: (filesJson) => native.moduleSpecifiers(filesJson),
1624
1681
  diagnosticCodes: () => native.diagnosticCodes(),
1625
- analyzeProject: (filesJsonRaw, scalesJson, variableMapJson, contextualVarsJson, propConfigJson, groupRegistryJson, packageResolutionJson, devMode, emitterConfigJson, selectorAliasesJson, _selectorOrderJson, globalStyleBlocksJson, pathAliasesJson, keyframesJson, staticCssJson, conditionAliasesJson, externalDirsJson, transformSourcesJson, transformProvenanceJson, declarationScalesJson, analysisContextJson) => {
1682
+ analyzeProject: (filesJsonRaw, scalesJson, variableMapJson, contextualVarsJson, propConfigJson, groupRegistryJson, packageResolutionJson, devMode, emitterConfigJson, selectorAliasesJson, _selectorOrderJson, globalStyleBlocksJson, pathAliasesJson, keyframesJson, staticCssJson, conditionAliasesJson, externalDirsJson, transformSourcesJson, transformProvenanceJson, declarationScalesJson, analysisContextJson, generatedNamesJson) => {
1626
1683
  const filesJson = deps.rehydrateFilesJson ? deps.rehydrateFilesJson(filesJsonRaw) : filesJsonRaw;
1627
1684
  const sent = /* @__PURE__ */ new Map();
1628
1685
  for (const entry of parseFilesJson(filesJson, label)) sent.set(entry.path, entry.source);
@@ -1650,6 +1707,7 @@ function createV2EngineApi(deps) {
1650
1707
  transformProvenanceJson: transformProvenanceJson ?? void 0,
1651
1708
  declarationScalesJson,
1652
1709
  analysisContextJson,
1710
+ generatedNamesJson,
1653
1711
  devMode
1654
1712
  };
1655
1713
  const engine = new native.ExtractEngine(config);
@@ -1972,7 +2030,7 @@ function walkFiles(dir, rootDir, exclude, extensionsSet) {
1972
2030
  const isExcluded = exclude ? (full, rel) => exclude.matches(full, rel) : () => false;
1973
2031
  for (const entry of entries) {
1974
2032
  const fullPath = join$1(dir, entry);
1975
- if (isExcluded(fullPath, relative(rootDir, fullPath))) continue;
2033
+ if (isExcluded(fullPath, relative$1(rootDir, fullPath))) continue;
1976
2034
  let stat;
1977
2035
  try {
1978
2036
  stat = statSync(fullPath);
@@ -1980,119 +2038,11 @@ function walkFiles(dir, rootDir, exclude, extensionsSet) {
1980
2038
  continue;
1981
2039
  }
1982
2040
  if (stat.isDirectory()) results.push(...walkFiles(fullPath, rootDir, exclude, extensionsSet));
1983
- else if (extensionsSet.has(extname(entry))) results.push(fullPath);
2041
+ else if (extensionsSet.has(extname$1(entry))) results.push(fullPath);
1984
2042
  }
1985
2043
  return results;
1986
2044
  }
1987
2045
  //#endregion
1988
- //#region pipeline/source-identity.ts
1989
- /**
1990
- * One derivation of source identity for discovery, watch ingestion, ownership
1991
- * and deletion: event paths are lookup INPUTS only and never fork identity.
1992
- */
1993
- /**
1994
- * True when `target` is `root` or a descendant, decided by `relative()`
1995
- * shape: string prefixing would let `/ui` claim `/ui-old`.
1996
- */
1997
- function isPathWithinRoot(root, target, pathApi = path) {
1998
- const rel = pathApi.relative(root, target);
1999
- return rel === "" || !pathApi.isAbsolute(rel) && rel !== ".." && !rel.startsWith(".." + pathApi.sep);
2000
- }
2001
- /**
2002
- * True when two paths share a platform root (win32 drive letter or UNC
2003
- * share; always true on posix). Drive letters compare case-insensitively.
2004
- */
2005
- function sharesVolumeRoot(a, b, pathApi = path) {
2006
- const volumeOf = (p) => pathApi.parse(pathApi.resolve(p)).root.toLowerCase();
2007
- return volumeOf(a) === volumeOf(b);
2008
- }
2009
- function canonicalize(p) {
2010
- try {
2011
- return realpathSync$1(p);
2012
- } catch {
2013
- return null;
2014
- }
2015
- }
2016
- function createSourceIdentity(rootDir) {
2017
- const normalizedRootDir = path.normalize(rootDir);
2018
- const canonicalRootDir = canonicalize(normalizedRootDir) ?? normalizedRootDir;
2019
- const roots = [];
2020
- const aliases = /* @__PURE__ */ new Map();
2021
- const owningRecord = (canonicalPath) => {
2022
- let owner = null;
2023
- for (const record of roots) {
2024
- if (!isPathWithinRoot(record.canonical, canonicalPath)) continue;
2025
- if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2026
- }
2027
- return owner;
2028
- };
2029
- return {
2030
- rootDir: normalizedRootDir,
2031
- canonicalRootDir,
2032
- registerExternalRoot(root) {
2033
- const asRegistered = path.normalize(root);
2034
- const canonical = canonicalize(asRegistered) ?? asRegistered;
2035
- const existing = roots.find((record) => record.canonical === canonical);
2036
- if (existing) return existing.canonical;
2037
- roots.push({
2038
- asRegistered,
2039
- canonical
2040
- });
2041
- return canonical;
2042
- },
2043
- externalRoots() {
2044
- return roots.map((record) => record.canonical);
2045
- },
2046
- resolveSourceId(inputPath) {
2047
- const lexical = path.normalize(inputPath);
2048
- const canonical = canonicalize(lexical);
2049
- if (canonical === null) return null;
2050
- const owner = owningRecord(canonical);
2051
- const ownedBy = (record) => {
2052
- const pathInRoot = path.relative(record.canonical, canonical);
2053
- return {
2054
- sourceKey: path.relative(normalizedRootDir, path.join(record.asRegistered, pathInRoot)),
2055
- owningRoot: record.canonical,
2056
- pathInRoot
2057
- };
2058
- };
2059
- const ownerIsMoreSpecific = owner !== null && owner.canonical.length > canonicalRootDir.length;
2060
- let resolved;
2061
- if (!ownerIsMoreSpecific && isPathWithinRoot(canonicalRootDir, canonical)) {
2062
- const key = path.relative(canonicalRootDir, canonical);
2063
- resolved = {
2064
- sourceKey: key,
2065
- owningRoot: null,
2066
- pathInRoot: key
2067
- };
2068
- } else if (owner) resolved = ownedBy(owner);
2069
- else return null;
2070
- aliases.set(lexical, resolved);
2071
- aliases.set(canonical, resolved);
2072
- return resolved;
2073
- },
2074
- resolveDeletedSourceId(inputPath) {
2075
- return aliases.get(path.normalize(inputPath)) ?? null;
2076
- },
2077
- containingExternalRoot(inputPath) {
2078
- const lexical = path.normalize(inputPath);
2079
- let owner = null;
2080
- for (const record of roots) {
2081
- if (!(isPathWithinRoot(record.canonical, lexical) || isPathWithinRoot(record.asRegistered, lexical))) continue;
2082
- if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2083
- }
2084
- if (owner) return owner.canonical;
2085
- const canonical = canonicalize(lexical);
2086
- if (canonical === null) return null;
2087
- for (const record of roots) {
2088
- if (!isPathWithinRoot(record.canonical, canonical)) continue;
2089
- if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2090
- }
2091
- return owner?.canonical ?? null;
2092
- }
2093
- };
2094
- }
2095
- //#endregion
2096
2046
  //#region pipeline/tsconfig-paths.ts
2097
2047
  /**
2098
2048
  * tsconfig `paths` → alias pairs, for drivers with no live bundler config.
@@ -2199,8 +2149,8 @@ function readConfig(path) {
2199
2149
  };
2200
2150
  }
2201
2151
  function resolveExtendsTarget(specifier, fromDir) {
2202
- if (specifier.startsWith(".") || isAbsolute(specifier)) {
2203
- const base = resolve(fromDir, specifier);
2152
+ if (specifier.startsWith(".") || isAbsolute$1(specifier)) {
2153
+ const base = resolve$1(fromDir, specifier);
2204
2154
  for (const candidate of [
2205
2155
  base,
2206
2156
  `${base}.json`,
@@ -2225,7 +2175,7 @@ function loadChain(entryPath) {
2225
2175
  const queue = [entryPath];
2226
2176
  while (queue.length > 0) {
2227
2177
  const path = queue.shift();
2228
- const key = resolve(path);
2178
+ const key = resolve$1(path);
2229
2179
  if (visited.has(key)) continue;
2230
2180
  visited.add(key);
2231
2181
  const node = readConfig(key);
@@ -2250,7 +2200,7 @@ function readTsconfigAliasPairs(rootDir) {
2250
2200
  if (pathsOwner === void 0 || paths === null) return [];
2251
2201
  const baseOwner = chain.find((node) => node.baseUrl !== null);
2252
2202
  const baseUrl = baseOwner?.baseUrl ?? null;
2253
- const base = baseOwner !== void 0 && baseUrl !== null ? resolve(baseOwner.dir, baseUrl) : pathsOwner.dir;
2203
+ const base = baseOwner !== void 0 && baseUrl !== null ? resolve$1(baseOwner.dir, baseUrl) : pathsOwner.dir;
2254
2204
  const pairs = [];
2255
2205
  for (const [pattern, target] of paths) {
2256
2206
  const patternStars = pattern.split("*").length - 1;
@@ -2260,7 +2210,7 @@ function readTsconfigAliasPairs(rootDir) {
2260
2210
  if (!target.endsWith("/*")) continue;
2261
2211
  pairs.push({
2262
2212
  pattern: pattern.slice(0, -2),
2263
- target: resolve(base, target.slice(0, -2)),
2213
+ target: resolve$1(base, target.slice(0, -2)),
2264
2214
  kind: "prefix"
2265
2215
  });
2266
2216
  continue;
@@ -2268,13 +2218,223 @@ function readTsconfigAliasPairs(rootDir) {
2268
2218
  if (patternStars > 0 || targetStars > 0) continue;
2269
2219
  pairs.push({
2270
2220
  pattern,
2271
- target: resolve(base, target),
2221
+ target: resolve$1(base, target),
2272
2222
  kind: "exact"
2273
2223
  });
2274
2224
  }
2275
2225
  return pairs;
2276
2226
  }
2277
2227
  //#endregion
2228
+ //#region pipeline/kit-descriptor.ts
2229
+ /** A kit's description, which `animus build --kit` writes at its package
2230
+ * root and the kit exports as `./animus.json`. */
2231
+ const KIT_DESCRIPTOR_FILE = "animus.json";
2232
+ /** A path with `/` separators, as descriptors key their components. */
2233
+ function posixPath$1(path) {
2234
+ return path.split(sep).join("/");
2235
+ }
2236
+ /** The descriptor of the kit a build analysed. */
2237
+ function buildKitDescriptor(manifest) {
2238
+ const components = {};
2239
+ for (const id of Object.keys(manifest.components).sort()) {
2240
+ const component = manifest.components[id];
2241
+ components[posixPath$1(id)] = {
2242
+ definition: component.definition_fingerprint,
2243
+ runtimeProps: [...new Set(component.system_prop_names)].sort()
2244
+ };
2245
+ }
2246
+ return {
2247
+ format: 1,
2248
+ system: manifest.system_fingerprint,
2249
+ components
2250
+ };
2251
+ }
2252
+ /** Reads the descriptor at a kit's package root; `null` when it has none. */
2253
+ function readKitDescriptor(pkgRoot, rootDir) {
2254
+ const path = join(pkgRoot, KIT_DESCRIPTOR_FILE);
2255
+ if (!existsSync$1(path)) return null;
2256
+ const packageRoot = posixPath$1(relative(rootDir, pkgRoot));
2257
+ let wire;
2258
+ try {
2259
+ wire = JSON.parse(readFileSync$1(path, "utf-8"));
2260
+ } catch {
2261
+ return {
2262
+ packageRoot,
2263
+ unreadable: "is not valid JSON: rebuild it with animus build --kit"
2264
+ };
2265
+ }
2266
+ const block = isJsonBlock(wire) ? wire : {};
2267
+ if (block.format !== 1) return {
2268
+ packageRoot,
2269
+ unreadable: `declares descriptor format ${JSON.stringify(block.format ?? null)}, which this Animus does not read (it reads format 1): upgrade Animus, or install a kit built for this version`
2270
+ };
2271
+ const definitions = {};
2272
+ const components = isJsonBlock(block.components) ? block.components : {};
2273
+ for (const [id, component] of Object.entries(components)) {
2274
+ const definition = isJsonBlock(component) ? component.definition : null;
2275
+ if (isJsonString(definition)) definitions[posixPath$1(id)] = definition;
2276
+ }
2277
+ return {
2278
+ packageRoot,
2279
+ definitions
2280
+ };
2281
+ }
2282
+ /**
2283
+ * A descriptor in a format this Animus cannot read fails the build; one
2284
+ * whose component definitions differ from the kit's shipped source, as the
2285
+ * analysis read it, or that describes a component its analysed file no
2286
+ * longer declares, was built from other source and is stale.
2287
+ */
2288
+ function kitDescriptorDiagnostics(records, manifest) {
2289
+ if (records.length === 0) return [];
2290
+ const diagnostics = [];
2291
+ const analysedById = new Map(Object.entries(manifest.components).map(([id, component]) => [posixPath$1(id), component]));
2292
+ const analysedFiles = new Set(Object.keys(manifest.fileFacts).map(posixPath$1));
2293
+ const declared = new Set(Object.entries(manifest.fileFacts).flatMap(([file, facts]) => facts.chains.map((chain) => `${posixPath$1(file)}::${chain.descriptor.binding}`)));
2294
+ for (const record of records) {
2295
+ const file = `${record.packageRoot}/${KIT_DESCRIPTOR_FILE}`;
2296
+ if ("unreadable" in record) {
2297
+ diagnostics.push({
2298
+ file,
2299
+ component: "kit",
2300
+ kind: "error",
2301
+ message: record.unreadable,
2302
+ code: KIT_UNSUPPORTED_FORMAT,
2303
+ severity: severityFor(KIT_UNSUPPORTED_FORMAT)
2304
+ });
2305
+ continue;
2306
+ }
2307
+ for (const [id, definition] of Object.entries(record.definitions)) {
2308
+ const key = `${record.packageRoot}/${id}`;
2309
+ const analysed = analysedById.get(key);
2310
+ const fileAnalysed = analysedFiles.has(key.slice(0, key.lastIndexOf("::")));
2311
+ let stale;
2312
+ if (analysed) {
2313
+ if (analysed.definition_fingerprint === definition) continue;
2314
+ stale = `describes ${id} with a definition other than the one its shipped source declares`;
2315
+ } else if (fileAnalysed && !declared.has(key)) stale = `describes ${id}, which its shipped source no longer declares`;
2316
+ else continue;
2317
+ diagnostics.push({
2318
+ file,
2319
+ component: analysed?.binding ?? id.slice(id.lastIndexOf("::") + 2),
2320
+ kind: "warn",
2321
+ message: `${stale}, so the descriptor is stale: rebuild it with animus build --kit`,
2322
+ code: KIT_STALE_DESCRIPTOR,
2323
+ severity: severityFor(KIT_STALE_DESCRIPTOR)
2324
+ });
2325
+ }
2326
+ }
2327
+ return diagnostics;
2328
+ }
2329
+ //#endregion
2330
+ //#region pipeline/source-identity.ts
2331
+ /**
2332
+ * One derivation of source identity for discovery, watch ingestion, ownership
2333
+ * and deletion: event paths are lookup INPUTS only and never fork identity.
2334
+ */
2335
+ /**
2336
+ * True when `target` is `root` or a descendant, decided by `relative()`
2337
+ * shape: string prefixing would let `/ui` claim `/ui-old`.
2338
+ */
2339
+ function isPathWithinRoot(root, target, pathApi = path) {
2340
+ const rel = pathApi.relative(root, target);
2341
+ return rel === "" || !pathApi.isAbsolute(rel) && rel !== ".." && !rel.startsWith(".." + pathApi.sep);
2342
+ }
2343
+ /**
2344
+ * True when two paths share a platform root (win32 drive letter or UNC
2345
+ * share; always true on posix). Drive letters compare case-insensitively.
2346
+ */
2347
+ function sharesVolumeRoot(a, b, pathApi = path) {
2348
+ const volumeOf = (p) => pathApi.parse(pathApi.resolve(p)).root.toLowerCase();
2349
+ return volumeOf(a) === volumeOf(b);
2350
+ }
2351
+ function canonicalize(p) {
2352
+ try {
2353
+ return realpathSync$1(p);
2354
+ } catch {
2355
+ return null;
2356
+ }
2357
+ }
2358
+ function createSourceIdentity(rootDir) {
2359
+ const normalizedRootDir = path.normalize(rootDir);
2360
+ const canonicalRootDir = canonicalize(normalizedRootDir) ?? normalizedRootDir;
2361
+ const roots = [];
2362
+ const aliases = /* @__PURE__ */ new Map();
2363
+ const owningRecord = (canonicalPath) => {
2364
+ let owner = null;
2365
+ for (const record of roots) {
2366
+ if (!isPathWithinRoot(record.canonical, canonicalPath)) continue;
2367
+ if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2368
+ }
2369
+ return owner;
2370
+ };
2371
+ return {
2372
+ rootDir: normalizedRootDir,
2373
+ canonicalRootDir,
2374
+ registerExternalRoot(root) {
2375
+ const asRegistered = path.normalize(root);
2376
+ const canonical = canonicalize(asRegistered) ?? asRegistered;
2377
+ const existing = roots.find((record) => record.canonical === canonical);
2378
+ if (existing) return existing.canonical;
2379
+ roots.push({
2380
+ asRegistered,
2381
+ canonical
2382
+ });
2383
+ return canonical;
2384
+ },
2385
+ externalRoots() {
2386
+ return roots.map((record) => record.canonical);
2387
+ },
2388
+ resolveSourceId(inputPath) {
2389
+ const lexical = path.normalize(inputPath);
2390
+ const canonical = canonicalize(lexical);
2391
+ if (canonical === null) return null;
2392
+ const owner = owningRecord(canonical);
2393
+ const ownedBy = (record) => {
2394
+ const pathInRoot = path.relative(record.canonical, canonical);
2395
+ return {
2396
+ sourceKey: path.relative(normalizedRootDir, path.join(record.asRegistered, pathInRoot)),
2397
+ owningRoot: record.canonical,
2398
+ pathInRoot
2399
+ };
2400
+ };
2401
+ const ownerIsMoreSpecific = owner !== null && owner.canonical.length > canonicalRootDir.length;
2402
+ let resolved;
2403
+ if (!ownerIsMoreSpecific && isPathWithinRoot(canonicalRootDir, canonical)) {
2404
+ const key = path.relative(canonicalRootDir, canonical);
2405
+ resolved = {
2406
+ sourceKey: key,
2407
+ owningRoot: null,
2408
+ pathInRoot: key
2409
+ };
2410
+ } else if (owner) resolved = ownedBy(owner);
2411
+ else return null;
2412
+ aliases.set(lexical, resolved);
2413
+ aliases.set(canonical, resolved);
2414
+ return resolved;
2415
+ },
2416
+ resolveDeletedSourceId(inputPath) {
2417
+ return aliases.get(path.normalize(inputPath)) ?? null;
2418
+ },
2419
+ containingExternalRoot(inputPath) {
2420
+ const lexical = path.normalize(inputPath);
2421
+ let owner = null;
2422
+ for (const record of roots) {
2423
+ if (!(isPathWithinRoot(record.canonical, lexical) || isPathWithinRoot(record.asRegistered, lexical))) continue;
2424
+ if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2425
+ }
2426
+ if (owner) return owner.canonical;
2427
+ const canonical = canonicalize(lexical);
2428
+ if (canonical === null) return null;
2429
+ for (const record of roots) {
2430
+ if (!isPathWithinRoot(record.canonical, canonical)) continue;
2431
+ if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2432
+ }
2433
+ return owner?.canonical ?? null;
2434
+ }
2435
+ };
2436
+ }
2437
+ //#endregion
2278
2438
  //#region pipeline/discover-packages.ts
2279
2439
  function findPackageRoot(absEntryPath) {
2280
2440
  let pkgRoot = dirname$1(absEntryPath);
@@ -2291,7 +2451,7 @@ function isExcludedPackageRelativePath(rel) {
2291
2451
  return PACKAGE_SRC_EXCLUDES.some((pattern) => rel.includes(pattern));
2292
2452
  }
2293
2453
  function walkPackageSources(packageDir, extensionsSet) {
2294
- return discoverFiles(packageDir, packageDir, void 0, extensionsSet).filter((absPath) => !isExcludedPackageRelativePath(relative(packageDir, absPath)));
2454
+ return discoverFiles(packageDir, packageDir, void 0, extensionsSet).filter((absPath) => !isExcludedPackageRelativePath(relative$1(packageDir, absPath)));
2295
2455
  }
2296
2456
  const PACKAGE_OUTPUT_EXCLUDES = [
2297
2457
  "node_modules",
@@ -2300,7 +2460,7 @@ const PACKAGE_OUTPUT_EXCLUDES = [
2300
2460
  ".d.ts",
2301
2461
  ".map"
2302
2462
  ];
2303
- const isFile = (path) => {
2463
+ const isFile$1 = (path) => {
2304
2464
  try {
2305
2465
  return statSync(path).isFile();
2306
2466
  } catch {
@@ -2312,14 +2472,15 @@ function resolveAbsolutePathSpecifier(absSpecifier, extensionsSet) {
2312
2472
  absSpecifier,
2313
2473
  ...Array.from(extensionsSet, (ext) => absSpecifier + ext),
2314
2474
  ...Array.from(extensionsSet, (ext) => join$1(absSpecifier, `index${ext}`))
2315
- ].find(isFile) ?? null;
2475
+ ].find(isFile$1) ?? null;
2316
2476
  }
2477
+ /** The package a bare specifier names: `@scope/name` or `name`. */
2317
2478
  function bareSpecifierPackageName(specifier) {
2318
2479
  const segments = specifier.split("/");
2319
2480
  return specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
2320
2481
  }
2321
2482
  function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
2322
- if (isAbsolute(specifier)) {
2483
+ if (isAbsolute$1(specifier)) {
2323
2484
  const resolved = resolveAbsolutePathSpecifier(specifier, extensionsSet);
2324
2485
  if (!resolved) return null;
2325
2486
  return isPathWithinRoot(srcDir, resolved) ? resolved : null;
@@ -2328,6 +2489,76 @@ function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
2328
2489
  const subpath = specifier.slice(packageName.length + 1);
2329
2490
  return resolveAbsolutePathSpecifier(join$1(srcDir, subpath || "index"), extensionsSet);
2330
2491
  }
2492
+ /** The package's parsed `package.json`, or null when it cannot be read. */
2493
+ function readPackageManifest(pkgRoot) {
2494
+ try {
2495
+ return JSON.parse(readFileSync(join$1(pkgRoot, "package.json"), "utf-8"));
2496
+ } catch {
2497
+ return null;
2498
+ }
2499
+ }
2500
+ /** Each `exports` subpath and its value; a bare target or condition object
2501
+ * is the `.` entry. */
2502
+ function exportsSubpaths(manifest) {
2503
+ const exports = isJsonBlock(manifest) ? manifest.exports : void 0;
2504
+ if (exports === void 0 || exports === null) return [];
2505
+ const subpaths = isJsonBlock(exports) && Object.keys(exports).some((k) => k.startsWith(".")) ? exports : { ".": exports };
2506
+ return Object.entries(subpaths).filter(([subpath]) => subpath.startsWith("."));
2507
+ }
2508
+ /**
2509
+ * The export condition a kit gives each public entry's original source:
2510
+ * `{ "types": …, "animus": "./src/system.ts", "import": …, "default": … }`.
2511
+ * Hosts never resolve through it; discovery reads it, redirects the entry to
2512
+ * its source in every host, and the system loader prefers it.
2513
+ */
2514
+ const KIT_SOURCE_CONDITION = "animus";
2515
+ /** The package's kit source condition, or null when no exact `exports`
2516
+ * entry declares it: the package is no source kit. */
2517
+ function readKitSourceCondition(pkgRoot) {
2518
+ const condition = {
2519
+ entries: [],
2520
+ invalid: [],
2521
+ root: null
2522
+ };
2523
+ for (const [subpath, value] of exportsSubpaths(readPackageManifest(pkgRoot))) {
2524
+ if (subpath.includes("*") || !isJsonBlock(value)) continue;
2525
+ const target = value[KIT_SOURCE_CONDITION];
2526
+ if (!isJsonString(target)) continue;
2527
+ const file = resolve$1(pkgRoot, target);
2528
+ if (isPathWithinRoot(pkgRoot, file) && isFile$1(file)) condition.entries.push([subpath, file]);
2529
+ else condition.invalid.push([subpath, target]);
2530
+ }
2531
+ if (condition.entries.length === 0 && condition.invalid.length === 0) return null;
2532
+ condition.root = condition.entries.reduce((root, [, file]) => root === null ? dirname$1(file) : commonDirectory(root, dirname$1(file)), null);
2533
+ return condition;
2534
+ }
2535
+ function commonDirectory(a, b) {
2536
+ let dir = a;
2537
+ while (!isPathWithinRoot(dir, b)) dir = dirname$1(dir);
2538
+ return dir;
2539
+ }
2540
+ /** Whether the manifest at `dir` names the package `name`. */
2541
+ function isPackageNamed(dir, name) {
2542
+ const manifest = readPackageManifest(dir);
2543
+ return isJsonBlock(manifest) && manifest.name === name;
2544
+ }
2545
+ function realPath(path) {
2546
+ try {
2547
+ return realpathSync(path);
2548
+ } catch {
2549
+ return path;
2550
+ }
2551
+ }
2552
+ /** The root of the installed package `name` as Node finds it from `fromDir`,
2553
+ * the first `node_modules/<name>` up the directory tree, at its real path,
2554
+ * as host resolvers report a linked package. */
2555
+ function locatePackageRoot(name, fromDir) {
2556
+ for (let dir = fromDir;; dir = dirname$1(dir)) {
2557
+ const candidate = join$1(dir, "node_modules", name);
2558
+ if (existsSync(join$1(candidate, "package.json"))) return realPath(candidate);
2559
+ if (dir === dirname$1(dir)) return null;
2560
+ }
2561
+ }
2331
2562
  /**
2332
2563
  * A package's `sideEffects` field, decoded the way Vite reads it: a boolean
2333
2564
  * as written, or the list's globs, one with no `/` matching the basename
@@ -2336,12 +2567,7 @@ function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
2336
2567
  * extglobs), which leaves the bundler's side-effectful default.
2337
2568
  */
2338
2569
  function readPackageSideEffects(pkgRoot) {
2339
- let manifest;
2340
- try {
2341
- manifest = JSON.parse(readFileSync(join$1(pkgRoot, "package.json"), "utf-8"));
2342
- } catch {
2343
- return;
2344
- }
2570
+ const manifest = readPackageManifest(pkgRoot);
2345
2571
  const field = isJsonBlock(manifest) ? manifest.sideEffects : void 0;
2346
2572
  if (field === true || field === false) return field;
2347
2573
  if (!Array.isArray(field)) return void 0;
@@ -2349,9 +2575,80 @@ function readPackageSideEffects(pkgRoot) {
2349
2575
  if (globs.some((glob) => /[{}[\]()!+@]/.test(glob))) return void 0;
2350
2576
  return globs.map((glob) => globToRegExp(glob.includes("/") ? glob.replace(/^\.?\//, "") : `**/${glob}`));
2351
2577
  }
2578
+ /** Whether a bundler that reads the nearest `package.json`'s `sideEffects`
2579
+ * against the file's own path keeps `absFile`; undefined without a field
2580
+ * it reads, which keeps the bundler's side-effectful default. */
2581
+ function fileSideEffects(absFile) {
2582
+ const pkgRoot = findPackageRoot(absFile);
2583
+ const field = readPackageSideEffects(pkgRoot);
2584
+ if (field === void 0 || field === true || field === false) return field;
2585
+ return matchesSideEffects(field, pkgRoot, [absFile]);
2586
+ }
2587
+ /** Whether a `sideEffects` glob can name a code file: a last segment with
2588
+ * no extension can name any file, and an extension with glob syntax or of
2589
+ * a script can name code; `*.css` cannot. Brace alternatives are each read,
2590
+ * and braces this reading cannot expand count as naming code. */
2591
+ function globNamesCode(glob) {
2592
+ const alternatives = expandBraces(glob);
2593
+ if (alternatives === null) return true;
2594
+ return alternatives.some((alternative) => {
2595
+ const last = alternative.split("/").at(-1) ?? "";
2596
+ const dot = last.lastIndexOf(".");
2597
+ if (dot === -1) return true;
2598
+ const extension = last.slice(dot + 1);
2599
+ return /[*?[]/.test(extension) || /^[cm]?[jt]sx?$/.test(extension);
2600
+ });
2601
+ }
2602
+ /** Every alternative a glob's `{a,b}` groups spell, nested groups included;
2603
+ * null when its braces do not balance. */
2604
+ function expandBraces(glob) {
2605
+ const open = glob.indexOf("{");
2606
+ if (open === -1) return glob.includes("}") ? null : [glob];
2607
+ let depth = 0;
2608
+ const commas = [];
2609
+ for (let at = open; at < glob.length; at++) if (glob[at] === "{") depth++;
2610
+ else if (glob[at] === "," && depth === 1) commas.push(at);
2611
+ else if (glob[at] === "}" && --depth === 0) {
2612
+ const bounds = [
2613
+ open,
2614
+ ...commas,
2615
+ at
2616
+ ];
2617
+ const rest = expandBraces(glob.slice(at + 1));
2618
+ if (rest === null) return null;
2619
+ const expanded = [];
2620
+ for (let i = 0; i < bounds.length - 1; i++) {
2621
+ const inner = expandBraces(glob.slice(bounds[i] + 1, bounds[i + 1]));
2622
+ if (inner === null) return null;
2623
+ for (const middle of inner) for (const tail of rest) expanded.push(glob.slice(0, open) + middle + tail);
2624
+ }
2625
+ return expanded;
2626
+ }
2627
+ return null;
2628
+ }
2629
+ /**
2630
+ * True when a source module of the package that owns `absFile` must stay
2631
+ * side-effectful: its `sideEffects` list names shipped code, and no proven
2632
+ * map takes a shipped file to its source module, so a bundler that reads
2633
+ * the list against the source path can drop a listed effect. Undefined
2634
+ * leaves the bundler's own reading, which no list naming code can mislead.
2635
+ */
2636
+ function kitSourceModuleSideEffects(absFile) {
2637
+ const manifest = readPackageManifest(findPackageRoot(absFile));
2638
+ const field = isJsonBlock(manifest) ? manifest.sideEffects : void 0;
2639
+ if (!Array.isArray(field)) return void 0;
2640
+ return field.some((glob) => isJsonString(glob) && globNamesCode(glob)) ? true : void 0;
2641
+ }
2642
+ /** Whether a host keeps the module at `file` side-effectful: it lies under
2643
+ * one of the discovered kit source directories, and its package's list
2644
+ * could misread it (see `kitSourceModuleSideEffects`). A host asks this of
2645
+ * the resolved module, never of its importer alone. */
2646
+ function keepsKitSourceEffects(file, kitDirs) {
2647
+ return kitDirs.some((dir) => isPathWithinRoot(dir, file)) && kitSourceModuleSideEffects(file) === true;
2648
+ }
2352
2649
  function matchesSideEffects(globs, pkgRoot, absFiles) {
2353
2650
  return absFiles.some((file) => {
2354
- const relPath = relative(pkgRoot, file).split(sep).join("/");
2651
+ const relPath = relative$1(pkgRoot, file).split(sep$1).join("/");
2355
2652
  return globs.some((glob) => glob.test(relPath));
2356
2653
  });
2357
2654
  }
@@ -2372,20 +2669,11 @@ function exportTarget(value) {
2372
2669
  /** Each exact `exports` entry of the package at `pkgRoot`, as its subpath
2373
2670
  * and absolute target; `*` patterns name no single file and are skipped. */
2374
2671
  function packageExportEntries(pkgRoot) {
2375
- let manifest;
2376
- try {
2377
- manifest = JSON.parse(readFileSync(join$1(pkgRoot, "package.json"), "utf-8"));
2378
- } catch {
2379
- return [];
2380
- }
2381
- const exports = isJsonBlock(manifest) ? manifest.exports : void 0;
2382
- if (exports === void 0 || exports === null) return [];
2383
- const subpaths = isJsonBlock(exports) && Object.keys(exports).some((k) => k.startsWith(".")) ? exports : { ".": exports };
2384
2672
  const entries = [];
2385
- for (const [subpath, value] of Object.entries(subpaths)) {
2386
- if (!subpath.startsWith(".") || subpath.includes("*")) continue;
2673
+ for (const [subpath, value] of exportsSubpaths(readPackageManifest(pkgRoot))) {
2674
+ if (subpath.includes("*")) continue;
2387
2675
  const target = exportTarget(value);
2388
- if (target !== null) entries.push([subpath, resolve(pkgRoot, target)]);
2676
+ if (target !== null) entries.push([subpath, resolve$1(pkgRoot, target)]);
2389
2677
  }
2390
2678
  return entries;
2391
2679
  }
@@ -2422,6 +2710,16 @@ async function collectExternalPackageSources(opts) {
2422
2710
  const sourceEntrySideEffects = /* @__PURE__ */ new Map();
2423
2711
  /** `replaced` names the entry the redirect stands in for; it is only
2424
2712
  * needed, and so only resolved, for a glob list. */
2713
+ /** The entry `subpath` of the package resolves to without the redirect.
2714
+ * A resolver with no `import` condition, as Node's `require` has none,
2715
+ * finds no ESM-only entry, so the manifest's own target answers then. */
2716
+ const shippedEntry = async (specifier, pkgRoot, subpath) => {
2717
+ try {
2718
+ const resolved = await resolveSpecifier(specifier);
2719
+ if (resolved) return resolved;
2720
+ } catch {}
2721
+ return packageExportEntries(pkgRoot).find(([entry]) => entry === subpath)?.[1] ?? null;
2722
+ };
2425
2723
  const redirect = async (specifier, srcEntry, pkgRoot, replaced) => {
2426
2724
  sourceEntries.set(specifier, srcEntry);
2427
2725
  const field = readPackageSideEffects(pkgRoot);
@@ -2434,6 +2732,8 @@ async function collectExternalPackageSources(opts) {
2434
2732
  sourceEntrySideEffects.set(specifier, replacedEntry === null || matchesSideEffects(field, pkgRoot, [srcEntry, replacedEntry]));
2435
2733
  };
2436
2734
  const packageDirs = [];
2735
+ const linkedDirs = [];
2736
+ const outputDirs = [];
2437
2737
  const dirOwnerSets = {};
2438
2738
  const dirExtensions = {};
2439
2739
  const fileOwners = {};
@@ -2442,6 +2742,31 @@ async function collectExternalPackageSources(opts) {
2442
2742
  (dirOwnerSets[dir] ??= []).push(specifier);
2443
2743
  };
2444
2744
  const alreadyIngested = (relPath) => hasEntry(relPath) || pushed.has(relPath);
2745
+ /** Adds `file` to the analysis set unless it is there; false when it
2746
+ * cannot be read. */
2747
+ const ingest = (file, specifier) => {
2748
+ const relPath = relative$1(rootDir, file);
2749
+ if (alreadyIngested(relPath)) return true;
2750
+ let source;
2751
+ try {
2752
+ source = readFileSync(file, "utf-8");
2753
+ } catch (err) {
2754
+ onUnreadable(relPath, err);
2755
+ return false;
2756
+ }
2757
+ onSourceRead?.(source, relPath, file);
2758
+ entries.push({
2759
+ path: relPath,
2760
+ source
2761
+ });
2762
+ pushed.add(relPath);
2763
+ fileOwners[relPath] ??= specifier;
2764
+ return true;
2765
+ };
2766
+ const diagnostics = [];
2767
+ const reportedPackages = /* @__PURE__ */ new Set();
2768
+ const kitDescriptors = [];
2769
+ const describedRoots = /* @__PURE__ */ new Set();
2445
2770
  for (const specifier of specifiers) {
2446
2771
  let absEntry;
2447
2772
  try {
@@ -2449,8 +2774,15 @@ async function collectExternalPackageSources(opts) {
2449
2774
  } catch {
2450
2775
  absEntry = null;
2451
2776
  }
2452
- if (!absEntry && isAbsolute(specifier)) absEntry = resolveAbsolutePathSpecifier(specifier, extensionsSet);
2453
- if (!absEntry) {
2777
+ if (!absEntry && isAbsolute$1(specifier)) absEntry = resolveAbsolutePathSpecifier(specifier, extensionsSet);
2778
+ const packageName = isAbsolute$1(specifier) ? null : bareSpecifierPackageName(specifier);
2779
+ const resolvedRoot = absEntry ? findPackageRoot(absEntry) : null;
2780
+ const locatedRoot = packageName && locatePackageRoot(packageName, rootDir);
2781
+ const pkgRoot = resolvedRoot && (!locatedRoot || isPackageNamed(resolvedRoot, packageName) || realPath(resolvedRoot) === locatedRoot) ? resolvedRoot : locatedRoot || resolvedRoot;
2782
+ const condition = packageName && pkgRoot ? readKitSourceCondition(pkgRoot) : null;
2783
+ const entryKey = packageName && `.${specifier.slice(packageName.length)}`;
2784
+ absEntry ??= condition?.entries.find(([entry]) => entry === entryKey)?.[1] ?? null;
2785
+ if (!absEntry || !pkgRoot) {
2454
2786
  outcomes.push({
2455
2787
  specifier,
2456
2788
  outcome: "unresolvable",
@@ -2458,106 +2790,82 @@ async function collectExternalPackageSources(opts) {
2458
2790
  });
2459
2791
  continue;
2460
2792
  }
2461
- const pkgRoot = findPackageRoot(absEntry);
2793
+ const realRoot = realPath(pkgRoot);
2794
+ if (!describedRoots.has(realRoot)) {
2795
+ describedRoots.add(realRoot);
2796
+ const described = readKitDescriptor(pkgRoot, rootDir);
2797
+ if (described) kitDescriptors.push(described);
2798
+ }
2799
+ const linked = !isInstalledPackage(pkgRoot);
2462
2800
  const srcDir = join$1(pkgRoot, "src");
2463
2801
  let fileCount = 0;
2464
2802
  let staleDist = false;
2465
- if (existsSync(srcDir)) {
2803
+ if (packageName && !reportedPackages.has(packageName)) {
2804
+ reportedPackages.add(packageName);
2805
+ diagnostics.push(...sourceConditionDiagnostics(packageName, condition));
2806
+ }
2807
+ if (condition && packageName) {
2808
+ for (const [entry, target] of condition.entries) {
2809
+ const entrySpecifier = packageName + entry.slice(1);
2810
+ packageMap[entrySpecifier] = relative$1(rootDir, target);
2811
+ await redirect(entrySpecifier, target, pkgRoot, () => shippedEntry(entrySpecifier, pkgRoot, entry));
2812
+ }
2813
+ packageMap[specifier] ??= relative$1(rootDir, absEntry);
2814
+ if (condition.root) {
2815
+ packageDirs.push(condition.root);
2816
+ if (linked) linkedDirs.push(condition.root);
2817
+ claimDir(condition.root, specifier);
2818
+ dirExtensions[condition.root] = [...extensionsSet];
2819
+ onPackageResolved?.(specifier, condition.root);
2820
+ for (const file of walkPackageSources(condition.root, extensionsSet)) if (ingest(file, specifier)) fileCount++;
2821
+ }
2822
+ } else if (existsSync(srcDir)) {
2466
2823
  packageDirs.push(srcDir);
2824
+ if (linked) linkedDirs.push(srcDir);
2467
2825
  claimDir(srcDir, specifier);
2468
2826
  dirExtensions[srcDir] = [...extensionsSet];
2469
2827
  onPackageResolved?.(specifier, srcDir);
2470
2828
  const srcEntry = sourceEntryForSpecifier(specifier, srcDir, extensionsSet);
2471
2829
  if (srcEntry) {
2472
- packageMap[specifier] = relative(rootDir, srcEntry);
2830
+ packageMap[specifier] = relative$1(rootDir, srcEntry);
2473
2831
  const replaced = absEntry;
2474
2832
  await redirect(specifier, srcEntry, pkgRoot, async () => replaced);
2475
- } else packageMap[specifier] = relative(rootDir, absEntry);
2476
- if (!isAbsolute(specifier)) {
2477
- const packageName = bareSpecifierPackageName(specifier);
2833
+ } else packageMap[specifier] = relative$1(rootDir, absEntry);
2834
+ if (packageName) {
2478
2835
  if (packageName !== specifier && !(packageName in packageMap)) {
2479
2836
  const rootEntry = sourceEntryForSpecifier(packageName, srcDir, extensionsSet);
2480
2837
  if (rootEntry) {
2481
- packageMap[packageName] = relative(rootDir, rootEntry);
2482
- await redirect(packageName, rootEntry, pkgRoot, async () => {
2483
- try {
2484
- return await resolveSpecifier(packageName);
2485
- } catch {
2486
- return null;
2487
- }
2488
- });
2838
+ packageMap[packageName] = relative$1(rootDir, rootEntry);
2839
+ await redirect(packageName, rootEntry, pkgRoot, () => shippedEntry(packageName, pkgRoot, "."));
2489
2840
  }
2490
2841
  }
2491
2842
  }
2492
2843
  const pkgFiles = walkPackageSources(srcDir, extensionsSet);
2493
- staleDist = !isInstalledPackage(pkgRoot) && distEntryIsStale(absEntry, srcDir, pkgFiles);
2494
- for (const pkgFile of pkgFiles) {
2495
- const relPath = relative(rootDir, pkgFile);
2496
- if (alreadyIngested(relPath)) {
2497
- fileCount++;
2498
- continue;
2499
- }
2500
- let source;
2501
- try {
2502
- source = readFileSync(pkgFile, "utf-8");
2503
- } catch (err) {
2504
- onUnreadable(relPath, err);
2505
- continue;
2506
- }
2507
- onSourceRead?.(source, relPath, pkgFile);
2508
- entries.push({
2509
- path: relPath,
2510
- source
2511
- });
2512
- pushed.add(relPath);
2513
- fileOwners[relPath] ??= specifier;
2514
- fileCount++;
2515
- }
2844
+ staleDist = linked && distEntryIsStale(absEntry, srcDir, pkgFiles);
2845
+ for (const pkgFile of pkgFiles) if (ingest(pkgFile, specifier)) fileCount++;
2516
2846
  } else {
2517
2847
  const outputDir = dirname$1(absEntry);
2518
2848
  packageDirs.push(outputDir);
2849
+ if (linked) linkedDirs.push(outputDir);
2850
+ outputDirs.push(outputDir);
2519
2851
  claimDir(outputDir, specifier);
2520
2852
  onPackageResolved?.(specifier, outputDir);
2521
- packageMap[specifier] = relative(rootDir, absEntry);
2853
+ packageMap[specifier] = relative$1(rootDir, absEntry);
2522
2854
  const outputExtensions = new Set(extensionsSet);
2523
- outputExtensions.add(extname(absEntry));
2855
+ outputExtensions.add(extname$1(absEntry));
2524
2856
  dirExtensions[outputDir] = [...outputExtensions];
2525
2857
  const outputFiles = discoverFiles(outputDir, outputDir, void 0, outputExtensions).filter((file) => {
2526
- const relToOutput = relative(outputDir, file);
2858
+ const relToOutput = relative$1(outputDir, file);
2527
2859
  return !PACKAGE_OUTPUT_EXCLUDES.some((pattern) => relToOutput.includes(pattern));
2528
2860
  });
2529
2861
  if (!outputFiles.includes(absEntry)) outputFiles.unshift(absEntry);
2530
- for (const outputFile of outputFiles) {
2531
- const outputRelPath = relative(rootDir, outputFile);
2532
- if (alreadyIngested(outputRelPath)) {
2533
- fileCount++;
2534
- continue;
2535
- }
2536
- let source;
2537
- try {
2538
- source = readFileSync(outputFile, "utf-8");
2539
- } catch (err) {
2540
- onUnreadable(outputRelPath, err);
2541
- continue;
2542
- }
2543
- onSourceRead?.(source, outputRelPath, outputFile);
2544
- entries.push({
2545
- path: outputRelPath,
2546
- source
2547
- });
2548
- pushed.add(outputRelPath);
2549
- fileOwners[outputRelPath] ??= specifier;
2550
- fileCount++;
2551
- }
2862
+ for (const outputFile of outputFiles) if (ingest(outputFile, specifier)) fileCount++;
2552
2863
  }
2553
- if (!isAbsolute(specifier)) {
2554
- const packageName = bareSpecifierPackageName(specifier);
2555
- for (const [subpath, target] of packageExportEntries(pkgRoot)) {
2556
- const entrySpecifier = packageName + subpath.slice(1);
2557
- const targetRelPath = relative(rootDir, target);
2558
- if (entrySpecifier in packageMap || !alreadyIngested(targetRelPath)) continue;
2559
- packageMap[entrySpecifier] = targetRelPath;
2560
- }
2864
+ if (packageName) for (const [subpath, target] of packageExportEntries(pkgRoot)) {
2865
+ const entrySpecifier = packageName + subpath.slice(1);
2866
+ const targetRelPath = relative$1(rootDir, target);
2867
+ if (entrySpecifier in packageMap || !alreadyIngested(targetRelPath)) continue;
2868
+ packageMap[entrySpecifier] = targetRelPath;
2561
2869
  }
2562
2870
  outcomes.push({
2563
2871
  specifier,
@@ -2571,12 +2879,112 @@ async function collectExternalPackageSources(opts) {
2571
2879
  sourceEntries,
2572
2880
  sourceEntrySideEffects,
2573
2881
  packageDirs,
2882
+ linkedDirs,
2883
+ outputDirs,
2574
2884
  dirOwnerSets,
2575
2885
  dirExtensions,
2576
2886
  fileOwners,
2577
- outcomes
2887
+ outcomes,
2888
+ diagnostics: [...diagnostics, ...noKitFilesDiagnostics(outcomes)],
2889
+ kitDescriptors
2578
2890
  };
2579
2891
  }
2892
+ /** The dependency names a manifest lists in `fields`. */
2893
+ function dependencyNames(manifest, fields) {
2894
+ if (!isJsonBlock(manifest)) return [];
2895
+ const names = /* @__PURE__ */ new Set();
2896
+ for (const field of fields) {
2897
+ const deps = manifest[field];
2898
+ if (isJsonBlock(deps)) for (const name of Object.keys(deps)) names.add(name);
2899
+ }
2900
+ return [...names];
2901
+ }
2902
+ /** The source kits the application at `rootDir` declares as dependencies.
2903
+ * A bundler serves an installed one as compiled code unless told
2904
+ * otherwise: Next keeps it external on the server unless it is in
2905
+ * `transpilePackages`, and Vite's optimizer prebundles it. */
2906
+ function sourceKitDependencies(rootDir) {
2907
+ return dependencyNames(readPackageManifest(rootDir), ["dependencies", "devDependencies"]).flatMap((name) => {
2908
+ const pkgRoot = locatePackageRoot(name, rootDir);
2909
+ if (pkgRoot === null || readKitSourceCondition(pkgRoot) === null) return [];
2910
+ return [{
2911
+ name,
2912
+ installed: isInstalledPackage(pkgRoot),
2913
+ dependencies: dependencyNames(readPackageManifest(pkgRoot), ["dependencies"])
2914
+ }];
2915
+ });
2916
+ }
2917
+ /** A specifier that names a package: not relative or absolute, and no URL,
2918
+ * scheme (`node:`, `virtual:`), subpath import or virtual id. */
2919
+ function isPackageSpecifier(specifier) {
2920
+ return /^(?:@[^/\\:]+\/)?[^./\\#\0:][^:]*$/.test(specifier);
2921
+ }
2922
+ /**
2923
+ * An error for each kit the application's own `files` import or re-export
2924
+ * whose system the application's system does not include: a package that
2925
+ * declares the kit source condition, with no kit the system extends
2926
+ * (`systemKits`) in that package. One app build has exactly one system, and
2927
+ * every kit's system is part of it, so such a kit is not extracted against
2928
+ * a system it was not built for. One batch parse reads the imports of every
2929
+ * file the engine parses as it is; an adapted source (`.svelte`, `.mdx`)
2930
+ * reaches the engine only as its generated children.
2931
+ */
2932
+ function importedKitDiagnostics(files, engine, rootDir, systemKits) {
2933
+ const { extractFacts } = engine;
2934
+ const parsed = files.filter(({ path }) => isEngineTransformExtension(path));
2935
+ if (!extractFacts || parsed.length === 0) return [];
2936
+ let facts;
2937
+ try {
2938
+ facts = parseInternalWire(extractFacts(JSON.stringify(parsed.map(({ path, source }) => ({
2939
+ path,
2940
+ source
2941
+ })))), "extractFacts");
2942
+ } catch {
2943
+ return [];
2944
+ }
2945
+ const seen = new Set(systemKits.filter((specifier) => !isAbsolute$1(specifier)).map(bareSpecifierPackageName));
2946
+ const diagnostics = [];
2947
+ for (const [path, file] of Object.entries(facts.files)) {
2948
+ if (file.parsePanicked) continue;
2949
+ const specifiers = [...file.imports.map((fact) => fact.source), ...file.exports.flatMap((fact) => fact.source === null ? [] : [fact.source])];
2950
+ for (const specifier of specifiers) {
2951
+ if (!isPackageSpecifier(specifier)) continue;
2952
+ const name = bareSpecifierPackageName(specifier);
2953
+ if (seen.has(name)) continue;
2954
+ seen.add(name);
2955
+ const pkgRoot = locatePackageRoot(name, dirname$1(resolve$1(rootDir, path)));
2956
+ if (pkgRoot && readKitSourceCondition(pkgRoot)) diagnostics.push({
2957
+ file: path,
2958
+ component: name,
2959
+ kind: "warn",
2960
+ message: `the application imports this kit, but its system is not included in the application's system, so its components are not extracted — include the kit's system in the application's system: createSystem().extend(<the kit's system>)`,
2961
+ code: KIT_SYSTEM_NOT_INCLUDED,
2962
+ severity: severityFor(KIT_SYSTEM_NOT_INCLUDED)
2963
+ });
2964
+ }
2965
+ }
2966
+ return diagnostics;
2967
+ }
2968
+ /** A kit without the source condition, warned once, or each condition entry
2969
+ * whose target is missing or outside the package. */
2970
+ function sourceConditionDiagnostics(packageName, condition) {
2971
+ if (condition === null) return [{
2972
+ file: packageName,
2973
+ component: "kit",
2974
+ kind: "warn",
2975
+ message: `declares no "${KIT_SOURCE_CONDITION}" export condition, so discovery guesses its source from src/ — give each public exports entry an "${KIT_SOURCE_CONDITION}" condition naming its original source`,
2976
+ code: KIT_WITHOUT_SOURCE_CONDITION,
2977
+ severity: severityFor(KIT_WITHOUT_SOURCE_CONDITION)
2978
+ }];
2979
+ return condition.invalid.map(([subpath, target]) => ({
2980
+ file: packageName,
2981
+ component: "kit",
2982
+ kind: "warn",
2983
+ message: `exports["${subpath}"].${KIT_SOURCE_CONDITION} names ${target}, which is missing or outside the package, so that entry is not read from source`,
2984
+ code: INVALID_KIT_SOURCE_CONDITION,
2985
+ severity: severityFor(INVALID_KIT_SOURCE_CONDITION)
2986
+ }));
2987
+ }
2580
2988
  function firstOwners(dirOwnerSets) {
2581
2989
  const owners = {};
2582
2990
  for (const [dir, specifiers] of Object.entries(dirOwnerSets)) if (specifiers.length > 0) owners[dir] = specifiers[0];
@@ -2589,7 +2997,7 @@ function excludeCollectedPackages(collected, rejectedSpecifiers, rootDir) {
2589
2997
  const targetRejected = (specifier, absTarget) => rejectedSpecifiers.has(specifier) || underRejectedDir(absTarget);
2590
2998
  const packageMap = {};
2591
2999
  for (const [specifier, relTarget] of Object.entries(collected.packageMap)) {
2592
- if (targetRejected(specifier, resolve(rootDir, relTarget))) continue;
3000
+ if (targetRejected(specifier, resolve$1(rootDir, relTarget))) continue;
2593
3001
  packageMap[specifier] = relTarget;
2594
3002
  }
2595
3003
  const sourceEntries = /* @__PURE__ */ new Map();
@@ -2622,10 +3030,14 @@ function excludeCollectedPackages(collected, rejectedSpecifiers, rootDir) {
2622
3030
  sourceEntries,
2623
3031
  sourceEntrySideEffects,
2624
3032
  packageDirs: collected.packageDirs.filter((dir) => !rejectedDirs.includes(dir)),
3033
+ linkedDirs: collected.linkedDirs.filter((dir) => !rejectedDirs.includes(dir)),
3034
+ outputDirs: collected.outputDirs.filter((dir) => !rejectedDirs.includes(dir)),
2625
3035
  dirOwnerSets,
2626
3036
  dirExtensions,
2627
3037
  fileOwners,
2628
- outcomes: collected.outcomes
3038
+ outcomes: collected.outcomes,
3039
+ diagnostics: collected.diagnostics,
3040
+ kitDescriptors: collected.kitDescriptors.filter((record) => !rejectedDirs.some((dir) => isPathWithinRoot(resolve$1(rootDir, record.packageRoot), dir)))
2629
3041
  };
2630
3042
  }
2631
3043
  function unresolvableIncludesMessage(outcomes) {
@@ -2654,7 +3066,8 @@ function engineModuleParser(engine) {
2654
3066
  }])), "extractFacts").files[path];
2655
3067
  return facts && !facts.parsePanicked ? {
2656
3068
  imports: facts.imports,
2657
- exports: facts.exports
3069
+ exports: facts.exports,
3070
+ unboundCreateSystemCalls: facts.unboundCreateSystemCalls ?? []
2658
3071
  } : null;
2659
3072
  } catch {
2660
3073
  return null;
@@ -2665,7 +3078,7 @@ const ANIMUS_SYSTEM_SPECIFIER = /^@animus-ui\/system(?:\/.*)?$/;
2665
3078
  /** The file a specifier names from `importer`: a relative one by the
2666
3079
  * ingestion's probe order, a bare one by the host's package resolution. */
2667
3080
  async function resolveModuleFile(importer, specifier, resolvePackage) {
2668
- if (specifier.startsWith(".")) return relativeSourceCandidates(importer, specifier).find(isFile) ?? null;
3081
+ if (specifier.startsWith(".")) return relativeSourceCandidates(importer, specifier).find(isFile$1) ?? null;
2669
3082
  try {
2670
3083
  return await resolvePackage?.(specifier) ?? null;
2671
3084
  } catch {
@@ -2750,13 +3163,15 @@ const NAMESPACE_IMPORT = /\bimport\s+(?:[a-zA-Z_$][a-zA-Z0-9_$]*\s*,\s*)?\*\s*as
2750
3163
  * `import()` of a module. A binding named `createSystem` shown to be
2751
3164
  * something else is no root. One whose identity discovery cannot follow
2752
3165
  * keeps the admission spelling gave it, so a resolution limit never drops a
2753
- * kit. Both are reported. The bare name also anchors, as a global, unless
2754
- * the file binds it.
3166
+ * kit. Both are reported. A call of the bare name, which the file neither
3167
+ * imports nor declares, is no root: the system loader evaluates the file
3168
+ * without auto-imports, where the name is undefined. It is reported once.
2755
3169
  */
2756
- async function systemRoots(systemFilePath, source, imports, following) {
3170
+ async function systemRoots(systemFilePath, source, record, following) {
3171
+ const { imports } = record;
2757
3172
  const roots = /* @__PURE__ */ new Set();
2758
3173
  const identityOf = (specifier, name) => exportIdentity(systemFilePath, specifier, name, following, /* @__PURE__ */ new Set());
2759
- const called = (callee) => new RegExp(`(?<![a-zA-Z0-9_$.])${escapeRegExp$1(callee)}\\s*\\(`).test(source);
3174
+ const called = (callee) => callOf(callee).test(source);
2760
3175
  /** Admits a binding named `createSystem` by its identity: an unknown one
2761
3176
  * keeps `spellingAdmits`, and every unproven one is reported. */
2762
3177
  const admit = (local, offset, identity, spellingAdmits) => {
@@ -2776,11 +3191,8 @@ async function systemRoots(systemFilePath, source, imports, following) {
2776
3191
  ...locationIn(source, offset)
2777
3192
  });
2778
3193
  };
2779
- let bindsName = false;
2780
3194
  for (const binding of imports) {
2781
- const named = binding.imported === "createSystem" || binding.local === "createSystem";
2782
- if (binding.local === "createSystem") bindsName = true;
2783
- if (named) {
3195
+ if (binding.imported === "createSystem" || binding.local === "createSystem") {
2784
3196
  const statement = new RegExp(`\\bimport\\b[^;]*?\\bfrom\\s*['"]${escapeRegExp$1(binding.source)}['"]`, "g");
2785
3197
  let offset = 0;
2786
3198
  for (const match of source.matchAll(statement)) {
@@ -2811,19 +3223,47 @@ async function systemRoots(systemFilePath, source, imports, following) {
2811
3223
  why: `it is destructured from '${initializer}', which is not a module namespace`
2812
3224
  });
2813
3225
  };
3226
+ for (const { local, offset, initializer } of destructuredCreateSystems(source)) admit(local, offset, await destructuredFrom(initializer), local === "createSystem");
3227
+ const unimported = unimportedCreateSystemCall(systemFilePath, record);
3228
+ if (unimported) following.report?.(unimported);
3229
+ return roots;
3230
+ }
3231
+ /** A call of `callee` as a whole name, not a member. */
3232
+ function callOf(callee) {
3233
+ return new RegExp(`(?<![a-zA-Z0-9_$.])${escapeRegExp$1(callee)}\\s*\\(`);
3234
+ }
3235
+ /** Each `createSystem` property a declaration destructures: its local name,
3236
+ * its offset in `source`, and the destructured initializer. */
3237
+ function* destructuredCreateSystems(source) {
2814
3238
  for (const match of source.matchAll(/\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*([^;\n]+)/g)) {
2815
3239
  const [whole, pattern, initializer] = match;
2816
3240
  for (const property of pattern.split(",")) {
2817
3241
  const binding = /^\s*createSystem\s*(?::\s*([a-zA-Z_$][a-zA-Z0-9_$]*))?\s*(?:=[\s\S]*)?$/.exec(property);
2818
3242
  if (!binding) continue;
2819
- const local = binding[1] ?? "createSystem";
2820
- if (local === "createSystem") bindsName = true;
2821
- admit(local, match.index + whole.indexOf("createSystem"), await destructuredFrom(initializer.trim()), local === "createSystem");
3243
+ yield {
3244
+ local: binding[1] ?? "createSystem",
3245
+ offset: match.index + whole.indexOf("createSystem"),
3246
+ initializer: initializer.trim()
3247
+ };
2822
3248
  }
2823
3249
  }
2824
- const declaresName = /\b(?:function\*?|class)\s+createSystem\b|\b(?:const|let|var)\s+createSystem\b/.test(source);
2825
- if (!bindsName && !declaresName) roots.add("createSystem");
2826
- return roots;
3250
+ }
3251
+ /** The warning for a `createSystem` call that the parser's scopes leave
3252
+ * unbound: no import, declaration or parameter names it. Null when there is
3253
+ * none, or when the parser reports no scopes. */
3254
+ function unimportedCreateSystemCall(systemFilePath, record) {
3255
+ const call = record.unboundCreateSystemCalls?.[0];
3256
+ if (!call) return null;
3257
+ return {
3258
+ file: systemFilePath,
3259
+ component: "createSystem",
3260
+ kind: "warn",
3261
+ message: `'createSystem' is called with no import or local binding, so it is not read as a system root: the system loader evaluates this file without auto-imports, where the name is undefined — import createSystem from '@animus-ui/system'`,
3262
+ code: UNIMPORTED_CREATE_SYSTEM,
3263
+ severity: severityFor(UNIMPORTED_CREATE_SYSTEM),
3264
+ line: call[0],
3265
+ column: call[1]
3266
+ };
2827
3267
  }
2828
3268
  /** A pattern matching a call of any of `callees` as a whole name, or null
2829
3269
  * when there is none to anchor on. */
@@ -2839,9 +3279,8 @@ async function extractSystemFilePackages(systemFilePath, parseModule, report, re
2839
3279
  return [];
2840
3280
  }
2841
3281
  const parsed = parseModule?.(source, systemFilePath) ?? null;
2842
- const parsedImports = parsed && parsed.imports.length > 0 ? parsed.imports : null;
2843
3282
  let rootCall = "createSystem";
2844
- if (parseModule && parsedImports) rootCall = rootCallPattern([...await systemRoots(systemFilePath, source, parsedImports, {
3283
+ if (parseModule && parsed) rootCall = rootCallPattern([...await systemRoots(systemFilePath, source, parsed, {
2845
3284
  parseModule,
2846
3285
  resolvePackage,
2847
3286
  report
@@ -3013,9 +3452,9 @@ async function extractSystemFilePackages(systemFilePath, parseModule, report, re
3013
3452
  }
3014
3453
  if (identifiers.size === 0) return [];
3015
3454
  const importMap = /* @__PURE__ */ new Map();
3016
- for (const binding of parsedImports ?? []) importMap.set(binding.local, binding.source);
3455
+ for (const binding of parsed?.imports ?? []) importMap.set(binding.local, binding.source);
3017
3456
  const importRegex = /^\s*import\s+(?:([a-zA-Z_$][a-zA-Z0-9_$]*)\s*,\s*)?(?:\{([^}]*)\}|([a-zA-Z_$][a-zA-Z0-9_$]*))\s+from\s+['"]([^'"]+)['"]/gm;
3018
- if (!parsedImports) {
3457
+ if (!parsed) {
3019
3458
  let importMatch;
3020
3459
  while ((importMatch = importRegex.exec(source)) !== null) {
3021
3460
  const [, comboDefault, namedImports, defaultImport, specifier] = importMatch;
@@ -3045,7 +3484,7 @@ async function extractSystemFilePackages(systemFilePath, parseModule, report, re
3045
3484
  for (const id of identifiers) {
3046
3485
  const specifier = importMap.get(throughAliases(id));
3047
3486
  if (!specifier) continue;
3048
- if (specifier.startsWith(".")) packages.add(resolve(systemFileDir, specifier));
3487
+ if (specifier.startsWith(".")) packages.add(resolve$1(systemFileDir, specifier));
3049
3488
  else packages.add(specifier);
3050
3489
  }
3051
3490
  return Array.from(packages);
@@ -3148,7 +3587,7 @@ function resolveThroughPathAliases(specifier, rootDir, pathAliasesJson) {
3148
3587
  if (alias.pattern === specifier) mapped = alias.replacement;
3149
3588
  } else if (specifier.startsWith(alias.pattern)) mapped = alias.replacement + specifier.slice(alias.pattern.length);
3150
3589
  if (mapped === null) continue;
3151
- const absolute = isAbsolute(mapped) ? mapped : join$1(rootDir, mapped);
3590
+ const absolute = isAbsolute$1(mapped) ? mapped : join$1(rootDir, mapped);
3152
3591
  if (existsSync(absolute)) return absolute;
3153
3592
  }
3154
3593
  return null;
@@ -3267,8 +3706,13 @@ function enforceExternalTokenContracts(opts) {
3267
3706
  sourceTokens
3268
3707
  });
3269
3708
  if (messages.length === 0) return;
3270
- if (opts.strict) throw new Error(`${opts.prefix} ${messages.join("\n")}`);
3271
- for (const message of messages) opts.warn(message);
3709
+ if (!opts.strict) {
3710
+ for (const message of messages) opts.warn(message);
3711
+ return;
3712
+ }
3713
+ const message = `${opts.prefix} ${messages.join("\n")}`;
3714
+ if (!opts.reportErrors) throw new Error(message);
3715
+ opts.reportErrors(message);
3272
3716
  }
3273
3717
  //#endregion
3274
3718
  //#region pipeline/path-aliases.ts
@@ -3880,11 +4324,14 @@ function buildAnalysisInputs(opts) {
3880
4324
  externalDirsJson: opts.externalDirs?.length && hasSourceThemeManifests(opts.system) ? JSON.stringify(opts.externalDirs) : null
3881
4325
  };
3882
4326
  if (opts.system.declarationScalesJson) inputs.declarationScalesJson = opts.system.declarationScalesJson;
4327
+ if (opts.system.generatedNamesJson) inputs.generatedNamesJson = opts.system.generatedNamesJson;
3883
4328
  const context = opts.analysisContext;
3884
4329
  if (context?.skippedSources?.length || context?.unbundledComputedImports || context?.packageDirs?.length) inputs.analysisContextJson = JSON.stringify({
3885
4330
  skippedSources: context.skippedSources ?? [],
3886
4331
  unbundledComputedImports: context.unbundledComputedImports ?? false,
3887
- packageDirs: context.packageDirs ?? []
4332
+ packageDirs: context.packageDirs ?? [],
4333
+ linkedDirs: context.linkedDirs ?? [],
4334
+ outputDirs: context.outputDirs ?? []
3888
4335
  });
3889
4336
  return inputs;
3890
4337
  }
@@ -3925,7 +4372,12 @@ function runProjectAnalysis(engineApi, opts) {
3925
4372
  t = performance.now();
3926
4373
  const manifest = JSON.parse(manifestJson);
3927
4374
  const systemErrors = systemLoadDiagnostics(opts.system).filter((diagnostic) => diagnostic.kind === "error");
3928
- if (systemErrors.length > 0) manifest.diagnostics = [...systemErrors, ...manifest.diagnostics ?? []];
4375
+ const kitDiagnostics = kitDescriptorDiagnostics(opts.kitDescriptors ?? [], manifest);
4376
+ if (systemErrors.length > 0 || kitDiagnostics.length > 0) manifest.diagnostics = [
4377
+ ...systemErrors,
4378
+ ...kitDiagnostics,
4379
+ ...manifest.diagnostics ?? []
4380
+ ];
3929
4381
  const componentCss = applyUnitFallback(manifest.css);
3930
4382
  const propertyDiagnostics = checkCustomProperties({
3931
4383
  system: opts.system,
@@ -3936,6 +4388,7 @@ function runProjectAnalysis(engineApi, opts) {
3936
4388
  surfaceManifestDiagnostics(manifest, opts.warn, {
3937
4389
  strict: opts.strict,
3938
4390
  info: opts.info,
4391
+ reportErrors: opts.reportErrors,
3939
4392
  levels: opts.diagnostics,
3940
4393
  knownCodes: opts.diagnostics ? knownDiagnosticCodes(diagnosticCodes?.()) : void 0,
3941
4394
  prepend: [
@@ -4043,36 +4496,34 @@ function renameCustomProperties(css, names) {
4043
4496
  }
4044
4497
  //#endregion
4045
4498
  //#region pipeline/prefix.ts
4046
- /** Prefix variable references without changing their matching rules. */
4047
- function prefixVariableReferences(prefix, value) {
4048
- if (!prefix) return value;
4049
- return value.replace(/var\(--([a-zA-Z][\w-]*)\)/g, `var(--${prefix}-$1)`);
4050
- }
4051
- function applyPrefix(prefix, variableMapJson, variableCss, themeJson, contextualVarsJson) {
4499
+ /**
4500
+ * The prefix without `prefixContextualVars`: every name Animus generates (a
4501
+ * variable the theme's map or variable CSS defines) takes `--${prefix}-`
4502
+ * wherever it is defined, registered or read, `var()` fallbacks at any depth
4503
+ * included. Every other name stays as written: each declared contextual
4504
+ * variable, and any custom property an author writes.
4505
+ */
4506
+ function applyPrefix(prefix, variableMapJson, variableCss, themeJson, contextualVarsJson, declarationScalesJson) {
4052
4507
  if (!prefix) return {
4053
4508
  variableMapJson,
4054
4509
  variableCss,
4055
4510
  themeJson,
4056
- contextualVarsJson
4511
+ contextualVarsJson,
4512
+ declarationScalesJson
4057
4513
  };
4058
- const map = JSON.parse(variableMapJson);
4059
- const prefixed = {};
4060
- for (const [key, varName] of Object.entries(map)) prefixed[key] = varName.startsWith("--") ? `--${prefix}-${varName.slice(2)}` : varName;
4061
- let css = variableCss;
4062
- css = css.replace(/--([a-zA-Z][\w-]*)\s*:/g, `--${prefix}-$1:`);
4063
- css = prefixVariableReferences(prefix, css);
4064
- css = css.replace(/@property(\s+)--([a-zA-Z][\w-]*)/g, `@property$1--${prefix}-$2`);
4514
+ const contextual = new Set(contextualVarsJson ? Object.values(parseInternalWire(contextualVarsJson, "contextualVarsJson (the theme's contextual variable names)")).flat() : []);
4515
+ const variableMap = parseInternalWire(variableMapJson, "variableMapJson (the theme's token variables)");
4516
+ const generated = [...Object.values(variableMap).map((name) => name.replace(/^--/, "")), ...themeDefinitions(variableCss)].filter((name) => !contextual.has(name));
4517
+ const names = createPropertyNames([], prefix, generated);
4518
+ const rename = (value) => renameCustomProperties(value, names);
4065
4519
  const result = {
4066
- variableMapJson: JSON.stringify(prefixed),
4067
- variableCss: css
4520
+ variableMapJson: JSON.stringify(Object.fromEntries(Object.entries(variableMap).map(([key, name]) => [key, rename(name)]))),
4521
+ variableCss: rename(variableCss)
4068
4522
  };
4069
- if (themeJson) result.themeJson = prefixVariableReferences(prefix, themeJson);
4070
- if (contextualVarsJson) {
4071
- const ctxVars = JSON.parse(contextualVarsJson);
4072
- const prefixedCtx = {};
4073
- for (const [scale, names] of Object.entries(ctxVars)) prefixedCtx[scale] = names.map((name) => `${prefix}-${name}`);
4074
- result.contextualVarsJson = JSON.stringify(prefixedCtx);
4075
- }
4523
+ if (themeJson) result.themeJson = renameTokenValues(themeJson, rename);
4524
+ if (contextualVarsJson) result.contextualVarsJson = contextualVarsJson;
4525
+ if (generated.length > 0) result.generatedNamesJson = JSON.stringify(Object.fromEntries(generated.map((name) => [name, `${prefix}-${name}`])));
4526
+ if (declarationScalesJson) result.declarationScalesJson = renameDeclarationRecords(declarationScalesJson, rename);
4076
4527
  return result;
4077
4528
  }
4078
4529
  /** The runtime's transport variables are `--animus-<prop>`. */
@@ -4088,7 +4539,8 @@ function applyPropertyNames(prefix, artifacts) {
4088
4539
  const byScale = artifacts.contextualVarsJson ? parseInternalWire(artifacts.contextualVarsJson, "contextualVarsJson (the theme's contextual variable names)") : null;
4089
4540
  const declared = Object.values(byScale ?? {}).flat();
4090
4541
  const variableMap = parseInternalWire(artifacts.variableMapJson, "variableMapJson (the theme's token variables)");
4091
- const managed = createPropertyNames(declared, prefix, [...Object.values(variableMap).map((name) => name.replace(/^--/, "")), ...[...artifacts.variableCss.matchAll(THEME_DEFINITION)].map((m) => m[1])]);
4542
+ const themeDefined = [...Object.values(variableMap).map((name) => name.replace(/^--/, "")), ...themeDefinitions(artifacts.variableCss)];
4543
+ const managed = createPropertyNames(declared, prefix, themeDefined);
4092
4544
  const nameConflicts = [...[...new Set(declared)].flatMap((name) => {
4093
4545
  const final = managed.finalName(name) ?? name;
4094
4546
  return final.startsWith(TRANSPORT_NAMESPACE) ? [{
@@ -4112,11 +4564,30 @@ function applyPropertyNames(prefix, artifacts) {
4112
4564
  }))]))),
4113
4565
  declarationScalesJson: artifacts.declarationScalesJson === null ? null : renameDeclarationRecords(artifacts.declarationScalesJson, rename),
4114
4566
  nameConflicts,
4115
- contextualProperties: [...new Set(declared)].map((name) => `--${managed.finalName(name) ?? name}`)
4567
+ contextualProperties: [...new Set(declared)].map((name) => `--${managed.finalName(name) ?? name}`),
4568
+ generatedNamesJson: generatedNamesJson(themeDefined.filter((name) => !declared.includes(name)), managed)
4116
4569
  };
4117
4570
  }
4118
- /** A custom property the theme's CSS defines or registers. */
4119
- const THEME_DEFINITION = /(?:@property\s+|(?:^|[\s;{]))--([\w-]+)(?=\s*[:{])/g;
4571
+ /** The generated names' final names, for authored component styles. */
4572
+ function generatedNamesJson(names, managed) {
4573
+ const entries = [...new Set(names)].flatMap((name) => {
4574
+ const final = managed.finalName(name);
4575
+ return final === void 0 ? [] : [[name, final]];
4576
+ });
4577
+ return entries.length === 0 ? null : JSON.stringify(Object.fromEntries(entries));
4578
+ }
4579
+ /** The custom properties the theme's CSS declares or `@property` registers,
4580
+ * read as CSS tokenizes it: a name in a string or comment defines nothing. */
4581
+ function themeDefinitions(variableCss) {
4582
+ const tokens = tokenize(variableCss).filter((token) => token.type !== "whitespace");
4583
+ return tokens.flatMap((token, index) => {
4584
+ if (token.type !== "ident" || !token.value.startsWith("--")) return [];
4585
+ const previous = tokens[index - 1];
4586
+ const declared = (previous === void 0 || previous.type === "{" || previous.type === ";") && tokens[index + 1]?.type === ":";
4587
+ const registered = previous?.type === "at-keyword" && previous.value.toLowerCase() === "property";
4588
+ return declared || registered ? [token.value.slice(2)] : [];
4589
+ });
4590
+ }
4120
4591
  /** Renames inside the token map's values. */
4121
4592
  function renameTokenValues(themeJson, rename) {
4122
4593
  const tokens = parseInternalWire(themeJson, "themeJson (the theme's flattened token values)");
@@ -4132,23 +4603,40 @@ function renameDeclarationRecords(declarationScalesJson, rename) {
4132
4603
  }
4133
4604
  //#endregion
4134
4605
  //#region pipeline/system-config.ts
4606
+ /** The loader's evaluation of the system file. A failure on a file that
4607
+ * calls `createSystem` with no binding leads with discovery's warning line
4608
+ * for it, then keeps the loader's own error. */
4609
+ function evaluateSystemModule(engine, systemPath, rootDir, conditions) {
4610
+ try {
4611
+ return engine.loadSystemModule(systemPath, rootDir, void 0, conditions);
4612
+ } catch (error) {
4613
+ let source;
4614
+ try {
4615
+ source = readFileSync(systemPath, "utf-8");
4616
+ } catch {
4617
+ throw error;
4618
+ }
4619
+ const record = engineModuleParser(engine)?.(source, systemPath);
4620
+ const call = record && unimportedCreateSystemCall(systemPath, record);
4621
+ if (!call) throw error;
4622
+ throw new Error(`${warnLine(call)}\n${String(error)}`, { cause: error });
4623
+ }
4624
+ }
4135
4625
  /**
4136
4626
  * Load and normalize a SystemInstance; `prefix` namespaces every CSS
4137
4627
  * variable name. Error handling stays at the call site.
4138
4628
  */
4139
4629
  function loadSystemConfig(engineApi, opts) {
4140
- const { loadSystemModule } = engineApi();
4141
- const config = loadSystemModule(opts.systemPath, opts.rootDir);
4630
+ const config = evaluateSystemModule(engineApi(), opts.systemPath, opts.rootDir, opts.conditions);
4142
4631
  let scalesJson = config.scalesJson;
4143
4632
  let variableMapJson = config.variableMapJson;
4144
4633
  const registrations = splitInvalidPropertyRegistrations(config.variableCss);
4145
4634
  let variableCss = registrations.css;
4146
4635
  let contextualVarsJson = config.contextualVarsJson || null;
4147
4636
  let declarationScalesJson = config.declarationScalesJson || null;
4148
- const declaredNames = Object.values(parseInternalWire(contextualVarsJson ?? "{}", "contextualVarsJson (the theme's contextual variable names)")).flat();
4149
- let contextualProperties = declaredNames.map((name) => `--${name}`);
4150
- let legacyPrefixedContextualVars = [];
4637
+ let contextualProperties = Object.values(parseInternalWire(contextualVarsJson ?? "{}", "contextualVarsJson (the theme's contextual variable names)")).flat().map((name) => `--${name}`);
4151
4638
  let prefixNameConflicts = [];
4639
+ let generatedNamesJson;
4152
4640
  if (opts.prefix && opts.prefixContextualVars) {
4153
4641
  const resolved = applyPropertyNames(opts.prefix, {
4154
4642
  variableMapJson,
@@ -4164,15 +4652,14 @@ function loadSystemConfig(engineApi, opts) {
4164
4652
  contextualProperties = resolved.contextualProperties;
4165
4653
  prefixNameConflicts = resolved.nameConflicts;
4166
4654
  declarationScalesJson = resolved.declarationScalesJson;
4655
+ generatedNamesJson = resolved.generatedNamesJson;
4167
4656
  } else if (opts.prefix) {
4168
- legacyPrefixedContextualVars = declaredNames;
4169
- contextualProperties = declaredNames.map((name) => `--${opts.prefix}-${name}`);
4170
- const prefixed = applyPrefix(opts.prefix, variableMapJson, variableCss, scalesJson, contextualVarsJson || void 0);
4657
+ const prefixed = applyPrefix(opts.prefix, variableMapJson, variableCss, scalesJson, contextualVarsJson || void 0, declarationScalesJson || void 0);
4171
4658
  variableMapJson = prefixed.variableMapJson;
4172
4659
  variableCss = prefixed.variableCss;
4173
4660
  if (prefixed.themeJson) scalesJson = prefixed.themeJson;
4174
- if (prefixed.contextualVarsJson) contextualVarsJson = prefixed.contextualVarsJson;
4175
- if (declarationScalesJson) declarationScalesJson = prefixVariableReferences(opts.prefix, declarationScalesJson);
4661
+ if (prefixed.declarationScalesJson) declarationScalesJson = prefixed.declarationScalesJson;
4662
+ generatedNamesJson = prefixed.generatedNamesJson;
4176
4663
  }
4177
4664
  const system = {
4178
4665
  propConfigJson: config.propConfig,
@@ -4196,7 +4683,7 @@ function loadSystemConfig(engineApi, opts) {
4196
4683
  if (config.propertyRecordsJson) system.propertyRecordsJson = config.propertyRecordsJson;
4197
4684
  if (registrations.invalid.length > 0) system.invalidPropertyRegistrations = registrations.invalid;
4198
4685
  if (prefixNameConflicts.length > 0) system.prefixNameConflicts = prefixNameConflicts;
4199
- if (legacyPrefixedContextualVars.length > 0) system.legacyPrefixedContextualVars = [...new Set(legacyPrefixedContextualVars)];
4686
+ if (generatedNamesJson) system.generatedNamesJson = generatedNamesJson;
4200
4687
  return system;
4201
4688
  }
4202
4689
  //#endregion
@@ -4205,8 +4692,7 @@ function runStructuralSelfCheck(input) {
4205
4692
  const failures = [];
4206
4693
  if (input.componentCount === 0) failures.push("No component CSS produced — check the system file and its includes list");
4207
4694
  else if (input.assembledCss !== void 0 ? !/@layer\s+anm-base\s*\{/.test(input.assembledCss) : input.componentCss.trim().length === 0) failures.push(`${input.componentCount} component(s) discovered but the emitted component CSS is empty`);
4208
- for (const { specifier, outcome } of input.externalOutcomes ?? []) if (outcome === "empty") failures.push(`include '${specifier}' resolved but discovered no component sources [${NO_KIT_FILES}]`);
4209
- else if (outcome === "unresolvable") failures.push(`include '${specifier}' could not be resolved`);
4695
+ for (const { specifier, outcome } of input.externalOutcomes ?? []) if (outcome === "unresolvable") failures.push(`include '${specifier}' could not be resolved`);
4210
4696
  if ((input.variableMapJson == null || Object.keys(parseInternalWire(input.variableMapJson, "variableMapJson (the theme's token → variable map)")).length > 0) && !input.variableCss.includes(":root")) failures.push("No :root variable block found in variable CSS");
4211
4697
  if ((input.assembledCss ?? `${input.variableCss}\n${input.globalCss}\n${input.componentCss}`).includes("__TRANSFORM__")) failures.push("Unresolved __TRANSFORM__ placeholders found in CSS output");
4212
4698
  if (input.componentCount > 0 && (input.componentCss.length > 0 || input.assembledCss !== void 0)) {
@@ -4240,7 +4726,8 @@ function buildDynamicPropConfig(dynamicProps) {
4240
4726
  kind: meta.kind,
4241
4727
  slotClass: meta.slotClass,
4242
4728
  memberVars: meta.memberVars,
4243
- declarationScaleValues: meta.declarationScaleValues
4729
+ declarationScaleValues: meta.declarationScaleValues,
4730
+ ...meta.productionConditions && { productionConditions: meta.productionConditions }
4244
4731
  };
4245
4732
  continue;
4246
4733
  }
@@ -4258,6 +4745,7 @@ function buildDynamicPropConfig(dynamicProps) {
4258
4745
  if (meta.strict) entry.strict = true;
4259
4746
  if (meta.keywords?.length) entry.keywords = meta.keywords;
4260
4747
  if (meta.currentVar) entry.currentVar = meta.currentVar;
4748
+ if (meta.productionConditions) entry.productionConditions = meta.productionConditions;
4261
4749
  configEntries[propName] = entry;
4262
4750
  }
4263
4751
  return configEntries;
@@ -4296,6 +4784,191 @@ function assertNoErrorDiagnostics(diagnostics) {
4296
4784
  throw new Error(lines.join("\n"));
4297
4785
  }
4298
4786
  //#endregion
4787
+ //#region pipeline/kit-publication.ts
4788
+ /** Source a kit publishes and the loader or a bundler parses for imports. */
4789
+ const CODE_EXTENSIONS = /* @__PURE__ */ new Set([
4790
+ ".ts",
4791
+ ".tsx",
4792
+ ".mts",
4793
+ ".cts",
4794
+ ".js",
4795
+ ".jsx",
4796
+ ".mjs",
4797
+ ".cjs"
4798
+ ]);
4799
+ const isFile = (path) => {
4800
+ try {
4801
+ return statSync$1(path).isFile();
4802
+ } catch {
4803
+ return false;
4804
+ }
4805
+ };
4806
+ const posixPath = (path) => path.split(sep).join("/");
4807
+ /**
4808
+ * The package-relative files `npm pack` publishes, read with npm's own rules
4809
+ * (`files`, `.npmignore`, `.gitignore` and the files npm always includes)
4810
+ * through a dry run that runs no scripts and needs no network.
4811
+ */
4812
+ function npmPublishedFiles(pkgRoot) {
4813
+ const windows = process.platform === "win32";
4814
+ const run = spawnSync(windows ? "npm.cmd" : "npm", [
4815
+ "pack",
4816
+ "--dry-run",
4817
+ "--json",
4818
+ "--ignore-scripts"
4819
+ ], {
4820
+ cwd: pkgRoot,
4821
+ encoding: "utf-8",
4822
+ shell: windows,
4823
+ env: {
4824
+ ...process.env,
4825
+ npm_config_update_notifier: "false"
4826
+ }
4827
+ });
4828
+ if (run.error || run.status !== 0) return {
4829
+ kind: "failed",
4830
+ reason: `npm pack --dry-run could not list the published files: ${String(run.error ?? run.stderr.trim())}`
4831
+ };
4832
+ let output;
4833
+ try {
4834
+ output = JSON.parse(run.stdout);
4835
+ } catch (error) {
4836
+ return {
4837
+ kind: "failed",
4838
+ reason: `npm pack --dry-run printed no JSON: ${String(error)}`
4839
+ };
4840
+ }
4841
+ const pack = Array.isArray(output) ? output[0] : void 0;
4842
+ const files = isJsonBlock(pack) ? pack.files : void 0;
4843
+ if (!Array.isArray(files)) return {
4844
+ kind: "failed",
4845
+ reason: "npm pack --dry-run printed no file list"
4846
+ };
4847
+ return {
4848
+ kind: "listed",
4849
+ files: new Set(files.flatMap((file) => isJsonBlock(file) && isJsonString(file.path) ? [posixPath(file.path)] : []))
4850
+ };
4851
+ }
4852
+ function animusTargets(manifest) {
4853
+ const targets = [];
4854
+ const unreadable = [];
4855
+ const visit = (subpath, value, underAnimus) => {
4856
+ if (isJsonString(value)) {
4857
+ if (underAnimus) targets.push([subpath, value]);
4858
+ } else if (Array.isArray(value)) for (const entry of value) visit(subpath, entry, underAnimus);
4859
+ else if (isJsonBlock(value)) for (const [key, entry] of Object.entries(value)) visit(subpath, entry, underAnimus || key === "animus");
4860
+ else if (underAnimus && value !== null) unreadable.push([subpath, JSON.stringify(value)]);
4861
+ };
4862
+ for (const [subpath, value] of exportsSubpaths(manifest)) visit(subpath, value, false);
4863
+ return {
4864
+ targets,
4865
+ unreadable
4866
+ };
4867
+ }
4868
+ /** Every file in the package outside `node_modules` and `.git`,
4869
+ * package-relative. */
4870
+ function packageFiles(pkgRoot, dir = "") {
4871
+ return readdirSync$1(join(pkgRoot, dir), { withFileTypes: true }).flatMap((entry) => {
4872
+ const path = dir === "" ? entry.name : `${dir}/${entry.name}`;
4873
+ if (entry.isDirectory()) return entry.name === "node_modules" || entry.name === ".git" ? [] : packageFiles(pkgRoot, path);
4874
+ return entry.isFile() ? [path] : [];
4875
+ });
4876
+ }
4877
+ /** A `*` target pattern as a matcher of package-relative files. Node puts
4878
+ * one subpath into every `*`, so each later `*` repeats the first match. */
4879
+ function targetPattern(target) {
4880
+ const body = posixPath(target).replace(/^\.\//, "").split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).reduce((pattern, part, index) => index === 0 ? part : `${pattern}${index === 1 ? "(.+)" : "\\1"}${part}`);
4881
+ return new RegExp(`^${body}$`);
4882
+ }
4883
+ /**
4884
+ * Why the kit at `pkgRoot` would fail an installed consumer: each `animus`
4885
+ * source target, at any condition depth or as a pattern, and each file its
4886
+ * relative imports reach, must be in the package and among the files `npm
4887
+ * pack` publishes, and each bare package import a declared dependency.
4888
+ * Each line names the file, the import and the cause; none means the
4889
+ * published source is complete. With `artifactDir`, a build's artifact
4890
+ * directory inside the package that `npm pack` would publish is a line too.
4891
+ */
4892
+ function kitPublicationFailures(pkgRoot, engine, artifactDir) {
4893
+ let manifest;
4894
+ try {
4895
+ manifest = JSON.parse(readFileSync$1(join(pkgRoot, "package.json"), "utf-8"));
4896
+ } catch (error) {
4897
+ return [`package.json: cannot be read: ${String(error)}`];
4898
+ }
4899
+ const { targets, unreadable } = animusTargets(manifest);
4900
+ if (targets.length === 0 && unreadable.length === 0) return [];
4901
+ const { moduleSpecifiers } = engine;
4902
+ if (moduleSpecifiers === void 0) throw new Error("the native engine does not expose moduleSpecifiers, which the kit publication check needs — rebuild @animus-ui/extract");
4903
+ const publication = npmPublishedFiles(pkgRoot);
4904
+ if (publication.kind === "failed") return [`package.json: ${publication.reason}`];
4905
+ const published = (packageRelative) => publication.files.has(packageRelative);
4906
+ const declared = new Set([
4907
+ "dependencies",
4908
+ "peerDependencies",
4909
+ "optionalDependencies"
4910
+ ].flatMap((field) => {
4911
+ const block = isJsonBlock(manifest) ? manifest[field] : void 0;
4912
+ return isJsonBlock(block) ? Object.keys(block) : [];
4913
+ }));
4914
+ const ownName = isJsonBlock(manifest) && isJsonString(manifest.name) ? manifest.name : null;
4915
+ const failures = [];
4916
+ const rel = (file) => posixPath(relative(pkgRoot, file));
4917
+ const outside = (relPath) => relPath.startsWith("../") || isAbsolute(relPath);
4918
+ for (const [subpath, value] of unreadable) failures.push(`package.json: exports["${subpath}"] has an "animus" value, ${value}, that is no target path`);
4919
+ const queue = [];
4920
+ const admit = (subpath, relPath) => {
4921
+ if (published(relPath)) queue.push(resolve(pkgRoot, relPath));
4922
+ else failures.push(`package.json: the "animus" target of exports["${subpath}"], ${relPath}, is not in the published files`);
4923
+ };
4924
+ let files = null;
4925
+ for (const [subpath, target] of targets) {
4926
+ const relPath = rel(resolve(pkgRoot, target));
4927
+ if (outside(relPath)) failures.push(`package.json: the "animus" target of exports["${subpath}"], ${target}, is outside the package`);
4928
+ else if (target.includes("*")) {
4929
+ files ??= packageFiles(pkgRoot);
4930
+ const pattern = targetPattern(target);
4931
+ const matched = files.filter((file) => pattern.test(file));
4932
+ if (matched.length === 0) failures.push(`package.json: the "animus" target of exports["${subpath}"], ${target}, matches no file in the package`);
4933
+ for (const file of matched) admit(subpath, file);
4934
+ } else if (!isFile(resolve(pkgRoot, target))) failures.push(`package.json: the "animus" target of exports["${subpath}"], ${target}, does not exist in the package`);
4935
+ else admit(subpath, relPath);
4936
+ }
4937
+ const visited = /* @__PURE__ */ new Set();
4938
+ while (queue.length > 0) {
4939
+ const file = queue.shift();
4940
+ if (visited.has(file)) continue;
4941
+ visited.add(file);
4942
+ const specifiers = parseInternalWire(moduleSpecifiers(JSON.stringify([{
4943
+ path: file,
4944
+ source: readFileSync$1(file, "utf-8")
4945
+ }])), "moduleSpecifiers").files[file] ?? [];
4946
+ for (const specifier of specifiers) {
4947
+ if (specifier.startsWith(".")) {
4948
+ const target = relativeSourceCandidates(file, specifier).find(isFile);
4949
+ if (target === void 0) failures.push(`${rel(file)}: import '${specifier}' resolves to no file in the package`);
4950
+ else if (outside(rel(target))) failures.push(`${rel(file)}: import '${specifier}' resolves to ${rel(target)}, outside the package`);
4951
+ else if (!published(rel(target))) failures.push(`${rel(file)}: import '${specifier}' resolves to ${rel(target)}, which is not in the published files`);
4952
+ else if (CODE_EXTENSIONS.has(extname(target))) queue.push(target);
4953
+ continue;
4954
+ }
4955
+ if (specifier.startsWith("/") || /^[a-z][\w+.-]*:/i.test(specifier)) {
4956
+ if (!isBuiltin(specifier)) failures.push(`${rel(file)}: import '${specifier}' is not a package or relative import, so an installed consumer cannot resolve it`);
4957
+ continue;
4958
+ }
4959
+ const name = bareSpecifierPackageName(specifier);
4960
+ if (isBuiltin(name) || name === ownName || declared.has(name)) continue;
4961
+ failures.push(`${rel(file)}: import '${specifier}' names the package ${name}, which package.json does not declare in dependencies, peerDependencies or optionalDependencies`);
4962
+ }
4963
+ }
4964
+ const artifacts = artifactDir === void 0 ? "" : rel(artifactDir);
4965
+ if (artifacts !== "" && !outside(artifacts)) {
4966
+ const shipped = [...publication.files].filter((file) => file.startsWith(`${artifacts}/`));
4967
+ if (shipped.length > 0) failures.push(`${artifacts}/: npm pack would publish this build-artifact directory (${shipped.length} files) — add "${artifacts}/" to .npmignore or .gitignore, or list the published files in package.json "files"`);
4968
+ }
4969
+ return failures;
4970
+ }
4971
+ //#endregion
4299
4972
  //#region pipeline/replacement-plans.ts
4300
4973
  const snapshotByManifest = /* @__PURE__ */ new WeakMap();
4301
4974
  /** `null` (a context before its first analysis) snapshots to the empty plan
@@ -4372,4 +5045,4 @@ function realpathThroughNearestExistingAncestor(path) {
4372
5045
  }
4373
5046
  }
4374
5047
  //#endregion
4375
- export { resolveVerbosity as $, firstOwners as A, substituteSheetAssets as At, isPathWithinRoot as B, resolveThroughPathAliases as C, unresolvedParentName as Ct, excludeCollectedPackages as D, generatedModuleCode as Dt, engineModuleParser as E, findSheetAssetSpecifiers as Et, walkPackageSources as F, assembleStylesheet as Ft, CORE_OPTION_KEYS as G, compareDiscoveryOrder as H, isJsonBlock as I, stripLeadingLayerDeclaration as It, REPLACEABLE_DEFAULT_EXCLUDE as J, DEFAULT_EXCLUDE as K, isJsonString as L, validateLayerOrder as Lt, resolveAbsolutePathSpecifier as M, contentHash as Mt, staleDistIncludesMessage as N, buildAnalyzeProjectArgs as Nt, extractSystemFilePackages as O, reportSurvivingAssetPlaceholders as Ot, unresolvableIncludesMessage as P, ANIMUS_LAYERS as Pt, resolveMode as Q, readTsconfigAliasPairs as R, __require as Rt, resolveAssetFile as S, unreadableSourceDiagnostic as St, collectExternalPackageSources as T, findAssetSpecifiers as Tt, discoverFiles as U, sharesVolumeRoot as V, AnimusConfigError as W, assertKnownOptionKeys as X, STRUCTURAL_EXCLUDE as Y, createExcludeMatcher as Z, applyUnitFallback as _, isDeletedSource as _t, assertNoErrorDiagnostics as a, parseFilesJson as at, buildPathAliasesJson as b, surfaceManifestDiagnostics as bt, runStructuralSelfCheck as c, DEFAULT_EXTENSIONS as ct, serializeStaticCss as d, preprocessMdx as dt, RETIRED_ENGINE_MESSAGE as et, camelToKebab as f, DIAGNOSTIC_LEVELS as ft, runProjectAnalysis as g, VOCABULARY_LEGACY_VERB as gt, clearEngineCache as h, VOCABULARY_COLLISION as ht, snapshotFilePlans as i, isAdvisorySourceDiagnostic as it, isExcludedPackageRelativePath as j, parseInternalWire as jt, findPackageRoot as k, substituteAssetPlaceholders as kt, loadSystemConfig as l, ENGINE_TRANSFORM_EXTENSIONS as lt, buildAnalysisInputs as m, INVALID_PROPERTY_REGISTRATION as mt, diffFilePlans as n, createV2EngineApi as nt, buildSystemPropsModule as o, projectExternalFileOwners as ot, stableStringify as p, DiagnosticFailure as pt, DRIVER_NAMESPACES as q, hashReplacementPlans as r, ingestSourceEntries as rt, buildDynamicPropConfig as s, adaptSvelteSource as st, toWatchKeys as t, assertNoRetiredEngineSelection as tt, applyPrefix as u, isEngineTransformExtension as ut, postProcessCss as v, isUnresolvedParentDrop as vt, createSourceCorpus as w, vocabularyWitnessDiagnostics as wt, enforceExternalTokenContracts as x, systemLoadDiagnostics as xt, resolveLightningTargets as y, noKitFilesDiagnostics as yt, createSourceIdentity as z };
5048
+ export { discoverFiles as $, fileSideEffects as A, surfaceManifestDiagnostics as At, unresolvableIncludesMessage as B, substituteSheetAssets as Bt, resolveAssetFile as C, DiagnosticFailure as Ct, engineModuleParser as D, isDeletedSource as Dt, collectExternalPackageSources as E, VOCABULARY_LEGACY_VERB as Et, keepsKitSourceEffects as F, findAssetSpecifiers as Ft, KIT_DESCRIPTOR_FILE as G, assembleStylesheet as Gt, createSourceIdentity as H, contentHash as Ht, kitSourceModuleSideEffects as I, findSheetAssetSpecifiers as It, readKitDescriptor as J, __require as Jt, buildKitDescriptor as K, stripLeadingLayerDeclaration as Kt, resolveAbsolutePathSpecifier as L, generatedModuleCode as Lt, firstOwners as M, unreadableSourceDiagnostic as Mt, importedKitDiagnostics as N, unresolvedParentName as Nt, excludeCollectedPackages as O, isUnresolvedParentDrop as Ot, isExcludedPackageRelativePath as P, vocabularyWitnessDiagnostics as Pt, compareDiscoveryOrder as Q, sourceKitDependencies as R, reportSurvivingAssetPlaceholders as Rt, enforceExternalTokenContracts as S, DIAGNOSTIC_LEVELS as St, createSourceCorpus as T, VOCABULARY_COLLISION as Tt, isPathWithinRoot as U, buildAnalyzeProjectArgs as Ut, walkPackageSources as V, parseInternalWire as Vt, sharesVolumeRoot as W, ANIMUS_LAYERS as Wt, isJsonString as X, isJsonBlock as Y, readTsconfigAliasPairs as Z, runProjectAnalysis as _, adaptSvelteSource as _t, kitPublicationFailures as a, STRUCTURAL_EXCLUDE as at, resolveLightningTargets as b, isEngineTransformExtension as bt, buildDynamicPropConfig as c, resolveMode as ct, applyPrefix as d, assertNoRetiredEngineSelection as dt, AnimusConfigError as et, serializeStaticCss as f, createV2EngineApi as ft, clearEngineCache as g, projectExternalFileOwners as gt, buildAnalysisInputs as h, parseFilesJson as ht, snapshotFilePlans as i, REPLACEABLE_DEFAULT_EXCLUDE as it, findPackageRoot as j, systemLoadDiagnostics as jt, extractSystemFilePackages as k, noKitFilesDiagnostics as kt, runStructuralSelfCheck as l, resolveVerbosity as lt, stableStringify as m, isAdvisorySourceDiagnostic as mt, diffFilePlans as n, DEFAULT_EXCLUDE as nt, assertNoErrorDiagnostics as o, assertKnownOptionKeys as ot, camelToKebab as p, ingestSourceEntries as pt, kitDescriptorDiagnostics as q, validateLayerOrder as qt, hashReplacementPlans as r, DRIVER_NAMESPACES as rt, buildSystemPropsModule as s, createExcludeMatcher as st, toWatchKeys as t, CORE_OPTION_KEYS as tt, loadSystemConfig as u, RETIRED_ENGINE_MESSAGE as ut, applyUnitFallback as v, DEFAULT_EXTENSIONS as vt, resolveThroughPathAliases as w, INVALID_PROPERTY_REGISTRATION as wt, buildPathAliasesJson as x, preprocessMdx as xt, postProcessCss as y, ENGINE_TRANSFORM_EXTENSIONS as yt, staleDistIncludesMessage as z, substituteAssetPlaceholders as zt };