Skip to content

Commit 94945e9

Browse files
committed
fix(tools): restore the dynamic-import and namespace-alias edge detection
A bad merge during a rebase reverted this file to a pre-fix revision, silently dropping `DYNAMIC_IMPORT_RE` and the `export * as ns from` alias branch that earlier commits on this branch had already added. The guard still passed, which is the worst way for a lint to break — it simply stopped following edges. Caught it because the per-route counts fell after the rebase (files 1,424 -> 1,314, logs 1,610 -> 1,545) rather than staying put. A guard that reports fewer modules after a no-op merge is not passing, it is blind. Now verified against every bypass form rather than the one I happened to think of, so a future regression of this kind fails loudly: CAUGHT extensionful import { tools } from '@/tools/registry.ts' CAUGHT dynamic import('@/tools/registry') CAUGHT ns re-export export * as ns from '@/tools/registry' CAUGHT side-effect import '@/tools/registry' CAUGHT plain named import { tools } from '@/tools/registry' clean tree passes
1 parent 7ad4327 commit 94945e9

1 file changed

Lines changed: 13 additions & 4 deletions

File tree

scripts/check-tool-registry-boundary.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,20 @@ function collectEntries(dir: string, found: string[] = []): string[] {
6161
const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs']
6262

6363
/**
64-
* Matches value imports and re-exports, skipping `import type` — a type-only
65-
* edge is erased at compile time and costs nothing at runtime.
64+
* Matches value imports and re-exports, skipping `import type` and
65+
* `export type` — a type-only edge is erased at compile time and costs nothing.
66+
*
67+
* `REEXPORT_RE` allows an alias after the star so `export * as ns from` is not
68+
* missed, and `DYNAMIC_IMPORT_RE` covers `import('…')`. A dynamic import splits
69+
* the registry into its own chunk rather than the route's initial one, but it
70+
* still puts 4,300 tools' worth of executable config on a client path, so it
71+
* counts as reaching it — and the settings route's registry edge hid behind
72+
* exactly such an import.
6673
*/
6774
const IMPORT_RE = /(?:^|\n)\s*import\s+(?!type\b)(?:[\s\S]*?from\s*)?['"]([^'"]+)['"]/g
68-
const REEXPORT_RE = /(?:^|\n)\s*export\s+(?!type\b)(?:\*|\{[\s\S]*?\})\s*from\s*['"]([^'"]+)['"]/g
75+
const REEXPORT_RE =
76+
/(?:^|\n)\s*export\s+(?!type\b)(?:\*(?:\s+as\s+[\w$]+)?|\{[\s\S]*?\})\s*from\s*['"]([^'"]+)['"]/g
77+
const DYNAMIC_IMPORT_RE = /\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/g
6978

7079
/** Resolves `@/` and relative specifiers. Bare package specifiers are ignored. */
7180
function resolveSpecifier(specifier: string, importer: string): string | null {
@@ -110,7 +119,7 @@ function walk(entry: string): Walk {
110119
} catch {
111120
continue
112121
}
113-
for (const pattern of [IMPORT_RE, REEXPORT_RE]) {
122+
for (const pattern of [IMPORT_RE, REEXPORT_RE, DYNAMIC_IMPORT_RE]) {
114123
pattern.lastIndex = 0
115124
let match = pattern.exec(source)
116125
while (match !== null) {

0 commit comments

Comments
 (0)