UNPKG

@sanity/pkg-utils

Version:

Simple utilities for modern npm packages.

872 lines (870 loc) 33.4 kB
import chalk from "chalk"; import { Observable, from } from "rxjs"; import path from "node:path"; import * as rimraf from "rimraf"; import { rimraf as rimraf$1 } from "rimraf"; import ts from "typescript"; import fs, { readFile } from "node:fs/promises"; import { ExtractorConfig, Extractor } from "@microsoft/api-extractor"; import { mkdirp } from "mkdirp"; import * as prettier from "prettier"; import { createRequire } from "node:module"; import { TSDocConfigFile } from "@microsoft/tsdoc-config"; import { parse } from "jsonc-parser"; import { parse as parse$1, print } from "recast"; import typeScriptParser from "recast/parsers/typescript.js"; import { createConsoleSpy, resolveConfigProperty, pkgExtMap } from "./consoleSpy.js"; import { rollup, watch } from "rollup"; import { optimizeLodashImports } from "@optimize-lodash/rollup-plugin"; import alias from "@rollup/plugin-alias"; import { babel, getBabelOutputPlugin } from "@rollup/plugin-babel"; import commonjs from "@rollup/plugin-commonjs"; import json from "@rollup/plugin-json"; import { nodeResolve } from "@rollup/plugin-node-resolve"; import replace from "@rollup/plugin-replace"; import terser from "@rollup/plugin-terser"; import esbuild from "rollup-plugin-esbuild"; function printExtractMessages(ctx, messages) { const { cwd, logger } = ctx, warnings = messages.filter((msg) => msg.logLevel === "warning"); warnings.length && logger.log(); for (const msg of warnings) { const sourceFilePath = msg.sourceFilePath && path.relative(cwd, msg.sourceFilePath); msg.messageId !== "TS6307" && logger.log( [ `${chalk.cyan(sourceFilePath || "?")}`, `:${chalk.yellow(msg.sourceFileLine)}:${chalk.yellow(msg.sourceFileColumn)}`, ` - ${chalk.yellow("warning")} ${chalk.gray(msg.messageId)} `, msg.text, ` ` ].join("") ); } const errors = messages.filter((msg) => msg.logLevel === "error"); !warnings.length && errors.length && logger.log(""); for (const msg of errors) { const sourceFilePath = msg.sourceFilePath && path.relative(cwd, msg.sourceFilePath); logger.log( [ `${chalk.cyan(sourceFilePath || "?")}`, `:${chalk.yellow(msg.sourceFileLine)}:${chalk.yellow(msg.sourceFileColumn)}`, ` - ${chalk.red("error")} ${chalk.gray(msg.messageId)} `, msg.text, ` ` ].join("") ); } errors.length && process.exit(1); } var printExtractMessages$1 = /* @__PURE__ */ Object.freeze({ __proto__: null, printExtractMessages }); function printDiagnostic(options) { const { cwd, logger, diagnostic } = options; if (diagnostic.file && diagnostic.start) { const { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), message = ts.flattenDiagnosticMessageText(diagnostic.messageText, ` `), file = path.relative(cwd, diagnostic.file.fileName), output = [ `${chalk.yellow(file)}:${chalk.blue(line + 1)}:${chalk.blue(character + 1)} - `, `${chalk.gray(`TS${diagnostic.code}:`)} ${message}` ].join(""); diagnostic.category === ts.DiagnosticCategory.Error && logger.error(output), diagnostic.category === ts.DiagnosticCategory.Warning && logger.warn(output), diagnostic.category === ts.DiagnosticCategory.Message && logger.log(output), diagnostic.category === ts.DiagnosticCategory.Suggestion && logger.log(output); } else logger.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, ` `)); } async function buildTypes(options) { const { cwd, logger, outDir, tsconfig, strict = !1 } = options, compilerOptions = { ...tsconfig.options, declaration: !0, declarationDir: outDir, emitDeclarationOnly: !0, noEmit: !1, noEmitOnError: strict ? !0 : tsconfig.options.noEmitOnError ?? !0, noCheck: tsconfig.options.noCheck ?? tsconfig.options.isolatedDeclarations, outDir }, program = ts.createProgram(tsconfig.fileNames, compilerOptions), emitResult = program.emit(), allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); for (const diagnostic of allDiagnostics) printDiagnostic({ cwd, logger, diagnostic }); if (emitResult.emitSkipped && allDiagnostics.filter((diag) => diag.category === ts.DiagnosticCategory.Error).length) throw new Error("failed to compile TypeScript definitions"); } class DtsError extends Error { messages; constructor(message, messages) { super(message), this.messages = messages; } } function createApiExtractorConfig(options) { const { bundledPackages, distPath, exportPath, filePath, messages, projectFolder, mainEntryPointFilePath, tsconfig, tsconfigPath, dtsRollupEnabled } = options; return { apiReport: { enabled: !1, reportFileName: "<unscopedPackageName>.api.md" }, bundledPackages, // If `paths` are used for self-referencing imports (e.g. the module is named `sanity`, and the `sanity/structure` export is also importing from `sanity/router`), compiler: tsconfig.options.paths ? { overrideTsconfig: { extends: tsconfigPath, compilerOptions: { // An empty object replaces whatever is in the original tsconfig file paths: {} } } } : { tsconfigFilePath: tsconfigPath }, docModel: { enabled: !1, apiJsonFilePath: path.resolve(distPath, `${exportPath}.api.json`) }, dtsRollup: { enabled: dtsRollupEnabled, untrimmedFilePath: path.resolve(distPath, filePath) // betaTrimmedFilePath: path.resolve(distPath, filePath.replace('.d.ts', '-beta.d.ts')), // publicTrimmedFilePath: path.resolve(distPath, filePath.replace('.d.ts', '-public.d.ts')), }, tsdocMetadata: { enabled: !1 }, messages, mainEntryPointFilePath, projectFolder }; } var createApiExtractorConfig$1 = /* @__PURE__ */ Object.freeze({ __proto__: null, createApiExtractorConfig }); const require2 = createRequire(import.meta.url); async function createTSDocConfig(opts) { const { customTags } = opts; if (customTags.length === 0) return; const tsDocBaseBuf = await readFile( require2.resolve("@microsoft/api-extractor/extends/tsdoc-base.json") ), tsDocBaseConfig = parse(tsDocBaseBuf.toString()), tagDefinitions = (tsDocBaseConfig.tagDefinitions || []).concat( customTags.map((t) => ({ tagName: `@${t.name}`, syntaxKind: t.syntaxKind, allowMultiple: t.allowMultiple })) ), supportForTags = { ...tsDocBaseConfig.supportForTags }; for (const customTag of customTags) supportForTags[`@${customTag.name}`] = !0; return TSDocConfigFile.loadFromObject({ ...tsDocBaseConfig, noStandardTags: !1, tagDefinitions, supportForTags }); } var createTSDocConfig$1 = /* @__PURE__ */ Object.freeze({ __proto__: null, createTSDocConfig }); async function extractModuleBlocksFromTypes({ tsOutDir, extractResult }) { const program = extractResult.compilerState.program, moduleBlocks = [], sourceFiles = [...program.getSourceFiles()].filter((sourceFile) => sourceFile.fileName.includes(tsOutDir)); for (const sourceFile of sourceFiles) sourceFile.text.includes("declare module") && moduleBlocks.push(...extractModuleBlocks(sourceFile.text)); return moduleBlocks; } function extractModuleBlocks(fileContent) { return parse$1(fileContent, { parser: typeScriptParser }).program.body.filter((node) => node.type === "TSModuleDeclaration").map((node) => print(node).code); } const LOG_LEVELS = { error: "error", info: "info", off: "none", warn: "warning" }; function getExtractMessagesConfig(options) { const { rules, disabled = !1 } = options; function ruleToLogLevel(key, defaultLevel) { const r = rules?.[key]; return r ? LOG_LEVELS[r] : defaultLevel || "warning"; } return { compilerMessageReporting: { default: { logLevel: disabled ? "none" : "warning" } }, extractorMessageReporting: disabled ? { default: { logLevel: "none", addToApiReportFile: !1 } } : { default: { logLevel: "warning", addToApiReportFile: !1 }, "ae-forgotten-export": { /** * This is hardcoded to `none` as it's no longer needed since TypeScript 5.5 https://github.com/microsoft/TypeScript/issues/42873 * It's hardcoded to `none` since supported by API Extractor when using `module: 'Preserve'` doesn't support it well since `@microsoft/api-extractor` v7.49.0, which upgraded from TS 5.4 to 5.7 internally */ logLevel: "none", addToApiReportFile: !1 }, "ae-incompatible-release-tags": { logLevel: ruleToLogLevel("ae-incompatible-release-tags", "error"), addToApiReportFile: !1 }, "ae-internal-missing-underscore": { logLevel: ruleToLogLevel("ae-internal-missing-underscore"), addToApiReportFile: !1 }, "ae-missing-release-tag": { logLevel: ruleToLogLevel("ae-missing-release-tag", "error"), addToApiReportFile: !1 }, "ae-wrong-input-file-type": { logLevel: "none", addToApiReportFile: !1 } }, tsdocMessageReporting: disabled ? { default: { logLevel: "none", addToApiReportFile: !1 } } : { default: { logLevel: "warning", addToApiReportFile: !1 }, "tsdoc-link-tag-unescaped-text": { logLevel: ruleToLogLevel( "tsdoc-link-tag-unescaped-text", "warning" ), addToApiReportFile: !1 }, "tsdoc-undefined-tag": { logLevel: ruleToLogLevel("tsdoc-undefined-tag", "error"), addToApiReportFile: !1 }, "tsdoc-unsupported-tag": { logLevel: ruleToLogLevel("tsdoc-unsupported-tag", "none"), addToApiReportFile: !1 } } }; } var getExtractMessagesConfig$1 = /* @__PURE__ */ Object.freeze({ __proto__: null, getExtractMessagesConfig }); async function extractTypes(options) { const { bundledPackages, customTags, distPath, exportPath, files, filePaths, projectPath, rules, sourceTypesPath, tmpPath, tsconfig, tsconfigPath, extractorDisabled } = options, tsdocConfigFile = await createTSDocConfig({ customTags: customTags || [] }), filePath = filePaths[0].replace(/\.d\.[mc]ts$/, ".d.ts"), shouldCleanUpDts = !filePaths.includes(filePath), extractorConfig = ExtractorConfig.prepare({ configObject: createApiExtractorConfig({ bundledPackages, distPath, exportPath, filePath, messages: getExtractMessagesConfig({ rules, disabled: extractorDisabled }), projectFolder: projectPath, mainEntryPointFilePath: sourceTypesPath, tsconfig, tsconfigPath, dtsRollupEnabled: !0 }), configObjectFullPath: void 0, tsdocConfigFile, packageJsonFullPath: path.resolve(projectPath, "package.json") }), messages = [], extractorResult = Extractor.invoke(extractorConfig, { // Equivalent to the "--local" command-line parameter localBuild: !0, // Equivalent to the "--verbose" command-line parameter showVerboseMessages: !0, // handle messages messageCallback(message) { messages.push(message), message.handled = !0; } }), typesPath = path.resolve(distPath, filePath), typesBuf = await fs.readFile(typesPath), prettierConfig = await prettier.resolveConfig(typesPath); await mkdirp(path.dirname(typesPath)); const moduleBlocks = await extractModuleBlocksFromTypes({ extractResult: extractorResult, tsOutDir: tmpPath }), code = [typesBuf.toString(), ...moduleBlocks].join(` `), prettyCode = await prettier.format(code, { ...prettierConfig, filepath: typesPath }); for (const expFilePath of filePaths) { const expTypesPath = path.resolve(distPath, expFilePath); await fs.writeFile(expTypesPath, prettyCode), files.push({ type: "types", path: expTypesPath }); } return shouldCleanUpDts && await fs.unlink(typesPath), { extractorResult, messages }; } async function doExtract(ctx, task) { const { config, cwd, files, logger, strict, ts: ts2, bundledPackages } = ctx; if (!ts2.config || !ts2.configPath) return { type: "dts", messages: [], results: [] }; const { outDir, rootDir = cwd } = ts2.config.options; if (!outDir) throw new Error("tsconfig.json is missing `compilerOptions.outDir`"); const tmpPath = path.resolve(outDir, "__tmp__"); await buildTypes({ cwd, logger, outDir: tmpPath, strict, tsconfig: ts2.config }); const messages = [], results = []; for (const entry of task.entries) { const exportPath = entry.exportPath === "." ? "./index" : entry.exportPath, sourceTypesPath = path.resolve( tmpPath, path.relative(rootDir, path.resolve(cwd, entry.sourcePath)).replace(/\.ts$/, ".d.ts") ), targetPaths = entry.targetPaths.map((targetPath) => path.resolve(cwd, targetPath)), filePaths = targetPaths.map((targetPath) => path.relative(outDir, targetPath)), result = await extractTypes({ bundledPackages: bundledPackages || [], customTags: config?.extract?.customTags, distPath: outDir, exportPath, files, filePaths, projectPath: cwd, rules: config?.extract?.rules, sourceTypesPath, tsconfig: ts2.config, tmpPath, tsconfigPath: path.resolve(cwd, ts2.configPath || "tsconfig.json"), extractorDisabled: config?.extract?.enabled === !1 }); messages.push(...result.messages); const errors = result.messages.filter((msg) => msg.logLevel === "error"); if (errors.length > 0) throw await rimraf$1(tmpPath), new DtsError(`encountered ${errors.length} errors when extracting types`, errors); results.push({ sourcePath: path.resolve(cwd, entry.sourcePath), filePaths: targetPaths }); } return await rimraf$1(tmpPath), { type: "dts", messages, results }; } const dtsTask = { name: (ctx, task) => [ `Build type definitions with ${chalk.bold(ctx.dts)}...`, " entries:", ...task.entries.map((entry) => entry.targetPaths.map((targetPath) => [ ` - ${chalk.cyan(entry.importId)}: `, `${chalk.yellow(entry.sourcePath)} ${chalk.gray("\u2192")} ${chalk.yellow(targetPath)}` ].join("")).join(` `)) ].join(` `), exec: (ctx, task) => new Observable((observer) => { doExtract(ctx, task).then((result) => { observer.next(result), observer.complete(); }).catch((err) => { observer.error(err); }); }), complete: (ctx, _task, result) => { printExtractMessages(ctx, result.messages); }, error: (ctx, _task, err) => { const { logger } = ctx; err instanceof DtsError ? printExtractMessages(ctx, err.messages) : err instanceof Error && logger.error(err); } }, dtsWatchTask = { name: (_ctx, task) => [ "build type definitions", ...task.entries.map((entry) => entry.targetPaths.map((targetPath) => [ ` - ${chalk.cyan(entry.importId)}: `, `${chalk.yellow(entry.sourcePath)} ${chalk.gray("\u2192")} ${chalk.yellow(targetPath)}` ].join(""))) ].join(` `), exec: (ctx, task) => { const { config, cwd, files, logger, strict, ts: tsContext, bundledPackages } = ctx; return new Observable((observer) => { if (!tsContext.config || !tsContext.configPath) { observer.next({ type: "dts", messages: [], results: [] }), observer.complete(); return; } const { outDir, rootDir = cwd } = tsContext.config.options; if (!outDir) { observer.error(new Error("tsconfig.json is missing `compilerOptions.outDir`")); return; } const tmpPath = path.resolve(outDir, "__tmp__"); buildTypes({ cwd, logger, outDir: tmpPath, tsconfig: tsContext.config, strict }).catch((err) => { observer.error(err); }); const host = ts.createWatchCompilerHost( tsContext.configPath, { ...tsContext.config.options, declaration: !0, declarationDir: tmpPath, emitDeclarationOnly: !0, noEmit: !1, noEmitOnError: strict ? !0 : tsContext.config.options.noEmitOnError ?? !0, outDir: tmpPath }, ts.sys, ts.createEmitAndSemanticDiagnosticsBuilderProgram, (diagnostic) => { logger.error(ts.flattenDiagnosticMessageText(diagnostic.messageText, ` `)); }, (diagnostic) => { logger.info(ts.flattenDiagnosticMessageText(diagnostic.messageText, ` `)); } ), origPostProgramCreate = host.afterProgramCreate; host.afterProgramCreate = async (program) => { origPostProgramCreate?.(program); const messages = [], results = []; for (const entry of task.entries) { const exportPath = entry.exportPath === "." ? "./index" : entry.exportPath, sourceTypesPath = path.resolve( tmpPath, path.relative(rootDir, path.resolve(cwd, entry.sourcePath)).replace(/\.ts$/, ".d.ts") ), targetPaths = entry.targetPaths.map((targetPath) => path.resolve(cwd, targetPath)), filePaths = targetPaths.map((targetPath) => path.relative(outDir, targetPath)); try { const result = await extractTypes({ bundledPackages: bundledPackages || [], customTags: config?.extract?.customTags, cwd, distPath: outDir, exportPath, files, filePaths, projectPath: cwd, rules: config?.extract?.rules, sourceTypesPath, tsconfig: tsContext.config, tmpPath, tsconfigPath: path.resolve(cwd, tsContext.configPath || "tsconfig.json"), extractorDisabled: config?.extract?.enabled === !1 }); messages.push(...result.messages), results.push({ sourcePath: path.resolve(cwd, entry.sourcePath), filePaths: targetPaths }); } catch (err) { if (err instanceof DtsError) messages.push(...err.messages); else { observer.error(err); return; } } } observer.next({ type: "dts", messages, results }); }; const watchProgram = ts.createWatchProgram(host); return () => { watchProgram.close(), rimraf.sync(tmpPath); }; }); }, complete: (ctx, task, result) => { const { logger } = ctx; printExtractMessages(ctx, result.messages), logger.success( `build type definitions ${task.entries.map( (entry) => ` - ${chalk.cyan(entry.importId)}: ${chalk.yellow(entry.sourcePath)} ${chalk.gray("\u2192")} ${chalk.yellow(entry.targetPaths.join(", "))}` ).join(` `)}` ), logger.log(""); }, error: (ctx, _task, err) => { const { logger } = ctx; err instanceof DtsError ? printExtractMessages(ctx, err.messages) : err instanceof Error && logger.error(err); } }, rolldownDtsTask = { name: (ctx, task) => { const bundleEntries = task.entries.filter((e) => e.path.includes("__$$bundle_")), entries = task.entries.filter((e) => !e.path.includes("__$$bundle_")), targetLines = task.target.length ? [" target:", ...task.target.map((t) => ` - ${chalk.yellow(t)}`)] : [], bundlesLines = bundleEntries.length ? [ " bundles:", ...bundleEntries.map( (e) => [ " - ", `${chalk.yellow(e.source)} ${chalk.gray("\u2192")} ${chalk.yellow(replaceFileEnding(e.output))}` ].join("") ) ] : [], entriesLines = entries.length ? [ " entries:", ...entries.map( (e) => [ " - ", `${chalk.cyan(path.join(ctx.pkg.name, e.path))}: `, `${chalk.yellow(e.source)} ${chalk.gray("\u2192")} ${chalk.yellow(replaceFileEnding(e.output))}` ].join("") ) ] : []; return [ `Build type definitions with ${chalk.bold("rolldown")}...`, ` format: ${chalk.yellow(task.format)}`, ...targetLines, ...bundlesLines, ...entriesLines ].join(` `); }, exec: (ctx, task) => from(execPromise$1(ctx, task)), complete: () => { }, error: (_ctx, _task, err) => { console.error(err); } }; async function execPromise$1(ctx, task) { const [{ rolldown }, { resolveRolldownConfig }] = await Promise.all([ import("rolldown"), import("./resolveRolldownConfig.js") ]), { distPath, files, logger } = ctx, outDir = path.relative(ctx.cwd, distPath), consoleSpy = createConsoleSpy({ onRestored: (messages) => { for (const msg of messages) { const text = String(msg.args[0]); msg.code !== "CIRCULAR_DEPENDENCY" && (text.startsWith("Dynamic import can only") || text.startsWith("Sourcemap is likely to be incorrect") || (msg.type === "log" && logger.info(...msg.args), msg.type === "warn" && logger.warn(...msg.args), msg.type === "error" && logger.error(...msg.args))); } } }); try { const { inputOptions, outputOptions } = resolveRolldownConfig(ctx, task), bundle = await rolldown({ ...inputOptions, onwarn(warning) { consoleSpy.messages.push({ type: "warn", code: warning.code, args: [warning.message] }); } }), { output } = await bundle.generate(outputOptions); for (const chunkOrAsset of output) chunkOrAsset.type === "asset" ? files.push({ type: "asset", path: path.resolve(outDir, chunkOrAsset.fileName) }) : files.push({ type: "chunk", path: path.resolve(outDir, chunkOrAsset.fileName) }); await bundle.write(outputOptions), await bundle.close(), consoleSpy.restore(); } catch (err) { throw consoleSpy.restore(), err; } } function replaceFileEnding(path2) { switch (!0) { case path2.endsWith(".mjs"): return path2.replace(/\.mjs$/, ".d.mts"); case path2.endsWith(".cjs"): return path2.replace(/\.cjs$/, ".d.cts"); default: return path2.replace(/\.js$/, ".d.ts"); } } function resolveRollupConfig(ctx, buildTask) { const { format, runtime, target } = buildTask, { config, cwd, exports: _exports, external, distPath, logger, pkg, ts: ts2 } = ctx, outputExt = pkgExtMap[pkg.type || "commonjs"][format], minify = config?.minify ?? !1, outDir = path.relative(cwd, distPath), pathAliases = Object.fromEntries( Object.entries(ts2.config?.options.paths || {}).map(([key, val]) => [key, path.resolve(cwd, ts2.config?.options.baseUrl || ".", val[0])]) ), entries = buildTask.entries.map((entry) => ({ ...entry, name: path.relative(outDir, entry.output).replace(/\.[^/.]+$/, "") }), {}), exportIds = _exports && Object.keys(_exports).map((exportPath) => path.join(pkg.name, exportPath)), sourcePaths = _exports && Object.values(_exports).map((e) => path.resolve(cwd, e.source)), replacements = Object.fromEntries( Object.entries(config?.define || {}).map(([key, val]) => [key, JSON.stringify(val)]) ), { optimizeLodash: enableOptimizeLodash = hasDependency(pkg, "lodash") } = config?.rollup || {}, defaultPlugins = [ replace({ preventAssignment: !0, values: pkg.name === "@sanity/pkg-utils" ? { ...replacements } : { "process.env.PKG_FILE_PATH": (arg) => { const sourcePath = `./${path.relative(cwd, arg)}`, entry = entries.find((e) => e.source === sourcePath); return entry ? JSON.stringify( path.relative(cwd, path.resolve(outDir, entry.name + outputExt)) ) : (console.error(`could not find source entry: ${sourcePath}`), "null"); }, "process.env.PKG_FORMAT": JSON.stringify(format), "process.env.PKG_RUNTIME": JSON.stringify(runtime), "process.env.PKG_VERSION": JSON.stringify(process.env.PKG_VERSION || pkg.version), ...replacements } }), alias({ entries: { ...pathAliases } }), nodeResolve({ browser: runtime === "browser", extensions: [".cjs", ".mjs", ".js", ".jsx", ".json", ".node"], preferBuiltins: !0 }), commonjs(), json(), (config?.babel?.reactCompiler || config?.babel?.styledComponents) && babel({ babelrc: !1, presets: ["@babel/preset-typescript"], babelHelpers: "bundled", extensions: [".ts", ".tsx", ".js", ".jsx"], plugins: [ // The styled-components plugin needs to run before the react-compiler plugin, in case the css prop is used config?.babel?.styledComponents && [ "babel-plugin-styled-components", { // Unnecessary, as the way we use styled-components in Sanity is usually by wrapping `@sanity/ui` primitives, not declaring new ones like "const Button = styled.button``" fileName: !1, // Native template literals take less space than this transpilation transpileTemplateLiterals: !1, // Massively helps dead code elimination and tree-shaking pure: !0, // disabled, as pkg-utils tends to be used for npm publishing, while other tooling, like `sanity dev`, `next dev`, etc are used for testing cssProp: !1, ...typeof config.babel.styledComponents == "object" ? config.babel.styledComponents : {} } ], config?.babel?.reactCompiler && [ "babel-plugin-react-compiler", config?.reactCompilerOptions || {} ] ].filter(Boolean) }), esbuild({ jsx: config?.jsx ?? "automatic", jsxFactory: config?.jsxFactory ?? "createElement", jsxFragment: config?.jsxFragment ?? "Fragment", jsxImportSource: config?.jsxImportSource ?? "react", target, tsconfig: ctx.ts.configPath || "tsconfig.json", treeShaking: !0, minifySyntax: config?.minify !== !1, supported: { "template-literal": !0 } }), Array.isArray(config?.babel?.plugins) && getBabelOutputPlugin({ babelrc: !1, plugins: config.babel.plugins }), enableOptimizeLodash && optimizeLodashImports({ useLodashEs: format === "esm" && hasDependency(pkg, "lodash-es") ? !0 : void 0, ...typeof config?.rollup?.optimizeLodash == "boolean" ? {} : config?.rollup?.optimizeLodash }), minify && terser({ compress: { directives: !1, passes: 10 }, ecma: 2020, output: { comments: (_node, comment) => { const text = comment.value; return comment.type === "comment2" ? /@preserve|@license|@cc_on/i.test(text) : !1; }, preserve_annotations: !0 } }) ].filter(Boolean), userPlugins = config?.rollup?.plugins, plugins = Array.isArray(userPlugins) ? defaultPlugins.concat(userPlugins) : resolveConfigProperty(config?.rollup?.plugins, defaultPlugins), hashChunkFileNames = config?.rollup?.hashChunkFileNames ?? !1, chunkFileNames = `${hashChunkFileNames ? "_chunks" : "_chunks-[format]"}/${hashChunkFileNames ? "[name]-[hash]" : "[name]"}${outputExt}`, entryFileNames = `[name]${outputExt}`; return { inputOptions: { context: cwd, external: (id, importer) => { if (exportIds?.includes(id)) return !0; if (importer && (id.startsWith(".") || id.startsWith("/"))) { const idPath = path.resolve(path.dirname(importer), id); if (sourcePaths?.includes(idPath)) return logger.warn( `detected self-referencing import \u2013 treating as external: ${path.relative( cwd, idPath )}` ), !0; } const idParts = id.split("/"), name = idParts[0].startsWith("@") ? `${idParts[0]}/${idParts[1]}` : idParts[0]; return !!(name && external.includes(name)); }, input: entries.reduce( (acc, entry) => Object.assign(acc, { [entry.name]: entry.source }), {} ), watch: { chokidar: { usePolling: !0 } }, plugins, treeshake: { preset: "recommended", propertyReadSideEffects: !1, moduleSideEffects: "no-external", annotations: !0, ...config?.rollup?.treeshake }, experimentalLogSideEffects: config?.rollup?.experimentalLogSideEffects }, outputOptions: { chunkFileNames, compact: minify, dir: outDir, entryFileNames, esModule: !0, format, interop: "compat", sourcemap: config?.sourcemap ?? !0, hoistTransitiveImports: !1, minifyInternalExports: minify, ...config?.rollup?.output } }; } function hasDependency(pkg, packageName) { return pkg.dependencies ? packageName in pkg.dependencies : pkg.peerDependencies ? packageName in pkg.peerDependencies : !1; } const rollupTask = { name: (ctx, task) => { const bundleEntries = task.entries.filter((e) => e.path.includes("__$$bundle_")), entries = task.entries.filter((e) => !e.path.includes("__$$bundle_")), targetLines = task.target.length ? [" target:", ...task.target.map((t) => ` - ${chalk.yellow(t)}`)] : [], bundlesLines = bundleEntries.length ? [ " bundles:", ...bundleEntries.map( (e) => [ " - ", `${chalk.yellow(e.source)} ${chalk.gray("\u2192")} ${chalk.yellow(e.output)}` ].join("") ) ] : [], entriesLines = entries.length ? [ " entries:", ...entries.map( (e) => [ " - ", `${chalk.cyan(path.join(ctx.pkg.name, e.path))}: `, `${chalk.yellow(e.source)} ${chalk.gray("\u2192")} ${chalk.yellow(e.output)}` ].join("") ) ] : []; return [ "Build javascript files...", ` format: ${chalk.yellow(task.format)}`, ...targetLines, ...bundlesLines, ...entriesLines ].join(` `); }, exec: (ctx, task) => new Observable((observer) => { execPromise(ctx, task).then((result) => { observer.next(result), observer.complete(); }).catch((err) => observer.error(err)); }), complete: () => { }, error: (_ctx, _task, err) => { console.error(err); } }; async function execPromise(ctx, task) { const { distPath, files, logger } = ctx, outDir = path.relative(ctx.cwd, distPath), consoleSpy = createConsoleSpy({ onRestored: (messages) => { for (const msg of messages) { const text = String(msg.args[0]); msg.code !== "CIRCULAR_DEPENDENCY" && (text.startsWith("Dynamic import can only") || text.startsWith("Sourcemap is likely to be incorrect") || (msg.type === "log" && logger.info(...msg.args), msg.type === "warn" && logger.warn(...msg.args), msg.type === "error" && logger.error(...msg.args))); } } }); try { const { inputOptions, outputOptions } = resolveRollupConfig(ctx, task), bundle = await rollup({ ...inputOptions, onwarn(warning) { consoleSpy.messages.push({ type: "warn", code: warning.code, args: [warning.message] }); } }), { output } = await bundle.generate(outputOptions); for (const chunkOrAsset of output) chunkOrAsset.type === "asset" ? files.push({ type: "asset", path: path.resolve(outDir, chunkOrAsset.fileName) }) : files.push({ type: "chunk", path: path.resolve(outDir, chunkOrAsset.fileName) }); await bundle.write(outputOptions), await bundle.close(), consoleSpy.restore(); } catch (err) { throw consoleSpy.restore(), err; } } const rollupWatchTask = { name: (ctx, task) => `build javascript files (target ${task.target.join(" + ")}, format ${task.format}) ${task.entries.map((e) => `${chalk.blue(path.join(ctx.pkg.name, e.path))}: ${e.source} -> ${e.output}`).join(` `)}`, exec: (ctx, task) => { const { inputOptions, outputOptions } = resolveRollupConfig(ctx, task); return new Observable((observer) => { const watchOptions = { ...inputOptions, output: outputOptions }, watcher = watch(watchOptions); return watcher.on("event", (event) => { observer.next(event); }), () => { watcher.close(); }; }); }, complete: (ctx, task, event) => { const { logger } = ctx; if (event.code === "BUNDLE_END") { logger.success( `build javascript files (target ${task.target.join(" + ")}, format ${task.format}) ${task.entries.map((e) => `${chalk.blue(path.join(ctx.pkg.name, e.path))}: ${e.source} -> ${e.output}`).join(` `)}` ), logger.log(""); return; } if (event.code !== "BUNDLE_START" && event.code !== "END" && event.code === "ERROR") { logger.error(event.code, event); return; } }, error: (ctx, _task, err) => { const { logger } = ctx; err instanceof Error && logger.log(err); } }, buildTaskHandlers = { "build:dts": dtsTask, "build:js": rollupTask, "rolldown:dts": rolldownDtsTask }, watchTaskHandlers = { "watch:dts": dtsWatchTask, "watch:js": rollupWatchTask }; export { buildTaskHandlers, createApiExtractorConfig$1 as createApiExtractorConfig, createTSDocConfig$1 as createTSDocConfig, getExtractMessagesConfig, getExtractMessagesConfig$1, printExtractMessages$1 as printExtractMessages, watchTaskHandlers }; //# sourceMappingURL=index.js.map