Skip to content

Commit a8b78b7

Browse files
committed
Merge remote-tracking branch 'origin/staging' into feat/quickbooks-integration
2 parents a066b25 + e2c42c5 commit a8b78b7

2 files changed

Lines changed: 77 additions & 18 deletions

File tree

bunfig.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ exact = true
33
# Supply-chain gate: only install package versions published at least 7 days ago
44
# (blocks freshly published, potentially compromised releases).
55
minimumReleaseAge = 604800
6-
# @typescript/native-preview stays excluded permanently: it only publishes nightly
7-
# dev builds, so every version is structurally younger than any age gate.
8-
minimumReleaseAgeExcludes = [
9-
"@typescript/native-preview",
10-
]
116

127
[run]
138
env = { NEXT_PUBLIC_APP_URL = "http://localhost:3000" }

scripts/check-native-typecheck.ts

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,93 @@
11
#!/usr/bin/env bun
22
/**
3-
* Asserts that a bare `tsc` runs the native (Go) TypeScript 7 compiler.
3+
* Asserts that every workspace's bare `tsc` runs the native (Go) TypeScript 7 compiler.
44
*
5-
* `@typescript/typescript6` (needed for apps/sim's runtime TypeScript API) pulls in an alias of
6-
* `typescript@6` that declares its own `tsc` bin. Package managers pick bin winners by lexical
7-
* sort, not dependency depth, so it wins `node_modules/.bin/tsc` unless something sorts ahead —
8-
* which is the only job the root `@typescript/native` alias has. Nothing imports that alias, so
9-
* deleting it looks free and silently costs every `tsc` in the repo ~10x.
5+
* `@typescript/typescript6` (needed for apps/sim's runtime TypeScript API, and for the audit
6+
* scripts that read the stable compiler API) pulls in an alias of `typescript@6` that declares
7+
* its own `tsc` bin. Package managers pick bin winners by lexical sort, not dependency depth, so
8+
* it wins `node_modules/.bin/tsc` unless something sorts ahead — which is the only job the root
9+
* `@typescript/native` alias has. Nothing imports that alias, so deleting it looks free and
10+
* silently costs every `tsc` in the repo ~10x.
11+
*
12+
* Every workspace's `type-check` is a bare `tsc --noEmit`, which resolves through the nearest
13+
* `node_modules/.bin` walking up from that package. They all reach the root bin today, but a
14+
* workspace that installs anything shipping its own `tsc` would get a local one that shadows it —
15+
* invisible to a root-only assertion, and slow in exactly the same silent way. So each workspace
16+
* is resolved the way its own script would.
1017
*
1118
* @see https://github.com/microsoft/typescript-go/issues/4567
1219
*/
1320
import { spawnSync } from 'node:child_process'
14-
import { localBin } from './local-bin'
21+
import { existsSync } from 'node:fs'
22+
import path from 'node:path'
23+
import { fileURLToPath } from 'node:url'
24+
import { Glob } from 'bun'
25+
26+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
27+
28+
/**
29+
* The `tsc` a bare invocation in `dir` would run: nearest `node_modules/.bin`, walking up.
30+
*
31+
* The walk stops at the repository root even when nothing is found there. A machine that happens
32+
* to have a TypeScript 7 above the checkout would otherwise satisfy every workspace and let the
33+
* audit pass with `@typescript/native` deleted — the one thing it exists to catch.
34+
*/
35+
function resolveTsc(dir: string): string | null {
36+
let current = dir
37+
while (true) {
38+
const candidate = path.join(current, 'node_modules', '.bin', 'tsc')
39+
if (existsSync(candidate)) return candidate
40+
if (current === ROOT) return null
41+
const parent = path.dirname(current)
42+
if (parent === current) return null
43+
current = parent
44+
}
45+
}
46+
47+
/** Read from the manifest rather than restating its globs, so a new workspace pattern is covered. */
48+
function workspacePatterns(): string[] {
49+
const manifest = require(path.join(ROOT, 'package.json'))
50+
const declared = Array.isArray(manifest.workspaces)
51+
? manifest.workspaces
52+
: (manifest.workspaces?.packages ?? [])
53+
if (declared.length === 0) throw new Error('Root package.json declares no workspaces')
54+
return declared
55+
}
1556

16-
const result = spawnSync(localBin('tsc'), ['--version'], { encoding: 'utf8' })
17-
const reported = result.stdout?.trim() ?? ''
57+
const workspaceDirs = [
58+
'.',
59+
...workspacePatterns().flatMap((pattern) =>
60+
[...new Glob(`${pattern}/package.json`).scanSync(ROOT)].map(path.dirname)
61+
),
62+
].sort()
63+
64+
const failures: string[] = []
65+
66+
for (const workspace of workspaceDirs) {
67+
const tsc = resolveTsc(path.join(ROOT, workspace))
68+
if (!tsc) {
69+
failures.push(`${workspace}: no \`tsc\` resolvable from this package`)
70+
continue
71+
}
72+
const result = spawnSync(tsc, ['--version'], { encoding: 'utf8' })
73+
const reported = result.stdout?.trim() ?? ''
74+
if (!/^Version 7\./.test(reported)) {
75+
const detail = reported || result.stderr?.trim() || `exit ${result.status}`
76+
failures.push(`${workspace}: ${path.relative(ROOT, tsc)} reports "${detail}"`)
77+
}
78+
}
1879

19-
if (!/^Version 7\./.test(reported)) {
20-
const detail = reported || result.stderr?.trim() || `exit ${result.status}`
80+
if (failures.length > 0) {
2181
console.error(
22-
`Native type-check audit failed: node_modules/.bin/tsc reports "${detail}", expected TypeScript 7.x.\n\n` +
82+
`Native type-check audit failed — expected TypeScript 7.x everywhere:\n\n${failures
83+
.map((failure) => ` ${failure}`)
84+
.join('\n')}\n\n` +
2385
' Check that `@typescript/native` is still in the root devDependencies, and that no newly\n' +
2486
' added package sorts ahead of it while declaring a `tsc` bin.'
2587
)
2688
process.exit(1)
2789
}
2890

29-
console.log(`Native type-check audit passed (bare \`tsc\` is ${reported}).`)
91+
console.log(
92+
`Native type-check audit passed (bare \`tsc\` is TypeScript 7.x in ${workspaceDirs.length} workspaces).`
93+
)

0 commit comments

Comments
 (0)