create-pubinfo 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,20 +1,80 @@
1
1
  # create-pubinfo
2
2
 
3
- [![npm version][npm-version-src]][npm-version-href]
4
- [![Monorepo][monorepo-src]][monorepo-href]
5
- ![License][License-src]
3
+ Pubinfo 的项目脚手架,用来生成应用模板、模块模板和 monorepo 模板。
6
4
 
7
- > 一键生成项目模板
5
+ ## 它在做什么
6
+
7
+ - 提供交互式初始化流程
8
+ - 支持三套本地模板:`pubinfo-app`、`pubinfo-module`、`pubinfo-monorepo`
9
+ - 根据勾选结果裁剪可选模块,目前内置 `rbac`
10
+ - 支持按模板变量渲染 `.hbs` 文件,并复制原始资源文件
11
+ - 初始化完成后自动尝试执行 `git init`
12
+ - 保留一套 `v1` 兼容流程,用远端模板包下载旧版脚手架
8
13
 
9
14
  ## 基本用法
10
15
 
11
16
  ```bash
12
- npm create pubinfo
17
+ pnpm create pubinfo
18
+ pnpx create-pubinfo
19
+ npx create-pubinfo
20
+ ```
21
+
22
+ 运行后会询问:
23
+
24
+ - 目录名称 `dir`
25
+ - 项目标识 `key`
26
+ - 模板类型
27
+ - 是否启用 `rbac`
28
+ - 是否启用 `openapi`
29
+ - 使用 `v1` 还是 `v2`
30
+
31
+ ## 非交互式用法
32
+
33
+ 如果需要给 agent、脚本或 CI 调用,可以直接通过命令行参数生成项目:
34
+
35
+ ```bash
36
+ create-pubinfo --dir my-app --key my-app --template pubinfo-app --modules rbac --openapi false --yes
37
+ ```
38
+
39
+ 参数说明:
40
+
41
+ - `--dir`: 目标目录名称
42
+ - `--key`: 项目标识
43
+ - `--template`: 模板类型,支持 `pubinfo-app`、`pubinfo-module`、`pubinfo-monorepo`
44
+ - `--modules`: 模块列表,多个模块用逗号分隔;目前支持 `rbac`,不启用模块可传 `none`
45
+ - `--openapi`: 是否启用运行时接口生成,支持 `true` 或 `false`
46
+ - `--yes`: 跳过确认;当目标目录已存在时会覆盖该目录
47
+
48
+ 只要传入上述生成参数,CLI 就会进入非交互模式,不再询问 `v1/v2` 或其他问题。
49
+
50
+ ## 模板类型
51
+
52
+ - `pubinfo-app`: 单应用模板
53
+ - `pubinfo-module`: 模块开发模板,带 playground
54
+ - `pubinfo-monorepo`: monorepo 模板
55
+
56
+ ## 代码用法
57
+
58
+ ```ts
59
+ import { generate } from 'create-pubinfo';
60
+
61
+ await generate({
62
+ templateName: 'pubinfo-app',
63
+ key: 'demo',
64
+ version: '2.2.0',
65
+ modules: ['rbac'],
66
+ openapi: false,
67
+ });
13
68
  ```
14
69
 
15
- <!-- Badges -->
16
- [npm-version-src]: https://img.shields.io/npm/v/create-pubinfo?style=flat-square
17
- [npm-version-href]: https://npmjs.com/package/create-pubinfo
18
- [monorepo-src]: https://img.shields.io/badge/Monorepo-with%20pnpm-F5871D.svg
19
- [monorepo-href]: https://pnpm.io/workspaces
20
- [License-src]: https://img.shields.io/badge/license-MIT-green
70
+ ## 主要导出
71
+
72
+ - `generate`: 基于模板生成项目
73
+ - `copyTemplate`: 直接复制模板目录
74
+ - `interaction`: 获取交互式选项
75
+ - `readPackageJSON`: 读取脚手架自身包信息
76
+
77
+ ## 仓库关系
78
+
79
+ - 被 `@pubinfo/cli` 的 `generate` 和 `monorepo` 子命令直接复用。
80
+ - `templates/` 目录就是这个包真正的核心资产。
package/dist/cli.mjs CHANGED
@@ -1,18 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import { a as validateInput, n as readPackageJSON, r as run, t as bootstrop } from "./helper.mjs";
2
+ import { a as validateInput, n as readPackageJSON, o as generate, r as run, t as bootstrop } from "./helper.mjs";
3
+ import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
4
+ import { readFile, rm, writeFile } from "node:fs/promises";
5
+ import { dirname, resolve } from "node:path";
6
+ import process from "node:process";
7
+ import { fileURLToPath } from "node:url";
3
8
  import { checkbox, confirm, input, select } from "@inquirer/prompts";
