mirror of
https://github.com/zuiidea/antd-admin
synced 2026-11-04 09:04:02 +00:00
feat(create): wire CLI entry and create command pipeline
Made-with: Cursor
This commit is contained in:
@@ -1,2 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
console.log("create-antd-admin stub");
|
||||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { Command, Option } from "commander";
|
||||
import pc from "picocolors";
|
||||
import { runCreate } from "./commands/create.js";
|
||||
import { EXIT_ERROR, EXIT_SIGINT } from "./constants.js";
|
||||
import { CliError } from "./errors.js";
|
||||
|
||||
const pkg = JSON.parse(
|
||||
readFileSync(
|
||||
path.join(path.dirname(fileURLToPath(import.meta.url)), "../package.json"),
|
||||
"utf8"
|
||||
)
|
||||
) as { version: string };
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name("create-antd-admin")
|
||||
.description("Create an Antd Admin app from official examples")
|
||||
.version(pkg.version, "-v, --version")
|
||||
.argument("[project-directory]", "Directory for the new project")
|
||||
.option("-e, --example <name|url>", "Example name or template URL")
|
||||
.option("--example-path <path>", "Path inside repo when URL is ambiguous")
|
||||
.addOption(
|
||||
new Option("-m, --package-manager <pm>", "Package manager").choices([
|
||||
"npm",
|
||||
"yarn",
|
||||
"pnpm",
|
||||
"bun",
|
||||
])
|
||||
)
|
||||
.option("--skip-install", "Skip installing dependencies", false)
|
||||
.option("--skip-transforms", "Skip code transforms", false)
|
||||
.option("--no-git", "Skip git repository initialization")
|
||||
.action(
|
||||
async (
|
||||
projectDirectory: string | undefined,
|
||||
cmdOpts: {
|
||||
example?: string;
|
||||
examplePath?: string;
|
||||
packageManager?: "npm" | "yarn" | "pnpm" | "bun";
|
||||
skipInstall?: boolean;
|
||||
skipTransforms?: boolean;
|
||||
git?: boolean;
|
||||
}
|
||||
) => {
|
||||
try {
|
||||
await runCreate({
|
||||
projectDirectory,
|
||||
example: cmdOpts.example,
|
||||
examplePath: cmdOpts.examplePath,
|
||||
packageManager: cmdOpts.packageManager,
|
||||
skipInstall: Boolean(cmdOpts.skipInstall),
|
||||
skipTransforms: Boolean(cmdOpts.skipTransforms),
|
||||
git: cmdOpts.git !== false,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof CliError) {
|
||||
console.error(pc.red(e.message));
|
||||
process.exit(e.exitCode);
|
||||
}
|
||||
console.error(e);
|
||||
process.exit(EXIT_ERROR);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
process.on("SIGINT", () => {
|
||||
process.exit(EXIT_SIGINT);
|
||||
});
|
||||
|
||||
program.parseAsync(process.argv).catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(EXIT_ERROR);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import fsSync from "node:fs";
|
||||
import path from "node:path";
|
||||
import pc from "picocolors";
|
||||
import { assertValidExample, loadExamplesManifest } from "../examples.js";
|
||||
import { downloadExampleToTemp } from "../download.js";
|
||||
import { installDependencies } from "../install.js";
|
||||
import {
|
||||
detectAvailableManagers,
|
||||
type PackageManagerName,
|
||||
} from "../package-manager.js";
|
||||
import { resolveTargetRoot } from "../paths.js";
|
||||
import {
|
||||
promptExample,
|
||||
promptPackageManager,
|
||||
promptPackageName,
|
||||
promptTargetDir,
|
||||
} from "../prompts.js";
|
||||
import { resolveExampleSource } from "../resolve-example-source.js";
|
||||
import { tryGitInit } from "../git.js";
|
||||
import { runTransforms } from "../transforms/run-transforms.js";
|
||||
|
||||
export async function runCreate(
|
||||
opts: Omit<import("../types.js").CreateCliOptions, "git"> & {
|
||||
projectDirectory?: string;
|
||||
git?: boolean;
|
||||
}
|
||||
): Promise<void> {
|
||||
const cwd = process.cwd();
|
||||
const manifest = loadExamplesManifest();
|
||||
|
||||
const exampleTrim = opts.example?.trim();
|
||||
const example = exampleTrim
|
||||
? exampleTrim
|
||||
: await promptExample(manifest);
|
||||
|
||||
if (!/^https?:\/\//i.test(example)) {
|
||||
assertValidExample(example, manifest);
|
||||
}
|
||||
|
||||
const projectDirRaw = opts.projectDirectory?.trim();
|
||||
const projectDir = projectDirRaw
|
||||
? projectDirRaw
|
||||
: await promptTargetDir();
|
||||
|
||||
const targetRoot = resolveTargetRoot(cwd, projectDir);
|
||||
fsSync.mkdirSync(targetRoot, { recursive: true });
|
||||
|
||||
const defaultPkgName =
|
||||
projectDir === "."
|
||||
? (() => {
|
||||
const normalized = path
|
||||
.basename(cwd)
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "");
|
||||
return normalized || "antd-admin-app";
|
||||
})()
|
||||
: path.basename(targetRoot);
|
||||
|
||||
const packageName = await promptPackageName(defaultPkgName);
|
||||
|
||||
const packageManager: PackageManagerName =
|
||||
opts.packageManager ??
|
||||
(await promptPackageManager(detectAvailableManagers()));
|
||||
|
||||
if (opts.skipTransforms && opts.packageManager) {
|
||||
console.warn(
|
||||
pc.yellow(
|
||||
"--skip-transforms was used with an explicit package manager; package.json name may not be updated before install."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const { gigetSource } = resolveExampleSource({
|
||||
example,
|
||||
examplePath: opts.examplePath,
|
||||
});
|
||||
|
||||
const tmp = await downloadExampleToTemp(gigetSource);
|
||||
try {
|
||||
fsSync.cpSync(tmp, targetRoot, { recursive: true, dereference: true });
|
||||
} finally {
|
||||
fsSync.rmSync(tmp, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
await runTransforms({
|
||||
projectRoot: targetRoot,
|
||||
packageName,
|
||||
skip: opts.skipTransforms,
|
||||
});
|
||||
|
||||
if (!opts.skipInstall) {
|
||||
installDependencies(targetRoot, packageManager);
|
||||
}
|
||||
|
||||
tryGitInit(targetRoot, opts.git !== false);
|
||||
|
||||
console.log(pc.green(`Success! Project created at ${targetRoot}`));
|
||||
}
|
||||
Reference in New Issue
Block a user