UNPKG

@modern-js/module-tools

Version:

Simple, powerful, high-performance modern npm package development solution.

245 lines (244 loc) • 9.8 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); var dts_exports = {}; __export(dts_exports, { detectTSVersion: () => detectTSVersion, getProjectTsconfig: () => getProjectTsconfig, getTscBinPath: () => getTscBinPath, printOrThrowDtsErrors: () => printOrThrowDtsErrors, processDtsFilesAfterTsc: () => processDtsFilesAfterTsc, tsTargetAtOrAboveES2022: () => tsTargetAtOrAboveES2022 }); module.exports = __toCommonJS(dts_exports); var import_path = require("path"); var import_napi = require("@ast-grep/napi"); var import_utils = require("@modern-js/utils"); var import_lodash = require("@modern-js/utils/lodash"); var import_tsconfig_paths = require("@modern-js/utils/tsconfig-paths"); var import_magic_string = __toESM(require("magic-string")); var import_builder = require("./builder"); const getProjectTsconfig = async (tsconfigPath, resolutionContext = {}) => { if (!import_utils.fs.existsSync(tsconfigPath)) { return {}; } const absolutePath = (0, import_path.resolve)(tsconfigPath); if (resolutionContext[absolutePath]) { return {}; } resolutionContext[absolutePath] = true; const tsConfig = await import_utils.json5.parse(import_utils.fs.readFileSync(tsconfigPath, "utf-8")); if (!tsConfig.extends) { return tsConfig; } const extendsResolutionTarget = Array.isArray(tsConfig.extends) ? tsConfig.extends : [ tsConfig.extends ]; const resolveParentTsConfigPromises = extendsResolutionTarget.map(async (target) => { let parentTsconfigPath; try { parentTsconfigPath = require.resolve(target); if (!parentTsconfigPath.endsWith(".json")) { parentTsconfigPath = require.resolve(`${target}/tsconfig.json`); } } catch { parentTsconfigPath = (0, import_path.resolve)((0, import_path.dirname)(tsconfigPath), target); } return await getProjectTsconfig(parentTsconfigPath, resolutionContext); }); const parentTsConfigs = await Promise.all(resolveParentTsConfigPromises); return (0, import_lodash.mergeWith)({}, ...parentTsConfigs, tsConfig); }; async function detectTSVersion(appDirectory) { const cwd = appDirectory !== null && appDirectory !== void 0 ? appDirectory : process.cwd(); const typescriptPath = (0, import_path.join)(cwd, "node_modules", "typescript"); if (await import_utils.fs.pathExists(typescriptPath)) { const typescriptPkg = await import_utils.fs.readJson((0, import_path.join)(typescriptPath, "package.json")); const version = Number(typescriptPkg.version.split(".")[0]); return version; } } const getTscBinPath = async (appDirectory) => { const { default: findUp, exists: pathExists } = await Promise.resolve().then(() => __toESM(require("../../compiled/find-up"))); const tscBinFile = await findUp(async (directory) => { const targetFilePath = (0, import_path.join)(directory, "./node_modules/.bin/tsc"); const hasTscBinFile = await pathExists(targetFilePath); if (hasTscBinFile) { return targetFilePath; } return void 0; }, { cwd: appDirectory }); if (!tscBinFile || !import_utils.fs.existsSync(tscBinFile)) { throw new Error("Failed to excute the `tsc` command, please check if `typescript` is installed correctly in the current directory."); } return tscBinFile; }; const processDtsFilesAfterTsc = async (config) => { const { distPath, tsconfigPath, userTsconfig, dtsExtension, banner, footer } = config; const dtsFilesPath = await (0, import_utils.globby)("**/*.d.ts", { absolute: true, cwd: distPath }); const result = (0, import_tsconfig_paths.loadConfig)(tsconfigPath); if (result.resultType === "failed") { import_utils.logger.error(result.message); return; } const { absoluteBaseUrl, paths, mainFields, addMatchAll } = result; const matchPath = (0, import_tsconfig_paths.createMatchPath)(absoluteBaseUrl, paths, mainFields, addMatchAll); await Promise.all(dtsFilesPath.map((filePath) => { var _userTsconfig_compilerOptions; const code = import_utils.fs.readFileSync(filePath, "utf8"); const str = new import_magic_string.default(code); const originalFilePath = (0, import_path.resolve)(absoluteBaseUrl, (userTsconfig === null || userTsconfig === void 0 ? void 0 : (_userTsconfig_compilerOptions = userTsconfig.compilerOptions) === null || _userTsconfig_compilerOptions === void 0 ? void 0 : _userTsconfig_compilerOptions.rootDir) || "src", (0, import_path.relative)(distPath, filePath)); try { const sgNode = (0, import_napi.parse)(import_napi.Lang.JavaScript, code).root(); const matcher = { rule: { kind: "string_fragment", any: [ { inside: { stopBy: "end", kind: "import_statement", field: "source" } }, { inside: { stopBy: "end", kind: "export_statement", field: "source" } }, { inside: { kind: "string", inside: { kind: "arguments", inside: { kind: "call_expression", has: { field: "function", regex: "^(import|require)$" } } } } } ] } }; const matchModule = sgNode.findAll(matcher).map((matchNode) => { return { name: matchNode.text(), start: matchNode.range().start.index, end: matchNode.range().end.index }; }); matchModule.forEach((module2) => { if (!module2.name) { return; } const { start, end, name } = module2; const absoluteImportPath = matchPath(name, void 0, void 0, [ ".jsx", ".tsx", ".js", ".ts" ]); if (absoluteImportPath) { const relativePath = (0, import_path.relative)((0, import_path.dirname)(originalFilePath), absoluteImportPath); const relativeImportPath = (0, import_builder.normalizeSlashes)(relativePath.startsWith("..") ? relativePath : `./${relativePath}`); str.overwrite(start, end, relativeImportPath); } }); } catch (e) { import_utils.logger.error("[parse error]", e); } banner && str.prepend(`${banner} `); footer && str.append(` ${footer} `); const content = str.toString(); const finalPath = ( // We confirm that users will not mix ts and c(m)ts files in their projects. // If a mix is required, please configure separate buildConfig to handle different inputs. // So we don't replace .d.(c|m)ts that generated by tsc directly, this can confirm that // users can use c(m)ts directly rather than enable autoExtension, in this condition, // users need to set esbuild out-extensions like { '.js': '.mjs' } filePath.replace(/\.d\.ts/, dtsExtension) ); const writeTask = () => { return import_utils.fs.writeFile( // only replace .d.ts, if tsc generate .d.m(c)ts, keep. finalPath, content ); }; const removeTask = () => { return import_utils.fs.remove(filePath); }; return dtsExtension === ".d.ts" ? [ writeTask() ] : [ writeTask(), removeTask() ]; }).flat()); }; const printOrThrowDtsErrors = async (error, options) => { const { InternalDTSError } = await Promise.resolve().then(() => __toESM(require("../error"))); const local = await Promise.resolve().then(() => __toESM(require("../locale"))); const { abortOnError, buildType } = options !== null && options !== void 0 ? options : {}; if (error instanceof Error) { if (abortOnError) { throw new InternalDTSError(error, { buildType }); } else { import_utils.logger.warn(import_utils.chalk.bgYellowBright(local.i18n.t(local.localeKeys.warns.dts.abortOnError))); import_utils.logger.error(new InternalDTSError(error, { buildType })); } } }; const tsTargetAtOrAboveES2022 = (target) => target === "es2022" || target === "esnext"; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { detectTSVersion, getProjectTsconfig, getTscBinPath, printOrThrowDtsErrors, processDtsFilesAfterTsc, tsTargetAtOrAboveES2022 });