chore(lint): adopt unicorn/prefer-import-meta-properties (error) (#6847)

Migrate fileURLToPath(import.meta.url) / dirname(...) boilerplate to the
native import.meta.dirname / import.meta.filename, then enable the rule
at error so new code stays on the native form.

The oxlint autofix rewrites the expression but leaves the now-unused
node:url / node:path imports behind (which the already-enabled
no-unused-vars=error would then flag), so this commit also removes those
34 orphaned imports — trimming the named import where other names are
still used, deleting the line where it was the sole import.

Scope is build scripts + Node-env tests only (config/scripts, tools/
benchmarks, *.test.{ts,mjs}, vitest configs); zero shipped runtime code.
The native properties are exact equivalents (Node >= 20.11; repo is on
24), so behavior is unchanged.

Verified: oxlint 0 errors tree-wide (root + mobile), oxfmt clean,
typecheck (node+cli+web) + mobile tsc pass, root vitest 22825 passed /
0 failed, mobile vitest 1018 passed. Exercised the rewritten scripts
directly: build:relay (6 targets), ensure-native-runtime,
verify-macos-entitlements all run correctly with import.meta.dirname.
This commit is contained in:
Neil 2026-06-29 23:37:30 -07:00 committed by GitHub
parent 2f5f7daa03
commit f9e18910ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 59 additions and 95 deletions

View File

@ -61,6 +61,7 @@
"unicorn/prefer-at": "error",
"unicorn/prefer-date-now": "error",
"unicorn/prefer-includes": "error",
"unicorn/prefer-import-meta-properties": "error",
"unicorn/prefer-math-min-max": "error",
"unicorn/prefer-negative-index": "error",
"unicorn/prefer-node-protocol": "error",

View File

@ -1,9 +1,8 @@
import { spawnSync } from 'node:child_process'
import { chmodSync, copyFileSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..')
const repoRoot = path.resolve(import.meta.dirname, '../..')
const packagePath = path.join(repoRoot, 'native', 'computer-use-macos')
const binaryPath = path.join(packagePath, '.build', 'release', 'orca-computer-use-macos')
const appPath = path.join(packagePath, '.build', 'release', 'Orca Computer Use.app')

View File

@ -11,10 +11,9 @@
import { build } from 'esbuild'
import { createHash } from 'node:crypto'
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
import { join, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join } from 'node:path'
const __dirname = dirname(fileURLToPath(import.meta.url))
const __dirname = import.meta.dirname
// Why: the script lives under config/scripts, so go two levels up to reach the repo root.
const ROOT = join(__dirname, '..', '..')
const RELAY_ENTRY = join(ROOT, 'src', 'relay', 'relay.ts')

View File

@ -1,9 +1,8 @@
#!/usr/bin/env node
import { readdir, stat } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const __dirname = import.meta.dirname
const ROOT = path.join(__dirname, '..', '..')
const FEATURE_WALL_ASSET_DIR = path.join(ROOT, 'resources', 'onboarding', 'feature-wall')
const MAX_BYTES = 11 * 1024 * 1024

View File

@ -1,10 +1,9 @@
import { readFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
import { parse } from 'yaml'
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
const projectDir = resolve(import.meta.dirname, '../..')
describe('computer-use e2e workflow', () => {
it('runs computer-use e2e files serially because they share desktop focus', () => {

View File

@ -1,9 +1,8 @@
import { readFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
const projectDir = resolve(import.meta.dirname, '../..')
const skillPath = join(projectDir, 'skills', 'computer-use', 'SKILL.md')
describe('computer-use skill guidance', () => {

View File

@ -4,12 +4,11 @@ import { spawnSync } from 'node:child_process'
import { createRequire } from 'node:module'
import { existsSync, readFileSync } from 'node:fs'
import { release } from 'node:os'
import { basename, dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { basename, resolve } from 'node:path'
const require = createRequire(import.meta.url)
const scriptPath = fileURLToPath(import.meta.url)
const projectDir = resolve(dirname(scriptPath), '../..')
const scriptPath = import.meta.filename
const projectDir = resolve(import.meta.dirname, '../..')
const runtime = readRuntimeArg()
const NATIVE_MODULES = ['node-pty']

View File

@ -4,9 +4,8 @@
import { existsSync, lstatSync, readlinkSync } from 'node:fs'
import { execFileSync } from 'node:child_process'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const scriptDir = path.dirname(fileURLToPath(import.meta.url))
const scriptDir = import.meta.dirname
const source = path.join(scriptDir, 'orca-dev.mjs')
const commandPath =

View File

@ -14,10 +14,9 @@ import {
import { spawnSync } from 'node:child_process'
import { createRequire } from 'node:module'
import { platform as osPlatform, tmpdir } from 'node:os'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
const projectDir = resolve(import.meta.dirname, '../..')
const electronPackageDir = resolve(projectDir, 'node_modules/electron')
const electronRequire = createRequire(resolve(electronPackageDir, 'package.json'))
const { version: electronVersion } = electronRequire('./package.json')

View File

@ -1,14 +1,10 @@
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
// Korean key-specific overrides (reviewed in full UI context: product names, git terms, and
// labels MT mistranslated). Stored as a JSON data file — too many entries to inline under the
// .mjs max-lines limit — and loaded here so the catalog scripts keep a single ko key-override source.
const jsonPath = path.join(
path.dirname(fileURLToPath(import.meta.url)),
'locale-ko-key-overrides.json'
)
const jsonPath = path.join(import.meta.dirname, 'locale-ko-key-overrides.json')
let parsed
try {

View File

@ -1,9 +1,8 @@
import { readFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
const projectDir = resolve(import.meta.dirname, '../..')
const skillPath = join(projectDir, 'skills', 'orca-cli', 'SKILL.md')
function readSkill() {

View File

@ -3,9 +3,8 @@
import { spawnSync } from 'node:child_process'
import { accessSync, constants, existsSync, realpathSync, statSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const scriptPath = realpathSync(fileURLToPath(import.meta.url))
const scriptPath = realpathSync(import.meta.filename)
const scriptDir = path.dirname(scriptPath)
const repoRoot = path.resolve(scriptDir, '..', '..')
const cliEntry =

View File

@ -1,9 +1,8 @@
import { readFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
const projectDir = resolve(import.meta.dirname, '../..')
const canonicalSkillPath = join(projectDir, 'skills', 'orca-linear', 'SKILL.md')
const legacySkillPath = join(projectDir, 'skills', 'linear-tickets', 'SKILL.md')
const legacyIntro =

View File

@ -1,9 +1,8 @@
import { readFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
const projectDir = resolve(import.meta.dirname, '../..')
const skillPath = join(projectDir, 'skills', 'orchestration', 'SKILL.md')
function readSkill() {

View File

@ -1,10 +1,9 @@
import { readFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
import { parse } from 'yaml'
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
const projectDir = resolve(import.meta.dirname, '../..')
const packageJson = JSON.parse(readFileSync(join(projectDir, 'package.json'), 'utf8'))
describe('Electron runtime package contract', () => {

View File

@ -17,7 +17,6 @@ import {
import net from 'node:net'
import { createRequire } from 'node:module'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
// Why: Electron-based hosts (e.g. Claude Code, VS Code) set
// ELECTRON_RUN_AS_NODE=1 in their terminal environment. If this leaks into
@ -26,7 +25,7 @@ import { fileURLToPath } from 'node:url'
delete process.env.ELECTRON_RUN_AS_NODE
const require = createRequire(import.meta.url)
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..')
const repoRoot = path.resolve(import.meta.dirname, '../..')
const STABLE_NAME_FLAG = '--stable-name'
const rawForwardedArgs = process.argv.slice(2)
// Why: keep an escape hatch for tools that key off Electron's stock app name.

View File

@ -4,7 +4,6 @@ import { execFileSync, spawnSync } from 'node:child_process'
import { existsSync, mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { installSyntheticVisibleSpinners } from './idle-cpu-synthetic-spinners.mjs'
const DEFAULT_WARMUP_MS = 15_000
@ -454,7 +453,7 @@ function terminateProcesses(processes) {
async function main() {
const options = parseArgs(process.argv.slice(2))
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
const root = path.resolve(import.meta.dirname, '..', '..')
const mainPath = buildAppIfNeeded(root, options.skipBuild)
const userDataDir = mkdtempSync(path.join(os.tmpdir(), 'orca-idle-cpu-userdata-'))
const { repoDir, cleanupDirs } = createIdleRepo(options.worktrees)

View File

@ -2,7 +2,6 @@
import { accessSync, constants, existsSync } from 'node:fs'
import { spawnSync } from 'node:child_process'
import { resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
function isExecutable(filePath, platform, access = accessSync) {
if (platform === 'win32') {
@ -59,6 +58,6 @@ export function runInternalDevSetup({
return 0
}
if (process.argv[1] && resolve(fileURLToPath(import.meta.url)) === resolve(process.argv[1])) {
if (process.argv[1] && resolve(import.meta.filename) === resolve(process.argv[1])) {
process.exit(runInternalDevSetup())
}

View File

@ -2,7 +2,6 @@ import { spawnSync } from 'node:child_process'
import { closeSync, copyFileSync, mkdirSync, mkdtempSync, openSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
const DEFAULT_REPORT_PATH = 'test-results/terminal-scale-perf-report.json'
@ -118,6 +117,6 @@ export function runTerminalScalePerfReportGate({
return exitCode(budgetResult)
}
if (process.argv[1] === fileURLToPath(import.meta.url)) {
if (process.argv[1] === import.meta.filename) {
process.exit(runTerminalScalePerfReportGate())
}

View File

@ -5,7 +5,6 @@
// ~83% of the frame and looks visibly small next to native apps (issue #5357).
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { PNG } from 'pngjs'
// Why: Windows renders the largest ICO frame at small sizes too, so the glyph
@ -195,7 +194,7 @@ export function buildWindowsIcoFromPng(sourcePngBuffer, sizes = ICO_FRAME_SIZES)
}
function resolveDefaultPaths() {
const scriptDir = dirname(fileURLToPath(import.meta.url))
const scriptDir = import.meta.dirname
const projectDir = dirname(dirname(scriptDir))
return {
sourcePng: join(projectDir, 'resources', 'build', 'icon.png'),

View File

@ -1,6 +1,5 @@
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { describe, expect, it } from 'vitest'
import { PNG } from 'pngjs'
import {
@ -11,7 +10,7 @@ import {
squareWithMargin
} from './trim-windows-icon-source.mjs'
const scriptDir = dirname(fileURLToPath(import.meta.url))
const scriptDir = import.meta.dirname
const projectDir = dirname(dirname(scriptDir))
const buildDir = join(projectDir, 'resources', 'build')

View File

@ -3,9 +3,8 @@ import { copyFile, mkdir, writeFile } from 'node:fs/promises'
import { spawnSync } from 'node:child_process'
import { homedir } from 'node:os'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const __dirname = import.meta.dirname
const ROOT = path.join(__dirname, '..', '..')
const DEFAULT_MARKETING_REPO = path.join(
homedir(),

View File

@ -2,9 +2,8 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = fileURLToPath(new URL('.', import.meta.url))
const __dirname = import.meta.dirname
const repoRoot = resolve(__dirname, '../..')
const defaultPlists = [

View File

@ -31,8 +31,7 @@
// and the Windows `.cmd`-shim/`shell: true` workaround.
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
// Why @electron/asar: canonical replacement for the deprecated `asar` package.
// It's transitively available via electron-builder (and pnpm's
// `shamefully-hoist=true` in `.npmrc` flattens it into the root
@ -45,7 +44,7 @@ import { extractFile, listPackage } from '@electron/asar'
// Resolving relative to the script's own location turns a misleading
// "could not parse TELEMETRY_ENABLED flag" parse error into a clear
// file-not-found error, and decouples the script from the caller's cwd.
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..')
const repoRoot = resolve(import.meta.dirname, '..', '..')
function findAsar(rootDir) {
// Why: electron-builder produces one `app.asar` per platform-arch combo.

View File

@ -3,10 +3,9 @@
import { spawn } from 'node:child_process'
import path from 'node:path'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import { ensureMobileExpoCli } from './mobile-expo-cli.mjs'
const scriptDir = path.dirname(fileURLToPath(import.meta.url))
const scriptDir = import.meta.dirname
const mobileDir = path.resolve(scriptDir, '..')
function pnpmCommand(args) {

View File

@ -1,12 +1,11 @@
import { describe, expect, it } from 'vitest'
import { readFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { resolve } from 'node:path'
import { MOBILE_AGENT_CATALOG } from './mobile-agent-catalog'
import { MOBILE_TUI_AGENT_AUTO_PICK_ORDER } from './mobile-tui-agents'
const currentDir = dirname(fileURLToPath(import.meta.url))
const currentDir = import.meta.dirname
function readDesktopSharedFile(relativePath: string): string {
return readFileSync(resolve(currentDir, '../../../src/shared', relativePath), 'utf8')

View File

@ -1,5 +1,4 @@
import { defineConfig } from 'vitest/config'
import { fileURLToPath } from 'node:url'
const tsconfigRaw = JSON.stringify({
compilerOptions: {
@ -12,7 +11,7 @@ const tsconfigRaw = JSON.stringify({
})
export default defineConfig({
root: fileURLToPath(new URL('.', import.meta.url)),
root: import.meta.dirname,
esbuild: {
tsconfigRaw
},

View File

@ -1,9 +1,8 @@
import { spawn } from 'node:child_process'
import { writeFileSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const __dirname = import.meta.dirname
const grandchildPath = path.join(__dirname, 'electron-vite-dev-grandchild.mjs')
const pidFile = process.env.ORCA_DEV_WRAPPER_TEST_PID_FILE
const envFile = process.env.ORCA_DEV_WRAPPER_TEST_ENV_FILE

View File

@ -1,9 +1,8 @@
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join } from 'node:path'
import { describe, expect, it } from 'vitest'
const ONBOARDING_FLOW_PATH = join(dirname(fileURLToPath(import.meta.url)), 'use-onboarding-flow.ts')
const ONBOARDING_FLOW_PATH = join(import.meta.dirname, 'use-onboarding-flow.ts')
describe('useOnboardingFlow project-added handoff', () => {
it('routes Git repo completion through the shared default-checkout opener', () => {

View File

@ -1,16 +1,15 @@
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join } from 'node:path'
import { describe, expect, it } from 'vitest'
const ADD_REPO_DIALOG_PATH = join(dirname(fileURLToPath(import.meta.url)), 'AddRepoDialog.tsx')
const ADD_REPO_DIALOG_PATH = join(import.meta.dirname, 'AddRepoDialog.tsx')
const ADD_REPO_FLOW_PATHS = [
ADD_REPO_DIALOG_PATH,
join(dirname(fileURLToPath(import.meta.url)), 'AddRepoSteps.tsx'),
join(dirname(fileURLToPath(import.meta.url)), 'useAddRepoCloneFlow.ts'),
join(dirname(fileURLToPath(import.meta.url)), 'useAddRepoLocalFolderFlow.ts'),
join(dirname(fileURLToPath(import.meta.url)), 'useAddRepoServerPathFlow.ts'),
join(dirname(fileURLToPath(import.meta.url)), 'useAddRepoNestedImportFlow.ts')
join(import.meta.dirname, 'AddRepoSteps.tsx'),
join(import.meta.dirname, 'useAddRepoCloneFlow.ts'),
join(import.meta.dirname, 'useAddRepoLocalFolderFlow.ts'),
join(import.meta.dirname, 'useAddRepoServerPathFlow.ts'),
join(import.meta.dirname, 'useAddRepoNestedImportFlow.ts')
]
function readAddRepoFlowSource(): string {

View File

@ -1,11 +1,10 @@
import { readFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
import { WORKTREE_SIDEBAR_RESIZE_HANDLE_CLASS_NAME } from './index'
function getWorktreeSidebarScrollbarPaddingRight(): number {
const testDir = dirname(fileURLToPath(import.meta.url))
const testDir = import.meta.dirname
const css = readFileSync(resolve(testDir, '../../assets/main.css'), 'utf8')
const block = css.match(/\.worktree-sidebar-scrollbar\s*\{(?<body>[^}]*)\}/)?.groups?.body ?? ''
const value = block.match(/padding-right:\s*(?<px>\d+)px/)?.groups?.px

View File

@ -1,6 +1,5 @@
import { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { dirname, resolve } from 'node:path'
import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
import { buildSettingsNavigationMetadata } from './useSettingsNavigationMetadata'
import type { Repo } from '../../../shared/types'
@ -169,7 +168,7 @@ describe('settings navigation metadata', () => {
})
it('does not import Settings page or pane UI modules from the metadata hook', () => {
const testDir = dirname(fileURLToPath(import.meta.url))
const testDir = import.meta.dirname
const hookSource = readFileSync(resolve(testDir, 'useSettingsNavigationMetadata.ts'), 'utf8')
const importLines = hookSource
.split('\n')
@ -182,7 +181,7 @@ describe('settings navigation metadata', () => {
})
it('does not import Settings page or pane UI modules from the quick action registry', () => {
const testDir = dirname(fileURLToPath(import.meta.url))
const testDir = import.meta.dirname
const registrySource = readFileSync(
resolve(testDir, '../components/cmd-j/quick-actions.ts'),
'utf8'

View File

@ -7,12 +7,11 @@
import { createRequire } from 'node:module'
import { createWriteStream, existsSync, mkdirSync, writeFileSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const require = createRequire(import.meta.url)
const pty = require('node-pty')
const scriptDir = path.dirname(fileURLToPath(import.meta.url))
const scriptDir = import.meta.dirname
const repoRoot = path.resolve(scriptDir, '..', '..')
function readOption(name, fallback) {

View File

@ -21,10 +21,9 @@
import { spawn, spawnSync } from 'node:child_process'
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
import os from 'node:os'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
const scriptDir = dirname(fileURLToPath(import.meta.url))
const scriptDir = import.meta.dirname
const repoRoot = resolve(scriptDir, '..', '..')
const CURRENT_PROTOCOL_VERSION = 12

View File

@ -29,10 +29,9 @@ import {
} from 'node:fs'
import { createRequire } from 'node:module'
import os from 'node:os'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { join, resolve } from 'node:path'
const scriptDir = dirname(fileURLToPath(import.meta.url))
const scriptDir = import.meta.dirname
const repoRoot = resolve(scriptDir, '..', '..')
const require = createRequire(import.meta.url)