@component-compass/cli 0.1.7 → 0.1.8
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/dist/cli/help.js +1 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/parse.js +1 -0
- package/dist/cli/parse.js.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/scan.d.ts +7 -0
- package/dist/commands/scan.js +96 -32
- package/dist/commands/scan.js.map +1 -1
- package/dist/identity.d.ts +8 -0
- package/dist/identity.js +4 -2
- package/dist/identity.js.map +1 -1
- package/dist/seeds.js +3 -0
- package/dist/seeds.js.map +1 -1
- package/dist/util/git.d.ts +1 -0
- package/dist/util/git.js +9 -0
- package/dist/util/git.js.map +1 -1
- package/dist/walker/bounded-definition-resolver.d.ts +9 -0
- package/dist/walker/bounded-definition-resolver.js +122 -0
- package/dist/walker/bounded-definition-resolver.js.map +1 -0
- package/dist/walker/package-alias-layers.d.ts +7 -0
- package/dist/walker/package-alias-layers.js +40 -0
- package/dist/walker/package-alias-layers.js.map +1 -0
- package/dist/walker/resolve-import.d.ts +4 -0
- package/dist/walker/resolve-import.js +29 -5
- package/dist/walker/resolve-import.js.map +1 -1
- package/dist/walker/tsconfig-discovery.d.ts +4 -2
- package/dist/walker/tsconfig-discovery.js +4 -2
- package/dist/walker/tsconfig-discovery.js.map +1 -1
- package/dist/walker/workspace-exports.js +103 -39
- package/dist/walker/workspace-exports.js.map +1 -1
- package/dist/workspace/build-graph.d.ts +14 -1
- package/dist/workspace/build-graph.js +4 -1
- package/dist/workspace/build-graph.js.map +1 -1
- package/dist/workspace/find-workspace-root.d.ts +1 -0
- package/dist/workspace/find-workspace-root.js +60 -0
- package/dist/workspace/find-workspace-root.js.map +1 -0
- package/dist/workspace/types.d.ts +3 -1
- package/package.json +4 -4
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ResolveImport } from "@component-compass/plugin-core";
|
|
2
|
+
export declare function createBoundedDefinitionResolver(opts: {
|
|
3
|
+
moduleResolver: ResolveImport;
|
|
4
|
+
maxFiles?: number;
|
|
5
|
+
onWarning?: (msg: string) => void;
|
|
6
|
+
}): (absTarget: string, imported: string) => {
|
|
7
|
+
absFile: string;
|
|
8
|
+
exportName: string;
|
|
9
|
+
} | null;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pin the identity of an un-walked workspace-member import to its definition
|
|
3
|
+
* file (spec: bounded re-export resolution — identity must be scope-invariant
|
|
4
|
+
* between whole-root and sub-package scans).
|
|
5
|
+
*
|
|
6
|
+
* Strategy: maintain a private "shadow graph" containing only chain files,
|
|
7
|
+
* parsed on demand, and re-run `followReExportChain` until the landing file is
|
|
8
|
+
* one we've parsed (fixpoint) or `maxFiles` is hit. For NAMED re-exports the
|
|
9
|
+
* seam returns the hop target when a file is absent from the graph, which is
|
|
10
|
+
* exactly the "parse this next" signal. For `export *` the seam recurses
|
|
11
|
+
* internally and returns null when the intermediate barrel isn't parsed yet, so
|
|
12
|
+
* a stalled walk triggers a bounded star-frontier expansion (parse one
|
|
13
|
+
* un-parsed star target, reading the graph's public `exports`, then retry) —
|
|
14
|
+
* the seam itself is never modified (single-seam requirement). Files parsed
|
|
15
|
+
* here are NEVER walked for occurrences/props/composition — they only pin
|
|
16
|
+
* identity (spec Piece 2).
|
|
17
|
+
*
|
|
18
|
+
* The shadow graph is built with NO `repoRoot`, so it has no
|
|
19
|
+
* `resolveToGraphKey`; `followReExportChain` hops therefore stay absolute,
|
|
20
|
+
* matching the `moduleResolver` output and the shadow-graph file keys.
|
|
21
|
+
*/
|
|
22
|
+
import { readFileSync } from "node:fs";
|
|
23
|
+
import { createGraphBuilder, followReExportChain } from "@component-compass/reference-graph";
|
|
24
|
+
import { emitReact } from "@component-compass/parser-react";
|
|
25
|
+
import { parseByExt } from "../parse-by-ext.js";
|
|
26
|
+
export function createBoundedDefinitionResolver(opts) {
|
|
27
|
+
const maxFiles = opts.maxFiles ?? 10;
|
|
28
|
+
const memo = new Map();
|
|
29
|
+
// Shadow graph keyed by ABSOLUTE paths: no repoRoot → no resolveToGraphKey,
|
|
30
|
+
// so followReExportChain hops stay absolute (matches moduleResolver output).
|
|
31
|
+
const builder = createGraphBuilder({ moduleResolver: opts.moduleResolver });
|
|
32
|
+
const parsed = new Set();
|
|
33
|
+
const tryParse = (absFile) => {
|
|
34
|
+
if (parsed.has(absFile))
|
|
35
|
+
return true;
|
|
36
|
+
let source;
|
|
37
|
+
try {
|
|
38
|
+
source = readFileSync(absFile, "utf8");
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
let file;
|
|
44
|
+
try {
|
|
45
|
+
file = parseByExt(absFile, source);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (file.kind !== "babel")
|
|
51
|
+
return false; // react-engine path only; Vue SFC barrels fall back
|
|
52
|
+
try {
|
|
53
|
+
const fb = builder.beginFile(absFile);
|
|
54
|
+
emitReact({ file: absFile, source, ast: file.ast, fileBuilder: fb });
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
parsed.add(absFile);
|
|
60
|
+
return true;
|
|
61
|
+
};
|
|
62
|
+
// Parse one not-yet-parsed `export *` target reachable from an already-parsed
|
|
63
|
+
// file. `followReExportChain` recurses into star sources internally and
|
|
64
|
+
// returns null (rather than a hop target) when the source file is absent from
|
|
65
|
+
// the graph, so a stalled named walk needs this to advance the star frontier.
|
|
66
|
+
// Returns true when it parsed a new file. Star `from` specifiers resolve from
|
|
67
|
+
// the parsed file's own absolute key.
|
|
68
|
+
const expandStarFrontier = () => {
|
|
69
|
+
const graph = builder.build();
|
|
70
|
+
for (const [fileKey, fileGraph] of graph.files) {
|
|
71
|
+
for (const exp of fileGraph.exports) {
|
|
72
|
+
if (exp.kind !== "star")
|
|
73
|
+
continue;
|
|
74
|
+
const targetAbs = opts.moduleResolver(fileKey, exp.from);
|
|
75
|
+
if (!targetAbs || parsed.has(targetAbs))
|
|
76
|
+
continue;
|
|
77
|
+
if (tryParse(targetAbs))
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
};
|
|
83
|
+
return function resolveDefinition(absTarget, imported) {
|
|
84
|
+
const key = `${absTarget}\0${imported}`;
|
|
85
|
+
const hit = memo.get(key);
|
|
86
|
+
if (hit !== undefined)
|
|
87
|
+
return hit;
|
|
88
|
+
let result = null;
|
|
89
|
+
if (tryParse(absTarget)) {
|
|
90
|
+
let filesUsed = 1;
|
|
91
|
+
for (;;) {
|
|
92
|
+
const chained = followReExportChain(builder.build(), absTarget, imported);
|
|
93
|
+
if (chained) {
|
|
94
|
+
if (parsed.has(chained.file)) {
|
|
95
|
+
result = { absFile: chained.file, exportName: chained.localExport };
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (filesUsed >= maxFiles || !tryParse(chained.file)) {
|
|
99
|
+
// Cap or unparseable hop: best-effort pin to the named hop target.
|
|
100
|
+
opts.onWarning?.(`bounded re-export resolution stopped at ${chained.file} for "${imported}" (cap ${maxFiles})`);
|
|
101
|
+
result = { absFile: chained.file, exportName: chained.localExport };
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
filesUsed++;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
// Named walk stalled. A star barrel we haven't parsed may still hold the
|
|
108
|
+
// name — expand one star target (bounded) and retry. Genuinely
|
|
109
|
+
// unresolvable when no unparsed star target remains: caller falls back
|
|
110
|
+
// to absTarget.
|
|
111
|
+
if (filesUsed >= maxFiles)
|
|
112
|
+
break;
|
|
113
|
+
if (!expandStarFrontier())
|
|
114
|
+
break;
|
|
115
|
+
filesUsed++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
memo.set(key, result);
|
|
119
|
+
return result;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=bounded-definition-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-definition-resolver.js","sourceRoot":"","sources":["../../src/walker/bounded-definition-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WorkspaceGraph } from "../workspace/types.js";
|
|
2
|
+
import { type AliasEntry } from "./tsconfig-loader.js";
|
|
3
|
+
export type PackageAliasLayer = {
|
|
4
|
+
pkgRealPath: string;
|
|
5
|
+
entries: AliasEntry[];
|
|
6
|
+
};
|
|
7
|
+
export declare function buildPackageAliasLayers(graph: WorkspaceGraph, onWarning?: (message: string) => void): PackageAliasLayer[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-workspace-package tsconfig alias layers (spec Piece 3). Each member's
|
|
3
|
+
* own tsconfig(.base).json contributes an AliasEntry[] applied ONLY to files
|
|
4
|
+
* owned by that member — two apps both defining `@/*` never collide.
|
|
5
|
+
* Discovery per member reuses resolveTsconfigPath with configDir = repoRoot =
|
|
6
|
+
* the member dir (no walk-up per member; the root layer covers inheritance).
|
|
7
|
+
*/
|
|
8
|
+
import { realpathSync } from "node:fs";
|
|
9
|
+
import { resolveTsconfigPath } from "./tsconfig-discovery.js";
|
|
10
|
+
import { loadTsconfigChain } from "./tsconfig-loader.js";
|
|
11
|
+
export function buildPackageAliasLayers(graph, onWarning) {
|
|
12
|
+
const layers = [];
|
|
13
|
+
for (const pkg of graph.packages) {
|
|
14
|
+
const tsconfigPath = resolveTsconfigPath({
|
|
15
|
+
configDir: pkg.absolutePath,
|
|
16
|
+
repoRoot: pkg.absolutePath,
|
|
17
|
+
});
|
|
18
|
+
if (!tsconfigPath)
|
|
19
|
+
continue;
|
|
20
|
+
const { entries, warnings } = loadTsconfigChain(tsconfigPath);
|
|
21
|
+
if (onWarning)
|
|
22
|
+
for (const w of warnings)
|
|
23
|
+
onWarning(`${pkg.name}: ${w}`);
|
|
24
|
+
if (entries.length === 0)
|
|
25
|
+
continue;
|
|
26
|
+
layers.push({ pkgRealPath: safeRealpath(pkg.absolutePath), entries });
|
|
27
|
+
}
|
|
28
|
+
// Longest path first → nested packages beat their ancestors.
|
|
29
|
+
layers.sort((a, b) => b.pkgRealPath.length - a.pkgRealPath.length);
|
|
30
|
+
return layers;
|
|
31
|
+
}
|
|
32
|
+
function safeRealpath(p) {
|
|
33
|
+
try {
|
|
34
|
+
return realpathSync(p);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return p;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=package-alias-layers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-alias-layers.js","sourceRoot":"","sources":["../../src/walker/package-alias-layers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAmB,MAAM,sBAAsB,CAAC;AAI1E,MAAM,UAAU,uBAAuB,CACrC,KAAqB,EACrB,SAAqC;IAErC,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,YAAY,GAAG,mBAAmB,CAAC;YACvC,SAAS,EAAE,GAAG,CAAC,YAAY;YAC3B,QAAQ,EAAE,GAAG,CAAC,YAAY;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,YAAY;YAAE,SAAS;QAC5B,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAC9D,IAAI,SAAS;YAAE,KAAK,MAAM,CAAC,IAAI,QAAQ;gBAAE,SAAS,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC;QACxE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,MAAM,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,6DAA6D;IAC7D,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ResolveImport } from "@component-compass/plugin-core";
|
|
2
|
+
import type { PackageAliasLayer } from "./package-alias-layers.js";
|
|
2
3
|
import type { WorkspaceGraph } from "../workspace/types.js";
|
|
3
4
|
export type { ResolveImport } from "@component-compass/plugin-core";
|
|
4
5
|
export type CreateImportResolverOptions = {
|
|
@@ -13,6 +14,9 @@ export type CreateImportResolverOptions = {
|
|
|
13
14
|
* See workspace-exports.ts for the supported `exports` shapes.
|
|
14
15
|
*/
|
|
15
16
|
workspaceGraph?: WorkspaceGraph;
|
|
17
|
+
/** Per-workspace-package tsconfig alias layers; the layer whose pkgRealPath
|
|
18
|
+
* owns `from` is applied between config aliases and the root tsconfig layer. */
|
|
19
|
+
packageAliasLayers?: PackageAliasLayer[];
|
|
16
20
|
/** Called once per non-fatal warning produced while loading the tsconfig chain
|
|
17
21
|
* (unreadable file, parse error, unresolvable extends, cycle). Invoked at
|
|
18
22
|
* resolver construction time, not per resolution call. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { statSync } from "node:fs";
|
|
1
|
+
import { realpathSync, statSync } from "node:fs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, isAbsolute, resolve as pathResolve } from "node:path";
|
|
4
4
|
import { loadTsconfigChain, compileAliasPattern } from "./tsconfig-loader.js";
|
|
@@ -8,9 +8,11 @@ import { buildWorkspaceExportEntries } from "./workspace-exports.js";
|
|
|
8
8
|
*
|
|
9
9
|
* Resolution order (first hit wins):
|
|
10
10
|
* 1. Config `aliases` (explicit user-supplied alias map).
|
|
11
|
-
* 2.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* 2. The owning workspace package's own tsconfig `paths` layer (when
|
|
12
|
+
* `packageAliasLayers` provided and `from` sits inside a member).
|
|
13
|
+
* 3. `compilerOptions.paths` from the tsconfig at `tsconfigPath`.
|
|
14
|
+
* 4. `package.json#exports` from each workspace package (when `workspaceGraph` provided).
|
|
15
|
+
* 5. Node module resolution via `require.resolve`.
|
|
14
16
|
*
|
|
15
17
|
* Returns the absolute path of the resolved file, or `null` if no layer
|
|
16
18
|
* matches. See spec §3.5.
|
|
@@ -31,6 +33,28 @@ export function createImportResolver(opts) {
|
|
|
31
33
|
const workspaceExportEntries = opts.workspaceGraph
|
|
32
34
|
? buildWorkspaceExportEntries(opts.workspaceGraph)
|
|
33
35
|
: [];
|
|
36
|
+
const pkgLayers = opts.packageAliasLayers ?? [];
|
|
37
|
+
const fromDirRealCache = new Map();
|
|
38
|
+
const ownerEntriesFor = (fromDir) => {
|
|
39
|
+
if (pkgLayers.length === 0)
|
|
40
|
+
return [];
|
|
41
|
+
let real = fromDirRealCache.get(fromDir);
|
|
42
|
+
if (real === undefined) {
|
|
43
|
+
try {
|
|
44
|
+
real = realpathSync(fromDir);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
real = fromDir;
|
|
48
|
+
}
|
|
49
|
+
fromDirRealCache.set(fromDir, real);
|
|
50
|
+
}
|
|
51
|
+
for (const layer of pkgLayers) {
|
|
52
|
+
const withSep = layer.pkgRealPath.endsWith("/") ? layer.pkgRealPath : `${layer.pkgRealPath}/`;
|
|
53
|
+
if (real === layer.pkgRealPath || real.startsWith(withSep))
|
|
54
|
+
return layer.entries;
|
|
55
|
+
}
|
|
56
|
+
return [];
|
|
57
|
+
};
|
|
34
58
|
// Reused for `require.resolve` fallback. Anchoring at <repoRoot>/_ ensures
|
|
35
59
|
// Node walks up through <repoRoot>/node_modules and parents.
|
|
36
60
|
const requireFromRepo = createRequire(pathResolve(opts.repoRoot, "_"));
|
|
@@ -50,7 +74,7 @@ export function createImportResolver(opts) {
|
|
|
50
74
|
return result;
|
|
51
75
|
};
|
|
52
76
|
function resolveUncached(fromDir, spec) {
|
|
53
|
-
for (const layers of [configEntries, tsconfigEntries, workspaceExportEntries]) {
|
|
77
|
+
for (const layers of [configEntries, ownerEntriesFor(fromDir), tsconfigEntries, workspaceExportEntries]) {
|
|
54
78
|
for (const entry of layers) {
|
|
55
79
|
const m = entry.pattern.exec(spec);
|
|
56
80
|
if (!m)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-import.js","sourceRoot":"","sources":["../../src/walker/resolve-import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve-import.js","sourceRoot":"","sources":["../../src/walker/resolve-import.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,7 +28,9 @@ export type TsconfigDiscoveryInput = {
|
|
|
28
28
|
* handles `extends` from there. Deliberately does NOT walk up from configDir
|
|
29
29
|
* or repoRoot.
|
|
30
30
|
*
|
|
31
|
-
* Per-package tsconfigs in monorepos
|
|
32
|
-
*
|
|
31
|
+
* Per-package tsconfigs in monorepos are handled separately by
|
|
32
|
+
* `buildPackageAliasLayers` (walker/package-alias-layers.ts), which calls
|
|
33
|
+
* this function once per workspace member with configDir = repoRoot = the
|
|
34
|
+
* member's own directory.
|
|
33
35
|
*/
|
|
34
36
|
export declare function resolveTsconfigPath(input: TsconfigDiscoveryInput): string | null;
|
|
@@ -17,8 +17,10 @@ import { isAbsolute, resolve, join } from "node:path";
|
|
|
17
17
|
* handles `extends` from there. Deliberately does NOT walk up from configDir
|
|
18
18
|
* or repoRoot.
|
|
19
19
|
*
|
|
20
|
-
* Per-package tsconfigs in monorepos
|
|
21
|
-
*
|
|
20
|
+
* Per-package tsconfigs in monorepos are handled separately by
|
|
21
|
+
* `buildPackageAliasLayers` (walker/package-alias-layers.ts), which calls
|
|
22
|
+
* this function once per workspace member with configDir = repoRoot = the
|
|
23
|
+
* member's own directory.
|
|
22
24
|
*/
|
|
23
25
|
export function resolveTsconfigPath(input) {
|
|
24
26
|
if (input.tsconfigPath) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tsconfig-discovery.js","sourceRoot":"","sources":["../../src/walker/tsconfig-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAgBtD
|
|
1
|
+
{"version":3,"file":"tsconfig-discovery.js","sourceRoot":"","sources":["../../src/walker/tsconfig-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAgBtD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAA6B;IAC/D,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,OAAO,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC;YACnC,CAAC,CAAC,KAAK,CAAC,YAAY;YACpB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IACnD,CAAC;IACD,wEAAwE;IACxE,uEAAuE;IACvE,2EAA2E;IAC3E,sEAAsE;IACtE,wEAAwE;IACxE,qCAAqC;IACrC,MAAM,UAAU,GAAG,CAAC,eAAe,EAAE,oBAAoB,CAAC,CAAC;IAC3D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC5D,IAAI,UAAU,CAAC,kBAAkB,CAAC;YAAE,OAAO,kBAAkB,CAAC;IAChE,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC;QACvC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC1D,IAAI,UAAU,CAAC,iBAAiB,CAAC;gBAAE,OAAO,iBAAiB,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1,54 +1,118 @@
|
|
|
1
1
|
import { compileAliasPattern } from "./tsconfig-loader.js";
|
|
2
|
-
//
|
|
3
|
-
//
|
|
2
|
+
// The workspace-member name→source resolution seam. For every member, emit
|
|
3
|
+
// resolver entries so any import of the member's name resolves to its source
|
|
4
|
+
// on disk — independent of install state (no symlink needed) and winning over
|
|
5
|
+
// a version-pinned published copy in node_modules (this layer precedes Node
|
|
6
|
+
// resolution). Per member, in precedence order:
|
|
4
7
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
+
// 1. Declared `exports` subpaths (existing behaviour):
|
|
9
|
+
// - Constant: "./types" -> "./types.ts" matches <pkgName>/types exactly.
|
|
10
|
+
// - Pattern: "./icons/<star>" -> "./icons/<star>.tsx".
|
|
11
|
+
// Skipped shapes (follow-ups if a real consumer hits them): conditional
|
|
12
|
+
// objects, null targets, multi-wildcard targets, non-subpath keys.
|
|
13
|
+
// Note: a `null` (deny) subpath is deliberately overridden by the
|
|
14
|
+
// wildcard source probe below — this seam attributes usage to source;
|
|
15
|
+
// it does not enforce publish-time encapsulation.
|
|
16
|
+
// 2. One bare-name entry: <pkgName> -> [exports["."], module, main, ".", "./src"].
|
|
17
|
+
// The "." / "./src" directory targets rely on tryFileWithExtensions'
|
|
18
|
+
// index probing. Conditional exports["."] contributes its first string
|
|
19
|
+
// among import/module/default (one level deep).
|
|
20
|
+
// 3. One wildcard fallback: <pkgName>/<star> -> ./<star> (source-tree probe).
|
|
8
21
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// - Non-subpath keys (the "." self-reference, "#imports", conditional roots)
|
|
14
|
-
// - Bare-string exports (sugar for the "." main-entry case)
|
|
15
|
-
//
|
|
16
|
-
// Within a package, entries sort by static-prefix length descending so more-
|
|
17
|
-
// specific subpaths (e.g. "./icons/special") beat patterns (e.g. "./icons/<star>")
|
|
18
|
-
// for the same spec — matches the Node.js exports-map specificity rule.
|
|
22
|
+
// Within a package, subpath entries sort by static-prefix length descending so
|
|
23
|
+
// more-specific subpaths beat patterns — matches Node's exports specificity
|
|
24
|
+
// rule; the bare-name and wildcard entries follow, so declared exports always
|
|
25
|
+
// win when their targets exist on disk.
|
|
19
26
|
export function buildWorkspaceExportEntries(graph) {
|
|
20
27
|
const out = [];
|
|
21
28
|
for (const pkg of graph.packages) {
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
out.push(...subpathExportEntries(pkg));
|
|
30
|
+
out.push(bareNameEntry(pkg));
|
|
31
|
+
out.push({
|
|
32
|
+
pattern: wildcardPattern(pkg.name),
|
|
33
|
+
targets: ["./*"],
|
|
34
|
+
base: pkg.absolutePath,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function subpathExportEntries(pkg) {
|
|
40
|
+
const exports = pkg.packageJson.exports;
|
|
41
|
+
if (exports === null || exports === undefined)
|
|
42
|
+
return [];
|
|
43
|
+
if (typeof exports !== "object")
|
|
44
|
+
return [];
|
|
45
|
+
if (Array.isArray(exports))
|
|
46
|
+
return [];
|
|
47
|
+
const out = [];
|
|
48
|
+
const subpaths = Object.entries(exports)
|
|
49
|
+
.filter(([key]) => key.startsWith("./") && key !== "./")
|
|
50
|
+
.sort(([a], [b]) => staticPrefixLength(b) - staticPrefixLength(a));
|
|
51
|
+
for (const [subpath, target] of subpaths) {
|
|
52
|
+
if (target === null)
|
|
24
53
|
continue;
|
|
25
|
-
if (typeof
|
|
54
|
+
if (typeof target !== "string")
|
|
26
55
|
continue;
|
|
27
|
-
if (
|
|
56
|
+
if (target.includes("**"))
|
|
28
57
|
continue;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
continue;
|
|
39
|
-
if (target.split("*").length > 2)
|
|
40
|
-
continue;
|
|
41
|
-
// "./icons/*" + "@example/icons" → "@example/icons/icons/*"
|
|
42
|
-
const fullPattern = `${pkg.name}${subpath.slice(1)}`;
|
|
43
|
-
out.push({
|
|
44
|
-
pattern: compileAliasPattern(fullPattern),
|
|
45
|
-
targets: [target],
|
|
46
|
-
base: pkg.absolutePath,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
58
|
+
if (target.split("*").length > 2)
|
|
59
|
+
continue;
|
|
60
|
+
// "./icons/*" + "@example/icons" → "@example/icons/icons/*"
|
|
61
|
+
const fullPattern = `${pkg.name}${subpath.slice(1)}`;
|
|
62
|
+
out.push({
|
|
63
|
+
pattern: compileAliasPattern(fullPattern),
|
|
64
|
+
targets: [target],
|
|
65
|
+
base: pkg.absolutePath,
|
|
66
|
+
});
|
|
49
67
|
}
|
|
50
68
|
return out;
|
|
51
69
|
}
|
|
70
|
+
function bareNameEntry(pkg) {
|
|
71
|
+
const targets = [];
|
|
72
|
+
const dot = dotExportTarget(pkg.packageJson.exports);
|
|
73
|
+
if (dot !== null)
|
|
74
|
+
targets.push(dot);
|
|
75
|
+
if (typeof pkg.packageJson.module === "string")
|
|
76
|
+
targets.push(pkg.packageJson.module);
|
|
77
|
+
if (typeof pkg.packageJson.main === "string")
|
|
78
|
+
targets.push(pkg.packageJson.main);
|
|
79
|
+
targets.push(".", "./src");
|
|
80
|
+
return {
|
|
81
|
+
pattern: compileAliasPattern(pkg.name),
|
|
82
|
+
targets,
|
|
83
|
+
base: pkg.absolutePath,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// `<pkgName>/*` with `..` path segments rejected, so the source-tree probe
|
|
87
|
+
// cannot expand outside the member directory (`@ws/ui/../secret` falls through
|
|
88
|
+
// to Node resolution instead). `..` inside a segment name (`a..b`) stays legal.
|
|
89
|
+
// Reuses compileAliasPattern for the name's regex escaping; the name itself
|
|
90
|
+
// contains no `*`, so the compiled source is the escaped literal.
|
|
91
|
+
function wildcardPattern(pkgName) {
|
|
92
|
+
const escapedName = compileAliasPattern(pkgName).source.slice(1, -1);
|
|
93
|
+
return new RegExp(`^${escapedName}/((?!\\.\\.(?:/|$))(?:(?!/\\.\\.(?:/|$)).)*)$`);
|
|
94
|
+
}
|
|
95
|
+
// exports["."] as an entry-point target: string form, the bare-string sugar,
|
|
96
|
+
// or (one level deep) the first string among import/module/default in a
|
|
97
|
+
// conditional object. Anything else → null (bare-name entry falls through to
|
|
98
|
+
// module/main/directory probes).
|
|
99
|
+
function dotExportTarget(exports) {
|
|
100
|
+
if (typeof exports === "string")
|
|
101
|
+
return exports;
|
|
102
|
+
if (exports === null || typeof exports !== "object" || Array.isArray(exports))
|
|
103
|
+
return null;
|
|
104
|
+
const dot = exports["."];
|
|
105
|
+
if (typeof dot === "string")
|
|
106
|
+
return dot;
|
|
107
|
+
if (dot !== null && typeof dot === "object" && !Array.isArray(dot)) {
|
|
108
|
+
for (const key of ["import", "module", "default"]) {
|
|
109
|
+
const value = dot[key];
|
|
110
|
+
if (typeof value === "string")
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
52
116
|
function staticPrefixLength(subpath) {
|
|
53
117
|
const starIdx = subpath.indexOf("*");
|
|
54
118
|
return starIdx === -1 ? subpath.length : starIdx;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-exports.js","sourceRoot":"","sources":["../../src/walker/workspace-exports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG3D,+EAA+E;AAC/E,
|
|
1
|
+
{"version":3,"file":"workspace-exports.js","sourceRoot":"","sources":["../../src/walker/workspace-exports.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
import type { WorkspaceGraph } from "./types.js";
|
|
1
|
+
import type { WorkspaceGraph, WorkspacePackage } from "./types.js";
|
|
2
2
|
export declare function buildWorkspaceGraph(rootPath: string): WorkspaceGraph;
|
|
3
|
+
/**
|
|
4
|
+
* Loosened input for `detectWorkspacePackages`: only the `workspaces` field
|
|
5
|
+
* is typed, plus an index signature so callers can pass any freshly-parsed,
|
|
6
|
+
* unvalidated `package.json` (e.g. `findWorkspaceRoot` walking arbitrary
|
|
7
|
+
* ancestor directories) without casting at the call site.
|
|
8
|
+
*/
|
|
9
|
+
export type DetectWorkspacePackagesInput = Record<string, unknown> & {
|
|
10
|
+
workspaces?: WorkspacePackage["packageJson"]["workspaces"];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* pnpm-workspace.yaml → package.json#workspaces → empty array.
|
|
14
|
+
*/
|
|
15
|
+
export declare function detectWorkspacePackages(absRoot: string, rootPkg: DetectWorkspacePackagesInput): WorkspacePackage[];
|
|
@@ -35,7 +35,10 @@ function sniffPackageManager(absRoot) {
|
|
|
35
35
|
return "yarn";
|
|
36
36
|
return "unknown";
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
/**
|
|
39
|
+
* pnpm-workspace.yaml → package.json#workspaces → empty array.
|
|
40
|
+
*/
|
|
41
|
+
export function detectWorkspacePackages(absRoot, rootPkg) {
|
|
39
42
|
// pnpm-workspace.yaml wins when both configs present.
|
|
40
43
|
const pnpmYamlPath = join(absRoot, "pnpm-workspace.yaml");
|
|
41
44
|
if (existsSync(pnpmYamlPath)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-graph.js","sourceRoot":"","sources":["../../src/workspace/build-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAGhC,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,cAAc,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IACtD,MAAM,eAAe,GACnB,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC;IAEhE,OAAO;QACL,cAAc,EAAE,mBAAmB,CAAC,OAAO,CAAC;QAC5C,QAAQ,EAAE,OAAO;QACjB,eAAe;QACf,QAAQ,EAAE,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe;IAC1C,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/D,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACjE,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1D,OAAO,SAAS,CAAC;AACnB,CAAC;
|
|
1
|
+
{"version":3,"file":"build-graph.js","sourceRoot":"","sources":["../../src/workspace/build-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function findWorkspaceRoot(scanRoot: string, stopAt?: string): string | null;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walk up from scanRoot to the nearest ancestor that declares workspaces
|
|
3
|
+
* (pnpm-workspace.yaml or package.json#workspaces) AND whose expanded member
|
|
4
|
+
* globs include scanRoot. Spec Piece 1: ownership/resolution anchor at the
|
|
5
|
+
* true workspace root, independent of where the scan is pointed.
|
|
6
|
+
*
|
|
7
|
+
* The walk starts at dirname(scanRoot): a scanRoot that is itself a workspace
|
|
8
|
+
* root needs no promotion (caller falls back to scanRoot).
|
|
9
|
+
* Bounded by stopAt (inclusive; typically the git toplevel) and the fs root.
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
12
|
+
import { dirname, join, resolve } from "node:path";
|
|
13
|
+
import { detectWorkspacePackages } from "./build-graph.js";
|
|
14
|
+
export function findWorkspaceRoot(scanRoot, stopAt) {
|
|
15
|
+
const absScan = safeRealpath(resolve(scanRoot));
|
|
16
|
+
const stop = stopAt ? safeRealpath(resolve(stopAt)) : null;
|
|
17
|
+
let dir = dirname(absScan);
|
|
18
|
+
// stopAt below scanRoot's parent → nothing to walk.
|
|
19
|
+
for (;;) {
|
|
20
|
+
if (stop && !isPathPrefix(stop, dir))
|
|
21
|
+
return null;
|
|
22
|
+
const pkgJsonPath = join(dir, "package.json");
|
|
23
|
+
const hasPnpmYaml = existsSync(join(dir, "pnpm-workspace.yaml"));
|
|
24
|
+
if (hasPnpmYaml || existsSync(pkgJsonPath)) {
|
|
25
|
+
const rootPkg = readJsonSafely(pkgJsonPath) ?? {};
|
|
26
|
+
const members = detectWorkspacePackages(dir, rootPkg);
|
|
27
|
+
if (members.some((m) => safeRealpath(m.absolutePath) === absScan))
|
|
28
|
+
return dir;
|
|
29
|
+
}
|
|
30
|
+
const parent = dirname(dir);
|
|
31
|
+
if (parent === dir)
|
|
32
|
+
return null;
|
|
33
|
+
dir = parent;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function readJsonSafely(p) {
|
|
37
|
+
try {
|
|
38
|
+
// JSON.parse returns `any`, which assigns to DetectWorkspacePackagesInput
|
|
39
|
+
// without a cast — matches build-graph.ts's own local readJsonSafely.
|
|
40
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function safeRealpath(p) {
|
|
47
|
+
try {
|
|
48
|
+
return realpathSync(p);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return p;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function isPathPrefix(prefix, candidate) {
|
|
55
|
+
if (candidate === prefix)
|
|
56
|
+
return true;
|
|
57
|
+
const withSep = prefix.endsWith("/") ? prefix : `${prefix}/`;
|
|
58
|
+
return candidate.startsWith(withSep);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=find-workspace-root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-workspace-root.js","sourceRoot":"","sources":["../../src/workspace/find-workspace-root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAqC,MAAM,kBAAkB,CAAC;AAE9F,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,MAAe;IACjE,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3D,IAAI,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,oDAAoD;IACpD,SAAS,CAAC;QACR,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC,CAAC;QACjE,IAAI,WAAW,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG,cAAc,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAClD,MAAM,OAAO,GAAG,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACtD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC;gBAAE,OAAO,GAAG,CAAC;QAChF,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,CAAS;IAC/B,IAAI,CAAC;QACH,0EAA0E;QAC1E,sEAAsE;QACtE,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,MAAc,EAAE,SAAiB;IACrD,IAAI,SAAS,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC;IAC7D,OAAO,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC"}
|