limina 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,20 @@
1
- import { c as getCheckerAdapter, h as toRelativePath, l as isPathInsideDirectory, o as collectMissingCheckerPeerDependencies, r as getActiveCheckers, s as formatMissingCheckerPeerDependencies, u as normalizeAbsolutePath } from "./dep-jgc7X0zw.js";
2
- import { builtinModules } from "node:module";
3
- import { createElapsedTimer, formatErrorMessage, formatErrorMessage as formatErrorMessage$1 } from "@docs-islands/logger/helper";
1
+ import { c as getCheckerAdapter, d as normalizeAbsolutePath, g as toRelativePath, h as toPosixPath, l as normalizeExtensions, o as collectMissingCheckerPeerDependencies, r as getActiveCheckers, s as formatMissingCheckerPeerDependencies, u as isPathInsideDirectory } from "./dep-DzYrmtQJ.js";
2
+ import { builtinModules, createRequire } from "node:module";
3
+ import { createElapsedTimer, formatErrorMessage, formatErrorMessage as formatErrorMessage$1 } from "logaria/helper";
4
4
  import { existsSync, readFileSync, statSync } from "node:fs";
5
5
  import path from "node:path";
6
6
  import ts from "typescript";
7
7
  import { execFile, spawn } from "node:child_process";
8
8
  import { glob } from "tinyglobby";
9
- import { createLogger } from "@docs-islands/logger";
9
+ import { createLogger } from "logaria";
10
10
  import readline from "node:readline";
11
- import { availableParallelism } from "node:os";
12
11
  import * as prompts from "@clack/prompts";
12
+ import { mkdir, writeFile } from "node:fs/promises";
13
+ import { parse } from "yaml";
13
14
 
14
15
  //#region src/tsconfig.ts
15
16
  const dtsConfigFilePattern = /^tsconfig(?:\..+)?\.dts\.json$/u;
16
17
  const buildGraphConfigFilePattern = /^tsconfig(?:\..+)?\.build\.json$/u;
17
- const deprecatedGraphConfigFilePattern = /^tsconfig(?:\..+)?\.graph\.json$/u;
18
18
  const generatedConfigFilePattern = /^tsconfig(?:\..+)?\.paths\.generated\.json$/u;
19
19
  const baseConfigFilePattern = /^tsconfig(?:\..+)?\.base\.json$/u;
20
20
  const checkConfigFilePattern = /^tsconfig(?:\..+)?\.check\.json$/u;
@@ -30,7 +30,7 @@ function escapeRegExp(value) {
30
30
  return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
31
31
  }
32
32
  function createExtensionPattern(extensions) {
33
- if (extensions.length === 0) return /$./u;
33
+ if (extensions.length === 0) return /(?!)/u;
34
34
  return new RegExp(`(?:${extensions.sort((left, right) => right.length - left.length).map(escapeRegExp).join("|")})$`, "u");
35
35
  }
36
36
  function createExtraFileExtensions(extensions) {
@@ -140,13 +140,6 @@ function collectReferencePathInfosFromConfigObject(rootDir, configPath, configOb
140
140
  references: referenceInfos
141
141
  };
142
142
  }
143
- function isNonEmptyStringArray(value) {
144
- return Array.isArray(value) && value.some((item) => typeof item === "string");
145
- }
146
- function hasOwnTypecheckInputs(configObject) {
147
- if (!Object.hasOwn(configObject, "files") && !Object.hasOwn(configObject, "include")) return true;
148
- return isNonEmptyStringArray(configObject.files) || isNonEmptyStringArray(configObject.include);
149
- }
150
143
  function isDtsConfigPath(configPath) {
151
144
  return dtsConfigFilePattern.test(path.basename(configPath));
152
145
  }
@@ -161,101 +154,13 @@ function getDtsCompanionConfigPath(dtsConfigPath) {
161
154
  function isBuildGraphConfigPath(configPath) {
162
155
  return buildGraphConfigFilePattern.test(path.basename(configPath));
163
156
  }
164
- function isDeprecatedGraphConfigPath(configPath) {
165
- return deprecatedGraphConfigFilePattern.test(path.basename(configPath));
166
- }
167
157
  function isReservedTypeScriptConfigFile(fileName) {
168
- return dtsConfigFilePattern.test(fileName) || buildGraphConfigFilePattern.test(fileName) || deprecatedGraphConfigFilePattern.test(fileName) || generatedConfigFilePattern.test(fileName) || baseConfigFilePattern.test(fileName) || checkConfigFilePattern.test(fileName);
158
+ return dtsConfigFilePattern.test(fileName) || buildGraphConfigFilePattern.test(fileName) || generatedConfigFilePattern.test(fileName) || baseConfigFilePattern.test(fileName) || checkConfigFilePattern.test(fileName);
169
159
  }
170
160
  function isOrdinaryTypecheckConfigPath(configPath) {
171
161
  const fileName = path.basename(configPath);
172
162
  return tsconfigFilePattern.test(fileName) && !isReservedTypeScriptConfigFile(fileName);
173
163
  }
174
- function collectTypecheckTargetProjectPaths(options) {
175
- const rootConfigPath = normalizeAbsolutePath(options.rootConfigPath);
176
- const reportedCycles = /* @__PURE__ */ new Set();
177
- const seen = /* @__PURE__ */ new Set();
178
- const problems = [];
179
- const projectPaths = [];
180
- const targetProjectPaths = [];
181
- const formatConfigPath = (configPath) => toRelativePath(options.rootDir, configPath);
182
- const addCycleProblem = (referencePath, stack) => {
183
- const cycleStartIndex = stack.indexOf(referencePath);
184
- const cyclePaths = cycleStartIndex === -1 ? [...stack, referencePath] : [...stack.slice(cycleStartIndex), referencePath];
185
- const cycleKey = cyclePaths.join("\0");
186
- if (reportedCycles.has(cycleKey)) return;
187
- reportedCycles.add(cycleKey);
188
- problems.push([
189
- "Circular reference in ordinary tsconfig references:",
190
- ` cycle: ${cyclePaths.map(formatConfigPath).join(" -> ")}`,
191
- " reason: ordinary tsconfig references used by limina checker typecheck must form an acyclic graph.",
192
- " fix: remove one reference from the cycle, or move shared options into extends instead of references."
193
- ].join("\n"));
194
- };
195
- const visitProject = (projectPath, stack) => {
196
- if (stack.includes(projectPath)) {
197
- addCycleProblem(projectPath, stack);
198
- return;
199
- }
200
- if (seen.has(projectPath)) return;
201
- if (!existsSync(projectPath)) {
202
- problems.push(["Ordinary tsconfig reference graph references a missing tsconfig:", ` config: ${formatConfigPath(projectPath)}`].join("\n"));
203
- return;
204
- }
205
- if (!isOrdinaryTypecheckConfigPath(projectPath)) {
206
- problems.push([
207
- "Invalid config in ordinary tsconfig reference graph:",
208
- ` config: ${formatConfigPath(projectPath)}`,
209
- " reason: ordinary tsconfig references must stay on ordinary tsconfig*.json files; tsconfig*.build.json graph aggregators and tsconfig*.dts.json declaration leaves belong to checker entries."
210
- ].join("\n"));
211
- return;
212
- }
213
- seen.add(projectPath);
214
- projectPaths.push(projectPath);
215
- const configObject = readJsonConfigFile(options.rootDir, projectPath);
216
- const referenceCollection = collectReferencePathInfosFromConfigObject(options.rootDir, projectPath, configObject);
217
- const referencePaths = referenceCollection.references.map((reference) => reference.resolvedPath);
218
- problems.push(...referenceCollection.problems);
219
- if (referencePaths.length === 0 || hasOwnTypecheckInputs(configObject)) targetProjectPaths.push(projectPath);
220
- const nextStack = [...stack, projectPath];
221
- for (const referencePath of referencePaths) {
222
- if (isBuildGraphConfigPath(referencePath) || isDtsConfigPath(referencePath)) {
223
- problems.push([
224
- "Invalid reference in ordinary tsconfig reference graph:",
225
- ` from: ${formatConfigPath(projectPath)}`,
226
- ` to: ${formatConfigPath(referencePath)}`,
227
- " reason: ordinary tsconfig references must stay on ordinary tsconfig*.json files; build graph configs and declaration leaves are checked through checker entries."
228
- ].join("\n"));
229
- continue;
230
- }
231
- if (!isOrdinaryTypecheckConfigPath(referencePath)) {
232
- problems.push([
233
- "Invalid reference in ordinary tsconfig reference graph:",
234
- ` from: ${formatConfigPath(projectPath)}`,
235
- ` to: ${formatConfigPath(referencePath)}`,
236
- " reason: referenced config must be an ordinary tsconfig*.json file."
237
- ].join("\n"));
238
- continue;
239
- }
240
- if (nextStack.includes(referencePath)) {
241
- addCycleProblem(referencePath, nextStack);
242
- continue;
243
- }
244
- visitProject(referencePath, nextStack);
245
- }
246
- };
247
- visitProject(rootConfigPath, []);
248
- if (problems.length === 0 && targetProjectPaths.length === 0) problems.push([
249
- "Ordinary tsconfig reference graph has no tsconfig targets:",
250
- ` root: ${toRelativePath(options.rootDir, rootConfigPath)}`,
251
- " reason: limina checker typecheck runs ordinary tsconfig*.json files without references, plus configs that have references and their own source inputs."
252
- ].join("\n"));
253
- return {
254
- problems,
255
- projectPaths,
256
- targetProjectPaths
257
- };
258
- }
259
164
  function collectGraphProjectRouteFromRoot(options) {
260
165
  const rootGraphConfigPath = normalizeAbsolutePath(options.rootConfigPath);
261
166
  const seen = /* @__PURE__ */ new Set();
@@ -269,13 +174,7 @@ function collectGraphProjectRouteFromRoot(options) {
269
174
  }));
270
175
  const formatConfigPath = (configPath) => toRelativePath(options.rootDir, configPath);
271
176
  problems.push(...rootReferences.problems);
