create-pangza 1.0.1 → 1.1.0

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
@@ -13,6 +13,10 @@ npm create pangza@latest -- init my-app
13
13
  交互勾选模块:`orm` / `auth` / `redis` / `log` / `schedule` / `encrypt` / `validate`。
14
14
  勾选 `orm` / `redis` 时会写入 `EnableOrm()` / `EnableRedis()`;未勾选则启动不连库、不因缺配置报错。不生成 `.gitkeep`。
15
15
 
16
+ 初始化还会生成:
17
+ - `application.yaml`:默认 `server.port: 5270`;按所选模块追加 `redis` / `datasource`+`orm` 等
18
+ - `tsconfig.json`:`@/*` → `src/*`(dev:`tsconfig-paths`;build:`tsc-alias`)
19
+
16
20
  ```bash
17
21
  npx create-pangza init my-app --modules=orm,auth,redis --db=mysql
18
22
  ```
package/lib/generate.js CHANGED
@@ -31,7 +31,13 @@ function findProjectRoot(cwd = process.cwd()) {
31
31
  ...(json.dependencies || {}),
32
32
  ...(json.devDependencies || {}),
33
33
  };
34
- if (deps["@pangza/express"]) return dir;
34
+ if (
35
+ deps["@pangza/express"] ||
36
+ deps["@pangza/application"] ||
37
+ deps["@pangza/core"]
38
+ ) {
39
+ return dir;
40
+ }
35
41
  } catch {
36
42
  /* ignore */
37
43
  }
@@ -59,7 +65,7 @@ function writeFile(filePath, content, { force }) {
59
65
  }
60
66
 