4
9
  import { logger } from "@pubinfo/shared";
5
10
  import { Command } from "commander";
6
- import { resolve } from "node:path";
7
- import process from "node:process";
8
- import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
9
11
  import colors from "ansi-colors";
10
12
  import { downloadTemplate } from "giget";
11
13
  import ora from "ora";
12
14
  import { coerce, compare } from "semver";
13
15
  import { ofetch } from "ofetch";
14
16
  import { rimrafSync } from "rimraf";
15
- import { readFile, writeFile } from "node:fs/promises";
16
17
  import { parseJSON, parseJSONC, stringifyJSON } from "confbox";
17
18
 
18
19
  //#region src/v1/constant.ts
@@ -230,13 +231,76 @@ async function runV1() {
230
231
 
231
232
  //#endregion
232
233
  //#region src/cli.ts
234
+ const TEMPLATE_NAMES = [
235
+ "pubinfo-app",
236
+ "pubinfo-module",
237
+ "pubinfo-monorepo"
238
+ ];
239
+ const MODULE_NAMES = ["rbac"];
240
+ const templateDir = resolve(dirname(fileURLToPath(import.meta.url)), "../templates");
241
+ function parseBoolean(value, name) {
242
+ if (value === void 0) return false;
243
+ if ([
244
+ "true",
245
+ "1",
246
+ "yes"
247
+ ].includes(value)) return true;
248
+ if ([
249
+ "false",
250
+ "0",
251
+ "no"
252
+ ].includes(value)) return false;
253
+ throw new Error(`参数 ${name} 只能是 true 或 false`);
254
+ }
255
+ function isTemplateName(value) {
256
+ return TEMPLATE_NAMES.includes(value);
257
+ }
258
+ function isModuleName(value) {
259
+ return MODULE_NAMES.includes(value);
260
+ }
261
+ function parseModules(value) {
262
+ if (!value || value === "none") return [];
263
+ const modules = value.split(",").map((item) => item.trim()).filter(Boolean);
264
+ const invalidModules = modules.filter((moduleName) => !isModuleName(moduleName));
265
+ if (invalidModules.length > 0) throw new Error(`未知模块: ${invalidModules.join(", ")}`);
266
+ return modules;
267
+ }
268
+ function hasGenerateOptions(options) {
269
+ return Boolean(options.dir || options.key || options.template || options.modules || options.openapi !== void 0 || options.yes);
270
+ }
271
+ async function runWithCliOptions(options, version) {
272
+ if (!options.dir || !options.key || !options.template) throw new Error("非交互模式必须提供 --dir、--key 和 --template");
273
+ if (!isTemplateName(options.template)) throw new Error(`未知模板: ${options.template}`);
274
+ const targetDir = resolve(process.cwd(), options.dir);
275
+ if (existsSync(targetDir)) {
276
+ if (!options.yes) throw new Error(`目录 ${options.dir} 已存在,请添加 --yes 覆盖`);
277
+ await rm(targetDir, {
278
+ recursive: true,
279
+ force: true
280
+ });
281
+ }
282
+ await generate({
283
+ dir: options.dir,
284
+ key: options.key,
285
+ templateName: options.template,
286
+ modules: parseModules(options.modules),
287
+ openapi: parseBoolean(options.openapi, "--openapi"),
288
+ templateDir,
289
+ version
290
+ });
291
+ }
233
292
  async function main() {
234
293
  const program = new Command();
235
294
  const pkg = readPackageJSON();
236
295
  program.name(pkg.name).description(pkg.description).version(pkg.version);
237
- program.description("初始化框架").action(async () => {
238
- bootstrop();
296
+ program.description("初始化框架").option("--dir <dir>", "目录名称").option("--key <key>", "项目唯一标识").option("--template <template>", "模板类型: pubinfo-app | pubinfo-module | pubinfo-monorepo").option("--modules <modules>", "模块列表,多个模块使用逗号分隔,例如 rbac").option("--openapi <boolean>", "是否运行时自动生成接口文件").option("-y, --yes", "跳过确认;目标目录已存在时覆盖").action(async () => {
239
297
  try {
298
+ const options = program.opts();
299
+ if (hasGenerateOptions(options)) {
300
+ await runWithCliOptions(options, pkg.version);
301
+ return;
302
+ }
303
+ bootstrop();
240
304
  if (await select({
241
305
  message: "使用 v1/v2 版本?",
242
306
  default: "v2",
@@ -250,7 +314,7 @@ async function main() {
250
314
  logger.error(error);
251
315
  }
252
316
  });
253
- program.parse();
317
+ await program.parseAsync();
254
318
  }
255
319
  main();
256
320
 
package/dist/helper.mjs CHANGED
@@ -1,10 +1,10 @@
1
- import { checkbox, confirm, input, select } from "@inquirer/prompts";
2
- import { logger } from "@pubinfo/shared";
1
+ import fs, { existsSync, renameSync } from "node:fs";
3
2
  import { dirname, posix, relative, resolve, sep } from "node:path";
4
3
  import process, { cwd } from "node:process";
5
4
  import { fileURLToPath } from "node:url";
5
+ import { checkbox, confirm, input, select } from "@inquirer/prompts";
6
+ import { logger } from "@pubinfo/shared";
6
7
  import { copy } from "fs-extra";
7
- import fs, { existsSync, renameSync } from "node:fs";
8
8
  import colors from "ansi-colors";
9
9
  import nodePlop from "node-plop";
10
10
  import { spawn } from "node:child_process";
@@ -196,7 +196,7 @@ async function run(version) {
196
196
  var package_default = {
197
197
  name: "create-pubinfo",
198
198
  type: "module",
199
- version: "2.2.0",
199
+ version: "2.2.2",
200
200
  description: "初始化项目框架",
201
201
  author: "Werheng <werheng.zhang@gmail.com>",
202
202
  license: "MIT",
@@ -216,7 +216,7 @@ var package_default = {
216
216
  scripts: {
217
217
  "dev": "tsdown --watch src",
218
218
  "build": "tsdown",
219
- "cli": "node dist/cli.js",
219
+ "cli": "node dist/cli.mjs",
220
220
  "cli:clean": "rimraf ./my-app",
221
221
  "lint": "eslint . --cache --fix"
222
222
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-pubinfo",
3
3
  "type": "module",
4
- "version": "2.2.0",
4
+ "version": "2.2.2",
5
5
  "description": "初始化项目框架",
6
6
  "author": "Werheng <werheng.zhang@gmail.com>",
7
7
  "license": "MIT",
@@ -38,7 +38,7 @@
38
38
  "ora": "^9.3.0",
39
39
  "rimraf": "^6.1.2",
40
40
  "semver": "^7.7.4",
41
- "@pubinfo/shared": "2.2.0"
41
+ "@pubinfo/shared": "2.2.2"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^25.2.2"
@@ -46,7 +46,7 @@
46
46
  "scripts": {
47
47
  "dev": "tsdown --watch src",
48
48
  "build": "tsdown",
49
- "cli": "node dist/cli.js",
49
+ "cli": "node dist/cli.mjs",
50
50
  "cli:clean": "rimraf ./my-app",
51
51
  "lint": "eslint . --cache --fix"
52
52
  }
@@ -43,7 +43,7 @@
43
43
  "typescript": "^5.8.3"
44
44
  },
45
45
  "simple-git-hooks": {
46
- "pre-commit": "pnpm lint-staged",
46
+ "pre-commit": "pnpm lint-staged --no-stash",
47
47
  "commit-msg": "pnpm exec pubinfo commit --edit $1"
48
48
  },
49
49
  "lint-staged": {
@@ -51,7 +51,7 @@
51
51
  "typescript": "^5.8.3"
52
52
  },
53
53
  "simple-git-hooks": {
54
- "pre-commit": "pnpm lint-staged",
54
+ "pre-commit": "pnpm lint-staged --no-stash",
55
55
  "commit-msg": "pnpm exec pubinfo commit --edit $1"
56
56
  },
57
57
  "lint-staged": {
@@ -30,7 +30,7 @@
30
30
  "typescript": "^5.9.3"
31
31
  },
32
32
  "simple-git-hooks": {
33
- "pre-commit": "pnpm lint-staged && pnpm run lint",
33
+ "pre-commit": "pnpm lint-staged --no-stash && pnpm run lint",
34
34
  "commit-msg": "pnpm exec pubinfo-commit --edit $1"
35
35
  },
36
36
  "lint-staged": {