Skip to content

Commit d15cf1d

Browse files
committed
fix(scripts): make the specifier audit path-separator agnostic
Review round: isGeneratedPath split the repo-relative path on '/', but path.relative returns backslashes on Windows, so '.source' and 'node_modules' never matched a segment and generated output was treated as source. The repo does support Windows dev — scripts/setup branches on win32. The finding named one site; there were three. isCompiledSource compared against 'apps/sim/scripts/' with the same assumption, and workspaceFor matched `${w.dir}/`, which on Windows never matches an absolute path and would have dropped every file out of its own workspace — silently disabling tsconfig paths resolution rather than erroring. Normalized behind a repoPath() helper, with workspaceFor using path.sep against absolute paths. Reported paths now go through it too, so output is identical on either platform. spec.split('/') is left alone: import specifiers are always '/'-separated regardless of host. Verified by simulating win32 separators through the same predicates, and posix behaviour is unchanged at 37,437 specifiers.
1 parent 10878fb commit d15cf1d

1 file changed

Lines changed: 11 additions & 6 deletions

File tree

scripts/check-import-specifiers.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Usage: `bun run scripts/check-import-specifiers.ts [--verbose]`
1919
*/
2020
import { readdirSync, readFileSync, statSync } from 'node:fs'
21-
import { dirname, join, relative, resolve } from 'node:path'
21+
import { dirname, join, relative, resolve, sep } from 'node:path'
2222
import { fileURLToPath } from 'node:url'
2323

2424
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url))
@@ -46,11 +46,16 @@ const REQUIRE_RE = /\brequire\s*\(\s*['"]([^'"]+)['"]\s*\)/g
4646
*/
4747
const SUBPATH_REQUIRED = new Set(['@sim/utils'])
4848

49+
/** Repo-relative path, always `/`-separated — `relative()` yields `\` on Windows. */
50+
function repoPath(absolute: string): string {
51+
return relative(ROOT, absolute).replaceAll('\\', '/')
52+
}
53+
4954
/** Only source a bundler compiles — see the "Deliberately NOT checked" note above. */
5055
function isCompiledSource(full: string, name: string): boolean {
5156
if (!/\.(ts|tsx)$/.test(name) || name.endsWith('.d.ts')) return false
5257
if (/\.(test|spec)\.tsx?$/.test(name)) return false
53-
const rel = relative(ROOT, full)
58+
const rel = repoPath(full)
5459
return !rel.startsWith('apps/sim/scripts/') && !rel.startsWith('apps/realtime/scripts/')
5560
}
5661

@@ -78,7 +83,7 @@ function walk(dir: string, acc: string[] = []): string[] {
7883
* would otherwise make every specifier in the repo look generated.
7984
*/
8085
function isGeneratedPath(absolute: string): boolean {
81-
const rel = relative(ROOT, absolute)
86+
const rel = repoPath(absolute)
8287
if (rel.startsWith('..')) return true
8388
return rel.split('/').some((segment) => segment.startsWith('.') || SKIP_DIRS.has(segment))
8489
}
@@ -160,7 +165,7 @@ for (const group of ['apps', 'packages']) {
160165
workspaces.sort((a, b) => b.dir.length - a.dir.length)
161166

162167
function workspaceFor(file: string): Workspace | undefined {
163-
return workspaces.find((w) => file.startsWith(`${w.dir}/`))
168+
return workspaces.find((w) => file.startsWith(w.dir + sep))
164169
}
165170

166171
/** Matched a tsconfig path, but every target is generated — distinct from missing (`null`). */
@@ -328,7 +333,7 @@ for (const file of files) {
328333
checked++
329334
if (!outcome.ok) {
330335
violations.push({
331-
file: relative(ROOT, file),
336+
file: repoPath(file),
332337
line: lineAt(at),
333338
specifier: spec,
334339
kind: 'unresolved',
@@ -340,7 +345,7 @@ for (const file of files) {
340345
const subs = packageExports(spec)
341346
const example = subs ? [...subs.keys()].find((k) => k !== '.') : undefined
342347
violations.push({
343-
file: relative(ROOT, file),
348+
file: repoPath(file),
344349
line: lineAt(at),
345350
specifier: spec,
346351
kind: 'bare-barrel',

0 commit comments

Comments
 (0)