61
67
  function tplEntity({ Pascal, snake }) {
62
- return `import { TableField, TableId, TableName } from "@pangza/express";
68
+ return `import { TableField, TableId, TableName } from "@pangza/orm";
63
69
 
64
70
  @TableName("${snake}")
65
71
  export default class ${Pascal}Entity {
@@ -89,7 +95,7 @@ export default class ${Pascal}Entity {
89
95
  }
90
96
 
91
97
  function tplMapper({ Pascal, fileBase }) {
92
- return `import { Mapper, MapperType } from "@pangza/express";
98
+ return `import { Mapper, MapperType } from "@pangza/orm";
93
99
  import ${Pascal}Entity from "../entity/${fileBase}";
94
100
 
95
101
  @Mapper(${Pascal}Entity)
@@ -98,7 +104,7 @@ export default class ${Pascal}Mapper extends MapperType {}
98
104
  }
99
105
 
100
106
  function tplService({ Pascal, fileBase }) {
101
- return `import { BaseService, Service } from "@pangza/express";
107
+ return `import { BaseService, Service } from "@pangza/core";
102
108
  import ${Pascal}Mapper from "../mapper/${fileBase}";
103
109
 
104
110
  @Service(${Pascal}Mapper)
@@ -115,8 +121,8 @@ function tplController({ Pascal, fileBase, apiPath, camel }) {
115
121
  PutMapping,
116
122
  RequestBody,
117
123
  RequestPath,
118
- Resource,
119
- } from "@pangza/express";
124
+ } from "@pangza/application";
125
+ import { Resource } from "@pangza/core";
120
126
  import ${Pascal}Service from "../../service/${fileBase}";
121
127
 
122
128
  @Controller("/api/${apiPath}")
package/lib/modules.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- /** 可选能力模块(当前均由单包 @pangza/express 提供,差异在依赖与脚手架文件) */
3
+ /** 可选能力模块(按分包安装;入口按模块分包导入) */
4
4
  const MODULES = [
5
5
  {
6
6
  id: "orm",
@@ -35,7 +35,7 @@ const MODULES = [
35
35
  {
36
36
  id: "validate",
37
37
  label: "Validate",
38
- hint: "参数校验装饰器",
38
+ hint: "参数校验装饰器(含在 @pangza/core)",
39
39
  },
40
40
  ];
41
41
 
@@ -81,7 +81,8 @@ const DB_ENV = {
81
81
  /** @param {string[]} moduleIds @param {string} [dbType] */
82
82
  function resolveDependencies(moduleIds, dbType = "mysql") {
83
83
  const deps = {
84
- "@pangza/express": "^1.0.1",
84
+ "@pangza/application": "^1.1.0",
85
+ "@pangza/core": "^1.1.0",
85
86
  cors: "^2.8.5",
86
87
  express: "^5.2.1",
87
88
  inversify: "^8.2.3",
@@ -90,18 +91,28 @@ function resolveDependencies(moduleIds, dbType = "mysql") {
90
91
  const set = new Set(moduleIds);
91
92
 
92
93
  if (set.has("orm")) {
94
+ deps["@pangza/orm"] = "^1.1.0";
93
95
  Object.assign(deps, DB_DEPS[dbType] || DB_DEPS.mysql);
94
96
  }
95
97
  if (set.has("redis") || set.has("auth")) {
98
+ deps["@pangza/redis"] = "^1.1.0";
96
99
  deps.redis = "^6.2.1";
97
100
  }
98
101
  if (set.has("auth")) {
102
+ deps["@pangza/auth"] = "^1.1.0";
99
103
  deps.jsonwebtoken = "^9.0.3";
100
104
  deps.bcryptjs = "^3.0.3";
101
105
  }
106
+ if (set.has("log")) {
107
+ deps["@pangza/log"] = "^1.1.0";
108
+ }
102
109
  if (set.has("schedule")) {
110
+ deps["@pangza/schedule"] = "^1.1.0";
103
111
  deps["node-cron"] = "^4.6.0";
104
112
  }
113
+ if (set.has("encrypt")) {
114
+ deps["@pangza/encrypt"] = "^1.1.0";
115
+ }
105
116
 
106
117
  return deps;
107
118
  }
@@ -142,34 +153,146 @@ function resolveDirs(moduleIds) {
142
153
  return dirs;
143
154
  }
144
155
 
156
+ const DB_YAML = {
157
+ mysql: {
158
+ type: "mysql",
159
+ port: 3306,
160
+ user: "root",
161
+ database: "pangza",
162
+ },
163
+ postgresql: {
164
+ type: "postgresql",
165
+ port: 5432,
166
+ user: "postgres",
167
+ database: "pangza",
168
+ },
169
+ mssql: {
170
+ type: "sqlserver",
171
+ port: 1433,
172
+ user: "sa",
173
+ database: "pangza",
174
+ },
175
+ };
176
+
177
+ /**
178
+ * 按所选模块生成 application.yaml(始终含 server.port=5270)。
179
+ * @param {string[]} moduleIds
180
+ * @param {string} [dbType]
181
+ */
182
+ function generateApplicationYaml(moduleIds, dbType = "mysql") {
183
+ const set = new Set(moduleIds);
184
+ const lines = [
185
+ "# Generated by create-pangza init",
186
+ "# profile: PANGZA_PROFILE / APP_ENV / NODE_ENV(默认 development)",
187
+ "",
188
+ "server:",
189
+ " port: 5270",
190
+ " trustProxy: false",
191
+ ];
192
+
193
+ if (set.has("redis") || set.has("auth")) {
194
+ lines.push(
195
+ "",
196
+ "redis:",
197
+ " host: 127.0.0.1",
198
+ " port: 6379",
199
+ " password: \"\"",
200
+ " db: 0",
201
+ " keyPrefix: \"pangza:\"",
202
+ " mode: standalone",
203
+ );
204
+ }
205
+
206
+ if (set.has("orm")) {
207
+ const db = DB_YAML[dbType] || DB_YAML.mysql;
208
+ lines.push(
209
+ "",
210
+ "datasource:",
211
+ " default:",
212
+ ` type: ${db.type}`,
213
+ " host: 127.0.0.1",
214
+ ` port: ${db.port}`,
215
+ ` user: ${db.user}`,
216
+ " password: \"\"",
217
+ ` database: ${db.database}`,
218
+ " connectionLimit: 10",
219
+ "",
220
+ "orm:",
221
+ " logicDelete: true",
222
+ " logicDeleteField: delete_flag",
223
+ " logicDeleteValue: 1",
224
+ " logicNotDeleteValue: 0",
225
+ " idType: ASSIGN_ID",
226
+ " mapUnderscoreToCamelCase: true",
227
+ " mapperLocations: []",
228
+ " sqlLog:",
229
+ " enabled: false",
230
+ );
231
+ }
232
+
233
+ if (set.has("encrypt")) {
234
+ lines.push(
235
+ "",
236
+ "# encrypt: 密钥建议放代码或环境变量,勿提交生产密钥到仓库",
237
+ );
238
+ }
239
+
240
+ if (set.has("schedule")) {
241
+ lines.push("", "# schedule: 任务写在 src/schedule,由 Application.scan 加载");
242
+ }
243
+
244
+ if (set.has("log")) {
245
+ lines.push("", "# log: 在入口 registry(Log({ writer })) 中配置落库");
246
+ }
247
+
248
+ if (set.has("auth")) {
249
+ lines.push(
250
+ "",
251
+ "# auth: jwtSecret 等在入口 Auth({ ... }) 配置,勿写进 yaml 明文(除非自管)",
252
+ );
253
+ }
254
+
255
+ lines.push("");
256
+ return lines.join("\n");
257
+ }
258
+
145
259
  /**
146
260
  * 生成空项目入口:只起 HTTP;选了 redis/orm 才 Enable*,否则启动不连库。
147
261
  * @param {string[]} moduleIds
148
262
  */
149
263
  function generateMainTs(moduleIds) {
150
264
  const set = new Set(moduleIds);
151
- const named = ["Application", "Logger"];
152
- if (set.has("orm")) named.push("EnableOrm");
153
- if (set.has("redis") || set.has("auth")) named.push("EnableRedis");
154
- if (set.has("auth")) named.push("Auth", "Redis");
155
- if (set.has("log")) named.push("Log");
156
265
 
157
266
  const imports = [
158
267
  'import "reflect-metadata";',
159
268
  'import cors from "cors";',
160
269
  'import { json } from "express";',
161
- `import { ${named.join(", ")} } from "@pangza/express";`,
270
+ 'import { Application } from "@pangza/application";',
271
+ 'import { Logger } from "@pangza/core";',
162
272
  ];
163
273
 
274
+ if (set.has("orm")) {
275
+ imports.push('import { EnableOrm } from "@pangza/orm";');
276
+ }
277
+ if (set.has("redis") || set.has("auth")) {
278
+ imports.push('import Redis, { EnableRedis } from "@pangza/redis";');
279
+ }
280
+ if (set.has("auth")) {
281
+ imports.push('import Auth from "@pangza/auth";');
282
+ }
283
+ if (set.has("log")) {
284
+ imports.push('import Log from "@pangza/log";');
285
+ }
286
+
164
287
  const notes = [];
165
288
  if (set.has("schedule")) {
166
- notes.push("// Schedule: 在 src/schedule 编写任务并由扫描加载");
289
+ notes.push("// Schedule: 在 src/schedule 编写任务并由扫描加载(@pangza/schedule)");
167
290
  }
168
291
  if (set.has("encrypt")) {
169
- notes.push("// Encrypt: 从 @pangza/express 导入 AESUtil 等");
292
+ notes.push("// Encrypt: import { AESUtil } from \"@pangza/encrypt\"");
170
293
  }
171
294
  if (set.has("validate")) {
172
- notes.push("// Validate: 在 Controller 参数上使用校验装饰器");
295
+ notes.push("// Validate: 在 Controller 参数上使用 @pangza/core 校验装饰器");
173
296
  }
174
297
 
175
298
  const chain = [
@@ -209,5 +332,6 @@ module.exports = {
209
332
  resolveDependencies,
210
333
  resolveEnvLines,
211
334
  resolveDirs,
335
+ generateApplicationYaml,
212
336
  generateMainTs,
213
337
  };
package/lib/scaffold.js CHANGED
@@ -6,6 +6,7 @@ const {
6
6
  resolveDependencies,
7
7
  resolveEnvLines,
8
8
  resolveDirs,
9
+ generateApplicationYaml,
9
10
  generateMainTs,
10
11
  } = require("./modules");
11
12
 
@@ -64,7 +65,7 @@ function scaffold(opts) {
64
65
  description: "Pangza Express app",
65
66
  scripts: {
66
67
  dev: "ts-node -r tsconfig-paths/register src/main.ts",
67
- build: "tsc -p tsconfig.json",
68
+ build: "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
68
69
  start: "node dist/main.js",
69
70
  },
70
71
  dependencies: resolveDependencies(modules, dbType),
@@ -73,6 +74,7 @@ function scaffold(opts) {
73
74
  "@types/express": "^5.0.6",
74
75
  "@types/node": "^22.0.0",
75
76
  "ts-node": "^10.9.2",
77
+ "tsc-alias": "^1.8.16",
76
78
  "tsconfig-paths": "^4.2.0",
77
79
  typescript: "^5.9.3",
78
80
  },
@@ -86,6 +88,10 @@ function scaffold(opts) {
86
88
  path.join(targetDir, ".env.example"),
87
89
  resolveEnvLines(modules, dbType).join("\n") + "\n",
88
90
  );
91
+ writeFile(
92
+ path.join(targetDir, "application.yaml"),
93
+ generateApplicationYaml(modules, dbType),
94
+ );
89
95
  writeFile(path.join(targetDir, "src", "main.ts"), generateMainTs(modules));
90
96
 
91
97
  writeFile(
@@ -102,12 +108,14 @@ ${modules.includes("orm") ? `Database: **${dbType}**\n` : ""}
102
108
  ## Run
103
109
 
104
110
  \`\`\`bash
105
- cp .env.example .env
111
+ cp .env.example .env # 可选;端口与库配置以 application.yaml 为准
106
112
  npm install
107
113
  npm run dev
108
114
  \`\`\`
109
115
 
110
- 需要 Redis / 数据库时,请在入口 \`registry(EnableRedis())\` / \`registry(EnableOrm())\`(脚手架勾选对应模块时已自动写入)。
116
+ - 默认端口:\`application.yaml\` → \`server.port: 5270\`
117
+ - 路径别名:\`@/*\` → \`src/*\`(dev 用 tsconfig-paths,build 用 tsc-alias)
118
+ - 需要 Redis / 数据库时,入口已按模块写入 \`EnableRedis()\` / \`EnableOrm()\`
111
119
  `,
112
120
  );
113
121
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-pangza",
3
- "version": "1.0.1",
4
- "description": "Scaffold & generate for @pangza/express (init / g controller|service|mapper|entity|all)",
3
+ "version": "1.1.0",
4
+ "description": "Scaffold & generate for @pangza/* (init / g controller|service|mapper|entity|all)",
5
5
  "bin": {
6
6
  "create-pangza": "./bin/create-pangza.js"
7
7
  },
@@ -4,6 +4,10 @@
4
4
  "module": "CommonJS",
5
5
  "outDir": "dist",
6
6
  "rootDir": "src",
7
+ "baseUrl": ".",
8
+ "paths": {
9
+ "@/*": ["src/*"]
10
+ },
7
11
  "strict": true,
8
12
  "esModuleInterop": true,
9
13
  "skipLibCheck": true,