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:
Neil
2026-10-24 23:09:20 -07:00
committed by GitHub
parent fef00e4461
commit cc2b6fe6a2
23 changed files with 510 additions and 368 deletions
+11 -12
View File
@@ -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()
})
-2
View File
@@ -14,5 +14,3 @@ dist/
*.mobileprovision
*.orig.*
web-build/
.cache/typechecks/
+5 -4
View File
@@ -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"
+24
View File
@@ -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
+365 -220
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -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),
+24 -31
View File
@@ -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 }
}
-36
View File
@@ -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 -1
View File
@@ -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 {