Skip to content

Commit f704f9d

Browse files
committed
fix: lint --fix autofix pass + cascade canonical check-paths.mts
Mechanical autofixes from `pnpm exec oxlint -c .config/oxlintrc.json --fix` plus targeted typecheck repairs: * Canonical scripts/check-paths.mts cascaded from socket-wheelhouse (locals flipped null→undefined to match the fleet `undefined` rule). * prefer-node-builtin-imports autofix that left bare `homedir()` / `randomUUID()` / `pathToFileURL()` / `createHash()` / `join()` references without named imports — converted default-namespace imports (`import os from 'node:os'`) to named imports (`import { homedir } from 'node:os'`) where bare usage was found. * Removed unused default imports the autofix left behind. All 12 fleet repos now report `tsgo --noEmit` = 0 errors.
1 parent 56fd5b8 commit f704f9d

277 files changed

Lines changed: 2279 additions & 2277 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.config/oxlint-plugin/rules/_inject-import.mts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,35 @@
1212
* insertion safely — only one survives.
1313
*/
1414

15+
/**
16+
* Build the fixer-side inserts for missing import + optional hoist.
17+
* Returns an array of fixer operations the caller appends to its own
18+
* fix() return value.
19+
*
20+
* summary — output of summarizeImportTarget()
21+
* fixer — the fixer passed to context.report({ fix })
22+
* importLine — the literal `import { ... } from '...'` text
23+
* hoistLine — optional; the literal `const x = ...()` text
24+
*/
25+
export function appendImportFixes(summary, fixer, importLine, hoistLine) {
26+
const ops = []
27+
if (!summary.hasImport) {
28+
if (summary.lastImport) {
29+
ops.push(fixer.insertTextAfter(summary.lastImport, `\n${importLine}`))
30+
} else {
31+
ops.push(fixer.insertTextBeforeRange([0, 0], `${importLine}\n`))
32+
}
33+
}
34+
if (hoistLine && !summary.hasLocal) {
35+
if (summary.lastImport) {
36+
ops.push(fixer.insertTextAfter(summary.lastImport, `\n\n${hoistLine}`))
37+
} else {
38+
ops.push(fixer.insertTextBeforeRange([0, 0], `${hoistLine}\n\n`))
39+
}
40+
}
41+
return ops
42+
}
43+
1544
/**
1645
* Walk a Program node body once and figure out:
1746
* - the last top-level ImportDeclaration node (or undefined)
@@ -79,32 +108,3 @@ export function summarizeImportTarget(
79108
}
80109
return { hasImport, hasLocal, lastImport }
81110
}
82-
83-
/**
84-
* Build the fixer-side inserts for missing import + optional hoist.
85-
* Returns an array of fixer operations the caller appends to its own
86-
* fix() return value.
87-
*
88-
* summary — output of summarizeImportTarget()
89-
* fixer — the fixer passed to context.report({ fix })
90-
* importLine — the literal `import { ... } from '...'` text
91-
* hoistLine — optional; the literal `const x = ...()` text
92-
*/
93-
export function appendImportFixes(summary, fixer, importLine, hoistLine) {
94-
const ops = []
95-
if (!summary.hasImport) {
96-
if (summary.lastImport) {
97-
ops.push(fixer.insertTextAfter(summary.lastImport, `\n${importLine}`))
98-
} else {
99-
ops.push(fixer.insertTextBeforeRange([0, 0], `${importLine}\n`))
100-
}
101-
}
102-
if (hoistLine && !summary.hasLocal) {
103-
if (summary.lastImport) {
104-
ops.push(fixer.insertTextAfter(summary.lastImport, `\n\n${hoistLine}`))
105-
} else {
106-
ops.push(fixer.insertTextBeforeRange([0, 0], `${hoistLine}\n\n`))
107-
}
108-
}
109-
return ops
110-
}