272
- if (isDeprecatedGraphConfigPath(rootGraphConfigPath)) problems.push([
273
- "Checker entry uses a deprecated tsconfig name:",
274
- ` config: ${formatConfigPath(rootGraphConfigPath)}`,
275
- " reason: tsconfig*.graph.json has been renamed to tsconfig*.build.json for declaration build graph aggregators.",
276
- " fix: rename the checker entry to tsconfig*.build.json."
277
- ].join("\n"));
278
- else if (!isBuildGraphConfigPath(rootGraphConfigPath) && !isDtsConfigPath(rootGraphConfigPath)) problems.push([
177
+ if (!isBuildGraphConfigPath(rootGraphConfigPath) && !isDtsConfigPath(rootGraphConfigPath)) problems.push([
279
178
  "Invalid checker entry config:",
280
179
  ` config: ${formatConfigPath(rootGraphConfigPath)}`,
281
180
  " reason: checker entries should point to a tsconfig*.build.json graph aggregator or a direct tsconfig*.dts.json declaration leaf."
@@ -287,17 +186,6 @@ function collectGraphProjectRouteFromRoot(options) {
287
186
  for (const { projectPath } of queue) seen.add(projectPath);
288
187
  for (const { projectPath, rawReferencePath, referrerPath } of queue) {
289
188
  if (!projectPath) continue;
290
- if (isDeprecatedGraphConfigPath(projectPath)) {
291
- problems.push([
292
- "Deprecated checker entry reference:",
293
- ` from: ${formatConfigPath(referrerPath)}`,
294
- ` reference: ${rawReferencePath}`,
295
- ` resolved: ${formatConfigPath(projectPath)}`,
296
- " reason: tsconfig*.graph.json has been renamed to tsconfig*.build.json for declaration build graph aggregators.",
297
- " fix: rename the referenced config to tsconfig*.build.json and update this reference."
298
- ].join("\n"));
299
- continue;
300
- }
301
189
  if (!existsSync(projectPath)) {
302
190
  problems.push([
303
191
  "Checker entry references a missing tsconfig:",
@@ -341,18 +229,8 @@ function collectGraphProjectRoutes(config) {
341
229
  const routes = [];
342
230
  const problems = [];
343
231
  for (const checker of getActiveCheckers(config)) {
344
- if (!getCheckerAdapter(checker.preset)?.graph) continue;
232
+ if (!getCheckerAdapter(checker.preset)?.sourceGraph) continue;
345
233
  const rootConfigPath = resolveProjectConfigPath(config.rootDir, checker.entry);
346
- if (isDeprecatedGraphConfigPath(rootConfigPath)) {
347
- problems.push([
348
- "Checker graph entry uses a deprecated tsconfig name:",
349
- ` checker: ${checker.name}`,
350
- ` config: ${toRelativePath(config.rootDir, rootConfigPath)}`,
351
- " reason: tsconfig*.graph.json has been renamed to tsconfig*.build.json for declaration build graph aggregators.",
352
- " fix: rename the checker entry to tsconfig*.build.json."
353
- ].join("\n"));
354
- continue;
355
- }
356
234
  if (!existsSync(rootConfigPath)) {
357
235
  problems.push([
358
236
  "Checker graph entry references a missing tsconfig:",
@@ -368,6 +246,7 @@ function collectGraphProjectRoutes(config) {
368
246
  problems.push(...routeCollection.problems);
369
247
  routes.push({
370
248
  checkerName: checker.name,
249
+ extensions: checker.extensions,
371
250
  projectPaths: routeCollection.projectPaths,
372
251
  rootConfigPath
373
252
  });
@@ -382,16 +261,6 @@ function collectCheckerEntryProjectRoutes(config) {
382
261
  const problems = [];
383
262
  for (const checker of getActiveCheckers(config)) {
384
263
  const rootConfigPath = resolveProjectConfigPath(config.rootDir, checker.entry);
385
- if (isDeprecatedGraphConfigPath(rootConfigPath)) {
386
- problems.push([
387
- "Checker entry uses a deprecated tsconfig name:",
388
- ` checker: ${checker.name}`,
389
- ` config: ${toRelativePath(config.rootDir, rootConfigPath)}`,
390
- " reason: tsconfig*.graph.json has been renamed to tsconfig*.build.json for declaration build graph aggregators.",
391
- " fix: rename the checker entry to tsconfig*.build.json."
392
- ].join("\n"));
393
- continue;
394
- }
395
264
  if (!existsSync(rootConfigPath)) {
396
265
  problems.push([
397
266
  "Checker entry references a missing tsconfig:",
@@ -407,6 +276,7 @@ function collectCheckerEntryProjectRoutes(config) {
407
276
  problems.push(...routeCollection.problems);
408
277
  routes.push({
409
278
  checkerName: checker.name,
279
+ extensions: checker.extensions,
410
280
  projectPaths: routeCollection.projectPaths,
411
281
  rootConfigPath
412
282
  });
@@ -423,8 +293,18 @@ function collectGraphProjectRoute(config) {
423
293
  projectPaths: [...new Set(routeCollection.routes.flatMap((route) => route.projectPaths))].sort()
424
294
  };
425
295
  }
426
- function parseProjectFileNames(config, configPath, pattern = /\.(?:[cm]?tsx?|d\.[cm]?ts|json)$/u) {
427
- return parseProjectFileNamesForExtensions(config, configPath, [], pattern);
296
+ function collectSourceGraphProjectExtensions(config) {
297
+ const routeCollection = collectGraphProjectRoutes(config);
298
+ const projectExtensionsByPath = /* @__PURE__ */ new Map();
299
+ const typeScriptExtensions = getCheckerAdapter("tsc")?.defaultExtensions ?? [];
300
+ for (const route of routeCollection.routes) {
301
+ const routeExtensions = normalizeExtensions([...typeScriptExtensions, ...route.extensions]);
302
+ for (const projectPath of route.projectPaths) projectExtensionsByPath.set(projectPath, normalizeExtensions([...projectExtensionsByPath.get(projectPath) ?? [], ...routeExtensions]));
303
+ }
304
+ return {
305
+ problems: routeCollection.problems,
306
+ projectExtensionsByPath
307
+ };
428
308
  }
429
309
  function parseProjectFileNamesForExtensions(config, configPath, extensions, pattern = createExtensionPattern(extensions)) {
430
310
  const diagnostics = [];
@@ -441,7 +321,7 @@ function formatReferences(rootDir, references) {
441
321
 
442
322
  //#endregion
443
323
  //#region src/workspace.ts
444
- const pnpmWorkspaceFileName = "pnpm-workspace.yaml";
324
+ const pnpmWorkspaceFileName$1 = "pnpm-workspace.yaml";
445
325
  const pnpmWorkspaceListTimeoutMs = 3e3;
446
326
  function readJsonFile(filePath) {
447
327
  return JSON.parse(readFileSync(filePath, "utf8"));
@@ -488,7 +368,7 @@ function collectWorkspacePatterns(config) {
488
368
  const rootPackageJson = readJsonFile(rootPackageJsonPath);
489
369
  if (Array.isArray(rootPackageJson.workspaces)) for (const pattern of rootPackageJson.workspaces) patterns.add(pattern);
490
370
  }
491
- const workspacePath = path.join(config.rootDir, pnpmWorkspaceFileName);
371
+ const workspacePath = path.join(config.rootDir, pnpmWorkspaceFileName$1);
492
372
  if (existsSync(workspacePath)) for (const pattern of collectPnpmWorkspacePatterns(readFileSync(workspacePath, "utf8"))) patterns.add(pattern);
493
373
  return [...patterns].sort();
494
374
  }
@@ -625,6 +505,22 @@ function getDependencySections(importer) {
625
505
  importer.peerDependencies
626
506
  ].filter((section) => Boolean(section));
627
507
  }
508
+ function getPublishDependencySections(importer) {
509
+ return [
510
+ {
511
+ dependencies: importer.dependencies,
512
+ name: "dependencies"
513
+ },
514
+ {
515
+ dependencies: importer.peerDependencies,
516
+ name: "peerDependencies"
517
+ },
518
+ {
519
+ dependencies: importer.optionalDependencies,
520
+ name: "optionalDependencies"
521
+ }
522
+ ].filter((section) => Boolean(section.dependencies));
523
+ }
628
524
  function isWorkspaceDependencySpecifier(specifier) {
629
525
  return specifier.startsWith("workspace:");
630
526
  }
@@ -663,7 +559,7 @@ function collectImporters(config, packages) {
663
559
 
664
560
  //#endregion
665
561
  //#region src/graph-context.ts
666
- function isRelativeSpecifier(specifier) {
562
+ function isRelativeSpecifier$1(specifier) {
667
563
  return specifier === "." || specifier === ".." || specifier.startsWith("./") || specifier.startsWith("../");
668
564
  }
669
565
  function isDtsProjectConfig(configPath) {
@@ -702,9 +598,9 @@ function readProjectLabel(config, configPath) {
702
598
  ].join("\n")
703
599
  };
704
600
  }
705
- function parseProject(config, configPath) {
601
+ function parseProject(config, configPath, extensions) {
706
602
  const diagnostics = [];
707
- const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, {
603
+ const parsed = extensions ? ts.parseJsonConfigFileContent(readJsonConfig(config, configPath), ts.sys, path.dirname(configPath), {}, configPath, void 0, createExtraFileExtensions(extensions)) : ts.getParsedCommandLineOfConfigFile(configPath, {}, {
708
604
  ...ts.sys,
709
605
  onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
710
606
  diagnostics.push(diagnostic);
@@ -721,9 +617,20 @@ function parseProject(config, configPath) {
721
617
  getNewLine: () => "\n"
722
618
  }));
723
619
  const labelInfo = readProjectLabel(config, configPath);
620
+ const projectExtensions = extensions ?? [
621
+ ".ts",
622
+ ".tsx",
623
+ ".cts",
624
+ ".mts",
625
+ ".d.ts",
626
+ ".d.cts",
627
+ ".d.mts"
628
+ ];
629
+ const filePattern = createExtensionPattern(projectExtensions);
724
630
  return {
725
631
  configPath: normalizeAbsolutePath(configPath),
726
- fileNames: parsed.fileNames.filter((fileName) => /\.(?:[cm]?tsx?|d\.[cm]?ts)$/u.test(fileName)).map(normalizeAbsolutePath),
632
+ extensions: projectExtensions,
633
+ fileNames: parsed.fileNames.filter((fileName) => filePattern.test(fileName)).map(normalizeAbsolutePath),
727
634
  label: labelInfo.label,
728
635
  labelProblem: labelInfo.labelProblem,
729
636
  options: parsed.options,
@@ -738,15 +645,27 @@ function getSourceFileKind(filePath) {
738
645
  function stringLiteralValue(node) {
739
646
  return node && ts.isStringLiteralLike(node) ? node.text : null;
740
647
  }
741
- function collectImportsFromFile(filePath) {
742
- const sourceText = readFileSync(filePath, "utf8");
743
- const sourceFile = ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true, getSourceFileKind(filePath));
648
+ function getVueCompilerSfc(rootDir) {
649
+ const requireFromRoot = createRequire(path.join(rootDir, "package.json"));
650
+ try {
651
+ return requireFromRoot("@vue/compiler-sfc");
652
+ } catch (error) {
653
+ if (error && typeof error === "object" && "code" in error && error.code === "MODULE_NOT_FOUND") throw new Error("Vue source graph support requires @vue/compiler-sfc. Fix: pnpm add -D @vue/compiler-sfc");
654
+ throw error;
655
+ }
656
+ }
657
+ function getVueBlockScriptKind(block) {
658
+ return block.lang === "tsx" || block.lang === "jsx" ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
659
+ }
660
+ function collectImportsFromSourceText(options) {
661
+ const sourceFile = ts.createSourceFile(options.filePath, options.sourceText, ts.ScriptTarget.Latest, true, options.scriptKind);
744
662
  const imports = [];
663
+ const lineOffset = options.lineOffset ?? 0;
745
664
  const addImport = (specifier, node) => {
746
665
  const location = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
747
666
  imports.push({
748
- filePath,
749
- line: location.line + 1,
667
+ filePath: options.filePath,
668
+ line: lineOffset + location.line + 1,
750
669
  specifier
751
670
  });
752
671
  };
@@ -766,9 +685,37 @@ function collectImportsFromFile(filePath) {
766
685
  visit(sourceFile);
767
686
  return imports;
768
687
  }
769
- function resolveInternalImport(specifier, containingFile, options) {
688
+ function collectVueImportsFromFile(filePath, rootDir) {
689
+ const sourceText = readFileSync(filePath, "utf8");
690
+ const result = getVueCompilerSfc(rootDir).parse(sourceText, { filename: filePath });
691
+ if (result.errors.length > 0) throw new Error(`Failed to parse Vue SFC imports for ${toRelativePath(rootDir, filePath)}: ${String(result.errors[0])}`);
692
+ return [result.descriptor.script, result.descriptor.scriptSetup].filter((block) => Boolean(block && !block.src)).flatMap((block) => collectImportsFromSourceText({
693
+ filePath,
694
+ lineOffset: block.loc.start.line - 1,
695
+ scriptKind: getVueBlockScriptKind(block),
696
+ sourceText: block.content
697
+ }));
698
+ }
699
+ function collectImportsFromFile(filePath, rootDir) {
700
+ if (filePath.endsWith(".vue")) return collectVueImportsFromFile(filePath, rootDir);
701
+ return collectImportsFromSourceText({
702
+ filePath,
703
+ scriptKind: getSourceFileKind(filePath),
704
+ sourceText: readFileSync(filePath, "utf8")
705
+ });
706
+ }
707
+ function resolveInternalImport(specifier, containingFile, options, extensions = []) {
770
708
  const resolved = ts.resolveModuleName(specifier, containingFile, options, ts.sys).resolvedModule;
771
- return resolved?.resolvedFileName ? normalizeAbsolutePath(resolved.resolvedFileName) : null;
709
+ if (resolved?.resolvedFileName) return normalizeAbsolutePath(resolved.resolvedFileName);
710
+ if (!isRelativeSpecifier$1(specifier)) return null;
711
+ const resolvedSpecifierPath = path.resolve(path.dirname(containingFile), specifier);
712
+ const candidatePaths = path.extname(specifier) ? [resolvedSpecifierPath] : extensions.flatMap((extension) => [`${resolvedSpecifierPath}${extension}`, path.join(resolvedSpecifierPath, `index${extension}`)]);
713
+ for (const candidatePath of candidatePaths) {
714
+ if (!existsSync(candidatePath)) continue;
715
+ if (!statSync(candidatePath).isFile()) continue;
716
+ return normalizeAbsolutePath(candidatePath);
717
+ }
718
+ return null;
772
719
  }
773
720
  function chooseOwningProject(projectPaths) {
774
721
  return [...projectPaths].sort((left, right) => {
@@ -779,9 +726,6 @@ function chooseOwningProject(projectPaths) {
779
726
  function findPackageForFile(filePath, packages) {
780
727
  return [...packages].sort((left, right) => right.directory.length - left.directory.length).find((workspacePackage) => isPathInsideDirectory(filePath, workspacePackage.directory)) ?? null;
781
728
  }
782
- function isWorkspacePackageFile(filePath, packages) {
783
- return packages.some((workspacePackage) => isPathInsideDirectory(filePath, workspacePackage.directory));
784
- }
785
729
  function findImporterForFile(filePath, importers) {
786
730
  return importers.find((importer) => isPathInsideDirectory(filePath, importer.directory)) ?? null;
787
731
  }
@@ -834,6 +778,60 @@ function formatUnknownValue(value) {
834
778
  function addRuleEntryConfigProblem(problems, details) {
835
779
  problems.push(["Invalid graph rule config:", ...details].join("\n"));
836
780
  }
781
+ function isUrlOrDataOrFileSpecifier$1(specifier) {
782
+ return specifier.startsWith("data:") || specifier.startsWith("file:") || specifier.startsWith("http:") || specifier.startsWith("https:");
783
+ }
784
+ function isRelativeSpecifier(specifier) {
785
+ return specifier === "." || specifier === ".." || specifier.startsWith("./") || specifier.startsWith("../");
786
+ }
787
+ function isPackageImportPattern(name) {
788
+ return name.startsWith("#");
789
+ }
790
+ function matchWildcardPattern(pattern, value) {
791
+ if (pattern === value) return true;
792
+ const wildcardIndex = pattern.indexOf("*");
793
+ if (wildcardIndex === -1) return false;
794
+ const prefix = pattern.slice(0, wildcardIndex);
795
+ const suffix = pattern.slice(wildcardIndex + 1);
796
+ return value.startsWith(prefix) && value.endsWith(suffix);
797
+ }
798
+ function getNodeBuiltinRuleName(name) {
799
+ if (name === "node:*") return {
800
+ matchAllNodeBuiltins: true,
801
+ normalizedName: "*"
802
+ };
803
+ const normalizedName = name.startsWith("node:") ? name.slice(5) : name;
804
+ if (!nodeBuiltinNames.has(normalizedName)) return null;
805
+ return {
806
+ matchAllNodeBuiltins: false,
807
+ normalizedName
808
+ };
809
+ }
810
+ function createNormalizedDep(name, reason) {
811
+ const nodeBuiltin = getNodeBuiltinRuleName(name);
812
+ if (nodeBuiltin) return {
813
+ kind: "node-builtin",
814
+ matchAllNodeBuiltins: nodeBuiltin.matchAllNodeBuiltins,
815
+ name,
816
+ normalizedName: nodeBuiltin.normalizedName,
817
+ reason
818
+ };
819
+ if (isPackageImportPattern(name)) return {
820
+ kind: "package-import",
821
+ matchAllNodeBuiltins: false,
822
+ name,
823
+ normalizedName: name,
824
+ reason
825
+ };
826
+ if (isRelativeSpecifier(name) || isUrlOrDataOrFileSpecifier$1(name) || path.isAbsolute(name) || getPackageRootSpecifier(name) !== name) return null;
827
+ return {
828
+ kind: "package",
829
+ matchAllNodeBuiltins: false,
830
+ name,
831
+ normalizedName: name,
832
+ reason
833
+ };
834
+ }
837
835
  function getRulesRecord(config, problems) {
838
836
  const rules = config.graph?.rules;
839
837
  if (rules === void 0) return {};
@@ -900,13 +898,13 @@ function addNormalizedRuleRef(options) {
900
898
  });
901
899
  options.refsByLabel.set(options.label, refs);
902
900
  }
903
- function addNormalizedWorkspaceDep(options) {
904
- const field = `${options.fieldPrefix}[${options.index}]`;
901
+ function addNormalizedDep(options) {
902
+ const field = `graph.rules.${options.label}.deny.deps[${options.index}]`;
905
903
  if (!isPlainRecord(options.entry)) {
906
904
  addRuleEntryConfigProblem(options.problems, [
907
905
  ` field: ${field}`,
908
906
  ` value: ${formatUnknownValue(options.entry)}`,
909
- " reason: deny workspace dependency entries must be objects with non-empty name and reason fields."
907
+ " reason: deny.deps entries must be objects with non-empty name and reason fields."
910
908
  ]);
911
909
  return;
912
910
  }
@@ -916,7 +914,7 @@ function addNormalizedWorkspaceDep(options) {
916
914
  addRuleEntryConfigProblem(options.problems, [
917
915
  ` field: ${field}.name`,
918
916
  ` value: ${formatUnknownValue(nameValue)}`,
919
- " reason: workspace dependency name is required and must be a non-empty string."
917
+ " reason: deny.deps name is required and must be a non-empty string."
920
918
  ]);
921
919
  return;
922
920
  }
@@ -924,82 +922,31 @@ function addNormalizedWorkspaceDep(options) {
924
922
  addRuleEntryConfigProblem(options.problems, [
925
923
  ` field: ${field}.reason`,
926
924
  ` value: ${formatUnknownValue(reasonValue)}`,
927
- " reason: workspace dependency reason is required and must be a non-empty string."
928
- ]);
929
- return;
930
- }
931
- const packageName = nameValue.trim();
932
- if (!options.packageNames.has(packageName)) {
933
- addRuleEntryConfigProblem(options.problems, [
934
- ` field: ${field}.name`,
935
- ` name: ${packageName}`,
936
- " reason: deny.workspaceDeps and legacy deny.deps only accept discovered workspace package names. Use deny.nodeBuiltins for Node builtins."
937
- ]);
938
- return;
939
- }
940
- const deps = options.workspaceDepsByLabel.get(options.label) ?? /* @__PURE__ */ new Map();
941
- deps.set(packageName, {
942
- name: packageName,
943
- reason: reasonValue.trim()
944
- });
945
- options.workspaceDepsByLabel.set(options.label, deps);
946
- }
947
- function addNormalizedNodeBuiltin(options) {
948
- const field = `graph.rules.${options.label}.deny.nodeBuiltins[${options.index}]`;
949
- if (!isPlainRecord(options.entry)) {
950
- addRuleEntryConfigProblem(options.problems, [
951
- ` field: ${field}`,
952
- ` value: ${formatUnknownValue(options.entry)}`,
953
- " reason: deny.nodeBuiltins entries must be objects with non-empty name and reason fields."
954
- ]);
955
- return;
956
- }
957
- const nameValue = options.entry.name;
958
- const reasonValue = options.entry.reason;
959
- if (!isNonEmptyString(nameValue)) {
960
- addRuleEntryConfigProblem(options.problems, [
961
- ` field: ${field}.name`,
962
- ` value: ${formatUnknownValue(nameValue)}`,
963
- " reason: deny.nodeBuiltins name is required and must be a non-empty string."
964
- ]);
965
- return;
966
- }
967
- if (!isNonEmptyString(reasonValue)) {
968
- addRuleEntryConfigProblem(options.problems, [
969
- ` field: ${field}.reason`,
970
- ` value: ${formatUnknownValue(reasonValue)}`,
971
- " reason: deny.nodeBuiltins reason is required and must be a non-empty string."
925
+ " reason: deny.deps reason is required and must be a non-empty string."
972
926
  ]);
973
927
  return;
974
928
  }
975
929
  const name = nameValue.trim();
976
- const normalizedName = name.startsWith("node:") ? name.slice(5) : name;
977
- const matchAll = name === "node:*";
978
- if (!matchAll && !nodeBuiltinNames.has(normalizedName)) {
930
+ const normalizedDep = createNormalizedDep(name, reasonValue.trim());
931
+ if (!normalizedDep) {
979
932
  addRuleEntryConfigProblem(options.problems, [
980
933
  ` field: ${field}.name`,
981
934
  ` name: ${name}`,
982
- " reason: deny.nodeBuiltins name must be \"node:*\" or a Node builtin specifier such as \"fs\" or \"node:fs\"."
935
+ " reason: deny.deps name must be a package root, a package.json imports specifier such as \"#internal/*\", or a Node builtin such as \"fs\", \"node:fs\", or \"node:*\"."
983
936
  ]);
984
937
  return;
985
938
  }
986
- const entries = options.nodeBuiltinsByLabel.get(options.label) ?? [];
987
- entries.push({
988
- matchAll,
989
- name: normalizedName,
990
- reason: reasonValue.trim()
991
- });
992
- options.nodeBuiltinsByLabel.set(options.label, entries);
939
+ const deps = options.depsByLabel.get(options.label) ?? [];
940
+ deps.push(normalizedDep);
941
+ options.depsByLabel.set(options.label, deps);
993
942
  }
994
943
  function shouldNormalizeRuleKind(include, kind) {
995
944
  return include?.[kind] ?? true;
996
945
  }
997
946
  function normalizeGraphRules(options) {
947
+ const depsByLabel = /* @__PURE__ */ new Map();
998
948
  const refsByLabel = /* @__PURE__ */ new Map();
999
- const workspaceDepsByLabel = /* @__PURE__ */ new Map();
1000
- const nodeBuiltinsByLabel = /* @__PURE__ */ new Map();
1001
949
  const projectPathSet = new Set(options.projectPaths);
1002
- const packageNames = new Set(options.packages.map((workspacePackage) => workspacePackage.name));
1003
950
  for (const [rawLabel, rawRule] of Object.entries(getRulesRecord(options.config, options.problems))) {
1004
951
  const label = rawLabel.trim();
1005
952
  if (!label) {
@@ -1040,60 +987,35 @@ function normalizeGraphRules(options) {
1040
987
  refsByLabel
1041
988
  });
1042
989
  });
1043
- const legacyDeps = rawRule.deny.deps;
1044
- if (shouldNormalizeRuleKind(options.include, "workspaceDeps") && legacyDeps !== void 0) if (!Array.isArray(legacyDeps)) addRuleEntryConfigProblem(options.problems, [
1045
- ` field: graph.rules.${label}.deny.deps`,
1046
- ` value: ${formatUnknownValue(legacyDeps)}`,
1047
- " reason: deny.deps must be an array."
1048
- ]);
1049
- else legacyDeps.forEach((entry, index) => {
1050
- addNormalizedWorkspaceDep({
1051
- entry,
1052
- fieldPrefix: `graph.rules.${label}.deny.deps`,
1053
- index,
1054
- label,
1055
- packageNames,
1056
- problems: options.problems,
1057
- workspaceDepsByLabel
1058
- });
1059
- });
1060
- const workspaceDeps = rawRule.deny.workspaceDeps;
1061
- if (shouldNormalizeRuleKind(options.include, "workspaceDeps") && workspaceDeps !== void 0) if (!Array.isArray(workspaceDeps)) addRuleEntryConfigProblem(options.problems, [
990
+ if (shouldNormalizeRuleKind(options.include, "deps") && rawRule.deny.workspaceDeps !== void 0) addRuleEntryConfigProblem(options.problems, [
1062
991
  ` field: graph.rules.${label}.deny.workspaceDeps`,
1063
- ` value: ${formatUnknownValue(workspaceDeps)}`,
1064
- " reason: deny.workspaceDeps must be an array."
992
+ ` value: ${formatUnknownValue(rawRule.deny.workspaceDeps)}`,
993
+ " reason: deny.workspaceDeps has been removed; use deny.deps."
1065
994
  ]);
1066
- else workspaceDeps.forEach((entry, index) => {
1067
- addNormalizedWorkspaceDep({
1068
- entry,
1069
- fieldPrefix: `graph.rules.${label}.deny.workspaceDeps`,
1070
- index,
1071
- label,
1072
- packageNames,
1073
- problems: options.problems,
1074
- workspaceDepsByLabel
1075
- });
1076
- });
1077
- const nodeBuiltins = rawRule.deny.nodeBuiltins;
1078
- if (shouldNormalizeRuleKind(options.include, "nodeBuiltins") && nodeBuiltins !== void 0) if (!Array.isArray(nodeBuiltins)) addRuleEntryConfigProblem(options.problems, [
995
+ if (shouldNormalizeRuleKind(options.include, "deps") && rawRule.deny.nodeBuiltins !== void 0) addRuleEntryConfigProblem(options.problems, [
1079
996
  ` field: graph.rules.${label}.deny.nodeBuiltins`,
1080
- ` value: ${formatUnknownValue(nodeBuiltins)}`,
1081
- " reason: deny.nodeBuiltins must be an array."
997
+ ` value: ${formatUnknownValue(rawRule.deny.nodeBuiltins)}`,
998
+ " reason: deny.nodeBuiltins has been removed; use deny.deps."
1082
999
  ]);
1083
- else nodeBuiltins.forEach((entry, index) => {
1084
- addNormalizedNodeBuiltin({
1000
+ const deps = rawRule.deny.deps;
1001
+ if (shouldNormalizeRuleKind(options.include, "deps") && deps !== void 0) if (!Array.isArray(deps)) addRuleEntryConfigProblem(options.problems, [
1002
+ ` field: graph.rules.${label}.deny.deps`,
1003
+ ` value: ${formatUnknownValue(deps)}`,
1004
+ " reason: deny.deps must be an array."
1005
+ ]);
1006
+ else deps.forEach((entry, index) => {
1007
+ addNormalizedDep({
1008
+ depsByLabel,
1085
1009
  entry,
1086
1010
  index,
1087
1011
  label,
1088
- nodeBuiltinsByLabel,
1089
1012
  problems: options.problems
1090
1013
  });
1091
1014
  });
1092
1015
  }
1093
1016
  return {
1094
- nodeBuiltinsByLabel,
1095
- refsByLabel,
1096
- workspaceDepsByLabel
1017
+ depsByLabel,
1018
+ refsByLabel
1097
1019
  };
1098
1020
  }
1099
1021
  function isNodeBuiltinSpecifier(specifier) {
@@ -1103,14 +1025,24 @@ function getDeniedRefRule(rules, label, targetProjectPath) {
1103
1025
  if (!label) return null;
1104
1026
  return rules.refsByLabel.get(label)?.get(targetProjectPath) ?? null;
1105
1027
  }
1106
- function getDeniedWorkspaceDepRule(rules, label, targetPackageName) {
1107
- if (!label) return null;
1108
- return rules.workspaceDepsByLabel.get(label)?.get(targetPackageName) ?? null;
1109
- }
1110
- function getDeniedNodeBuiltinRule(rules, label, specifier) {
1111
- if (!label || !isNodeBuiltinSpecifier(specifier)) return null;
1112
- const normalizedSpecifier = specifier.startsWith("node:") ? specifier.slice(5) : specifier;
1113
- return rules.nodeBuiltinsByLabel.get(label)?.find((rule) => rule.matchAll || rule.name === normalizedSpecifier) ?? null;
1028
+ function getRuleDeps(rules, label) {
1029
+ if (!label) return [];
1030
+ return rules.depsByLabel.get(label) ?? [];
1031
+ }
1032
+ function getDeniedDepRuleForPackage(rules, label, packageName) {
1033
+ return getRuleDeps(rules, label).find((rule) => rule.kind === "package" && rule.normalizedName === packageName) ?? null;
1034
+ }
1035
+ function getDeniedDepRuleForSpecifier(rules, label, specifier) {
1036
+ const deps = getRuleDeps(rules, label);
1037
+ const packageImportRule = deps.find((rule) => rule.kind === "package-import" && matchWildcardPattern(rule.normalizedName, specifier));
1038
+ if (packageImportRule) return packageImportRule;
1039
+ if (isNodeBuiltinSpecifier(specifier)) {
1040
+ const normalizedSpecifier = specifier.startsWith("node:") ? specifier.slice(5) : specifier;
1041
+ const nodeRule = deps.find((rule) => rule.kind === "node-builtin" && (rule.matchAllNodeBuiltins || rule.normalizedName === normalizedSpecifier));
1042
+ if (nodeRule) return nodeRule;
1043
+ }
1044
+ if (isRelativeSpecifier(specifier) || isPackageImportPattern(specifier) || isUrlOrDataOrFileSpecifier$1(specifier) || path.isAbsolute(specifier)) return null;
1045
+ return getDeniedDepRuleForPackage(rules, label, getPackageRootSpecifier(specifier));
1114
1046
  }
1115
1047
 
1116
1048
  //#endregion
@@ -1118,6 +1050,7 @@ function getDeniedNodeBuiltinRule(rules, label, specifier) {
1118
1050
  const logger = createLogger({ main: "limina" });
1119
1051
  const CliLogger = logger.getLoggerByGroup("task.cli");
1120
1052
  const GraphLogger = logger.getLoggerByGroup("task.graph");
1053
+ const InitLogger = logger.getLoggerByGroup("task.init");
1121
1054
  const PackageLogger = logger.getLoggerByGroup("task.package");
1122
1055
  const PathsLogger = logger.getLoggerByGroup("task.paths");
1123
1056
  const ProofLogger = logger.getLoggerByGroup("task.proof");
@@ -1132,6 +1065,541 @@ function clearCliScreen() {
1132
1065
  readline.clearScreenDown(process.stdout);
1133
1066
  }
1134
1067
 
1068
+ //#endregion
1069
+ //#region src/commands/init.ts
1070
+ const pnpmWorkspaceFileName = "pnpm-workspace.yaml";
1071
+ const liminaConfigFileName = "limina.config.mjs";
1072
+ const liminaCheckScriptName = "limina:check";
1073
+ const liminaCheckScriptValue = "limina check";
1074
+ const ignoredGlobPatterns = [
1075
+ "**/.git/**",
1076
+ "**/.limina/**",
1077
+ "**/.pnpm-store/**",
1078
+ "**/.tsbuild/**",
1079
+ "**/coverage/**",
1080
+ "**/dist/**",
1081
+ "**/node_modules/**"
1082
+ ];
1083
+ function findPnpmWorkspaceRoot(startDir) {
1084
+ let currentDir = path.resolve(startDir);
1085
+ while (true) {
1086
+ if (existsSync(path.join(currentDir, pnpmWorkspaceFileName))) return normalizeAbsolutePath(currentDir);
1087
+ const parentDir = path.dirname(currentDir);
1088
+ if (parentDir === currentDir) return null;
1089
+ currentDir = parentDir;
1090
+ }
1091
+ }
1092
+ function createInitConfig(rootDir) {
1093
+ return {
1094
+ configPath: path.join(rootDir, liminaConfigFileName),
1095
+ rootDir
1096
+ };
1097
+ }
1098
+ function formatConfigPath(rootDir, configPath) {
1099
+ return toRelativePath(rootDir, configPath);
1100
+ }
1101
+ function formatReferencePath(fromConfigPath, toConfigPath) {
1102
+ const relativePath = toPosixPath(path.relative(path.dirname(fromConfigPath), toConfigPath));
1103
+ return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
1104
+ }
1105
+ function stringifyJson(value) {
1106
+ return `${JSON.stringify(value, null, 2)}\n`;
1107
+ }
1108
+ function getProjectScope(configPath) {
1109
+ const fileName = path.basename(configPath);
1110
+ if (fileName === "tsconfig.json") return "tsconfig";
1111
+ return /^tsconfig\.(.+)\.json$/u.exec(fileName)?.[1] ?? "tsconfig";
1112
+ }
1113
+ function getDtsConfigPath(configPath) {
1114
+ const directory = path.dirname(configPath);
1115
+ const fileName = path.basename(configPath);
1116
+ const dtsFileName = fileName === "tsconfig.json" ? "tsconfig.dts.json" : fileName.replace(/\.json$/u, ".dts.json");
1117
+ return path.join(directory, dtsFileName);
1118
+ }
1119
+ function hasReferences(configObject) {
1120
+ return Array.isArray(configObject.references) && configObject.references.length > 0;
1121
+ }
1122
+ function parseTypeScriptConfig(rootDir, configPath) {
1123
+ const diagnostics = [];
1124
+ const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, {
1125
+ ...ts.sys,
1126
+ onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
1127
+ diagnostics.push(diagnostic);
1128
+ }
1129
+ });
1130
+ if (!parsed) throw new Error(ts.formatDiagnosticsWithColorAndContext(diagnostics, {
1131
+ getCanonicalFileName: (fileName) => fileName,
1132
+ getCurrentDirectory: () => rootDir,
1133
+ getNewLine: () => "\n"
1134
+ }));
1135
+ if (parsed.errors.length > 0) throw new Error(ts.formatDiagnosticsWithColorAndContext(parsed.errors, {
1136
+ getCanonicalFileName: (fileName) => fileName,
1137
+ getCurrentDirectory: () => rootDir,
1138
+ getNewLine: () => "\n"
1139
+ }));
1140
+ return {
1141
+ fileNames: parsed.fileNames.map(normalizeAbsolutePath),
1142
+ options: parsed.options
1143
+ };
1144
+ }
1145
+ function findNearestWorkspacePackage(filePath, packages) {
1146
+ return [...packages].sort((left, right) => right.directory.length - left.directory.length).find((workspacePackage) => isPathInsideDirectory(filePath, workspacePackage.directory)) ?? null;
1147
+ }
1148
+ function collectWorkspaceDependencyNames(manifest) {
1149
+ const dependencyNames = /* @__PURE__ */ new Set();
1150
+ for (const dependencies of getDependencySections(manifest)) for (const [dependencyName, specifier] of Object.entries(dependencies)) if (isWorkspaceDependencySpecifier(specifier)) dependencyNames.add(dependencyName);
1151
+ return dependencyNames;
1152
+ }
1153
+ function findOwningProjectForFile(filePath, projects) {
1154
+ const normalizedFilePath = normalizeAbsolutePath(filePath);
1155
+ return projects.filter((project) => project.fileNames.includes(normalizedFilePath)).sort((left, right) => {
1156
+ const depthDelta = path.dirname(right.configPath).length - path.dirname(left.configPath).length;
1157
+ return depthDelta === 0 ? left.configPath.localeCompare(right.configPath) : depthDelta;
1158
+ })[0] ?? null;
1159
+ }
1160
+ function isDirectory(filePath) {
1161
+ try {
1162
+ return statSync(filePath).isDirectory();
1163
+ } catch {
1164
+ return false;
1165
+ }
1166
+ }
1167
+ function mapVirtualWorkspacePath(filePath, packageByName) {
1168
+ const segments = normalizeAbsolutePath(filePath).split("/");
1169
+ for (let index = 0; index < segments.length; index += 1) {
1170
+ if (segments[index] !== "node_modules") continue;
1171
+ const firstPackageSegment = segments[index + 1];
1172
+ if (!firstPackageSegment) continue;
1173
+ const isScopedPackage = firstPackageSegment.startsWith("@");
1174
+ const packageName = isScopedPackage ? `${firstPackageSegment}/${segments[index + 2] ?? ""}` : firstPackageSegment;
1175
+ const restStart = index + (isScopedPackage ? 3 : 2);
1176
+ const workspacePackage = packageByName.get(packageName);
1177
+ if (!workspacePackage) continue;
1178
+ return path.join(workspacePackage.directory, ...segments.slice(restStart));
1179
+ }
1180
+ return null;
1181
+ }
1182
+ function isVirtualWorkspaceDirectory(directoryPath, packageByName) {
1183
+ const segments = normalizeAbsolutePath(directoryPath).split("/");
1184
+ for (let index = 0; index < segments.length; index += 1) {
1185
+ if (segments[index] !== "node_modules") continue;
1186
+ const firstPackageSegment = segments[index + 1];
1187
+ if (!firstPackageSegment) return packageByName.size > 0;
1188
+ if (firstPackageSegment.startsWith("@") && segments[index + 2] === void 0) return [...packageByName.keys()].some((packageName) => packageName.startsWith(`${firstPackageSegment}/`));
1189
+ }
1190
+ const mappedPath = mapVirtualWorkspacePath(directoryPath, packageByName);
1191
+ return mappedPath ? isDirectory(mappedPath) : false;
1192
+ }
1193
+ function createWorkspaceModuleResolutionHost(options) {
1194
+ const mapPath = (filePath) => mapVirtualWorkspacePath(filePath, options.packageByName) ?? filePath;
1195
+ return {
1196
+ directoryExists: (directoryPath) => isVirtualWorkspaceDirectory(directoryPath, options.packageByName) || (ts.sys.directoryExists?.(directoryPath) ?? isDirectory(directoryPath)),
1197
+ fileExists: (filePath) => {
1198
+ const mappedPath = mapPath(filePath);
1199
+ return existsSync(mappedPath) && !isDirectory(mappedPath);
1200
+ },
1201
+ getCurrentDirectory: () => options.rootDir,
1202
+ readFile: (filePath) => ts.sys.readFile(mapPath(filePath)),
1203
+ realpath: (filePath) => normalizeAbsolutePath(mapPath(filePath)),
1204
+ useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames
1205
+ };
1206
+ }
1207
+ function resolveImportWithTypeScript(options) {
1208
+ const resolvedModule = ts.resolveModuleName(options.importRecord.specifier, options.importRecord.filePath, options.project.options, options.host, options.cache).resolvedModule;
1209
+ if (!resolvedModule?.resolvedFileName) return null;
1210
+ return normalizeAbsolutePath(mapVirtualWorkspacePath(resolvedModule.resolvedFileName, options.packageByName) ?? resolvedModule.resolvedFileName);
1211
+ }
1212
+ function isPackageImportSpecifier$1(specifier) {
1213
+ return specifier.startsWith("#");
1214
+ }
1215
+ function createDtsConfig(project) {
1216
+ const fileName = path.basename(project.configPath);
1217
+ const scope = project.scope;
1218
+ const output = {
1219
+ $schema: "https://json.schemastore.org/tsconfig",
1220
+ extends: [`./${fileName}`],
1221
+ compilerOptions: {
1222
+ composite: true,
1223
+ incremental: true,
1224
+ noEmit: false,
1225
+ declaration: true,
1226
+ emitDeclarationOnly: true,
1227
+ declarationMap: false,
1228
+ rootDir: ".",
1229
+ outDir: "./.limina",
1230
+ tsBuildInfoFile: `./.limina/${scope}.tsbuildinfo`
1231
+ }
1232
+ };
1233
+ if (project.references.length > 0) output.references = project.references.map((referencePath) => ({ path: referencePath }));
1234
+ return output;
1235
+ }
1236
+ function createBuildAggregator(references) {
1237
+ return {
1238
+ $schema: "https://json.schemastore.org/tsconfig",
1239
+ files: [],
1240
+ references: references.map((referencePath) => ({ path: referencePath }))
1241
+ };
1242
+ }
1243
+ function createLiminaConfigContent() {
1244
+ return `import { defineConfig } from 'limina';
1245
+
1246
+ export default defineConfig({
1247
+ // Shared checker entries used by graph, proof, paths, and typecheck checks.
1248
+ config: {
1249
+ checkers: {
1250
+ typescript: {
1251
+ preset: 'tsc',
1252
+ entry: 'tsconfig.build.json',
1253
+ },
1254
+ },
1255
+ },
1256
+ });
1257
+ `;
1258
+ }
1259
+ async function confirmAction(options, message) {
1260
+ if (options.yes) return true;
1261
+ if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error(`${message} Run limina init --yes to accept the default confirmation in non-interactive environments.`);
1262
+ const result = await prompts.confirm({
1263
+ initialValue: true,
1264
+ message
1265
+ });
1266
+ if (prompts.isCancel(result)) throw new Error("limina init canceled.");
1267
+ return result;
1268
+ }
1269
+ async function writeTextFile(filePath, content, writtenFiles) {
1270
+ await mkdir(path.dirname(filePath), { recursive: true });
1271
+ await writeFile(filePath, content);
1272
+ writtenFiles.push(filePath);
1273
+ }
1274
+ async function writeBuildAggregatorFile(options) {
1275
+ if (options.references.length === 0) return false;
1276
+ await writeTextFile(options.configPath, stringifyJson(createBuildAggregator(options.references)), options.writtenFiles);
1277
+ return true;
1278
+ }
1279
+ function findPnpmWorkspacePath(startDir) {
1280
+ const rootDir = findPnpmWorkspaceRoot(startDir);
1281
+ return rootDir ? path.join(rootDir, pnpmWorkspaceFileName) : null;
1282
+ }
1283
+ function resolveCatalogRange(range, packageName, packageManifestPath) {
1284
+ if (!range) return null;
1285
+ if (!range.startsWith("catalog:")) return range;
1286
+ const workspacePath = findPnpmWorkspacePath(path.dirname(packageManifestPath));
1287
+ if (!workspacePath || !existsSync(workspacePath)) return null;
1288
+ const parsed = parse(readFileSync(workspacePath, "utf8"));
1289
+ const catalogName = range.slice(8);
1290
+ if (catalogName.length === 0 || catalogName === "default") return parsed?.catalog?.[packageName] ?? null;
1291
+ return parsed?.catalogs?.[catalogName]?.[packageName] ?? null;
1292
+ }
1293
+ function readLiminaPackageMetadata() {
1294
+ const manifestPath = createRequire(import.meta.url).resolve("limina/package.json");
1295
+ const manifest = readJsonFile(manifestPath);
1296
+ const versionRange = manifest.version ? `^${manifest.version}` : "^0.0.1";
1297
+ const rawTypeScriptRange = manifest.peerDependencies?.typescript ?? manifest.devDependencies?.typescript ?? manifest.dependencies?.typescript;
1298
+ return {
1299
+ typescriptRange: resolveCatalogRange(rawTypeScriptRange, "typescript", manifestPath) ?? rawTypeScriptRange ?? "^5.9.0",
1300
+ versionRange
1301
+ };
1302
+ }
1303
+ function hasDependency(manifest, dependencyName) {
1304
+ return Boolean(manifest.dependencies?.[dependencyName] || manifest.devDependencies?.[dependencyName] || manifest.optionalDependencies?.[dependencyName] || manifest.peerDependencies?.[dependencyName]);
1305
+ }
1306
+ async function updateRootPackageJson(options) {
1307
+ const packageJsonPath = path.join(options.rootDir, "package.json");
1308
+ let installRequired = false;
1309
+ if (!existsSync(packageJsonPath)) {
1310
+ if (!await confirmAction(options.prompt, `No package.json found at ${formatConfigPath(options.rootDir, packageJsonPath)}. Create one?`)) {
1311
+ options.skippedFiles.push(packageJsonPath);
1312
+ return false;
1313
+ }
1314
+ await writeTextFile(packageJsonPath, stringifyJson({
1315
+ private: true,
1316
+ type: "module",
1317
+ scripts: { [liminaCheckScriptName]: liminaCheckScriptValue },
1318
+ devDependencies: {
1319
+ limina: options.metadata.versionRange,
1320
+ typescript: options.metadata.typescriptRange
1321
+ }
1322
+ }), options.writtenFiles);
1323
+ return true;
1324
+ }
1325
+ const manifest = readJsonFile(packageJsonPath);
1326
+ const scripts = { ...manifest.scripts ?? {} };
1327
+ let changed = false;
1328
+ if (scripts[liminaCheckScriptName] && scripts[liminaCheckScriptName] !== liminaCheckScriptValue) {
1329
+ if (await confirmAction(options.prompt, `Script "${liminaCheckScriptName}" already exists in package.json. Overwrite it?`)) {
1330
+ scripts[liminaCheckScriptName] = liminaCheckScriptValue;
1331
+ changed = true;
1332
+ }
1333
+ } else if (!scripts[liminaCheckScriptName]) {
1334
+ scripts[liminaCheckScriptName] = liminaCheckScriptValue;
1335
+ changed = true;
1336
+ }
1337
+ if (!hasDependency(manifest, "limina")) {
1338
+ manifest.devDependencies = {
1339
+ ...manifest.devDependencies ?? {},
1340
+ limina: options.metadata.versionRange
1341
+ };
1342
+ installRequired = true;
1343
+ changed = true;
1344
+ }
1345
+ if (changed) await writeTextFile(packageJsonPath, stringifyJson({
1346
+ ...manifest,
1347
+ scripts
1348
+ }), options.writtenFiles);
1349
+ return installRequired;
1350
+ }
1351
+ async function collectReservedConfigConflicts(rootDir) {
1352
+ const conflicts = await glob([
1353
+ "tsconfig*.build.json",
1354
+ "**/tsconfig*.build.json",
1355
+ "tsconfig*.dts.json",
1356
+ "**/tsconfig*.dts.json"
1357
+ ], {
1358
+ absolute: false,
1359
+ cwd: rootDir,
1360
+ ignore: ignoredGlobPatterns
1361
+ });
1362
+ return [...new Set(conflicts)].sort();
1363
+ }
1364
+ async function collectOrdinaryTsconfigPaths(rootDir) {
1365
+ const configPaths = await glob(["tsconfig*.json", "**/tsconfig*.json"], {
1366
+ absolute: false,
1367
+ cwd: rootDir,
1368
+ ignore: ignoredGlobPatterns
1369
+ });
1370
+ return [...new Set(configPaths)].map((configPath) => normalizeAbsolutePath(path.join(rootDir, configPath))).filter(isOrdinaryTypecheckConfigPath).sort();
1371
+ }
1372
+ function analyzeTypecheckProjects(options) {
1373
+ const problems = [];
1374
+ const projects = [];
1375
+ for (const configPath of options.configPaths) {
1376
+ const configObject = readJsonConfig(options.config, configPath);
1377
+ const parsed = parseTypeScriptConfig(options.config.rootDir, configPath);
1378
+ const hasProjectReferences = hasReferences(configObject);
1379
+ const fileName = path.basename(configPath);
1380
+ if (fileName === "tsconfig.json" && hasProjectReferences && parsed.fileNames.length > 0) {
1381
+ problems.push([
1382
+ "Invalid tsconfig role:",
1383
+ ` config: ${formatConfigPath(options.config.rootDir, configPath)}`,
1384
+ " reason: tsconfig.json must be either a pure aggregator with files: [] and references, or a typecheck leaf with source files, but not both."
1385
+ ].join("\n"));
1386
+ continue;
1387
+ }
1388
+ if (fileName !== "tsconfig.json" && hasProjectReferences) {
1389
+ problems.push([
1390
+ "Invalid scoped tsconfig role:",
1391
+ ` config: ${formatConfigPath(options.config.rootDir, configPath)}`,
1392
+ " reason: tsconfig.<scope>.json files may only be typecheck leaves; graph aggregation belongs in tsconfig*.build.json."
1393
+ ].join("\n"));
1394
+ continue;
1395
+ }
1396
+ if (fileName === "tsconfig.json" && hasProjectReferences) continue;
1397
+ projects.push({
1398
+ configPath,
1399
+ dtsConfigPath: getDtsConfigPath(configPath),
1400
+ fileNames: parsed.fileNames,
1401
+ options: parsed.options,
1402
+ owner: findNearestWorkspacePackage(configPath, options.workspacePackages),
1403
+ references: [],
1404
+ scope: getProjectScope(configPath)
1405
+ });
1406
+ }
1407
+ return {
1408
+ problems,
1409
+ projects
1410
+ };
1411
+ }
1412
+ function inferProjectReferences(options) {
1413
+ const problems = [];
1414
+ const packageByName = new Map(options.workspacePackages.map((workspacePackage) => [workspacePackage.name, workspacePackage]));
1415
+ const host = createWorkspaceModuleResolutionHost({
1416
+ packageByName,
1417
+ rootDir: options.config.rootDir
1418
+ });
1419
+ for (const project of options.projects) {
1420
+ if (!project.owner) continue;
1421
+ const workspaceDependencyNames = collectWorkspaceDependencyNames(project.owner.manifest);
1422
+ const resolutionCache = ts.createModuleResolutionCache(path.dirname(project.configPath), (fileName) => fileName, project.options);
1423
+ const referencePaths = /* @__PURE__ */ new Set();
1424
+ for (const fileName of project.fileNames) {
1425
+ if (!/\.(?:[cm]?tsx?|d\.[cm]?ts)$/u.test(fileName)) continue;
1426
+ for (const importRecord of collectImportsFromFile(fileName, options.config.rootDir)) {
1427
+ const resolvedFilePath = resolveImportWithTypeScript({
1428
+ cache: resolutionCache,
1429
+ host,
1430
+ importRecord,
1431
+ packageByName,
1432
+ project
1433
+ });
1434
+ const packageName = isRelativeSpecifier$1(importRecord.specifier) || isPackageImportSpecifier$1(importRecord.specifier) ? null : getPackageRootSpecifier(importRecord.specifier);
1435
+ const targetPackage = packageName ? packageByName.get(packageName) : null;
1436
+ const isWorkspaceGraphDependency = targetPackage && (targetPackage.name === project.owner.name || workspaceDependencyNames.has(targetPackage.name));
1437
+ if (packageName && workspaceDependencyNames.has(packageName) && !targetPackage) {
1438
+ problems.push([
1439
+ "Workspace dependency was not discovered by pnpm:",
1440
+ ` importing project: ${formatConfigPath(options.config.rootDir, project.dtsConfigPath)}`,
1441
+ ` file: ${formatConfigPath(options.config.rootDir, importRecord.filePath)}:${importRecord.line}`,
1442
+ ` imported specifier: ${importRecord.specifier}`,
1443
+ ` package: ${packageName}`,
1444
+ " reason: package.json declares this dependency with the workspace: protocol, but limina init could not find a matching workspace package."
1445
+ ].join("\n"));
1446
+ continue;
1447
+ }
1448
+ if (targetPackage && !isWorkspaceGraphDependency) continue;
1449
+ if (!resolvedFilePath) {
1450
+ if (targetPackage && isWorkspaceGraphDependency) problems.push([
1451
+ "Unable to resolve workspace import with TypeScript:",
1452
+ ` importing project: ${formatConfigPath(options.config.rootDir, project.dtsConfigPath)}`,
1453
+ ` file: ${formatConfigPath(options.config.rootDir, importRecord.filePath)}:${importRecord.line}`,
1454
+ ` imported specifier: ${importRecord.specifier}`,
1455
+ ` package: ${targetPackage.name}`,
1456
+ " reason: workspace:* imports must resolve with the project TypeScript compilerOptions before limina init can generate project references."
1457
+ ].join("\n"));
1458
+ continue;
1459
+ }
1460
+ if (isRelativeSpecifier$1(importRecord.specifier)) {
1461
+ const sourcePackage = findNearestWorkspacePackage(importRecord.filePath, options.workspacePackages);
1462
+ const resolvedPackage = findNearestWorkspacePackage(resolvedFilePath, options.workspacePackages);
1463
+ if (sourcePackage && resolvedPackage && sourcePackage.name !== resolvedPackage.name) continue;
1464
+ }
1465
+ const targetProject = findOwningProjectForFile(resolvedFilePath, options.projects);
1466
+ if (!targetProject) {
1467
+ if (targetPackage && isWorkspaceGraphDependency) problems.push([
1468
+ "Unable to map workspace import to a generated declaration leaf:",
1469
+ ` importing project: ${formatConfigPath(options.config.rootDir, project.dtsConfigPath)}`,
1470
+ ` file: ${formatConfigPath(options.config.rootDir, importRecord.filePath)}:${importRecord.line}`,
1471
+ ` imported specifier: ${importRecord.specifier}`,
1472
+ ` resolved file: ${formatConfigPath(options.config.rootDir, resolvedFilePath)}`,
1473
+ " reason: TypeScript resolved this workspace import, but the resolved module is not covered by any ordinary tsconfig*.json leaf."
1474
+ ].join("\n"));
1475
+ continue;
1476
+ }
1477
+ if (targetProject.dtsConfigPath !== project.dtsConfigPath) referencePaths.add(formatReferencePath(project.dtsConfigPath, targetProject.dtsConfigPath));
1478
+ }
1479
+ }
1480
+ project.references = [...referencePaths].sort();
1481
+ }
1482
+ return problems;
1483
+ }
1484
+ function collectProjectReferencesForOwner(options) {
1485
+ return options.projects.filter((project) => project.owner?.directory === options.owner?.directory).map((project) => formatReferencePath(options.targetConfigPath, project.dtsConfigPath)).sort();
1486
+ }
1487
+ function collectRootBuildProjectReferences(options) {
1488
+ return options.projects.filter((project) => !project.owner || project.owner.directory === options.rootDir || path.dirname(project.configPath) === options.rootDir).map((project) => formatReferencePath(options.targetConfigPath, project.dtsConfigPath)).sort();
1489
+ }
1490
+ async function writeGeneratedTsconfigs(options) {
1491
+ for (const project of options.projects) await writeTextFile(project.dtsConfigPath, stringifyJson(createDtsConfig(project)), options.writtenFiles);
1492
+ const nonRootWorkspacePackages = options.workspacePackages.filter((workspacePackage) => workspacePackage.directory !== options.rootDir);
1493
+ const workspaceBuildConfigPaths = [];
1494
+ for (const workspacePackage of nonRootWorkspacePackages) {
1495
+ const buildConfigPath = path.join(workspacePackage.directory, "tsconfig.build.json");
1496
+ if (await writeBuildAggregatorFile({
1497
+ configPath: buildConfigPath,
1498
+ references: collectProjectReferencesForOwner({
1499
+ owner: workspacePackage,
1500
+ projects: options.projects,
1501
+ targetConfigPath: buildConfigPath
1502
+ }),
1503
+ writtenFiles: options.writtenFiles
1504
+ })) workspaceBuildConfigPaths.push(buildConfigPath);
1505
+ }
1506
+ const rootBuildConfigPath = path.join(options.rootDir, "tsconfig.build.json");
1507
+ await writeBuildAggregatorFile({
1508
+ configPath: rootBuildConfigPath,
1509
+ references: [...collectRootBuildProjectReferences({
1510
+ projects: options.projects,
1511
+ rootDir: options.rootDir,
1512
+ targetConfigPath: rootBuildConfigPath
1513
+ }), ...workspaceBuildConfigPaths.map((buildConfigPath) => formatReferencePath(rootBuildConfigPath, buildConfigPath))].sort(),
1514
+ writtenFiles: options.writtenFiles
1515
+ });
1516
+ }
1517
+ async function writeLiminaConfig(options) {
1518
+ const configPath = path.join(options.rootDir, liminaConfigFileName);
1519
+ if (existsSync(configPath)) {
1520
+ if (!await confirmAction(options.prompt, `${liminaConfigFileName} already exists. Overwrite it?`)) {
1521
+ options.skippedFiles.push(configPath);
1522
+ return;
1523
+ }
1524
+ }
1525
+ await writeTextFile(configPath, createLiminaConfigContent(), options.writtenFiles);
1526
+ }
1527
+ async function runInitInternal(options) {
1528
+ const cwd = normalizeAbsolutePath(options.cwd ?? process.cwd());
1529
+ const rootDir = findPnpmWorkspaceRoot(cwd);
1530
+ if (!rootDir) throw new Error(`Unable to run limina init from ${cwd}: no pnpm-workspace.yaml was found in this directory or its parents.`);
1531
+ const rootPackageJsonPath = path.join(rootDir, "package.json");
1532
+ const rootPackageName = existsSync(rootPackageJsonPath) ? readJsonFile(rootPackageJsonPath).name : void 0;
1533
+ if (!await confirmAction(options, `Use pnpm workspace ${rootPackageName ? `"${rootPackageName}" ` : ""}at ${rootDir}?`)) throw new Error("limina init canceled.");
1534
+ const reservedConflicts = await collectReservedConfigConflicts(rootDir);
1535
+ if (reservedConflicts.length > 0) throw new Error([
1536
+ "Unable to run limina init because reserved Limina tsconfig names already exist:",
1537
+ ...reservedConflicts.map((configPath) => ` - ${configPath}`),
1538
+ "reason: tsconfig*.build.json and tsconfig*.dts.json are Limina init output names; rename existing files before running init."
1539
+ ].join("\n"));
1540
+ const config = createInitConfig(rootDir);
1541
+ const workspacePackages = (await collectWorkspacePackages(config)).filter((workspacePackage) => workspacePackage.directory !== rootDir);
1542
+ const projectAnalysis = analyzeTypecheckProjects({
1543
+ config,
1544
+ configPaths: await collectOrdinaryTsconfigPaths(rootDir),
1545
+ workspacePackages
1546
+ });
1547
+ const problems = [...projectAnalysis.problems];
1548
+ if (problems.length === 0) problems.push(...inferProjectReferences({
1549
+ config,
1550
+ projects: projectAnalysis.projects,
1551
+ workspacePackages
1552
+ }));
1553
+ if (problems.length > 0) throw new Error(problems.join("\n\n"));
1554
+ const metadata = readLiminaPackageMetadata();
1555
+ const writtenFiles = [];
1556
+ const skippedFiles = [];
1557
+ await writeGeneratedTsconfigs({
1558
+ projects: projectAnalysis.projects,
1559
+ rootDir,
1560
+ workspacePackages,
1561
+ writtenFiles
1562
+ });
1563
+ await writeLiminaConfig({
1564
+ prompt: options,
1565
+ rootDir,
1566
+ skippedFiles,
1567
+ writtenFiles
1568
+ });
1569
+ return {
1570
+ checkCommand: "pnpm limina:check",
1571
+ installRequired: await updateRootPackageJson({
1572
+ metadata,
1573
+ prompt: options,
1574
+ rootDir,
1575
+ skippedFiles,
1576
+ writtenFiles
1577
+ }),
1578
+ rootDir,
1579
+ skippedFiles,
1580
+ workspacePackageCount: workspacePackages.length,
1581
+ writtenFiles
1582
+ };
1583
+ }
1584
+ async function runInit(options = {}) {
1585
+ if (options.clearScreen ?? true) clearCliScreen();
1586
+ const elapsed = createElapsedTimer();
1587
+ const task = options.flow?.start("init workspace", { depth: options.flowDepth ?? 0 });
1588
+ InitLogger.info("init started");
1589
+ try {
1590
+ const result = await runInitInternal(options);
1591
+ InitLogger.success(`init generated ${result.writtenFiles.length} files for ${result.workspacePackageCount} workspace packages.`, elapsed());
1592
+ if (result.installRequired) InitLogger.info("limina was added to devDependencies; run pnpm i before checking.");
1593
+ InitLogger.info(`next: ${result.installRequired ? "pnpm i && " : ""}${result.checkCommand}`);
1594
+ task?.pass();
1595
+ return result;
1596
+ } catch (error) {
1597
+ InitLogger.error(`init failed: ${formatErrorMessage$1(error)}`, elapsed());
1598
+ task?.fail("init failed", { error });
1599
+ throw error;
1600
+ }
1601
+ }
1602
+
1135
1603
  //#endregion
1136
1604
  //#region src/commands/source.ts
1137
1605
  function findOwnerForFile(filePath, owners) {
@@ -1140,11 +1608,14 @@ function findOwnerForFile(filePath, owners) {
1140
1608
  function isUrlOrDataOrFileSpecifier(specifier) {
1141
1609
  return specifier.startsWith("data:") || specifier.startsWith("file:") || specifier.startsWith("http:") || specifier.startsWith("https:");
1142
1610
  }
1611
+ function isVirtualModuleSpecifier(specifier) {
1612
+ return specifier.startsWith("virtual:");
1613
+ }
1143
1614
  function isPackageImportSpecifier(specifier) {
1144
1615
  return specifier.startsWith("#");
1145
1616
  }
1146
1617
  function isBarePackageSpecifier(specifier) {
1147
- return !isRelativeSpecifier(specifier) && !isPackageImportSpecifier(specifier) && !isUrlOrDataOrFileSpecifier(specifier) && !path.isAbsolute(specifier);
1618
+ return !isRelativeSpecifier$1(specifier) && !isPackageImportSpecifier(specifier) && !isUrlOrDataOrFileSpecifier(specifier) && !isVirtualModuleSpecifier(specifier) && !path.isAbsolute(specifier);
1148
1619
  }
1149
1620
  function isDependencyAuthorized(manifest, packageName) {
1150
1621
  return Boolean(manifest.dependencies?.[packageName] || manifest.devDependencies?.[packageName]);
@@ -1218,17 +1689,6 @@ function addPackageImportAuthorizationProblem(options) {
1218
1689
  " reason: source imports must be authorized by the nearest package.json dependencies or devDependencies."
1219
1690
  ].join("\n"));
1220
1691
  }
1221
- function addNodeBuiltinDenyProblem(options) {
1222
- options.problems.push([
1223
- "Denied Node builtin import:",
1224
- ` rule: ${options.project.label}`,
1225
- ` importing project: ${toRelativePath(options.config.rootDir, options.project.configPath)}`,
1226
- ` file: ${toRelativePath(options.config.rootDir, options.importRecord.filePath)}:${options.importRecord.line}`,
1227
- ` imported specifier: ${options.importRecord.specifier}`,
1228
- ` denied builtin: ${options.ruleName}`,
1229
- ` reason: ${options.reason}`
1230
- ].join("\n"));
1231
- }
1232
1692
  function addPackageImportProblem(options) {
1233
1693
  if (!packageImportsMatch(options.owner.manifest.imports, options.importRecord.specifier)) {
1234
1694
  options.problems.push([
@@ -1263,7 +1723,7 @@ function createSourceProjectEntries(config, projects) {
1263
1723
  return projects.filter((project) => isDtsProjectConfig(project.configPath)).map((project) => {
1264
1724
  const typecheckConfigPath = getTypecheckConfigPath(project.configPath);
1265
1725
  const fileNames = new Set(project.fileNames);
1266
- if (existsSync(typecheckConfigPath)) for (const fileName of parseProject(config, typecheckConfigPath).fileNames) fileNames.add(fileName);
1726
+ if (existsSync(typecheckConfigPath)) for (const fileName of parseProject(config, typecheckConfigPath, project.extensions).fileNames) fileNames.add(fileName);
1267
1727
  return {
1268
1728
  fileNames: [...fileNames].sort(),
1269
1729
  project
@@ -1271,24 +1731,12 @@ function createSourceProjectEntries(config, projects) {
1271
1731
  });
1272
1732
  }
1273
1733
  async function runSourceCheckInternal(config, options = {}) {
1274
- const graphRoute = collectGraphProjectRoute(config);
1275
- const projectPaths = graphRoute.projectPaths;
1276
- const projects = projectPaths.map((projectPath) => parseProject(config, projectPath));
1734
+ const graphRoute = collectSourceGraphProjectExtensions(config);
1735
+ const projects = [...graphRoute.projectExtensionsByPath.keys()].sort().map((projectPath) => parseProject(config, projectPath, graphRoute.projectExtensionsByPath.get(projectPath)));
1277
1736
  const sourceProjectEntries = createSourceProjectEntries(config, projects);
1278
1737
  const packages = await collectWorkspacePackages(config);
1279
1738
  const packageOwners = await collectPackageOwners(config);
1280
1739
  const problems = [...graphRoute.problems];
1281
- const graphRules = normalizeGraphRules({
1282
- config,
1283
- include: {
1284
- nodeBuiltins: true,
1285
- refs: false,
1286
- workspaceDeps: false
1287
- },
1288
- packages,
1289
- problems,
1290
- projectPaths
1291
- });
1292
1740
  for (const project of projects) {
1293
1741
  if (project.labelProblem) problems.push(project.labelProblem);
1294
1742
  if (!isDtsProjectConfig(project.configPath)) continue;
@@ -1304,7 +1752,7 @@ async function runSourceCheckInternal(config, options = {}) {
1304
1752
  if (existsSync(typecheckConfigPath)) addProjectOwnerProblems({
1305
1753
  config,
1306
1754
  configPath: typecheckConfigPath,
1307
- fileNames: parseProject(config, typecheckConfigPath).fileNames,
1755
+ fileNames: parseProject(config, typecheckConfigPath, project.extensions).fileNames,
1308
1756
  owners: packageOwners,
1309
1757
  problems,
1310
1758
  role: "typecheck companion"
@@ -1313,9 +1761,9 @@ async function runSourceCheckInternal(config, options = {}) {
1313
1761
  for (const { fileNames, project } of sourceProjectEntries) for (const filePath of fileNames) {
1314
1762
  const owner = findOwnerForFile(filePath, packageOwners);
1315
1763
  if (!owner) continue;
1316
- for (const importRecord of collectImportsFromFile(filePath)) {
1317
- const resolvedFilePath = resolveInternalImport(importRecord.specifier, filePath, project.options);
1318
- if (isRelativeSpecifier(importRecord.specifier)) {
1764
+ for (const importRecord of collectImportsFromFile(filePath, config.rootDir)) {
1765
+ const resolvedFilePath = resolveInternalImport(importRecord.specifier, filePath, project.options, project.extensions);
1766
+ if (isRelativeSpecifier$1(importRecord.specifier)) {
1319
1767
  if (!resolvedFilePath) continue;
1320
1768
  const targetOwner = findOwnerForFile(resolvedFilePath, packageOwners);
1321
1769
  if (targetOwner?.packageJsonPath !== owner.packageJsonPath) addRelativeImportOwnerProblem({
@@ -1338,20 +1786,9 @@ async function runSourceCheckInternal(config, options = {}) {
1338
1786
  });
1339
1787
  continue;
1340
1788
  }
1341
- if (isUrlOrDataOrFileSpecifier(importRecord.specifier)) continue;
1789
+ if (isUrlOrDataOrFileSpecifier(importRecord.specifier) || isVirtualModuleSpecifier(importRecord.specifier)) continue;
1342
1790
  if (!isBarePackageSpecifier(importRecord.specifier)) continue;
1343
- if (isNodeBuiltinSpecifier(importRecord.specifier)) {
1344
- const deniedBuiltinRule = getDeniedNodeBuiltinRule(graphRules, project.label, importRecord.specifier);
1345
- if (deniedBuiltinRule) addNodeBuiltinDenyProblem({
1346
- config,
1347
- importRecord,
1348
- problems,
1349
- project,
1350
- reason: deniedBuiltinRule.reason,
1351
- ruleName: deniedBuiltinRule.matchAll ? "node:*" : deniedBuiltinRule.name
1352
- });
1353
- continue;
1354
- }
1791
+ if (isNodeBuiltinSpecifier(importRecord.specifier)) continue;
1355
1792
  const packageName = getPackageRootSpecifier(importRecord.specifier);
1356
1793
  if (owner.name === packageName) continue;
1357
1794
  const workspacePackage = packages.find((candidate) => candidate.name === packageName) ?? null;
@@ -1398,14 +1835,9 @@ async function runSourceCheck(config, options = {}) {
1398
1835
 
1399
1836
  //#endregion
1400
1837
  //#region src/commands/typecheck.ts
1401
- function normalizeConcurrency(value) {
1402
- if (value === void 0) return Math.max(1, availableParallelism());
1403
- if (!Number.isInteger(value) || value < 1) throw new Error("Typecheck concurrency must be a positive integer.");
1404
- return value;
1405
- }
1406
1838
  function getExecutionCheckers(options) {
1407
1839
  return options.checkers.filter((checker) => {
1408
- return getCheckerAdapter(checker.preset)?.supportedExecutions.includes(options.executionKind);
1840
+ return getCheckerAdapter(checker.preset)?.execution === options.executionKind;
1409
1841
  });
1410
1842
  }
1411
1843
  function collectCheckerPeerDependencyProblems(options) {
@@ -1427,49 +1859,14 @@ function createCheckerTarget(options) {
1427
1859
  executionKind: options.executionKind
1428
1860
  };
1429
1861
  }
1430
- function collectCompanionTypecheckTargets(options) {
1431
- const entryConfigPath = resolveProjectConfigPath(options.projectRootDir, options.checker.entry);
1432
- if (!existsSync(entryConfigPath)) return {
1433
- entryConfigPath,
1434
- problems: [[
1435
- "Checker entry references a missing tsconfig:",
1436
- ` checker: ${options.checker.name}`,
1437
- ` config: ${toRelativePath(options.projectRootDir, entryConfigPath)}`
1438
- ].join("\n")],
1439
- targetProjectPaths: []
1440
- };
1441
- const routeCollection = collectGraphProjectRouteFromRoot({
1442
- rootConfigPath: entryConfigPath,
1443
- rootDir: options.projectRootDir
1444
- });
1445
- const dtsConfigPaths = routeCollection.projectPaths.filter(isDtsConfigPath);
1446
- const targetProjectPaths = [...new Set(dtsConfigPaths.map(getDtsCompanionConfigPath))].sort();
1447
- const problems = [...routeCollection.problems];
1448
- if (dtsConfigPaths.length === 0) problems.push([
1449
- "Checker entry has no declaration leaf targets:",
1450
- ` checker: ${options.checker.name}`,
1451
- ` entry: ${toRelativePath(options.projectRootDir, entryConfigPath)}`,
1452
- " reason: checker:typecheck derives targets from tsconfig*.dts.json leaves reachable from the checker entry."
1453
- ].join("\n"));
1454
- for (const configPath of targetProjectPaths) {
1455
- if (existsSync(configPath)) continue;
1456
- problems.push([
1457
- "DTS leaf companion config is missing:",
1458
- ` checker: ${options.checker.name}`,
1459
- ` expected: ${toRelativePath(options.projectRootDir, configPath)}`,
1460
- " reason: checker:typecheck runs the strict local tsconfig companion for each reachable declaration leaf."
1461
- ].join("\n"));
1462
- }
1463
- return {
1464
- entryConfigPath,
1465
- problems,
1466
- targetProjectPaths
1467
- };
1468
- }
1469
1862
  function createDefaultRunner() {
1470
1863
  return async (target) => await new Promise((resolve) => {
1471
1864
  const child = spawn(target.command, target.args, {
1472
1865
  cwd: target.cwd,
1866
+ env: {
1867
+ ...process.env,
1868
+ PATH: [path.join(target.cwd, "node_modules/.bin"), process.env.PATH].filter(Boolean).join(path.delimiter)
1869
+ },
1473
1870
  shell: process.platform === "win32",
1474
1871
  stdio: "inherit"
1475
1872
  });
@@ -1514,138 +1911,106 @@ async function runWithConcurrency(targets, concurrency, runner, options = {}) {
1514
1911
  }));
1515
1912
  return results;
1516
1913
  }
1517
- async function runCheckerTypecheckInternal(options) {
1914
+ async function runCheckerBuildInternal(options) {
1518
1915
  const cwd = path.resolve(options.cwd ?? process.cwd());
1519
1916
  const projectRootDir = normalizeAbsolutePath(options.config.rootDir);
1520
1917
  const allCheckers = getActiveCheckers(options.config);
1521
1918
  const checkers = getExecutionCheckers({
1522
1919
  checkers: allCheckers,
1523
- executionKind: "typecheck"
1920
+ executionKind: "build"
1524
1921
  });
1525
1922
  const flowDepth = options.flowDepth ?? 0;
1526
- const concurrency = normalizeConcurrency(options.concurrency);
1923
+ const rootConfigPaths = [];
1527
1924
  const problems = collectCheckerPeerDependencyProblems({
1528
1925
  checkers: allCheckers,
1529
1926
  projectRootDir,
1530
1927
  resolvePackage: options.checkerPackageResolver
1531
1928
  });
1532
- const rootConfigPaths = [];
1533
- const targetProjectPaths = [];
1534
- const targets = [];
1535
1929
  if (problems.length > 0) {
1536
1930
  options.flow?.fail("checker dependency preflight failed", { depth: flowDepth + 1 });
1537
1931
  TypecheckLogger.error(problems.join("\n\n"));
1538
1932
  return {
1539
1933
  passed: false,
1540
1934
  projectRootDir,
1541
- results: [],
1542
- rootConfigPaths,
1543
- targetProjectPaths
1935
+ rootConfigPaths
1544
1936
  };
1545
1937
  }
1546
- if (checkers.length === 0) problems.push(["No checker typecheck entries configured:", " reason: configure config.checkers.<name>.entry with a preset that supports checker:typecheck."].join("\n"));
1547
- for (const checker of checkers) {
1548
- const targetCollection = collectCompanionTypecheckTargets({
1549
- checker,
1550
- projectRootDir
1551
- });
1552
- problems.push(...targetCollection.problems);
1553
- rootConfigPaths.push(targetCollection.entryConfigPath);
1554
- targetProjectPaths.push(...targetCollection.targetProjectPaths);
1555
- targets.push(...targetCollection.targetProjectPaths.map((configPath) => createCheckerTarget({
1938
+ const targets = checkers.flatMap((checker) => {
1939
+ const configPath = resolveProjectConfigPath(projectRootDir, checker.entry);
1940
+ rootConfigPaths.push(configPath);
1941
+ return [createCheckerTarget({
1556
1942
  checker,
1557
1943
  commandOverride: options.tscCommand,
1558
1944
  configPath,
1559
- executionKind: "typecheck",
1945
+ executionKind: "build",
1560
1946
  projectRootDir
1561
- })));
1562
- }
1563
- if (problems.length > 0) {
1564
- options.flow?.fail("typecheck target discovery failed", { depth: flowDepth + 1 });
1565
- TypecheckLogger.error(problems.join("\n\n"));
1566
- return {
1567
- passed: false,
1568
- projectRootDir,
1569
- results: [],
1570
- rootConfigPaths,
1571
- targetProjectPaths
1572
- };
1573
- }
1574
- options.flow?.info(`found ${targets.length} typecheck target config(s) across ${checkers.length} checker(s); concurrency ${concurrency}`, { depth: flowDepth + 1 });
1947
+ })];
1948
+ });
1949
+ options.flow?.info(`found ${targets.length} checker build entry(s)`, { depth: flowDepth + 1 });
1575
1950
  TypecheckLogger.info([
1576
- `Running checker typechecks for ${targets.length} target config(s).`,
1951
+ `Running build checks for ${targets.length} checker entry(s).`,
1577
1952
  `CWD: ${toRelativePath(cwd, projectRootDir)}`,
1578
1953
  `Entries: ${rootConfigPaths.map((configPath) => toRelativePath(projectRootDir, configPath)).join(", ")}`
1579
1954
  ].join("\n"));
1580
- const targetFlowStates = /* @__PURE__ */ new Map();
1581
- const results = await runWithConcurrency(targets, concurrency, options.runner ?? createDefaultRunner(), {
1955
+ const targetTasks = /* @__PURE__ */ new Map();
1956
+ const failedResults = (await runWithConcurrency(targets, 1, options.runner ?? createDefaultRunner(), {
1582
1957
  onTargetResult: (target, result) => {
1583
- if (!options.flow) return;
1584
- const flowState = targetFlowStates.get(target.configPath);
1585
- if (!flowState) return;
1586
- const resultOptions = {
1587
- depth: flowDepth + 1,
1588
- elapsedTimeMs: performance.now() - flowState.startedAt
1589
- };
1590
- if (result.status === 0) options.flow.pass(flowState.label, resultOptions);
1958
+ const task = targetTasks.get(target.configPath);
1959
+ if (!task) return;
1960
+ if (result.status === 0) task.pass();
1591
1961
  else {
1592
1962
  const suffix = result.error ? formatErrorMessage$1(result.error) : `exited with code ${result.status}`;
1593
- options.flow.fail(flowState.label, {
1594
- ...resultOptions,
1595
- error: suffix
1596
- });
1963
+ task.fail(void 0, { error: suffix });
1597
1964
  }
1598
1965
  },
1599
1966
  onTargetStart: (target) => {
1600
1967
  if (!options.flow) return;
1601
- targetFlowStates.set(target.configPath, {
1602
- label: target.label ?? `checker: ${toRelativePath(projectRootDir, target.configPath)}`,
1603
- startedAt: performance.now()
1604
- });
1968
+ targetTasks.set(target.configPath, options.flow.start(target.label ?? `checker build: ${toRelativePath(projectRootDir, target.configPath)}`, {
1969
+ collapseOnSuccess: false,
1970
+ depth: flowDepth + 1
1971
+ }));
1605
1972
  }
1606
- });
1607
- const failedResults = results.filter((result) => result.status !== 0);
1608
- if (failedResults.length > 0) TypecheckLogger.error([`Typecheck failed for ${failedResults.length} config(s):`, ...failedResults.map((result) => {
1973
+ })).filter((result) => result.status !== 0);
1974
+ const passed = failedResults.length === 0;
1975
+ if (!passed) TypecheckLogger.error(["build checks failed:", ...failedResults.map((result) => {
1609
1976
  const suffix = result.error ? `: ${formatErrorMessage$1(result.error)}` : ` exited with code ${result.status}`;
1610
1977
  return ` ${toRelativePath(projectRootDir, result.configPath)}${suffix}`;
1611
1978
  })].join("\n"));
1612
- else if (!options.flow?.interactive) TypecheckLogger.success(`Checked ${targets.length} typecheck target config(s) from ${rootConfigPaths.length} checker entry(s).`);
1979
+ else if (!options.flow?.interactive) TypecheckLogger.success(`Checked ${targets.length} checker build entry(s).`);
1613
1980
  return {
1614
- passed: failedResults.length === 0,
1981
+ passed,
1615
1982
  projectRootDir,
1616
- results,
1617
- rootConfigPaths,
1618
- targetProjectPaths
1983
+ rootConfigPaths
1619
1984
  };
1620
1985
  }
1621
- async function runCheckerTypecheck(options) {
1986
+ async function runCheckerBuild(options) {
1622
1987
  if (options.clearScreen ?? true) clearCliScreen();
1623
1988
  const elapsed = createElapsedTimer();
1624
- const task = options.flow?.start("checker typecheck", { depth: options.flowDepth ?? 0 });
1625
- TypecheckLogger.info("checker typecheck started");
1989
+ const task = options.flow?.start("checker build", { depth: options.flowDepth ?? 0 });
1990
+ TypecheckLogger.info("checker build started");
1626
1991
  try {
1627
- const result = await runCheckerTypecheckInternal(options);
1992
+ const result = await runCheckerBuildInternal(options);
1628
1993
  if (result.passed) {
1629
- if (!options.flow?.interactive) TypecheckLogger.success("checker typecheck finished", elapsed());
1994
+ if (!options.flow?.interactive) TypecheckLogger.success("checker build finished", elapsed());
1630
1995
  task?.pass();
1631
1996
  } else {
1632
- TypecheckLogger.error("checker typecheck finished with failures", elapsed());
1633
- task?.fail("checker typecheck finished with failures");
1997
+ TypecheckLogger.error("checker build finished with failures", elapsed());
1998
+ task?.fail("checker build finished with failures");
1634
1999
  }
1635
2000
  return result;
1636
2001
  } catch (error) {
1637
- TypecheckLogger.error(`checker typecheck failed: ${formatErrorMessage$1(error)}`, elapsed());
1638
- task?.fail("checker typecheck failed", { error });
2002
+ TypecheckLogger.error(`checker build failed: ${formatErrorMessage$1(error)}`, elapsed());
2003
+ task?.fail("checker build failed", { error });
1639
2004
  throw error;
1640
2005
  }
1641
2006
  }
1642
- async function runCheckerBuildInternal(options) {
2007
+ async function runCheckerTypecheckInternal(options) {
1643
2008
  const cwd = path.resolve(options.cwd ?? process.cwd());
1644
2009
  const projectRootDir = normalizeAbsolutePath(options.config.rootDir);
1645
2010
  const allCheckers = getActiveCheckers(options.config);
1646
2011
  const checkers = getExecutionCheckers({
1647
2012
  checkers: allCheckers,
1648
- executionKind: "build"
2013
+ executionKind: "typecheck"
1649
2014
  });
1650
2015
  const flowDepth = options.flowDepth ?? 0;
1651
2016
  const rootConfigPaths = [];
@@ -1663,20 +2028,29 @@ async function runCheckerBuildInternal(options) {
1663
2028
  rootConfigPaths
1664
2029
  };
1665
2030
  }
1666
- const targets = checkers.flatMap((checker) => {
2031
+ const targets = checkers.map((checker) => {
1667
2032
  const configPath = resolveProjectConfigPath(projectRootDir, checker.entry);
1668
2033
  rootConfigPaths.push(configPath);
1669
- return [createCheckerTarget({
2034
+ return createCheckerTarget({
1670
2035
  checker,
1671
2036
  commandOverride: options.tscCommand,
1672
2037
  configPath,
1673
- executionKind: "build",
2038
+ executionKind: "typecheck",
1674
2039
  projectRootDir
1675
- })];
2040
+ });
1676
2041
  });
1677
- options.flow?.info(`found ${targets.length} checker build entry(s)`, { depth: flowDepth + 1 });
2042
+ if (targets.length === 0) {
2043
+ options.flow?.info("no source-only checker entries configured", { depth: flowDepth + 1 });
2044
+ if (!options.flow?.interactive) TypecheckLogger.success("No source-only checker entries configured.");
2045
+ return {
2046
+ passed: true,
2047
+ projectRootDir,
2048
+ rootConfigPaths
2049
+ };
2050
+ }
2051
+ options.flow?.info(`found ${targets.length} checker typecheck entry(s)`, { depth: flowDepth + 1 });
1678
2052
  TypecheckLogger.info([
1679
- `Running build checks for ${targets.length} checker entry(s).`,
2053
+ `Running typecheck for ${targets.length} checker entry(s).`,
1680
2054
  `CWD: ${toRelativePath(cwd, projectRootDir)}`,
1681
2055
  `Entries: ${rootConfigPaths.map((configPath) => toRelativePath(projectRootDir, configPath)).join(", ")}`
1682
2056
  ].join("\n"));
@@ -1693,42 +2067,42 @@ async function runCheckerBuildInternal(options) {
1693
2067
  },
1694
2068
  onTargetStart: (target) => {
1695
2069
  if (!options.flow) return;
1696
- targetTasks.set(target.configPath, options.flow.start(target.label ?? `checker build: ${toRelativePath(projectRootDir, target.configPath)}`, {
2070
+ targetTasks.set(target.configPath, options.flow.start(target.label ?? `checker typecheck: ${toRelativePath(projectRootDir, target.configPath)}`, {
1697
2071
  collapseOnSuccess: false,
1698
2072
  depth: flowDepth + 1
1699
2073
  }));
1700
2074
  }
1701
2075
  })).filter((result) => result.status !== 0);
1702
2076
  const passed = failedResults.length === 0;
1703
- if (!passed) TypecheckLogger.error(["build checks failed:", ...failedResults.map((result) => {
2077
+ if (!passed) TypecheckLogger.error(["typecheck checks failed:", ...failedResults.map((result) => {
1704
2078
  const suffix = result.error ? `: ${formatErrorMessage$1(result.error)}` : ` exited with code ${result.status}`;
1705
2079
  return ` ${toRelativePath(projectRootDir, result.configPath)}${suffix}`;
1706
2080
  })].join("\n"));
1707
- else if (!options.flow?.interactive) TypecheckLogger.success(`Checked ${targets.length} checker build entry(s).`);
2081
+ else if (!options.flow?.interactive) TypecheckLogger.success(`Checked ${targets.length} checker typecheck entry(s).`);
1708
2082
  return {
1709
2083
  passed,
1710
2084
  projectRootDir,
1711
2085
  rootConfigPaths
1712
2086
  };
1713
2087
  }
1714
- async function runCheckerBuild(options) {
2088
+ async function runCheckerTypecheck(options) {
1715
2089
  if (options.clearScreen ?? true) clearCliScreen();
1716
2090
  const elapsed = createElapsedTimer();
1717
- const task = options.flow?.start("checker build", { depth: options.flowDepth ?? 0 });
1718
- TypecheckLogger.info("checker build started");
2091
+ const task = options.flow?.start("checker typecheck", { depth: options.flowDepth ?? 0 });
2092
+ TypecheckLogger.info("checker typecheck started");
1719
2093
  try {
1720
- const result = await runCheckerBuildInternal(options);
2094
+ const result = await runCheckerTypecheckInternal(options);
1721
2095
  if (result.passed) {
1722
- if (!options.flow?.interactive) TypecheckLogger.success("checker build finished", elapsed());
2096
+ if (!options.flow?.interactive) TypecheckLogger.success("checker typecheck finished", elapsed());
1723
2097
  task?.pass();
1724
2098
  } else {
1725
- TypecheckLogger.error("checker build finished with failures", elapsed());
1726
- task?.fail("checker build finished with failures");
2099
+ TypecheckLogger.error("checker typecheck finished with failures", elapsed());
2100
+ task?.fail("checker typecheck finished with failures");
1727
2101
  }
1728
2102
  return result;
1729
2103
  } catch (error) {
1730
- TypecheckLogger.error(`checker build failed: ${formatErrorMessage$1(error)}`, elapsed());
1731
- task?.fail("checker build failed", { error });
2104
+ TypecheckLogger.error(`checker typecheck failed: ${formatErrorMessage$1(error)}`, elapsed());
2105
+ task?.fail("checker typecheck failed", { error });
1732
2106
  throw error;
1733
2107
  }
1734
2108
  }
@@ -2023,4 +2397,4 @@ function createLiminaFlowReporter(options = {}) {
2023
2397
  }
2024
2398
 
2025
2399
  //#endregion
2026
- export { collectImporters as A, createFormatHost as B, inferPackageProject as C, parseProject as D, isWorkspacePackageFile as E, collectGraphProjectRoute as F, isOrdinaryTypecheckConfigPath as G, getDtsCompanionConfigPath as H, collectGraphProjectRouteFromRoot as I, readJsonConfig as J, parseProjectFileNames as K, collectGraphProjectRoutes as L, findPackageForSpecifier as M, getPackageRootSpecifier as N, resolveInternalImport as O, collectCheckerEntryProjectRoutes as P, collectTypecheckTargetProjectPaths as R, getTypecheckConfigPath as S, isRelativeSpecifier as T, getRawReferencePaths as U, formatReferences as V, isDtsConfigPath as W, resolveReferencePath as X, resolveProjectConfigPath as Y, createFileOwnerLookup as _, runSourceCheck as a, findTargetProject as b, PackageLogger as c, clearCliScreen as d, formatErrorMessage$1 as f, collectImportsFromFile as g, normalizeGraphRules as h, runCheckerTypecheck as i, collectWorkspacePackages as j, shouldResolveThroughGraph as k, PathsLogger as l, getDeniedWorkspaceDepRule as m, createLiminaFlowReporter as n, CliLogger as o, getDeniedRefRule as p, parseProjectFileNamesForExtensions as q, runCheckerBuild as r, GraphLogger as s, LiminaFlowReporter as t, ProofLogger as u, findImporterForFile as v, isDtsProjectConfig as w, formatArtifactDependencyPolicy as x, findPackageForFile as y, createExtensionPattern as z };
2400
+ export { shouldResolveThroughGraph as A, collectGraphProjectRoutes as B, formatArtifactDependencyPolicy as C, isRelativeSpecifier$1 as D, isDtsProjectConfig as E, getPublishDependencySections as F, formatReferences as G, createExtensionPattern as H, isWorkspaceDependencySpecifier as I, isOrdinaryTypecheckConfigPath as J, getDtsCompanionConfigPath as K, collectCheckerEntryProjectRoutes as L, collectWorkspacePackages as M, findPackageForSpecifier as N, parseProject as O, getPackageRootSpecifier as P, resolveReferencePath as Q, collectGraphProjectRoute as R, findTargetProject as S, inferPackageProject as T, createExtraFileExtensions as U, collectSourceGraphProjectExtensions as V, createFormatHost as W, readJsonConfig as X, parseProjectFileNamesForExtensions as Y, resolveProjectConfigPath as Z, normalizeGraphRules as _, runSourceCheck as a, findImporterForFile as b, GraphLogger as c, ProofLogger as d, clearCliScreen as f, getDeniedRefRule as g, getDeniedDepRuleForSpecifier as h, runCheckerTypecheck as i, collectImporters as j, resolveInternalImport as k, PackageLogger as l, getDeniedDepRuleForPackage as m, createLiminaFlowReporter as n, runInit as o, formatErrorMessage$1 as p, getRawReferencePaths as q, runCheckerBuild as r, CliLogger as s, LiminaFlowReporter as t, PathsLogger as u, collectImportsFromFile as v, getTypecheckConfigPath as w, findPackageForFile as x, createFileOwnerLookup as y, collectGraphProjectRouteFromRoot as z };