mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
build(mobile): move to TypeScript 7 and Vitest 5, typecheck through the root tsrs runner (#33419)
- Bump mobile typescript to ^7.0.2 and vitest to 5.0.5; keep TypeScript 6 as typescript-api for the test-support code that walks the AST, mirroring the root. - Patch Expo CLI's tsconfig reader to fall back to typescript-api: TypeScript 7 has no compiler API, and Metro otherwise crashes reading tsconfig paths. - Register mobile/tsconfig.json and mobile/tsconfig.test.json with the root typecheck runner; locally they use incremental tsrs (Bun elsewhere), CI uses Bun like root CI. - Route the tests-typecheck ratchet through the same compiler selection. - Enforce root/mobile parity for typescript, typescript-api and vitest.
This commit is contained in:
@@ -32,6 +32,10 @@ on:
|
||||
- '.github/workflows/mobile.yml'
|
||||
- 'config/mobile-ci.vitest.config.mjs'
|
||||
- 'config/scripts/run-mobile-ci-tests.mjs'
|
||||
# Mobile typechecks run through the root compiler selection.
|
||||
- 'config/scripts/run-typecheck-projects-in-parallel.mjs'
|
||||
- 'config/scripts/tsrs-typecheck-compiler.mjs'
|
||||
- 'config/scripts/pinned-bun-executable.mjs'
|
||||
- 'config/oxlint-code-quality-native-plugins.json'
|
||||
- 'config/.bun-version'
|
||||
- '.github/actions/install-node-dependencies/**'
|
||||
@@ -76,6 +80,9 @@ on:
|
||||
- '.github/workflows/mobile.yml'
|
||||
- 'config/mobile-ci.vitest.config.mjs'
|
||||
- 'config/scripts/run-mobile-ci-tests.mjs'
|
||||
- 'config/scripts/run-typecheck-projects-in-parallel.mjs'
|
||||
- 'config/scripts/tsrs-typecheck-compiler.mjs'
|
||||
- 'config/scripts/pinned-bun-executable.mjs'
|
||||
- 'config/.bun-version'
|
||||
- '.github/actions/install-node-dependencies/**'
|
||||
- '.github/actions/setup-pnpm/**'
|
||||
@@ -114,7 +121,7 @@ jobs:
|
||||
# from the Gemfile, which is how the release jobs could land on different
|
||||
# fastlane versions in the first place. Fail here instead.
|
||||
BUNDLE_FROZEN: 'true'
|
||||
ORCA_MOBILE_TYPECHECK_COMPILER: 'native'
|
||||
ORCA_MOBILE_TYPECHECK_COMPILER: 'bun'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -171,9 +178,7 @@ jobs:
|
||||
- name: Typecheck
|
||||
id: production-types
|
||||
background: true
|
||||
env:
|
||||
GOMAXPROCS: '2'
|
||||
run: node scripts/typecheck-mobile.mjs
|
||||
run: node ../config/scripts/run-typecheck-projects-in-parallel.mjs --compiler=bun --bun-threads=2 --project=mobile/tsconfig.json
|
||||
|
||||
# Why a ratchet and not the raw typecheck: mobile/tsconfig.json excludes test files, so until
|
||||
# tsconfig.test.json existed nothing checked them, and at introduction 127 of the 632 had
|
||||
@@ -182,8 +187,6 @@ jobs:
|
||||
- name: Typecheck tests (ratchet)
|
||||
id: test-types
|
||||
background: true
|
||||
env:
|
||||
GOMAXPROCS: '2'
|
||||
run: node scripts/check-tests-typecheck-ratchet.mjs
|
||||
|
||||
# This includes the bridged replay of the whole recording corpus, which used to be a second
|
||||
@@ -304,7 +307,7 @@ jobs:
|
||||
main-tests:
|
||||
name: Mobile tests on main
|
||||
env:
|
||||
ORCA_MOBILE_TYPECHECK_COMPILER: 'native'
|
||||
ORCA_MOBILE_TYPECHECK_COMPILER: 'bun'
|
||||
if: github.event_name == 'push'
|
||||
# Why ARM: the same pure-Node Vitest run `verify` makes on a pull request.
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404-arm
|
||||
@@ -331,15 +334,11 @@ jobs:
|
||||
- name: Typecheck
|
||||
id: production-types
|
||||
background: true
|
||||
env:
|
||||
GOMAXPROCS: '2'
|
||||
run: node scripts/typecheck-mobile.mjs
|
||||
run: node ../config/scripts/run-typecheck-projects-in-parallel.mjs --compiler=bun --bun-threads=2 --project=mobile/tsconfig.json
|
||||
|
||||
- name: Typecheck tests (ratchet)
|
||||
id: test-types
|
||||
background: true
|
||||
env:
|
||||
GOMAXPROCS: '2'
|
||||
run: node scripts/check-tests-typecheck-ratchet.mjs
|
||||
|
||||
# The whole suite, not only the recordings: the mutant and page-bridge suites read the goldens
|
||||
|
||||
@@ -10,6 +10,12 @@ import { lockedVersion, lockfileRootImporter } from './pnpm-lockfile-root-import
|
||||
// merges two copies only at the same version; else zod-wrapped schemas infer `{}` (phone-feed-list.ts).
|
||||
export const SHARED_DEPENDENCIES = ['zod', 'tweetnacl', '@noble/hashes', '@types/ws']
|
||||
|
||||
// Mobile typechecks through the root runner, whose Bun path accepts one TypeScript version, and
|
||||
// mobile CI runs its tests with the root's Vitest CLI against mobile's `vitest` imports.
|
||||
export const TOOLCHAIN_DEPENDENCIES = ['typescript', 'typescript-api', 'vitest']
|
||||
|
||||
const CHECKED_DEPENDENCIES = [...SHARED_DEPENDENCIES, ...TOOLCHAIN_DEPENDENCIES]
|
||||
|
||||
function importerVersion(importer, name) {
|
||||
return lockedVersion(importer.dependencies?.[name] ?? importer.devDependencies?.[name])
|
||||
}
|
||||
@@ -17,7 +23,7 @@ function importerVersion(importer, name) {
|
||||
export function findSharedDependencyVersionProblems({
|
||||
rootImporter,
|
||||
mobileImporter,
|
||||
names = SHARED_DEPENDENCIES
|
||||
names = CHECKED_DEPENDENCIES
|
||||
}) {
|
||||
const problems = []
|
||||
for (const name of names) {
|
||||
@@ -49,7 +55,7 @@ export function main(root = resolve(import.meta.dirname, '../..')) {
|
||||
)
|
||||
return 1
|
||||
}
|
||||
console.log(`Root and mobile lock the same ${SHARED_DEPENDENCIES.join(', ')}.`)
|
||||
console.log(`Root and mobile lock the same ${CHECKED_DEPENDENCIES.join(', ')}.`)
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('findSharedDependencyVersionProblems', () => {
|
||||
expect(checkZod({}, locked('4.6.7'))).toEqual(['zod is not a direct dependency of the root'])
|
||||
})
|
||||
|
||||
it('checks every shared dependency by default', () => {
|
||||
it('checks every shared and toolchain dependency by default', () => {
|
||||
const problems = findSharedDependencyVersionProblems({
|
||||
rootImporter: locked('4.6.7'),
|
||||
mobileImporter: locked('4.6.7')
|
||||
@@ -43,7 +43,10 @@ describe('findSharedDependencyVersionProblems', () => {
|
||||
expect(problems).toEqual([
|
||||
'tweetnacl is not a direct dependency of the root',
|
||||
'@noble/hashes is not a direct dependency of the root',
|
||||
'@types/ws is not a direct dependency of the root'
|
||||
'@types/ws is not a direct dependency of the root',
|
||||
'typescript is not a direct dependency of the root',
|
||||
'typescript-api is not a direct dependency of the root',
|
||||
'vitest is not a direct dependency of the root'
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,16 +2,14 @@ import { readFileSync } from 'node:fs'
|
||||
import { expect, it } from 'vitest'
|
||||
import { parse } from 'yaml'
|
||||
|
||||
it('runs full native checks and collects failures on pull requests and main', () => {
|
||||
it('runs uncached Bun checks like root CI and collects failures on pull requests and main', () => {
|
||||
const workflow = parse(readFileSync('.github/workflows/mobile.yml', 'utf8'))
|
||||
for (const job of [workflow.jobs.verify, workflow.jobs['main-tests']]) {
|
||||
expect(job.env.ORCA_MOBILE_TYPECHECK_COMPILER).toBe('native')
|
||||
expect(job.env.ORCA_MOBILE_TYPECHECK_CACHE_DIR).toBeUndefined()
|
||||
expect(job.env.ORCA_MOBILE_TYPECHECK_COMPILER).toBe('bun')
|
||||
const steps = job.steps
|
||||
expect(
|
||||
steps.some(
|
||||
(step) =>
|
||||
step.uses === 'actions/cache@v5' && step.with?.path?.includes('mobile/.cache/typechecks')
|
||||
(step) => step.uses === 'actions/cache@v5' && step.with?.path?.includes('.cache/typecheck')
|
||||
)
|
||||
).toBe(false)
|
||||
const install = steps.findIndex((step) => step.name === 'Install dependencies')
|
||||
@@ -21,13 +19,12 @@ it('runs full native checks and collects failures on pull requests and main', ()
|
||||
expect(check.if).toBeUndefined()
|
||||
expect(check.background).toBe(true)
|
||||
expect(check['continue-on-error']).toBeUndefined()
|
||||
expect(check.env.GOMAXPROCS).toBe('2')
|
||||
expect(steps.indexOf(check)).toBeGreaterThan(install)
|
||||
expect(wait.wait).toContain(id)
|
||||
expect(steps.indexOf(wait)).toBeGreaterThan(steps.indexOf(check))
|
||||
}
|
||||
expect(steps.find((step) => step.id === 'production-types').run).toBe(
|
||||
'node scripts/typecheck-mobile.mjs'
|
||||
'node ../config/scripts/run-typecheck-projects-in-parallel.mjs --compiler=bun --bun-threads=2 --project=mobile/tsconfig.json'
|
||||
)
|
||||
expect(steps.find((step) => step.id === 'test-types').run).toBe(
|
||||
'node scripts/check-tests-typecheck-ratchet.mjs'
|
||||
|
||||
@@ -2,7 +2,7 @@ import { runProcessSync, spawnProcess } from '@orca/process-host'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { createRequire } from 'node:module'
|
||||
import { availableParallelism, totalmem } from 'node:os'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { dirname, join, resolve } from 'node:path'
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url'
|
||||
import { readPinnedBunVersion, resolvePinnedBunExecutable } from './pinned-bun-executable.mjs'
|
||||
import { resolveTsrsTypecheckCommand, supportsTsrs } from './tsrs-typecheck-compiler.mjs'
|
||||
@@ -21,6 +21,12 @@ export const TYPECHECK_PROJECTS = [
|
||||
{ config: 'src/packages/process-host/tsconfig.test.json', heapGib: 1 }
|
||||
]
|
||||
|
||||
// Selected only by --project: mobile is a separate install that root checks cannot assume.
|
||||
export const MOBILE_TYPECHECK_PROJECTS = [
|
||||
{ config: 'mobile/tsconfig.json', heapGib: 2 },
|
||||
{ config: 'mobile/tsconfig.test.json', heapGib: 3 }
|
||||
]
|
||||
|
||||
// The OS, node itself, and the runner agent need their share; the rest is what tsc may hold.
|
||||
export function admissibleHeapGib(totalBytes) {
|
||||
return Math.max(1, (totalBytes / BYTES_PER_GIB) * 0.75)
|
||||
@@ -62,7 +68,7 @@ export function planTypecheckBatches(projects, { budgetGib, parallelism }) {
|
||||
const repoRoot = fileURLToPath(new URL('../..', import.meta.url))
|
||||
|
||||
export function resolveProjectCompilerInfo(config, root = repoRoot) {
|
||||
const require = createRequire(join(root, dirname(config), 'package.json'))
|
||||
const require = createRequire(join(resolve(root, dirname(config)), 'package.json'))
|
||||
const manifestPath = require.resolve('typescript/package.json')
|
||||
const { bin, version } = JSON.parse(readFileSync(manifestPath, 'utf8'))
|
||||
return { program: join(dirname(manifestPath), typeof bin === 'string' ? bin : bin.tsc), version }
|
||||
@@ -92,7 +98,9 @@ export function parseTypecheckOptions(args) {
|
||||
options.bunThreads = Number(argument.slice('--bun-threads='.length))
|
||||
} else if (argument.startsWith('--project=')) {
|
||||
const config = argument.slice('--project='.length)
|
||||
const project = TYPECHECK_PROJECTS.find((candidate) => candidate.config === config)
|
||||
const project = [...TYPECHECK_PROJECTS, ...MOBILE_TYPECHECK_PROJECTS].find(
|
||||
(candidate) => candidate.config === config
|
||||
)
|
||||
if (!project) {
|
||||
throw new Error(`Unknown typecheck project: ${config}`)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { join, relative, sep } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
MOBILE_TYPECHECK_PROJECTS,
|
||||
TYPECHECK_PROJECTS,
|
||||
admissibleHeapGib,
|
||||
planTypecheckBatches,
|
||||
@@ -194,6 +195,10 @@ describe('local and CI compiler selection', () => {
|
||||
TYPECHECK_PROJECTS[0]
|
||||
])
|
||||
expect(parseTypecheckOptions([]).projects).toEqual(TYPECHECK_PROJECTS)
|
||||
expect(parseTypecheckOptions(['--project=mobile/tsconfig.test.json']).projects).toEqual([
|
||||
MOBILE_TYPECHECK_PROJECTS[1]
|
||||
])
|
||||
expect(TYPECHECK_PROJECTS).not.toContainEqual(MOBILE_TYPECHECK_PROJECTS[0])
|
||||
expect(() => parseTypecheckOptions(['--project=config/tsconfig.json'])).toThrow()
|
||||
})
|
||||
|
||||
|
||||
@@ -14,5 +14,3 @@ dist/
|
||||
*.mobileprovision
|
||||
*.orig.*
|
||||
web-build/
|
||||
|
||||
.cache/typechecks/
|
||||
|
||||
+5
-4
@@ -10,8 +10,8 @@
|
||||
"native": "node scripts/native-client.mjs",
|
||||
"postinstall": "node scripts/build-terminal-webview-engine.mjs && node scripts/build-mermaid-page-engine.mjs && node scripts/build-terminal-document-script.mjs",
|
||||
"test": "vitest run",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"typecheck:tests": "tsc --noEmit -p tsconfig.test.json",
|
||||
"typecheck": "node ../config/scripts/run-typecheck-projects-in-parallel.mjs --project=mobile/tsconfig.json",
|
||||
"typecheck:tests": "node ../config/scripts/run-typecheck-projects-in-parallel.mjs --project=mobile/tsconfig.test.json",
|
||||
"check:tests-typecheck": "node scripts/check-tests-typecheck-ratchet.mjs",
|
||||
"rpc:record": "tsx --conditions=orca-source scripts/rpc-recording.mts",
|
||||
"rpc:diff": "tsx --conditions=orca-source scripts/rpc-diff.mts",
|
||||
@@ -90,9 +90,10 @@
|
||||
"oxlint": "^1.88.0",
|
||||
"react-test-renderer": "19.2.8",
|
||||
"tsx": "^4.23.15",
|
||||
"typescript": "6.0.3",
|
||||
"typescript": "^7.0.2",
|
||||
"typescript-api": "npm:typescript@6.0.3",
|
||||
"vite": "^8.3.4",
|
||||
"vitest": "^4.1.12",
|
||||
"vitest": "5.0.5",
|
||||
"ws": "^8.22.0"
|
||||
},
|
||||
"packageManager": "pnpm@12.14.0+sha512.c18ba6d87993d3d164cb5e8948f32b2c06ee854487e06cd8d86781342fb3e5bb4634367034711e86802baa9c37bea906ce1929ad08d70884c97d801df13389a6"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
diff --git a/build/src/utils/tsconfig/evaluateTsConfig.js b/build/src/utils/tsconfig/evaluateTsConfig.js
|
||||
index ecf0298a6858541f2e33d0af5293ad61aa80a159..491d9800703dab8e3c197c09bd45af4fd3e13b58 100644
|
||||
--- a/build/src/utils/tsconfig/evaluateTsConfig.js
|
||||
+++ b/build/src/utils/tsconfig/evaluateTsConfig.js
|
||||
@@ -77,11 +77,15 @@ function evaluateTsConfig(ts, tsConfigPath) {
|
||||
}
|
||||
}
|
||||
function importTypeScriptFromProjectOptionally(projectRoot) {
|
||||
- const resolvedPath = _resolvefrom().default.silent(projectRoot, 'typescript');
|
||||
- if (!resolvedPath) {
|
||||
- return null;
|
||||
+ // TypeScript 7 ships no compiler API; read tsconfig with the project's TypeScript 6 alias.
|
||||
+ for (const name of ['typescript', 'typescript-api']) {
|
||||
+ const resolvedPath = _resolvefrom().default.silent(projectRoot, name);
|
||||
+ const ts = resolvedPath ? require(resolvedPath) : null;
|
||||
+ if (typeof (ts == null ? void 0 : ts.readConfigFile) === 'function') {
|
||||
+ return ts;
|
||||
+ }
|
||||
}
|
||||
- return require(resolvedPath);
|
||||
+ return null;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=evaluateTsConfig.js.map
|
||||
Generated
+365
-220
File diff suppressed because it is too large
Load Diff
@@ -28,3 +28,4 @@ patchedDependencies:
|
||||
react-native@0.83.10: patches/react-native@0.83.10.patch
|
||||
braces@3.0.3: patches/braces@3.0.3.patch
|
||||
node-forge@1.4.0: patches/node-forge@1.4.0.patch
|
||||
'@expo/cli@55.0.36': patches/@expo__cli@55.0.36.patch
|
||||
|
||||
@@ -1,31 +1,41 @@
|
||||
import { existsSync, mkdtempSync, realpathSync, writeFileSync, unlinkSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import {
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
realpathSync,
|
||||
writeFileSync,
|
||||
unlinkSync
|
||||
} from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import { supportsTsrs } from '../../config/scripts/tsrs-typecheck-compiler.mjs'
|
||||
import { removeTreeSync } from '../../src/shared/windows-transient-lock-removal'
|
||||
import { collectTypecheckPass, findTsNocheckFiles } from './check-tests-typecheck-ratchet.mjs'
|
||||
import { resolveMobileTypecheckCommand } from './mobile-typecheck-compiler.mjs'
|
||||
|
||||
const mobileRoot = realpathSync(join(import.meta.dirname, '..'))
|
||||
|
||||
it.each([
|
||||
{ compiler: 'javascript', incremental: true },
|
||||
...(supportsTsrs() ? [{ compiler: 'tsrs', incremental: true }] : []),
|
||||
{ compiler: 'bun', incremental: false },
|
||||
{ compiler: 'native', incremental: false }
|
||||
])(
|
||||
'rechecks changed types, diagnostics and test membership with $compiler',
|
||||
({ compiler, incremental }) => {
|
||||
const root = realpathSync(mkdtempSync(join(tmpdir(), 'orca-mobile-typecheck-')))
|
||||
const cache = join(root, '.cache')
|
||||
vi.stubEnv('ORCA_MOBILE_TYPECHECK_CACHE_DIR', cache)
|
||||
// Inside mobile so the project resolves mobile's TypeScript, as the real test project does.
|
||||
const scratch = join(mobileRoot, 'node_modules', '.cache')
|
||||
mkdirSync(scratch, { recursive: true })
|
||||
const root = mkdtempSync(join(scratch, 'orca-mobile-typecheck-'))
|
||||
vi.stubEnv('ORCA_MOBILE_TYPECHECK_COMPILER', compiler)
|
||||
const buildInfo = resolveMobileTypecheckCommand('tsconfig.test.json', root).args.find((arg) =>
|
||||
arg.endsWith('.tsbuildinfo')
|
||||
)
|
||||
expect(Boolean(buildInfo)).toBe(incremental)
|
||||
try {
|
||||
writeFileSync(
|
||||
join(root, 'tsconfig.test.json'),
|
||||
JSON.stringify({
|
||||
compilerOptions: {
|
||||
strict: true,
|
||||
skipLibCheck: true,
|
||||
types: [],
|
||||
target: 'ES2022',
|
||||
incremental: true
|
||||
},
|
||||
compilerOptions: { strict: true, skipLibCheck: true, types: [], target: 'ES2022' },
|
||||
include: ['*.ts']
|
||||
})
|
||||
)
|
||||
@@ -35,7 +45,9 @@ it.each([
|
||||
writeFileSync(test, source)
|
||||
const clean = collectTypecheckPass(root)
|
||||
expect(clean).toEqual({ failing: [], programTestFiles: ['value.test.ts'] })
|
||||
expect(existsSync(join(cache, 'tests.tsbuildinfo'))).toBe(incremental)
|
||||
if (buildInfo) {
|
||||
expect(existsSync(buildInfo)).toBe(true)
|
||||
}
|
||||
expect(existsSync(join(root, 'tsconfig.test.tsbuildinfo'))).toBe(false)
|
||||
expect(collectTypecheckPass(root)).toEqual(clean)
|
||||
|
||||
@@ -56,7 +68,10 @@ it.each([
|
||||
} finally {
|
||||
vi.unstubAllEnvs()
|
||||
removeTreeSync(root)
|
||||
if (buildInfo) {
|
||||
removeTreeSync(buildInfo)
|
||||
}
|
||||
}
|
||||
},
|
||||
15_000
|
||||
30_000
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { resolveMobileTypecheckCompiler } from './mobile-typecheck-compiler.mjs'
|
||||
import { resolveMobileTypecheckCommand } from './mobile-typecheck-compiler.mjs'
|
||||
|
||||
// Ratchet gate for the mobile test typecheck.
|
||||
//
|
||||
@@ -148,34 +148,17 @@ export function diffBaseline(current, baseline) {
|
||||
}
|
||||
}
|
||||
|
||||
function runTsc(root, args, compiler) {
|
||||
return runProcessSync({
|
||||
program: compiler.program,
|
||||
args: [...compiler.args, ...args],
|
||||
cwd: root,
|
||||
timeoutMs: null,
|
||||
maxOutputBytes: 64 * 1024 * 1024
|
||||
})
|
||||
}
|
||||
|
||||
// tsc exits non-zero on type errors, which is the expected state here, so only a crash is fatal.
|
||||
// One pass answers both questions: --listFiles names the program, the diagnostics name the failures.
|
||||
export function collectTypecheckPass(root = process.cwd()) {
|
||||
const compiler = resolveMobileTypecheckCompiler()
|
||||
const cache = process.env.ORCA_MOBILE_TYPECHECK_CACHE_DIR
|
||||
const result = runTsc(
|
||||
root,
|
||||
[
|
||||
'--noEmit',
|
||||
'--listFiles',
|
||||
'-p',
|
||||
PROJECT,
|
||||
...(cache && !compiler.native
|
||||
? ['--incremental', '--tsBuildInfoFile', path.join(cache, 'tests.tsbuildinfo')]
|
||||
: [])
|
||||
],
|
||||
compiler
|
||||
)
|
||||
const command = resolveMobileTypecheckCommand(PROJECT, root)
|
||||
const result = runProcessSync({
|
||||
program: command.program,
|
||||
args: [...command.args, '--listFiles'],
|
||||
cwd: command.cwd,
|
||||
timeoutMs: null,
|
||||
maxOutputBytes: 64 * 1024 * 1024
|
||||
})
|
||||
const output = `${result.stdout ?? ''}${result.stderr ?? ''}`
|
||||
return {
|
||||
failing: parseFailingFiles(output),
|
||||
|
||||
@@ -1,38 +1,31 @@
|
||||
import { createRequire } from 'node:module'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { runProcessSync } from '@orca/process-host'
|
||||
import { resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { resolveProjectCompilerInfo } from '../../config/scripts/run-typecheck-projects-in-parallel.mjs'
|
||||
import { resolvePinnedBunExecutable } from '../../config/scripts/pinned-bun-executable.mjs'
|
||||
import {
|
||||
resolveTypecheckCommand,
|
||||
selectTypecheckCompiler
|
||||
} from '../../config/scripts/run-typecheck-projects-in-parallel.mjs'
|
||||
|
||||
const root = fileURLToPath(new URL('../..', import.meta.url))
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
export function resolveMobileTypecheckCompiler() {
|
||||
const mode = process.env.ORCA_MOBILE_TYPECHECK_COMPILER ?? 'javascript'
|
||||
if (mode !== 'javascript' && mode !== 'native') {
|
||||
throw new Error(`Unknown mobile typecheck compiler: ${mode}`)
|
||||
/**
|
||||
* The root runner's compiler command for a mobile project, run from `cwd` so diagnostics name
|
||||
* files relative to it. Compiler: ORCA_MOBILE_TYPECHECK_COMPILER (auto|tsrs|bun|native).
|
||||
*/
|
||||
export function resolveMobileTypecheckCommand(project, cwd = process.cwd()) {
|
||||
const requested = process.env.ORCA_MOBILE_TYPECHECK_COMPILER ?? 'auto'
|
||||
if (!/^(auto|tsrs|bun|native)$/.test(requested)) {
|
||||
throw new Error(`Unknown mobile typecheck compiler: ${requested}`)
|
||||
}
|
||||
const native = mode === 'native'
|
||||
// Expo needs mobile's JavaScript compiler API; CI can use the root native compiler.
|
||||
const compiler = resolveProjectCompilerInfo(
|
||||
native ? 'package.json' : 'mobile/tsconfig.json',
|
||||
const selection = selectTypecheckCompiler(requested, {
|
||||
root,
|
||||
resolveBunExecutable: (repoRoot) => resolvePinnedBunExecutable(repoRoot, runProcessSync)
|
||||
})
|
||||
const command = resolveTypecheckCommand(resolve(cwd, project), {
|
||||
...selection,
|
||||
bunThreads: 2,
|
||||
root
|
||||
)
|
||||
if (native) {
|
||||
// Use the package's resolver, then let process-host hide Windows children.
|
||||
const getExecutablePath = require(
|
||||
join(dirname(compiler.program), '../lib/getExePath.js')
|
||||
).default
|
||||
return {
|
||||
program: getExecutablePath(),
|
||||
args: ['--incremental', 'false'],
|
||||
native,
|
||||
version: compiler.version
|
||||
}
|
||||
}
|
||||
return {
|
||||
program: process.execPath,
|
||||
args: [compiler.program],
|
||||
native,
|
||||
version: compiler.version
|
||||
}
|
||||
})
|
||||
return { ...command, cwd, compiler: selection.compiler }
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import { runProcess } from '@orca/process-host'
|
||||
import { resolveMobileTypecheckCompiler } from './mobile-typecheck-compiler.mjs'
|
||||
|
||||
const compiler = resolveMobileTypecheckCompiler()
|
||||
const abort = new AbortController()
|
||||
// Keep the CLI alive while process-host's termination barrier settles.
|
||||
const keepAlive = setInterval(() => undefined, 60_000)
|
||||
let signalExitCode
|
||||
const interrupt = () => {
|
||||
signalExitCode ??= 130
|
||||
abort.abort()
|
||||
}
|
||||
const terminate = () => {
|
||||
signalExitCode ??= 143
|
||||
abort.abort()
|
||||
}
|
||||
process.once('SIGINT', interrupt)
|
||||
process.once('SIGTERM', terminate)
|
||||
try {
|
||||
if (compiler.native) {
|
||||
console.log(`TypeScript ${compiler.version}: native compiler`)
|
||||
}
|
||||
const result = await runProcess({
|
||||
program: compiler.program,
|
||||
args: [...compiler.args, '--noEmit', ...process.argv.slice(2)],
|
||||
stdio: 'inherit',
|
||||
timeoutMs: null,
|
||||
signal: abort.signal,
|
||||
terminationBarrier: true
|
||||
})
|
||||
process.exitCode = signalExitCode ?? result.code ?? 1
|
||||
} finally {
|
||||
clearInterval(keepAlive)
|
||||
process.removeListener('SIGINT', interrupt)
|
||||
process.removeListener('SIGTERM', terminate)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { readFileSync, readdirSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { basename, dirname, extname, join, relative } from 'node:path'
|
||||
import ts from 'typescript'
|
||||
import ts from 'typescript-api'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
const appDirectory = fileURLToPath(new URL('../app', import.meta.url))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ts from 'typescript'
|
||||
import ts from 'typescript-api'
|
||||
|
||||
/**
|
||||
* Reads what a Pressable's source says about itself, for the accessibility censuses that judge
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ts from 'typescript'
|
||||
import ts from 'typescript-api'
|
||||
import {
|
||||
MOBILE_TASKS_SOURCE_FILES,
|
||||
readMobileTasksSource
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ts from 'typescript'
|
||||
import ts from 'typescript-api'
|
||||
import {
|
||||
MOBILE_TASKS_SOURCE_FILES,
|
||||
readMobileTasksSource
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { readFileSync, readdirSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import ts from 'typescript'
|
||||
import ts from 'typescript-api'
|
||||
|
||||
const TASKS_DIRECTORY = __dirname
|
||||
const SOURCE_PATTERN = /^(?:MobileTasks.*\.tsx|mobile-tasks-.*\.tsx?|use-mobile-tasks-.*\.tsx?)$/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { compileFunction } from 'node:vm'
|
||||
import ts from 'typescript'
|
||||
import ts from 'typescript-api'
|
||||
|
||||
type CompiledModule = {
|
||||
source: string
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { existsSync, readFileSync } from 'node:fs'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import ts from 'typescript'
|
||||
import ts from 'typescript-api'
|
||||
import { nativeMountingSubstitutes } from './native-mounting-substitutes'
|
||||
import { observeSalvagedReads } from './salvage-observation'
|
||||
import * as deliveryAmbiguity from '../../transport/rpc-delivery-ambiguity'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { extname, join, relative, resolve } from 'node:path'
|
||||
import ts from 'typescript'
|
||||
import ts from 'typescript-api'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { censusSourceFiles } from '../test-support/census-source-files'
|
||||
import {
|
||||
|
||||
Reference in New Issue
Block a user