@animus-ui/extract 0.1.23 → 0.1.25

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 +22 -3
  5. package/dist/index.cjs +11 -1
  6. package/dist/index.mjs +2 -2
  7. package/dist/pipeline/analyze-project-args.d.ts +9 -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-B3JzXiSY.cjs → pipeline-DOgKR4VZ.cjs} +1066 -302
  41. package/dist/{pipeline-kA3VEMgt.mjs → pipeline-YGWpNr_Z.mjs} +1024 -321
  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,14 @@ 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
+ inputs.propertyRecordsJson
99
+ ];
100
+ const last = tail.findLastIndex((slot) => slot !== void 0 && slot !== "");
101
+ for (const slot of tail.slice(0, last + 1)) args.push(slot || void 0);
95
102
  return args;
96
103
  }
97
104
  //#endregion
@@ -237,13 +244,17 @@ function substituteSheetAssets(sheets, urlBySpecifier) {
237
244
  }
238
245
  const UNSUBSTITUTED_ASSET_CODE = "animus.asset.unsubstituted-placeholder";
239
246
  /** A placeholder in emitted CSS is a broken URL in the browser: it fails a
240
- * strict build and warns otherwise. */
247
+ * strict build, strict development reports it, and it warns otherwise. */
241
248
  function reportSurvivingAssetPlaceholders(css, report) {
242
249
  const specifiers = placeholdersInAssetCalls(css);
243
250
  if (specifiers.length === 0) return;
244
251
  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);
252
+ if (!report.strict) {
253
+ report.warn(message);
254
+ return;
255
+ }
256
+ if (!report.reportErrors) throw new Error(message);
257
+ report.reportErrors(message);
247
258
  }
248
259
  /**
249
260
  * The runtime code an analysis generates: each dynamic prop config, which the
@@ -272,6 +283,15 @@ function locatedPrefix(diagnostic) {
272
283
  function droppedSuffix(diagnostic) {
273
284
  return diagnostic.dropped && !diagnostic.message.includes(diagnostic.dropped) ? ` — dropped: ${diagnostic.dropped}` : "";
274
285
  }
286
+ /** The record's code, when its message does not already quote it. */
287
+ function codeSuffix(diagnostic) {
288
+ return diagnostic.code && !diagnostic.message.includes(diagnostic.code) ? ` [${diagnostic.code}]` : "";
289
+ }
290
+ /** A warn-kind record's line after its mark:
291
+ * `file:line:column: component: message [code]`. */
292
+ function warnLine(diagnostic) {
293
+ return `${locationOf(diagnostic)}: ${diagnostic.component}: ${diagnostic.message}${droppedSuffix(diagnostic)}${codeSuffix(diagnostic)}`;
294
+ }
275
295
  /** Stable code for selector forms with no substitutable subject; the
276
296
  * extraction engine mints the same string. */
277
297
  const SELECTOR_UNSUPPORTED_SUBJECT = "animus.selector.unsupported-subject";
@@ -290,10 +310,19 @@ const DIAGNOSTIC_LEVELS = /* @__PURE__ */ new Set([
290
310
  "warn",
291
311
  "error"
292
312
  ]);
313
+ /** A key that selects every record of a kind: `kind:bail`, `kind:skip`,
314
+ * `kind:warn` or `kind:error`. */
315
+ const KIND_KEY = "kind:";
316
+ const DIAGNOSTIC_KINDS = /* @__PURE__ */ new Set([
317
+ "bail",
318
+ "skip",
319
+ "warn",
320
+ "error"
321
+ ]);
293
322
  /** The level `levels` sets for `code`: its exact entry, else the entry of
294
323
  * the longest prefix it starts with. */
