limina 0.0.1 → 0.0.2
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.
- package/LICENSE.md +21 -0
- package/README.md +384 -0
- package/bin/limina.js +0 -0
- package/chunks/{dep-DoSHsBSP.js → dep-uPXyoC0V.js} +654 -206
- package/cli.js +225 -150
- package/config.d.ts +7 -41
- package/index.d.ts +20 -2
- package/index.js +2 -2
- package/package.json +14 -2
|
@@ -1,20 +1,21 @@
|
|
|
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 "
|
|
1
|
+
import { c as getCheckerAdapter, h as toRelativePath, l as isPathInsideDirectory, m as toPosixPath, o as collectMissingCheckerPeerDependencies, r as getActiveCheckers, s as formatMissingCheckerPeerDependencies, u as normalizeAbsolutePath } from "./dep-jgc7X0zw.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 "
|
|
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";
|
|
14
|
+
import { availableParallelism } from "node:os";
|
|
13
15
|
|
|
14
16
|
//#region src/tsconfig.ts
|
|
15
17
|
const dtsConfigFilePattern = /^tsconfig(?:\..+)?\.dts\.json$/u;
|
|
16
18
|
const buildGraphConfigFilePattern = /^tsconfig(?:\..+)?\.build\.json$/u;
|
|
17
|
-
const deprecatedGraphConfigFilePattern = /^tsconfig(?:\..+)?\.graph\.json$/u;
|
|
18
19
|
const generatedConfigFilePattern = /^tsconfig(?:\..+)?\.paths\.generated\.json$/u;
|
|
19
20
|
const baseConfigFilePattern = /^tsconfig(?:\..+)?\.base\.json$/u;
|
|
20
21
|
const checkConfigFilePattern = /^tsconfig(?:\..+)?\.check\.json$/u;
|
|
@@ -161,11 +162,8 @@ function getDtsCompanionConfigPath(dtsConfigPath) {
|
|
|
161
162
|
function isBuildGraphConfigPath(configPath) {
|
|
162
163
|
return buildGraphConfigFilePattern.test(path.basename(configPath));
|
|
163
164
|
}
|
|
164
|
-
function isDeprecatedGraphConfigPath(configPath) {
|
|
165
|
-
return deprecatedGraphConfigFilePattern.test(path.basename(configPath));
|
|
166
|
-
}
|
|
167
165
|
function isReservedTypeScriptConfigFile(fileName) {
|
|
168
|
-
return dtsConfigFilePattern.test(fileName) || buildGraphConfigFilePattern.test(fileName) ||
|
|
166
|
+
return dtsConfigFilePattern.test(fileName) || buildGraphConfigFilePattern.test(fileName) || generatedConfigFilePattern.test(fileName) || baseConfigFilePattern.test(fileName) || checkConfigFilePattern.test(fileName);
|
|
169
167
|
}
|
|
170
168
|
function isOrdinaryTypecheckConfigPath(configPath) {
|
|
171
169
|
const fileName = path.basename(configPath);
|
|
@@ -269,13 +267,7 @@ function collectGraphProjectRouteFromRoot(options) {
|
|
|
269
267
|
}));
|
|
270
268
|
const formatConfigPath = (configPath) => toRelativePath(options.rootDir, configPath);
|
|
271
269
|
problems.push(...rootReferences.problems);
|
|
272
|
-
if (
|
|
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([
|
|
270
|
+
if (!isBuildGraphConfigPath(rootGraphConfigPath) && !isDtsConfigPath(rootGraphConfigPath)) problems.push([
|
|
279
271
|
"Invalid checker entry config:",
|
|
280
272
|
` config: ${formatConfigPath(rootGraphConfigPath)}`,
|
|
281
273
|
" reason: checker entries should point to a tsconfig*.build.json graph aggregator or a direct tsconfig*.dts.json declaration leaf."
|
|
@@ -287,17 +279,6 @@ function collectGraphProjectRouteFromRoot(options) {
|
|
|
287
279
|
for (const { projectPath } of queue) seen.add(projectPath);
|
|
288
280
|
for (const { projectPath, rawReferencePath, referrerPath } of queue) {
|
|
289
281
|
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
282
|
if (!existsSync(projectPath)) {
|
|
302
283
|
problems.push([
|
|
303
284
|
"Checker entry references a missing tsconfig:",
|
|
@@ -343,16 +324,6 @@ function collectGraphProjectRoutes(config) {
|
|
|
343
324
|
for (const checker of getActiveCheckers(config)) {
|
|
344
325
|
if (!getCheckerAdapter(checker.preset)?.graph) continue;
|
|
345
326
|
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
327
|
if (!existsSync(rootConfigPath)) {
|
|
357
328
|
problems.push([
|
|
358
329
|
"Checker graph entry references a missing tsconfig:",
|
|
@@ -382,16 +353,6 @@ function collectCheckerEntryProjectRoutes(config) {
|
|
|
382
353
|
const problems = [];
|
|
383
354
|
for (const checker of getActiveCheckers(config)) {
|
|
384
355
|
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
356
|
if (!existsSync(rootConfigPath)) {
|
|
396
357
|
problems.push([
|
|
397
358
|
"Checker entry references a missing tsconfig:",
|
|
@@ -441,7 +402,7 @@ function formatReferences(rootDir, references) {
|
|
|
441
402
|
|
|
442
403
|
//#endregion
|
|
443
404
|
//#region src/workspace.ts
|
|
444
|
-
const pnpmWorkspaceFileName = "pnpm-workspace.yaml";
|
|
405
|
+
const pnpmWorkspaceFileName$1 = "pnpm-workspace.yaml";
|
|
445
406
|
const pnpmWorkspaceListTimeoutMs = 3e3;
|
|
446
407
|
function readJsonFile(filePath) {
|
|
447
408
|
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
@@ -488,7 +449,7 @@ function collectWorkspacePatterns(config) {
|
|
|
488
449
|
const rootPackageJson = readJsonFile(rootPackageJsonPath);
|
|
489
450
|
if (Array.isArray(rootPackageJson.workspaces)) for (const pattern of rootPackageJson.workspaces) patterns.add(pattern);
|
|
490
451
|
}
|
|
491
|
-
const workspacePath = path.join(config.rootDir, pnpmWorkspaceFileName);
|
|
452
|
+
const workspacePath = path.join(config.rootDir, pnpmWorkspaceFileName$1);
|
|
492
453
|
if (existsSync(workspacePath)) for (const pattern of collectPnpmWorkspacePatterns(readFileSync(workspacePath, "utf8"))) patterns.add(pattern);
|
|
493
454
|
return [...patterns].sort();
|
|
494
455
|
}
|
|
@@ -663,7 +624,7 @@ function collectImporters(config, packages) {
|
|
|
663
624
|
|
|
664
625
|
//#endregion
|
|
665
626
|
//#region src/graph-context.ts
|
|
666
|
-
function isRelativeSpecifier(specifier) {
|
|
627
|
+
function isRelativeSpecifier$1(specifier) {
|
|
667
628
|
return specifier === "." || specifier === ".." || specifier.startsWith("./") || specifier.startsWith("../");
|
|
668
629
|
}
|
|
669
630
|
function isDtsProjectConfig(configPath) {
|
|
@@ -779,9 +740,6 @@ function chooseOwningProject(projectPaths) {
|
|
|
779
740
|
function findPackageForFile(filePath, packages) {
|
|
780
741
|
return [...packages].sort((left, right) => right.directory.length - left.directory.length).find((workspacePackage) => isPathInsideDirectory(filePath, workspacePackage.directory)) ?? null;
|
|
781
742
|
}
|
|
782
|
-
function isWorkspacePackageFile(filePath, packages) {
|
|
783
|
-
return packages.some((workspacePackage) => isPathInsideDirectory(filePath, workspacePackage.directory));
|
|
784
|
-
}
|
|
785
743
|
function findImporterForFile(filePath, importers) {
|
|
786
744
|
return importers.find((importer) => isPathInsideDirectory(filePath, importer.directory)) ?? null;
|
|
787
745
|
}
|
|
@@ -834,6 +792,60 @@ function formatUnknownValue(value) {
|
|
|
834
792
|
function addRuleEntryConfigProblem(problems, details) {
|
|
835
793
|
problems.push(["Invalid graph rule config:", ...details].join("\n"));
|
|
836
794
|
}
|
|
795
|
+
function isUrlOrDataOrFileSpecifier$1(specifier) {
|
|
796
|
+
return specifier.startsWith("data:") || specifier.startsWith("file:") || specifier.startsWith("http:") || specifier.startsWith("https:");
|
|
797
|
+
}
|
|
798
|
+
function isRelativeSpecifier(specifier) {
|
|
799
|
+
return specifier === "." || specifier === ".." || specifier.startsWith("./") || specifier.startsWith("../");
|
|
800
|
+
}
|
|
801
|
+
function isPackageImportPattern(name) {
|
|
802
|
+
return name.startsWith("#");
|
|
803
|
+
}
|
|
804
|
+
function matchWildcardPattern(pattern, value) {
|
|
805
|
+
if (pattern === value) return true;
|
|
806
|
+
const wildcardIndex = pattern.indexOf("*");
|
|
807
|
+
if (wildcardIndex === -1) return false;
|
|
808
|
+
const prefix = pattern.slice(0, wildcardIndex);
|
|
809
|
+
const suffix = pattern.slice(wildcardIndex + 1);
|
|
810
|
+
return value.startsWith(prefix) && value.endsWith(suffix);
|
|
811
|
+
}
|
|
812
|
+
function getNodeBuiltinRuleName(name) {
|
|
813
|
+
if (name === "node:*") return {
|
|
814
|
+
matchAllNodeBuiltins: true,
|
|
815
|
+
normalizedName: "*"
|
|
816
|
+
};
|
|
817
|
+
const normalizedName = name.startsWith("node:") ? name.slice(5) : name;
|
|
818
|
+
if (!nodeBuiltinNames.has(normalizedName)) return null;
|
|
819
|
+
return {
|
|
820
|
+
matchAllNodeBuiltins: false,
|
|
821
|
+
normalizedName
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
function createNormalizedDep(name, reason) {
|
|
825
|
+
const nodeBuiltin = getNodeBuiltinRuleName(name);
|
|
826
|
+
if (nodeBuiltin) return {
|
|
827
|
+
kind: "node-builtin",
|
|
828
|
+
matchAllNodeBuiltins: nodeBuiltin.matchAllNodeBuiltins,
|
|
829
|
+
name,
|
|
830
|
+
normalizedName: nodeBuiltin.normalizedName,
|
|
831
|
+
reason
|
|
832
|
+
};
|
|
833
|
+
if (isPackageImportPattern(name)) return {
|
|
834
|
+
kind: "package-import",
|
|
835
|
+
matchAllNodeBuiltins: false,
|
|
836
|
+
name,
|
|
837
|
+
normalizedName: name,
|
|
838
|
+
reason
|
|
839
|
+
};
|
|
840
|
+
if (isRelativeSpecifier(name) || isUrlOrDataOrFileSpecifier$1(name) || path.isAbsolute(name) || getPackageRootSpecifier(name) !== name) return null;
|
|
841
|
+
return {
|
|
842
|
+
kind: "package",
|
|
843
|
+
matchAllNodeBuiltins: false,
|
|
844
|
+
name,
|
|
845
|
+
normalizedName: name,
|
|
846
|
+
reason
|
|
847
|
+
};
|
|
848
|
+
}
|
|
837
849
|
function getRulesRecord(config, problems) {
|
|
838
850
|
const rules = config.graph?.rules;
|
|
839
851
|
if (rules === void 0) return {};
|
|
@@ -900,57 +912,13 @@ function addNormalizedRuleRef(options) {
|
|
|
900
912
|
});
|
|
901
913
|
options.refsByLabel.set(options.label, refs);
|
|
902
914
|
}
|
|
903
|
-
function
|
|
904
|
-
const field =
|
|
905
|
-
if (!isPlainRecord(options.entry)) {
|
|
906
|
-
addRuleEntryConfigProblem(options.problems, [
|
|
907
|
-
` field: ${field}`,
|
|
908
|
-
` value: ${formatUnknownValue(options.entry)}`,
|
|
909
|
-
" reason: deny workspace dependency entries must be objects with non-empty name and reason fields."
|
|
910
|
-
]);
|
|
911
|
-
return;
|
|
912
|
-
}
|
|
913
|
-
const nameValue = options.entry.name;
|
|
914
|
-
const reasonValue = options.entry.reason;
|
|
915
|
-
if (!isNonEmptyString(nameValue)) {
|
|
916
|
-
addRuleEntryConfigProblem(options.problems, [
|
|
917
|
-
` field: ${field}.name`,
|
|
918
|
-
` value: ${formatUnknownValue(nameValue)}`,
|
|
919
|
-
" reason: workspace dependency name is required and must be a non-empty string."
|
|
920
|
-
]);
|
|
921
|
-
return;
|
|
922
|
-
}
|
|
923
|
-
if (!isNonEmptyString(reasonValue)) {
|
|
924
|
-
addRuleEntryConfigProblem(options.problems, [
|
|
925
|
-
` field: ${field}.reason`,
|
|
926
|
-
` 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}]`;
|
|
915
|
+
function addNormalizedDep(options) {
|
|
916
|
+
const field = `graph.rules.${options.label}.deny.deps[${options.index}]`;
|
|
949
917
|
if (!isPlainRecord(options.entry)) {
|
|
950
918
|
addRuleEntryConfigProblem(options.problems, [
|
|
951
919
|
` field: ${field}`,
|
|
952
920
|
` value: ${formatUnknownValue(options.entry)}`,
|
|
953
|
-
" reason: deny.
|
|
921
|
+
" reason: deny.deps entries must be objects with non-empty name and reason fields."
|
|
954
922
|
]);
|
|
955
923
|
return;
|
|
956
924
|
}
|
|
@@ -960,7 +928,7 @@ function addNormalizedNodeBuiltin(options) {
|
|
|
960
928
|
addRuleEntryConfigProblem(options.problems, [
|
|
961
929
|
` field: ${field}.name`,
|
|
962
930
|
` value: ${formatUnknownValue(nameValue)}`,
|
|
963
|
-
" reason: deny.
|
|
931
|
+
" reason: deny.deps name is required and must be a non-empty string."
|
|
964
932
|
]);
|
|
965
933
|
return;
|
|
966
934
|
}
|
|
@@ -968,38 +936,31 @@ function addNormalizedNodeBuiltin(options) {
|
|
|
968
936
|
addRuleEntryConfigProblem(options.problems, [
|
|
969
937
|
` field: ${field}.reason`,
|
|
970
938
|
` value: ${formatUnknownValue(reasonValue)}`,
|
|
971
|
-
" reason: deny.
|
|
939
|
+
" reason: deny.deps reason is required and must be a non-empty string."
|
|
972
940
|
]);
|
|
973
941
|
return;
|
|
974
942
|
}
|
|
975
943
|
const name = nameValue.trim();
|
|
976
|
-
const
|
|
977
|
-
|
|
978
|
-
if (!matchAll && !nodeBuiltinNames.has(normalizedName)) {
|
|
944
|
+
const normalizedDep = createNormalizedDep(name, reasonValue.trim());
|
|
945
|
+
if (!normalizedDep) {
|
|
979
946
|
addRuleEntryConfigProblem(options.problems, [
|
|
980
947
|
` field: ${field}.name`,
|
|
981
948
|
` name: ${name}`,
|
|
982
|
-
" reason: deny.
|
|
949
|
+
" 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
950
|
]);
|
|
984
951
|
return;
|
|
985
952
|
}
|
|
986
|
-
const
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
name: normalizedName,
|
|
990
|
-
reason: reasonValue.trim()
|
|
991
|
-
});
|
|
992
|
-
options.nodeBuiltinsByLabel.set(options.label, entries);
|
|
953
|
+
const deps = options.depsByLabel.get(options.label) ?? [];
|
|
954
|
+
deps.push(normalizedDep);
|
|
955
|
+
options.depsByLabel.set(options.label, deps);
|
|
993
956
|
}
|
|
994
957
|
function shouldNormalizeRuleKind(include, kind) {
|
|
995
958
|
return include?.[kind] ?? true;
|
|
996
959
|
}
|
|
997
960
|
function normalizeGraphRules(options) {
|
|
961
|
+
const depsByLabel = /* @__PURE__ */ new Map();
|
|
998
962
|
const refsByLabel = /* @__PURE__ */ new Map();
|
|
999
|
-
const workspaceDepsByLabel = /* @__PURE__ */ new Map();
|
|
1000
|
-
const nodeBuiltinsByLabel = /* @__PURE__ */ new Map();
|
|
1001
963
|
const projectPathSet = new Set(options.projectPaths);
|
|
1002
|
-
const packageNames = new Set(options.packages.map((workspacePackage) => workspacePackage.name));
|
|
1003
964
|
for (const [rawLabel, rawRule] of Object.entries(getRulesRecord(options.config, options.problems))) {
|
|
1004
965
|
const label = rawLabel.trim();
|
|
1005
966
|
if (!label) {
|
|
@@ -1040,60 +1001,35 @@ function normalizeGraphRules(options) {
|
|
|
1040
1001
|
refsByLabel
|
|
1041
1002
|
});
|
|
1042
1003
|
});
|
|
1043
|
-
|
|
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, [
|
|
1004
|
+
if (shouldNormalizeRuleKind(options.include, "deps") && rawRule.deny.workspaceDeps !== void 0) addRuleEntryConfigProblem(options.problems, [
|
|
1062
1005
|
` field: graph.rules.${label}.deny.workspaceDeps`,
|
|
1063
|
-
` value: ${formatUnknownValue(workspaceDeps)}`,
|
|
1064
|
-
" reason: deny.workspaceDeps
|
|
1006
|
+
` value: ${formatUnknownValue(rawRule.deny.workspaceDeps)}`,
|
|
1007
|
+
" reason: deny.workspaceDeps has been removed; use deny.deps."
|
|
1065
1008
|
]);
|
|
1066
|
-
|
|
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, [
|
|
1009
|
+
if (shouldNormalizeRuleKind(options.include, "deps") && rawRule.deny.nodeBuiltins !== void 0) addRuleEntryConfigProblem(options.problems, [
|
|
1079
1010
|
` field: graph.rules.${label}.deny.nodeBuiltins`,
|
|
1080
|
-
` value: ${formatUnknownValue(nodeBuiltins)}`,
|
|
1081
|
-
" reason: deny.nodeBuiltins
|
|
1011
|
+
` value: ${formatUnknownValue(rawRule.deny.nodeBuiltins)}`,
|
|
1012
|
+
" reason: deny.nodeBuiltins has been removed; use deny.deps."
|
|
1082
1013
|
]);
|
|
1083
|
-
|
|
1084
|
-
|
|
1014
|
+
const deps = rawRule.deny.deps;
|
|
1015
|
+
if (shouldNormalizeRuleKind(options.include, "deps") && deps !== void 0) if (!Array.isArray(deps)) addRuleEntryConfigProblem(options.problems, [
|
|
1016
|
+
` field: graph.rules.${label}.deny.deps`,
|
|
1017
|
+
` value: ${formatUnknownValue(deps)}`,
|
|
1018
|
+
" reason: deny.deps must be an array."
|
|
1019
|
+
]);
|
|
1020
|
+
else deps.forEach((entry, index) => {
|
|
1021
|
+
addNormalizedDep({
|
|
1022
|
+
depsByLabel,
|
|
1085
1023
|
entry,
|
|
1086
1024
|
index,
|
|
1087
1025
|
label,
|
|
1088
|
-
nodeBuiltinsByLabel,
|
|
1089
1026
|
problems: options.problems
|
|
1090
1027
|
});
|
|
1091
1028
|
});
|
|
1092
1029
|
}
|
|
1093
1030
|
return {
|
|
1094
|
-
|
|
1095
|
-
refsByLabel
|
|
1096
|
-
workspaceDepsByLabel
|
|
1031
|
+
depsByLabel,
|
|
1032
|
+
refsByLabel
|
|
1097
1033
|
};
|
|
1098
1034
|
}
|
|
1099
1035
|
function isNodeBuiltinSpecifier(specifier) {
|
|
@@ -1103,14 +1039,24 @@ function getDeniedRefRule(rules, label, targetProjectPath) {
|
|
|
1103
1039
|
if (!label) return null;
|
|
1104
1040
|
return rules.refsByLabel.get(label)?.get(targetProjectPath) ?? null;
|
|
1105
1041
|
}
|
|
1106
|
-
function
|
|
1107
|
-
if (!label) return
|
|
1108
|
-
return rules.
|
|
1109
|
-
}
|
|
1110
|
-
function
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1042
|
+
function getRuleDeps(rules, label) {
|
|
1043
|
+
if (!label) return [];
|
|
1044
|
+
return rules.depsByLabel.get(label) ?? [];
|
|
1045
|
+
}
|
|
1046
|
+
function getDeniedDepRuleForPackage(rules, label, packageName) {
|
|
1047
|
+
return getRuleDeps(rules, label).find((rule) => rule.kind === "package" && rule.normalizedName === packageName) ?? null;
|
|
1048
|
+
}
|
|
1049
|
+
function getDeniedDepRuleForSpecifier(rules, label, specifier) {
|
|
1050
|
+
const deps = getRuleDeps(rules, label);
|
|
1051
|
+
const packageImportRule = deps.find((rule) => rule.kind === "package-import" && matchWildcardPattern(rule.normalizedName, specifier));
|
|
1052
|
+
if (packageImportRule) return packageImportRule;
|
|
1053
|
+
if (isNodeBuiltinSpecifier(specifier)) {
|
|
1054
|
+
const normalizedSpecifier = specifier.startsWith("node:") ? specifier.slice(5) : specifier;
|
|
1055
|
+
const nodeRule = deps.find((rule) => rule.kind === "node-builtin" && (rule.matchAllNodeBuiltins || rule.normalizedName === normalizedSpecifier));
|
|
1056
|
+
if (nodeRule) return nodeRule;
|
|
1057
|
+
}
|
|
1058
|
+
if (isRelativeSpecifier(specifier) || isPackageImportPattern(specifier) || isUrlOrDataOrFileSpecifier$1(specifier) || path.isAbsolute(specifier)) return null;
|
|
1059
|
+
return getDeniedDepRuleForPackage(rules, label, getPackageRootSpecifier(specifier));
|
|
1114
1060
|
}
|
|
1115
1061
|
|
|
1116
1062
|
//#endregion
|
|
@@ -1118,6 +1064,7 @@ function getDeniedNodeBuiltinRule(rules, label, specifier) {
|
|
|
1118
1064
|
const logger = createLogger({ main: "limina" });
|
|
1119
1065
|
const CliLogger = logger.getLoggerByGroup("task.cli");
|
|
1120
1066
|
const GraphLogger = logger.getLoggerByGroup("task.graph");
|
|
1067
|
+
const InitLogger = logger.getLoggerByGroup("task.init");
|
|
1121
1068
|
const PackageLogger = logger.getLoggerByGroup("task.package");
|
|
1122
1069
|
const PathsLogger = logger.getLoggerByGroup("task.paths");
|
|
1123
1070
|
const ProofLogger = logger.getLoggerByGroup("task.proof");
|
|
@@ -1132,6 +1079,541 @@ function clearCliScreen() {
|
|
|
1132
1079
|
readline.clearScreenDown(process.stdout);
|
|
1133
1080
|
}
|
|
1134
1081
|
|
|
1082
|
+
//#endregion
|
|
1083
|
+
//#region src/commands/init.ts
|
|
1084
|
+
const pnpmWorkspaceFileName = "pnpm-workspace.yaml";
|
|
1085
|
+
const liminaConfigFileName = "limina.config.mjs";
|
|
1086
|
+
const liminaCheckScriptName = "limina:check";
|
|
1087
|
+
const liminaCheckScriptValue = "limina check";
|
|
1088
|
+
const ignoredGlobPatterns = [
|
|
1089
|
+
"**/.git/**",
|
|
1090
|
+
"**/.limina/**",
|
|
1091
|
+
"**/.pnpm-store/**",
|
|
1092
|
+
"**/.tsbuild/**",
|
|
1093
|
+
"**/coverage/**",
|
|
1094
|
+
"**/dist/**",
|
|
1095
|
+
"**/node_modules/**"
|
|
1096
|
+
];
|
|
1097
|
+
function findPnpmWorkspaceRoot(startDir) {
|
|
1098
|
+
let currentDir = path.resolve(startDir);
|
|
1099
|
+
while (true) {
|
|
1100
|
+
if (existsSync(path.join(currentDir, pnpmWorkspaceFileName))) return normalizeAbsolutePath(currentDir);
|
|
1101
|
+
const parentDir = path.dirname(currentDir);
|
|
1102
|
+
if (parentDir === currentDir) return null;
|
|
1103
|
+
currentDir = parentDir;
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
function createInitConfig(rootDir) {
|
|
1107
|
+
return {
|
|
1108
|
+
configPath: path.join(rootDir, liminaConfigFileName),
|
|
1109
|
+
rootDir
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
function formatConfigPath(rootDir, configPath) {
|
|
1113
|
+
return toRelativePath(rootDir, configPath);
|
|
1114
|
+
}
|
|
1115
|
+
function formatReferencePath(fromConfigPath, toConfigPath) {
|
|
1116
|
+
const relativePath = toPosixPath(path.relative(path.dirname(fromConfigPath), toConfigPath));
|
|
1117
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
1118
|
+
}
|
|
1119
|
+
function stringifyJson(value) {
|
|
1120
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
1121
|
+
}
|
|
1122
|
+
function getProjectScope(configPath) {
|
|
1123
|
+
const fileName = path.basename(configPath);
|
|
1124
|
+
if (fileName === "tsconfig.json") return "tsconfig";
|
|
1125
|
+
return /^tsconfig\.(.+)\.json$/u.exec(fileName)?.[1] ?? "tsconfig";
|
|
1126
|
+
}
|
|
1127
|
+
function getDtsConfigPath(configPath) {
|
|
1128
|
+
const directory = path.dirname(configPath);
|
|
1129
|
+
const fileName = path.basename(configPath);
|
|
1130
|
+
const dtsFileName = fileName === "tsconfig.json" ? "tsconfig.dts.json" : fileName.replace(/\.json$/u, ".dts.json");
|
|
1131
|
+
return path.join(directory, dtsFileName);
|
|
1132
|
+
}
|
|
1133
|
+
function hasReferences(configObject) {
|
|
1134
|
+
return Array.isArray(configObject.references) && configObject.references.length > 0;
|
|
1135
|
+
}
|
|
1136
|
+
function parseTypeScriptConfig(rootDir, configPath) {
|
|
1137
|
+
const diagnostics = [];
|
|
1138
|
+
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, {
|
|
1139
|
+
...ts.sys,
|
|
1140
|
+
onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
|
|
1141
|
+
diagnostics.push(diagnostic);
|
|
1142
|
+
}
|
|
1143
|
+
});
|
|
1144
|
+
if (!parsed) throw new Error(ts.formatDiagnosticsWithColorAndContext(diagnostics, {
|
|
1145
|
+
getCanonicalFileName: (fileName) => fileName,
|
|
1146
|
+
getCurrentDirectory: () => rootDir,
|
|
1147
|
+
getNewLine: () => "\n"
|
|
1148
|
+
}));
|
|
1149
|
+
if (parsed.errors.length > 0) throw new Error(ts.formatDiagnosticsWithColorAndContext(parsed.errors, {
|
|
1150
|
+
getCanonicalFileName: (fileName) => fileName,
|
|
1151
|
+
getCurrentDirectory: () => rootDir,
|
|
1152
|
+
getNewLine: () => "\n"
|
|
1153
|
+
}));
|
|
1154
|
+
return {
|
|
1155
|
+
fileNames: parsed.fileNames.map(normalizeAbsolutePath),
|
|
1156
|
+
options: parsed.options
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
function findNearestWorkspacePackage(filePath, packages) {
|
|
1160
|
+
return [...packages].sort((left, right) => right.directory.length - left.directory.length).find((workspacePackage) => isPathInsideDirectory(filePath, workspacePackage.directory)) ?? null;
|
|
1161
|
+
}
|
|
1162
|
+
function collectWorkspaceDependencyNames(manifest) {
|
|
1163
|
+
const dependencyNames = /* @__PURE__ */ new Set();
|
|
1164
|
+
for (const dependencies of getDependencySections(manifest)) for (const [dependencyName, specifier] of Object.entries(dependencies)) if (isWorkspaceDependencySpecifier(specifier)) dependencyNames.add(dependencyName);
|
|
1165
|
+
return dependencyNames;
|
|
1166
|
+
}
|
|
1167
|
+
function findOwningProjectForFile(filePath, projects) {
|
|
1168
|
+
const normalizedFilePath = normalizeAbsolutePath(filePath);
|
|
1169
|
+
return projects.filter((project) => project.fileNames.includes(normalizedFilePath)).sort((left, right) => {
|
|
1170
|
+
const depthDelta = path.dirname(right.configPath).length - path.dirname(left.configPath).length;
|
|
1171
|
+
return depthDelta === 0 ? left.configPath.localeCompare(right.configPath) : depthDelta;
|
|
1172
|
+
})[0] ?? null;
|
|
1173
|
+
}
|
|
1174
|
+
function isDirectory(filePath) {
|
|
1175
|
+
try {
|
|
1176
|
+
return statSync(filePath).isDirectory();
|
|
1177
|
+
} catch {
|
|
1178
|
+
return false;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
function mapVirtualWorkspacePath(filePath, packageByName) {
|
|
1182
|
+
const segments = normalizeAbsolutePath(filePath).split("/");
|
|
1183
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
1184
|
+
if (segments[index] !== "node_modules") continue;
|
|
1185
|
+
const firstPackageSegment = segments[index + 1];
|
|
1186
|
+
if (!firstPackageSegment) continue;
|
|
1187
|
+
const isScopedPackage = firstPackageSegment.startsWith("@");
|
|
1188
|
+
const packageName = isScopedPackage ? `${firstPackageSegment}/${segments[index + 2] ?? ""}` : firstPackageSegment;
|
|
1189
|
+
const restStart = index + (isScopedPackage ? 3 : 2);
|
|
1190
|
+
const workspacePackage = packageByName.get(packageName);
|
|
1191
|
+
if (!workspacePackage) continue;
|
|
1192
|
+
return path.join(workspacePackage.directory, ...segments.slice(restStart));
|
|
1193
|
+
}
|
|
1194
|
+
return null;
|
|
1195
|
+
}
|
|
1196
|
+
function isVirtualWorkspaceDirectory(directoryPath, packageByName) {
|
|
1197
|
+
const segments = normalizeAbsolutePath(directoryPath).split("/");
|
|
1198
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
1199
|
+
if (segments[index] !== "node_modules") continue;
|
|
1200
|
+
const firstPackageSegment = segments[index + 1];
|
|
1201
|
+
if (!firstPackageSegment) return packageByName.size > 0;
|
|
1202
|
+
if (firstPackageSegment.startsWith("@") && segments[index + 2] === void 0) return [...packageByName.keys()].some((packageName) => packageName.startsWith(`${firstPackageSegment}/`));
|
|
1203
|
+
}
|
|
1204
|
+
const mappedPath = mapVirtualWorkspacePath(directoryPath, packageByName);
|
|
1205
|
+
return mappedPath ? isDirectory(mappedPath) : false;
|
|
1206
|
+
}
|
|
1207
|
+
function createWorkspaceModuleResolutionHost(options) {
|
|
1208
|
+
const mapPath = (filePath) => mapVirtualWorkspacePath(filePath, options.packageByName) ?? filePath;
|
|
1209
|
+
return {
|
|
1210
|
+
directoryExists: (directoryPath) => isVirtualWorkspaceDirectory(directoryPath, options.packageByName) || (ts.sys.directoryExists?.(directoryPath) ?? isDirectory(directoryPath)),
|
|
1211
|
+
fileExists: (filePath) => {
|
|
1212
|
+
const mappedPath = mapPath(filePath);
|
|
1213
|
+
return existsSync(mappedPath) && !isDirectory(mappedPath);
|
|
1214
|
+
},
|
|
1215
|
+
getCurrentDirectory: () => options.rootDir,
|
|
1216
|
+
readFile: (filePath) => ts.sys.readFile(mapPath(filePath)),
|
|
1217
|
+
realpath: (filePath) => normalizeAbsolutePath(mapPath(filePath)),
|
|
1218
|
+
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
function resolveImportWithTypeScript(options) {
|
|
1222
|
+
const resolvedModule = ts.resolveModuleName(options.importRecord.specifier, options.importRecord.filePath, options.project.options, options.host, options.cache).resolvedModule;
|
|
1223
|
+
if (!resolvedModule?.resolvedFileName) return null;
|
|
1224
|
+
return normalizeAbsolutePath(mapVirtualWorkspacePath(resolvedModule.resolvedFileName, options.packageByName) ?? resolvedModule.resolvedFileName);
|
|
1225
|
+
}
|
|
1226
|
+
function isPackageImportSpecifier$1(specifier) {
|
|
1227
|
+
return specifier.startsWith("#");
|
|
1228
|
+
}
|
|
1229
|
+
function createDtsConfig(project) {
|
|
1230
|
+
const fileName = path.basename(project.configPath);
|
|
1231
|
+
const scope = project.scope;
|
|
1232
|
+
const output = {
|
|
1233
|
+
$schema: "https://json.schemastore.org/tsconfig",
|
|
1234
|
+
extends: [`./${fileName}`],
|
|
1235
|
+
compilerOptions: {
|
|
1236
|
+
composite: true,
|
|
1237
|
+
incremental: true,
|
|
1238
|
+
noEmit: false,
|
|
1239
|
+
declaration: true,
|
|
1240
|
+
emitDeclarationOnly: true,
|
|
1241
|
+
declarationMap: false,
|
|
1242
|
+
rootDir: ".",
|
|
1243
|
+
outDir: "./.limina",
|
|
1244
|
+
tsBuildInfoFile: `./.limina/${scope}.tsbuildinfo`
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
if (project.references.length > 0) output.references = project.references.map((referencePath) => ({ path: referencePath }));
|
|
1248
|
+
return output;
|
|
1249
|
+
}
|
|
1250
|
+
function createBuildAggregator(references) {
|
|
1251
|
+
return {
|
|
1252
|
+
$schema: "https://json.schemastore.org/tsconfig",
|
|
1253
|
+
files: [],
|
|
1254
|
+
references: references.map((referencePath) => ({ path: referencePath }))
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
function createLiminaConfigContent() {
|
|
1258
|
+
return `import { defineConfig } from 'limina';
|
|
1259
|
+
|
|
1260
|
+
export default defineConfig({
|
|
1261
|
+
// Shared checker entries used by graph, proof, paths, and typecheck checks.
|
|
1262
|
+
config: {
|
|
1263
|
+
checkers: {
|
|
1264
|
+
typescript: {
|
|
1265
|
+
preset: 'tsc',
|
|
1266
|
+
entry: 'tsconfig.build.json',
|
|
1267
|
+
},
|
|
1268
|
+
},
|
|
1269
|
+
},
|
|
1270
|
+
});
|
|
1271
|
+
`;
|
|
1272
|
+
}
|
|
1273
|
+
async function confirmAction(options, message) {
|
|
1274
|
+
if (options.yes) return true;
|
|
1275
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error(`${message} Run limina init --yes to accept the default confirmation in non-interactive environments.`);
|
|
1276
|
+
const result = await prompts.confirm({
|
|
1277
|
+
initialValue: true,
|
|
1278
|
+
message
|
|
1279
|
+
});
|
|
1280
|
+
if (prompts.isCancel(result)) throw new Error("limina init canceled.");
|
|
1281
|
+
return result;
|
|
1282
|
+
}
|
|
1283
|
+
async function writeTextFile(filePath, content, writtenFiles) {
|
|
1284
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
1285
|
+
await writeFile(filePath, content);
|
|
1286
|
+
writtenFiles.push(filePath);
|
|
1287
|
+
}
|
|
1288
|
+
async function writeBuildAggregatorFile(options) {
|
|
1289
|
+
if (options.references.length === 0) return false;
|
|
1290
|
+
await writeTextFile(options.configPath, stringifyJson(createBuildAggregator(options.references)), options.writtenFiles);
|
|
1291
|
+
return true;
|
|
1292
|
+
}
|
|
1293
|
+
function findPnpmWorkspacePath(startDir) {
|
|
1294
|
+
const rootDir = findPnpmWorkspaceRoot(startDir);
|
|
1295
|
+
return rootDir ? path.join(rootDir, pnpmWorkspaceFileName) : null;
|
|
1296
|
+
}
|
|
1297
|
+
function resolveCatalogRange(range, packageName, packageManifestPath) {
|
|
1298
|
+
if (!range) return null;
|
|
1299
|
+
if (!range.startsWith("catalog:")) return range;
|
|
1300
|
+
const workspacePath = findPnpmWorkspacePath(path.dirname(packageManifestPath));
|
|
1301
|
+
if (!workspacePath || !existsSync(workspacePath)) return null;
|
|
1302
|
+
const parsed = parse(readFileSync(workspacePath, "utf8"));
|
|
1303
|
+
const catalogName = range.slice(8);
|
|
1304
|
+
if (catalogName.length === 0 || catalogName === "default") return parsed?.catalog?.[packageName] ?? null;
|
|
1305
|
+
return parsed?.catalogs?.[catalogName]?.[packageName] ?? null;
|
|
1306
|
+
}
|
|
1307
|
+
function readLiminaPackageMetadata() {
|
|
1308
|
+
const manifestPath = createRequire(import.meta.url).resolve("limina/package.json");
|
|
1309
|
+
const manifest = readJsonFile(manifestPath);
|
|
1310
|
+
const versionRange = manifest.version ? `^${manifest.version}` : "^0.0.1";
|
|
1311
|
+
const rawTypeScriptRange = manifest.peerDependencies?.typescript ?? manifest.devDependencies?.typescript ?? manifest.dependencies?.typescript;
|
|
1312
|
+
return {
|
|
1313
|
+
typescriptRange: resolveCatalogRange(rawTypeScriptRange, "typescript", manifestPath) ?? rawTypeScriptRange ?? "^5.9.0",
|
|
1314
|
+
versionRange
|
|
1315
|
+
};
|
|
1316
|
+
}
|
|
1317
|
+
function hasDependency(manifest, dependencyName) {
|
|
1318
|
+
return Boolean(manifest.dependencies?.[dependencyName] || manifest.devDependencies?.[dependencyName] || manifest.optionalDependencies?.[dependencyName] || manifest.peerDependencies?.[dependencyName]);
|
|
1319
|
+
}
|
|
1320
|
+
async function updateRootPackageJson(options) {
|
|
1321
|
+
const packageJsonPath = path.join(options.rootDir, "package.json");
|
|
1322
|
+
let installRequired = false;
|
|
1323
|
+
if (!existsSync(packageJsonPath)) {
|
|
1324
|
+
if (!await confirmAction(options.prompt, `No package.json found at ${formatConfigPath(options.rootDir, packageJsonPath)}. Create one?`)) {
|
|
1325
|
+
options.skippedFiles.push(packageJsonPath);
|
|
1326
|
+
return false;
|
|
1327
|
+
}
|
|
1328
|
+
await writeTextFile(packageJsonPath, stringifyJson({
|
|
1329
|
+
private: true,
|
|
1330
|
+
type: "module",
|
|
1331
|
+
scripts: { [liminaCheckScriptName]: liminaCheckScriptValue },
|
|
1332
|
+
devDependencies: {
|
|
1333
|
+
limina: options.metadata.versionRange,
|
|
1334
|
+
typescript: options.metadata.typescriptRange
|
|
1335
|
+
}
|
|
1336
|
+
}), options.writtenFiles);
|
|
1337
|
+
return true;
|
|
1338
|
+
}
|
|
1339
|
+
const manifest = readJsonFile(packageJsonPath);
|
|
1340
|
+
const scripts = { ...manifest.scripts ?? {} };
|
|
1341
|
+
let changed = false;
|
|
1342
|
+
if (scripts[liminaCheckScriptName] && scripts[liminaCheckScriptName] !== liminaCheckScriptValue) {
|
|
1343
|
+
if (await confirmAction(options.prompt, `Script "${liminaCheckScriptName}" already exists in package.json. Overwrite it?`)) {
|
|
1344
|
+
scripts[liminaCheckScriptName] = liminaCheckScriptValue;
|
|
1345
|
+
changed = true;
|
|
1346
|
+
}
|
|
1347
|
+
} else if (!scripts[liminaCheckScriptName]) {
|
|
1348
|
+
scripts[liminaCheckScriptName] = liminaCheckScriptValue;
|
|
1349
|
+
changed = true;
|
|
1350
|
+
}
|
|
1351
|
+
if (!hasDependency(manifest, "limina")) {
|
|
1352
|
+
manifest.devDependencies = {
|
|
1353
|
+
...manifest.devDependencies ?? {},
|
|
1354
|
+
limina: options.metadata.versionRange
|
|
1355
|
+
};
|
|
1356
|
+
installRequired = true;
|
|
1357
|
+
changed = true;
|
|
1358
|
+
}
|
|
1359
|
+
if (changed) await writeTextFile(packageJsonPath, stringifyJson({
|
|
1360
|
+
...manifest,
|
|
1361
|
+
scripts
|
|
1362
|
+
}), options.writtenFiles);
|
|
1363
|
+
return installRequired;
|
|
1364
|
+
}
|
|
1365
|
+
async function collectReservedConfigConflicts(rootDir) {
|
|
1366
|
+
const conflicts = await glob([
|
|
1367
|
+
"tsconfig*.build.json",
|
|
1368
|
+
"**/tsconfig*.build.json",
|
|
1369
|
+
"tsconfig*.dts.json",
|
|
1370
|
+
"**/tsconfig*.dts.json"
|
|
1371
|
+
], {
|
|
1372
|
+
absolute: false,
|
|
1373
|
+
cwd: rootDir,
|
|
1374
|
+
ignore: ignoredGlobPatterns
|
|
1375
|
+
});
|
|
1376
|
+
return [...new Set(conflicts)].sort();
|
|
1377
|
+
}
|
|
1378
|
+
async function collectOrdinaryTsconfigPaths(rootDir) {
|
|
1379
|
+
const configPaths = await glob(["tsconfig*.json", "**/tsconfig*.json"], {
|
|
1380
|
+
absolute: false,
|
|
1381
|
+
cwd: rootDir,
|
|
1382
|
+
ignore: ignoredGlobPatterns
|
|
1383
|
+
});
|
|
1384
|
+
return [...new Set(configPaths)].map((configPath) => normalizeAbsolutePath(path.join(rootDir, configPath))).filter(isOrdinaryTypecheckConfigPath).sort();
|
|
1385
|
+
}
|
|
1386
|
+
function analyzeTypecheckProjects(options) {
|
|
1387
|
+
const problems = [];
|
|
1388
|
+
const projects = [];
|
|
1389
|
+
for (const configPath of options.configPaths) {
|
|
1390
|
+
const configObject = readJsonConfig(options.config, configPath);
|
|
1391
|
+
const parsed = parseTypeScriptConfig(options.config.rootDir, configPath);
|
|
1392
|
+
const hasProjectReferences = hasReferences(configObject);
|
|
1393
|
+
const fileName = path.basename(configPath);
|
|
1394
|
+
if (fileName === "tsconfig.json" && hasProjectReferences && parsed.fileNames.length > 0) {
|
|
1395
|
+
problems.push([
|
|
1396
|
+
"Invalid tsconfig role:",
|
|
1397
|
+
` config: ${formatConfigPath(options.config.rootDir, configPath)}`,
|
|
1398
|
+
" reason: tsconfig.json must be either a pure aggregator with files: [] and references, or a typecheck leaf with source files, but not both."
|
|
1399
|
+
].join("\n"));
|
|
1400
|
+
continue;
|
|
1401
|
+
}
|
|
1402
|
+
if (fileName !== "tsconfig.json" && hasProjectReferences) {
|
|
1403
|
+
problems.push([
|
|
1404
|
+
"Invalid scoped tsconfig role:",
|
|
1405
|
+
` config: ${formatConfigPath(options.config.rootDir, configPath)}`,
|
|
1406
|
+
" reason: tsconfig.<scope>.json files may only be typecheck leaves; graph aggregation belongs in tsconfig*.build.json."
|
|
1407
|
+
].join("\n"));
|
|
1408
|
+
continue;
|
|
1409
|
+
}
|
|
1410
|
+
if (fileName === "tsconfig.json" && hasProjectReferences) continue;
|
|
1411
|
+
projects.push({
|
|
1412
|
+
configPath,
|
|
1413
|
+
dtsConfigPath: getDtsConfigPath(configPath),
|
|
1414
|
+
fileNames: parsed.fileNames,
|
|
1415
|
+
options: parsed.options,
|
|
1416
|
+
owner: findNearestWorkspacePackage(configPath, options.workspacePackages),
|
|
1417
|
+
references: [],
|
|
1418
|
+
scope: getProjectScope(configPath)
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
return {
|
|
1422
|
+
problems,
|
|
1423
|
+
projects
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function inferProjectReferences(options) {
|
|
1427
|
+
const problems = [];
|
|
1428
|
+
const packageByName = new Map(options.workspacePackages.map((workspacePackage) => [workspacePackage.name, workspacePackage]));
|
|
1429
|
+
const host = createWorkspaceModuleResolutionHost({
|
|
1430
|
+
packageByName,
|
|
1431
|
+
rootDir: options.config.rootDir
|
|
1432
|
+
});
|
|
1433
|
+
for (const project of options.projects) {
|
|
1434
|
+
if (!project.owner) continue;
|
|
1435
|
+
const workspaceDependencyNames = collectWorkspaceDependencyNames(project.owner.manifest);
|
|
1436
|
+
const resolutionCache = ts.createModuleResolutionCache(path.dirname(project.configPath), (fileName) => fileName, project.options);
|
|
1437
|
+
const referencePaths = /* @__PURE__ */ new Set();
|
|
1438
|
+
for (const fileName of project.fileNames) {
|
|
1439
|
+
if (!/\.(?:[cm]?tsx?|d\.[cm]?ts)$/u.test(fileName)) continue;
|
|
1440
|
+
for (const importRecord of collectImportsFromFile(fileName)) {
|
|
1441
|
+
const resolvedFilePath = resolveImportWithTypeScript({
|
|
1442
|
+
cache: resolutionCache,
|
|
1443
|
+
host,
|
|
1444
|
+
importRecord,
|
|
1445
|
+
packageByName,
|
|
1446
|
+
project
|
|
1447
|
+
});
|
|
1448
|
+
const packageName = isRelativeSpecifier$1(importRecord.specifier) || isPackageImportSpecifier$1(importRecord.specifier) ? null : getPackageRootSpecifier(importRecord.specifier);
|
|
1449
|
+
const targetPackage = packageName ? packageByName.get(packageName) : null;
|
|
1450
|
+
const isWorkspaceGraphDependency = targetPackage && (targetPackage.name === project.owner.name || workspaceDependencyNames.has(targetPackage.name));
|
|
1451
|
+
if (packageName && workspaceDependencyNames.has(packageName) && !targetPackage) {
|
|
1452
|
+
problems.push([
|
|
1453
|
+
"Workspace dependency was not discovered by pnpm:",
|
|
1454
|
+
` importing project: ${formatConfigPath(options.config.rootDir, project.dtsConfigPath)}`,
|
|
1455
|
+
` file: ${formatConfigPath(options.config.rootDir, importRecord.filePath)}:${importRecord.line}`,
|
|
1456
|
+
` imported specifier: ${importRecord.specifier}`,
|
|
1457
|
+
` package: ${packageName}`,
|
|
1458
|
+
" reason: package.json declares this dependency with the workspace: protocol, but limina init could not find a matching workspace package."
|
|
1459
|
+
].join("\n"));
|
|
1460
|
+
continue;
|
|
1461
|
+
}
|
|
1462
|
+
if (targetPackage && !isWorkspaceGraphDependency) continue;
|
|
1463
|
+
if (!resolvedFilePath) {
|
|
1464
|
+
if (targetPackage && isWorkspaceGraphDependency) problems.push([
|
|
1465
|
+
"Unable to resolve workspace import with TypeScript:",
|
|
1466
|
+
` importing project: ${formatConfigPath(options.config.rootDir, project.dtsConfigPath)}`,
|
|
1467
|
+
` file: ${formatConfigPath(options.config.rootDir, importRecord.filePath)}:${importRecord.line}`,
|
|
1468
|
+
` imported specifier: ${importRecord.specifier}`,
|
|
1469
|
+
` package: ${targetPackage.name}`,
|
|
1470
|
+
" reason: workspace:* imports must resolve with the project TypeScript compilerOptions before limina init can generate project references."
|
|
1471
|
+
].join("\n"));
|
|
1472
|
+
continue;
|
|
1473
|
+
}
|
|
1474
|
+
if (isRelativeSpecifier$1(importRecord.specifier)) {
|
|
1475
|
+
const sourcePackage = findNearestWorkspacePackage(importRecord.filePath, options.workspacePackages);
|
|
1476
|
+
const resolvedPackage = findNearestWorkspacePackage(resolvedFilePath, options.workspacePackages);
|
|
1477
|
+
if (sourcePackage && resolvedPackage && sourcePackage.name !== resolvedPackage.name) continue;
|
|
1478
|
+
}
|
|
1479
|
+
const targetProject = findOwningProjectForFile(resolvedFilePath, options.projects);
|
|
1480
|
+
if (!targetProject) {
|
|
1481
|
+
if (targetPackage && isWorkspaceGraphDependency) problems.push([
|
|
1482
|
+
"Unable to map workspace import to a generated declaration leaf:",
|
|
1483
|
+
` importing project: ${formatConfigPath(options.config.rootDir, project.dtsConfigPath)}`,
|
|
1484
|
+
` file: ${formatConfigPath(options.config.rootDir, importRecord.filePath)}:${importRecord.line}`,
|
|
1485
|
+
` imported specifier: ${importRecord.specifier}`,
|
|
1486
|
+
` resolved file: ${formatConfigPath(options.config.rootDir, resolvedFilePath)}`,
|
|
1487
|
+
" reason: TypeScript resolved this workspace import, but the resolved module is not covered by any ordinary tsconfig*.json leaf."
|
|
1488
|
+
].join("\n"));
|
|
1489
|
+
continue;
|
|
1490
|
+
}
|
|
1491
|
+
if (targetProject.dtsConfigPath !== project.dtsConfigPath) referencePaths.add(formatReferencePath(project.dtsConfigPath, targetProject.dtsConfigPath));
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
project.references = [...referencePaths].sort();
|
|
1495
|
+
}
|
|
1496
|
+
return problems;
|
|
1497
|
+
}
|
|
1498
|
+
function collectProjectReferencesForOwner(options) {
|
|
1499
|
+
return options.projects.filter((project) => project.owner?.directory === options.owner?.directory).map((project) => formatReferencePath(options.targetConfigPath, project.dtsConfigPath)).sort();
|
|
1500
|
+
}
|
|
1501
|
+
function collectRootBuildProjectReferences(options) {
|
|
1502
|
+
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();
|
|
1503
|
+
}
|
|
1504
|
+
async function writeGeneratedTsconfigs(options) {
|
|
1505
|
+
for (const project of options.projects) await writeTextFile(project.dtsConfigPath, stringifyJson(createDtsConfig(project)), options.writtenFiles);
|
|
1506
|
+
const nonRootWorkspacePackages = options.workspacePackages.filter((workspacePackage) => workspacePackage.directory !== options.rootDir);
|
|
1507
|
+
const workspaceBuildConfigPaths = [];
|
|
1508
|
+
for (const workspacePackage of nonRootWorkspacePackages) {
|
|
1509
|
+
const buildConfigPath = path.join(workspacePackage.directory, "tsconfig.build.json");
|
|
1510
|
+
if (await writeBuildAggregatorFile({
|
|
1511
|
+
configPath: buildConfigPath,
|
|
1512
|
+
references: collectProjectReferencesForOwner({
|
|
1513
|
+
owner: workspacePackage,
|
|
1514
|
+
projects: options.projects,
|
|
1515
|
+
targetConfigPath: buildConfigPath
|
|
1516
|
+
}),
|
|
1517
|
+
writtenFiles: options.writtenFiles
|
|
1518
|
+
})) workspaceBuildConfigPaths.push(buildConfigPath);
|
|
1519
|
+
}
|
|
1520
|
+
const rootBuildConfigPath = path.join(options.rootDir, "tsconfig.build.json");
|
|
1521
|
+
await writeBuildAggregatorFile({
|
|
1522
|
+
configPath: rootBuildConfigPath,
|
|
1523
|
+
references: [...collectRootBuildProjectReferences({
|
|
1524
|
+
projects: options.projects,
|
|
1525
|
+
rootDir: options.rootDir,
|
|
1526
|
+
targetConfigPath: rootBuildConfigPath
|
|
1527
|
+
}), ...workspaceBuildConfigPaths.map((buildConfigPath) => formatReferencePath(rootBuildConfigPath, buildConfigPath))].sort(),
|
|
1528
|
+
writtenFiles: options.writtenFiles
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
async function writeLiminaConfig(options) {
|
|
1532
|
+
const configPath = path.join(options.rootDir, liminaConfigFileName);
|
|
1533
|
+
if (existsSync(configPath)) {
|
|
1534
|
+
if (!await confirmAction(options.prompt, `${liminaConfigFileName} already exists. Overwrite it?`)) {
|
|
1535
|
+
options.skippedFiles.push(configPath);
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
await writeTextFile(configPath, createLiminaConfigContent(), options.writtenFiles);
|
|
1540
|
+
}
|
|
1541
|
+
async function runInitInternal(options) {
|
|
1542
|
+
const cwd = normalizeAbsolutePath(options.cwd ?? process.cwd());
|
|
1543
|
+
const rootDir = findPnpmWorkspaceRoot(cwd);
|
|
1544
|
+
if (!rootDir) throw new Error(`Unable to run limina init from ${cwd}: no pnpm-workspace.yaml was found in this directory or its parents.`);
|
|
1545
|
+
const rootPackageJsonPath = path.join(rootDir, "package.json");
|
|
1546
|
+
const rootPackageName = existsSync(rootPackageJsonPath) ? readJsonFile(rootPackageJsonPath).name : void 0;
|
|
1547
|
+
if (!await confirmAction(options, `Use pnpm workspace ${rootPackageName ? `"${rootPackageName}" ` : ""}at ${rootDir}?`)) throw new Error("limina init canceled.");
|
|
1548
|
+
const reservedConflicts = await collectReservedConfigConflicts(rootDir);
|
|
1549
|
+
if (reservedConflicts.length > 0) throw new Error([
|
|
1550
|
+
"Unable to run limina init because reserved Limina tsconfig names already exist:",
|
|
1551
|
+
...reservedConflicts.map((configPath) => ` - ${configPath}`),
|
|
1552
|
+
"reason: tsconfig*.build.json and tsconfig*.dts.json are Limina init output names; rename existing files before running init."
|
|
1553
|
+
].join("\n"));
|
|
1554
|
+
const config = createInitConfig(rootDir);
|
|
1555
|
+
const workspacePackages = (await collectWorkspacePackages(config)).filter((workspacePackage) => workspacePackage.directory !== rootDir);
|
|
1556
|
+
const projectAnalysis = analyzeTypecheckProjects({
|
|
1557
|
+
config,
|
|
1558
|
+
configPaths: await collectOrdinaryTsconfigPaths(rootDir),
|
|
1559
|
+
workspacePackages
|
|
1560
|
+
});
|
|
1561
|
+
const problems = [...projectAnalysis.problems];
|
|
1562
|
+
if (problems.length === 0) problems.push(...inferProjectReferences({
|
|
1563
|
+
config,
|
|
1564
|
+
projects: projectAnalysis.projects,
|
|
1565
|
+
workspacePackages
|
|
1566
|
+
}));
|
|
1567
|
+
if (problems.length > 0) throw new Error(problems.join("\n\n"));
|
|
1568
|
+
const metadata = readLiminaPackageMetadata();
|
|
1569
|
+
const writtenFiles = [];
|
|
1570
|
+
const skippedFiles = [];
|
|
1571
|
+
await writeGeneratedTsconfigs({
|
|
1572
|
+
projects: projectAnalysis.projects,
|
|
1573
|
+
rootDir,
|
|
1574
|
+
workspacePackages,
|
|
1575
|
+
writtenFiles
|
|
1576
|
+
});
|
|
1577
|
+
await writeLiminaConfig({
|
|
1578
|
+
prompt: options,
|
|
1579
|
+
rootDir,
|
|
1580
|
+
skippedFiles,
|
|
1581
|
+
writtenFiles
|
|
1582
|
+
});
|
|
1583
|
+
return {
|
|
1584
|
+
checkCommand: "pnpm limina:check",
|
|
1585
|
+
installRequired: await updateRootPackageJson({
|
|
1586
|
+
metadata,
|
|
1587
|
+
prompt: options,
|
|
1588
|
+
rootDir,
|
|
1589
|
+
skippedFiles,
|
|
1590
|
+
writtenFiles
|
|
1591
|
+
}),
|
|
1592
|
+
rootDir,
|
|
1593
|
+
skippedFiles,
|
|
1594
|
+
workspacePackageCount: workspacePackages.length,
|
|
1595
|
+
writtenFiles
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
async function runInit(options = {}) {
|
|
1599
|
+
if (options.clearScreen ?? true) clearCliScreen();
|
|
1600
|
+
const elapsed = createElapsedTimer();
|
|
1601
|
+
const task = options.flow?.start("init workspace", { depth: options.flowDepth ?? 0 });
|
|
1602
|
+
InitLogger.info("init started");
|
|
1603
|
+
try {
|
|
1604
|
+
const result = await runInitInternal(options);
|
|
1605
|
+
InitLogger.success(`init generated ${result.writtenFiles.length} files for ${result.workspacePackageCount} workspace packages.`, elapsed());
|
|
1606
|
+
if (result.installRequired) InitLogger.info("limina was added to devDependencies; run pnpm i before checking.");
|
|
1607
|
+
InitLogger.info(`next: ${result.installRequired ? "pnpm i && " : ""}${result.checkCommand}`);
|
|
1608
|
+
task?.pass();
|
|
1609
|
+
return result;
|
|
1610
|
+
} catch (error) {
|
|
1611
|
+
InitLogger.error(`init failed: ${formatErrorMessage$1(error)}`, elapsed());
|
|
1612
|
+
task?.fail("init failed", { error });
|
|
1613
|
+
throw error;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1135
1617
|
//#endregion
|
|
1136
1618
|
//#region src/commands/source.ts
|
|
1137
1619
|
function findOwnerForFile(filePath, owners) {
|
|
@@ -1144,7 +1626,7 @@ function isPackageImportSpecifier(specifier) {
|
|
|
1144
1626
|
return specifier.startsWith("#");
|
|
1145
1627
|
}
|
|
1146
1628
|
function isBarePackageSpecifier(specifier) {
|
|
1147
|
-
return !isRelativeSpecifier(specifier) && !isPackageImportSpecifier(specifier) && !isUrlOrDataOrFileSpecifier(specifier) && !path.isAbsolute(specifier);
|
|
1629
|
+
return !isRelativeSpecifier$1(specifier) && !isPackageImportSpecifier(specifier) && !isUrlOrDataOrFileSpecifier(specifier) && !path.isAbsolute(specifier);
|
|
1148
1630
|
}
|
|
1149
1631
|
function isDependencyAuthorized(manifest, packageName) {
|
|
1150
1632
|
return Boolean(manifest.dependencies?.[packageName] || manifest.devDependencies?.[packageName]);
|
|
@@ -1218,17 +1700,6 @@ function addPackageImportAuthorizationProblem(options) {
|
|
|
1218
1700
|
" reason: source imports must be authorized by the nearest package.json dependencies or devDependencies."
|
|
1219
1701
|
].join("\n"));
|
|
1220
1702
|
}
|
|
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
1703
|
function addPackageImportProblem(options) {
|
|
1233
1704
|
if (!packageImportsMatch(options.owner.manifest.imports, options.importRecord.specifier)) {
|
|
1234
1705
|
options.problems.push([
|
|
@@ -1272,23 +1743,11 @@ function createSourceProjectEntries(config, projects) {
|
|
|
1272
1743
|
}
|
|
1273
1744
|
async function runSourceCheckInternal(config, options = {}) {
|
|
1274
1745
|
const graphRoute = collectGraphProjectRoute(config);
|
|
1275
|
-
const
|
|
1276
|
-
const projects = projectPaths.map((projectPath) => parseProject(config, projectPath));
|
|
1746
|
+
const projects = graphRoute.projectPaths.map((projectPath) => parseProject(config, projectPath));
|
|
1277
1747
|
const sourceProjectEntries = createSourceProjectEntries(config, projects);
|
|
1278
1748
|
const packages = await collectWorkspacePackages(config);
|
|
1279
1749
|
const packageOwners = await collectPackageOwners(config);
|
|
1280
1750
|
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
1751
|
for (const project of projects) {
|
|
1293
1752
|
if (project.labelProblem) problems.push(project.labelProblem);
|
|
1294
1753
|
if (!isDtsProjectConfig(project.configPath)) continue;
|
|
@@ -1315,7 +1774,7 @@ async function runSourceCheckInternal(config, options = {}) {
|
|
|
1315
1774
|
if (!owner) continue;
|
|
1316
1775
|
for (const importRecord of collectImportsFromFile(filePath)) {
|
|
1317
1776
|
const resolvedFilePath = resolveInternalImport(importRecord.specifier, filePath, project.options);
|
|
1318
|
-
if (isRelativeSpecifier(importRecord.specifier)) {
|
|
1777
|
+
if (isRelativeSpecifier$1(importRecord.specifier)) {
|
|
1319
1778
|
if (!resolvedFilePath) continue;
|
|
1320
1779
|
const targetOwner = findOwnerForFile(resolvedFilePath, packageOwners);
|
|
1321
1780
|
if (targetOwner?.packageJsonPath !== owner.packageJsonPath) addRelativeImportOwnerProblem({
|
|
@@ -1340,18 +1799,7 @@ async function runSourceCheckInternal(config, options = {}) {
|
|
|
1340
1799
|
}
|
|
1341
1800
|
if (isUrlOrDataOrFileSpecifier(importRecord.specifier)) continue;
|
|
1342
1801
|
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
|
-
}
|
|
1802
|
+
if (isNodeBuiltinSpecifier(importRecord.specifier)) continue;
|
|
1355
1803
|
const packageName = getPackageRootSpecifier(importRecord.specifier);
|
|
1356
1804
|
if (owner.name === packageName) continue;
|
|
1357
1805
|
const workspacePackage = packages.find((candidate) => candidate.name === packageName) ?? null;
|
|
@@ -2023,4 +2471,4 @@ function createLiminaFlowReporter(options = {}) {
|
|
|
2023
2471
|
}
|
|
2024
2472
|
|
|
2025
2473
|
//#endregion
|
|
2026
|
-
export {
|
|
2474
|
+
export { shouldResolveThroughGraph as A, createExtensionPattern as B, formatArtifactDependencyPolicy as C, isRelativeSpecifier$1 as D, isDtsProjectConfig as E, collectCheckerEntryProjectRoutes as F, isDtsConfigPath as G, formatReferences as H, collectGraphProjectRoute as I, parseProjectFileNamesForExtensions as J, isOrdinaryTypecheckConfigPath as K, collectGraphProjectRouteFromRoot as L, collectWorkspacePackages as M, findPackageForSpecifier as N, parseProject as O, getPackageRootSpecifier as P, collectGraphProjectRoutes as R, findTargetProject as S, inferPackageProject as T, getDtsCompanionConfigPath as U, createFormatHost as V, getRawReferencePaths as W, resolveProjectConfigPath as X, readJsonConfig as Y, resolveReferencePath 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, parseProjectFileNames 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, collectTypecheckTargetProjectPaths as z };
|