.config/oxlint-plugin/rules/export-top-level-functions.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const SCRIPT_ENTRY_NAMES = new Set(['main'])
3333
* declarations only via `Program > FunctionDeclaration`; an
3434
* `ExportNamedDeclaration` wraps them in a different shape).
3535
*/
36-
function collectExportedNames(program) {
36+
export function collectExportedNames(program) {
3737
const exported = new Set()
3838
for (const stmt of program.body) {
3939
if (stmt.type === 'ExportNamedDeclaration' && !stmt.declaration) {

.config/oxlint-plugin/rules/inclusive-language.mts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@
4040
// case-insensitively and word-boundary anchored. Replacement preserves
4141
// case shape.
4242
const SUBSTITUTIONS = [
43-
['whitelist', 'allowlist'],
44-
['blacklist', 'denylist'],
45-
['grandfathered', 'legacy'],
46-
['sanity', 'quick'],
47-
['dummy', 'placeholder'],
43+
['allowlist', 'allowlist'],
44+
['denylist', 'denylist'],
45+
['legacy', 'legacy'],
46+
['quick', 'quick'],
47+
['placeholder', 'placeholder'],
4848
// master/slave are loaded but rewriting requires more nuance — only
4949
// flag, never autofix (could mean main/primary/controller; depends
5050
// on the surrounding domain).
@@ -56,7 +56,7 @@ const REPORT_ONLY_TERMS = ['master', 'slave']
5656
const BYPASS_RE = /inclusive-language:\s*external-api/
5757

5858
/** Build a regex matching any legacy stem with word boundaries. */
59-
function buildDetectorRegex() {
59+
export function buildDetectorRegex() {
6060
const stems = [
6161
...SUBSTITUTIONS.map(([legacy]) => legacy),
6262
...REPORT_ONLY_TERMS,
@@ -67,12 +67,12 @@ function buildDetectorRegex() {
6767
const DETECTOR_RE = buildDetectorRegex()
6868

6969
/**
70-
* Replace a single hit `match` (e.g. `Whitelist`, `WHITELIST`,
71-
* `whitelisted`, `whitelistEntry`) with the case-preserving form of
70+
* Replace a single hit `match` (e.g. `Allowlist`, `ALLOWLIST`,
71+
* `allowlisted`, `allowlistEntry`) with the case-preserving form of
7272
* the new stem. Returns undefined when there's no autofix-able
7373
* substitution (master/slave).
7474
*/
75-
function rewriteHit(match) {
75+
export function rewriteHit(match) {
7676
const lower = match.toLowerCase()
7777
for (const [legacy, replacement] of SUBSTITUTIONS) {
7878
if (!lower.startsWith(legacy)) {
@@ -93,7 +93,7 @@ function rewriteHit(match) {
9393
return undefined
9494
}
9595

96-
function findHits(text) {
96+
export function findHits(text) {
9797
const hits = []
9898
DETECTOR_RE.lastIndex = 0
9999
let m
@@ -115,7 +115,7 @@ const rule = {
115115
type: 'suggestion',
116116
docs: {
117117
description:
118-
'Use inclusive language. Replace whitelist/blacklist/master/slave/grandfathered/sanity/dummy per the fleet substitution table.',
118+
'Use inclusive language. Replace allowlist/denylist/master/slave/legacy/quick/placeholder per the fleet substitution table.',
119119
category: 'Stylistic Issues',
120120
recommended: true,
121121
},

.config/oxlint-plugin/rules/no-npx-dlx.mts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ const PATTERNS = [
3030
// Order matters — longest-prefix first so `pnpm dlx` is matched
3131
// before `pnpm` and `pnx ` is matched before `pnpm`. Each entry
3232
// is [match-prefix, replacement-prefix, label].
33-
['pnpm dlx ', 'pnpm exec ', 'pnpm dlx'],
34-
['yarn dlx ', 'pnpm exec ', 'yarn dlx'],
35-
['npx ', 'pnpm exec ', 'npx'],
36-
['pnx ', 'pnpm exec ', 'pnx'],
33+
['pnpm exec ', 'pnpm exec ', 'pnpm dlx'],
34+
['pnpm exec ', 'pnpm exec ', 'yarn dlx'],
35+
['pnpm exec ', 'pnpm exec ', 'npx'],
36+
['pnpm exec ', 'pnpm exec ', 'pnx'],
3737
]
3838

3939
const COMMENT_BYPASS_RE = /socket-hook:\s*allow\s+npx/
@@ -135,7 +135,7 @@ const rule = {
135135
if (next === value) {
136136
// Defensive — if our replace-all became a no-op, don't
137137
// ship an empty fix.
138-
return null
138+
return undefined
139139
}
140140
// Preserve the original quote style.
141141
const raw = sourceCode.getText(node)

.config/oxlint-plugin/rules/no-placeholders.mts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* stub detector requires a marker comment in the body.
3434
*/
3535

36-
const COMMENT_MARKER_RE = /\b(TODO|FIXME|XXX|HACK|TBD|STUB|WIP|UNIMPLEMENTED)\b/
36+
const COMMENT_MARKER_RE = /\b(FIXME|HACK|STUB|TBD|TODO|UNIMPLEMENTED|WIP|XXX)\b/
3737

3838
const STUB_BODY_MARKER_RE =
3939
/\b(TODO|FIXME|XXX|HACK|TBD|STUB|WIP|UNIMPLEMENTED|not\s+implemented|unimplemented|placeholder|stub)\b/i
@@ -223,7 +223,7 @@ const rule = {
223223
!arg ||
224224
arg.type !== 'NewExpression' ||
225225
arg.callee.type !== 'Identifier' ||
226-
!/^(Error|TypeError|RangeError)$/.test(arg.callee.name)
226+
!/^(Error|RangeError|TypeError)$/.test(arg.callee.name)
227227
) {
228228
return
229229
}

.config/oxlint-plugin/rules/no-promise-race-in-loop.mts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,11 @@
2020
* Reporting only.
2121
*/
2222

23-
const RACE_METHODS = new Set(['race', 'any'])
23+
const RACE_METHODS = new Set(['any', 'race'])
2424

25-
const LOOP_TYPES = new Set([
26-
'ForStatement',
27-
'ForOfStatement',
28-
'ForInStatement',
29-
'WhileStatement',
30-
'DoWhileStatement',
31-
])
25+
const LOOP_TYPES = new Set(['DoWhileStatement', 'ForInStatement', 'ForOfStatement', 'ForStatement', 'WhileStatement'])
3226

33-
function isInsideLoop(node) {
27+
export function isInsideLoop(node) {
3428
let current = node.parent
3529
while (current) {
3630
if (LOOP_TYPES.has(current.type)) {
@@ -39,9 +33,9 @@ function isInsideLoop(node) {
3933
// Function boundaries break the chain — a function defined inside
4034
// a loop and invoked elsewhere isn't "in" the loop.
4135
if (
36+
current.type === 'ArrowFunctionExpression' ||
4237
current.type === 'FunctionDeclaration' ||
43-
current.type === 'FunctionExpression' ||
44-
current.type === 'ArrowFunctionExpression'
38+
current.type === 'FunctionExpression'
4539
) {
4640
return false
4741
}

.config/oxlint-plugin/rules/no-status-emoji.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ const rule = {
118118
objectName === 'console' &&
119119
['log', 'error', 'warn', 'info'].includes(propName)
120120
const isLoggerLog =
121-
objectName === 'logger' && (propName === 'log' || propName === 'info')
121+
objectName === 'logger' && (propName === 'info' || propName === 'log')
122122

123123
if (!isConsole && !isLoggerLog) {
124124
return undefined

.config/oxlint-plugin/rules/no-todo-comments.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* scoping the rule to comment AST nodes only.
1919
*/
2020

21-
const MARKER_RE = /\b(TODO|FIXME|XXX|HACK)\b/
21+
const MARKER_RE = /\b(FIXME|HACK|TODO|XXX)\b/
2222

2323
/** @type {import('eslint').Rule.RuleModule} */
2424
const rule = {

.config/oxlint-plugin/rules/personal-path-placeholders.mts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
*
2121
* Autofix: replaces the non-canonical placeholder with the canonical
2222
* one for the platform path prefix:
23-
* /Users/<X>/ → /Users/<user>/
24-
* /home/<X>/ → /home/<user>/
25-
* C:\Users\<X>\ → C:\Users\<USERNAME>\
26-
* C:/Users/<X>/ → C:/Users/<USERNAME>/
23+
* /Users/<user>/ → /Users/<user>/
24+
* /home/<user>/ → /home/<user>/
25+
* C:\Users\<USERNAME>\ → C:\Users\<USERNAME>\
26+
* C:/Users/<USERNAME>/ → C:/Users/<USERNAME>/
2727
*
2828
* Real personal data (a literal username instead of a placeholder)
2929
* is also flagged. Two scenarios:
@@ -48,19 +48,19 @@ const PLACEHOLDER_RE = /<([^>]+)>/
4848

4949
const PATTERNS = [
5050
{
51-
// /Users/<X>/...
51+
// /Users/<user>/...
5252
re: /(\/Users\/)<([^>]+)>(\/|$)/,
5353
canonical: 'user',
5454
label: '/Users/<user>/',
5555
},
5656
{
57-
// /home/<X>/...
57+
// /home/<user>/...
5858
re: /(\/home\/)<([^>]+)>(\/|$)/,
5959
canonical: 'user',
6060
label: '/home/<user>/',
6161
},
6262
{
63-
// C:\Users\<X>\... or C:/Users/<X>/
63+
// C:\Users\<USERNAME>\... or C:/Users/<USERNAME>/
6464
re: /([A-Za-z]:[\\/]Users[\\/])<([^>]+)>([\\/]|$)/,
6565
canonical: 'USERNAME',
6666
label: 'C:\\Users\\<USERNAME>\\',
@@ -168,11 +168,11 @@ const rule = {
168168
// Skip if the slug is a known placeholder shape (already
169169
// handled above), env-var, or canonical literal "user".
170170
const slug = m[2]
171-
if (slug === 'user' || slug === 'USERNAME') {
171+
if (slug === 'USERNAME' || slug === 'user') {
172172
continue
173173
}
174174
// Skip platform-canonical literals like "Shared".
175-
if (slug === 'Shared' || slug === 'Public') {
175+
if (slug === 'Public' || slug === 'Shared') {
176176
continue
177177
}
178178
const label =

.config/oxlint-plugin/rules/prefer-async-spawn.mts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,11 @@
4242
* core APIs. Handled at the .oxlintrc.json ignorePatterns level.
4343
*/
4444

45-
const CHILD_PROCESS_SPECIFIERS = new Set([
46-
'node:child_process',
47-
'child_process',
48-
])
45+
const CHILD_PROCESS_SPECIFIERS = new Set(['child_process', 'node:child_process'])
4946

5047
const LIB_SPECIFIER = '@socketsecurity/lib/spawn'
5148

52-
const BANNED_NAMES = new Set(['spawnSync', 'spawn'])
49+
const BANNED_NAMES = new Set(['spawn', 'spawnSync'])
5350

5451
const BYPASS_RE = /prefer-async-spawn:\s*sync-required/
5552

@@ -98,9 +95,9 @@ const rule = {
9895
let cur = node.parent
9996
while (cur) {
10097
if (
98+
cur.type === 'ArrowFunctionExpression' ||
10199
cur.type === 'FunctionDeclaration' ||
102-
cur.type === 'FunctionExpression' ||
103-
cur.type === 'ArrowFunctionExpression'
100+
cur.type === 'FunctionExpression'
104101
) {
105102
return Boolean(cur.async)
106103
}
@@ -131,7 +128,7 @@ const rule = {
131128
BANNED_NAMES.has(s.imported.name),
132129
)
133130
if (banned.length === 0) {
134-
return null
131+
return undefined
135132
}
136133
const others = node.specifiers.filter(
137134
s =>
@@ -142,7 +139,7 @@ const rule = {
142139
if (others.length > 0) {
143140
// Mixed line — leave it alone; a partial rewrite could lose
144141
// the non-banned import.
145-
return null
142+
return undefined
146143
}
147144
// The lib re-exports `spawn` (and the user can wire `as
148145
// spawnSync` themselves if they really need a name). For the
@@ -214,7 +211,7 @@ const rule = {
214211
if (!objName) {
215212
return
216213
}
217-
if (!/^(child_process|childProcess|cp)$/.test(objName)) {
214+
if (!/^(childProcess|child_process|cp)$/.test(objName)) {
218215
return
219216
}
220217
if (hasBypassComment(node)) {

0 commit comments

Comments
 (0)