295
- function levelFor(code, levels) {
296
- if (code === void 0 || levels === void 0) return void 0;
324
+ function codeLevel(code, levels) {
325
+ if (code === void 0) return void 0;
297
326
  if (Object.hasOwn(levels, code)) return levels[code];
298
327
  let longest;
299
328
  for (const [key, level] of Object.entries(levels)) {
@@ -306,11 +335,19 @@ function levelFor(code, levels) {
306
335
  }
307
336
  return longest?.level;
308
337
  }
338
+ /** The level `levels` sets for a record: its code's level, else its kind's. */
339
+ function levelFor({ code, kind }, levels) {
340
+ if (levels === void 0) return void 0;
341
+ const kindKey = `${KIND_KEY}${kind}`;
342
+ return codeLevel(code, levels) ?? (Object.hasOwn(levels, kindKey) ? levels[kindKey] : void 0);
343
+ }
309
344
  /** 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. */
345
+ * `error` for a hard error (an `error`-kind record) or an error-severity
346
+ * record under `strict`, else its own. */
311
347
  function effectiveLevel(diagnostic, policy) {
312
- const level = levelFor(diagnostic.code, policy.levels);
348
+ const level = levelFor(diagnostic, policy.levels);
313
349
  if (level !== void 0) return level;
350
+ if (diagnostic.kind === "error") return "error";
314
351
  if (diagnostic.severity === "info") return "info";
315
352
  return policy.strict && diagnostic.severity === "error" ? "error" : "warn";
316
353
  }
@@ -329,6 +366,7 @@ function knownDiagnosticCodes(engineCodesJson) {
329
366
  /** The keys of `levels` that name no known code, exactly or as a prefix. */
330
367
  function unknownDiagnosticKeys(levels, known) {
331
368
  return Object.keys(levels).filter((key) => {
369
+ if (key.startsWith(KIND_KEY)) return !DIAGNOSTIC_KINDS.has(key.slice(5));
332
370
  if (!key.endsWith(".*")) return !known.has(key);
333
371
  const prefix = key.slice(0, -1);
334
372
  return ![...known].some((code) => code.startsWith(prefix));
@@ -383,9 +421,22 @@ function collectSelectorAliasDiagnostics(selectorAliasesJson) {
383
421
  const UNREADABLE_SOURCE_FILE = "animus.ingestion.unreadable-source-file";
384
422
  /** A kit the system extends resolved, yet discovery found none of its files. */
385
423
  const NO_KIT_FILES = "animus.discovery.no-kit-files";
424
+ /** A kit with no `animus` export condition whose exports do not all target
425
+ * TypeScript source: discovery guesses its source from `src/`. */
426
+ const KIT_WITHOUT_SOURCE_CONDITION = "animus.discovery.kit-without-source-condition";
427
+ /** A kit's `animus` export condition names a file that is missing or outside
428
+ * its package, so that entry is not read from source. */
429
+ const INVALID_KIT_SOURCE_CONDITION = "animus.discovery.invalid-source-condition";
430
+ /** A kit the application imports whose system the application's system
431
+ * does not include: its components are not extracted. */
432
+ const KIT_SYSTEM_NOT_INCLUDED = "animus.kit.system-not-included";
386
433
  /** A system file's `createSystem` binding that discovery could not follow to
387
434
  * Animus's factory, so it is no root. */
388
435
  const UNPROVEN_ROOT_BINDING = "animus.discovery.unproven-root-binding";
436
+ /** A system file calls `createSystem` with no import or local binding. The
437
+ * system loader evaluates the file without auto-imports, where the name is
438
+ * undefined, so the call is no root. */
439
+ const UNIMPORTED_CREATE_SYSTEM = "animus.discovery.unimported-create-system";
389
440
  /** What a skipped source file costs: the analysis never sees what it
390
441
  * renders. */
391
442
  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 +472,11 @@ function noKitFilesDiagnostics(outcomes) {
421
472
  severity: severityFor(NO_KIT_FILES)
422
473
  }));
423
474
  }
475
+ /** A kit's descriptor declares a format this Animus does not read. */
476
+ const KIT_UNSUPPORTED_FORMAT = "animus.kit.unsupported-format";
477
+ /** A kit's descriptor records a definition its shipped source no longer
478
+ * declares. */
479
+ const KIT_STALE_DESCRIPTOR = "animus.kit.stale-descriptor";
424
480
  /** The collision entry code minted by the system package's merge. */
425
481
  const VOCABULARY_COLLISION = "animus.vocabulary.collision";
426
482
  /** A theme `@property` registration browsers would ignore; it is not emitted. */
@@ -446,9 +502,6 @@ const PROPERTY_FALLBACK_SELF_REFERENCE = "animus.property.fallback-self-referenc
446
502
  * another directly, so every property in the cycle is invalid at
447
503
  * computed-value time. */
448
504
  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
505
  /** Under `prefixContextualVars`, a final name that collides with a runtime
453
506
  * transport variable or a theme variable of the same spelling. */
454
507
  const PREFIX_NAME_CONFLICT = "animus.prefix.name-conflict";
@@ -462,7 +515,13 @@ const DIAGNOSTIC_SEVERITY = /* @__PURE__ */ new Map([
462
515
  [SELECTOR_UNSUPPORTED_SUBJECT, "error"],
463
516
  [UNREADABLE_SOURCE_FILE, "error"],
464
517
  [NO_KIT_FILES, "warn"],
518
+ [KIT_WITHOUT_SOURCE_CONDITION, "warn"],
519
+ [INVALID_KIT_SOURCE_CONDITION, "error"],
520
+ [KIT_SYSTEM_NOT_INCLUDED, "error"],
521
+ [KIT_UNSUPPORTED_FORMAT, "error"],
522
+ [KIT_STALE_DESCRIPTOR, "warn"],
465
523
  [UNPROVEN_ROOT_BINDING, "warn"],
524
+ [UNIMPORTED_CREATE_SYSTEM, "warn"],
466
525
  [VOCABULARY_COLLISION, "warn"],
467
526
  [VOCABULARY_LEGACY_VERB, "warn"],
468
527
  [INVALID_PROPERTY_REGISTRATION, "error"],
@@ -472,7 +531,6 @@ const DIAGNOSTIC_SEVERITY = /* @__PURE__ */ new Map([
472
531
  [PROPERTY_SELF_REFERENCE, "warn"],
473
532
  [PROPERTY_FALLBACK_SELF_REFERENCE, "warn"],
474
533
  [PROPERTY_CURRENT_VAR_CYCLE, "warn"],
475
- [PREFIX_CONTEXTUAL_VARS_UNPREFIXED, "warn"],
476
534
  [PREFIX_NAME_CONFLICT, "error"],
477
535
  [PROPERTY_LEGACY_TOKEN_COLLISION, "warn"],
478
536
  [PROPERTY_TOKEN_COLLISION, "error"]
@@ -527,15 +585,6 @@ function systemLoadDiagnostics(system) {
527
585
  code: INVALID_PROPERTY_REGISTRATION,
528
586
  severity: severityFor(INVALID_PROPERTY_REGISTRATION)
529
587
  }));
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
588
  const conflicts = (system.prefixNameConflicts ?? []).map(({ name, final, reason }) => ({
540
589
  file: "system",
541
590
  component: `--${name}`,
@@ -547,7 +596,6 @@ function systemLoadDiagnostics(system) {
547
596
  return [
548
597
  ...vocabularyWitnessDiagnostics(system.vocabularyWitnessesJson),
549
598
  ...registrations,
550
- ...unprefixed,
551
599
  ...conflicts,
552
600
  ...tokenCollisionDiagnostics(system)
553
601
  ];
@@ -583,13 +631,14 @@ function tokenCollisionDiagnostics(system) {
583
631
  }
584
632
  /**
585
633
  * The single strict-escalation policy point for both extraction plugins:
586
- * error-severity diagnostics throw together under `strict`, else warn.
634
+ * error-severity diagnostics throw together under `strict`, else warn. A
635
+ * development session reports them through `reportErrors` instead.
587
636
  */
588
637
  function surfaceManifestDiagnostics(manifest, warn, policy = {}) {
589
- const errors = [];
638
+ const errors = /* @__PURE__ */ new Set();
590
639
  if (policy.levels && policy.knownCodes && !checkedLevels.has(policy.levels)) {
591
640
  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)`);
641
+ 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
642
  }
594
643
  const diagnostics = policy.prepend?.length ? [...policy.prepend, ...manifest.diagnostics ?? []] : manifest.diagnostics ?? [];
595
644
  for (const diagnostic of diagnostics) {
@@ -598,22 +647,28 @@ function surfaceManifestDiagnostics(manifest, warn, policy = {}) {
598
647
  let line = null;
599
648
  const mark = level === "info" ? "ℹ" : "⚠";
600
649
  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}`;
650
+ if (diagnostic.kind === "bail") line = `${mark} ${locatedPrefix(diagnostic)}${diagnostic.component} not extracted: ${message}${codeSuffix(diagnostic)}`;
651
+ else if (diagnostic.kind === "skip") line = `${mark} ${locatedPrefix(diagnostic)}${diagnostic.component}: skipped ${message}${codeSuffix(diagnostic)}`;
652
+ else if (diagnostic.kind === "warn" || diagnostic.kind === "error") line = `${mark} ${warnLine(diagnostic)}`;
604
653
  if (line === null) continue;
605
- if (diagnostic.code && !diagnostic.message.includes(diagnostic.code)) line += ` [${diagnostic.code}]`;
606
654
  if (level === "info") {
607
655
  policy.info?.(line);
608
656
  continue;
609
657
  }
610
658
  if (level === "error") {
611
- errors.push(`${diagnostic.code ?? "error"} — ${locatedPrefix(diagnostic)}${diagnostic.component}: ${message}`);
659
+ const subject = diagnostic.kind === "warn" || diagnostic.kind === "error" ? `${locationOf(diagnostic)}: ` : locatedPrefix(diagnostic);
660
+ errors.add(`${diagnostic.code ?? "error"} — ${subject}${diagnostic.component}: ${message}`);
612
661
  continue;
613
662
  }
614
663
  warn(line);
615
664
  }
616
- if (errors.length > 0) throw new DiagnosticFailure(`[animus] strict: ${errors.length} error diagnostic(s):\n${errors.join("\n")}`);
665
+ if (errors.size === 0) return;
666
+ const message = `[animus] strict: ${errors.size} error diagnostic(s):\n${[...errors].join("\n")}`;
667
+ if (policy.reportErrors) {
668
+ policy.reportErrors(message);
669
+ return;
670
+ }
671
+ throw new DiagnosticFailure(message);
617
672
  }
618
673
  //#endregion
619
674
  //#region pipeline/mdx-preprocessor.ts
@@ -1580,7 +1635,8 @@ function createSourceIngestor(host) {
1580
1635
  const fatal = diagnostics.filter((diagnostic) => !isAdvisorySourceDiagnostic(diagnostic));
1581
1636
  const invalidOriginals = new Set(fatal.map((diagnostic) => diagnostic.originalPath));
1582
1637
  if (diagnostics.length === 0) return invalidOriginals;
1583
- if (host.strict() && fatal.length > 0) {
1638
+ const reportError = host.strict() ? host.reportErrors?.() : void 0;
1639
+ if (host.strict() && fatal.length > 0 && !reportError) {
1584
1640
  const lines = fatal.map((diagnostic) => `${diagnostic.code} ${diagnostic.originalPath}: ${diagnostic.message} (${SKIPPED_SOURCE_COST})`);
1585
1641
  throw new Error(`${host.prefix} ${lines.join(`\n${host.prefix} `)}`);
1586
1642
  }
@@ -1594,7 +1650,8 @@ function createSourceIngestor(host) {
1594
1650
  }
1595
1651
  if (warned.has(line)) continue;
1596
1652
  warned.add(line);
1597
- host.warn(`${host.prefix} ${line}`);
1653
+ if (reportError && skipped) reportError(`${host.prefix} ${line}`);
1654
+ else host.warn(`${host.prefix} ${line}`);
1598
1655
  }
1599
1656
  return invalidOriginals;
1600
1657
  },
@@ -1621,8 +1678,9 @@ function createV2EngineApi(deps) {
1621
1678
  return {
1622
1679
  loadSystemModule: (...args) => native.loadSystemModule(...args),
1623
1680
  extractFacts: (filesJson) => native.extractFacts(filesJson),
1681
+ moduleSpecifiers: (filesJson) => native.moduleSpecifiers(filesJson),
1624
1682
  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) => {
1683
+ analyzeProject: (filesJsonRaw, scalesJson, variableMapJson, contextualVarsJson, propConfigJson, groupRegistryJson, packageResolutionJson, devMode, emitterConfigJson, selectorAliasesJson, _selectorOrderJson, globalStyleBlocksJson, pathAliasesJson, keyframesJson, staticCssJson, conditionAliasesJson, externalDirsJson, transformSourcesJson, transformProvenanceJson, declarationScalesJson, analysisContextJson, generatedNamesJson, propertyRecordsJson) => {
1626
1684
  const filesJson = deps.rehydrateFilesJson ? deps.rehydrateFilesJson(filesJsonRaw) : filesJsonRaw;
1627
1685
  const sent = /* @__PURE__ */ new Map();
1628
1686
  for (const entry of parseFilesJson(filesJson, label)) sent.set(entry.path, entry.source);
@@ -1650,6 +1708,8 @@ function createV2EngineApi(deps) {
1650
1708
  transformProvenanceJson: transformProvenanceJson ?? void 0,
1651
1709
  declarationScalesJson,
1652
1710
  analysisContextJson,
1711
+ generatedNamesJson,
1712
+ propertyRecordsJson,
1653
1713
  devMode
1654
1714
  };
1655
1715
  const engine = new native.ExtractEngine(config);
@@ -1972,7 +2032,7 @@ function walkFiles(dir, rootDir, exclude, extensionsSet) {
1972
2032
  const isExcluded = exclude ? (full, rel) => exclude.matches(full, rel) : () => false;
1973
2033
  for (const entry of entries) {
1974
2034
  const fullPath = join$1(dir, entry);
1975
- if (isExcluded(fullPath, relative(rootDir, fullPath))) continue;
2035
+ if (isExcluded(fullPath, relative$1(rootDir, fullPath))) continue;
1976
2036
  let stat;
1977
2037
  try {
1978
2038
  stat = statSync(fullPath);
@@ -1980,119 +2040,11 @@ function walkFiles(dir, rootDir, exclude, extensionsSet) {
1980
2040
  continue;
1981
2041
  }
1982
2042
  if (stat.isDirectory()) results.push(...walkFiles(fullPath, rootDir, exclude, extensionsSet));
1983
- else if (extensionsSet.has(extname(entry))) results.push(fullPath);
2043
+ else if (extensionsSet.has(extname$1(entry))) results.push(fullPath);
1984
2044
  }
1985
2045
  return results;
1986
2046
  }
1987
2047
  //#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
2048
  //#region pipeline/tsconfig-paths.ts
2097
2049
  /**
2098
2050
  * tsconfig `paths` → alias pairs, for drivers with no live bundler config.
@@ -2199,8 +2151,8 @@ function readConfig(path) {
2199
2151
  };
2200
2152
  }
2201
2153
  function resolveExtendsTarget(specifier, fromDir) {
2202
- if (specifier.startsWith(".") || isAbsolute(specifier)) {
2203
- const base = resolve(fromDir, specifier);
2154
+ if (specifier.startsWith(".") || isAbsolute$1(specifier)) {
2155
+ const base = resolve$1(fromDir, specifier);
2204
2156
  for (const candidate of [
2205
2157
  base,
2206
2158
  `${base}.json`,
@@ -2225,7 +2177,7 @@ function loadChain(entryPath) {
2225
2177
  const queue = [entryPath];
2226
2178
  while (queue.length > 0) {
2227
2179
  const path = queue.shift();
2228
- const key = resolve(path);
2180
+ const key = resolve$1(path);
2229
2181
  if (visited.has(key)) continue;
2230
2182
  visited.add(key);
2231
2183
  const node = readConfig(key);
@@ -2250,7 +2202,7 @@ function readTsconfigAliasPairs(rootDir) {
2250
2202
  if (pathsOwner === void 0 || paths === null) return [];
2251
2203
  const baseOwner = chain.find((node) => node.baseUrl !== null);
2252
2204
  const baseUrl = baseOwner?.baseUrl ?? null;
2253
- const base = baseOwner !== void 0 && baseUrl !== null ? resolve(baseOwner.dir, baseUrl) : pathsOwner.dir;
2205
+ const base = baseOwner !== void 0 && baseUrl !== null ? resolve$1(baseOwner.dir, baseUrl) : pathsOwner.dir;
2254
2206
  const pairs = [];
2255
2207
  for (const [pattern, target] of paths) {
2256
2208
  const patternStars = pattern.split("*").length - 1;
@@ -2260,7 +2212,7 @@ function readTsconfigAliasPairs(rootDir) {
2260
2212
  if (!target.endsWith("/*")) continue;
2261
2213
  pairs.push({
2262
2214
  pattern: pattern.slice(0, -2),
2263
- target: resolve(base, target.slice(0, -2)),
2215
+ target: resolve$1(base, target.slice(0, -2)),
2264
2216
  kind: "prefix"
2265
2217
  });
2266
2218
  continue;
@@ -2268,13 +2220,223 @@ function readTsconfigAliasPairs(rootDir) {
2268
2220
  if (patternStars > 0 || targetStars > 0) continue;
2269
2221
  pairs.push({
2270
2222
  pattern,
2271
- target: resolve(base, target),
2223
+ target: resolve$1(base, target),
2272
2224
  kind: "exact"
2273
2225
  });
2274
2226
  }
2275
2227
  return pairs;
2276
2228
  }
2277
2229
  //#endregion
2230
+ //#region pipeline/kit-descriptor.ts
2231
+ /** A kit's description, which `animus build --kit` writes at its package
2232
+ * root and the kit exports as `./animus.json`. */
2233
+ const KIT_DESCRIPTOR_FILE = "animus.json";
2234
+ /** A path with `/` separators, as descriptors key their components. */
2235
+ function posixPath$1(path) {
2236
+ return path.split(sep).join("/");
2237
+ }
2238
+ /** The descriptor of the kit a build analysed. */
2239
+ function buildKitDescriptor(manifest) {
2240
+ const components = {};
2241
+ for (const id of Object.keys(manifest.components).sort()) {
2242
+ const component = manifest.components[id];
2243
+ components[posixPath$1(id)] = {
2244
+ definition: component.definition_fingerprint,
2245
+ runtimeProps: [...new Set(component.system_prop_names)].sort()
2246
+ };
2247
+ }
2248
+ return {
2249
+ format: 1,
2250
+ system: manifest.system_fingerprint,
2251
+ components
2252
+ };
2253
+ }
2254
+ /** Reads the descriptor at a kit's package root; `null` when it has none. */
2255
+ function readKitDescriptor(pkgRoot, rootDir) {
2256
+ const path = join(pkgRoot, KIT_DESCRIPTOR_FILE);
2257
+ if (!existsSync$1(path)) return null;
2258
+ const packageRoot = posixPath$1(relative(rootDir, pkgRoot));
2259
+ let wire;
2260
+ try {
2261
+ wire = JSON.parse(readFileSync$1(path, "utf-8"));
2262
+ } catch {
2263
+ return {
2264
+ packageRoot,
2265
+ unreadable: "is not valid JSON: rebuild it with animus build --kit"
2266
+ };
2267
+ }
2268
+ const block = isJsonBlock(wire) ? wire : {};
2269
+ if (block.format !== 1) return {
2270
+ packageRoot,
2271
+ 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`
2272
+ };
2273
+ const definitions = {};
2274
+ const components = isJsonBlock(block.components) ? block.components : {};
2275
+ for (const [id, component] of Object.entries(components)) {
2276
+ const definition = isJsonBlock(component) ? component.definition : null;
2277
+ if (isJsonString(definition)) definitions[posixPath$1(id)] = definition;
2278
+ }
2279
+ return {
2280
+ packageRoot,
2281
+ definitions
2282
+ };
2283
+ }
2284
+ /**
2285
+ * A descriptor in a format this Animus cannot read fails the build; one
2286
+ * whose component definitions differ from the kit's shipped source, as the
2287
+ * analysis read it, or that describes a component its analysed file no
2288
+ * longer declares, was built from other source and is stale.
2289
+ */
2290
+ function kitDescriptorDiagnostics(records, manifest) {
2291
+ if (records.length === 0) return [];
2292
+ const diagnostics = [];
2293
+ const analysedById = new Map(Object.entries(manifest.components).map(([id, component]) => [posixPath$1(id), component]));
2294
+ const analysedFiles = new Set(Object.keys(manifest.fileFacts).map(posixPath$1));
2295
+ const declared = new Set(Object.entries(manifest.fileFacts).flatMap(([file, facts]) => facts.chains.map((chain) => `${posixPath$1(file)}::${chain.descriptor.binding}`)));
2296
+ for (const record of records) {
2297
+ const file = `${record.packageRoot}/${KIT_DESCRIPTOR_FILE}`;
2298
+ if ("unreadable" in record) {
2299
+ diagnostics.push({
2300
+ file,
2301
+ component: "kit",
2302
+ kind: "error",
2303
+ message: record.unreadable,
2304
+ code: KIT_UNSUPPORTED_FORMAT,
2305
+ severity: severityFor(KIT_UNSUPPORTED_FORMAT)
2306
+ });
2307
+ continue;
2308
+ }
2309
+ for (const [id, definition] of Object.entries(record.definitions)) {
2310
+ const key = `${record.packageRoot}/${id}`;
2311
+ const analysed = analysedById.get(key);
2312
+ const fileAnalysed = analysedFiles.has(key.slice(0, key.lastIndexOf("::")));
2313
+ let stale;
2314
+ if (analysed) {
2315
+ if (analysed.definition_fingerprint === definition) continue;
2316
+ stale = `describes ${id} with a definition other than the one its shipped source declares`;
2317
+ } else if (fileAnalysed && !declared.has(key)) stale = `describes ${id}, which its shipped source no longer declares`;
2318
+ else continue;
2319
+ diagnostics.push({
2320
+ file,
2321
+ component: analysed?.binding ?? id.slice(id.lastIndexOf("::") + 2),
2322
+ kind: "warn",
2323
+ message: `${stale}, so the descriptor is stale: rebuild it with animus build --kit`,
2324
+ code: KIT_STALE_DESCRIPTOR,
2325
+ severity: severityFor(KIT_STALE_DESCRIPTOR)
2326
+ });
2327
+ }
2328
+ }
2329
+ return diagnostics;
2330
+ }
2331
+ //#endregion
2332
+ //#region pipeline/source-identity.ts
2333
+ /**
2334
+ * One derivation of source identity for discovery, watch ingestion, ownership
2335
+ * and deletion: event paths are lookup INPUTS only and never fork identity.
2336
+ */
2337
+ /**
2338
+ * True when `target` is `root` or a descendant, decided by `relative()`
2339
+ * shape: string prefixing would let `/ui` claim `/ui-old`.
2340
+ */
2341
+ function isPathWithinRoot(root, target, pathApi = path) {
2342
+ const rel = pathApi.relative(root, target);
2343
+ return rel === "" || !pathApi.isAbsolute(rel) && rel !== ".." && !rel.startsWith(".." + pathApi.sep);
2344
+ }
2345
+ /**
2346
+ * True when two paths share a platform root (win32 drive letter or UNC
2347
+ * share; always true on posix). Drive letters compare case-insensitively.
2348
+ */
2349
+ function sharesVolumeRoot(a, b, pathApi = path) {
2350
+ const volumeOf = (p) => pathApi.parse(pathApi.resolve(p)).root.toLowerCase();
2351
+ return volumeOf(a) === volumeOf(b);
2352
+ }
2353
+ function canonicalize(p) {
2354
+ try {
2355
+ return realpathSync$1(p);
2356
+ } catch {
2357
+ return null;
2358
+ }
2359
+ }
2360
+ function createSourceIdentity(rootDir) {
2361
+ const normalizedRootDir = path.normalize(rootDir);
2362
+ const canonicalRootDir = canonicalize(normalizedRootDir) ?? normalizedRootDir;
2363
+ const roots = [];
2364
+ const aliases = /* @__PURE__ */ new Map();
2365
+ const owningRecord = (canonicalPath) => {
2366
+ let owner = null;
2367
+ for (const record of roots) {
2368
+ if (!isPathWithinRoot(record.canonical, canonicalPath)) continue;
2369
+ if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2370
+ }
2371
+ return owner;
2372
+ };
2373
+ return {
2374
+ rootDir: normalizedRootDir,
2375
+ canonicalRootDir,
2376
+ registerExternalRoot(root) {
2377
+ const asRegistered = path.normalize(root);
2378
+ const canonical = canonicalize(asRegistered) ?? asRegistered;
2379
+ const existing = roots.find((record) => record.canonical === canonical);
2380
+ if (existing) return existing.canonical;
2381
+ roots.push({
2382
+ asRegistered,
2383
+ canonical
2384
+ });
2385
+ return canonical;
2386
+ },
2387
+ externalRoots() {
2388
+ return roots.map((record) => record.canonical);
2389
+ },
2390
+ resolveSourceId(inputPath) {
2391
+ const lexical = path.normalize(inputPath);
2392
+ const canonical = canonicalize(lexical);
2393
+ if (canonical === null) return null;
2394
+ const owner = owningRecord(canonical);
2395
+ const ownedBy = (record) => {
2396
+ const pathInRoot = path.relative(record.canonical, canonical);
2397
+ return {
2398
+ sourceKey: path.relative(normalizedRootDir, path.join(record.asRegistered, pathInRoot)),
2399
+ owningRoot: record.canonical,
2400
+ pathInRoot
2401
+ };
2402
+ };
2403
+ const ownerIsMoreSpecific = owner !== null && owner.canonical.length > canonicalRootDir.length;
2404
+ let resolved;
2405
+ if (!ownerIsMoreSpecific && isPathWithinRoot(canonicalRootDir, canonical)) {
2406
+ const key = path.relative(canonicalRootDir, canonical);
2407
+ resolved = {
2408
+ sourceKey: key,
2409
+ owningRoot: null,
2410
+ pathInRoot: key
2411
+ };
2412
+ } else if (owner) resolved = ownedBy(owner);
2413
+ else return null;
2414
+ aliases.set(lexical, resolved);
2415
+ aliases.set(canonical, resolved);
2416
+ return resolved;
2417
+ },
2418
+ resolveDeletedSourceId(inputPath) {
2419
+ return aliases.get(path.normalize(inputPath)) ?? null;
2420
+ },
2421
+ containingExternalRoot(inputPath) {
2422
+ const lexical = path.normalize(inputPath);
2423
+ let owner = null;
2424
+ for (const record of roots) {
2425
+ if (!(isPathWithinRoot(record.canonical, lexical) || isPathWithinRoot(record.asRegistered, lexical))) continue;
2426
+ if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2427
+ }
2428
+ if (owner) return owner.canonical;
2429
+ const canonical = canonicalize(lexical);
2430
+ if (canonical === null) return null;
2431
+ for (const record of roots) {
2432
+ if (!isPathWithinRoot(record.canonical, canonical)) continue;
2433
+ if (!owner || record.canonical.length > owner.canonical.length) owner = record;
2434
+ }
2435
+ return owner?.canonical ?? null;
2436
+ }
2437
+ };
2438
+ }
2439
+ //#endregion
2278
2440
  //#region pipeline/discover-packages.ts
2279
2441
  function findPackageRoot(absEntryPath) {
2280
2442
  let pkgRoot = dirname$1(absEntryPath);
@@ -2291,7 +2453,7 @@ function isExcludedPackageRelativePath(rel) {
2291
2453
  return PACKAGE_SRC_EXCLUDES.some((pattern) => rel.includes(pattern));
2292
2454
  }
2293
2455
  function walkPackageSources(packageDir, extensionsSet) {
2294
- return discoverFiles(packageDir, packageDir, void 0, extensionsSet).filter((absPath) => !isExcludedPackageRelativePath(relative(packageDir, absPath)));
2456
+ return discoverFiles(packageDir, packageDir, void 0, extensionsSet).filter((absPath) => !isExcludedPackageRelativePath(relative$1(packageDir, absPath)));
2295
2457
  }
2296
2458
  const PACKAGE_OUTPUT_EXCLUDES = [
2297
2459
  "node_modules",
@@ -2300,7 +2462,7 @@ const PACKAGE_OUTPUT_EXCLUDES = [
2300
2462
  ".d.ts",
2301
2463
  ".map"
2302
2464
  ];
2303
- const isFile = (path) => {
2465
+ const isFile$1 = (path) => {
2304
2466
  try {
2305
2467
  return statSync(path).isFile();
2306
2468
  } catch {
@@ -2312,14 +2474,15 @@ function resolveAbsolutePathSpecifier(absSpecifier, extensionsSet) {
2312
2474
  absSpecifier,
2313
2475
  ...Array.from(extensionsSet, (ext) => absSpecifier + ext),
2314
2476
  ...Array.from(extensionsSet, (ext) => join$1(absSpecifier, `index${ext}`))
2315
- ].find(isFile) ?? null;
2477
+ ].find(isFile$1) ?? null;
2316
2478
  }
2479
+ /** The package a bare specifier names: `@scope/name` or `name`. */
2317
2480
  function bareSpecifierPackageName(specifier) {
2318
2481
  const segments = specifier.split("/");
2319
2482
  return specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
2320
2483
  }
2321
2484
  function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
2322
- if (isAbsolute(specifier)) {
2485
+ if (isAbsolute$1(specifier)) {
2323
2486
  const resolved = resolveAbsolutePathSpecifier(specifier, extensionsSet);
2324
2487
  if (!resolved) return null;
2325
2488
  return isPathWithinRoot(srcDir, resolved) ? resolved : null;
@@ -2328,6 +2491,103 @@ function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
2328
2491
  const subpath = specifier.slice(packageName.length + 1);
2329
2492
  return resolveAbsolutePathSpecifier(join$1(srcDir, subpath || "index"), extensionsSet);
2330
2493
  }
2494
+ /** The package's parsed `package.json`, or null when it cannot be read. */
2495
+ function readPackageManifest(pkgRoot) {
2496
+ try {
2497
+ return JSON.parse(readFileSync(join$1(pkgRoot, "package.json"), "utf-8"));
2498
+ } catch {
2499
+ return null;
2500
+ }
2501
+ }
2502
+ /** Each `exports` subpath and its value; a bare target or condition object
2503
+ * is the `.` entry. */
2504
+ function exportsSubpaths(manifest) {
2505
+ const exports = isJsonBlock(manifest) ? manifest.exports : void 0;
2506
+ if (exports === void 0 || exports === null) return [];
2507
+ const subpaths = isJsonBlock(exports) && Object.keys(exports).some((k) => k.startsWith(".")) ? exports : { ".": exports };
2508
+ return Object.entries(subpaths).filter(([subpath]) => subpath.startsWith("."));
2509
+ }
2510
+ /**
2511
+ * The export condition a kit gives each public entry's original source:
2512
+ * `{ "types": …, "animus": "./src/system.ts", "import": …, "default": … }`.
2513
+ * Hosts never resolve through it; discovery reads it, redirects the entry to
2514
+ * its source in every host, and the system loader prefers it.
2515
+ */
2516
+ const KIT_SOURCE_CONDITION = "animus";
2517
+ /** The package's kit source condition, or null when no exact `exports`
2518
+ * entry declares it: the package is no source kit. */
2519
+ function readKitSourceCondition(pkgRoot) {
2520
+ const condition = {
2521
+ entries: [],
2522
+ invalid: [],
2523
+ root: null
2524
+ };
2525
+ for (const [subpath, value] of exportsSubpaths(readPackageManifest(pkgRoot))) {
2526
+ if (subpath.includes("*") || !isJsonBlock(value)) continue;
2527
+ const target = value[KIT_SOURCE_CONDITION];
2528
+ if (!isJsonString(target)) continue;
2529
+ const file = resolve$1(pkgRoot, target);
2530
+ if (isPathWithinRoot(pkgRoot, file) && isFile$1(file)) condition.entries.push([subpath, file]);
2531
+ else condition.invalid.push([subpath, target]);
2532
+ }
2533
+ if (condition.entries.length === 0 && condition.invalid.length === 0) return null;
2534
+ condition.root = sourceRoot(condition.entries);
2535
+ return condition;
2536
+ }
2537
+ /** The deepest directory holding every entry's file. */
2538
+ function sourceRoot(entries) {
2539
+ return entries.reduce((root, [, file]) => root === null ? dirname$1(file) : commonDirectory(root, dirname$1(file)), null);
2540
+ }
2541
+ /** A TypeScript source file; compiled output and declarations are not. */
2542
+ const TS_SOURCE = /(?<!\.d)\.[cm]?tsx?$/;
2543
+ /** A kit with no source condition whose every exact `exports` entry already
2544
+ * targets TypeScript source in the package under `import` or `default`:
2545
+ * those targets are its source, as the condition would name them. Null
2546
+ * when any exact entry has no such target, such as one only `require` or
2547
+ * `types` reaches, or there is no exact entry. */
2548
+ function sourceExportsCondition(pkgRoot) {
2549
+ const entries = [];
2550
+ for (const [subpath, value] of exportsSubpaths(readPackageManifest(pkgRoot))) {
2551
+ if (subpath.includes("*")) continue;
2552
+ const target = exportTarget(value);
2553
+ const file = target === null ? null : resolve$1(pkgRoot, target);
2554
+ if (file === null || !TS_SOURCE.test(file) || !isPathWithinRoot(pkgRoot, file) || !isFile$1(file)) return null;
2555
+ entries.push([subpath, file]);
2556
+ }
2557
+ if (entries.length === 0) return null;
2558
+ return {
2559
+ entries,
2560
+ invalid: [],
2561
+ root: sourceRoot(entries)
2562
+ };
2563
+ }
2564
+ function commonDirectory(a, b) {
2565
+ let dir = a;
2566
+ while (!isPathWithinRoot(dir, b)) dir = dirname$1(dir);
2567
+ return dir;
2568
+ }
2569
+ /** Whether the manifest at `dir` names the package `name`. */
2570
+ function isPackageNamed(dir, name) {
2571
+ const manifest = readPackageManifest(dir);
2572
+ return isJsonBlock(manifest) && manifest.name === name;
2573
+ }
2574
+ function realPath(path) {
2575
+ try {
2576
+ return realpathSync(path);
2577
+ } catch {
2578
+ return path;
2579
+ }
2580
+ }
2581
+ /** The root of the installed package `name` as Node finds it from `fromDir`,
2582
+ * the first `node_modules/<name>` up the directory tree, at its real path,
2583
+ * as host resolvers report a linked package. */
2584
+ function locatePackageRoot(name, fromDir) {
2585
+ for (let dir = fromDir;; dir = dirname$1(dir)) {
2586
+ const candidate = join$1(dir, "node_modules", name);
2587
+ if (existsSync(join$1(candidate, "package.json"))) return realPath(candidate);
2588
+ if (dir === dirname$1(dir)) return null;
2589
+ }
2590
+ }
2331
2591
  /**
2332
2592
  * A package's `sideEffects` field, decoded the way Vite reads it: a boolean
2333
2593
  * as written, or the list's globs, one with no `/` matching the basename
@@ -2336,12 +2596,7 @@ function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
2336
2596
  * extglobs), which leaves the bundler's side-effectful default.
2337
2597
  */
2338
2598
  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
- }
2599
+ const manifest = readPackageManifest(pkgRoot);
2345
2600
  const field = isJsonBlock(manifest) ? manifest.sideEffects : void 0;
2346
2601
  if (field === true || field === false) return field;
2347
2602
  if (!Array.isArray(field)) return void 0;
@@ -2349,9 +2604,80 @@ function readPackageSideEffects(pkgRoot) {
2349
2604
  if (globs.some((glob) => /[{}[\]()!+@]/.test(glob))) return void 0;
2350
2605
  return globs.map((glob) => globToRegExp(glob.includes("/") ? glob.replace(/^\.?\//, "") : `**/${glob}`));
2351
2606
  }
2607
+ /** Whether a bundler that reads the nearest `package.json`'s `sideEffects`
2608
+ * against the file's own path keeps `absFile`; undefined without a field
2609
+ * it reads, which keeps the bundler's side-effectful default. */
2610
+ function fileSideEffects(absFile) {
2611
+ const pkgRoot = findPackageRoot(absFile);
2612
+ const field = readPackageSideEffects(pkgRoot);
2613
+ if (field === void 0 || field === true || field === false) return field;
2614
+ return matchesSideEffects(field, pkgRoot, [absFile]);
2615
+ }
2616
+ /** Whether a `sideEffects` glob can name a code file: a last segment with
2617
+ * no extension can name any file, and an extension with glob syntax or of
2618
+ * a script can name code; `*.css` cannot. Brace alternatives are each read,
2619
+ * and braces this reading cannot expand count as naming code. */
2620
+ function globNamesCode(glob) {
2621
+ const alternatives = expandBraces(glob);
2622
+ if (alternatives === null) return true;
2623
+ return alternatives.some((alternative) => {
2624
+ const last = alternative.split("/").at(-1) ?? "";
2625
+ const dot = last.lastIndexOf(".");
2626
+ if (dot === -1) return true;
2627
+ const extension = last.slice(dot + 1);
2628
+ return /[*?[]/.test(extension) || /^[cm]?[jt]sx?$/.test(extension);
2629
+ });
2630
+ }
2631
+ /** Every alternative a glob's `{a,b}` groups spell, nested groups included;
2632
+ * null when its braces do not balance. */
2633
+ function expandBraces(glob) {
2634
+ const open = glob.indexOf("{");
2635
+ if (open === -1) return glob.includes("}") ? null : [glob];
2636
+ let depth = 0;
2637
+ const commas = [];
2638
+ for (let at = open; at < glob.length; at++) if (glob[at] === "{") depth++;
2639
+ else if (glob[at] === "," && depth === 1) commas.push(at);
2640
+ else if (glob[at] === "}" && --depth === 0) {
2641
+ const bounds = [
2642
+ open,
2643
+ ...commas,
2644
+ at
2645
+ ];
2646
+ const rest = expandBraces(glob.slice(at + 1));
2647
+ if (rest === null) return null;
2648
+ const expanded = [];
2649
+ for (let i = 0; i < bounds.length - 1; i++) {
2650
+ const inner = expandBraces(glob.slice(bounds[i] + 1, bounds[i + 1]));
2651
+ if (inner === null) return null;
2652
+ for (const middle of inner) for (const tail of rest) expanded.push(glob.slice(0, open) + middle + tail);
2653
+ }
2654
+ return expanded;
2655
+ }
2656
+ return null;
2657
+ }
2658
+ /**
2659
+ * True when a source module of the package that owns `absFile` must stay
2660
+ * side-effectful: its `sideEffects` list names shipped code, and no proven
2661
+ * map takes a shipped file to its source module, so a bundler that reads
2662
+ * the list against the source path can drop a listed effect. Undefined
2663
+ * leaves the bundler's own reading, which no list naming code can mislead.
2664
+ */
2665
+ function kitSourceModuleSideEffects(absFile) {
2666
+ const manifest = readPackageManifest(findPackageRoot(absFile));
2667
+ const field = isJsonBlock(manifest) ? manifest.sideEffects : void 0;
2668
+ if (!Array.isArray(field)) return void 0;
2669
+ return field.some((glob) => isJsonString(glob) && globNamesCode(glob)) ? true : void 0;
2670
+ }
2671
+ /** Whether a host keeps the module at `file` side-effectful: it lies under
2672
+ * one of the discovered kit source directories, and its package's list
2673
+ * could misread it (see `kitSourceModuleSideEffects`). A host asks this of
2674
+ * the resolved module, never of its importer alone. */
2675
+ function keepsKitSourceEffects(file, kitDirs) {
2676
+ return kitDirs.some((dir) => isPathWithinRoot(dir, file)) && kitSourceModuleSideEffects(file) === true;
2677
+ }
2352
2678
  function matchesSideEffects(globs, pkgRoot, absFiles) {
2353
2679
  return absFiles.some((file) => {
2354
- const relPath = relative(pkgRoot, file).split(sep).join("/");
2680
+ const relPath = relative$1(pkgRoot, file).split(sep$1).join("/");
2355
2681
  return globs.some((glob) => glob.test(relPath));
2356
2682
  });
2357
2683
  }
@@ -2372,20 +2698,11 @@ function exportTarget(value) {
2372
2698
  /** Each exact `exports` entry of the package at `pkgRoot`, as its subpath
2373
2699
  * and absolute target; `*` patterns name no single file and are skipped. */
2374
2700
  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
2701
  const entries = [];
2385
- for (const [subpath, value] of Object.entries(subpaths)) {
2386
- if (!subpath.startsWith(".") || subpath.includes("*")) continue;
2702
+ for (const [subpath, value] of exportsSubpaths(readPackageManifest(pkgRoot))) {
2703
+ if (subpath.includes("*")) continue;
2387
2704
  const target = exportTarget(value);
2388
- if (target !== null) entries.push([subpath, resolve(pkgRoot, target)]);
2705
+ if (target !== null) entries.push([subpath, resolve$1(pkgRoot, target)]);
2389
2706
  }
2390
2707
  return entries;
2391
2708
  }
@@ -2422,6 +2739,16 @@ async function collectExternalPackageSources(opts) {
2422
2739
  const sourceEntrySideEffects = /* @__PURE__ */ new Map();
2423
2740
  /** `replaced` names the entry the redirect stands in for; it is only
2424
2741
  * needed, and so only resolved, for a glob list. */
2742
+ /** The entry `subpath` of the package resolves to without the redirect.
2743
+ * A resolver with no `import` condition, as Node's `require` has none,
2744
+ * finds no ESM-only entry, so the manifest's own target answers then. */
2745
+ const shippedEntry = async (specifier, pkgRoot, subpath) => {
2746
+ try {
2747
+ const resolved = await resolveSpecifier(specifier);
2748
+ if (resolved) return resolved;
2749
+ } catch {}
2750
+ return packageExportEntries(pkgRoot).find(([entry]) => entry === subpath)?.[1] ?? null;
2751
+ };
2425
2752
  const redirect = async (specifier, srcEntry, pkgRoot, replaced) => {
2426
2753
  sourceEntries.set(specifier, srcEntry);
2427
2754
  const field = readPackageSideEffects(pkgRoot);
@@ -2434,6 +2761,8 @@ async function collectExternalPackageSources(opts) {
2434
2761
  sourceEntrySideEffects.set(specifier, replacedEntry === null || matchesSideEffects(field, pkgRoot, [srcEntry, replacedEntry]));
2435
2762
  };
2436
2763
  const packageDirs = [];
2764
+ const linkedDirs = [];
2765
+ const outputDirs = [];
2437
2766
  const dirOwnerSets = {};
2438
2767
  const dirExtensions = {};
2439
2768
  const fileOwners = {};
@@ -2442,6 +2771,31 @@ async function collectExternalPackageSources(opts) {
2442
2771
  (dirOwnerSets[dir] ??= []).push(specifier);
2443
2772
  };
2444
2773
  const alreadyIngested = (relPath) => hasEntry(relPath) || pushed.has(relPath);
2774
+ /** Adds `file` to the analysis set unless it is there; false when it
2775
+ * cannot be read. */
2776
+ const ingest = (file, specifier) => {
2777
+ const relPath = relative$1(rootDir, file);
2778
+ if (alreadyIngested(relPath)) return true;
2779
+ let source;
2780
+ try {
2781
+ source = readFileSync(file, "utf-8");
2782
+ } catch (err) {
2783
+ onUnreadable(relPath, err);
2784
+ return false;
2785
+ }
2786
+ onSourceRead?.(source, relPath, file);
2787
+ entries.push({
2788
+ path: relPath,
2789
+ source
2790
+ });
2791
+ pushed.add(relPath);
2792
+ fileOwners[relPath] ??= specifier;
2793
+ return true;
2794
+ };
2795
+ const diagnostics = [];
2796
+ const reportedPackages = /* @__PURE__ */ new Set();
2797
+ const kitDescriptors = [];
2798
+ const describedRoots = /* @__PURE__ */ new Set();
2445
2799
  for (const specifier of specifiers) {
2446
2800
  let absEntry;
2447
2801
  try {
@@ -2449,8 +2803,15 @@ async function collectExternalPackageSources(opts) {
2449
2803
  } catch {
2450
2804
  absEntry = null;
2451
2805
  }
2452
- if (!absEntry && isAbsolute(specifier)) absEntry = resolveAbsolutePathSpecifier(specifier, extensionsSet);
2453
- if (!absEntry) {
2806
+ if (!absEntry && isAbsolute$1(specifier)) absEntry = resolveAbsolutePathSpecifier(specifier, extensionsSet);
2807
+ const packageName = isAbsolute$1(specifier) ? null : bareSpecifierPackageName(specifier);
2808
+ const resolvedRoot = absEntry ? findPackageRoot(absEntry) : null;
2809
+ const locatedRoot = packageName && locatePackageRoot(packageName, rootDir);
2810
+ const pkgRoot = resolvedRoot && (!locatedRoot || isPackageNamed(resolvedRoot, packageName) || realPath(resolvedRoot) === locatedRoot) ? resolvedRoot : locatedRoot || resolvedRoot;
2811
+ const condition = packageName && pkgRoot ? readKitSourceCondition(pkgRoot) ?? sourceExportsCondition(pkgRoot) : null;
2812
+ const entryKey = packageName && `.${specifier.slice(packageName.length)}`;
2813
+ absEntry ??= condition?.entries.find(([entry]) => entry === entryKey)?.[1] ?? null;
2814
+ if (!absEntry || !pkgRoot) {
2454
2815
  outcomes.push({
2455
2816
  specifier,
2456
2817
  outcome: "unresolvable",
@@ -2458,106 +2819,82 @@ async function collectExternalPackageSources(opts) {
2458
2819
  });
2459
2820
  continue;
2460
2821
  }
2461
- const pkgRoot = findPackageRoot(absEntry);
2822
+ const realRoot = realPath(pkgRoot);
2823
+ if (!describedRoots.has(realRoot)) {
2824
+ describedRoots.add(realRoot);
2825
+ const described = readKitDescriptor(pkgRoot, rootDir);
2826
+ if (described) kitDescriptors.push(described);
2827
+ }
2828
+ const linked = !isInstalledPackage(pkgRoot);
2462
2829
  const srcDir = join$1(pkgRoot, "src");
2463
2830
  let fileCount = 0;
2464
2831
  let staleDist = false;
2465
- if (existsSync(srcDir)) {
2832
+ if (packageName && !reportedPackages.has(packageName)) {
2833
+ reportedPackages.add(packageName);
2834
+ diagnostics.push(...sourceConditionDiagnostics(packageName, condition));
2835
+ }
2836
+ if (condition && packageName) {
2837
+ for (const [entry, target] of condition.entries) {
2838
+ const entrySpecifier = packageName + entry.slice(1);
2839
+ packageMap[entrySpecifier] = relative$1(rootDir, target);
2840
+ await redirect(entrySpecifier, target, pkgRoot, () => shippedEntry(entrySpecifier, pkgRoot, entry));
2841
+ }
2842
+ packageMap[specifier] ??= relative$1(rootDir, absEntry);
2843
+ if (condition.root) {
2844
+ packageDirs.push(condition.root);
2845
+ if (linked) linkedDirs.push(condition.root);
2846
+ claimDir(condition.root, specifier);
2847
+ dirExtensions[condition.root] = [...extensionsSet];
2848
+ onPackageResolved?.(specifier, condition.root);
2849
+ for (const file of walkPackageSources(condition.root, extensionsSet)) if (ingest(file, specifier)) fileCount++;
2850
+ }
2851
+ } else if (existsSync(srcDir)) {
2466
2852
  packageDirs.push(srcDir);
2853
+ if (linked) linkedDirs.push(srcDir);
2467
2854
  claimDir(srcDir, specifier);
2468
2855
  dirExtensions[srcDir] = [...extensionsSet];
2469
2856
  onPackageResolved?.(specifier, srcDir);
2470
2857
  const srcEntry = sourceEntryForSpecifier(specifier, srcDir, extensionsSet);
2471
2858
  if (srcEntry) {
2472
- packageMap[specifier] = relative(rootDir, srcEntry);
2859
+ packageMap[specifier] = relative$1(rootDir, srcEntry);
2473
2860
  const replaced = absEntry;
2474
2861
  await redirect(specifier, srcEntry, pkgRoot, async () => replaced);
2475
- } else packageMap[specifier] = relative(rootDir, absEntry);
2476
- if (!isAbsolute(specifier)) {
2477
- const packageName = bareSpecifierPackageName(specifier);
2862
+ } else packageMap[specifier] = relative$1(rootDir, absEntry);
2863
+ if (packageName) {
2478
2864
  if (packageName !== specifier && !(packageName in packageMap)) {
2479
2865
  const rootEntry = sourceEntryForSpecifier(packageName, srcDir, extensionsSet);
2480
2866
  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
- });
2867
+ packageMap[packageName] = relative$1(rootDir, rootEntry);
2868
+ await redirect(packageName, rootEntry, pkgRoot, () => shippedEntry(packageName, pkgRoot, "."));
2489
2869
  }
2490
2870
  }
2491
2871
  }
2492
2872
  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
- }
2873
+ staleDist = linked && distEntryIsStale(absEntry, srcDir, pkgFiles);
2874
+ for (const pkgFile of pkgFiles) if (ingest(pkgFile, specifier)) fileCount++;
2516
2875
  } else {
2517
2876
  const outputDir = dirname$1(absEntry);
2518
2877
  packageDirs.push(outputDir);
2878
+ if (linked) linkedDirs.push(outputDir);
2879
+ outputDirs.push(outputDir);
2519
2880
  claimDir(outputDir, specifier);
2520
2881
  onPackageResolved?.(specifier, outputDir);
2521
- packageMap[specifier] = relative(rootDir, absEntry);
2882
+ packageMap[specifier] = relative$1(rootDir, absEntry);
2522
2883
  const outputExtensions = new Set(extensionsSet);
2523
- outputExtensions.add(extname(absEntry));
2884
+ outputExtensions.add(extname$1(absEntry));
2524
2885
  dirExtensions[outputDir] = [...outputExtensions];
2525
2886
  const outputFiles = discoverFiles(outputDir, outputDir, void 0, outputExtensions).filter((file) => {
2526
- const relToOutput = relative(outputDir, file);
2887
+ const relToOutput = relative$1(outputDir, file);
2527
2888
  return !PACKAGE_OUTPUT_EXCLUDES.some((pattern) => relToOutput.includes(pattern));
2528
2889
  });
2529
2890
  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
- }
2891
+ for (const outputFile of outputFiles) if (ingest(outputFile, specifier)) fileCount++;
2552
2892
  }
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
- }
2893
+ if (packageName) for (const [subpath, target] of packageExportEntries(pkgRoot)) {
2894
+ const entrySpecifier = packageName + subpath.slice(1);
2895
+ const targetRelPath = relative$1(rootDir, target);
2896
+ if (entrySpecifier in packageMap || !alreadyIngested(targetRelPath)) continue;
2897
+ packageMap[entrySpecifier] = targetRelPath;
2561
2898
  }
2562
2899
  outcomes.push({
2563
2900
  specifier,
@@ -2571,12 +2908,112 @@ async function collectExternalPackageSources(opts) {
2571
2908
  sourceEntries,
2572
2909
  sourceEntrySideEffects,
2573
2910
  packageDirs,
2911
+ linkedDirs,
2912
+ outputDirs,
2574
2913
  dirOwnerSets,
2575
2914
  dirExtensions,
2576
2915
  fileOwners,
2577
- outcomes
2916
+ outcomes,
2917
+ diagnostics: [...diagnostics, ...noKitFilesDiagnostics(outcomes)],
2918
+ kitDescriptors
2578
2919
  };
2579
2920
  }
2921
+ /** The dependency names a manifest lists in `fields`. */
2922
+ function dependencyNames(manifest, fields) {
2923
+ if (!isJsonBlock(manifest)) return [];
2924
+ const names = /* @__PURE__ */ new Set();
2925
+ for (const field of fields) {
2926
+ const deps = manifest[field];
2927
+ if (isJsonBlock(deps)) for (const name of Object.keys(deps)) names.add(name);
2928
+ }
2929
+ return [...names];
2930
+ }
2931
+ /** The source kits the application at `rootDir` declares as dependencies.
2932
+ * A bundler serves an installed one as compiled code unless told
2933
+ * otherwise: Next keeps it external on the server unless it is in
2934
+ * `transpilePackages`, and Vite's optimizer prebundles it. */
2935
+ function sourceKitDependencies(rootDir) {
2936
+ return dependencyNames(readPackageManifest(rootDir), ["dependencies", "devDependencies"]).flatMap((name) => {
2937
+ const pkgRoot = locatePackageRoot(name, rootDir);
2938
+ if (pkgRoot === null || readKitSourceCondition(pkgRoot) === null) return [];
2939
+ return [{
2940
+ name,
2941
+ installed: isInstalledPackage(pkgRoot),
2942
+ dependencies: dependencyNames(readPackageManifest(pkgRoot), ["dependencies"])
2943
+ }];
2944
+ });
2945
+ }
2946
+ /** A specifier that names a package: not relative or absolute, and no URL,
2947
+ * scheme (`node:`, `virtual:`), subpath import or virtual id. */
2948
+ function isPackageSpecifier(specifier) {
2949
+ return /^(?:@[^/\\:]+\/)?[^./\\#\0:][^:]*$/.test(specifier);
2950
+ }
2951
+ /**
2952
+ * An error for each kit the application's own `files` import or re-export
2953
+ * whose system the application's system does not include: a package that
2954
+ * declares the kit source condition, with no kit the system extends
2955
+ * (`systemKits`) in that package. One app build has exactly one system, and
2956
+ * every kit's system is part of it, so such a kit is not extracted against
2957
+ * a system it was not built for. One batch parse reads the imports of every
2958
+ * file the engine parses as it is; an adapted source (`.svelte`, `.mdx`)
2959
+ * reaches the engine only as its generated children.
2960
+ */
2961
+ function importedKitDiagnostics(files, engine, rootDir, systemKits) {
2962
+ const { extractFacts } = engine;
2963
+ const parsed = files.filter(({ path }) => isEngineTransformExtension(path));
2964
+ if (!extractFacts || parsed.length === 0) return [];
2965
+ let facts;
2966
+ try {
2967
+ facts = parseInternalWire(extractFacts(JSON.stringify(parsed.map(({ path, source }) => ({
2968
+ path,
2969
+ source
2970
+ })))), "extractFacts");
2971
+ } catch {
2972
+ return [];
2973
+ }
2974
+ const seen = new Set(systemKits.filter((specifier) => !isAbsolute$1(specifier)).map(bareSpecifierPackageName));
2975
+ const diagnostics = [];
2976
+ for (const [path, file] of Object.entries(facts.files)) {
2977
+ if (file.parsePanicked) continue;
2978
+ const specifiers = [...file.imports.map((fact) => fact.source), ...file.exports.flatMap((fact) => fact.source === null ? [] : [fact.source])];
2979
+ for (const specifier of specifiers) {
2980
+ if (!isPackageSpecifier(specifier)) continue;
2981
+ const name = bareSpecifierPackageName(specifier);
2982
+ if (seen.has(name)) continue;
2983
+ seen.add(name);
2984
+ const pkgRoot = locatePackageRoot(name, dirname$1(resolve$1(rootDir, path)));
2985
+ if (pkgRoot && readKitSourceCondition(pkgRoot)) diagnostics.push({
2986
+ file: path,
2987
+ component: name,
2988
+ kind: "warn",
2989
+ 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>)`,
2990
+ code: KIT_SYSTEM_NOT_INCLUDED,
2991
+ severity: severityFor(KIT_SYSTEM_NOT_INCLUDED)
2992
+ });
2993
+ }
2994
+ }
2995
+ return diagnostics;
2996
+ }
2997
+ /** A kit without the source condition, warned once, or each condition entry
2998
+ * whose target is missing or outside the package. */
2999
+ function sourceConditionDiagnostics(packageName, condition) {
3000
+ if (condition === null) return [{
3001
+ file: packageName,
3002
+ component: "kit",
3003
+ kind: "warn",
3004
+ 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`,
3005
+ code: KIT_WITHOUT_SOURCE_CONDITION,
3006
+ severity: severityFor(KIT_WITHOUT_SOURCE_CONDITION)
3007
+ }];
3008
+ return condition.invalid.map(([subpath, target]) => ({
3009
+ file: packageName,
3010
+ component: "kit",
3011
+ kind: "warn",
3012
+ message: `exports["${subpath}"].${KIT_SOURCE_CONDITION} names ${target}, which is missing or outside the package, so that entry is not read from source`,
3013
+ code: INVALID_KIT_SOURCE_CONDITION,
3014
+ severity: severityFor(INVALID_KIT_SOURCE_CONDITION)
3015
+ }));
3016
+ }
2580
3017
  function firstOwners(dirOwnerSets) {
2581
3018
  const owners = {};
2582
3019
  for (const [dir, specifiers] of Object.entries(dirOwnerSets)) if (specifiers.length > 0) owners[dir] = specifiers[0];
@@ -2589,7 +3026,7 @@ function excludeCollectedPackages(collected, rejectedSpecifiers, rootDir) {
2589
3026
  const targetRejected = (specifier, absTarget) => rejectedSpecifiers.has(specifier) || underRejectedDir(absTarget);
2590
3027
  const packageMap = {};
2591
3028
  for (const [specifier, relTarget] of Object.entries(collected.packageMap)) {
2592
- if (targetRejected(specifier, resolve(rootDir, relTarget))) continue;
3029
+ if (targetRejected(specifier, resolve$1(rootDir, relTarget))) continue;
2593
3030
  packageMap[specifier] = relTarget;
2594
3031
  }
2595
3032
  const sourceEntries = /* @__PURE__ */ new Map();
@@ -2622,10 +3059,14 @@ function excludeCollectedPackages(collected, rejectedSpecifiers, rootDir) {
2622
3059
  sourceEntries,
2623
3060
  sourceEntrySideEffects,
2624
3061
  packageDirs: collected.packageDirs.filter((dir) => !rejectedDirs.includes(dir)),
3062
+ linkedDirs: collected.linkedDirs.filter((dir) => !rejectedDirs.includes(dir)),
3063
+ outputDirs: collected.outputDirs.filter((dir) => !rejectedDirs.includes(dir)),
2625
3064
  dirOwnerSets,
2626
3065
  dirExtensions,
2627
3066
  fileOwners,
2628
- outcomes: collected.outcomes
3067
+ outcomes: collected.outcomes,
3068
+ diagnostics: collected.diagnostics,
3069
+ kitDescriptors: collected.kitDescriptors.filter((record) => !rejectedDirs.some((dir) => isPathWithinRoot(resolve$1(rootDir, record.packageRoot), dir)))
2629
3070
  };
2630
3071
  }
2631
3072
  function unresolvableIncludesMessage(outcomes) {
@@ -2654,7 +3095,8 @@ function engineModuleParser(engine) {
2654
3095
  }])), "extractFacts").files[path];
2655
3096
  return facts && !facts.parsePanicked ? {
2656
3097
  imports: facts.imports,
2657
- exports: facts.exports
3098
+ exports: facts.exports,
3099
+ unboundCreateSystemCalls: facts.unboundCreateSystemCalls ?? []
2658
3100
  } : null;
2659
3101
  } catch {
2660
3102
  return null;
@@ -2665,7 +3107,7 @@ const ANIMUS_SYSTEM_SPECIFIER = /^@animus-ui\/system(?:\/.*)?$/;
2665
3107
  /** The file a specifier names from `importer`: a relative one by the
2666
3108
  * ingestion's probe order, a bare one by the host's package resolution. */
2667
3109
  async function resolveModuleFile(importer, specifier, resolvePackage) {
2668
- if (specifier.startsWith(".")) return relativeSourceCandidates(importer, specifier).find(isFile) ?? null;
3110
+ if (specifier.startsWith(".")) return relativeSourceCandidates(importer, specifier).find(isFile$1) ?? null;
2669
3111
  try {
2670
3112
  return await resolvePackage?.(specifier) ?? null;
2671
3113
  } catch {
@@ -2750,13 +3192,15 @@ const NAMESPACE_IMPORT = /\bimport\s+(?:[a-zA-Z_$][a-zA-Z0-9_$]*\s*,\s*)?\*\s*as
2750
3192
  * `import()` of a module. A binding named `createSystem` shown to be
2751
3193
  * something else is no root. One whose identity discovery cannot follow
2752
3194
  * 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.
3195
+ * kit. Both are reported. A call of the bare name, which the file neither
3196
+ * imports nor declares, is no root: the system loader evaluates the file
3197
+ * without auto-imports, where the name is undefined. It is reported once.
2755
3198
  */
2756
- async function systemRoots(systemFilePath, source, imports, following) {
3199
+ async function systemRoots(systemFilePath, source, record, following) {
3200
+ const { imports } = record;
2757
3201
  const roots = /* @__PURE__ */ new Set();
2758
3202
  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);
3203
+ const called = (callee) => callOf(callee).test(source);
2760
3204
  /** Admits a binding named `createSystem` by its identity: an unknown one
2761
3205
  * keeps `spellingAdmits`, and every unproven one is reported. */
2762
3206
  const admit = (local, offset, identity, spellingAdmits) => {
@@ -2776,11 +3220,8 @@ async function systemRoots(systemFilePath, source, imports, following) {
2776
3220
  ...locationIn(source, offset)
2777
3221
  });
2778
3222
  };
2779
- let bindsName = false;
2780
3223
  for (const binding of imports) {
2781
- const named = binding.imported === "createSystem" || binding.local === "createSystem";
2782
- if (binding.local === "createSystem") bindsName = true;
2783
- if (named) {
3224
+ if (binding.imported === "createSystem" || binding.local === "createSystem") {
2784
3225
  const statement = new RegExp(`\\bimport\\b[^;]*?\\bfrom\\s*['"]${escapeRegExp$1(binding.source)}['"]`, "g");
2785
3226
  let offset = 0;
2786
3227
  for (const match of source.matchAll(statement)) {
@@ -2811,19 +3252,47 @@ async function systemRoots(systemFilePath, source, imports, following) {
2811
3252
  why: `it is destructured from '${initializer}', which is not a module namespace`
2812
3253
  });
2813
3254
  };
3255
+ for (const { local, offset, initializer } of destructuredCreateSystems(source)) admit(local, offset, await destructuredFrom(initializer), local === "createSystem");
3256
+ const unimported = unimportedCreateSystemCall(systemFilePath, record);
3257
+ if (unimported) following.report?.(unimported);
3258
+ return roots;
3259
+ }
3260
+ /** A call of `callee` as a whole name, not a member. */
3261
+ function callOf(callee) {
3262
+ return new RegExp(`(?<![a-zA-Z0-9_$.])${escapeRegExp$1(callee)}\\s*\\(`);
3263
+ }
3264
+ /** Each `createSystem` property a declaration destructures: its local name,
3265
+ * its offset in `source`, and the destructured initializer. */
3266
+ function* destructuredCreateSystems(source) {
2814
3267
  for (const match of source.matchAll(/\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*([^;\n]+)/g)) {
2815
3268
  const [whole, pattern, initializer] = match;
2816
3269
  for (const property of pattern.split(",")) {
2817
3270
  const binding = /^\s*createSystem\s*(?::\s*([a-zA-Z_$][a-zA-Z0-9_$]*))?\s*(?:=[\s\S]*)?$/.exec(property);
2818
3271
  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");
3272
+ yield {
3273
+ local: binding[1] ?? "createSystem",
3274
+ offset: match.index + whole.indexOf("createSystem"),
3275
+ initializer: initializer.trim()
3276
+ };
2822
3277
  }
2823
3278
  }
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;
3279
+ }
3280
+ /** The warning for a `createSystem` call that the parser's scopes leave
3281
+ * unbound: no import, declaration or parameter names it. Null when there is
3282
+ * none, or when the parser reports no scopes. */
3283
+ function unimportedCreateSystemCall(systemFilePath, record) {
3284
+ const call = record.unboundCreateSystemCalls?.[0];
3285
+ if (!call) return null;
3286
+ return {
3287
+ file: systemFilePath,
3288
+ component: "createSystem",
3289
+ kind: "warn",
3290
+ 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'`,
3291
+ code: UNIMPORTED_CREATE_SYSTEM,
3292
+ severity: severityFor(UNIMPORTED_CREATE_SYSTEM),
3293
+ line: call[0],
3294
+ column: call[1]
3295
+ };
2827
3296
  }
2828
3297
  /** A pattern matching a call of any of `callees` as a whole name, or null
2829
3298
  * when there is none to anchor on. */
@@ -2839,9 +3308,8 @@ async function extractSystemFilePackages(systemFilePath, parseModule, report, re
2839
3308
  return [];
2840
3309
  }
2841
3310
  const parsed = parseModule?.(source, systemFilePath) ?? null;
2842
- const parsedImports = parsed && parsed.imports.length > 0 ? parsed.imports : null;
2843
3311
  let rootCall = "createSystem";
2844
- if (parseModule && parsedImports) rootCall = rootCallPattern([...await systemRoots(systemFilePath, source, parsedImports, {
3312
+ if (parseModule && parsed) rootCall = rootCallPattern([...await systemRoots(systemFilePath, source, parsed, {
2845
3313
  parseModule,
2846
3314
  resolvePackage,
2847
3315
  report
@@ -3013,9 +3481,9 @@ async function extractSystemFilePackages(systemFilePath, parseModule, report, re
3013
3481
  }
3014
3482
  if (identifiers.size === 0) return [];
3015
3483
  const importMap = /* @__PURE__ */ new Map();
3016
- for (const binding of parsedImports ?? []) importMap.set(binding.local, binding.source);
3484
+ for (const binding of parsed?.imports ?? []) importMap.set(binding.local, binding.source);
3017
3485
  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) {
3486
+ if (!parsed) {
3019
3487
  let importMatch;
3020
3488
  while ((importMatch = importRegex.exec(source)) !== null) {
3021
3489
  const [, comboDefault, namedImports, defaultImport, specifier] = importMatch;
@@ -3045,7 +3513,7 @@ async function extractSystemFilePackages(systemFilePath, parseModule, report, re
3045
3513
  for (const id of identifiers) {
3046
3514
  const specifier = importMap.get(throughAliases(id));
3047
3515
  if (!specifier) continue;
3048
- if (specifier.startsWith(".")) packages.add(resolve(systemFileDir, specifier));
3516
+ if (specifier.startsWith(".")) packages.add(resolve$1(systemFileDir, specifier));
3049
3517
  else packages.add(specifier);
3050
3518
  }
3051
3519
  return Array.from(packages);
@@ -3148,7 +3616,7 @@ function resolveThroughPathAliases(specifier, rootDir, pathAliasesJson) {
3148
3616
  if (alias.pattern === specifier) mapped = alias.replacement;
3149
3617
  } else if (specifier.startsWith(alias.pattern)) mapped = alias.replacement + specifier.slice(alias.pattern.length);
3150
3618
  if (mapped === null) continue;
3151
- const absolute = isAbsolute(mapped) ? mapped : join$1(rootDir, mapped);
3619
+ const absolute = isAbsolute$1(mapped) ? mapped : join$1(rootDir, mapped);
3152
3620
  if (existsSync(absolute)) return absolute;
3153
3621
  }
3154
3622
  return null;
@@ -3267,8 +3735,13 @@ function enforceExternalTokenContracts(opts) {
3267
3735
  sourceTokens
3268
3736
  });
3269
3737
  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);
3738
+ if (!opts.strict) {
3739
+ for (const message of messages) opts.warn(message);
3740
+ return;
3741
+ }
3742
+ const message = `${opts.prefix} ${messages.join("\n")}`;
3743
+ if (!opts.reportErrors) throw new Error(message);
3744
+ opts.reportErrors(message);
3272
3745
  }
3273
3746
  //#endregion
3274
3747
  //#region pipeline/path-aliases.ts
@@ -3880,11 +4353,15 @@ function buildAnalysisInputs(opts) {
3880
4353
  externalDirsJson: opts.externalDirs?.length && hasSourceThemeManifests(opts.system) ? JSON.stringify(opts.externalDirs) : null
3881
4354
  };
3882
4355
  if (opts.system.declarationScalesJson) inputs.declarationScalesJson = opts.system.declarationScalesJson;
4356
+ if (opts.system.generatedNamesJson) inputs.generatedNamesJson = opts.system.generatedNamesJson;
4357
+ if (opts.system.propertyRecordsJson) inputs.propertyRecordsJson = opts.system.propertyRecordsJson;
3883
4358
  const context = opts.analysisContext;
3884
4359
  if (context?.skippedSources?.length || context?.unbundledComputedImports || context?.packageDirs?.length) inputs.analysisContextJson = JSON.stringify({
3885
4360
  skippedSources: context.skippedSources ?? [],
3886
4361
  unbundledComputedImports: context.unbundledComputedImports ?? false,
3887
- packageDirs: context.packageDirs ?? []
4362
+ packageDirs: context.packageDirs ?? [],
4363
+ linkedDirs: context.linkedDirs ?? [],
4364
+ outputDirs: context.outputDirs ?? []
3888
4365
  });
3889
4366
  return inputs;
3890
4367
  }
@@ -3925,7 +4402,12 @@ function runProjectAnalysis(engineApi, opts) {
3925
4402
  t = performance.now();
3926
4403
  const manifest = JSON.parse(manifestJson);
3927
4404
  const systemErrors = systemLoadDiagnostics(opts.system).filter((diagnostic) => diagnostic.kind === "error");
3928
- if (systemErrors.length > 0) manifest.diagnostics = [...systemErrors, ...manifest.diagnostics ?? []];
4405
+ const kitDiagnostics = kitDescriptorDiagnostics(opts.kitDescriptors ?? [], manifest);
4406
+ if (systemErrors.length > 0 || kitDiagnostics.length > 0) manifest.diagnostics = [
4407
+ ...systemErrors,
4408
+ ...kitDiagnostics,
4409
+ ...manifest.diagnostics ?? []
4410
+ ];
3929
4411
  const componentCss = applyUnitFallback(manifest.css);
3930
4412
  const propertyDiagnostics = checkCustomProperties({
3931
4413
  system: opts.system,
@@ -3936,6 +4418,7 @@ function runProjectAnalysis(engineApi, opts) {
3936
4418
  surfaceManifestDiagnostics(manifest, opts.warn, {
3937
4419
  strict: opts.strict,
3938
4420
  info: opts.info,
4421
+ reportErrors: opts.reportErrors,
3939
4422
  levels: opts.diagnostics,
3940
4423
  knownCodes: opts.diagnostics ? knownDiagnosticCodes(diagnosticCodes?.()) : void 0,
3941
4424
  prepend: [
@@ -4043,36 +4526,34 @@ function renameCustomProperties(css, names) {
4043
4526
  }
4044
4527
  //#endregion
4045
4528
  //#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) {
4529
+ /**
4530
+ * The prefix without `prefixContextualVars`: every name Animus generates (a
4531
+ * variable the theme's map or variable CSS defines) takes `--${prefix}-`
4532
+ * wherever it is defined, registered or read, `var()` fallbacks at any depth
4533
+ * included. Every other name stays as written: each declared contextual
4534
+ * variable, and any custom property an author writes.
4535
+ */
4536
+ function applyPrefix(prefix, variableMapJson, variableCss, themeJson, contextualVarsJson, declarationScalesJson) {
4052
4537
  if (!prefix) return {
4053
4538
  variableMapJson,
4054
4539
  variableCss,
4055
4540
  themeJson,
4056
- contextualVarsJson
4541
+ contextualVarsJson,
4542
+ declarationScalesJson
4057
4543
  };
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`);
4544
+ const contextual = new Set(contextualVarsJson ? Object.values(parseInternalWire(contextualVarsJson, "contextualVarsJson (the theme's contextual variable names)")).flat() : []);
4545
+ const variableMap = parseInternalWire(variableMapJson, "variableMapJson (the theme's token variables)");
4546
+ const generated = [...Object.values(variableMap).map((name) => name.replace(/^--/, "")), ...themeDefinitions(variableCss)].filter((name) => !contextual.has(name));
4547
+ const names = createPropertyNames([], prefix, generated);
4548
+ const rename = (value) => renameCustomProperties(value, names);
4065
4549
  const result = {
4066
- variableMapJson: JSON.stringify(prefixed),
4067
- variableCss: css
4550
+ variableMapJson: JSON.stringify(Object.fromEntries(Object.entries(variableMap).map(([key, name]) => [key, rename(name)]))),
4551
+ variableCss: rename(variableCss)
4068
4552
  };
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
- }
4553
+ if (themeJson) result.themeJson = renameTokenValues(themeJson, rename);
4554
+ if (contextualVarsJson) result.contextualVarsJson = contextualVarsJson;
4555
+ if (generated.length > 0) result.generatedNamesJson = JSON.stringify(Object.fromEntries(generated.map((name) => [name, `${prefix}-${name}`])));
4556
+ if (declarationScalesJson) result.declarationScalesJson = renameDeclarationRecords(declarationScalesJson, rename);
4076
4557
  return result;
4077
4558
  }
4078
4559
  /** The runtime's transport variables are `--animus-<prop>`. */
@@ -4088,7 +4569,8 @@ function applyPropertyNames(prefix, artifacts) {
4088
4569
  const byScale = artifacts.contextualVarsJson ? parseInternalWire(artifacts.contextualVarsJson, "contextualVarsJson (the theme's contextual variable names)") : null;
4089
4570
  const declared = Object.values(byScale ?? {}).flat();
4090
4571
  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])]);
4572
+ const themeDefined = [...Object.values(variableMap).map((name) => name.replace(/^--/, "")), ...themeDefinitions(artifacts.variableCss)];
4573
+ const managed = createPropertyNames(declared, prefix, themeDefined);
4092
4574
  const nameConflicts = [...[...new Set(declared)].flatMap((name) => {
4093
4575
  const final = managed.finalName(name) ?? name;
4094
4576
  return final.startsWith(TRANSPORT_NAMESPACE) ? [{
@@ -4112,11 +4594,30 @@ function applyPropertyNames(prefix, artifacts) {
4112
4594
  }))]))),
4113
4595
  declarationScalesJson: artifacts.declarationScalesJson === null ? null : renameDeclarationRecords(artifacts.declarationScalesJson, rename),
4114
4596
  nameConflicts,
4115
- contextualProperties: [...new Set(declared)].map((name) => `--${managed.finalName(name) ?? name}`)
4597
+ contextualProperties: [...new Set(declared)].map((name) => `--${managed.finalName(name) ?? name}`),
4598
+ generatedNamesJson: generatedNamesJson(themeDefined.filter((name) => !declared.includes(name)), managed)
4116
4599
  };
4117
4600
  }
4118
- /** A custom property the theme's CSS defines or registers. */
4119
- const THEME_DEFINITION = /(?:@property\s+|(?:^|[\s;{]))--([\w-]+)(?=\s*[:{])/g;
4601
+ /** The generated names' final names, for authored component styles. */
4602
+ function generatedNamesJson(names, managed) {
4603
+ const entries = [...new Set(names)].flatMap((name) => {
4604
+ const final = managed.finalName(name);
4605
+ return final === void 0 ? [] : [[name, final]];
4606
+ });
4607
+ return entries.length === 0 ? null : JSON.stringify(Object.fromEntries(entries));
4608
+ }
4609
+ /** The custom properties the theme's CSS declares or `@property` registers,
4610
+ * read as CSS tokenizes it: a name in a string or comment defines nothing. */
4611
+ function themeDefinitions(variableCss) {
4612
+ const tokens = tokenize(variableCss).filter((token) => token.type !== "whitespace");
4613
+ return tokens.flatMap((token, index) => {
4614
+ if (token.type !== "ident" || !token.value.startsWith("--")) return [];
4615
+ const previous = tokens[index - 1];
4616
+ const declared = (previous === void 0 || previous.type === "{" || previous.type === ";") && tokens[index + 1]?.type === ":";
4617
+ const registered = previous?.type === "at-keyword" && previous.value.toLowerCase() === "property";
4618
+ return declared || registered ? [token.value.slice(2)] : [];
4619
+ });
4620
+ }
4120
4621
  /** Renames inside the token map's values. */
4121
4622
  function renameTokenValues(themeJson, rename) {
4122
4623
  const tokens = parseInternalWire(themeJson, "themeJson (the theme's flattened token values)");
@@ -4132,23 +4633,40 @@ function renameDeclarationRecords(declarationScalesJson, rename) {
4132
4633
  }
4133
4634
  //#endregion
4134
4635
  //#region pipeline/system-config.ts
4636
+ /** The loader's evaluation of the system file. A failure on a file that
4637
+ * calls `createSystem` with no binding leads with discovery's warning line
4638
+ * for it, then keeps the loader's own error. */
4639
+ function evaluateSystemModule(engine, systemPath, rootDir, conditions) {
4640
+ try {
4641
+ return engine.loadSystemModule(systemPath, rootDir, void 0, conditions);
4642
+ } catch (error) {
4643
+ let source;
4644
+ try {
4645
+ source = readFileSync(systemPath, "utf-8");
4646
+ } catch {
4647
+ throw error;
4648
+ }
4649
+ const record = engineModuleParser(engine)?.(source, systemPath);
4650
+ const call = record && unimportedCreateSystemCall(systemPath, record);
4651
+ if (!call) throw error;
4652
+ throw new Error(`${warnLine(call)}\n${String(error)}`, { cause: error });
4653
+ }
4654
+ }
4135
4655
  /**
4136
4656
  * Load and normalize a SystemInstance; `prefix` namespaces every CSS
4137
4657
  * variable name. Error handling stays at the call site.
4138
4658
  */
4139
4659
  function loadSystemConfig(engineApi, opts) {
4140
- const { loadSystemModule } = engineApi();
4141
- const config = loadSystemModule(opts.systemPath, opts.rootDir);
4660
+ const config = evaluateSystemModule(engineApi(), opts.systemPath, opts.rootDir, opts.conditions);
4142
4661
  let scalesJson = config.scalesJson;
4143
4662
  let variableMapJson = config.variableMapJson;
4144
4663
  const registrations = splitInvalidPropertyRegistrations(config.variableCss);
4145
4664
  let variableCss = registrations.css;
4146
4665
  let contextualVarsJson = config.contextualVarsJson || null;
4147
4666
  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 = [];
4667
+ let contextualProperties = Object.values(parseInternalWire(contextualVarsJson ?? "{}", "contextualVarsJson (the theme's contextual variable names)")).flat().map((name) => `--${name}`);
4151
4668
  let prefixNameConflicts = [];
4669
+ let generatedNamesJson;
4152
4670
  if (opts.prefix && opts.prefixContextualVars) {
4153
4671
  const resolved = applyPropertyNames(opts.prefix, {
4154
4672
  variableMapJson,
@@ -4164,15 +4682,14 @@ function loadSystemConfig(engineApi, opts) {
4164
4682
  contextualProperties = resolved.contextualProperties;
4165
4683
  prefixNameConflicts = resolved.nameConflicts;
4166
4684
  declarationScalesJson = resolved.declarationScalesJson;
4685
+ generatedNamesJson = resolved.generatedNamesJson;
4167
4686
  } 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);
4687
+ const prefixed = applyPrefix(opts.prefix, variableMapJson, variableCss, scalesJson, contextualVarsJson || void 0, declarationScalesJson || void 0);
4171
4688
  variableMapJson = prefixed.variableMapJson;
4172
4689
  variableCss = prefixed.variableCss;
4173
4690
  if (prefixed.themeJson) scalesJson = prefixed.themeJson;
4174
- if (prefixed.contextualVarsJson) contextualVarsJson = prefixed.contextualVarsJson;
4175
- if (declarationScalesJson) declarationScalesJson = prefixVariableReferences(opts.prefix, declarationScalesJson);
4691
+ if (prefixed.declarationScalesJson) declarationScalesJson = prefixed.declarationScalesJson;
4692
+ generatedNamesJson = prefixed.generatedNamesJson;
4176
4693
  }
4177
4694
  const system = {
4178
4695
  propConfigJson: config.propConfig,
@@ -4196,7 +4713,7 @@ function loadSystemConfig(engineApi, opts) {
4196
4713
  if (config.propertyRecordsJson) system.propertyRecordsJson = config.propertyRecordsJson;
4197
4714
  if (registrations.invalid.length > 0) system.invalidPropertyRegistrations = registrations.invalid;
4198
4715
  if (prefixNameConflicts.length > 0) system.prefixNameConflicts = prefixNameConflicts;
4199
- if (legacyPrefixedContextualVars.length > 0) system.legacyPrefixedContextualVars = [...new Set(legacyPrefixedContextualVars)];
4716
+ if (generatedNamesJson) system.generatedNamesJson = generatedNamesJson;
4200
4717
  return system;
4201
4718
  }
4202
4719
  //#endregion
@@ -4205,8 +4722,7 @@ function runStructuralSelfCheck(input) {
4205
4722
  const failures = [];
4206
4723
  if (input.componentCount === 0) failures.push("No component CSS produced — check the system file and its includes list");
4207
4724
  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`);
4725
+ for (const { specifier, outcome } of input.externalOutcomes ?? []) if (outcome === "unresolvable") failures.push(`include '${specifier}' could not be resolved`);
4210
4726
  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
4727
  if ((input.assembledCss ?? `${input.variableCss}\n${input.globalCss}\n${input.componentCss}`).includes("__TRANSFORM__")) failures.push("Unresolved __TRANSFORM__ placeholders found in CSS output");
4212
4728
  if (input.componentCount > 0 && (input.componentCss.length > 0 || input.assembledCss !== void 0)) {
@@ -4240,7 +4756,8 @@ function buildDynamicPropConfig(dynamicProps) {
4240
4756
  kind: meta.kind,
4241
4757
  slotClass: meta.slotClass,
4242
4758
  memberVars: meta.memberVars,
4243
- declarationScaleValues: meta.declarationScaleValues
4759
+ declarationScaleValues: meta.declarationScaleValues,
4760
+ ...meta.productionConditions && { productionConditions: meta.productionConditions }
4244
4761
  };
4245
4762
  continue;
4246
4763
  }
@@ -4258,6 +4775,7 @@ function buildDynamicPropConfig(dynamicProps) {
4258
4775
  if (meta.strict) entry.strict = true;
4259
4776
  if (meta.keywords?.length) entry.keywords = meta.keywords;
4260
4777
  if (meta.currentVar) entry.currentVar = meta.currentVar;
4778
+ if (meta.productionConditions) entry.productionConditions = meta.productionConditions;
4261
4779
  configEntries[propName] = entry;
4262
4780
  }
4263
4781
  return configEntries;
@@ -4296,6 +4814,191 @@ function assertNoErrorDiagnostics(diagnostics) {
4296
4814
  throw new Error(lines.join("\n"));
4297
4815
  }
4298
4816
  //#endregion
4817
+ //#region pipeline/kit-publication.ts
4818
+ /** Source a kit publishes and the loader or a bundler parses for imports. */
4819
+ const CODE_EXTENSIONS = /* @__PURE__ */ new Set([
4820
+ ".ts",
4821
+ ".tsx",
4822
+ ".mts",
4823
+ ".cts",
4824
+ ".js",
4825
+ ".jsx",
4826
+ ".mjs",
4827
+ ".cjs"
4828
+ ]);
4829
+ const isFile = (path) => {
4830
+ try {
4831
+ return statSync$1(path).isFile();
4832
+ } catch {
4833
+ return false;
4834
+ }
4835
+ };
4836
+ const posixPath = (path) => path.split(sep).join("/");
4837
+ /**
4838
+ * The package-relative files `npm pack` publishes, read with npm's own rules
4839
+ * (`files`, `.npmignore`, `.gitignore` and the files npm always includes)
4840
+ * through a dry run that runs no scripts and needs no network.
4841
+ */
4842
+ function npmPublishedFiles(pkgRoot) {
4843
+ const windows = process.platform === "win32";
4844
+ const run = spawnSync(windows ? "npm.cmd" : "npm", [
4845
+ "pack",
4846
+ "--dry-run",
4847
+ "--json",
4848
+ "--ignore-scripts"
4849
+ ], {
4850
+ cwd: pkgRoot,
4851
+ encoding: "utf-8",
4852
+ shell: windows,
4853
+ env: {
4854
+ ...process.env,
4855
+ npm_config_update_notifier: "false"
4856
+ }
4857
+ });
4858
+ if (run.error || run.status !== 0) return {
4859
+ kind: "failed",
4860
+ reason: `npm pack --dry-run could not list the published files: ${String(run.error ?? run.stderr.trim())}`
4861
+ };
4862
+ let output;
4863
+ try {
4864
+ output = JSON.parse(run.stdout);
4865
+ } catch (error) {
4866
+ return {
4867
+ kind: "failed",
4868
+ reason: `npm pack --dry-run printed no JSON: ${String(error)}`
4869
+ };
4870
+ }
4871
+ const pack = Array.isArray(output) ? output[0] : void 0;
4872
+ const files = isJsonBlock(pack) ? pack.files : void 0;
4873
+ if (!Array.isArray(files)) return {
4874
+ kind: "failed",
4875
+ reason: "npm pack --dry-run printed no file list"
4876
+ };
4877
+ return {
4878
+ kind: "listed",
4879
+ files: new Set(files.flatMap((file) => isJsonBlock(file) && isJsonString(file.path) ? [posixPath(file.path)] : []))
4880
+ };
4881
+ }
4882
+ function animusTargets(manifest) {
4883
+ const targets = [];
4884
+ const unreadable = [];
4885
+ const visit = (subpath, value, underAnimus) => {
4886
+ if (isJsonString(value)) {
4887
+ if (underAnimus) targets.push([subpath, value]);
4888
+ } else if (Array.isArray(value)) for (const entry of value) visit(subpath, entry, underAnimus);
4889
+ else if (isJsonBlock(value)) for (const [key, entry] of Object.entries(value)) visit(subpath, entry, underAnimus || key === "animus");
4890
+ else if (underAnimus && value !== null) unreadable.push([subpath, JSON.stringify(value)]);
4891
+ };
4892
+ for (const [subpath, value] of exportsSubpaths(manifest)) visit(subpath, value, false);
4893
+ return {
4894
+ targets,
4895
+ unreadable
4896
+ };
4897
+ }
4898
+ /** Every file in the package outside `node_modules` and `.git`,
4899
+ * package-relative. */
4900
+ function packageFiles(pkgRoot, dir = "") {
4901
+ return readdirSync$1(join(pkgRoot, dir), { withFileTypes: true }).flatMap((entry) => {
4902
+ const path = dir === "" ? entry.name : `${dir}/${entry.name}`;
4903
+ if (entry.isDirectory()) return entry.name === "node_modules" || entry.name === ".git" ? [] : packageFiles(pkgRoot, path);
4904
+ return entry.isFile() ? [path] : [];
4905
+ });
4906
+ }
4907
+ /** A `*` target pattern as a matcher of package-relative files. Node puts
4908
+ * one subpath into every `*`, so each later `*` repeats the first match. */
4909
+ function targetPattern(target) {
4910
+ const body = posixPath(target).replace(/^\.\//, "").split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).reduce((pattern, part, index) => index === 0 ? part : `${pattern}${index === 1 ? "(.+)" : "\\1"}${part}`);
4911
+ return new RegExp(`^${body}$`);
4912
+ }
4913
+ /**
4914
+ * Why the kit at `pkgRoot` would fail an installed consumer: each `animus`
4915
+ * source target, at any condition depth or as a pattern, and each file its
4916
+ * relative imports reach, must be in the package and among the files `npm
4917
+ * pack` publishes, and each bare package import a declared dependency.
4918
+ * Each line names the file, the import and the cause; none means the
4919
+ * published source is complete. With `artifactDir`, a build's artifact
4920
+ * directory inside the package that `npm pack` would publish is a line too.
4921
+ */
4922
+ function kitPublicationFailures(pkgRoot, engine, artifactDir) {
4923
+ let manifest;
4924
+ try {
4925
+ manifest = JSON.parse(readFileSync$1(join(pkgRoot, "package.json"), "utf-8"));
4926
+ } catch (error) {
4927
+ return [`package.json: cannot be read: ${String(error)}`];
4928
+ }
4929
+ const { targets, unreadable } = animusTargets(manifest);
4930
+ if (targets.length === 0 && unreadable.length === 0) return [];
4931
+ const { moduleSpecifiers } = engine;
4932
+ if (moduleSpecifiers === void 0) throw new Error("the native engine does not expose moduleSpecifiers, which the kit publication check needs — rebuild @animus-ui/extract");
4933
+ const publication = npmPublishedFiles(pkgRoot);
4934
+ if (publication.kind === "failed") return [`package.json: ${publication.reason}`];
4935
+ const published = (packageRelative) => publication.files.has(packageRelative);
4936
+ const declared = new Set([
4937
+ "dependencies",
4938
+ "peerDependencies",
4939
+ "optionalDependencies"
4940
+ ].flatMap((field) => {
4941
+ const block = isJsonBlock(manifest) ? manifest[field] : void 0;
4942
+ return isJsonBlock(block) ? Object.keys(block) : [];
4943
+ }));
4944
+ const ownName = isJsonBlock(manifest) && isJsonString(manifest.name) ? manifest.name : null;
4945
+ const failures = [];
4946
+ const rel = (file) => posixPath(relative(pkgRoot, file));
4947
+ const outside = (relPath) => relPath.startsWith("../") || isAbsolute(relPath);
4948
+ for (const [subpath, value] of unreadable) failures.push(`package.json: exports["${subpath}"] has an "animus" value, ${value}, that is no target path`);
4949
+ const queue = [];
4950
+ const admit = (subpath, relPath) => {
4951
+ if (published(relPath)) queue.push(resolve(pkgRoot, relPath));
4952
+ else failures.push(`package.json: the "animus" target of exports["${subpath}"], ${relPath}, is not in the published files`);
4953
+ };
4954
+ let files = null;
4955
+ for (const [subpath, target] of targets) {
4956
+ const relPath = rel(resolve(pkgRoot, target));
4957
+ if (outside(relPath)) failures.push(`package.json: the "animus" target of exports["${subpath}"], ${target}, is outside the package`);
4958
+ else if (target.includes("*")) {
4959
+ files ??= packageFiles(pkgRoot);
4960
+ const pattern = targetPattern(target);
4961
+ const matched = files.filter((file) => pattern.test(file));
4962
+ if (matched.length === 0) failures.push(`package.json: the "animus" target of exports["${subpath}"], ${target}, matches no file in the package`);
4963
+ for (const file of matched) admit(subpath, file);
4964
+ } else if (!isFile(resolve(pkgRoot, target))) failures.push(`package.json: the "animus" target of exports["${subpath}"], ${target}, does not exist in the package`);
4965
+ else admit(subpath, relPath);
4966
+ }
4967
+ const visited = /* @__PURE__ */ new Set();
4968
+ while (queue.length > 0) {
4969
+ const file = queue.shift();
4970
+ if (visited.has(file)) continue;
4971
+ visited.add(file);
4972
+ const specifiers = parseInternalWire(moduleSpecifiers(JSON.stringify([{
4973
+ path: file,
4974
+ source: readFileSync$1(file, "utf-8")
4975
+ }])), "moduleSpecifiers").files[file] ?? [];
4976
+ for (const specifier of specifiers) {
4977
+ if (specifier.startsWith(".")) {
4978
+ const target = relativeSourceCandidates(file, specifier).find(isFile);
4979
+ if (target === void 0) failures.push(`${rel(file)}: import '${specifier}' resolves to no file in the package`);
4980
+ else if (outside(rel(target))) failures.push(`${rel(file)}: import '${specifier}' resolves to ${rel(target)}, outside the package`);
4981
+ else if (!published(rel(target))) failures.push(`${rel(file)}: import '${specifier}' resolves to ${rel(target)}, which is not in the published files`);
4982
+ else if (CODE_EXTENSIONS.has(extname(target))) queue.push(target);
4983
+ continue;
4984
+ }
4985
+ if (specifier.startsWith("/") || /^[a-z][\w+.-]*:/i.test(specifier)) {
4986
+ if (!isBuiltin(specifier)) failures.push(`${rel(file)}: import '${specifier}' is not a package or relative import, so an installed consumer cannot resolve it`);
4987
+ continue;
4988
+ }
4989
+ const name = bareSpecifierPackageName(specifier);
4990
+ if (isBuiltin(name) || name === ownName || declared.has(name)) continue;
4991
+ failures.push(`${rel(file)}: import '${specifier}' names the package ${name}, which package.json does not declare in dependencies, peerDependencies or optionalDependencies`);
4992
+ }
4993
+ }
4994
+ const artifacts = artifactDir === void 0 ? "" : rel(artifactDir);
4995
+ if (artifacts !== "" && !outside(artifacts)) {
4996
+ const shipped = [...publication.files].filter((file) => file.startsWith(`${artifacts}/`));
4997
+ 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"`);
4998
+ }
4999
+ return failures;
5000
+ }
5001
+ //#endregion
4299
5002
  //#region pipeline/replacement-plans.ts
4300
5003
  const snapshotByManifest = /* @__PURE__ */ new WeakMap();
4301
5004
  /** `null` (a context before its first analysis) snapshots to the empty plan
@@ -4372,4 +5075,4 @@ function realpathThroughNearestExistingAncestor(path) {
4372
5075
  }
4373
5076
  }
4374
5077
  //#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 };
5078
+ 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 };