aqu
Version:
🌊 Powerful tool for easy typescript/javascript package development
1,474 lines (1,389 loc) • 70.2 kB
JavaScript
#!/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