import __cjs_url__ from 'url'; import __cjs_path__ from 'path'; import __cjs_mod__ from 'module'; const __filename = __cjs_url__.fileURLToPath(import.meta.url); const __dirname = __cjs_path__.dirname(__filename); const require = __cjs_mod__.createRequire(import.meta.url); import { relative, posix, resolve as resolve$1, isAbsolute, dirname, normalize, sep, basename } from 'node:path'; import { existsSync, readdirSync, lstatSync, rmdirSync } from 'node:fs'; import { readFile, mkdir, writeFile, unlink } from 'node:fs/promises'; import { cpus } from 'node:os'; import { createParsedCommandLine } from '@vue/language-core'; import ts from 'typescript'; import { createFilter } from '@rollup/pluginutils'; import { createProgram } from 'vue-tsc'; import debug from 'debug'; import { cyan, yellow, green } from 'kolorist'; import { ExtractorConfig, Extractor } from '@microsoft/api-extractor'; const windowsSlashRE = /\\+/g; function slash(p) { return p.replace(windowsSlashRE, "/"); } function normalizePath(id) { return posix.normalize(slash(id)); } function resolve(...paths) { return normalizePath(resolve$1(...paths)); } function isNativeObj(value) { return Object.prototype.toString.call(value) === "[object Object]"; } function isRegExp(value) { return Object.prototype.toString.call(value) === "[object RegExp]"; } function isPromise(value) { return !!value && (typeof value === "function" || typeof value === "object") && typeof value.then === "function"; } async function wrapPromise(maybePromise) { return isPromise(maybePromise) ? await maybePromise : maybePromise; } function ensureAbsolute(path, root) { return normalizePath(path ? isAbsolute(path) ? path : resolve(root, path) : root); } function ensureArray(value) { return Array.isArray(value) ? value : value ? [value] : []; } async function runParallel(maxConcurrency, source, iteratorFn) { const ret = []; const executing = []; for (const item of source) { const p = Promise.resolve().then(() => iteratorFn(item, source)); ret.push(p); if (maxConcurrency <= source.length) { const e = p.then(() => executing.splice(executing.indexOf(e), 1)); executing.push(e); if (executing.length >= maxConcurrency) { await Promise.race(executing); } } } return Promise.all(ret); } const speRE = /[\\/]/; function queryPublicPath(paths) { if (paths.length === 0) { return ""; } else if (paths.length === 1) { return dirname(paths[0]); } let publicPath = normalize(dirname(paths[0])) + sep; let publicUnits = publicPath.split(speRE); let index = publicUnits.length - 1; for (const path of paths.slice(1)) { if (!index) { return publicPath; } const dirPath = normalize(dirname(path)) + sep; if (dirPath.startsWith(publicPath)) { continue; } const units = dirPath.split(speRE); if (units.length < index) { publicPath = dirPath; publicUnits = units; continue; } for (let i = 0; i <= index; ++i) { if (publicUnits[i] !== units[i]) { if (!i) { return ""; } index = i - 1; publicUnits = publicUnits.slice(0, index + 1); publicPath = publicUnits.join(sep) + sep; break; } } } return publicPath.slice(0, -1); } function removeDirIfEmpty(dir) { if (!existsSync(dir)) { return; } let onlyHasDir = true; for (const file of readdirSync(dir)) { const abs = resolve(dir, file); if (lstatSync(abs).isDirectory()) { if (!removeDirIfEmpty(abs)) { onlyHasDir = false; } } else { onlyHasDir = false; } } if (onlyHasDir) { rmdirSync(dir); } return onlyHasDir; } function getTsConfig(tsConfigPath, readFileSync) { const tsConfig = { compilerOptions: {}, ...ts.readConfigFile(tsConfigPath, readFileSync).config ?? {} }; if (tsConfig.extends) { ensureArray(tsConfig.extends).forEach((configPath) => { const config = getTsConfig(ensureAbsolute(configPath, dirname(tsConfigPath)), readFileSync); Object.assign(tsConfig.compilerOptions, config.compilerOptions); if (!tsConfig.include) { tsConfig.include = config.include; } if (!tsConfig.exclude) { tsConfig.exclude = config.exclude; } }); } return tsConfig; } const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""); function base64Encode(number) { if (number >= 0 && number < BASE64_ALPHABET.length) { return BASE64_ALPHABET[number]; } throw new TypeError("Base64 integer must be between 0 and 63: " + number); } const VLQ_BASE_SHIFT = 5; const VLQ_BASE = 1 << VLQ_BASE_SHIFT; const VLQ_BASE_MASK = VLQ_BASE - 1; const VLQ_CONTINUATION_BIT = VLQ_BASE; function toVLQSigned(number) { return number < 0 ? (-number << 1) + 1 : (number << 1) + 0; } function base64VLQEncode(numbers) { let encoded = ""; for (const number of numbers) { let vlq = toVLQSigned(number); let digit; do { digit = vlq & VLQ_BASE_MASK; vlq >>>= VLQ_BASE_SHIFT; if (vlq > 0) { digit |= VLQ_CONTINUATION_BIT; } encoded += base64Encode(digit); } while (vlq > 0); } return encoded; } const pkgPathCache = /* @__PURE__ */ new Map(); function tryGetPkgPath(beginPath) { beginPath = normalizePath(beginPath); if (pkgPathCache.has(beginPath)) { return pkgPathCache.get(beginPath); } const pkgPath = resolve(beginPath, "package.json"); if (existsSync(pkgPath)) { pkgPathCache.set(beginPath, pkgPath); return pkgPath; } const parentDir = normalizePath(dirname(beginPath)); if (!parentDir || parentDir === beginPath) { pkgPathCache.set(beginPath, void 0); return; } return tryGetPkgPath(parentDir); } function toCapitalCase(value) { value = value.trim().replace(/\s+/g, "-"); value = value.replace(/-+(\w)/g, (_, char) => char ? char.toUpperCase() : ""); return (value.charAt(0).toLocaleUpperCase() + value.slice(1)).replace( /[^\w]/g, "" ); } function findTypesPath(...pkgs) { let path; for (const pkg of pkgs) { if (typeof pkg !== "object") continue; path = pkg.types || pkg.typings || pkg.exports?.["."]?.types || pkg.exports?.["./"]?.types; if (path) return path; } } function setModuleResolution(options) { if (options.moduleResolution) return; const module = typeof options.module === "number" ? options.module : options.target ?? ts.ScriptTarget.ES5 >= 2 ? ts.ModuleKind.ES2015 : ts.ModuleKind.CommonJS; let moduleResolution; switch (module) { case ts.ModuleKind.CommonJS: moduleResolution = ts.ModuleResolutionKind.Node10; break; case ts.ModuleKind.Node16: moduleResolution = ts.ModuleResolutionKind.Node16; break; case ts.ModuleKind.NodeNext: moduleResolution = ts.ModuleResolutionKind.NodeNext; break; default: moduleResolution = ts.version.startsWith("5") ? ts.ModuleResolutionKind.Bundler : ts.ModuleResolutionKind.Classic; break; } options.moduleResolution = moduleResolution; } function editSourceMapDir(content, fromDir, toDir) { const relativeOutDir = relative(fromDir, toDir); if (relativeOutDir) { try { const sourceMap = JSON.parse(content); sourceMap.sources = sourceMap.sources.map((source) => { return normalizePath(relative(relativeOutDir, source)); }); return JSON.stringify(sourceMap); } catch (e) { return false; } } return true; } const dtsRE$1 = /\.d\.tsx?$/; function rollupDeclarationFiles({ root, configPath, compilerOptions, outDir, entryPath, fileName, libFolder, rollupConfig = {}, rollupOptions = {} }) { const configObjectFullPath = resolve$1(root, "api-extractor.json"); if (!dtsRE$1.test(fileName)) { fileName += ".d.ts"; } const extractorConfig = ExtractorConfig.prepare({ configObject: { ...rollupConfig, projectFolder: root, mainEntryPointFilePath: entryPath, compiler: { tsconfigFilePath: configPath, overrideTsconfig: { $schema: "http://json.schemastore.org/tsconfig", compilerOptions } }, apiReport: { enabled: false, reportFileName: ".api.md", ...rollupConfig.apiReport }, docModel: { enabled: false, ...rollupConfig.docModel }, dtsRollup: { enabled: true, publicTrimmedFilePath: resolve$1(outDir, fileName) }, tsdocMetadata: { enabled: false, ...rollupConfig.tsdocMetadata }, messages: { compilerMessageReporting: { default: { logLevel: "none" } }, extractorMessageReporting: { default: { logLevel: "none" } }, ...rollupConfig.messages } }, configObjectFullPath, packageJsonFullPath: tryGetPkgPath(configObjectFullPath) }); const result = Extractor.invoke(extractorConfig, { localBuild: false, showVerboseMessages: false, showDiagnostics: false, typescriptCompilerFolder: libFolder ? resolve$1(libFolder) : void 0, ...rollupOptions }); return result.succeeded; } const jsonRE = /\.json$/; function JsonResolver() { return { name: "json", supports(id) { return jsonRE.test(id); }, transform({ id, root, program }) { const sourceFile = program.getSourceFile(id); if (!sourceFile) return []; return [ { path: relative(root, `${id}.d.ts`), content: `declare const _default: ${sourceFile.text}; export default _default; ` } ]; } }; } const svelteRE = /\.svelte$/; function SvelteResolver() { return { name: "svelte", supports(id) { return svelteRE.test(id); }, transform({ id, root }) { return [ { path: relative(root, `${id}.d.ts`), content: "export { SvelteComponentTyped as default } from 'svelte';\n" } ]; } }; } const vueRE = /\.vue$/; function VueResolver() { return { name: "vue", supports(id) { return vueRE.test(id); }, transform({ id, code, program, service }) { const sourceFile = program.getSourceFile(id) || program.getSourceFile(id + ".ts") || program.getSourceFile(id + ".js") || program.getSourceFile(id + ".tsx") || program.getSourceFile(id + ".jsx"); if (!sourceFile) return []; const outputs = service.getEmitOutput(sourceFile.fileName, true).outputFiles.map((file) => { return { path: file.name, content: file.text }; }); if (!program.getCompilerOptions().declarationMap) return outputs; const [beforeScript] = code.split(/\s*/); const beforeLines = beforeScript.split("\n").length; for (const output of outputs) { if (output.path.endsWith(".map")) { try { const sourceMap = JSON.parse(output.content); sourceMap.sources = sourceMap.sources.map( (source) => source.replace(/\.vue\.ts$/, ".vue") ); if (beforeScript && beforeScript !== code && beforeLines) { sourceMap.mappings = `${base64VLQEncode([0, 0, beforeLines, 0])};${sourceMap.mappings}`; } output.content = JSON.stringify(sourceMap); } catch (e) { } } } return outputs; } }; } function parseResolvers(resolvers) { const nameMap = /* @__PURE__ */ new Map(); for (const resolver of resolvers) { resolver.name && nameMap.set(resolver.name, resolver); } return Array.from(nameMap.values()); } const globSuffixRE = /^((?:.*\.[^.]+)|(?:\*+))$/; function normalizeGlob(path) { if (/[\\/]$/.test(path)) { return path + "**"; } else if (!globSuffixRE.test(path.split(/[\\/]/).pop())) { return path + "/**"; } return path; } const globalDynamicTypeRE = /import\(['"][^;\n]+?['"]\)\.\w+[.()[\]<>,;\n\s]/g; const dynamicTypeRE = /import\(['"](.+)['"]\)\.(.+)([.()[\]<>,;\n\s])/; const importTypesRE = /import\s?(?:type)?\s?\{(.+)\}\s?from\s?['"].+['"]/; function transformDynamicImport(content) { const importMap = /* @__PURE__ */ new Map(); const defaultMap = /* @__PURE__ */ new Map(); let defaultCount = 1; content = content.replace(globalDynamicTypeRE, (str) => { const matchResult = str.match(dynamicTypeRE); const libName = matchResult[1]; const importSet = importMap.get(libName) ?? importMap.set(libName, /* @__PURE__ */ new Set()).get(libName); let usedType = matchResult[2]; if (usedType === "default") { usedType = defaultMap.get(libName) ?? defaultMap.set(libName, `__DTS_${defaultCount++}__`).get(libName); importSet.add(`default as ${usedType}`); } else { importSet.add(usedType); } return usedType + matchResult[3]; }); importMap.forEach((importSet, libName) => { const importReg = new RegExp( `import\\s?(?:type)?\\s?\\{[^;\\n]+\\}\\s?from\\s?['"]${libName}['"]`, "g" ); const matchResult = content.match(importReg); if (matchResult?.[0]) { matchResult[0].match(importTypesRE)[1].trim().split(",").forEach((type) => { type && importSet.add(type.trim()); }); content = content.replace( matchResult[0], `import { ${Array.from(importSet).join(", ")} } from '${libName}'` ); } else { content = `import { ${Array.from(importSet).join(", ")} } from '${libName}'; ` + content; } }); return content; } function isAliasMatch(alias, importer) { if (isRegExp(alias.find)) return alias.find.test(importer); if (importer.length < alias.find.length) return false; if (importer === alias.find) return true; return importer.indexOf(alias.find) === 0 && (alias.find.endsWith("/") || importer.substring(alias.find.length)[0] === "/"); } function ensureStartWithDot(path) { return path.startsWith(".") ? path : `./${path}`; } const globalImportRE = /(?:(?:import|export)\s?(?:type)?\s?(?:(?:\{[^;\n]+\})|(?:[^;\n]+))\s?from\s?['"][^;\n]+['"])|(?:import\(['"][^;\n]+?['"]\))/g; const staticImportRE = /(?:import|export)\s?(?:type)?\s?\{?.+\}?\s?from\s?['"](.+)['"]/; const dynamicImportRE = /import\(['"]([^;\n]+?)['"]\)/; const simpleStaticImportRE = /((?:import|export).+from\s?)['"](.+)['"]/; const simpleDynamicImportRE = /(import\()['"](.+)['"]\)/; function transformAliasImport(filePath, content, aliases, exclude = []) { if (!aliases?.length) return content; return content.replace(globalImportRE, (str) => { let matchResult = str.match(staticImportRE); let isDynamic = false; if (!matchResult) { matchResult = str.match(dynamicImportRE); isDynamic = true; } if (matchResult?.[1]) { const matchedAlias = aliases.find((alias) => isAliasMatch(alias, matchResult[1])); if (matchedAlias) { if (exclude.some((e) => isRegExp(e) ? e.test(matchResult[1]) : String(e) === matchResult[1])) { return str; } const dir = dirname(filePath); const replacement = isAbsolute(matchedAlias.replacement) ? normalizePath(relative(dir, matchedAlias.replacement)) : normalizePath(matchedAlias.replacement); const endSlash = typeof matchedAlias.find === "string" ? matchedAlias.find.endsWith("/") : matchResult[1].match(matchedAlias.find)[0].endsWith("/"); const truthPath = matchResult[1].replace( matchedAlias.find, replacement + (endSlash ? "/" : "") ); const normalizedPath = normalizePath(relative(dir, resolve$1(dir, truthPath))); return str.replace( isDynamic ? simpleDynamicImportRE : simpleStaticImportRE, `$1'${ensureStartWithDot(normalizedPath)}'${isDynamic ? ")" : ""}` ); } } return str; }); } const pureImportRE = /import\s?['"][^;\n]+?['"];?\n?/g; function removePureImport(content) { return content.replace(pureImportRE, ""); } const asDefaultRE = /export\s*\{.*\w+\s*\bas\s+default\b.*\}\s*from\s*['"].+['"]/; function hasExportDefault(content) { return content.includes("export default") || asDefaultRE.test(content); } const jsRE = /\.(m|c)?jsx?$/; const tsRE = /\.(m|c)?tsx?$/; const dtsRE = /\.d\.(m|c)?tsx?$/; const tjsRE = /\.(m|c)?(t|j)sx?$/; const mtjsRE = /\.m(t|j)sx?$/; const ctjsRE = /\.c(t|j)sx?$/; const fullRelativeRE = /^\.\.?\//; const defaultIndex = "index.d.ts"; const logPrefix = cyan("[vite:dts]"); const bundleDebug = debug("vite-plugin-dts:bundle"); const fixedCompilerOptions = { noEmit: false, declaration: true, emitDeclarationOnly: true, noUnusedParameters: false, checkJs: false, skipLibCheck: true, preserveSymlinks: false, noEmitOnError: void 0, target: ts.ScriptTarget.ESNext }; const noop = () => { }; const extPrefix = (file) => mtjsRE.test(file) ? "m" : ctjsRE.test(file) ? "c" : ""; const regexpSymbolRE = /([$.\\+?()[\]!<=|{}^,])/g; const asteriskRE = /[*]+/g; function dtsPlugin(options = {}) { const { tsconfigPath, logLevel, staticImport = false, clearPureImport = true, cleanVueFileName = false, insertTypesEntry = false, rollupTypes = false, pathsToAliases = true, aliasesExclude = [], rollupOptions = {}, copyDtsFiles = false, declarationOnly = false, strictOutput = true, afterDiagnostic = noop, beforeWriteFile = noop, afterBuild = noop } = options; let root = ensureAbsolute(options.root ?? "", process.cwd()); let publicRoot = ""; let entryRoot = options.entryRoot ?? ""; let configPath; let compilerOptions; let rawCompilerOptions; let outDirs; let entries; let include; let exclude; let aliases; let libName; let indexName; let logger; let host; let program; let filter; let bundled = false; let timeRecord = 0; const resolvers = parseResolvers([ JsonResolver(), VueResolver(), SvelteResolver(), ...options.resolvers || [] ]); const rootFiles = /* @__PURE__ */ new Set(); const outputFiles = /* @__PURE__ */ new Map(); const rollupConfig = { ...options.rollupConfig || {} }; rollupConfig.bundledPackages = rollupConfig.bundledPackages || options.bundledPackages || []; return { name: "vite:dts", apply: "build", enforce: "pre", config(config) { const aliasOptions = config?.resolve?.alias ?? []; if (isNativeObj(aliasOptions)) { aliases = Object.entries(aliasOptions).map(([key, value]) => { return { find: key, replacement: value }; }); } else { aliases = ensureArray(aliasOptions).map((alias) => ({ ...alias })); } if (aliasesExclude.length > 0) { aliases = aliases.filter( ({ find }) => !aliasesExclude.some( (aliasExclude) => aliasExclude && (isRegExp(find) ? find.toString() === aliasExclude.toString() : isRegExp(aliasExclude) ? find.match(aliasExclude)?.[0] : find === aliasExclude) ) ); } for (const alias of aliases) { alias.replacement = resolve(alias.replacement); } }, async configResolved(config) { logger = logLevel ? (await import('vite')).createLogger(logLevel, { allowClearScreen: config.clearScreen }) : config.logger; root = ensureAbsolute(options.root ?? "", config.root); if (config.build.lib) { const input = typeof config.build.lib.entry === "string" ? [config.build.lib.entry] : config.build.lib.entry; if (Array.isArray(input)) { entries = input.reduce( (prev, current) => { prev[basename(current)] = current; return prev; }, {} ); } else { entries = { ...input }; } const filename = config.build.lib.fileName ?? defaultIndex; const entry = typeof config.build.lib.entry === "string" ? config.build.lib.entry : Object.values(config.build.lib.entry)[0]; libName = config.build.lib.name || "_default"; indexName = typeof filename === "string" ? filename : filename("es", entry); if (!dtsRE.test(indexName)) { indexName = `${indexName.replace(tjsRE, "")}.d.${extPrefix(indexName)}ts`; } } else { logger.warn( ` ${logPrefix} ${yellow( "You are building a library that may not need to generate declaration files." )} ` ); libName = "_default"; indexName = defaultIndex; } if (!options.outDir) { outDirs = [ensureAbsolute(config.build.outDir, root)]; } bundleDebug("parse vite config"); }, options(options2) { if (entries) return; const input = typeof options2.input === "string" ? [options2.input] : options2.input; if (Array.isArray(input)) { entries = input.reduce( (prev, current) => { prev[basename(current)] = current; return prev; }, {} ); } else { entries = { ...input }; } logger = logger || console; aliases = aliases || []; libName = "_default"; indexName = defaultIndex; bundleDebug("parse options"); }, async buildStart() { if (program) return; bundleDebug("begin buildStart"); timeRecord = 0; const startTime = Date.now(); configPath = tsconfigPath ? ensureAbsolute(tsconfigPath, root) : ts.findConfigFile(root, ts.sys.fileExists); const content = configPath ? createParsedCommandLine(ts, ts.sys, configPath) : void 0; compilerOptions = { ...content?.options || {}, ...options.compilerOptions || {}, ...fixedCompilerOptions, outDir: ".", declarationDir: "." }; rawCompilerOptions = content?.raw.compilerOptions || {}; if (content?.fileNames.find((name) => name.endsWith(".vue"))) { setModuleResolution(compilerOptions); } if (!outDirs) { outDirs = options.outDir ? ensureArray(options.outDir).map((d) => ensureAbsolute(d, root)) : [ensureAbsolute(content?.raw.compilerOptions?.outDir || "dist", root)]; } const { baseUrl, paths } = compilerOptions; if (pathsToAliases && baseUrl && paths) { const basePath = ensureAbsolute(baseUrl, configPath ? dirname(configPath) : root); for (const [pathWithAsterisk, replacements] of Object.entries(paths)) { const find = new RegExp( `^${pathWithAsterisk.replace(regexpSymbolRE, "\\$1").replace(asteriskRE, "(.+)")}$` ); let index = 1; aliases.push({ find, replacement: ensureAbsolute( replacements[0].replace(asteriskRE, () => `$${index++}`), basePath ) }); } } const computeGlobs = (rootGlobs, tsGlobs, defaultGlob) => { if (rootGlobs?.length) { return ensureArray(rootGlobs).map((glob) => normalizeGlob(ensureAbsolute(glob, root))); } return ensureArray(tsGlobs?.length ? tsGlobs : defaultGlob).map( (glob) => normalizeGlob(ensureAbsolute(glob, configPath ? dirname(configPath) : root)) ); }; include = computeGlobs(options.include, content?.raw.include, "**/*"); exclude = computeGlobs(options.exclude, content?.raw.exclude, "node_modules/**"); filter = createFilter(include, exclude); const rootNames = [ ...new Set( Object.values(entries).map((entry) => ensureAbsolute(entry, root)).concat(content?.fileNames.filter(filter) || []).map(normalizePath) ) ]; host = ts.createCompilerHost(compilerOptions); program = createProgram({ host, rootNames, options: compilerOptions }); libName = toCapitalCase(libName || "_default"); indexName = indexName || defaultIndex; const maybeEmitted = (sourceFile) => { return !(compilerOptions.noEmitForJsFiles && jsRE.test(sourceFile.fileName)) && !sourceFile.isDeclarationFile && !program.isSourceFileFromExternalLibrary(sourceFile); }; publicRoot = compilerOptions.rootDir ? ensureAbsolute(compilerOptions.rootDir, root) : compilerOptions.composite && compilerOptions.configFilePath ? dirname(compilerOptions.configFilePath) : queryPublicPath( program.getSourceFiles().filter(maybeEmitted).map((sourceFile) => sourceFile.fileName) ); publicRoot = normalizePath(publicRoot); entryRoot = entryRoot || publicRoot; entryRoot = ensureAbsolute(entryRoot, root); const diagnostics = program.getDeclarationDiagnostics(); if (diagnostics?.length) { logger.error(ts.formatDiagnosticsWithColorAndContext(diagnostics, host)); } if (typeof afterDiagnostic === "function") { await wrapPromise(afterDiagnostic(diagnostics)); } rootNames.forEach((file) => { this.addWatchFile(file); rootFiles.add(file); }); bundleDebug("create ts program"); timeRecord += Date.now() - startTime; }, async transform(code, id) { let resolver; id = normalizePath(id); if (!host || !program || !filter(id) || !(resolver = resolvers.find((r) => r.supports(id))) && !tjsRE.test(id)) { return; } const startTime = Date.now(); const outDir = outDirs[0]; const service = program.__vue.languageService; id = id.split("?")[0]; rootFiles.delete(id); if (resolver) { const result = await resolver.transform({ id, code, root: publicRoot, outDir, host, program, service }); for (const { path, content } of result) { outputFiles.set( resolve(publicRoot, relative(outDir, ensureAbsolute(path, outDir))), content ); } } else { const sourceFile = program.getSourceFile(id); if (sourceFile) { for (const outputFile of service.getEmitOutput(sourceFile.fileName, true).outputFiles) { outputFiles.set( resolve(publicRoot, relative(outDir, ensureAbsolute(outputFile.name, outDir))), outputFile.text ); } } } const dtsId = id.replace(tjsRE, "") + ".d.ts"; const dtsSourceFile = program.getSourceFile(dtsId); dtsSourceFile && filter(dtsSourceFile.fileName) && outputFiles.set(normalizePath(dtsSourceFile.fileName), dtsSourceFile.getFullText()); timeRecord += Date.now() - startTime; }, watchChange(id) { id = normalizePath(id); if (!host || !program || !filter(id) || !resolvers.find((r) => r.supports(id)) && !tjsRE.test(id)) { return; } id = id.split("?")[0]; const sourceFile = host.getSourceFile(id, ts.ScriptTarget.ESNext); if (sourceFile) { rootFiles.add(sourceFile.fileName); program.__vue.projectVersion++; bundled = false; timeRecord = 0; } }, async writeBundle() { if (!host || !program || bundled) return; bundled = true; bundleDebug("begin writeBundle"); logger.info(green(` ${logPrefix} Start generate declaration files...`)); const startTime = Date.now(); const outDir = outDirs[0]; const emittedFiles = /* @__PURE__ */ new Map(); const writeOutput = async (path, content, outDir2, record = true) => { if (typeof beforeWriteFile === "function") { const result = await wrapPromise(beforeWriteFile(path, content)); if (result === false) return; if (result) { path = result.filePath || path; content = result.content ?? content; } } path = normalizePath(path); const dir = normalizePath(dirname(path)); if (strictOutput && !dir.startsWith(normalizePath(outDir2))) { logger.warn(`${logPrefix} ${yellow("Outside emitted:")} ${path}`); return; } if (!existsSync(dir)) { await mkdir(dir, { recursive: true }); } await writeFile(path, content, "utf-8"); record && emittedFiles.set(path, content); }; const service = program.__vue.languageService; const sourceFiles = program.getSourceFiles(); for (const sourceFile of sourceFiles) { if (!filter(sourceFile.fileName)) continue; if (copyDtsFiles && dtsRE.test(sourceFile.fileName)) { outputFiles.set(normalizePath(sourceFile.fileName), sourceFile.getFullText()); } if (rootFiles.has(sourceFile.fileName)) { for (const outputFile of service.getEmitOutput(sourceFile.fileName, true).outputFiles) { outputFiles.set( resolve(publicRoot, relative(outDir, ensureAbsolute(outputFile.name, outDir))), outputFile.text ); } rootFiles.delete(sourceFile.fileName); } } bundleDebug("emit output patch"); const currentDir = host.getCurrentDirectory(); const vuePathRE = /['"](.+)\.vue['"]/g; await runParallel( cpus().length, Array.from(outputFiles.entries()), async ([path, content]) => { const isMapFile = path.endsWith(".map"); const baseDir = dirname(path); if (!isMapFile && content) { content = clearPureImport ? removePureImport(content) : content; content = transformAliasImport(path, content, aliases, aliasesExclude); content = staticImport || rollupTypes ? transformDynamicImport(content) : content; } path = resolve( outDir, relative(entryRoot, cleanVueFileName ? path.replace(".vue.d.ts", ".d.ts") : path) ); content = cleanVueFileName ? content.replace(vuePathRE, '"$1"') : content; if (isMapFile) { try { const sourceMap = JSON.parse(content); sourceMap.sources = sourceMap.sources.map((source) => { return normalizePath( relative( dirname(path), resolve(currentDir, relative(publicRoot, baseDir), source) ) ); }); content = JSON.stringify(sourceMap); } catch (e) { logger.warn(`${logPrefix} ${yellow("Processing source map fail:")} ${path}`); } } await writeOutput(path, content, outDir); } ); bundleDebug("write output"); if (insertTypesEntry || rollupTypes) { const pkgPath = tryGetPkgPath(root); let pkg; try { pkg = pkgPath && existsSync(pkgPath) ? JSON.parse(await readFile(pkgPath, "utf-8")) : {}; } catch (e) { } const entryNames = Object.keys(entries); const types = findTypesPath(pkg.publishConfig, pkg); const multiple = entryNames.length > 1; const cleanPath = (path) => { return cleanVueFileName ? path.replace(".vue.d.ts", ".d.ts") : path; }; let typesPath = cleanPath(types ? resolve(root, types) : resolve(outDir, indexName)); if (!multiple && !dtsRE.test(typesPath)) { logger.warn( ` ${logPrefix} ${yellow( "The resolved path of type entry is not ending with '.d.ts'." )} ` ); typesPath = `${typesPath.replace(tjsRE, "")}.d.${extPrefix(typesPath)}ts`; } for (const name of entryNames) { const path = multiple ? cleanPath(resolve(outDir, `${name.replace(tsRE, "")}.d.ts`)) : typesPath; if (existsSync(path)) continue; const index = cleanPath( resolve(outDir, relative(entryRoot, `${entries[name].replace(tsRE, "")}.d.ts`)) ); let fromPath = normalizePath(relative(dirname(path), index)); fromPath = fromPath.replace(dtsRE, ""); fromPath = fullRelativeRE.test(fromPath) ? fromPath : `./${fromPath}`; let content = `export * from '${fromPath}' `; if (existsSync(index) && hasExportDefault(await readFile(index, "utf-8"))) { content += `import ${libName} from '${fromPath}' export default ${libName} `; } await writeOutput(cleanPath(path), content, outDir); } bundleDebug("insert index"); if (rollupTypes) { logger.info(green(`${logPrefix} Start rollup declaration files...`)); let libFolder = resolve(root, "node_modules/typescript"); if (!existsSync(libFolder)) { if (root !== entryRoot) { libFolder = resolve(entryRoot, "node_modules/typescript"); if (!existsSync(libFolder)) libFolder = void 0; } libFolder = void 0; } const rollupFiles = /* @__PURE__ */ new Set(); const compilerOptions2 = configPath ? getTsConfig(configPath, host.readFile).compilerOptions : rawCompilerOptions; if (multiple) { for (const name of entryNames) { const path = cleanPath(resolve(outDir, `${name.replace(tsRE, "")}.d.ts`)); rollupDeclarationFiles({ root, configPath, compilerOptions: compilerOptions2, outDir, entryPath: path, fileName: basename(path), libFolder, rollupConfig, rollupOptions }); emittedFiles.delete(path); rollupFiles.add(path); } } else { rollupDeclarationFiles({ root, configPath, compilerOptions: compilerOptions2, outDir, entryPath: typesPath, fileName: basename(typesPath), libFolder, rollupConfig, rollupOptions }); emittedFiles.delete(typesPath); rollupFiles.add(typesPath); } await runParallel(cpus().length, Array.from(emittedFiles.keys()), (f) => unlink(f)); removeDirIfEmpty(outDir); emittedFiles.clear(); for (const file of rollupFiles) { emittedFiles.set(file, await readFile(file, "utf-8")); } bundleDebug("rollup output"); } } if (outDirs.length > 1) { const extraOutDirs = outDirs.slice(1); await runParallel(cpus().length, Array.from(emittedFiles), async ([wroteFile, content]) => { const relativePath = relative(outDir, wroteFile); await Promise.all( extraOutDirs.map(async (targetOutDir) => { const path = resolve(targetOutDir, relativePath); if (wroteFile.endsWith(".map")) { if (!editSourceMapDir(content, outDir, targetOutDir)) { logger.warn(`${logPrefix} ${yellow("Processing source map fail:")} ${path}`); } } await writeOutput(path, content, targetOutDir, false); }) ); }); } if (typeof afterBuild === "function") { await wrapPromise(afterBuild(emittedFiles)); } bundleDebug("finish"); logger.info( green(`${logPrefix} Declaration files built in ${timeRecord + Date.now() - startTime}ms. `) ); }, generateBundle(_, bundle) { if (declarationOnly) { for (const id of Object.keys(bundle)) { delete bundle[id]; } } } }; } export { dtsPlugin as default, editSourceMapDir };