UNPKG

@elsikora/setup-wizard

Version:

Setup Wizard - CLI scaffolding utility

564 lines (553 loc) 19.2 kB
#!/usr/bin/env node import path from 'node:path'; import { EBuildTool } from '../../../domain/enum/build-tool.enum.js'; import { BUILDER_TYPESCRIPT_PACKAGE_NAME, BUILDER_WEBPACK_PACKAGE_NAME, BUILDER_WEBPACK_CLI_PACKAGE_NAME, BUILDER_VITE_TSCONFIG_PATHS_PACKAGE_NAME, BUILDER_VITE_PACKAGE_NAME, BUILDER_TURBOPACK_PACKAGE_NAME, BUILDER_SWC_CORE_PACKAGE_NAME, BUILDER_SWC_CLI_PACKAGE_NAME, BUILDER_ROLLUP_PLUGIN_TYPESCRIPT, BUILDER_TSLIB_PACKAGE_NAME, BUILDER_ROLLUP_PLUGIN_DTS_PATH_ALIAS, BUILDER_ROLLUP_PLUGIN_TERSER, BUILDER_ROLLUP_PACKAGE_NAME, BUILDER_PARCEL_PACKAGE_NAME, BUILDER_ESBUILD_PACKAGE_NAME } from './package-names.constant.js'; /** * Configuration for different build tools. * Provides tool-specific settings and dependencies. */ const BUILD_TOOL_CONFIG = { [EBuildTool.ESBUILD]: { canSupportCliApps: true, configFileName: "esbuild.config.js", configGenerator: (options) => { const { entryPoint, formats, isCliApp, isMinifyEnabled, isSourceMapsEnabled, isTypeScript, outputDirectory } = options; // esbuild uses a JavaScript config file const format = formats[0]; // esbuild builds one format at a time let outExtension; if (format === "esm") { outExtension = ".mjs"; } else if (format === "cjs") { outExtension = ".cjs"; } else { outExtension = ".js"; } // Extract nested ternary for format let buildFormat; if (format === "esm") { buildFormat = "esm"; } else if (format === "cjs") { buildFormat = "cjs"; } else { buildFormat = "iife"; } return `import { build } from "esbuild"; import { resolve } from "path"; const args = process.argv.slice(2); const isWatch = args.includes("--watch"); const buildOptions = { entryPoints: ["${entryPoint}"], bundle: true, platform: "${isCliApp ? "node" : "neutral"}", format: "${buildFormat}", outfile: "${outputDirectory}/${path.basename(entryPoint, path.extname(entryPoint))}${outExtension}", sourcemap: ${isSourceMapsEnabled}, minify: ${isMinifyEnabled},${isCliApp ? ` banner: { js: "#!/usr/bin/env node", },` : ""}${isTypeScript ? ` tsconfig: "./tsconfig.json",` : ""} external: ${isCliApp ? '["node:*"]' : "[]"}, }; if (isWatch) { const context = await build({ ...buildOptions, metafile: true }); await context.watch(); console.log("Watching for changes..."); } else { await build(buildOptions); console.log("Build complete!"); } `; }, coreDependencies: [BUILDER_ESBUILD_PACKAGE_NAME], defaultOutputDir: "./dist", defaultOutputDirCli: "./bin", description: "An extremely fast JavaScript bundler", name: "esbuild", optionalDependencies: { minify: [], // Built-in typescript: [BUILDER_TYPESCRIPT_PACKAGE_NAME], }, scripts: { build: "node esbuild.config.js", dev: "node esbuild.config.js --watch", watch: "node esbuild.config.js --watch", }, supportedFormats: ["esm", "cjs", "iife"], }, [EBuildTool.PARCEL]: { canSupportCliApps: true, configFileName: ".parcelrc", configGenerator: (_options) => { // Parcel uses .parcelrc for configuration return `{ "extends": "@parcel/config-default", "transformers": { "*.{js,jsx,ts,tsx}": ["@parcel/transformer-js"] } } `; }, coreDependencies: [BUILDER_PARCEL_PACKAGE_NAME], defaultOutputDir: "./dist", defaultOutputDirCli: "./bin", description: "The zero configuration build tool", name: "Parcel", optionalDependencies: { minify: [], // Built-in typescript: [BUILDER_TYPESCRIPT_PACKAGE_NAME], }, scripts: { build: "parcel build", dev: "parcel watch", watch: "parcel watch", }, supportedFormats: ["esm", "cjs"], }, [EBuildTool.ROLLUP]: { canSupportCliApps: true, configFileName: "rollup.config.js", configGenerator: (options) => { const { entryPoint, formats, isCliApp, isCommonjsEnabled, isDecoratorsEnabled, isMinifyEnabled, isPackageJsonGenerationEnabled, isPathAliasEnabled, isSourceMapsEnabled, isTypeScript, outputDirectory, } = options; const imports = []; // Base imports imports.push("import resolve from '@rollup/plugin-node-resolve';"); // CommonJS plugin (only if enabled) if (isCommonjsEnabled) { imports.push("import commonjs from '@rollup/plugin-commonjs';"); } // TypeScript plugin if (isTypeScript) { imports.push("import typescript from '@rollup/plugin-typescript';"); } // Optional plugins if (isPathAliasEnabled) { imports.push("import dtsPathAlias from 'rollup-plugin-dts-path-alias';"); } if (isMinifyEnabled) { imports.push("import terser from '@rollup/plugin-terser';"); } if (isPackageJsonGenerationEnabled && !isCliApp) { imports.push("import generatePackageJson from 'rollup-plugin-generate-package-json';"); } // Generate configurations for each format if (isCliApp || formats.length === 1) { // Single configuration const format = formats[0]; const plugins = []; // Resolve plugin with decorators support if (isDecoratorsEnabled) { plugins.push(`resolve({ include: ["node_modules/tslib/**"], })`); } else { plugins.push("resolve()"); } if (isCommonjsEnabled) { plugins.push("commonjs()"); } if (isPathAliasEnabled) { plugins.push("dtsPathAlias()"); } if (isTypeScript) { const tsconfigPath = isCliApp ? "./tsconfig.json" : "./tsconfig.build.json"; plugins.push(`typescript({ declaration: true, outDir: "${outputDirectory}", sourceMap: ${isSourceMapsEnabled}, tsconfig: "${tsconfigPath}", })`); } if (isMinifyEnabled) { plugins.push("terser()"); } const outputOptions = []; if (isCliApp) { outputOptions.push(`banner: "#!/usr/bin/env node"`); } // Determine output file/dir const baseName = path.basename(entryPoint, path.extname(entryPoint)); if (isCliApp) { outputOptions.push(`dir: "${outputDirectory}"`, `preserveModules: true`, `preserveModulesRoot: "src"`); } else { let extension; if (format === "esm") { extension = "mjs"; } else if (format === "cjs") { extension = "cjs"; } else { extension = "js"; } outputOptions.push(`file: "${outputDirectory}/${baseName}.${extension}"`); } outputOptions.push(`format: "${format === "cjs" ? "cjs" : format}"`); if (format === "cjs") { outputOptions.push(`exports: "named"`); } else if (isCliApp && format === "esm") { outputOptions.push(`exports: "auto"`); } outputOptions.push(`sourcemap: ${isSourceMapsEnabled}`); return `${imports.join("\n")} export default { ${isCliApp ? 'external: ["node:fs", "node:fs/promises", "node:path", "node:child_process", "node:util"],\n\t' : ""}input: "${entryPoint}", output: { ${outputOptions.join(",\n\t\t")} }, plugins: [ ${plugins.join(",\n\t\t")} ], }; `; } else { // Multiple configurations for different formats const configs = []; for (const format of formats) { const outputDirectoryFormat = `${outputDirectory}/${format}`; const plugins = []; // Resolve plugin with decorators support if (isDecoratorsEnabled) { plugins.push(`resolve({ include: ["node_modules/tslib/**"], })`); } else { plugins.push("resolve()"); } if (isCommonjsEnabled) { plugins.push("commonjs()"); } if (isPathAliasEnabled) { plugins.push("dtsPathAlias()"); } if (isTypeScript) { plugins.push(`typescript({ declaration: true, declarationDir: "${outputDirectoryFormat}", outDir: "${outputDirectoryFormat}", sourceMap: ${isSourceMapsEnabled}, tsconfig: "./tsconfig.build.json", })`); } if (isMinifyEnabled) { plugins.push("terser()"); } if (isPackageJsonGenerationEnabled) { const packageType = format === "esm" ? "module" : "commonjs"; plugins.push(`generatePackageJson({ baseContents: { type: "${packageType}" }, outputFolder: "${outputDirectoryFormat}", })`); } const entryFileNamesFunction = isDecoratorsEnabled ? `entryFileNames: (chunkInfo) => { if (chunkInfo.name.includes("node_modules")) { return chunkInfo.name.replace("node_modules", "external") + ".js"; } return "[name].js"; },` : ""; configs.push(`{ input: "${entryPoint}", output: { dir: "${outputDirectoryFormat}", ${entryFileNamesFunction} ${format === "cjs" ? 'exports: "named",\n\t\t\t' : ""}format: "${format}", preserveModules: true, preserveModulesRoot: "src", sourcemap: ${isSourceMapsEnabled}, }, plugins: [ ${plugins.join(",\n\t\t\t")} ], }`); } return `${imports.join("\n")} export default [ ${configs.join(",\n\t")} ]; `; } }, coreDependencies: [BUILDER_ROLLUP_PACKAGE_NAME], defaultOutputDir: "./dist", defaultOutputDirCli: "./bin", description: "Next-generation ES module bundler", name: "Rollup", optionalDependencies: { decorators: [BUILDER_TSLIB_PACKAGE_NAME], minify: [BUILDER_ROLLUP_PLUGIN_TERSER], pathAlias: [BUILDER_ROLLUP_PLUGIN_DTS_PATH_ALIAS], typescript: [BUILDER_ROLLUP_PLUGIN_TYPESCRIPT, BUILDER_TSLIB_PACKAGE_NAME], }, scripts: { build: "rollup -c", dev: "rollup -c -w", watch: "rollup -c -w", }, supportedFormats: ["esm", "cjs", "umd", "iife"], }, [EBuildTool.SWC]: { canSupportCliApps: true, configFileName: ".swcrc", configGenerator: (options) => { const { isDecoratorsEnabled, isMinifyEnabled, isSourceMapsEnabled } = options; // SWC uses .swcrc for configuration return `{ "$schema": "https://json.schemastore.org/swcrc", "jsc": { "parser": { "syntax": "typescript", "tsx": true, "decorators": ${isDecoratorsEnabled} }, "target": "es2022", "loose": false, "minify": ${isMinifyEnabled ? `{ "compress": true, "mangle": true }` : "null"} }, "module": { "type": "es6" }, "minify": ${isMinifyEnabled}, "sourceMaps": ${isSourceMapsEnabled} } `; }, coreDependencies: [BUILDER_SWC_CORE_PACKAGE_NAME, BUILDER_SWC_CLI_PACKAGE_NAME], defaultOutputDir: "./dist", defaultOutputDirCli: "./bin", description: "Super-fast TypeScript/JavaScript compiler", name: "SWC", optionalDependencies: { minify: [], // Built-in typescript: [], // Built-in }, scripts: { build: "swc src -d dist", dev: "swc src -d dist --watch", watch: "swc src -d dist --watch", }, supportedFormats: ["esm", "cjs"], }, [EBuildTool.TURBOPACK]: { canSupportCliApps: true, configFileName: "turbopack.config.js", configGenerator: (options) => { const { entryPoint, isMinifyEnabled, isSourceMapsEnabled, outputDirectory } = options; // Turbopack uses a JavaScript config return `export default { entry: { main: "${entryPoint}", }, output: { path: "${outputDirectory}", filename: "[name].js", }, optimization: { minimize: ${isMinifyEnabled}, }, devtool: ${isSourceMapsEnabled ? '"source-map"' : "false"}, }; `; }, coreDependencies: [BUILDER_TURBOPACK_PACKAGE_NAME], defaultOutputDir: "./dist", defaultOutputDirCli: "./bin", description: "Incremental bundler optimized for JavaScript and TypeScript", name: "Turbopack", optionalDependencies: { minify: [], typescript: [BUILDER_TYPESCRIPT_PACKAGE_NAME], }, scripts: { build: "turbopack build", dev: "turbopack dev", watch: "turbopack dev", }, supportedFormats: ["esm", "cjs"], }, [EBuildTool.VITE]: { canSupportCliApps: false, configFileName: "vite.config.js", configGenerator: (options) => { const { entryPoint, formats, isMinifyEnabled, isPathAliasEnabled, isSourceMapsEnabled, isTypeScript, outputDirectory } = options; const plugins = []; if (isPathAliasEnabled && isTypeScript) { plugins.push("viteTsconfigPaths()"); } const formatMap = { esm: "es", umd: "umd", }; return `import { defineConfig } from "vite"; import { resolve } from "path";${isPathAliasEnabled && isTypeScript ? ` import viteTsconfigPaths from "vite-tsconfig-paths";` : ""} export default defineConfig({ build: { lib: { entry: resolve(__dirname, "${entryPoint}"), name: "MyLib", formats: ${JSON.stringify(formats.map((f) => formatMap[f] || f))}, fileName: (format) => \`index.\${format}.js\`, }, outDir: "${outputDirectory}", sourcemap: ${isSourceMapsEnabled}, minify: ${isMinifyEnabled ? '"esbuild"' : "false"}, rollupOptions: { external: [], output: { globals: {}, }, }, },${plugins.length > 0 ? ` plugins: [${plugins.join(", ")}],` : ""} }); `; }, coreDependencies: [BUILDER_VITE_PACKAGE_NAME], defaultOutputDir: "./dist", defaultOutputDirCli: "./bin", description: "Next generation frontend tooling", name: "Vite", optionalDependencies: { minify: [], // Built-in pathAlias: [BUILDER_VITE_TSCONFIG_PATHS_PACKAGE_NAME], typescript: [], // Built-in }, scripts: { build: "vite build", dev: "vite", watch: "vite build --watch", }, supportedFormats: ["esm", "umd"], }, [EBuildTool.WEBPACK]: { canSupportCliApps: true, configFileName: "webpack.config.js", configGenerator: (options) => { const { entryPoint, formats, isCliApp, isMinifyEnabled, isPathAliasEnabled, isSourceMapsEnabled, isTypeScript, outputDirectory } = options; const rules = []; const plugins = []; const imports = ["const path = require('path');"]; if (isTypeScript) { rules.push(`{ test: /\\.tsx?$/, use: 'ts-loader', exclude: /node_modules/, }`); } if (isMinifyEnabled) { imports.push("const TerserPlugin = require('terser-webpack-plugin');"); } if (isPathAliasEnabled && isTypeScript) { imports.push("const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');"); } // Webpack output format mapping const firstFormat = formats[0]; let libraryType; if (firstFormat === "commonjs") { libraryType = "commonjs2"; } else if (firstFormat === "module") { libraryType = "module"; } else { libraryType = "umd"; } return `${imports.join("\n")} module.exports = { entry: '${entryPoint}', mode: 'production', devtool: ${isSourceMapsEnabled ? "'source-map'" : "false"},${isCliApp ? ` target: 'node',` : ""} module: { rules: [${rules.length > 0 ? ` ${rules.join(",\n\t\t\t")}` : ""} ], },${(() => { if (isPathAliasEnabled && isTypeScript) { return ` resolve: { extensions: ['.tsx', '.ts', '.js'], plugins: [new TsconfigPathsPlugin()], },`; } else if (isTypeScript) { return ` resolve: { extensions: ['.tsx', '.ts', '.js'], },`; } else { return ""; } })()} output: { filename: 'index.js', path: path.resolve(__dirname, '${outputDirectory}'), library: { type: '${libraryType}', },${isCliApp ? ` hashbang: true,` : ""} },${isMinifyEnabled ? ` optimization: { minimize: true, minimizer: [new TerserPlugin()], },` : ""}${plugins.length > 0 ? ` plugins: [ ${plugins.join(",\n\t\t")} ],` : ""} }; `; }, coreDependencies: [BUILDER_WEBPACK_PACKAGE_NAME, BUILDER_WEBPACK_CLI_PACKAGE_NAME], defaultOutputDir: "./dist", defaultOutputDirCli: "./bin", description: "Static module bundler for modern JavaScript applications", name: "Webpack", optionalDependencies: { minify: [], // Built-in typescript: [BUILDER_TYPESCRIPT_PACKAGE_NAME], }, scripts: { build: "webpack --mode production", dev: "webpack --mode development --watch", watch: "webpack --mode development --watch", }, supportedFormats: ["esm", "cjs", "umd"], }, }; export { BUILD_TOOL_CONFIG }; //# sourceMappingURL=build-tool-config.constant.js.map