@akanjs/devkit 3.0.0-beta.19 → 3.0.0-beta.20
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/abstractDoc.test.ts +6 -15
- package/abstractDoc.ts +1 -4
- package/agentsIndex.test.ts +4 -7
- package/agentsIndex.ts +6 -22
- package/akanApp/BackendImportGraph.test.ts +8 -22
- package/akanApp/BackendImportGraph.ts +1 -20
- package/akanApp/akanApp.host.test.ts +1 -3
- package/akanApp/akanApp.host.ts +64 -250
- package/akanApp/devHostPolicy.test.ts +10 -34
- package/akanApp/devHostPolicy.ts +12 -98
- package/akanConfig/akanConfig.test.ts +30 -39
- package/akanConfig/akanConfig.ts +40 -136
- package/akanContext.ts +106 -159
- package/akanMcpContract.ts +28 -73
- package/appSelectionMemory.ts +1 -4
- package/applicationBuildReporter.ts +37 -5
- package/applicationBuildRunner.ts +25 -59
- package/applicationReleasePackager.ts +24 -44
- package/applicationTestPreload.ts +3 -12
- package/artifact/implicitRootLayout.test.ts +3 -19
- package/artifact/implicitRootLayout.ts +34 -91
- package/artifact/routeSeedIndex.ts +11 -44
- package/biomeBase.ts +2 -5
- package/capacitorApp.test.ts +4 -14
- package/capacitorApp.ts +86 -235
- package/cloud/cloudApi.test.ts +202 -0
- package/cloud/cloudApi.ts +33 -57
- package/cloud/configLock.test.ts +64 -0
- package/cloud/configLock.ts +96 -0
- package/cloud/constants.ts +3 -2
- package/cloud/globalConfig.ts +64 -31
- package/codeAgent/agent/AkanCodeServices.ts +15 -57
- package/codeAgent/agent/AkanContextFiles.ts +5 -28
- package/codeAgent/agent/CodeAgent.ts +33 -108
- package/codeAgent/agent/CodeAgentAsks.ts +7 -30
- package/codeAgent/agent/CodeAgentEventMapper.ts +9 -52
- package/codeAgent/agent/CodeAgentGate.ts +8 -34
- package/codeAgent/agent/CodeAgentProxy.ts +4 -13
- package/codeAgent/agent/CodeAgentRpcHost.ts +3 -16
- package/codeAgent/agent/CodeAgentRpcListener.ts +2 -10
- package/codeAgent/agent/CodeAgentStreamPrinter.ts +4 -15
- package/codeAgent/agent/CodeAgentSuspended.ts +1 -8
- package/codeAgent/agent/CodeAgentUi.ts +2 -7
- package/codeAgent/agent/CodeMailbox.ts +7 -34
- package/codeAgent/agent/CodeSessionFork.ts +4 -19
- package/codeAgent/agent/CodeSessionIndex.ts +5 -31
- package/codeAgent/agent/SubagentPool.ts +48 -58
- package/codeAgent/agent/akanCodeModel.ts +5 -39
- package/codeAgent/agent/akanCodePaths.ts +4 -24
- package/codeAgent/agent/akanContextFiles.test.ts +0 -2
- package/codeAgent/agent/akanSystemPrompt.ts +1 -9
- package/codeAgent/agent/codeAgent.test.ts +178 -0
- package/codeAgent/agent/codeAgentContract.test.ts +5 -28
- package/codeAgent/agent/codeMailbox.test.ts +0 -4
- package/codeAgent/agent/codeSessionFork.test.ts +0 -2
- package/codeAgent/agent/codeSessionIndex.test.ts +9 -4
- package/codeAgent/agent/consoleToStderr.ts +2 -12
- package/codeAgent/agent/jsonLines.ts +29 -0
- package/codeAgent/agent/stringArg.ts +5 -0
- package/codeAgent/feedback/DevLogFeedback.ts +3 -18
- package/codeAgent/feedback/PreviewChrome.ts +5 -29
- package/codeAgent/feedback/PreviewFeedback.ts +2 -9
- package/codeAgent/feedback/PreviewView.ts +3 -15
- package/codeAgent/feedback/TurnFeedback.ts +2 -17
- package/codeAgent/feedback/VerifyFeedback.ts +1 -7
- package/codeAgent/feedback/previewChrome.test.ts +1 -1
- package/codeAgent/index.ts +2 -10
- package/codeAgent/skills/akan-code/SKILL.md +12 -4
- package/codeAgent/tools/AkanCli.ts +4 -16
- package/codeAgent/tools/AkanCodePlugins.ts +21 -43
- package/codeAgent/tools/AkanEditScope.ts +2 -12
- package/codeAgent/tools/AkanEnvKeys.ts +3 -11
- package/codeAgent/tools/AkanToolPack.ts +6 -28
- package/codeAgent/tools/AkanVerifier.ts +1 -8
- package/codeAgent/tools/AskToolPack.ts +3 -15
- package/codeAgent/tools/MailToolPack.ts +0 -9
- package/codeAgent/tools/McpClient.ts +3 -24
- package/codeAgent/tools/McpOAuth.ts +6 -41
- package/codeAgent/tools/McpOAuthLoopback.ts +2 -15
- package/codeAgent/tools/McpServerConfig.ts +7 -26
- package/codeAgent/tools/McpSignIn.ts +46 -49
- package/codeAgent/tools/McpTokenStore.ts +6 -17
- package/codeAgent/tools/McpToolPack.ts +107 -35
- package/codeAgent/tools/SessionToolPack.ts +1 -11
- package/codeAgent/tools/WebToolPack.ts +1 -7
- package/codeAgent/tools/akanCodePlugins.test.ts +231 -63
- package/codeAgent/tools/askToolPack.test.ts +0 -3
- package/codeAgent/tools/mcpOAuth.test.ts +315 -27
- package/codeAgent/tools/mcpServerConfig.test.ts +21 -14
- package/codegenLock.test.ts +4 -13
- package/codegenLock.ts +3 -17
- package/commandDecorators/argMeta.ts +1 -5
- package/commandDecorators/camelToKebabCase.ts +1 -0
- package/commandDecorators/command.ts +44 -102
- package/commandDecorators/commandBuilder.ts +30 -61
- package/commandDecorators/commandDecorators.test.ts +1 -9
- package/commandDecorators/dependencyBuilder.ts +10 -1
- package/commandDecorators/helpFormatter.ts +66 -144
- package/commandDecorators/index.ts +0 -2
- package/commandDecorators/targetMeta.ts +9 -7
- package/createTunnel.ts +7 -14
- package/dependencyScanner.test.ts +4 -16
- package/dependencyScanner.ts +27 -78
- package/devkitUtils.test.ts +47 -19
- package/executors.test.ts +114 -60
- package/executors.ts +165 -484
- package/fileEditor.ts +9 -37
- package/{getDirname.test.ts → fileSys.test.ts} +1 -1
- package/fileSys.ts +6 -8
- package/formSetterScanner.ts +3 -16
- package/frontendBuild/allRoutesBuilder.ts +7 -21
- package/frontendBuild/autoImportSync.test.ts +14 -38
- package/frontendBuild/autoImportSync.ts +15 -67
- package/frontendBuild/buildRouteClient.test.ts +10 -36
- package/frontendBuild/bundleDefine.ts +12 -0
- package/frontendBuild/clientBuildTypes.ts +5 -36
- package/frontendBuild/clientEntriesBundler.ts +9 -40
- package/frontendBuild/clientEntryDiscovery.ts +6 -41
- package/frontendBuild/csrArtifactBuilder.ts +6 -25
- package/frontendBuild/cssCandidateCache.test.ts +0 -6
- package/frontendBuild/cssCandidateCache.ts +6 -41
- package/frontendBuild/cssCompiler.ts +29 -78
- package/frontendBuild/cssImportResolver.ts +5 -18
- package/frontendBuild/devChangePlanner.ts +7 -10
- package/frontendBuild/devGeneratedIndexSync.test.ts +12 -27
- package/frontendBuild/devGeneratedIndexSync.ts +1 -4
- package/frontendBuild/fontOptimizer.test.ts +5 -13
- package/frontendBuild/fontOptimizer.ts +15 -72
- package/frontendBuild/fontPruner.test.ts +5 -10
- package/frontendBuild/fontPruner.ts +5 -20
- package/frontendBuild/frontendBuild.test.ts +27 -52
- package/frontendBuild/hmrChangeClassifier.ts +2 -2
- package/frontendBuild/hmrWatcher.test.ts +7 -31
- package/frontendBuild/hmrWatcher.ts +14 -71
- package/frontendBuild/pagesBundleBuilder.ts +4 -29
- package/frontendBuild/precompressArtifacts.ts +5 -18
- package/frontendBuild/routeClientBuilder.ts +7 -47
- package/frontendBuild/routesManifestArtifactSerializer.ts +5 -36
- package/frontendBuild/sourceMtimeIndex.test.ts +37 -94
- package/frontendBuild/sourceMtimeIndex.ts +19 -130
- package/frontendBuild/ssrBaseArtifactBuilder.ts +2 -8
- package/frontendBuild/styleContract.ts +1 -8
- package/frontendBuild/themeValidator.ts +4 -26
- package/frontendBuild/watchRootResolver.test.ts +23 -42
- package/frontendBuild/watchRootResolver.ts +5 -27
- package/getRelatedCnsts.ts +12 -92
- package/incrementalBuilder/buildBatch.proc.ts +22 -57
- package/incrementalBuilder/buildBatchProtocol.ts +8 -36
- package/incrementalBuilder/buildBatchRunner.test.ts +34 -0
- package/incrementalBuilder/buildBatchRunner.ts +10 -31
- package/incrementalBuilder/builderChannel.test.ts +24 -49
- package/incrementalBuilder/builderChannel.ts +6 -37
- package/incrementalBuilder/builderRequestRouter.test.ts +0 -8
- package/incrementalBuilder/builderRequestRouter.ts +5 -24
- package/incrementalBuilder/devWatchBatch.test.ts +14 -18
- package/incrementalBuilder/incrementalBuilder.host.test.ts +18 -55
- package/incrementalBuilder/incrementalBuilder.host.ts +18 -76
- package/incrementalBuilder/incrementalBuilder.proc.test.ts +81 -0
- package/incrementalBuilder/incrementalBuilder.proc.ts +48 -161
- package/index.ts +3 -15
- package/integration/devResourceProbe.ts +50 -56
- package/integration/devStability.integration.test.ts +47 -194
- package/integration/devStabilityHarness.test.ts +9 -29
- package/integration/devStabilityHarness.ts +65 -330
- package/integration/ssrMemoryProbe.ts +41 -167
- package/libSource.test.ts +4 -15
- package/libSource.ts +19 -31
- package/lint/gritRules.test.ts +6 -23
- package/linter.test.ts +1 -2
- package/linter.ts +22 -115
- package/mobile/mobileTarget.ts +14 -13
- package/package.json +2 -2
- package/packageExports.test.ts +3 -18
- package/packageExportsMap.ts +3 -19
- package/piDependencyPins.test.ts +3 -14
- package/platformTest/IdleWatchedProcess.test.ts +5 -13
- package/platformTest/IdleWatchedProcess.ts +1 -5
- package/platformTest/LinuxDockerTarget.ts +20 -35
- package/platformTest/PlatformTestRun.test.ts +5 -9
- package/platformTest/PlatformTestTarget.ts +24 -2
- package/platformTest/TestSnapshot.test.ts +6 -14
- package/platformTest/TestSnapshot.ts +1 -5
- package/platformTest/WindowsSshTarget.ts +6 -22
- package/prompter.ts +3 -6
- package/qualityScanner.test.ts +6 -24
- package/qualityScanner.ts +196 -284
- package/recipeScanner.test.ts +7 -12
- package/recipeScanner.ts +9 -38
- package/repoIdentity.ts +2 -9
- package/routeSourceValidator.ts +7 -30
- package/scanInfo.ts +82 -214
- package/selectModel.ts +1 -2
- package/semver.ts +3 -5
- package/slicePlanner.test.ts +6 -24
- package/slicePlanner.ts +11 -32
- package/spinner.test.ts +3 -8
- package/spinner.ts +4 -16
- package/sshTunnel.ts +1 -6
- package/ssrScanner.test.ts +1 -6
- package/ssrScanner.ts +103 -113
- package/subspace.test.ts +6 -25
- package/subspace.ts +31 -109
- package/subspaceConfig.ts +3 -11
- package/testHelpers.ts +49 -34
- package/transforms/asyncDefaultExportDetector.ts +3 -11
- package/transforms/barrelAnalyzer.ts +43 -135
- package/transforms/barrelImportsPlugin.ts +38 -175
- package/transforms/externalizeFrameworkPlugin.test.ts +39 -118
- package/transforms/externalizeFrameworkPlugin.ts +13 -87
- package/transforms/moduleSyntax.ts +32 -0
- package/transforms/rscUseClientTransform.ts +35 -20
- package/transforms/transforms.test.ts +153 -44
- package/transforms/tsconfigPackageResolver.test.ts +6 -24
- package/transforms/useClientBundlePlugin.ts +2 -22
- package/typeChecker.ts +7 -63
- package/uploadRelease.ts +10 -25
- package/workflow/artifacts.ts +18 -0
- package/workflow/executor.test.ts +1 -12
- package/workflow/executor.ts +85 -146
- package/workflow/index.ts +0 -1
- package/workflow/moduleIndex.test.ts +4 -15
- package/workflow/moduleIndex.ts +9 -49
- package/workflow/plan.ts +18 -25
- package/workflow/render.ts +80 -96
- package/workflow/source.ts +33 -56
- package/workflow/sourceAst.ts +50 -0
- package/workspaceLayout.ts +4 -19
- package/commandDecorators/commandMeta.ts +0 -7
- package/commandDecorators/types.ts +0 -10
- package/getDirname.ts +0 -4
- package/local/optimize-resource/ipcprobe/child.ts +0 -1
- package/local/optimize-resource/ipcprobe/parent.ts +0 -11
- package/workflow/primitive.ts +0 -59
|
@@ -1,44 +1,36 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { Logger } from "akanjs/common";
|
|
3
|
+
import { parseNamedList } from "./moduleSyntax";
|
|
3
4
|
|
|
4
5
|
export interface BarrelExportTarget {
|
|
5
|
-
/** Subpath specifier to emit in rewritten import, e.g. `akanjs/ui/Empty`. */
|
|
6
6
|
subpath: string;
|
|
7
|
-
/** Name as it is exported by the leaf module. */
|
|
8
7
|
originalName: string;
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
export type BarrelExportMap = Map<string, BarrelExportTarget>;
|
|
12
11
|
|
|
13
12
|
export interface PackageEntry {
|
|
14
|
-
/** Package specifier (e.g. `akanjs/ui`). */
|
|
15
13
|
pkgName: string;
|
|
16
14
|
/** Absolute path of the barrel entry file. */
|
|
17
15
|
entryFile: string;
|
|
18
|
-
/** Absolute directory
|
|
16
|
+
/** Absolute base directory for subpath computation, typically `dirname(entryFile)`. */
|
|
19
17
|
pkgDir: string;
|
|
20
|
-
/**
|
|
18
|
+
/** Emit concrete file paths, for package exports that do not support extensionless deep imports. */
|
|
21
19
|
preserveFilePath?: boolean;
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
export interface BarrelAnalyzerOptions {
|
|
25
23
|
resolvePackage: (pkgName: string) => Promise<PackageEntry | null>;
|
|
26
|
-
/**
|
|
24
|
+
/** Resolves to an absolute file path on disk. */
|
|
27
25
|
resolveRelative?: (fromFile: string, relSpec: string) => Promise<string | null>;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
//
|
|
31
|
-
// `export * from "./x"`, `export * as ns from "./x"`. We rely on `Transpiler.scan`
|
|
32
|
-
// for the authoritative export name set; this regex only needs to give us the
|
|
33
|
-
// name↔source mapping that scan doesn't expose.
|
|
28
|
+
// `Transpiler.scan` gives the export names but not their sources; this regex supplies the name↔source mapping.
|
|
34
29
|
const REEXPORT_RE =
|
|
35
30
|
/(?:^|\n)\s*export\s+(?:type\s+)?(?:(\*)(?:\s+as\s+(\w+))?|\{\s*([^}]*?)\s*\})\s+from\s+(["'])([^"']+)\4;?/g;
|
|
36
31
|
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
// small regex fallback. The lookahead sits immediately after `}` so that
|
|
40
|
-
// greedy whitespace matching cannot backtrack past it — otherwise it would
|
|
41
|
-
// also match `export type { X } from "./y"` statements.
|
|
32
|
+
// `Transpiler.scan` omits `export { A, B as C };`. The lookahead sits right after `}` so whitespace backtracking
|
|
33
|
+
// cannot also match `export type { X } from "./y"`.
|
|
42
34
|
const LOCAL_NAMED_RE = /(?:^|\n)\s*export\s+\{\s*([^}]*?)\s*\}(?!\s*from)/g;
|
|
43
35
|
|
|
44
36
|
const CANDIDATE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
@@ -64,68 +56,53 @@ export class BarrelAnalyzer {
|
|
|
64
56
|
|
|
65
57
|
async #analyzeSafe(pkgName: string): Promise<BarrelExportMap | null> {
|
|
66
58
|
try {
|
|
67
|
-
|
|
59
|
+
const pkg = await this.#opts.resolvePackage(pkgName);
|
|
60
|
+
if (!pkg) return null;
|
|
61
|
+
const map: BarrelExportMap = new Map();
|
|
62
|
+
await this.#walk(pkg.entryFile, pkg, map, new Set());
|
|
63
|
+
return map;
|
|
68
64
|
} catch (err) {
|
|
69
65
|
this.#logger.error(`analyze failed for ${pkgName}: ${(err as Error).message}`);
|
|
70
66
|
return null;
|
|
71
67
|
}
|
|
72
68
|
}
|
|
73
69
|
|
|
74
|
-
async #analyzeUncached(pkgName: string): Promise<BarrelExportMap | null> {
|
|
75
|
-
const pkg = await this.#opts.resolvePackage(pkgName);
|
|
76
|
-
if (!pkg) return null;
|
|
77
|
-
const map: BarrelExportMap = new Map();
|
|
78
|
-
const visited = new Set<string>();
|
|
79
|
-
await this.#walk(pkg.entryFile, pkg, map, visited);
|
|
80
|
-
return map;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
70
|
async #walk(absFile: string, pkg: PackageEntry, map: BarrelExportMap, visited: Set<string>): Promise<void> {
|
|
84
71
|
if (visited.has(absFile)) return;
|
|
85
72
|
visited.add(absFile);
|
|
86
|
-
const
|
|
87
|
-
if (
|
|
73
|
+
const file = Bun.file(absFile);
|
|
74
|
+
if (!(await file.exists())) return;
|
|
75
|
+
const source = await file.text();
|
|
88
76
|
const currentSubpath = this.#subpathFor(pkg, absFile);
|
|
89
77
|
if (!currentSubpath) return;
|
|
90
78
|
|
|
91
|
-
//
|
|
92
|
-
// comments, strings, etc. automatically. `export *` re-exports are NOT
|
|
93
|
-
// flooded here — they only show up as imports, so we recurse separately.
|
|
79
|
+
// scan leaves out `export *` names (they surface only as imports), so star re-exports are walked below.
|
|
94
80
|
const authoritative = this.#scanExports(source, absFile);
|
|
95
|
-
//
|
|
96
|
-
// rewriting `import X from "pkg"` requires different semantics.
|
|
81
|
+
// Barrels rarely proxy defaults, and rewriting `import X from "pkg"` needs different semantics.
|
|
97
82
|
authoritative.delete("default");
|
|
98
83
|
|
|
99
|
-
// Names attributed to a specific leaf via `export ... from "./path"`.
|
|
100
|
-
// Everything left over in `authoritative` after this is treated as a local
|
|
101
|
-
// declaration at this file's own subpath.
|
|
102
84
|
const attributed = new Set<string>();
|
|
85
|
+
const attribute = (listBody: string, subpath: string) => {
|
|
86
|
+
for (const item of parseNamedList(listBody)) {
|
|
87
|
+
if (item.isType || item.imported === "default" || !authoritative.has(item.local)) continue;
|
|
88
|
+
attributed.add(item.local);
|
|
89
|
+
if (!map.has(item.local)) map.set(item.local, { subpath, originalName: item.imported });
|
|
90
|
+
}
|
|
91
|
+
};
|
|
103
92
|
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
while (m !== null) {
|
|
93
|
+
// A module's own exports shadow the names its stars bring (ES), so every one is mapped before a star is walked.
|
|
94
|
+
const starSpecs: string[] = [];
|
|
95
|
+
for (const m of source.matchAll(REEXPORT_RE)) {
|
|
108
96
|
const star = m[1];
|
|
109
97
|
const nsAs = m[2];
|
|
110
98
|
const namedList = m[3];
|
|
111
99
|
const spec = m[5] ?? "";
|
|
112
|
-
m = REEXPORT_RE.exec(source);
|
|
113
100
|
if (!isRelative(spec)) continue;
|
|
114
101
|
|
|
115
102
|
if (star) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// as a local declaration.
|
|
120
|
-
authoritative.delete(nsAs);
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
const targetAbs = await this.#resolveRel(absFile, spec);
|
|
124
|
-
if (!targetAbs) continue;
|
|
125
|
-
// Recurse: target's exports will land in `map` with target's subpath.
|
|
126
|
-
// These names don't appear in this file's `authoritative` set, so the
|
|
127
|
-
// local-declaration pass below won't misattribute them.
|
|
128
|
-
await this.#walk(targetAbs, pkg, map, visited);
|
|
103
|
+
// A namespace re-export cannot be flattened into subpath imports, nor is it a local declaration.
|
|
104
|
+
if (nsAs) authoritative.delete(nsAs);
|
|
105
|
+
else starSpecs.push(spec);
|
|
129
106
|
continue;
|
|
130
107
|
}
|
|
131
108
|
|
|
@@ -133,49 +110,28 @@ export class BarrelAnalyzer {
|
|
|
133
110
|
const targetAbs = await this.#resolveRel(absFile, spec);
|
|
134
111
|
if (!targetAbs) continue;
|
|
135
112
|
const targetSubpath = this.#subpathFor(pkg, targetAbs);
|
|
136
|
-
if (
|
|
137
|
-
for (const item of parseNamedList(namedList)) {
|
|
138
|
-
if (item.isType) continue;
|
|
139
|
-
if (item.imported === "default") continue;
|
|
140
|
-
// Validate against scan — drops anything hidden behind `export type`
|
|
141
|
-
// or otherwise not actually exported at runtime.
|
|
142
|
-
if (!authoritative.has(item.local)) continue;
|
|
143
|
-
attributed.add(item.local);
|
|
144
|
-
if (!map.has(item.local)) {
|
|
145
|
-
map.set(item.local, { subpath: targetSubpath, originalName: item.imported });
|
|
146
|
-
}
|
|
147
|
-
}
|
|
113
|
+
if (targetSubpath) attribute(namedList, targetSubpath);
|
|
148
114
|
}
|
|
149
115
|
}
|
|
150
116
|
|
|
151
|
-
// Pass 2: `export { A, B as C };` (no `from`). scan omits these, so the
|
|
152
|
-
// regex is authoritative for this narrow case.
|
|
153
117
|
LOCAL_NAMED_RE.lastIndex = 0;
|
|
154
118
|
let n: RegExpExecArray | null = LOCAL_NAMED_RE.exec(source);
|
|
155
119
|
while (n !== null) {
|
|
156
120
|
const body = n[1] ?? "";
|
|
157
121
|
n = LOCAL_NAMED_RE.exec(source);
|
|
158
|
-
|
|
159
|
-
if (item.isType) continue;
|
|
160
|
-
if (item.imported === "default") continue;
|
|
161
|
-
// Validate against scan — ensures we don't treat commented-out or
|
|
162
|
-
// otherwise dead code as a real local re-export.
|
|
163
|
-
if (!authoritative.has(item.local)) continue;
|
|
164
|
-
attributed.add(item.local);
|
|
165
|
-
if (!map.has(item.local)) {
|
|
166
|
-
map.set(item.local, { subpath: currentSubpath, originalName: item.imported });
|
|
167
|
-
}
|
|
168
|
-
}
|
|
122
|
+
attribute(body, currentSubpath);
|
|
169
123
|
}
|
|
170
124
|
|
|
171
|
-
// Pass 3: remaining authoritative names are local declarations defined in
|
|
172
|
-
// this file (const/function/class/...). scan already filtered out
|
|
173
|
-
// type-only and namespace-only exports for us.
|
|
174
125
|
for (const name of authoritative) {
|
|
175
126
|
if (attributed.has(name)) continue;
|
|
176
127
|
if (map.has(name)) continue;
|
|
177
128
|
map.set(name, { subpath: currentSubpath, originalName: name });
|
|
178
129
|
}
|
|
130
|
+
|
|
131
|
+
for (const spec of starSpecs) {
|
|
132
|
+
const targetAbs = await this.#resolveRel(absFile, spec);
|
|
133
|
+
if (targetAbs) await this.#walk(targetAbs, pkg, map, visited);
|
|
134
|
+
}
|
|
179
135
|
}
|
|
180
136
|
|
|
181
137
|
#scanExports(source: string, absFile: string): Set<string> {
|
|
@@ -193,12 +149,12 @@ export class BarrelAnalyzer {
|
|
|
193
149
|
const rel = path.relative(pkg.pkgDir, absFile);
|
|
194
150
|
if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) return null;
|
|
195
151
|
if (pkg.preserveFilePath) return `${pkg.pkgName}/${rel.split(path.sep).join("/")}`;
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return `${pkg.pkgName}/${tail
|
|
152
|
+
const ext = CANDIDATE_EXTS.find((candidate) => rel.endsWith(candidate));
|
|
153
|
+
const parts = (ext ? rel.slice(0, -ext.length) : rel).split(path.sep);
|
|
154
|
+
// `xxx/index` collapses to `xxx`: callers import `@pkg/xxx`, never `@pkg/xxx/index`.
|
|
155
|
+
if (parts[parts.length - 1] === "index") parts.pop();
|
|
156
|
+
const tail = parts.join("/");
|
|
157
|
+
return tail === "" ? pkg.pkgName : `${pkg.pkgName}/${tail}`;
|
|
202
158
|
}
|
|
203
159
|
|
|
204
160
|
async #resolveRel(fromFile: string, relSpec: string): Promise<string | null> {
|
|
@@ -207,45 +163,10 @@ export class BarrelAnalyzer {
|
|
|
207
163
|
}
|
|
208
164
|
}
|
|
209
165
|
|
|
210
|
-
interface NamedItem {
|
|
211
|
-
imported: string;
|
|
212
|
-
local: string;
|
|
213
|
-
isType: boolean;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const parseNamedList = (listBody: string): NamedItem[] => {
|
|
217
|
-
const out: NamedItem[] = [];
|
|
218
|
-
for (const raw of listBody.split(",")) {
|
|
219
|
-
const s = raw.trim();
|
|
220
|
-
if (!s) continue;
|
|
221
|
-
let rest = s;
|
|
222
|
-
let isType = false;
|
|
223
|
-
if (rest.startsWith("type ")) {
|
|
224
|
-
isType = true;
|
|
225
|
-
rest = rest.slice(5).trim();
|
|
226
|
-
}
|
|
227
|
-
const asMatch = /^(\w+)\s+as\s+(\w+)$/.exec(rest);
|
|
228
|
-
if (asMatch) {
|
|
229
|
-
out.push({ imported: asMatch[1] ?? "", local: asMatch[2] ?? "", isType });
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
if (/^\w+$/.test(rest)) {
|
|
233
|
-
out.push({ imported: rest, local: rest, isType });
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return out;
|
|
237
|
-
};
|
|
238
|
-
|
|
239
166
|
const isRelative = (spec: string): boolean => {
|
|
240
167
|
return spec.startsWith("./") || spec.startsWith("../") || spec === "." || spec === "..";
|
|
241
168
|
};
|
|
242
169
|
|
|
243
|
-
const readIfExists = async (absFile: string): Promise<string | null> => {
|
|
244
|
-
const file = Bun.file(absFile);
|
|
245
|
-
if (!(await file.exists())) return null;
|
|
246
|
-
return file.text();
|
|
247
|
-
};
|
|
248
|
-
|
|
249
170
|
const defaultResolveRelative = async (fromFile: string, relSpec: string): Promise<string | null> => {
|
|
250
171
|
const baseDir = path.dirname(fromFile);
|
|
251
172
|
const joined = path.resolve(baseDir, relSpec);
|
|
@@ -263,16 +184,3 @@ const defaultResolveRelative = async (fromFile: string, relSpec: string): Promis
|
|
|
263
184
|
}
|
|
264
185
|
return null;
|
|
265
186
|
};
|
|
266
|
-
|
|
267
|
-
const stripKnownExt = (relPath: string): string => {
|
|
268
|
-
for (const ext of CANDIDATE_EXTS) {
|
|
269
|
-
if (relPath.endsWith(ext)) return relPath.slice(0, -ext.length);
|
|
270
|
-
}
|
|
271
|
-
return relPath;
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const collapseIndex = (relPathNoExt: string): string => {
|
|
275
|
-
const parts = relPathNoExt.split(path.sep);
|
|
276
|
-
if (parts[parts.length - 1] === "index") parts.pop();
|
|
277
|
-
return parts.join(path.sep);
|
|
278
|
-
};
|