UNPKG

ts-patch

Version:

Patch typescript to support custom transformers in tsconfig.json

773 lines (772 loc) 38.2 kB
var tsp = (function () { "use strict"; var tsp; (function (tsp) { const os = require("os"); const path = require("path"); const fs = require("fs"); tsp.diagnosticMap = new WeakMap(); tsp.supportedExtensions = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"]; tsp.tsExtensions = [".ts", ".mts", ".cts"]; function diagnosticExtrasFactory(program) { const diagnostics = tsp.diagnosticMap.get(program) || tsp.diagnosticMap.set(program, []).get(program); const addDiagnostic = (diag) => diagnostics.push(diag); const removeDiagnostic = (index) => { diagnostics.splice(index, 1); }; return { addDiagnostic, removeDiagnostic, diagnostics }; } tsp.diagnosticExtrasFactory = diagnosticExtrasFactory; function getTmpDir(subPath) { const tmpDir = path.resolve(os.tmpdir(), "tsp", subPath); if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir, { recursive: true }); return tmpDir; } tsp.getTmpDir = getTmpDir; function getTsInstance() { return (typeof ts !== "undefined" ? ts : module.exports); } tsp.getTsInstance = getTsInstance; function getErrorMessage(e) { return String(e?.message || ""); } function extractFilePathFromError(e) { if (typeof e?.fileName === "string") return e.fileName; const stack = String(e?.stack || ""); const fileUrlMatch = stack.match(/file:\/\/([^:\n)]+\.[cm]?[tj]sx?):\d+:\d+/); if (fileUrlMatch) return decodeURIComponent(fileUrlMatch[1]); const pathMatch = stack.match(/(\/[^:\n)]+\.[cm]?[tj]sx?):\d+:\d+/); return pathMatch?.[1]; } function describeEsmInCjsError(e) { const msg = getErrorMessage(e); const filePath = extractFilePathFromError(e); const sourceRef = filePath ? ` "${filePath}"` : ""; if (msg.includes("import.meta") && msg.includes("outside a module")) { return (`Transformer source${sourceRef} uses "import.meta" but was loaded as CommonJS. ` + `Rename the transformer or helper to ".mts", set the transformer tsConfig "module" to ESNext, ` + `or use NodeNext with "type": "module" in the nearest package.json.`); } if (/await is only valid/i.test(msg) && /module/i.test(msg)) { return (`Transformer source${sourceRef} uses top-level "await" but was loaded as CommonJS. ` + `Rename the transformer or helper to ".mts", set the transformer tsConfig "module" to ESNext, ` + `or use NodeNext with "type": "module" in the nearest package.json.`); } if (e?.code === "ERR_REQUIRE_ASYNC_MODULE") { return (`Transformer source${sourceRef} contains top-level "await" in its ESM graph and cannot be loaded synchronously with require(). ` + `Move async initialization out of the top level, or open an issue if the transformer requires async module initialization.`); } return undefined; } tsp.describeEsmInCjsError = describeEsmInCjsError; class TsPatchError extends Error { constructor(message, diagnostic) { super(message); this.diagnostic = diagnostic; } } tsp.TsPatchError = TsPatchError; })(tsp || (tsp = {})); var tsp; (function (tsp) { const fs = require("fs"); const path = require("path"); const url = require("url"); const moduleApi = require("module"); function isTypeScriptPath(filePath) { return tsp.tsExtensions.includes(path.extname(filePath)); } function isBuiltinModule(specifier) { const builtinModules = moduleApi.builtinModules; const normalized = specifier.replace(/^node:/, ""); return builtinModules?.includes(specifier) || builtinModules?.includes(normalized); } function getParentDir(parentURL) { if (!parentURL) return process.cwd(); if (!parentURL.startsWith("file:")) return process.cwd(); return path.dirname(url.fileURLToPath(parentURL)); } function maybeFileURLToPath(specifier) { return specifier.startsWith("file:") ? url.fileURLToPath(specifier) : undefined; } function tryFile(filePath) { try { const stat = fs.statSync(filePath); return stat.isFile() ? filePath : undefined; } catch { return undefined; } } function resolveTypeScriptFile(basePath) { const ext = path.extname(basePath); if (tsp.tsExtensions.includes(ext)) return tryFile(basePath); const extensionReplacements = { ".js": [".ts"], ".mjs": [".mts"], ".cjs": [".cts"] }; for (const replacementExt of extensionReplacements[ext] || []) { const candidate = basePath.slice(0, -ext.length) + replacementExt; const res = tryFile(candidate); if (res) return res; } if (!ext) { for (const candidateExt of tsp.tsExtensions) { const res = tryFile(basePath + candidateExt); if (res) return res; } for (const candidateExt of tsp.tsExtensions) { const res = tryFile(path.join(basePath, "index" + candidateExt)); if (res) return res; } } return undefined; } function getTypeScriptModulePath(specifier, parentURL, registerConfig) { if (isBuiltinModule(specifier)) return undefined; const fileURLPath = maybeFileURLToPath(specifier); if (fileURLPath) return resolveTypeScriptFile(fileURLPath); if (path.isAbsolute(specifier)) return resolveTypeScriptFile(specifier); if (specifier.startsWith(".")) { return resolveTypeScriptFile(path.resolve(getParentDir(parentURL), specifier)); } const { compilerOptions, pluginConfig } = registerConfig; if (pluginConfig.resolvePathAliases && compilerOptions?.baseUrl && compilerOptions.paths) { const matchPath = tsp.getTsConfigPaths().createMatchPath(compilerOptions.baseUrl, compilerOptions.paths); const matchedPath = matchPath(specifier, undefined, fs.existsSync, tsp.supportedExtensions); if (matchedPath) return resolveTypeScriptFile(matchedPath); } return undefined; } function getCompilerOptions(registerConfig) { const baseOptions = registerConfig.compilerOptions || {}; const compilerOptions = { ...baseOptions, target: baseOptions.target ?? tsp.tsShim.ScriptTarget.ES2022, jsx: baseOptions.jsx ?? tsp.tsShim.JsxEmit.React, esModuleInterop: baseOptions.esModuleInterop ?? true, module: baseOptions.module ?? tsp.tsShim.ModuleKind.NodeNext, sourceMap: true, inlineSourceMap: false, inlineSources: true, declaration: false, declarationMap: false, emitDeclarationOnly: false, noEmit: false, outDir: undefined, outFile: undefined, composite: undefined, declarationDir: undefined }; if (baseOptions.module === undefined) { compilerOptions.moduleResolution = baseOptions.moduleResolution ?? tsp.tsShim.ModuleResolutionKind.NodeNext; } else if (baseOptions.moduleResolution !== undefined) { compilerOptions.moduleResolution = baseOptions.moduleResolution; } return compilerOptions; } function getTranspileCompilerOptions(format, compilerOptions) { const transpileOptions = { ...compilerOptions, module: format === "module" ? tsp.tsShim.ModuleKind.ESNext : tsp.tsShim.ModuleKind.CommonJS }; delete transpileOptions.moduleResolution; return transpileOptions; } function formatDiagnostics(diagnostics) { const diagnosticHost = { getCurrentDirectory: () => process.cwd(), getCanonicalFileName: (fileName) => fileName, getNewLine: () => tsp.tsShim.sys.newLine }; const formatter = tsp.tsShim.formatDiagnosticsWithColorAndContext || tsp.tsShim.formatDiagnostics; return formatter(diagnostics, diagnosticHost); } function getTranspileDiagnostics(diagnostics) { const ignoredDiagnostics = new Set([6059, 18002, 18003]); return (diagnostics || []).filter(diagnostic => !ignoredDiagnostics.has(diagnostic.code)); } function inlineSourceMap(outputText, sourceMapText) { if (!sourceMapText) return outputText; const sourceMapComment = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${Buffer.from(sourceMapText, "utf8").toString("base64")}`; const outputWithoutSourceMap = outputText.replace(/\r?\n?\/\/# sourceMappingURL=.*(?:\r?\n)?$/, ""); return `${outputWithoutSourceMap}\n${sourceMapComment}`; } function compileTransformer(filePath, registerConfig) { const sourceText = fs.readFileSync(filePath, "utf8"); const compilerOptions = getCompilerOptions(registerConfig); const format = tsp.getEmitFormat(filePath, sourceText, compilerOptions); if (format === "unsupported") { const moduleKind = compilerOptions.module === undefined ? "undefined" : tsp.tsShim.ModuleKind[compilerOptions.module]; throw new tsp.TsPatchError(`Transformer "${filePath}" uses tsConfig "module" setting "${moduleKind}", which is not loadable in Node. ` + `Use CommonJS, ES2015 or later, ESNext, Node16, NodeNext, or a module-specific extension such as ".cts" or ".mts".`); } const result = tsp.tsShim.transpileModule(sourceText, { compilerOptions: getTranspileCompilerOptions(format, compilerOptions), fileName: filePath, reportDiagnostics: true }); const diagnostics = getTranspileDiagnostics(result.diagnostics); if (diagnostics.length) { throw new tsp.TsPatchError(`Unable to compile TypeScript transformer "${filePath}":\n` + formatDiagnostics(diagnostics)); } return { format, source: inlineSourceMap(result.outputText, result.sourceMapText) }; } function registerCompilerLoader(registerConfig) { if (typeof moduleApi.registerHooks !== "function") { throw new tsp.TsPatchError("TypeScript transformer loading requires Node.js >=22.15.0 with module.registerHooks()."); } const compiledFiles = new Map(); const hooks = moduleApi.registerHooks({ resolve(specifier, context, nextResolve) { const parentURL = context?.parentURL; const explicitTsPath = getTypeScriptModulePath(specifier, parentURL, registerConfig); if (explicitTsPath) { return { url: url.pathToFileURL(explicitTsPath).href, shortCircuit: true }; } try { const resolved = nextResolve(specifier, context); if (resolved?.url?.startsWith("file:")) { const resolvedPath = url.fileURLToPath(resolved.url); if (isTypeScriptPath(resolvedPath)) { return { url: resolved.url, shortCircuit: true }; } } return resolved; } catch (e) { const fallbackPath = getTypeScriptModulePath(specifier, parentURL, registerConfig); if (fallbackPath) { return { url: url.pathToFileURL(fallbackPath).href, shortCircuit: true }; } throw e; } }, load(fileURL, context, nextLoad) { if (!fileURL.startsWith("file:")) return nextLoad(fileURL, context); const filePath = url.fileURLToPath(fileURL); if (!isTypeScriptPath(filePath)) return nextLoad(fileURL, context); let compiledFile = compiledFiles.get(filePath); if (!compiledFile) { compiledFile = compileTransformer(filePath, registerConfig); compiledFiles.set(filePath, compiledFile); } return { format: compiledFile.format, source: compiledFile.source, shortCircuit: true }; } }); return () => { compiledFiles.clear(); hooks.deregister(); }; } tsp.registerCompilerLoader = registerCompilerLoader; })(tsp || (tsp = {})); var tsp; (function (tsp) { const crypto = require("crypto"); function createTransformersFromPattern(opt) { const { factory, config, program, ls, registerConfig } = opt; const { transform, after, afterDeclarations, name, type, transformProgram, ...cleanConfig } = config; if (!transform) throw new tsp.TsPatchError("Not a valid config entry: \"transform\" key not found"); const transformerKind = after ? "after" : afterDeclarations ? "afterDeclarations" : "before"; let pluginFactoryResult; switch (config.type) { case "ls": if (!ls) throw new tsp.TsPatchError(`Plugin ${transform} needs a LanguageService`); pluginFactoryResult = factory(ls, cleanConfig); break; case "config": pluginFactoryResult = factory(cleanConfig); break; case "compilerOptions": pluginFactoryResult = factory(program.getCompilerOptions(), cleanConfig); break; case "checker": pluginFactoryResult = factory(program.getTypeChecker(), cleanConfig); break; case undefined: case "program": const { addDiagnostic, removeDiagnostic, diagnostics } = tsp.diagnosticExtrasFactory(program); pluginFactoryResult = factory(program, cleanConfig, { ts: tsp.getTsInstance(), addDiagnostic, removeDiagnostic, diagnostics, library: tsp.currentLibrary }); break; case "raw": pluginFactoryResult = (ctx) => factory(ctx, program, cleanConfig); break; default: throw new tsp.TsPatchError(`Invalid plugin type found in tsconfig.json: '${config.type}'`); } let transformerFactories; switch (typeof pluginFactoryResult) { case "function": transformerFactories = [pluginFactoryResult]; break; case "object": const factoryOrFactories = pluginFactoryResult[transformerKind]; if (typeof factoryOrFactories === "function") { transformerFactories = [pluginFactoryResult[transformerKind]]; break; } else if (Array.isArray(factoryOrFactories)) { transformerFactories = [...factoryOrFactories]; break; } default: throw new tsp.TsPatchError(`Invalid plugin result: expected a function or an object with a '${transformerKind}' property`); } const wrappedFactories = []; for (const transformerFactory of transformerFactories) { if (!transformerFactory || typeof transformerFactory !== "function") throw new tsp.TsPatchError(`Invalid plugin entry point! Expected a transformer factory function or an object with a '${transformerKind}' property`); const wrapper = wrapTransformerFactory(transformerFactory, registerConfig, true); wrappedFactories.push(wrapper); } const res = { [transformerKind]: wrappedFactories }; return res; } function wrapTransformerFactory(transformerFn, requireConfig, wrapInnerFunction) { const wrapper = function tspWrappedFactory(...args) { let res; try { tsp.registerPlugin(requireConfig); if (!wrapInnerFunction) { res = transformerFn(...args); } else { const resFn = transformerFn(...args); if (typeof resFn !== "function") throw new tsp.TsPatchError("Invalid plugin: expected a function"); res = wrapTransformerFactory(resFn, requireConfig, false); } } catch (e) { const hint = tsp.describeEsmInCjsError(e); if (hint) throw new tsp.TsPatchError(hint); throw e; } finally { tsp.unregisterPlugin(); } return res; }; return wrapper; } class PluginCreator { constructor(configs, options) { this.plugins = []; this.configs = configs; this.options = options; const { resolveBaseDir } = options; this.plugins = configs .filter(config => config.transform !== undefined) .map(config => new tsp.TspPlugin(config, { resolveBaseDir })); this.needsTscJsDocParsing = this.plugins.some(plugin => plugin.packageConfig?.tscOptions?.parseAllJsDoc === true); } mergeTransformers(into, source) { const slice = (input) => (Array.isArray(input) ? input.slice() : [input]); if (source.before) into.before.push(...slice(source.before)); if (source.after) into.after.push(...slice(source.after)); if (source.afterDeclarations) into.afterDeclarations.push(...slice(source.afterDeclarations)); return this; } createSourceTransformers(params, customTransformers) { const transformers = { before: [], after: [], afterDeclarations: [] }; const [ls, program] = ("ls" in params) ? [params.ls, params.ls.getProgram()] : [void 0, params.program]; for (const plugin of this.plugins) { if (plugin.kind !== "SourceTransformer") continue; const { config } = plugin; const createFactoryResult = plugin.createFactory(); if (!createFactoryResult) continue; const { factory, registerConfig } = createFactoryResult; this.mergeTransformers(transformers, createTransformersFromPattern({ factory: factory, registerConfig, config, program, ls })); } if (customTransformers) this.mergeTransformers(transformers, customTransformers); return transformers; } createProgramTransformers() { const res = new Map(); for (const plugin of this.plugins) { if (plugin.kind !== "ProgramTransformer") continue; const { config } = plugin; const createFactoryResult = plugin.createFactory(); if (createFactoryResult === undefined) continue; const { registerConfig, factory: unwrappedFactory } = createFactoryResult; const factory = wrapTransformerFactory(unwrappedFactory, registerConfig, false); const transformerKey = crypto .createHash("md5") .update(JSON.stringify({ factory, config })) .digest("hex"); res.set(transformerKey, [factory, config]); } return res; } } tsp.PluginCreator = PluginCreator; })(tsp || (tsp = {})); var tsp; (function (tsp) { const path = require("path"); const fs = require("fs"); const requireStack = []; function getPackagePath(entryFilePath) { let currentDir = path.dirname(entryFilePath); const seenPaths = new Set(); while (currentDir !== path.parse(currentDir).root) { if (seenPaths.has(currentDir)) return undefined; seenPaths.add(currentDir); const potentialPkgPath = path.join(currentDir, "package.json"); if (fs.existsSync(potentialPkgPath)) return potentialPkgPath; currentDir = path.resolve(currentDir, ".."); } return undefined; } class TspPlugin { constructor(config, createOptions) { this.config = { ...config }; this.validateConfig(); this._createOptions = createOptions; this.importKey = config.import || "default"; this.kind = config.transformProgram === true ? "ProgramTransformer" : "SourceTransformer"; const { resolveBaseDir } = createOptions; const configTransformValue = config.transform; this.tsConfigPath = config.tsConfig && path.resolve(resolveBaseDir, config.tsConfig); const entryFilePath = require.resolve(configTransformValue, { paths: [resolveBaseDir] }); this.entryFilePath = entryFilePath; let pluginPackageConfig; const modulePackagePath = getPackagePath(entryFilePath); if (modulePackagePath) { const modulePkgJsonContent = fs.readFileSync(modulePackagePath, "utf8"); const modulePkgJson = JSON.parse(modulePkgJsonContent); pluginPackageConfig = modulePkgJson.tsp; if (pluginPackageConfig === null || typeof pluginPackageConfig !== "object") pluginPackageConfig = undefined; } this.packageConfig = pluginPackageConfig; } validateConfig() { const { config } = this; const configTransformValue = config.transform; if (!configTransformValue) throw new tsp.TsPatchError(`Invalid plugin config: missing "transform" value`); if (config.resolvePathAliases && !config.tsConfig) { console.warn(`[ts-patch] Warning: resolvePathAliases needs a tsConfig value pointing to a tsconfig.json for transformer" ${configTransformValue}.`); } } createFactory() { const { entryFilePath, config, tsConfigPath, importKey } = this; const configTransformValue = config.transform; if (requireStack.includes(entryFilePath)) return; requireStack.push(entryFilePath); const isTs = configTransformValue.match(/\.[mc]?ts$/) != null; const registerConfig = { isTs, tsConfig: tsConfigPath, pluginConfig: config }; tsp.registerPlugin(registerConfig); try { const commonjsModule = loadEntryFile(); const factoryModule = (typeof commonjsModule === "function") ? { default: commonjsModule } : commonjsModule; const factory = factoryModule[importKey]; if (!factory) throw new tsp.TsPatchError(`tsconfig.json > plugins: "${configTransformValue}" does not have an export "${importKey}": ` + require("util").inspect(factoryModule)); if (typeof factory !== "function") { throw new tsp.TsPatchError(`tsconfig.json > plugins: "${configTransformValue}" export "${importKey}" is not a plugin: ` + require("util").inspect(factory)); } return { factory, registerConfig: registerConfig }; } finally { requireStack.pop(); tsp.unregisterPlugin(); } function loadEntryFile() { try { return require(entryFilePath); } catch (e) { const hint = tsp.describeEsmInCjsError(e); if (hint) throw new tsp.TsPatchError(hint); throw e; } } } } tsp.TspPlugin = TspPlugin; })(tsp || (tsp = {})); var tsp; (function (tsp) { const path = require("path"); let configStack = []; function getTsConfigPaths() { try { return require("tsconfig-paths"); } catch (e) { if (e.code === "MODULE_NOT_FOUND") throw new tsp.TsPatchError(`resolvePathAliases requires the library: tsconfig-paths. ` + `Add tsconfig-paths as a (dev)-dependency or install globally.`); else throw e; } } tsp.getTsConfigPaths = getTsConfigPaths; function getCompilerOptions(tsConfig) { const configFile = tsp.tsShim.readConfigFile(tsConfig, tsp.tsShim.sys.readFile); const parsedConfig = configFile && tsp.tsShim.parseJsonConfigFileContent(configFile.config, tsp.tsShim.sys, path.dirname(tsConfig)); return parsedConfig.options; } function unregisterPlugin() { const activeRegisterConfig = configStack.pop(); if (activeRegisterConfig.tsConfigPathsCleanup) { activeRegisterConfig.tsConfigPathsCleanup(); delete activeRegisterConfig.tsConfigPathsCleanup; } if (activeRegisterConfig.compilerLoaderCleanup) { activeRegisterConfig.compilerLoaderCleanup(); delete activeRegisterConfig.compilerLoaderCleanup; } } tsp.unregisterPlugin = unregisterPlugin; function registerPlugin(registerConfig) { if (!registerConfig) throw new tsp.TsPatchError("requireConfig is required"); configStack.push(registerConfig); const { isTs, tsConfig, pluginConfig } = registerConfig; if (tsConfig && pluginConfig.resolvePathAliases) { registerConfig.compilerOptions ?? (registerConfig.compilerOptions = getCompilerOptions(tsConfig)); const { paths, baseUrl } = registerConfig.compilerOptions; if (paths && baseUrl) { registerConfig.tsConfigPathsCleanup = getTsConfigPaths().register({ baseUrl, paths }); } } if (isTs) { if (tsConfig) registerConfig.compilerOptions ?? (registerConfig.compilerOptions = getCompilerOptions(tsConfig)); registerConfig.compilerLoaderCleanup = tsp.registerCompilerLoader(registerConfig); } } tsp.registerPlugin = registerPlugin; })(tsp || (tsp = {})); var tsp; (function (tsp) { function getCreateSourceFileOptions(filePath, compilerOptions) { const implied = tsp.tsShim.getImpliedNodeFormatForFileWorker(filePath, undefined, tsp.tsShim.sys, compilerOptions); return { ...(typeof implied === "object" ? implied : { impliedNodeFormat: implied }), languageVersion: tsp.tsShim.getEmitScriptTarget(compilerOptions), setExternalModuleIndicator: tsp.tsShim.getSetExternalModuleIndicator(compilerOptions) }; } function createFormatSourceFile(filePath, sourceText, compilerOptions) { const sourceFileOptions = getCreateSourceFileOptions(filePath, compilerOptions); const sourceFile = tsp.tsShim.createSourceFile(filePath, sourceText, sourceFileOptions, false); const internalSourceFile = sourceFile; internalSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations; internalSourceFile.packageJsonScope = sourceFileOptions.packageJsonScope; return sourceFile; } function getEmitFormat(filePath, sourceText, compilerOptions) { const sourceFile = createFormatSourceFile(filePath, sourceText, compilerOptions); const emitKind = tsp.tsShim.getEmitModuleFormatOfFileWorker(sourceFile, compilerOptions); switch (emitKind) { case undefined: case tsp.tsShim.ModuleKind.None: case tsp.tsShim.ModuleKind.CommonJS: return "commonjs"; case tsp.tsShim.ModuleKind.AMD: case tsp.tsShim.ModuleKind.UMD: case tsp.tsShim.ModuleKind.System: case tsp.tsShim.ModuleKind.Preserve: return "unsupported"; case tsp.tsShim.ModuleKind.ES2015: case tsp.tsShim.ModuleKind.ES2020: case tsp.tsShim.ModuleKind.ES2022: case tsp.tsShim.ModuleKind.ESNext: default: return "module"; } } tsp.getEmitFormat = getEmitFormat; })(tsp || (tsp = {})); var tsp; (function (tsp) { const activeProgramTransformers = new Set(); const { dirname } = require("path"); function getProjectDir(compilerOptions) { return compilerOptions.configFilePath && dirname(compilerOptions.configFilePath); } function getProjectConfig(compilerOptions, rootFileNames) { let configFilePath = compilerOptions.configFilePath; let projectDir = getProjectDir(compilerOptions); if (configFilePath === undefined) { const baseDir = (rootFileNames.length > 0) ? dirname(rootFileNames[0]) : projectDir ?? process.cwd(); configFilePath = tsp.tsShim.findConfigFile(baseDir, tsp.tsShim.sys.fileExists); if (configFilePath) { const config = readConfig(configFilePath); compilerOptions = { ...config.options, ...compilerOptions }; projectDir = getProjectDir(compilerOptions); } } return ({ projectDir, compilerOptions }); } function readConfig(configFileNamePath) { const projectDir = dirname(configFileNamePath); const result = tsp.tsShim.readConfigFile(configFileNamePath, tsp.tsShim.sys.readFile); if (result.error) throw new tsp.TsPatchError("Error in tsconfig.json: " + result.error.messageText); return tsp.tsShim.parseJsonConfigFileContent(result.config, tsp.tsShim.sys, projectDir, undefined, configFileNamePath); } function preparePluginsFromCompilerOptions(plugins) { if (!plugins) return []; if ((plugins.length === 1) && plugins[0].customTransformers) { const { before = [], after = [] } = plugins[0].customTransformers; return [ ...before.map((item) => ({ transform: item })), ...after.map((item) => ({ transform: item, after: true })), ]; } return plugins; } function createProgram(rootNamesOrOptions, options, host, oldProgram, configFileParsingDiagnostics) { let rootNames; const createOpts = !Array.isArray(rootNamesOrOptions) ? rootNamesOrOptions : void 0; if (createOpts) { rootNames = createOpts.rootNames; options = createOpts.options; host = createOpts.host; oldProgram = createOpts.oldProgram; configFileParsingDiagnostics = createOpts.configFileParsingDiagnostics; } else { options = options; rootNames = rootNamesOrOptions; } const projectConfig = getProjectConfig(options, rootNames); if (["tsc", "tsserver", "tsserverlibrary"].includes(tsp.currentLibrary)) { options = projectConfig.compilerOptions; if (createOpts) createOpts.options = options; } const plugins = preparePluginsFromCompilerOptions(options.plugins); const pluginCreator = new tsp.PluginCreator(plugins, { resolveBaseDir: projectConfig.projectDir ?? process.cwd() }); if (tsp.currentLibrary === "tsc" && tsp.tsShim.JSDocParsingMode && pluginCreator.needsTscJsDocParsing) { host.jsDocParsingMode = tsp.tsShim.JSDocParsingMode.ParseAll; } let program = createOpts ? tsp.tsShim.originalCreateProgram(createOpts) : tsp.tsShim.originalCreateProgram(rootNames, options, host, oldProgram, configFileParsingDiagnostics); const programTransformers = pluginCreator.createProgramTransformers(); for (const [transformerKey, [programTransformer, config]] of programTransformers) { if (activeProgramTransformers.has(transformerKey)) continue; activeProgramTransformers.add(transformerKey); const newProgram = programTransformer(program, host, config, { ts: tsp.getTsInstance() }); if (typeof newProgram?.["emit"] === "function") program = newProgram; activeProgramTransformers.delete(transformerKey); } if (!program.originalEmit) { program.originalEmit = program.emit; program.emit = newEmit; } function newEmit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, ...additionalArgs) { const transformers = pluginCreator.createSourceTransformers({ program }, customTransformers); const result = program.originalEmit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, transformers, ...additionalArgs); for (const diagnostic of tsp.diagnosticMap.get(program) || []) if (!result.diagnostics.includes(diagnostic)) result.diagnostics.push(diagnostic); return result; } return program; } tsp.createProgram = createProgram; })(tsp || (tsp = {})); var tsp; (function (tsp) { tsp.tsShim = new Proxy({}, { get(_, key) { const target = tsp.getTsInstance(); if (target) { return target[key]; } else { try { return eval(key); } catch (e) { throw new tsp.TsPatchError(`Failed to find "${key}" in TypeScript shim`, e); } } }, }); })(tsp || (tsp = {})); return tsp; })();