ttsc
Version:
General-purpose TypeScript-Go compiler, runtime, plugin host, and LSP host.
134 lines • 5.36 kB
JavaScript
;
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