UNPKG

aqu

Version:

🌊 Powerful tool for easy typescript/javascript package development

1,474 lines (1,389 loc) • 70.2 kB
#!/usr/bin/env node 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 __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( isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // src/index.ts var import_chalk13 = __toESM(require("chalk")); var import_commander2 = require("commander"); // src/build-utils/buildFromConfig.ts var import_esbuild = require("esbuild"); // src/build-utils/createBuildOptions.ts var import_node_resolve = __toESM(require("@esbuild-plugins/node-resolve")); // src/create-utils/getFolderFromPackageName.ts var getFolderFromPackageName = (name2) => { const matchResult = name2.match(/^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?([a-z0-9-~][a-z0-9-._~]*)$/); if (!matchResult) { return name2; } const [, packageName] = matchResult; if (packageName) { return packageName; } return name2; }; // src/utils/appResolve.ts var import_fs = require("fs"); var import_path = require("path"); var appDir = (0, import_fs.realpathSync)(process.cwd()); var appResolve = (...paths) => (0, import_path.resolve)(appDir, ...paths); // src/build-utils/createBuildOptions.ts var createBuildOptions = async (config) => { const { format, name: name2, cjsMode, input, outdir, outfile, buildOptions, incremental, tsconfig, externalNodeModules } = config; const safeName = getFolderFromPackageName(name2); const normalConfigs = []; const sharedOpts = { keepNames: true, bundle: true, sourcemap: "external", incremental, tsconfig, plugins: [ (0, import_node_resolve.default)({ extensions: [".ts", ".js", ".tsx", ".jsx", ".cjs", ".mjs"], onResolved: (resolved) => { if (externalNodeModules && resolved.includes("node_modules")) { return { external: true }; } return resolved; }, resolveOptions: { preserveSymlinks: config.buildOptions.preserveSymlinks } }) ], ...buildOptions, entryPoints: input, logLevel: "silent" }; if (format.includes("cjs")) { if (cjsMode === "development" || cjsMode === "mixed") { normalConfigs.push({ ...sharedOpts, format: "cjs", outfile: outfile || appResolve(outdir, `${safeName}.cjs.development.js`) }); } if (cjsMode === "production" || cjsMode === "mixed") { normalConfigs.push({ ...sharedOpts, minify: true, format: "cjs", outfile: outfile || appResolve(outdir, `${safeName}.cjs.production.min.js`) }); } } if (format.includes("esm")) { normalConfigs.push({ ...sharedOpts, format: "esm", outfile: outfile || appResolve(outdir, `${safeName}.esm.js`) }); } if (format.includes("iife")) { normalConfigs.push({ ...sharedOpts, format: "iife", outfile: outfile || appResolve(outdir, `${safeName}.js`) }); } return normalConfigs; }; // src/utils/insertArgs.ts var insertArgs = (str, args) => str.replace( /\${\s*((?:\w|\.)+)\s*}/g, (_, paramName) => paramName in args ? args[paramName] : `\${${paramName}}` ); // src/utils/safeWriteFile.ts var import_fs2 = require("fs"); var import_path2 = require("path"); var safeWriteFile = (path, content) => { return new Promise((resolve5, reject) => { (0, import_fs2.writeFile)(path, content, (err) => { if (err) { (0, import_fs2.mkdir)((0, import_path2.parse)(path).dir, { recursive: true }, (err2) => { if (err2) { reject(err2); } else { (0, import_fs2.writeFile)(path, content, (err3) => { if (err3) { reject(err3); } else { resolve5(); } }); } }); } else { resolve5(); } }); }); }; // src/build-utils/createMixedCjsEntrypoint.ts var cjsMixedEntrypoint = `'use strict' if(process.env.NODE_ENV === 'production') { module.exports = require('./\${name}.cjs.production.min.js'); } else { module.exports = require('./\${name}.cjs.development.js'); } `; var createMixedCjsEntrypoint = async (outdir, name2) => { await safeWriteFile( appResolve(outdir, "index.js"), insertArgs(cjsMixedEntrypoint, { name: getFolderFromPackageName(name2) }) ); }; // src/build-utils/emitDeclarations.ts var import_path4 = require("path"); var import_dts_bundle_generator = require("dts-bundle-generator"); // src/build-utils/defaultEmitDeclarations.ts var import_path3 = require("path"); var import_typescript = require("typescript"); var parseConfigHost = { useCaseSensitiveFileNames: import_typescript.sys.useCaseSensitiveFileNames, readDirectory: import_typescript.sys.readDirectory, fileExists: import_typescript.sys.fileExists, readFile: import_typescript.sys.readFile }; var defaultEmitDeclarations = async (config) => { const { outdir, input, tsconfig, incremental } = config; const rawConfig = (0, import_typescript.readConfigFile)(tsconfig, import_typescript.sys.readFile); const specifiedTsconfig = (0, import_typescript.parseJsonConfigFileContent)( rawConfig.config, parseConfigHost, appResolve((0, import_path3.dirname)(tsconfig)), void 0, tsconfig ); const options2 = { ...specifiedTsconfig.options, incremental, declaration: true, emitDeclarationOnly: true, outDir: outdir, noEmit: false }; const host = (0, import_typescript.createCompilerHost)(options2); const program = (0, import_typescript.createProgram)(input, options2, host); program.emit(); }; // src/logger.ts var import_chalk = __toESM(require("chalk")); var import_ora = __toESM(require("ora")); // src/utils/timeFrom.ts var timeFrom = (begin) => { const ms = new Date().getTime() - begin.getTime(); if (ms < 700) { return `${ms}ms`; } else if (ms < 7e3) { return `${(ms / 1e3).toFixed(1)}secs`; } else { return `${Math.round(ms / 1e3)}secs`; } }; // package.json var name = "aqu"; var version = "0.4.2"; var description = "\u{1F30A} Powerful tool for easy typescript/javascript package development"; // src/logger.ts var Progress = class { constructor(label) { this.label = label; this.spinner = (0, import_ora.default)(this.label).start(); this.beginPoint = new Date(); } succeed(label = this.label) { this.spinner.succeed(label + " " + import_chalk.default.gray(timeFrom(this.beginPoint))); } fail(label = this.label) { this.spinner.fail(label + " " + import_chalk.default.gray("failed")); } }; var logger = { error: (...args) => { console.error(import_chalk.default.red(`[${name}]`, ...args)); }, fatal: (...args) => { logger.error(...args); process.exit(1); }, warn: (...args) => { console.warn(import_chalk.default.yellow(`[${name}] WARNING:`), ...args); }, info: (...args) => { console.log(import_chalk.default.gray(`[${name}]:`), ...args); }, success: (...args) => { console.log(import_chalk.default.green(`[${name}]:`, ...args)); } }; var logger_default = logger; // src/messages.json var requiredField = "${path} is required - ${path} was not found in package.json, config file or cli arguments"; var requiredInputField = '${path} is required - "source" field not found in package.json, attempt to select the default ./src/index or ./lib/index also failed'; var unexpectedlyMissingField = "${path} is missing - suddenly, default value of ${path} is not load. This is probably aqu issue, please report about it."; var gracefulShutdownMessage = "\u2728 Shutting down gracefully"; var gracefulShutdownDetails = " Stopping esbuild service and closing watcher"; var configNotFound = "Cannot read config at path ${path}"; var packageNotFound = "package.json not not found (could miss some configuration options)"; var outfileCannotBeSpecified = "Cannot specify outfile because more than one entrypoint will be generated"; var cannotSpecifyMultipleEntrypoints = "Cannot use mixed cjsMode with multiple entrypoints. Please use 1 entrypoint or switch to other cjsMode."; var noOutputPathSpecified = "No output path specified."; var schemaValidationError = "Schema validation failed:"; var compilationStart = "Compilation started."; var compilationSuccess = "Successfully compiled!"; var compilationFailed = "Errors during compilation"; var watchIdle = "\u231A Waiting for changes..."; var notNumberError = 'Specified argument for ${path} - "${value}" is not number'; var noLintDirsSpecifiedError = 'No directories specified. Defaulting to "aqu lint ${dirs}" (entrypoint directories + test dir)'; var lintSuccess = "Successful lint"; var maxWarningsError = "Received ${warningCount} warnings, which is more than specified threshold - ${maxWarnings}. Exiting with code 1."; var licenseNotFound = "License ${license} do not exist"; var templateLoadLoop = 'During "${template}" template load loop found: ${loop}'; var creationOptionNotSpecfied = "${path} is not specified."; var creationOptionInvalid = "${value} is not valid ${path}"; var packageNameNotSpecified = "Package name is not specified."; var packageNameInvalid = "Package name ${name} is invalid"; var folderAlreadyExists = "Folder ${path} already exists"; var requiredCli = "Please enter the value"; var skipped = "skipped"; var notValidUrl = "${value} is not valid URL."; var pickCommandToEject = "Pick command to eject"; var pickCommandToRevert = "Pick command to revert"; var cannotEject = "Cannot eject command ${command}"; var cannotRevert = "Cannot revert command ${command}"; var ejectWarn = "Ejecting ${script} script will result in functionality loss - no declarations will be generated. Continue?"; var ejectPackageScriptWarn = "Found custom script in package.json - ${oldScript}. Do you want to replace it to ${newScript}?"; var revertWarning = "Reverting ${script} will revert ${packageScript} script in package.json and delete these files: ${files}. Continue?"; var noPackageManagersFound = "No package managers found. (none of ${available} currently installed on this machine)"; var pickPackageManager = "Pick package manager:"; var fileExistsWarning = "File ${path} already exists. Do you want to override it?"; var steps = { esbuild: "Bundling using esbuild", dtsBundle: "Generating declaration bundle", dtsStandard: "Emitting declarations", creating: "Creating ${package} using ${template} template...", creationSuccess: "Created ${package}", creationFail: "Create ${package}", skipInstallDeps: "Install dependencies", installingDeps: "Installing dependencies...", installDepsSuccess: "Dependencies intalled", installDepsFail: "Install dependencies", creationFinalize: "\nPackage ${package} successfully created\n\nHappy coding!" }; var additionalHelp = "\n\u2728 Found a bug? Or want to add new feature? Let us know! ${link}\n Let's make ${package} better together!"; var commands = { watch: "Watch project and rebuild on every change", build: "Bundle project using esbuild", test: "Run jest. (passes all rest cli arguments into jest)", lint: "Lint using eslint", create: "Create new package", eject: "Eject command. (if you want to do additional customizations)", revert: "Revert command eject. (will revert do initial command)" }; var options = { watchdir: "Specify custom watching directories", nosym: "do not follow symlinks", ignore: "Specify paths which will be ignored while watching", config: "Specify path to configuration", maxWarnings: "Number of warnings to trigger nonzero exit code. Default: infinity", fix: "Automatically fix problems", fixDryRun: "Automatically fix problems without saving the changes to the file system", cache: "Only check changed files. Default: false", cacheLocation: "Path to the cache file or directory", reportFile: "Specify file to write report to", description: "Specify custom package description", author: "Set package author", repo: "Specify package repository", license: "Pick package license. Default: MIT", template: "Pick package template. Default: typescript", yes: "Yes to all - Pick all default options", name: "Specify custom package name", input: "Entrypoints to your file. By default, will pick index file in src or lib folder", outdir: "Output directory of your build", outfile: "Output file of your bundle", format: "Output format. Available options: esm, cjs and iife. Default: esm and cjs", cjsMode: "CommonJS module generation mode. Available options: development, production and mixed. Default: mixed.", declaration: "Algorithm to emit declarations. Available options: none, normal and bundle. Default: bundle", tsconfig: "Path to tsconfig. Default: tsconfig.json in current working directory.", incremental: "Build incrementally. Default: true", noExternal: "Should include node_modules packages into bundle? Default: false", noCleanup: "Do not delete output folder before build" }; var createQuestions = { name: "Package name:", description: "Specify package description:", author: "Package author:", repo: "Git repository (only for package.json information):", license: "Pick license:", template: "Pick template:" }; // src/build-utils/emitDeclarations.ts var canHaveDeclarations = (filePath) => [".ts", ".tsx"].includes((0, import_path4.extname)(filePath)); var emitDeclarations = async (config) => { const { input, declaration, outfile, outdir, name: name2, tsconfig, dtsBundleGeneratorOptions, buildOptions } = config; if (input.some(canHaveDeclarations)) { if (declaration === "bundle") { const dtsProgress = new Progress(steps.dtsBundle); try { await Promise.all( (0, import_dts_bundle_generator.generateDtsBundle)( input.filter(canHaveDeclarations).map((entry) => ({ ...dtsBundleGeneratorOptions, filePath: entry })), { preferredConfigPath: tsconfig, followSymlinks: !buildOptions.preserveSymlinks } ).map((bundle) => { return safeWriteFile( outfile ? `${outfile.substring(0, outfile.lastIndexOf("."))}.d.ts` : appResolve(outdir, `${getFolderFromPackageName(name2)}.d.ts`), bundle ); }) ); dtsProgress.succeed(); } catch (err) { dtsProgress.fail(); throw err; } } else if (declaration === "normal") { const dtsProgress = new Progress(steps.dtsStandard); try { await defaultEmitDeclarations(config); dtsProgress.succeed(); } catch (err) { dtsProgress.fail(); throw err; } } } }; // src/build-utils/showSkippedStep.ts var import_chalk2 = __toESM(require("chalk")); var showSkippedStep = (label) => console.log(import_chalk2.default.yellow("\u2193"), label, import_chalk2.default.gray(skipped)); // src/utils/runWithESBuildBinaryContext.ts var runWithESBuildBinaryContext = async (run2) => { return await run2(); }; // src/build-utils/buildFromConfig.ts var buildFromConfig = async (config) => { const { cjsMode, outdir, name: name2, format, declaration } = config; if (format.includes("cjs") && cjsMode === "mixed") { createMixedCjsEntrypoint(outdir, name2); } const buildConfigs = await createBuildOptions(config); const esbuildProgress = new Progress(steps.esbuild); try { await runWithESBuildBinaryContext(() => Promise.all(buildConfigs.map((config2) => (0, import_esbuild.build)(config2)))); esbuildProgress.succeed(); } catch (err) { esbuildProgress.fail(); if (declaration !== "none") { showSkippedStep(declaration === "bundle" ? steps.dtsBundle : steps.dtsStandard); } throw err; } await emitDeclarations(config); }; // src/utils/deleteBuildDirs.ts var import_uniq = __toESM(require("lodash/uniq")); var import_rimraf = __toESM(require("rimraf")); var deleteBuildDirs = (configs) => { const folders = (0, import_uniq.default)(configs.map((value) => appResolve(value.outdir))); return Promise.all( folders.map( (folder) => new Promise( (resolve5) => (0, import_rimraf.default)(folder, (error) => { if (error) { logger_default.error(error); } resolve5(); }) ) ) ); }; // src/commands/build.ts var buildCommand = { name: "build", description: commands.build, options: [ { flag: { full: "no-cleanup" }, description: options.noCleanup } ], action: async (options2, config) => { if (!options2.NoCleanup) { await deleteBuildDirs(config); } try { await Promise.all(config.map((config2) => buildFromConfig(config2))); } catch (err) { logger_default.fatal(err); } finally { process.exit(); } } }; var build_default = buildCommand; // src/commands/create.ts var import_chalk6 = __toESM(require("chalk")); var import_inquirer2 = __toESM(require("inquirer")); var Yup2 = __toESM(require("yup")); // src/create-utils/createFromConfig.ts var import_chalk5 = __toESM(require("chalk")); // src/create-utils/createLicense.ts var import_path5 = require("path"); var import_fs_extra = require("fs-extra"); var createLicense = async (license, path, author) => { const licensePath = (0, import_path5.join)(__dirname, "..", "licenses", `${license}.txt`); const licenseExists = await (0, import_fs_extra.pathExists)(licensePath); if (!licenseExists) { throw new Error(insertArgs(licenseNotFound, { license })); } const content = await (0, import_fs_extra.readFile)(licensePath); await (0, import_fs_extra.writeFile)( path, insertArgs(content.toString(), { author, year: new Date().getFullYear() }) ); }; // src/create-utils/installDependencies.ts var import_path6 = require("path"); var import_execa2 = __toESM(require("execa")); var import_fs_extra2 = require("fs-extra"); // src/utils/packageManager.ts var import_chalk3 = __toESM(require("chalk")); var import_execa = __toESM(require("execa")); var import_inquirer = __toESM(require("inquirer")); var packageManager = null; var checkPackageManager = async (name2) => { try { const { stdout } = await (0, import_execa.default)(name2, ["-v"]); return { name: name2, version: stdout.trim() }; } catch { return void 0; } }; var managers = ["npm", "yarn", "pnpm"]; var findAllInstalledManagers = async () => { const available = await Promise.all(managers.map((manager) => checkPackageManager(manager))); return available.filter(Boolean); }; var getPackageManager = async () => { if (packageManager !== null) { return packageManager; } const available = await findAllInstalledManagers(); if (available.length === 0) { logger_default.fatal( insertArgs(noPackageManagersFound, { available: import_chalk3.default.bold.red(managers.join(", ")) }) ); } packageManager = available[0].name.trim(); return packageManager; }; var pickPackageManager2 = async () => { if (packageManager !== null) { return packageManager; } const availableManagers = await findAllInstalledManagers(); if (availableManagers.length === 0) { logger_default.fatal( insertArgs(noPackageManagersFound, { available: import_chalk3.default.bold.red(managers.join(", ")) }) ); } if (availableManagers.length === 1) { packageManager = availableManagers[0].name; return packageManager; } const out = await import_inquirer.default.prompt({ message: pickPackageManager, type: "list", name: "manager", choices: availableManagers.map((manager) => `${manager.name} ${import_chalk3.default.gray(`(${manager.version})`)}`) }); packageManager = out.manager.split(" ")[0].trim(); return packageManager; }; // src/create-utils/installDependencies.ts var installDependencies = async (name2) => { await (0, import_execa2.default)(await getPackageManager(), ["install"], { cwd: (0, import_path6.resolve)(process.cwd(), name2) }); const exampleFolder = (0, import_path6.resolve)(process.cwd(), name2, "example"); if (await (0, import_fs_extra2.pathExists)(exampleFolder)) { await (0, import_execa2.default)(await getPackageManager(), ["install"], { cwd: exampleFolder }); } }; // src/create-utils/loadTemplate.ts var import_path9 = require("path"); // src/create-utils/copyTemplate.ts var import_path7 = require("path"); var import_fs_extra4 = require("fs-extra"); // src/utils/mergeFiles.ts var import_fs_extra3 = require("fs-extra"); // src/utils/deepMerge.ts var import_webpack_merge = require("webpack-merge"); var customizedMerge = (0, import_webpack_merge.mergeWithCustomize)({ customizeArray: (_, b) => b }); var deepMerge = (firstObject, ...objects) => { if (Array.isArray(firstObject) && objects.length === 0) { firstObject = firstObject.filter(Boolean); } objects = objects.filter(Boolean); return customizedMerge(firstObject, ...objects); }; // src/utils/mergeFiles.ts var mergeFiles = async (first, second) => { const [firstFile, secondFile] = await Promise.all([(0, import_fs_extra3.readJson)(first), (0, import_fs_extra3.readJson)(second)]); return deepMerge(firstFile, secondFile); }; // src/create-utils/copyTemplate.ts var banFiles = ["aqu.template.js"]; var copyTemplate = async (from, to, options2, args) => { await (0, import_fs_extra4.ensureDir)(to); const { filesToMergePaths = [], templateFilePaths = [] } = options2; const templateFiles = await (0, import_fs_extra4.readdir)(from); const existingFiles = await (0, import_fs_extra4.readdir)(to); const isDirs = await Promise.all( templateFiles.map((file) => (0, import_fs_extra4.stat)((0, import_path7.join)(from, file)).then((fileStats) => fileStats.isDirectory())) ); await Promise.all( templateFiles.map(async (templateFile, index) => { if (banFiles.includes(templateFile)) return; const resolvedPath = (0, import_path7.resolve)(to, templateFile); if (isDirs[index]) { await copyTemplate((0, import_path7.join)(from, templateFile), (0, import_path7.join)(to, templateFile), options2, args); } else if (existingFiles.includes(templateFile) && filesToMergePaths.includes(resolvedPath)) { const file = await mergeFiles((0, import_path7.join)(to, templateFile), (0, import_path7.join)(from, templateFile)); let contents = JSON.stringify(file, null, 2); if (templateFilePaths.includes(resolvedPath)) { contents = insertArgs(contents, args); } await (0, import_fs_extra4.writeFile)((0, import_path7.join)(to, templateFile), contents); } else if (templateFilePaths.includes(resolvedPath)) { const contents = await (0, import_fs_extra4.readFile)((0, import_path7.join)(from, templateFile)); await (0, import_fs_extra4.writeFile)((0, import_path7.join)(to, templateFile), insertArgs(contents.toString(), args)); } else { await (0, import_fs_extra4.copy)((0, import_path7.join)(from, templateFile), (0, import_path7.join)(to, templateFile)); } }) ); }; // src/config/getDefaultFromCjs.ts var getDefaultFromCjs = (requiredModule) => { if (requiredModule.__esModule) { return requiredModule.default; } else { return requiredModule; } }; // src/config/getRawConfigFromCjs.ts var getRawConfigFromCjs = (path) => { try { const config = require(path); return getDefaultFromCjs(config); } catch (err) { logger_default.fatal(err); } }; // src/constants.ts var import_path8 = require("path"); var CONFIG_EXTENSIONS = ["ts", "js", "mjs", "cjs", "json"]; var CONFIG_NAMES = [...CONFIG_EXTENSIONS.map((ext) => `aqu.config.${ext}`), ".aqurc"]; var ENTRYPOINT_EXTENSIONS = ["ts", "tsx", "js", "jsx", "cjs", "mjs"]; var AVAILABLE_OUTPUT_FORMATS = ["iife", "cjs", "esm"]; var AVAILABLE_CJS_MODES = ["production", "development", "mixed"]; var AVAILABLE_DECLARATION_MODES = ["bundle", "normal", "none"]; var templatesPath = (0, import_path8.resolve)(__dirname, "templates"); var availableForEjectCommands = ["build", "watch", "lint", "test"]; var DEFAULT_OPTIONS = { format: ["cjs", "esm"], cjsMode: "mixed", outdir: "dist", declaration: "bundle", externalNodeModules: true, tsconfig: appResolve("tsconfig.json"), incremental: true, buildOptions: {}, watchOptions: { ignored: ["node_modules/**", "dist/**", "build/**", "out/**"], followSymlinks: false } }; // src/utils/assert.ts function assert(condition, message) { if (condition) { return; } logger_default.fatal("Assertion error:", message); } // src/create-utils/loadTemplate.ts var loadTemplate = async (templateOptions, githubUser, loadedTemplates = /* @__PURE__ */ new Set()) => { const { name: name2, template } = templateOptions; const folder = getFolderFromPackageName(name2); loadedTemplates.add(template); const scriptPath = (0, import_path9.join)(templatesPath, template, "aqu.template.js"); let options2 = {}; try { const templateScript = await getRawConfigFromCjs(scriptPath); options2 = await templateScript.initialize(await getPackageManager()); if (options2.templateFilePaths) { options2.templateFilePaths = options2.templateFilePaths.map((path) => appResolve(folder, path)); } if (options2.filesToMergePaths) { options2.filesToMergePaths = options2.filesToMergePaths.map((path) => appResolve(folder, path)); } } catch (err) { logger_default.error(err); } if (options2.extend) { assert( !loadedTemplates.has(options2.extend), insertArgs(templateLoadLoop, { template, loop: [...Array.from(loadedTemplates), options2.extend].join(" \u2192 ") }) ); await loadTemplate({ ...templateOptions, template: options2.extend }, githubUser, loadedTemplates); } await copyTemplate((0, import_path9.join)(templatesPath, template), (0, import_path9.join)(process.cwd(), folder), options2, { ...templateOptions, ...options2.customArgs, safeName: getFolderFromPackageName(name2), githubUser }); }; // src/create-utils/verifyCreateOptions.ts var Yup = __toESM(require("yup")); // src/create-utils/verifyPackageName.ts var import_chalk4 = __toESM(require("chalk")); var import_fs_extra5 = require("fs-extra"); var import_yup = require("yup"); var verifyPackageName = (name2) => (0, import_yup.string)().required(packageNameNotSpecified).matches( /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/, insertArgs(packageNameInvalid, { name: import_chalk4.default.bold.red("${value}") }) ).test( (value, { createError }) => (0, import_fs_extra5.pathExists)(appResolve(getFolderFromPackageName(value))).then( (exists) => exists ? createError({ message: insertArgs(folderAlreadyExists, { path: import_chalk4.default.bold.red(value) }) }) : true ) ).validate(name2 != null ? name2 : "").then(() => true).catch((err) => err); // src/create-utils/verifyCreateOptions.ts var verifyCreateOptions = async (obj, availableLicenses, availableTemplates) => { const createOptionsSchema = Yup.object().shape({ name: Yup.string().test(verifyPackageName), description: Yup.string().notRequired(), author: Yup.string().required(creationOptionNotSpecfied), repo: Yup.string().url().required(creationOptionNotSpecfied), license: Yup.string().required(creationOptionNotSpecfied).oneOf(availableLicenses, creationOptionInvalid), template: Yup.string().required(creationOptionNotSpecfied).oneOf(availableTemplates, creationOptionInvalid) }); try { await createOptionsSchema.validate(obj); } catch (err) { if (err instanceof Yup.ValidationError) { logger_default.fatal(schemaValidationError, err.message); } logger_default.fatal(err); } }; // src/create-utils/createFromConfig.ts var createFromConfig = async (options2, githubUser, availableLicenses, availableTemplates) => { await verifyCreateOptions(options2, availableLicenses, availableTemplates); console.log(); const creationProgress = new Progress( insertArgs(steps.creating, { package: import_chalk5.default.bold.cyan(options2.name), template: import_chalk5.default.cyan(options2.template) }) ); try { await loadTemplate(options2, githubUser); await createLicense(options2.license, appResolve(getFolderFromPackageName(options2.name), "LICENSE"), options2.author); creationProgress.succeed( insertArgs(steps.creationSuccess, { package: import_chalk5.default.bold.green(options2.name) }) ); } catch (err) { creationProgress.fail( insertArgs(steps.creationFail, { package: import_chalk5.default.bold.red(options2.name) }) ); showSkippedStep(steps.skipInstallDeps); logger_default.fatal(err); } const installProgress = new Progress(steps.installingDeps); try { await installDependencies(getFolderFromPackageName(options2.name)); installProgress.succeed(steps.installDepsSuccess); } catch (err) { installProgress.fail(steps.installDepsFail); logger_default.fatal(err); } console.log( insertArgs(steps.creationFinalize, { package: import_chalk5.default.bold.cyan(options2.name) }) ); console.log(); }; // src/create-utils/getAllLicenses.ts var import_path10 = require("path"); var import_fs_extra6 = require("fs-extra"); var getAllLicenses = async () => { const pathToLicensesFolder = (0, import_path10.join)(__dirname, "..", "licenses"); const licenses = await (0, import_fs_extra6.readdir)(pathToLicensesFolder); return licenses.map((licenseName) => licenseName.substring(0, licenseName.lastIndexOf("."))); }; // src/create-utils/getAllTemplates.ts var import_fs_extra7 = require("fs-extra"); var getAllTemplates = () => (0, import_fs_extra7.readdir)(templatesPath).then((files) => files.filter((template) => template.charAt(0) !== "_")); // src/utils/getAuthor.ts var import_execa3 = __toESM(require("execa")); var getAuthor = async () => { const nameCandidates = await Promise.all([ (0, import_execa3.default)(await getPackageManager(), ["config", "get", "init-author-name"]).then(({ stdout }) => stdout).catch(() => void 0), (0, import_execa3.default)("git", ["config", "--global", "--get", "user.name"]).then(({ stdout }) => stdout).catch(() => void 0) ]); const name2 = nameCandidates.find((element) => element !== "undefined" && Boolean(element)); const email = await (0, import_execa3.default)("git", ["config", "--global", "--get", "user.email"]).then(({ stdout }) => stdout).catch(() => void 0); return name2 ? email ? `${name2} <${email}>` : name2 : ""; }; // src/create-utils/getPackageScope.ts var getPackageScope = (name2) => { const matchResult = name2.match(/^(?:@([a-z0-9-*~][a-z0-9-*._~]*)\/)?[a-z0-9-~][a-z0-9-._~]*$/); if (!matchResult) { return name2; } const [, scope] = matchResult; if (scope) { return scope; } return name2; }; // src/utils/getDefaultRepo.ts var getDefaultRepo = (name2, user) => { if (user) { return `https://github.com/${user}/${getPackageScope(name2)}`; } return void 0; }; // src/utils/getGithubUser.ts var import_execa4 = __toESM(require("execa")); var import_github_username = __toESM(require("github-username")); var getGithubUser = async () => { const [githubUser, email] = await Promise.all([ (0, import_execa4.default)("git", ["config", "--global", "--get", "github.user"]).then((value) => value.stdout.trim()).catch(() => void 0), (0, import_execa4.default)("git", ["config", "--global", "--get", "user.email"]).then((value) => value.stdout.trim()).catch(() => void 0) ]); if (githubUser) { return githubUser; } else if (email) { return await (0, import_github_username.default)(email).catch(() => void 0); } return void 0; }; // src/commands/create.ts var title = ` ___ ___ ___ /\\ \\ /\\ \\ /\\__\\ /::\\ \\ /::\\ \\ /:/ _/_ /::\\:\\__\\ \\:\\:\\__\\ /:/_/\\__\\ \\/\\::/ / \\::/ / \\:\\/:/ / /:/ / /:/ / \\::/ / \\/__/ \\/__/ \\/__/ `; var createCommand = { name: "create", description: commands.create, options: [ { flag: { full: "description", short: "d", placeholder: "value" }, description: options.description }, { flag: { full: "author", short: "a", placeholder: "name" }, description: options.author }, { flag: { full: "repo", short: "r", placeholder: "url" }, description: options.repo }, { flag: { full: "license", short: "l", placeholder: "value" }, description: options.license }, { flag: { full: "template", short: "t", placeholder: "value" }, description: options.template }, { flag: { full: "yes", short: "y" }, description: options.yes } ], action: async (args, _, command) => { var _a, _b; console.log(import_chalk6.default.cyan(title)); if (!args.yes) { await pickPackageManager2(); } const name2 = command.args[0]; const githubUser = await getGithubUser(); const availableLicenses = await getAllLicenses(); const availableTemplates = await getAllTemplates(); const defaults = { name: name2, description: "", author: (_a = await getAuthor()) != null ? _a : "", repo: ({ name: name3 }) => getDefaultRepo(name3, githubUser), license: "MIT", template: "typescript" }; let options2; if (!args.yes) { options2 = await import_inquirer2.default.prompt( [ { type: "input", name: "name", message: createQuestions.name, validate: (input) => verifyPackageName(input).then((value) => typeof value === "boolean" ? value : value.message) }, { type: "input", name: "description", message: createQuestions.description, default: defaults.description }, { type: "input", name: "author", message: createQuestions.author, default: defaults.author, validate: (input) => Yup2.string().required(requiredCli).validate(input).then(() => true).catch((err) => err.message) }, { type: "input", name: "repo", message: createQuestions.repo, default: defaults.repo, validate: (input) => Yup2.string().required(requiredCli).url( insertArgs(notValidUrl, { value: import_chalk6.default.bold.red("${value}") }) ).validate(input).then(() => true).catch((err) => err.message) }, { type: "list", name: "license", message: createQuestions.license, default: defaults.license, choices: availableLicenses }, { type: "list", name: "template", message: createQuestions.template, default: defaults.template, choices: availableTemplates } ], { ...args, name: name2 } ); } else { options2 = { ...defaults, repo: (_b = defaults.repo(defaults)) != null ? _b : "", ...args }; } await createFromConfig(options2, githubUser, availableLicenses, availableTemplates); } }; var create_default = createCommand; // src/commands/eject.ts var import_chalk9 = __toESM(require("chalk")); var import_inquirer7 = require("inquirer"); // src/eject-utils/ejectBuild.ts var import_inquirer5 = require("inquirer"); // src/eject-utils/ejectNewScript.ts var import_path11 = require("path"); var import_flatten = __toESM(require("lodash/flatten")); // src/utils/writeFileWithWarning.ts var import_chalk7 = __toESM(require("chalk")); var import_inquirer3 = require("inquirer"); // src/utils/canReadFile.ts var import_fs_extra8 = require("fs-extra"); var canReadFile = (path) => (0, import_fs_extra8.pathExists)(path); // src/utils/writeFileWithWarning.ts var writeFileWithWarning = async (filename, content, skipWarning) => { const path = appResolve(filename); if (!skipWarning && await canReadFile(path)) { const result = await (0, import_inquirer3.prompt)({ name: "continue", message: insertArgs(fileExistsWarning, { path: import_chalk7.default.bold.yellow(filename) }), type: "confirm" }); if (!result.continue) { process.exit(0); } } await safeWriteFile(path, content); }; // src/eject-utils/ejectNewScript.ts var ejectNewScript = async (path, text, configs, skipWarning) => { const buildConfigs = (0, import_flatten.default)(await Promise.all(configs.map((config) => createBuildOptions(config)))); buildConfigs.map((config) => { var _a; config.plugins = (_a = config.plugins) == null ? void 0 : _a.map( (plugin) => plugin.name === "node-resolve" ? "${nodeResolve}" : plugin ); delete config.logLevel; }); const newText = insertArgs(text, { configs: insertArgs( JSON.stringify( buildConfigs, (key, value) => { if (["outdir", "outfile", "tsconfig"].includes(key)) { return (0, import_path11.relative)(appDir, value); } if (key === "entryPoints") { return value.map((entrypoint) => (0, import_path11.relative)(appDir, entrypoint)); } return value; }, 2 ).replace(/"\$\{nodeResolve\}"/g, "${nodeResolve}"), { nodeResolve: "nodeResolveExternal" } ) }); await writeFileWithWarning(path, newText, skipWarning); }; // src/eject-utils/ejectPackageScript.ts var import_chalk8 = __toESM(require("chalk")); var import_fs_extra9 = require("fs-extra"); var import_inquirer4 = require("inquirer"); var ejectPackageScript = async (script, defaultScript, newScript, skipWarning) => { try { const appPackagePath = appResolve("package.json"); const appPackage = await (0, import_fs_extra9.readJSON)(appPackagePath); if (appPackage.scripts && appPackage.scripts[script] && appPackage.scripts[script].trim() === newScript.trim()) { return; } if (!skipWarning && appPackage.scripts && appPackage.scripts[script] && appPackage.scripts[script].trim() !== defaultScript.trim()) { const result = await (0, import_inquirer4.prompt)({ name: "confirm", message: insertArgs(ejectPackageScriptWarn, { oldScript: import_chalk8.default.cyan(`"${appPackage.scripts[script]}"`), newScript: import_chalk8.default.bold.cyan(`"${newScript}"`) }), type: "confirm" }); if (!result.confirm) { return; } } if (!appPackage.scripts) { appPackage.scripts = {}; } appPackage.scripts[script] = newScript; await (0, import_fs_extra9.writeJSON)(appPackagePath, appPackage, { spaces: 2 }); } catch (err) { } }; // src/utils/lowPriorityWriteFile.ts var lowPriorityWriteFile = async (filename, content) => { if (!await canReadFile(filename)) { await safeWriteFile(filename, content); } }; // src/eject-utils/ejectBuild.ts var buildScriptSource = ` var esbuild = require('esbuild'); var NodeResolve = require('@esbuild-plugins/node-resolve').default; var rimraf = require('rimraf'); var path = require('path'); var nodeResolveExternal = NodeResolve({ extensions: ['.ts', '.js', '.tsx', '.jsx', '.cjs', '.mjs'], onResolved: (resolved) => { if (resolved.includes('node_modules')) { return { external: true, }; } return resolved; }, }); var configurations = \${configs}; function asyncRimraf(path) { return new Promise((resolve, reject) => { rimraf(path, (err) => { if (err) { reject(err); } else { resolve(); } }); }); } function main() { Promise.all( configurations.map((config) => { var dir = config.outdir || path.dirname(config.outfile); asyncRimraf(dir).catch(() => { console.log('Unable to delete directory', dir); }); }), ).then(() => { Promise.all(configurations.map((config) => esbuild.build(config))) .then(() => { console.log('\u2714 Build successfull'); process.exit(0); }) .catch((err) => { console.error('\u274C Build failed'); process.exit(1); }); }); } main(); `; var buildEslintConfig = { root: false, env: { node: true }, rules: { "no-console": "off", "@typescript-eslint/no-var-requires": "off" } }; var ejectBuild = async (configs, skipAllWarnings) => { if (!skipAllWarnings) { const result = await (0, import_inquirer5.prompt)({ type: "confirm", message: insertArgs(ejectWarn, { script: "build" }), name: "confirm" }); if (!result.confirm) { return; } } await ejectNewScript("./scripts/build.js", buildScriptSource, configs, skipAllWarnings); await ejectPackageScript("build", "aqu build", "node ./scripts/build.js", skipAllWarnings); await lowPriorityWriteFile(appResolve("./scripts/.eslintrc"), JSON.stringify(buildEslintConfig, null, 2)); }; // src/eject-utils/ejectConfig.ts var ejectConfig = async (filename, config, skipWarning) => { await writeFileWithWarning(filename, JSON.stringify(config, null, 2), skipWarning); }; // src/utils/hasReact.ts var import_fs3 = require("fs"); var hasReact = async () => new Promise((resolve5) => { (0, import_fs3.readFile)(appResolve("package.json"), (err, data) => { if (err) { resolve5(false); } else { const appPackage = JSON.parse(data.toString()); resolve5( appPackage.dependencies && appPackage.dependencies.react || appPackage.devDependencies && appPackage.devDependencies.react || appPackage.peerDependencies && appPackage.peerDependencies.react || appPackage.alias && appPackage.alias.react ); } }); }); // src/config/createEslintConfig.ts var createEslintConfig = async () => { const isReacted = await hasReact(); const config = { root: true, parser: "@typescript-eslint/parser", parserOptions: { ecmaVersion: 2020, sourceType: "module", ecmaFeatures: { jsx: isReacted ? true : void 0 } }, plugins: ["@typescript-eslint", "simple-import-sort"], extends: [ "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended" ], rules: { "@typescript-eslint/no-namespace": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/ban-types": "off", "no-console": "warn", "prettier/prettier": [ "error", { endOfLine: "auto" } ], "simple-import-sort/imports": [ "warn", { groups: [ [ "^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)" ], [...isReacted ? ["^react", "^react-dom", "^react-native"] : [], "^@?\\w"], ["^\\u0000"], ["^src", "^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$", "^\\.\\.(?!/?$)", "^\\.\\./?$"], isReacted && ["^.+\\.s?css$"] ].filter(Boolean) } ] } }; if (isReacted) { config.settings = { react: { version: "detect" } }; config.rules["react/prop-types"] = "off"; config.rules["react/display-name"] = "off"; } return config; }; // src/eject-utils/ejectLint.ts var ejectLint = async (skipAllWarnings) => { await ejectConfig(".eslintrc", await createEslintConfig(), skipAllWarnings); await ejectPackageScript("lint", "aqu lint", "eslint .", skipAllWarnings); }; // src/utils/getInputDirs.ts var import_path12 = require("path"); var import_uniq2 = __toESM(require("lodash/uniq")); var getInputDirs = (configs) => { const dirs = []; configs.forEach((config) => dirs.push(...config.input.map((entrypoint) => (0, import_path12.parse)(entrypoint).dir))); return (0, import_uniq2.default)(dirs); }; // src/config/createJestConfig.ts var createJestConfig = (configs) => ({ transformIgnorePatterns: ["[/\\\\]node_modules[/\\\\].+\\.(js|cjs|jsx)$'"], rootDir: process.cwd(), preset: "ts-jest/presets/js-with-babel", moduleFileExtensions: ["ts", "tsx", "js", "jsx", "cjs", "mjs", "json", "node"], collectCoverageFrom: getInputDirs(configs).map((dir) => `${dir}/**/*.{ts,tsx,js,jsx,cjs,mjs}`), testMatch: ["<rootDir>/**/*.(spec|test).{ts,tsx,js,jsx,cjs,mjs}"], testURL: "http://localhost", watchPlugins: [require.resolve("jest-watch-typeahead/filename"), require.resolve("jest-watch-typeahead/testname")] }); // src/eject-utils/ejectTest.ts var ejectTest = async (configs, skipAllWarnings) => { await ejectConfig("jest.config.json", await createJestConfig(configs), skipAllWarnings); await ejectPackageScript("test", "aqu test", "jest", skipAllWarnings); }; // src/eject-utils/ejectWatch.ts var import_inquirer6 = require("inquirer"); var buildScriptSource2 = ` var esbuild = require('esbuild'); var NodeResolve = require('@esbuild-plugins/node-resolve').default; var rimraf = require('rimraf'); var path = require('path'); var nodeResolveExternal = NodeResolve({ extensions: ['.ts', '.js', '.tsx', '.jsx', '.cjs', '.mjs'], onResolved: (resolved) => { if (resolved.includes('node_modules')) { return { external: true, }; } return resolved; }, }); var configurations = \${configs}; function asyncRimraf(path) { return new Promise((resolve, reject) => { rimraf(path, (err) => { if (err) { reject(err); } else { resolve(); } }); }); } function main() { Promise.all( configurations.map((config) => { var dir = config.outdir || path.dirname(config.outfile); asyncRimraf(dir).catch(() => { console.log('Unable to delete directory', dir); }); }), ).then(() => { configurations.forEach((config) => esbuild.build({ ...config, watch: true })); }); } main(); `; var ejectWatch = async (configs, skipAllWarnings) => { if (!skipAllWarnings) { const result = await (0, import_inquirer6.prompt)({ type: "confirm", message: insertArgs(ejectWarn, { script: "watch" }), name: "confirm" }); if (!result.confirm) { return; } } await ejectNewScript("./scripts/watch.js", buildScriptSource2, configs, skipAllWarnings); await ejectPackageScript("start", "aqu watch", "node ./scripts/watch.js", skipAllWarnings); await lowPriorityWriteFile(appResolve("./scripts/.eslintrc"), JSON.stringify(buildEslintConfig, null, 2)); }; // src/commands/eject.ts var ejectCommand = { name: "eject", description: commands.eject, options: [ { flag: { full: "yes", short: "y" }, description: options.yes } ], action: async ({ yes }, configs, command) => { let commandToEject = command.args[0]; if (!commandToEject) { const result = await (0, import_inquirer7.prompt)({ name: "target", type: "list", message: pickCommandToEject, choices: availableForEjectCommands }); commandToEject = result.target; } switch (commandToEject) { case "lint": await ejectLint(yes); break; case "test": await ejectTest(configs, yes); break; case "build": await ejectBuild(configs, yes); break; case "watch": await ejectWatch(configs, yes); break; default: logger_default.fatal( insertArgs(cannotEject, { command: import_chalk9.default.bold.red(commandToEject) }) ); } } }; var eject_default = ejectCommand; // src/commands/lint.ts var import_path14 = require("path"); var import_eslint = require("eslint"); // src/config/getConfigFromPackage.ts var import_fs4 = require("fs"); var getConfigFromPackage = (packageProp) => new Promise( (resolve5) => (0, import_fs4.readFile)(appResolve("package.json"), (err, data) => { if (err) { resolve5(void 0); } else { resolve5(JSON.parse(data.toString())[packageProp]); } }) ); // src/config/getRawConfig.ts var import_fs5 = require("fs"); var import_path13 = require("path"); // src/config/transpileAndGetRawConfig.ts var import_esbuild2 = require("esbuild"); function evaluateCommonjsModule(code) { const exports = {}; const module = { exports }; eval(code); return module.exports