Skip to content

Commit ff6a917

Browse files
committed
test(audits): pin which check:utils rules helper sources are exempt from
1 parent 6bc8a9c commit ff6a917

2 files changed

Lines changed: 77 additions & 42 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { findViolations } from './check-utils-enforcement'
3+
4+
const ES2023 = 'export const sorted = (items: number[]) => items.toSorted()\n'
5+
const INLINE_ERROR_MESSAGE =
6+
"export const message = (e: unknown) => (e instanceof Error ? e.message : 'failed')\n"
7+
8+
function descriptions(file: string, source: string) {
9+
return findViolations(file, source).map(({ description }) => description)
10+
}
11+
12+
describe('helper-source exemptions', () => {
13+
it('still applies browser-runtime rules to @sim/utils, which ships to the browser', () => {
14+
expect(descriptions('packages/utils/src/array.ts', ES2023)).toHaveLength(1)
15+
})
16+
17+
it('still applies browser-runtime rules to allowlisted files', () => {
18+
expect(descriptions('packages/cli/src/index.ts', ES2023)).toHaveLength(1)
19+
})
20+
21+
it('lets @sim/utils use the primitive its helper replaces', () => {
22+
expect(descriptions('packages/utils/src/errors.ts', INLINE_ERROR_MESSAGE)).toEqual([])
23+
})
24+
25+
it('rejects that primitive everywhere else', () => {
26+
expect(descriptions('apps/sim/lib/example.ts', INLINE_ERROR_MESSAGE)).toHaveLength(1)
27+
})
28+
})

‎scripts/check-utils-enforcement.ts‎

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525
import { readFileSync } from 'node:fs'
2626
import { readdir, readFile } from 'node:fs/promises'
2727
import path from 'node:path'
28+
import { fileURLToPath } from 'node:url'
2829

29-
const ROOT = path.resolve(import.meta.dir, '..')
30+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
3031

3132
const SCAN_DIRS = [path.join(ROOT, 'apps'), path.join(ROOT, 'packages')]
3233

@@ -293,6 +294,51 @@ function es2023LibViolations(): Violation[] {
293294
return violations
294295
}
295296

297+
/** Every banned-pattern hit in one file; `file` is repo-relative, which decides its exemptions. */
298+
export function findViolations(file: string, content: string): Violation[] {
299+
const violations: Violation[] = []
300+
const helperSource = file.startsWith(UTILS_SOURCE) || ALLOWLISTED_FILES.has(file)
301+
302+
const matches: Array<{
303+
index: number
304+
description: string
305+
suggestion: string
306+
}> = []
307+
308+
const prefilterHits = new Map<RegExp, boolean>()
309+
for (const { pattern, description, suggestion, prefilter, replacesHelper } of BANNED_PATTERNS) {
310+
if (helperSource && replacesHelper) continue
311+
if (prefilter) {
312+
let hit = prefilterHits.get(prefilter)
313+
if (hit === undefined) {
314+
hit = prefilter.test(content)
315+
prefilterHits.set(prefilter, hit)
316+
}
317+
if (!hit) continue
318+
}
319+
pattern.lastIndex = 0
320+
for (let match = pattern.exec(content); match !== null; match = pattern.exec(content)) {
321+
matches.push({ index: match.index, description, suggestion })
322+
}
323+
}
324+
if (matches.length === 0) return []
325+
326+
const lines = content.split('\n')
327+
const lineStarts = buildLineStarts(content)
328+
for (const match of matches) {
329+
const line = lineAt(lineStarts, match.index)
330+
if (hasAllow(lines, line)) continue
331+
violations.push({
332+
file,
333+
line,
334+
description: match.description,
335+
suggestion: match.suggestion,
336+
snippet: (lines[line - 1] ?? '').trim(),
337+
})
338+
}
339+
return violations
340+
}
341+
296342
async function main() {
297343
const allFiles: string[] = []
298344
for (const dir of SCAN_DIRS) {
@@ -303,46 +349,7 @@ async function main() {
303349

304350
for (const file of allFiles) {
305351
const rel = path.relative(ROOT, file)
306-
const helperSource = rel.startsWith(UTILS_SOURCE) || ALLOWLISTED_FILES.has(rel)
307-
308-
const content = await readFile(file, 'utf8')
309-
const matches: Array<{
310-
index: number
311-
description: string
312-
suggestion: string
313-
}> = []
314-
315-
const prefilterHits = new Map<RegExp, boolean>()
316-
for (const { pattern, description, suggestion, prefilter, replacesHelper } of BANNED_PATTERNS) {
317-
if (helperSource && replacesHelper) continue
318-
if (prefilter) {
319-
let hit = prefilterHits.get(prefilter)
320-
if (hit === undefined) {
321-
hit = prefilter.test(content)
322-
prefilterHits.set(prefilter, hit)
323-
}
324-
if (!hit) continue
325-
}
326-
pattern.lastIndex = 0
327-
for (let match = pattern.exec(content); match !== null; match = pattern.exec(content)) {
328-
matches.push({ index: match.index, description, suggestion })
329-
}
330-
}
331-
if (matches.length === 0) continue
332-
333-
const lines = content.split('\n')
334-
const lineStarts = buildLineStarts(content)
335-
for (const match of matches) {
336-
const line = lineAt(lineStarts, match.index)
337-
if (hasAllow(lines, line)) continue
338-
violations.push({
339-
file: rel,
340-
line,
341-
description: match.description,
342-
suggestion: match.suggestion,
343-
snippet: (lines[line - 1] ?? '').trim(),
344-
})
345-
}
352+
violations.push(...findViolations(rel, await readFile(file, 'utf8')))
346353
}
347354

348355
violations.push(...es2023LibViolations())
@@ -361,4 +368,4 @@ async function main() {
361368
process.exit(1)
362369
}
363370

364-
main()
371+
if (import.meta.main) main()

0 commit comments

Comments
 (0)