UNPKG

ttsc

Version:

General-purpose TypeScript-Go compiler, runtime, plugin host, and LSP host.

134 lines 5.36 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveProjectConfig = resolveProjectConfig; exports.resolveProjectIdentity = resolveProjectIdentity; const node_fs_1 = __importDefault(require("node:fs")); const node_path_1 = __importDefault(require("node:path")); /** * Resolve the tsconfig/jsconfig that owns a ttsc invocation. * * Resolution order: * * 1. `opts.tsconfig` — resolved absolute and checked for existence. * 2. `opts.file` — the nearest ancestor config that contains the file is found by * walking up from the file's directory. * 3. `opts.cwd` — the nearest ancestor config walking up from cwd. * * Returns the real (symlink-resolved) absolute config path. Use * {@link resolveProjectIdentity} when both the caller-selected spelling and the * Program identity are required. */ function resolveProjectConfig(opts = {}) { return resolveProjectIdentity(opts).physicalConfigPath; } /** * Resolve the selected config while retaining its lexical spelling separately * from the physical paths used by the TypeScript Program. */ function resolveProjectIdentity(opts = {}) { const cwd = node_path_1.default.resolve(opts.cwd ?? process.cwd()); const explicitProjectRoot = opts.projectRoot === undefined || opts.projectRoot === "" ? undefined : resolveAbsolutePath(cwd, opts.projectRoot); let logicalConfigPath; if (opts.tsconfig) { const resolved = resolveAbsolutePath(cwd, opts.tsconfig); if (!node_fs_1.default.existsSync(resolved)) { throw new Error(`ttsc: tsconfig not found: ${resolved}`); } // `-p <directory>` is the documented tsgo shorthand for the // directory that contains a `tsconfig.json`. Mirror that — without // this branch a forwarded `--tsconfig=sub` would feed the directory // path into `readResolvedCompilerOptions`, which calls // `fs.readFileSync` and throws `EISDIR` (the RCA's predicted // RC-3 §5 #2 bug, pinned by // `test_ttsc_dash_p_directory_path_is_accepted`). if (isDirectory(resolved)) { const tsconfigInDir = node_path_1.default.join(resolved, "tsconfig.json"); if (node_fs_1.default.existsSync(tsconfigInDir)) { logicalConfigPath = tsconfigInDir; } else { const jsconfigInDir = node_path_1.default.join(resolved, "jsconfig.json"); if (node_fs_1.default.existsSync(jsconfigInDir)) { logicalConfigPath = jsconfigInDir; } else { throw new Error(`ttsc: directory has no tsconfig.json / jsconfig.json: ${resolved}`); } } } else { logicalConfigPath = resolved; } } else { const start = opts.file ? resolveAbsolutePath(cwd, opts.file) : cwd; const from = isDirectory(start) ? start : node_path_1.default.dirname(start); const found = findUp(from, ["tsconfig.json", "jsconfig.json"]); if (!found) { throw new Error(`ttsc: could not find tsconfig.json or jsconfig.json starting from ${from}`); } logicalConfigPath = found; } const physicalConfigPath = resolveRealPath(logicalConfigPath); const physicalProjectRoot = resolveRealPath(explicitProjectRoot ?? node_path_1.default.dirname(physicalConfigPath)); return { ...(explicitProjectRoot === undefined ? {} : { explicitProjectRoot }), invocationCwd: cwd, logicalConfigPath, logicalProjectRoot: node_path_1.default.dirname(logicalConfigPath), physicalConfigPath, physicalProjectRoot, }; } /** Resolve `target` against `cwd` when it is not already absolute. */ function resolveAbsolutePath(cwd, target) { return node_path_1.default.isAbsolute(target) ? target : node_path_1.default.resolve(cwd, target); } /** * Resolve symlinks on `location`, returning the original path when * `realpathSync` fails (e.g. when the file does not yet exist). */ function resolveRealPath(location) { try { return node_fs_1.default.realpathSync(location); } catch { return location; } } /** * Walk up the directory tree from `from`, returning the first directory that * contains a file whose name is in `names`. Returns `null` when the filesystem * root is reached without finding a match. */ function findUp(from, names) { let current = node_path_1.default.resolve(from); while (true) { for (const name of names) { const candidate = node_path_1.default.join(current, name); if (node_fs_1.default.existsSync(candidate)) { return candidate; } } const parent = node_path_1.default.dirname(current); if (parent === current) { return null; } current = parent; } } /** Return true when `location` exists and is a directory. */ function isDirectory(location) { try { return node_fs_1.default.statSync(location).isDirectory(); } catch { return false; } } //# sourceMappingURL=resolveProjectConfig.js.map