UNPKG

merge-tsconfigs

Version:

Merge-tsconfigs is a CLI and node tool for merging tsconfig files into the exact tsconfig file you want 🛣️

300 lines (293 loc) 10.9 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { default: () => src_default, logger: () => logger, mergeConfigContent: () => mergeConfigContent, mergeConfigObjects: () => mergeConfigObjects, mergeTsConfigs: () => mergeTsConfigs, parsePath: () => parsePath, resolveJSON: () => resolveJSON, script: () => script, updateCompilerOptions: () => updateCompilerOptions, writeTsconfig: () => writeTsconfig }); module.exports = __toCommonJS(src_exports); // src/scripts.ts var import_fs = require("fs"); var import_path = require("path"); var import_json5 = __toESM(require("json5"), 1); var logger = ({ isDebugging = false, emoji = `\u{1F6E3}\uFE0F`, gap = ` => `, name = "merge-tsconfigs" }) => (type) => (section) => (message) => (err) => { const debugMsg = isDebugging ? "debugging:" : ""; const sectionMsg = section.length ? `${section}:` : ""; const firstLine = `${name}:${debugMsg}${sectionMsg}`; const secondLine = message ? `${emoji}${gap}${message}` : ""; if (type === "error") { console.error(firstLine); if (secondLine) console.error(secondLine); if (err) console.error(err); } else if (type === "debug") { console.debug(firstLine); if (secondLine) console.debug(secondLine); } else if (type === "info") { console.info(firstLine); if (secondLine) console.info(secondLine); } else { console.log(firstLine); if (secondLine) console.log(secondLine); } }; function resolveJSON(path, debug = false) { try { const json = import_json5.default.parse((0, import_fs.readFileSync)(path, "utf8")); return json; } catch (err) { if (debug) logger({ isDebugging: debug })("error")("resolveJSON")("There was an error:")(err); return {}; } } var mergeConfigObjects = (tsconfig1, tsconfig2) => ({ ...tsconfig1, ...tsconfig2, compilerOptions: { ...tsconfig1?.compilerOptions, ...tsconfig2?.compilerOptions }, ...tsconfig1?.exclude || tsconfig2?.exclude ? { exclude: [ ...tsconfig1?.exclude || [], ...tsconfig2?.exclude || [] ] } : {}, ...tsconfig1?.include || tsconfig2?.include ? { include: [ ...tsconfig1?.include || [], ...tsconfig2?.include || [] ] } : {} }); var mergeConfigContent = (tsconfigs, cwd, debug = false) => tsconfigs.reduce((acc = {}, tsconfig) => { const path = `${cwd}/${tsconfig}`; let tsconfigJSON = resolveJSON(path, debug); const parentPath = tsconfigJSON?.extends; if (parentPath) { const relativeParentPath = (0, import_path.join)((0, import_path.dirname)(path), parentPath); const parentTsconfig = resolveJSON(relativeParentPath, debug); if (parentTsconfig?.extends) { logger({ isDebugging: debug })("error")("mergeConfigContent")("Parent tsconfig:merge-tsconfigs only handles extending from a parent, consider extending tsconfigs less.")(parentTsconfig); } const { extends: _, ...tsconfigWithoutExtends } = tsconfigJSON; tsconfigJSON = mergeConfigObjects(parentTsconfig, tsconfigWithoutExtends); } if (!tsconfigJSON) { if (debug) logger({ isDebugging: debug })("error")("mergeConfigContent")("There was an error:")(tsconfigJSON); return acc; } return mergeConfigObjects(acc, tsconfigJSON); }, {}); var writeTsconfig = (tsconfig, cwd, out, isTesting) => { if (isTesting) return tsconfig; const path = `${cwd}/${out}`; (0, import_fs.mkdirSync)((0, import_path.dirname)(path), { recursive: true }); (0, import_fs.writeFileSync)(path, JSON.stringify(tsconfig, null, 2)); return tsconfig; }; var updateCompilerOptions = (compilerOptions2 = {}, currentCompilerOptions, updatedPath) => { const compilerOptionKeys = compilerOptions2 ? Object.keys(compilerOptions2) : []; const hasCompilerOptions = compilerOptionKeys.length > 0; if (!hasCompilerOptions) return {}; return compilerOptionKeys.reduce((acc = {}, key) => { const updatedOptions = { ...acc, ...currentCompilerOptions }; const value = compilerOptions2?.[key]; if (updatedOptions?.[key] === "delete") { delete updatedOptions[key]; return updatedOptions || {}; } const paths = { ...updatedOptions.paths || {}, ...key === "paths" ? { value } : {}, ...updatedPath ? { ...updatedPath } : {} }; return { ...updatedOptions, [key]: value, ...Object.keys(paths).length > 0 ? { paths } : {} }; }, {}); }; var parsePath = (path = "", debug = false) => { if (!path) return {}; try { const json = import_json5.default.parse(path); return json; } catch (err) { if (debug) logger({ isDebugging: debug })("error")("parsePath")("There was an error:")(err); return {}; } }; var mergeTsConfigs = ({ tsconfigs = [], exclude, include, compilerOptions: compilerOptions2, debug = false, out = "tsconfig.merged.json", path, isTesting = false }) => { if (tsconfigs.length === 0) { if (debug) logger({ isDebugging: debug })("error")("mergeTsConfig")("No tsconfig files were provided.")(null); return; } const cwd = process.cwd(); const updatedTsconfig = mergeConfigContent(tsconfigs, cwd, debug); if (debug) logger({ isDebugging: debug })("debug")("mergeTsConfig")("Updated tsconfig:")(updatedTsconfig); const updatedPath = parsePath(path, debug); const updatedCompilerOptions = updateCompilerOptions( compilerOptions2, updatedTsconfig?.compilerOptions || {}, updatedPath ); const updatedExclude = exclude ? { exclude: [...updatedTsconfig?.exclude || [], ...exclude] } : {}; const updatedInclude = include ? { include: [...updatedTsconfig.include || [], ...include] } : {}; const tsconfig = { ...updatedTsconfig, ...updatedExclude, ...updatedInclude, ...Object.keys(updatedCompilerOptions).length > 0 ? { compilerOptions: updatedCompilerOptions } : {} }; return writeTsconfig(tsconfig, cwd, out, isTesting); }; var script = mergeTsConfigs; var scripts_default = mergeTsConfigs; // src/program.ts var import_commander = require("commander"); // src/config.ts var compilerOptions = { target: "string", module: "string", lib: "array", allowJs: "boolean", checkJs: "boolean", jsx: "string", declaration: "boolean", sourceMap: "boolean", outFile: "string", outDir: "string", rootDir: "string", removeComments: "boolean", noEmit: "boolean", importHelpers: "boolean", downlevelIteration: "boolean", isolatedModules: "boolean", strict: "boolean", noImplicitAny: "boolean", strictNullChecks: "boolean", noImplicitThis: "boolean", alwaysStrict: "boolean", noUnusedLocals: "boolean", noUnusedParameters: "boolean", noImplicitReturns: "boolean", noFallthroughCasesInSwitch: "boolean", moduleResolution: "string", baseUrl: "string", paths: "object", rootDirs: "array", typeRoots: "array", types: "array", allowSyntheticDefaultImports: "boolean", sourceRoot: "string", mapRoot: "string", inlineSourceMap: "boolean", inlineSources: "boolean", experimentalDecorators: "boolean", emitDecoratorMetadata: "boolean" }; // src/program.ts function action(files, options = {}) { try { const { debug = false, exclude, include, isTesting = false, isTestingCLI = false, out, path, ...compilerOptions2 } = options; if (isTestingCLI) { console.info({ files, options }); return; } script({ debug, exclude, include, isTesting, path, out, tsconfigs: files, compilerOptions: compilerOptions2 }); } catch (err) { logger({ isDebugging: options.debug })("error")("action")("There was an error:")(err); } } import_commander.program.name("merge-tsconfigs").description( "Merge-tsconfigs is a CLI and node tool for merging tsconfig files into the exact tsconfig file you want \u{1F6E3}\uFE0F" ).argument("[files...]", "files to check, matches an array pattern").option("-d, --debug", "enable debugging").option("-e, --exclude [exclude...]", "files to exclude, matches a glob or array pattern").option("-i, --include [include...]", "files to include, matches a glob or array pattern").option("--isTesting", "enable testing").option("-o, --out <file>", "output file, otherwise, the file will be written to tsconfig.merged.json").option("--isTesting", "enable testing").option("-t, --isTestingCLI", "enable CLI only testing").option("-p, --path <path>", 'a json parseable string wrapped object, e.g. {"item/*": ["foo": "bar"]}'); Object.keys(compilerOptions).map((name) => ({ name, value: compilerOptions[name] })).forEach(({ name, value }) => { if (value === "boolean") { import_commander.program.option(`--${name}`, `tsconfig.compilerOptions.${name}`); } else if (value === "string") { import_commander.program.option(`--${name} <${value}>`, `tsconfig.compilerOptions.${name}`); } else if (value === "array") { import_commander.program.option(`--${name} [${value}...]`, `tsconfig.compilerOptions.${name}`); } else if (value === "object") { import_commander.program.option(`--${name} <${value}>`, `tsconfig.compilerOptions.${name}`); } }); import_commander.program.action(action).parse(process.argv); // src/index.ts var src_default = scripts_default; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { logger, mergeConfigContent, mergeConfigObjects, mergeTsConfigs, parsePath, resolveJSON, script, updateCompilerOptions, writeTsconfig });