|
| 1 | +import crypto from 'node:crypto' |
| 2 | +import { |
| 3 | + chmodSync, |
| 4 | + existsSync, |
| 5 | + mkdirSync, |
| 6 | + readFileSync, |
| 7 | + writeFileSync, |
| 8 | +} from 'node:fs' |
| 9 | +import { homedir } from 'node:os' |
| 10 | +import { dirname, join } from 'pathe' |
| 11 | +import { searchForWorkspaceRoot } from 'vite' |
| 12 | + |
| 13 | +export const API_TOKEN_FILE = '.vitest-secret-token' |
| 14 | + |
| 15 | +// Follows env-paths' user data directory conventions: |
| 16 | +// https://github.com/sindresorhus/env-paths/blob/v4.0.0/index.js |
| 17 | +function getUserDataDir(): string { |
| 18 | + if (process.platform === 'win32') { |
| 19 | + return process.env.LOCALAPPDATA || join(homedir(), 'AppData/Local') |
| 20 | + } |
| 21 | + if (process.platform === 'darwin') { |
| 22 | + return join(homedir(), 'Library/Application Support') |
| 23 | + } |
| 24 | + return process.env.XDG_DATA_HOME || join(homedir(), '.local/share') |
| 25 | +} |
| 26 | + |
| 27 | +function resolveTokenFromPath(tokenPath: string): { token: string; tokenCreated: boolean } { |
| 28 | + if (existsSync(tokenPath)) { |
| 29 | + return { token: readFileSync(tokenPath, 'utf-8').trim(), tokenCreated: false } |
| 30 | + } |
| 31 | + |
| 32 | + const token = crypto.randomUUID() |
| 33 | + mkdirSync(dirname(tokenPath), { recursive: true, mode: 0o700 }) |
| 34 | + writeFileSync(tokenPath, `${token}\n`, { mode: 0o600 }) |
| 35 | + try { |
| 36 | + chmodSync(dirname(tokenPath), 0o700) |
| 37 | + chmodSync(tokenPath, 0o600) |
| 38 | + } |
| 39 | + catch {} |
| 40 | + return { token, tokenCreated: true } |
| 41 | +} |
| 42 | + |
| 43 | +export function resolveApiToken(root: string): { token: string; tokenCreated: boolean; tokenPath: string } { |
| 44 | + const tokenPaths = [ |
| 45 | + join(getUserDataDir(), 'vitest', API_TOKEN_FILE), |
| 46 | + join(searchForWorkspaceRoot(root), 'node_modules/.vitest', API_TOKEN_FILE), |
| 47 | + ] |
| 48 | + |
| 49 | + for (const tokenPath of tokenPaths) { |
| 50 | + try { |
| 51 | + return { ...resolveTokenFromPath(tokenPath), tokenPath } |
| 52 | + } |
| 53 | + catch {} |
| 54 | + } |
| 55 | + |
| 56 | + throw new Error(`Failed to create Vitest API token at ${tokenPaths.join(' or ')}`) |
| 57 | +} |
0 commit comments