UNPKG

@wessberg/rollup-plugin-ts

Version:

A TypeScript Rollup plugin that bundles declarations, respects Browserslists, and enables seamless integration with transpilers such as babel and swc

1,068 lines (1,032 loc) 427 kB
'use strict'; var path = require('crosspath'); var chalk = require('chalk'); var util = require('util'); var browserslistGenerator = require('browserslist-generator'); var crypto = require('crypto'); var TSModule = require('typescript'); var browserslist = require('browserslist'); var pluginutils = require('@rollup/pluginutils'); var stringutil = require('@wessberg/stringutil'); var tslib = require('tslib'); var compatfactory = require('compatfactory'); var tsCloneNode = require('ts-clone-node'); var MagicString = require('magic-string'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var path__default = /*#__PURE__*/_interopDefaultLegacy(path); var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk); var TSModule__namespace = /*#__PURE__*/_interopNamespace(TSModule); var MagicString__default = /*#__PURE__*/_interopDefaultLegacy(MagicString); const SOURCE_MAP_EXTENSION = ".map"; const TS_EXTENSION = ".ts"; const TSX_EXTENSION = ".tsx"; const JS_EXTENSION = ".js"; const JS_MAP_EXTENSION = `${JS_EXTENSION}${SOURCE_MAP_EXTENSION}`; const JSX_EXTENSION = ".jsx"; const JSON_EXTENSION = ".json"; const MJS_EXTENSION = ".mjs"; const MJSX_EXTENSION = ".mjsx"; const D_TS_EXTENSION = `.d${TS_EXTENSION}`; const D_TS_MAP_EXTENSION = `.d${TS_EXTENSION}${SOURCE_MAP_EXTENSION}`; const TSBUILDINFO_EXTENSION = `.tsbuildinfo`; const ROLLUP_PLUGIN_MULTI_ENTRY_LEGACY = "\0rollup-plugin-multi-entry:entry-point"; const ROLLUP_PLUGIN_VIRTUAL_PREFIX = `\0virtual:`; const KNOWN_EXTENSIONS = new Set([ D_TS_EXTENSION, D_TS_MAP_EXTENSION, JS_MAP_EXTENSION, TS_EXTENSION, TSX_EXTENSION, JS_EXTENSION, JSX_EXTENSION, JSON_EXTENSION, MJS_EXTENSION, MJSX_EXTENSION, TSBUILDINFO_EXTENSION ]); const DEFAULT_TSCONFIG_FILE_NAME = "tsconfig.json"; const NODE_MODULES = "node_modules"; const NODE_MODULES_MATCH_PATH = `/${NODE_MODULES}/`; const SOURCE_MAP_COMMENT = "//# sourceMappingURL"; const SOURCE_MAP_COMMENT_REGEXP = /\/\/# sourceMappingURL=(\S*)/; const TSLIB_NAME = `tslib${D_TS_EXTENSION}`; const BABEL_RUNTIME_PREFIX_1 = "@babel/runtime/"; const BABEL_RUNTIME_PREFIX_2 = "babel-runtime/"; const SWC_HELPERS_PREFIX = "@swc/helpers"; const REGENERATOR_RUNTIME_NAME_1 = `${BABEL_RUNTIME_PREFIX_1}regenerator/index.js`; const REGENERATOR_RUNTIME_NAME_2 = `${BABEL_RUNTIME_PREFIX_2}regenerator/index.js`; const REGENERATOR_RUNTIME_NAME_3 = `regenerator-runtime/runtime.js`; const REGENERATOR_RUNTIME_VIRTUAL_SRC = `${ROLLUP_PLUGIN_VIRTUAL_PREFIX}regenerator-runtime`; const BABEL_REQUIRE_RUNTIME_HELPER_ESM_REGEXP_1 = new RegExp(`(require\\(["'\`])(${BABEL_RUNTIME_PREFIX_1}helpers/esm/[^"'\`]*)["'\`]\\)`); const BABEL_REQUIRE_RUNTIME_HELPER_ESM_REGEXP_2 = new RegExp(`(require\\(["'\`])(${BABEL_RUNTIME_PREFIX_2}helpers/esm/[^"'\`]*)["'\`]\\)`); const BABEL_IMPORT_RUNTIME_HELPER_CJS_REGEXP_1 = new RegExp(`(import\\s+\\w+\\s+from\\s+["'\`])(${BABEL_RUNTIME_PREFIX_1}helpers/[^"'/\`]*)["'\`]`); const BABEL_IMPORT_RUNTIME_HELPER_CJS_REGEXP_2 = new RegExp(`(import\\s+\\w+\\s+from\\s+["'\`])(${BABEL_RUNTIME_PREFIX_2}helpers/[^"'/\`]*)["'\`]`); const BABEL_IMPORT_RUNTIME_HELPER_CJS_REGEXP_3 = new RegExp(`(import\\s+["'\`])(${BABEL_RUNTIME_PREFIX_1}helpers/[^"'/\`]*)["'\`]`); const BABEL_IMPORT_RUNTIME_HELPER_CJS_REGEXP_4 = new RegExp(`(import\\s+["'\`])(${BABEL_RUNTIME_PREFIX_2}helpers/[^"'/\`]*)["'\`]`); const BABEL_MINIFICATION_BLACKLIST_PRESET_NAMES = []; const BABEL_MINIFICATION_BLACKLIST_PLUGIN_NAMES = ["@babel/plugin-transform-runtime", "babel-plugin-transform-runtime"]; const BABEL_MINIFY_PRESET_NAMES = ["babel-preset-minify"]; const BABEL_MINIFY_PLUGIN_NAMES = [ "babel-plugin-transform-minify-booleans", "babel-plugin-minify-builtins", "babel-plugin-transform-inline-consecutive-adds", "babel-plugin-minify-dead-code-elimination", "babel-plugin-minify-constant-folding", "babel-plugin-minify-flip-comparisons", "babel-plugin-minify-guarded-expressions", "babel-plugin-minify-infinity", "babel-plugin-minify-mangle-names", "babel-plugin-transform-member-expression-literals", "babel-plugin-transform-merge-sibling-variables", "babel-plugin-minify-numeric-literals", "babel-plugin-transform-property-literals", "babel-plugin-transform-regexp-constructors", "babel-plugin-transform-remove-console", "babel-plugin-transform-remove-debugger", "babel-plugin-transform-remove-undefined", "babel-plugin-minify-replace", "babel-plugin-minify-simplify", "babel-plugin-transform-simplify-comparison-operators", "babel-plugin-minify-type-constructors", "babel-plugin-transform-undefined-to-void" ]; const FORCED_SWC_MODULE_OPTIONS = { type: "es6" }; const FORCED_SWC_JSC_OPTIONS = { externalHelpers: true }; const FORCED_BABEL_PRESET_ENV_OPTIONS = { modules: false }; const FORCED_BABEL_YEARLY_PRESET_OPTIONS = Object.assign({}, FORCED_BABEL_PRESET_ENV_OPTIONS); const FORCED_BABEL_PLUGIN_TRANSFORM_RUNTIME_OPTIONS = { helpers: true, regenerator: true, // eslint-disable-next-line @typescript-eslint/naming-convention useESModules: true }; /** * Ensures that the given item is in fact an array */ function ensureArray(item) { return Array.isArray(item) ? item : [item]; } function isTypeScriptLib(p) { return p.startsWith(`lib.`) && p.endsWith(D_TS_EXTENSION); } /** * Gets the extension of the given file */ function getExtension(file) { if (file.endsWith(D_TS_EXTENSION)) return D_TS_EXTENSION; else if (file.endsWith(D_TS_MAP_EXTENSION)) return D_TS_MAP_EXTENSION; return path__default["default"].extname(file); } /** * Returns true if the given path represents an external library */ function isExternalLibrary(p) { return (!p.startsWith(".") && !p.startsWith("/")) || p.includes(NODE_MODULES_MATCH_PATH); } /** * Returns true if the given id represents tslib */ function isTslib(p) { return p === "tslib" || path__default["default"].normalize(p).endsWith(`/tslib/${TSLIB_NAME}`) || path__default["default"].normalize(p).endsWith("/tslib/tslib.es6.js") || path__default["default"].normalize(p).endsWith("/tslib/tslib.js"); } /** * Returns true if the given path represents a Babel helper */ function isBabelHelper(p) { return includesBabelEsmHelper(p) || isBabelCjsHelper(p); } function isRegeneratorRuntime(p) { return p.endsWith(REGENERATOR_RUNTIME_NAME_1) || p.endsWith(REGENERATOR_RUNTIME_NAME_2) || p.endsWith(REGENERATOR_RUNTIME_NAME_3) || p === REGENERATOR_RUNTIME_VIRTUAL_SRC; } /** * Returns true if the given path represents a swc helper */ function isSwcHelper(p) { return path__default["default"].normalize(p).includes(`${SWC_HELPERS_PREFIX}`); } /** * Returns true if the given path represents a Babel ESM helper */ function includesBabelEsmHelper(p) { return path__default["default"].normalize(p).includes(`${BABEL_RUNTIME_PREFIX_1}helpers/esm`) || path__default["default"].normalize(p).includes(`${BABEL_RUNTIME_PREFIX_2}helpers/esm`); } /** * Returns true if the given path represents a Babel CJS helper */ function isBabelCjsHelper(p) { return !includesBabelEsmHelper(p) && (path__default["default"].normalize(p).includes(`${BABEL_RUNTIME_PREFIX_1}helpers`) || path__default["default"].normalize(p).includes(`${BABEL_RUNTIME_PREFIX_2}helpers`)); } /** * Returns true if the given path represents @babel/preset-env */ function isBabelPresetEnv(p) { return path__default["default"].normalize(p).includes("@babel/preset-env") || path__default["default"].normalize(p).includes("babel-preset-env"); } /** * Returns true if the given path is the name of the entry module or @rollup/plugin-multi-entry */ function isMultiEntryModule(p, multiEntryModuleName) { const normalized = path__default["default"].normalize(p); return normalized === ROLLUP_PLUGIN_MULTI_ENTRY_LEGACY || (multiEntryModuleName != null && normalized === multiEntryModuleName); } /** * Returns true if the given path represents @babel/preset-es[2015|2016|2017] */ function isYearlyBabelPreset(p) { return path__default["default"].normalize(p).includes("@babel/preset-es") || path__default["default"].normalize(p).includes("babel-preset-es"); } /** * Returns true if the given path represents @babel/plugin-transform-runtime */ function isBabelPluginTransformRuntime(p) { return path__default["default"].normalize(p).includes("@babel/plugin-transform-runtime") || path__default["default"].normalize(p).includes("babel-plugin-transform-runtime"); } function somePathsAreRelated(paths, matchPath) { for (const p of paths) { if (pathsAreRelated(p, matchPath)) return true; } return false; } function pathsAreRelated(a, b) { if (a === b) return true; // A node_modules folder may contain one or more nested node_modules if (a.includes(NODE_MODULES) || b.includes(NODE_MODULES)) { const firstPathFromNodeModules = a.includes(NODE_MODULES) ? a.slice(a.indexOf(NODE_MODULES)) : a; const secondPathFromNodeModules = b.includes(NODE_MODULES) ? b.slice(b.indexOf(NODE_MODULES)) : b; if (firstPathFromNodeModules.includes(secondPathFromNodeModules)) return true; if (secondPathFromNodeModules.includes(firstPathFromNodeModules)) return true; } return false; } /** * Strips the extension from a file */ function stripKnownExtension(file) { let currentExtname; for (const extName of KNOWN_EXTENSIONS) { if (file.endsWith(extName)) { currentExtname = extName; break; } } if (currentExtname == null) return file; return file.slice(0, file.lastIndexOf(currentExtname)); } /** * Sets the given extension for the given file */ function setExtension(file, extension) { return path__default["default"].normalize(`${stripKnownExtension(file)}${extension}`); } /** * Ensure that the given path has a leading "." */ function ensureHasLeadingDotAndPosix(p, externalGuard = true) { if (externalGuard && isExternalLibrary(p)) return p; const posixPath = path__default["default"].normalize(p); if (posixPath.startsWith(".")) return posixPath; if (posixPath.startsWith("/")) return `.${posixPath}`; return `./${posixPath}`; } /** * Ensures that the given path is relative */ function ensureRelative(root, p) { // If the path is already relative, simply return it if (!path__default["default"].isAbsolute(p)) { return path__default["default"].normalize(p); } // Otherwise, construct a relative path from the root return path__default["default"].relative(root, p); } /** * Ensures that the given path is absolute */ function ensureAbsolute(root, p) { // If the path is already absolute, simply return it if (path__default["default"].isAbsolute(p)) { return path__default["default"].normalize(p); } // Otherwise, construct an absolute path from the root return path__default["default"].join(root, p); } /** * Checks the id from the given importer with respect to the given externalOption provided to Rollup */ function isExternal(id, importer, externalOption) { var _a; if (externalOption == null) return false; if (externalOption === true) return true; if (externalOption === false) return false; if (typeof externalOption === "function") return (_a = externalOption(id, importer, true)) !== null && _a !== void 0 ? _a : false; const ids = new Set(); const matchers = []; for (const value of ensureArray(externalOption)) { if (value instanceof RegExp) { matchers.push(value); } else { ids.add(value); } } return ids.has(id) || matchers.some(matcher => matcher.test(id)); } function finalizeParsedCommandLine({ cwd, parsedCommandLineResult: { originalCompilerOptions, parsedCommandLine, tsconfigPath } }) { // Declarations may be generated, but not as part of the Builder/Incremental program which is used during the transform, renderChunk, and generateBundle phases, so a nice optimization can be to instruct TypeScript not to generate them. // The raw CompilerOptions will be preserved and used in the last compilation phase to generate declarations if needed. // However, when 'composite' is true or when incremental compilation is active, declarations must be emitted for buildInfo to work, so under such circumstances this optimization must be skipped. const canApplySkipDeclarationsOptimization = !Boolean(parsedCommandLine.options.incremental) && !Boolean(parsedCommandLine.options.composite) && parsedCommandLine.options.tsBuildInfoFile == null && (parsedCommandLine.projectReferences == null || parsedCommandLine.projectReferences.length < 1); if (canApplySkipDeclarationsOptimization) { parsedCommandLine.options.declaration = false; parsedCommandLine.options.declarationMap = false; parsedCommandLine.options.declarationDir = undefined; } // Ensure that at tsBuildInfoFile exists if 'composite' or 'incremental' is true if (parsedCommandLine.options.incremental === true || parsedCommandLine.options.composite === true) { if (parsedCommandLine.options.tsBuildInfoFile != null) { parsedCommandLine.options.tsBuildInfoFile = ensureAbsolute(cwd, parsedCommandLine.options.tsBuildInfoFile); } // Otherwise, use the _actual_ outDir/outFile from the resolved tsconfig to build the path to the .tsbuildinfo file since TypeScript should be able to actually // resolve the file from the path pointed to by the user else { let tsBuildInfoAbsolutePath; // Use outDir as the base directory if (originalCompilerOptions.outDir != null) { tsBuildInfoAbsolutePath = path__default["default"].join(ensureAbsolute(cwd, originalCompilerOptions.outDir), `${path__default["default"].parse(tsconfigPath).name}${TSBUILDINFO_EXTENSION}`); } // Otherwise, use outFile but replace the extension else if (originalCompilerOptions.outFile != null) { tsBuildInfoAbsolutePath = ensureAbsolute(cwd, setExtension(originalCompilerOptions.outFile, TSBUILDINFO_EXTENSION)); } // Otherwise, use 'cwd' as the directory for the .tsbuildinfo file else { tsBuildInfoAbsolutePath = path__default["default"].join(ensureAbsolute(cwd, `${path__default["default"].parse(tsconfigPath).name}${TSBUILDINFO_EXTENSION}`)); } parsedCommandLine.options.tsBuildInfoFile = tsBuildInfoAbsolutePath; } } return parsedCommandLine; } function shouldDebugSourceFile(debug, { fileName, text }) { if (typeof debug === "boolean") return debug; return Boolean(debug({ kind: "transformer", fileName, text })); } function shouldDebugMetrics(debug, sourceFile) { if (typeof debug === "boolean") return debug; return Boolean(debug(Object.assign({ kind: "metrics" }, (sourceFile == null ? {} : { fileName: sourceFile.fileName })))); } function shouldDebugEmit(debug, fileName, text, outputPathKind) { if (typeof debug === "boolean") return debug; return Boolean(debug({ kind: "emit", fileKind: outputPathKind, fileName, text })); } function shouldDebugTsconfig(debug) { if (typeof debug === "boolean") return debug; return Boolean(debug({ kind: "tsconfig" })); } function getFormattedDateTimePrefix() { const currentDate = new Date(); const currentDateTime = `(${currentDate.getHours().toString().padStart(2, "0")}:${currentDate.getMinutes().toString().padStart(2, "0")}:${currentDate .getSeconds() .toString() .padStart(2, "0")})`; return `${chalk__default["default"].gray(currentDateTime)} `; } function inspect(item, depth = 4) { console.log(util.inspect(item, { colors: true, depth, maxArrayLength: 1000 })); } function logTsconfig(config) { console.log(`${getFormattedDateTimePrefix()}${chalk__default["default"].red(`tsconfig`)}`); inspect(config); } /** * Returns true if the given tsconfig is a ParsedCommandLine */ function isParsedCommandLine(tsconfig) { return tsconfig != null && typeof tsconfig !== "string" && typeof tsconfig !== "function" && "options" in tsconfig && !("hook" in tsconfig); } /** * Returns true if the given tsconfig are raw, JSON-serializable CompilerOptions */ function isRawCompilerOptions(tsconfig) { return tsconfig != null && typeof tsconfig !== "string" && typeof tsconfig !== "function" && !("options" in tsconfig) && !("hook" in tsconfig); } /** * Returns true if the given tsconfig is in fact a function that receives resolved CompilerOptions that can be extended */ function isTsConfigResolver(tsconfig) { return tsconfig != null && typeof tsconfig === "function"; } /** * Returns true if the given tsconfig is in fact an object that provides a filename for a tsconfig, * as well as a 'hook' function that receives resolved CompilerOptions that can be extended */ function isTsConfigResolverWithFileName(tsconfig) { return tsconfig != null && typeof tsconfig !== "string" && typeof tsconfig !== "function" && !("options" in tsconfig) && "hook" in tsconfig; } /** * Returns true if the given tsconfig are CompilerOptions */ function isCompilerOptions(tsconfig) { return (tsconfig != null && typeof tsconfig !== "string" && typeof tsconfig !== "function" && !("options" in tsconfig) && !("hook" in tsconfig) && (("module" in tsconfig && typeof tsconfig.module === "number") || ("target" in tsconfig && typeof tsconfig.target === "number") || ("jsx" in tsconfig && typeof tsconfig.jsx === "number") || ("moduleResolution" in tsconfig && typeof tsconfig.moduleResolution === "number") || ("newLine" in tsconfig && typeof tsconfig.newLine === "number"))); } /** * Gets a ParsedCommandLine based on the given options */ function getParsedCommandLine(options) { const { cwd, tsconfig, fileSystem, forcedCompilerOptions = {}, typescript } = options; const hasProvidedTsconfig = tsconfig != null; let originalCompilerOptions; let parsedCommandLine; let tsconfigPath = ensureAbsolute(cwd, DEFAULT_TSCONFIG_FILE_NAME); // If the given tsconfig is already a ParsedCommandLine, use that one, but apply the forced CompilerOptions if (isParsedCommandLine(tsconfig)) { originalCompilerOptions = tsconfig.options; tsconfig.options = Object.assign(Object.assign({}, tsconfig.options), forcedCompilerOptions); parsedCommandLine = tsconfig; } // If the user provided CompilerOptions directly, use those to build a ParsedCommandLine else if (isCompilerOptions(tsconfig)) { originalCompilerOptions = typescript.parseJsonConfigFileContent({}, fileSystem, cwd, tsconfig).options; parsedCommandLine = typescript.parseJsonConfigFileContent({}, fileSystem, cwd, Object.assign(Object.assign({}, tsconfig), forcedCompilerOptions)); } // If the user provided JSON-serializable ("raw") CompilerOptions directly, use those to build a ParsedCommandLine else if (isRawCompilerOptions(tsconfig)) { originalCompilerOptions = typescript.parseJsonConfigFileContent({ compilerOptions: tsconfig }, fileSystem, cwd).options; parsedCommandLine = typescript.parseJsonConfigFileContent({ compilerOptions: tsconfig }, fileSystem, cwd, forcedCompilerOptions); } // Otherwise, attempt to resolve it and parse it else { tsconfigPath = ensureAbsolute(cwd, isTsConfigResolverWithFileName(tsconfig) ? tsconfig.fileName : tsconfig != null && !isTsConfigResolver(tsconfig) ? tsconfig : DEFAULT_TSCONFIG_FILE_NAME); // If the file exists, read the tsconfig on that location let tsconfigContent = fileSystem.readFile(tsconfigPath); // Otherwise, if the user hasn't provided any tsconfig at all, start from an empty one (and only use the forced options) if (tsconfigContent == null && !hasProvidedTsconfig) { tsconfigContent = ""; } // Finally, if the user has provided a file that doesn't exist, throw else if (tsconfigContent == null) { throw new ReferenceError(`The given tsconfig: '${tsconfigPath}' doesn't exist!`); } const tsconfigJson = typescript.parseConfigFileTextToJson(tsconfigPath, tsconfigContent).config; const basePath = path__default["default"].native.dirname(tsconfigPath); originalCompilerOptions = typescript.parseJsonConfigFileContent(tsconfigJson, fileSystem, basePath, {}, tsconfigPath).options; parsedCommandLine = typescript.parseJsonConfigFileContent(tsconfigJson, fileSystem, basePath, forcedCompilerOptions, tsconfigPath); // If an extension hook has been provided. Make sure to still apply the forced CompilerOptions if (isTsConfigResolver(tsconfig)) { originalCompilerOptions = Object.assign({}, tsconfig(originalCompilerOptions)); parsedCommandLine.options = Object.assign(Object.assign({}, tsconfig(parsedCommandLine.options)), forcedCompilerOptions); } else if (isTsConfigResolverWithFileName(tsconfig)) { // If an extension hook has been provided through the 'hook' property. Make sure to still apply the forced CompilerOptions originalCompilerOptions = Object.assign({}, tsconfig.hook(originalCompilerOptions)); parsedCommandLine.options = Object.assign(Object.assign({}, tsconfig.hook(parsedCommandLine.options)), forcedCompilerOptions); } } // Ensure that the parsed command line, as well as the original CompilerOptions has a base URL if (parsedCommandLine.options.baseUrl == null) { parsedCommandLine.options.baseUrl = "."; } if (originalCompilerOptions.baseUrl == null) { originalCompilerOptions.baseUrl = "."; } // Remove all non-declaration files from the default file names since these will be handled separately by Rollup. // Also filter out all files that is matched by the include/exclude globs provided as plugin options parsedCommandLine.fileNames = parsedCommandLine.fileNames.filter(file => file.endsWith(D_TS_EXTENSION) && options.filter(file)); const parsedCommandLineResult = { parsedCommandLine, originalCompilerOptions, tsconfigPath }; // On some TypeScript versions such as 3.0.0, the 'composite' feature // require that a specific configFilePath exists on the CompilerOptions, // so make sure a path is always set. if (parsedCommandLine.options.configFilePath == null) { parsedCommandLine.options.configFilePath = tsconfigPath; } // Finalize the parsed command line finalizeParsedCommandLine(Object.assign(Object.assign({}, options), { parsedCommandLineResult })); if (shouldDebugTsconfig(options.pluginOptions.debug)) { logTsconfig(parsedCommandLine); } return parsedCommandLineResult; } /** * Gets the ScriptTarget to use from the given Browserslist */ function getScriptTargetFromBrowserslist(browserslist, typescript) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w; switch (browserslistGenerator.getAppropriateEcmaVersionForBrowserslist(browserslist)) { case "es3": return typescript.ScriptTarget.ES3; case "es5": return typescript.ScriptTarget.ES5; case "es2015": return typescript.ScriptTarget.ES2015; // Support older TypeScript versions that may not supported ES2016 as a ScriptTarget with nullish coalescing case "es2016": return (_a = typescript.ScriptTarget.ES2016) !== null && _a !== void 0 ? _a : typescript.ScriptTarget.ES2015; // Support older TypeScript versions that may not supported ES2017 as a ScriptTarget with nullish coalescing case "es2017": return (_c = (_b = typescript.ScriptTarget.ES2017) !== null && _b !== void 0 ? _b : typescript.ScriptTarget.ES2016) !== null && _c !== void 0 ? _c : typescript.ScriptTarget.ES2015; // Support older TypeScript versions that may not supported ES2018 as a ScriptTarget with nullish coalescing case "es2018": return (_f = (_e = (_d = typescript.ScriptTarget.ES2018) !== null && _d !== void 0 ? _d : typescript.ScriptTarget.ES2017) !== null && _e !== void 0 ? _e : typescript.ScriptTarget.ES2016) !== null && _f !== void 0 ? _f : typescript.ScriptTarget.ES2015; // Support older TypeScript versions that may not supported ES2019 as a ScriptTarget with nullish coalescing case "es2019": return (_k = (_j = (_h = (_g = typescript.ScriptTarget.ES2019) !== null && _g !== void 0 ? _g : typescript.ScriptTarget.ES2018) !== null && _h !== void 0 ? _h : typescript.ScriptTarget.ES2017) !== null && _j !== void 0 ? _j : typescript.ScriptTarget.ES2016) !== null && _k !== void 0 ? _k : typescript.ScriptTarget.ES2015; // Support older TypeScript versions that may not supported ES2020 as a ScriptTarget with nullish coalescing case "es2020": return ((_q = (_p = (_o = (_m = (_l = typescript.ScriptTarget.ES2020) !== null && _l !== void 0 ? _l : typescript.ScriptTarget.ES2019) !== null && _m !== void 0 ? _m : typescript.ScriptTarget.ES2018) !== null && _o !== void 0 ? _o : typescript.ScriptTarget.ES2017) !== null && _p !== void 0 ? _p : typescript.ScriptTarget.ES2016) !== null && _q !== void 0 ? _q : typescript.ScriptTarget.ES2015); // Support older TypeScript versions that may not supported ES2021 as a ScriptTarget with nullish coalescing case "es2021": case "es2022": return ((_w = (_v = (_u = (_t = (_s = (_r = typescript.ScriptTarget.ES2021) !== null && _r !== void 0 ? _r : typescript.ScriptTarget.ES2020) !== null && _s !== void 0 ? _s : typescript.ScriptTarget.ES2019) !== null && _t !== void 0 ? _t : typescript.ScriptTarget.ES2018) !== null && _u !== void 0 ? _u : typescript.ScriptTarget.ES2017) !== null && _v !== void 0 ? _v : typescript.ScriptTarget.ES2016) !== null && _w !== void 0 ? _w : typescript.ScriptTarget.ES2015); } } /** * Gets the EcmaVersion that represents the given ScriptTarget */ function getEcmaVersionForScriptTarget(scriptTarget, typescript) { switch (scriptTarget) { case typescript.ScriptTarget.ES3: return "es3"; case typescript.ScriptTarget.ES5: return "es5"; case typescript.ScriptTarget.ES2015: return "es2015"; case typescript.ScriptTarget.ES2016: return "es2016"; case typescript.ScriptTarget.ES2017: return "es2017"; case typescript.ScriptTarget.ES2018: return "es2018"; case typescript.ScriptTarget.ES2019: return "es2019"; case typescript.ScriptTarget.ES2020: return "es2020"; case typescript.ScriptTarget.ES2021: return "es2021"; case typescript.ScriptTarget.ESNext: case typescript.ScriptTarget.Latest: case typescript.ScriptTarget.JSON: return "es2021"; } } /** * Generates a random hash */ function generateRandomHash({ length = 8, key } = {}) { return key == null ? crypto.randomBytes(length / 2).toString("hex") : crypto.createHmac("sha1", key).digest("hex").slice(0, length); } function generateRandomIntegerHash(options, offset = 1000000) { const str = generateRandomHash(options); let result = 0; for (let i = 0; i < str.length; i++) { result = result + str.charCodeAt(i); } return result + offset; } /** * Gets the destination directory to use based on the given Rollup output options */ function getOutDir(cwd, options) { let outDir; if (options == null) { // Generate a random output directory. The idea is that this will never match any existing files on disk. // The reason being that Typescript may erroneously think that input files may be overwritten if 'allowJs' is true // and 'outDir' is '.' outDir = path__default["default"].join(cwd, generateRandomHash()); } else if (options.dir != null) { outDir = options.dir; } else if (options.file != null) { outDir = path__default["default"].dirname(options.file); } else { outDir = cwd; } // Return the relative output directory. Default to "." if it should be equal to cwd const relativeToCwd = ensureRelative(cwd, outDir); return relativeToCwd === "" ? "." : relativeToCwd; } /** * Gets the ModuleKind to force */ function getForcedModuleKindOption({ pluginOptions }) { // Under these circumstances, TypeScript is a client of Rollup, and Rollup only understands ESM. // Rollup, not TypeScript, is the decider of which module system(s) to target based on the Rollup configuration. // Because of this, TypeScript will always be instructed to emit ESM. return { module: pluginOptions.typescript.ModuleKind.ESNext }; } /** * Gets the ScriptTarget to force */ function getForcedScriptTargetOption({ pluginOptions, browserslist }) { // If anything else than TypeScript should perform the transpilation, always target the latest ECMAScript version and let the transpiler take care of the rest if (pluginOptions.transpiler !== "typescript") { return { target: pluginOptions.typescript.ScriptTarget.ESNext }; } // If a Browserslist is provided, and if Typescript should perform the transpilation, decide the appropriate ECMAScript version based on the Browserslist. else if (browserslist != null && browserslist !== false) { return { target: getScriptTargetFromBrowserslist(browserslist, pluginOptions.typescript) }; } // Otherwise, don't force the 'target' option return {}; } /** * Retrieves the CompilerOptions that will be forced */ function getForcedCompilerOptions(options) { return Object.assign(Object.assign(Object.assign({}, getForcedModuleKindOption(options)), getForcedScriptTargetOption(options)), { outDir: getOutDir(options.pluginOptions.cwd), // Rollup, not Typescript, is the decider of where to put files outFile: undefined, // Always generate SourceMaps. Rollup will then decide if it wants to use them or not sourceMap: true, // Never use inline source maps. Let Rollup inline the returned SourceMap if it can and if sourcemaps should be emitted in the OutputOptions, inlineSourceMap: false, // Since we never use inline source maps, inline sources aren't supported inlineSources: false, // Helpers should *always* be imported. We don't want them to be duplicated multiple times within generated chunks importHelpers: true, // Node resolution is required when 'importHelpers' are true moduleResolution: options.pluginOptions.typescript.ModuleResolutionKind.NodeJs, // Typescript should always be able to emit - otherwise we cannot transform source files noEmit: false, // Typescript should always be able to emit - otherwise we cannot transform source files noEmitOnError: false, // Typescript should always be able to emit other things than declarations - otherwise we cannot transform source files emitDeclarationOnly: false, // Typescript should always be able to emit helpers - since we force 'importHelpers' noEmitHelpers: false, // Typescript should always be able to resolve things - otherwise compilation will break noResolve: false, // Typescript should never watch files. That is the job of Rollup watch: false, // Typescript should never watch files. That is the job of Rollup preserveWatchOutput: false, skipLibCheck: true }); } /** * Returns true if the given OutputFile represents code */ function isCodeOutputFile({ name }) { const extension = getExtension(name); return [SOURCE_MAP_EXTENSION, D_TS_EXTENSION, D_TS_MAP_EXTENSION].every(otherExtension => extension !== otherExtension); } /** * Returns true if the given OutputFile represents a SourceMap */ function isMapOutputFile({ name }) { const extension = getExtension(name); return [SOURCE_MAP_EXTENSION, D_TS_MAP_EXTENSION].some(otherExtension => extension === otherExtension); } /** * Gets a SourceDescription from the given EmitOutput */ function getSourceDescriptionFromEmitOutput(output) { const code = output.outputFiles.find(isCodeOutputFile); if (code == null) return undefined; const map = output.outputFiles.find(isMapOutputFile); // Remove the SourceMap comment from the code if it is given. Rollup is the decider of whether or not to emit SourceMaps and if they should be inlined const inlinedSourcemapIndex = code.text.indexOf(`\n${SOURCE_MAP_COMMENT}`); if (inlinedSourcemapIndex >= 0) { code.text = code.text.slice(0, inlinedSourcemapIndex); } return Object.assign({ code: code.text }, (map == null ? {} : { map: map.text })); } /** * Gets diagnostics for the given fileName */ function emitDiagnostics({ host, context, pluginOptions }) { const typescript = host.getTypescript(); let diagnostics = host.getDiagnostics(); // If there is a hook for diagnostics, call it assign the result of calling it to the local variable 'diagnostics' if (pluginOptions.hook.diagnostics != null) { diagnostics = pluginOptions.hook.diagnostics(diagnostics); } // Don't proceed if the hook returned null or undefined if (diagnostics == null) return; diagnostics.forEach((diagnostic) => { const message = typescript.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); const position = diagnostic.start == null || diagnostic.file == null ? undefined : diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); // Color-format the diagnostics const colorFormatted = typescript.formatDiagnosticsWithColorAndContext([diagnostic], host); // Provide a normalized error code const code = `${diagnostic.scope == null ? "TS" : diagnostic.scope}${diagnostic.code}`; // Provide an empty Stack. There's nothing useful in seeing the internals of this Plugin in the reported error const stack = ""; // Isolate the frame const newLine = host.getNewLine(); let frame = colorFormatted.slice(colorFormatted.indexOf(message) + message.length); // Remove the trailing newline from the frame if it has one if (frame.startsWith(newLine)) { frame = frame.slice(frame.indexOf(newLine) + newLine.length); } switch (diagnostic.category) { case typescript.DiagnosticCategory.Error: context.error(Object.assign(Object.assign(Object.assign(Object.assign({ frame, code, name: code, stack }, (diagnostic.length == null ? {} : { length: diagnostic.length })), (diagnostic.file == null && position == null ? {} : { loc: Object.assign(Object.assign(Object.assign({}, (diagnostic.file == null ? {} : { file: diagnostic.file.fileName })), (position == null ? {} : { line: position.line + 1 })), (position == null ? {} : { column: position.character + 1 })) })), (diagnostic.file == null ? {} : { pos: diagnostic.file.pos })), { message }), position == null ? undefined : { line: position.line + 1, column: position.character + 1 }); break; case typescript.DiagnosticCategory.Warning: case typescript.DiagnosticCategory.Message: case typescript.DiagnosticCategory.Suggestion: context.warn(Object.assign(Object.assign(Object.assign(Object.assign({ frame, code, name: code }, (diagnostic.length == null ? {} : { length: diagnostic.length })), { loc: Object.assign(Object.assign(Object.assign({}, (diagnostic.file == null ? {} : { file: diagnostic.file.fileName })), (position == null ? {} : { line: position.line + 1 })), (position == null ? {} : { column: position.character + 1 })) }), (diagnostic.file == null ? {} : { pos: diagnostic.file.pos })), { message }), position == null ? undefined : { line: position.line + 1, column: position.character + 1 }); break; } }); } /** * Gets the extensions that are supported by Typescript, depending on whether or not to allow JS and JSON */ function getSupportedExtensions(allowJs, allowJson) { return new Set([TS_EXTENSION, TSX_EXTENSION, D_TS_EXTENSION, ...(allowJs ? [JS_EXTENSION, JSX_EXTENSION] : []), ...(allowJson ? [JSON_EXTENSION] : [])]); } /** * Returns true if the given asset is an OutputChunk */ function isOutputChunk(thing) { return !("isAsset" in thing); } /** * Takes all filenames that has been included in the given bundle */ function takeBundledFilesNames(bundle) { const bundledFilenames = new Set(); Object.values(bundle).forEach(value => { if (isOutputChunk(value)) { Object.keys(value.modules).forEach(fileName => bundledFilenames.add(path__default["default"].normalize(fileName))); } else { bundledFilenames.add(path__default["default"].normalize(value.fileName)); } }); return bundledFilenames; } /** * Gets normalized PluginOptions based on the given ones */ function getPluginOptions(options) { // Destructure the options and provide defaults const { browserslist, transpiler = "typescript", typescript = TSModule__namespace, cwd = path__default["default"].normalize(process.cwd()), tsconfig, transformers, include = [], exclude = [], transpileOnly = false, debug = false, fileSystem = typescript.sys, hook = {} } = options; // These options will be used no matter what const baseOptions = { typescript, browserslist, cwd: ensureAbsolute(process.cwd(), cwd), exclude, include, transformers, tsconfig, transpileOnly, debug, fileSystem, hook }; switch (transpiler) { case "babel": { return Object.assign(Object.assign(Object.assign({}, baseOptions), ("babelConfig" in options ? { babelConfig: options.babelConfig } : {})), { transpiler: "babel" }); } case "swc": { return Object.assign(Object.assign(Object.assign({}, baseOptions), ("swcConfig" in options ? { swcConfig: options.swcConfig } : {})), { transpiler: "swc" }); } // TypeScript default: { return Object.assign(Object.assign({}, baseOptions), { transpiler: "typescript" }); } } } /** * Returns true if the given browserslist is raw input for a Browserslist */ function isBrowserslistInput(browserslist) { return typeof browserslist === "string" || Array.isArray(browserslist); } /** * Returns true if the given browserslist is an IBrowserslistQueryConfig */ function isBrowserslistQueryConfig(browserslist) { return browserslist != null && !isBrowserslistInput(browserslist) && browserslist !== false && "query" in browserslist && browserslist.query != null; } /** * Returns true if the given browserslist is an IBrowserslistPathConfig */ function isBrowserslistPathConfig(browserslist) { return browserslist != null && !isBrowserslistInput(browserslist) && browserslist !== false && "path" in browserslist && browserslist.path != null; } /** * Gets a Browserslist based on the given options */ function getBrowserslist({ browserslist: browserslist$1, cwd, fileSystem }) { // If a Browserslist is provided directly from the options, use that if (browserslist$1 != null) { // If the Browserslist is equal to false, it should never be used. Return undefined if (browserslist$1 === false) { return false; } // If the Browserslist is some raw input queries, use them directly else if (isBrowserslistInput(browserslist$1)) { return browserslistGenerator.normalizeBrowserslist(ensureArray(browserslist$1)); } // If the Browserslist is a config with raw query options, use them directly else if (isBrowserslistQueryConfig(browserslist$1)) { return browserslistGenerator.normalizeBrowserslist(ensureArray(browserslist$1.query)); } // If the Browserslist is a config with a path, attempt to resolve the Browserslist from that property else if (isBrowserslistPathConfig(browserslist$1)) { const browserslistPath = ensureAbsolute(cwd, browserslist$1.path); const errorMessage = `The given path for a Browserslist: '${browserslistPath}' could not be resolved from '${cwd}'`; if (!fileSystem.fileExists(path__default["default"].native.normalize(browserslistPath))) { throw new ReferenceError(errorMessage); } else { // Read the config const match = browserslist.readConfig(browserslistPath); if (match == null) { throw new ReferenceError(errorMessage); } else { return match.defaults; } } } // The config object could not be validated. Return undefined else { return undefined; } } // Otherwise, try to locate a Browserslist else { const config = browserslist.findConfig(cwd); return config == null ? undefined : config.defaults; } } /** * A Cache over resolved modules */ class ResolveCache { constructor(options) { this.options = options; /** * A memory-persistent cache of resolved modules for files over time */ this.RESOLVE_CACHE = new Map(); } /** * Gets the resolved path for an id from a parent */ getFromCache(id, parent) { const parentMap = this.RESOLVE_CACHE.get(parent); if (parentMap == null) return undefined; return parentMap.get(id); } /** * Deletes the entry matching the given parent */ delete(parent) { return this.RESOLVE_CACHE.delete(parent); } clear() { this.RESOLVE_CACHE.clear(); } /** * Sets the given resolved module in the resolve cache */ setInCache(result, id, parent) { let parentMap = this.RESOLVE_CACHE.get(parent); if (parentMap == null) { parentMap = new Map(); this.RESOLVE_CACHE.set(parent, parentMap); } parentMap.set(id, result); return result; } /** * Resolves a module name, including internal helpers such as tslib, even if they aren't included in the language service */ resolveModuleName(typescript, moduleName, containingFile, compilerOptions, host, cache, redirectedReference) { // Default to using Typescript's resolver directly return typescript.resolveModuleName(moduleName, containingFile, compilerOptions, host, cache, redirectedReference); } /** * Gets a cached module result for the given file from the given parent and returns it if it exists already. * If not, it will compute it, update the cache, and then return it */ get(options) { const { id, parent, moduleResolutionHost } = options; let cacheResult = this.getFromCache(id, parent); const typescript = moduleResolutionHost.getTypescript(); const compilerOptions = moduleResolutionHost.getCompilationSettings(); const cwd = moduleResolutionHost.getCwd(); const nonAmbientSupportedExtensions = moduleResolutionHost.getSupportedNonAmbientExtensions(); if (cacheResult != null) { return cacheResult; } // Resolve the file via Typescript, either through classic or node module resolution const { resolvedModule } = this.resolveModuleName(typescript, id, parent, compilerOptions, moduleResolutionHost); // If it could not be resolved, the cache result will be equal to null if (resolvedModule == null) { cacheResult = null; } // Otherwise, proceed else { // Make sure that the path is absolute from the cwd resolvedModule.resolvedFileName = path__default["default"].includeDriveLetter(path__default["default"].normalize(ensureAbsolute(cwd, resolvedModule.resolvedFileName))); if (resolvedModule.resolvedFileName.endsWith(D_TS_EXTENSION)) { resolvedModule.resolvedAmbientFileName = resolvedModule.resolvedFileName; resolvedModule.resolvedFileName = undefined; resolvedModule.extension = D_TS_EXTENSION; if (isTslib(id)) { // Sometimes the drive letter is omitted by TypeScript on Windows here, which can lead to problems const candidate = path__default["default"].includeDriveLetter(path__default["default"].normalize(setExtension(resolvedModule.resolvedAmbientFileName, `.es6${JS_EXTENSION}`))); if (this.options.fileSystem.fileExists(path__default["default"].native.normalize(candidate))) { resolvedModule.resolvedFileName = candidate; } } // Don't go and attempt to resolve sources for external libraries else if (resolvedModule.isExternalLibraryImport == null || !resolvedModule.isExternalLibraryImport) { // Try to determine the resolved file name. for (const extension of nonAmbientSupportedExtensions) { const candidate = path__default["default"].normalize(setExtension(resolvedModule.resolvedAmbientFileName, extension)); if (this.options.fileSystem.fileExists(path__default["default"].native.normalize(candidate))) { resolvedModule.resolvedFileName = candidate; break; } } } } else { resolvedModule.resolvedAmbientFileName = undefined; const candidate = path__default["default"].normalize(setExtension(resolvedModule.resolvedFileName, D_TS_EXTENSION)); if (this.options.fileSystem.fileExists(path__default["default"].native.normalize(candidate))) { resolvedModule.resolvedAmbientFileName = candidate; } } cacheResult = resolvedModule; } // Store the new result in the cache return this.setInCache(cacheResult, id, parent); } } const REGENERATOR_SOURCE = `\ /** * Copyright (c) 2014-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ "use strict"; var Op = Object.prototype; var hasOwn = Op.hasOwnProperty; var undefined; // More compressible than void 0. var $Symbol = typeof Symbol === "function" ? Symbol : {}; var iteratorSymbol = $Symbol.iterator || "@@iterator"; var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; function wrap(innerFn, outerFn, self, tryLocsList) { // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator. var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; var generator = Object.create(protoGenerator.prototype); var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next, // .throw, and .return methods. generator._invoke = makeInvokeMethod(innerFn, self, context); return generator; } // Try/catch helper to minimize deoptimizations. Returns a completion // record like context.tryEntries[i].completion. This interface could // have been (and was previously) designed to take a closure to be // invoked without arguments, but in all the cases we care about we // already have an existing method we want to call, so there's no need // to create a new function object. We can even get away with assuming // the method takes exactly one argument, since that happens to be true // in every case, so we don't have to touch the arguments object. The // only additional allocation required is the completion record, which // has a stable shape and so hopefully should be cheap to allocate. function tryCatch(fn, obj, arg) { try { return { type: "normal", arg: fn.call(obj, arg) }; } catch (err) { return { type: "throw", arg: err }; } } var GenStateSuspendedStart = "suspendedStart"; var GenStateSuspendedYield = "suspendedYield"; var GenStateExecuting = "executing"; var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as // breaking out of the dispatch switch statement. var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and // .constructor