@shys/crud 1.0.1-beta.0 → 1.0.1-beta.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 ADDED
@@ -0,0 +1,342 @@
1
+ # @shys/crud
2
+
3
+ MidwayJS v4 模块化 CRUD CLI 代码生成器,支持 TypeORM / Sequelize / MikroORM,支持配置文件和自定义模板。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ # 全局安装
9
+ npm install -g @shys/crud
10
+
11
+ # 或项目内安装
12
+ npm install -D @shys/crud
13
+ ```
14
+
15
+ ## 快速开始
16
+
17
+ ```bash
18
+ # 交互式运行
19
+ npx @shys/crud
20
+
21
+ # 完整参数
22
+ npx @shys/crud --module home --table sys_user --src ./src
23
+ ```
24
+
25
+ ### 配置到 package.json
26
+
27
+ 在项目的 `package.json` 中添加 `scripts` 命令,方便团队成员快速使用:
28
+
29
+ ```json
30
+ {
31
+ "scripts": {
32
+ "crud": "shys-crud",
33
+ "crud:entity": "shys-crud --only-entity",
34
+ "crud:dry": "shys-crud --dry-run",
35
+ "crud:user": "shys-crud --module system --table sys_user --force",
36
+ "crud:order": "shys-crud --module order --table order_info --force"
37
+ },
38
+ "devDependencies": {
39
+ "@shys/crud": "^1.0.0"
40
+ }
41
+ }
42
+ ```
43
+
44
+ 配置后使用方式:
45
+
46
+ ```bash
47
+ # 交互式运行(推荐,可按需填写参数)
48
+ npm run crud
49
+
50
+ # 只生成 entity
51
+ npm run crud:entity
52
+
53
+ # 模拟运行预览(不实际写文件)
54
+ npm run crud:dry
55
+
56
+ # 生成指定表的完整 CRUD(已预定义 module 和 table)
57
+ npm run crud:user
58
+ npm run crud:order
59
+ ```
60
+
61
+ 如果使用 pnpm:
62
+
63
+ ```bash
64
+ pnpm crud
65
+ pnpm crud:user
66
+ ```
67
+
68
+ > **提示**:推荐将常用的表配置成独立脚本(如上面的 `crud:user`、`crud:order`),配合 `--force` 可直接覆盖重新生成,配合 `crud.config.ts` 配置文件使用体验更佳。
69
+
70
+ 生成的目录结构:
71
+
72
+ ```
73
+ src/modules/home/
74
+ ├── entity/
75
+ │ └── sysUser.entity.ts
76
+ ├── dto/
77
+ │ └── sysUser/
78
+ │ ├── create.dto.ts
79
+ │ ├── update.dto.ts
80
+ │ ├── replace.dto.ts
81
+ │ ├── query.dto.ts
82
+ │ └── index.ts
83
+ ├── vo/
84
+ │ └── sysUser/
85
+ │ ├── sysUser.vo.ts
86
+ │ ├── sysUserList.vo.ts
87
+ │ └── index.ts
88
+ ├── service/
89
+ │ └── sysUser.service.ts
90
+ └── controller/
91
+ └── sysUser.controller.ts
92
+ ```
93
+
94
+ ## CLI 参数
95
+
96
+ | 参数 | 简写 | 说明 |
97
+ |------|------|------|
98
+ | `--module` | `-m` | 模块名(如 home/order/goods) |
99
+ | `--table` | `-t` | 数据库表名(如 sys_dept/city/order_info) |
100
+ | `--src` | `-s` | Midway src 根路径,默认 `./src` |
101
+ | `--output` | `-o` | 生成文件输出路径,默认与 `--src` 相同 |
102
+ | `--templates-path` | - | 自定义模板目录路径 |
103
+ | `--force` | `-f` | 强制覆盖已存在的文件 |
104
+ | `--dry-run` | `-n` | 模拟运行,不实际写入文件 |
105
+ | `--compile` | `-c` | 生成后自动执行 `mwtsc --cleanOutDir` |
106
+ | `--only-entity` | - | 仅生成 entity 文件,不生成 DTO/VO/Service/Controller |
107
+ | `--no-db` | - | 不连接数据库,使用模板字段模式 |
108
+ | `--db-host` | - | 数据库 host |
109
+ | `--db-port` | - | 数据库端口,默认 3306 |
110
+ | `--db-user` | - | 数据库用户名 |
111
+ | `--db-pass` | - | 数据库密码 |
112
+ | `--db-name` | - | 数据库名 |
113
+ | `--help` | `-h` | 显示帮助信息 |
114
+
115
+ ## 配置文件
116
+
117
+ 在项目根目录或 `--src` 指向的目录下放置配置文件,支持以下格式(按优先级从高到低):
118
+
119
+ - `crud.config.ts`
120
+ - `crud.config.js`
121
+ - `crud.config.mjs`
122
+ - `crud.config.cjs`
123
+ - `.crudrc`
124
+ - `.crudrc.json`
125
+ - `.crudrc.yaml`
126
+ - `.crudrc.yml`
127
+ - `.crudrc.js`
128
+ - `.config/crudrc`
129
+ - `.config/crudrc.json`
130
+ - `package.json` 中的 `"crud"` 字段
131
+
132
+ ### 配置示例(crud.config.ts)
133
+
134
+ ```typescript
135
+ export default {
136
+ baseSrcPath: './src',
137
+ outputPath: './src',
138
+ moduleName: 'home',
139
+ tableName: 'sys_user',
140
+ force: false,
141
+ dryRun: false,
142
+ compile: false,
143
+ onlyEntity: false,
144
+ noDb: false,
145
+ templatesPath: './my-templates',
146
+ db: {
147
+ host: '127.0.0.1',
148
+ port: 3306,
149
+ user: 'root',
150
+ password: '',
151
+ database: 'mydb',
152
+ },
153
+ };
154
+ ```
155
+
156
+ ### 配置字段说明
157
+
158
+ | 字段 | 类型 | 默认值 | 说明 |
159
+ |------|------|--------|------|
160
+ | `baseSrcPath` | `string` | `./src` | Midway 项目的 src 根目录绝对或相对路径。生成的模块文件将放在此目录下的 `modules/` 中。 |
161
+ | `outputPath` | `string` | 与 `baseSrcPath` 相同 | 生成文件的输出路径。如需将代码生成到其他目录(如临时目录),可单独指定此项。 |
162
+ | `moduleName` | `string` | 交互式询问 | 业务模块名,用于组织目录结构,如 `home`、`order`、`goods`。 |
163
+ | `tableName` | `string` | 交互式询问 | 数据库表名,如 `sys_user`、`city`、`order_info`。用于生成类名和 DESCRIBE 表结构。 |
164
+ | `force` | `boolean` | `false` | 是否强制覆盖已存在的文件。为 `false` 时遇到同名文件会跳过并提示。 |
165
+ | `dryRun` | `boolean` | `false` | 模拟运行模式。只打印将要生成的文件列表,不实际写入磁盘。适合预览效果。 |
166
+ | `compile` | `boolean` | `false` | 生成完成后是否自动执行 `mwtsc --cleanOutDir` 进行 TypeScript 编译。 |
167
+ | `onlyEntity` | `boolean` | `false` | 仅生成 entity 实体文件,不生成 DTO、VO、Service、Controller 等其他文件。适合只需要实体类的场景。 |
168
+ | `noDb` | `boolean` | `false` | 不连接数据库读取表结构。启用后使用内置模板字段生成(字段为示例占位,需手动修改)。 |
169
+ | `templatesPath` | `string` | 无 | 自定义模板目录路径。在此目录下放置与默认模板同名的 `.njk` 文件即可覆盖对应模板。未覆盖的模板继续使用默认模板。 |
170
+ | `db.host` | `string` | `127.0.0.1` | 数据库主机地址。 |
171
+ | `db.port` | `number` | `3306` | 数据库端口。 |
172
+ | `db.user` | `string` | `root` | 数据库用户名。 |
173
+ | `db.password` | `string` | 空 | 数据库密码。 |
174
+ | `db.database` | `string` | 交互式询问 | 数据库名。指定后会尝试连接数据库并 DESCRIBE 表结构,使用真实字段信息生成代码。 |
175
+ | `db.type` | `string` | `mysql` | 数据库类型,目前仅支持 MySQL。 |
176
+
177
+ > **优先级说明**:命令行参数 > 配置文件 > 默认值。例如命令行传了 `--force`,即使配置文件中 `force: false`,最终也会以 `true` 为准。
178
+
179
+ ## 自定义模板
180
+
181
+ 本工具使用 [nunjucks](https://mozilla.github.io/nunjucks/) 作为模板引擎。所有模板文件均可自定义。
182
+
183
+ ### 使用方式
184
+
185
+ 1. 将默认模板复制到项目目录(如 `./my-templates`)
186
+ 2. 修改模板内容
187
+ 3. 通过 `--templates-path ./my-templates` 参数或配置文件 `templatesPath` 指定自定义模板目录
188
+
189
+ 未覆盖的模板会自动使用默认模板。
190
+
191
+ ### 可用的模板文件
192
+
193
+ | 模板名 | 文件名 | 说明 |
194
+ |--------|--------|------|
195
+ | entity | `entity.njk` | 实体类 |
196
+ | dto-create | `dto-create.njk` | 创建 DTO |
197
+ | dto-update | `dto-update.njk` | 更新 DTO |
198
+ | dto-replace | `dto-replace.njk` | 替换 DTO |
199
+ | dto-query | `dto-query.njk` | 查询 DTO |
200
+ | dto-index | `dto-index.njk` | DTO 索引导出 |
201
+ | vo-single | `vo-single.njk` | 单个 VO |
202
+ | vo-list | `vo-list.njk` | 列表 VO |
203
+ | vo-index | `vo-index.njk` | VO 索引导出 |
204
+ | service | `service.njk` | Service 类 |
205
+ | controller | `controller.njk` | Controller 类 |
206
+ | crud-page-vo | `crud-page-vo.njk` | 分页 VO(全局共享) |
207
+
208
+ ### 模板变量参考
209
+
210
+ #### entity.njk
211
+
212
+ ```
213
+ orm: string // ORM 类型:typeorm/sequelize/mikro-orm
214
+ ormSuffix: string // 实体文件后缀:entity/model
215
+ fields: Array<{ // 字段列表(排除主键和基础字段)
216
+ name: string // 数据库字段名
217
+ camel: string // 驼峰命名
218
+ type: string // 数据库类型
219
+ jsType: string // JavaScript 类型
220
+ ormType: string // ORM 类型
221
+ len: number | null // 字段长度
222
+ nullable: boolean // 是否可空
223
+ comment: string // 字段注释
224
+ supportsLength: boolean
225
+ isDate: boolean
226
+ isSensitive: boolean
227
+ idx: boolean // 是否索引字段
228
+ }>
229
+ tableName: string // 表名
230
+ Pascal: string // PascalCase 命名
231
+ Camel: string // camelCase 命名
232
+ pkInfo: Object | null // 主键信息
233
+ hasPk: boolean // 是否有主键
234
+ hasDateField: boolean // 是否有日期字段
235
+ idxCount: number // 索引字段数量
236
+ ```
237
+
238
+ #### dto-create.njk / dto-update.njk / dto-replace.njk
239
+
240
+ ```
241
+ CreateName: string // Create DTO 类名
242
+ UpdateName: string // Update DTO 类名
243
+ ReplaceName: string // Replace DTO 类名
244
+ Pascal: string // PascalCase 命名
245
+ createFields: Array // 可创建字段
246
+ writable: Array // 可写字段
247
+ picks: string // Pick 类型的字段列表字符串
248
+ typeArgs: string // 类型联合字符串
249
+ ```
250
+
251
+ #### service.njk
252
+
253
+ ```
254
+ ServiceName: string // Service 类名
255
+ Pascal: string // PascalCase 命名
256
+ Camel: string // camelCase 命名
257
+ ormInfo: {
258
+ orm: string
259
+ ormSuffix: string
260
+ serviceParent: string // 父类名
261
+ importCrudOrm: string // 导入语句
262
+ injectEntity: string // 装饰器名
263
+ }
264
+ ```
265
+
266
+ #### controller.njk
267
+
268
+ ```
269
+ CtrlName: string // Controller 类名
270
+ ServiceName: string // Service 类名
271
+ Pascal: string
272
+ Camel: string
273
+ pluralKebab: string // 复数 kebab-case 路由名
274
+ tagName: string // Swagger tag 名
275
+ desc: string // 接口描述
276
+ sortable: string[] // 可排序字段
277
+ filterable: string[] // 可过滤字段
278
+ searchable: string[] // 可搜索字段
279
+ ```
280
+
281
+ ### 自定义模板示例
282
+
283
+ 在 `./my-templates/service.njk` 中:
284
+
285
+ ```njk
286
+ import { Provide, Inject } from '@midwayjs/core';
287
+ import { {{ Pascal }} } from '../entity/{{ Camel }}.entity';
288
+ import { BaseService } from '../framework/base.service';
289
+
290
+ @Provide()
291
+ export class {{ ServiceName }} extends BaseService<{{ Pascal }}> {
292
+
293
+ entityClass = {{ Pascal }};
294
+
295
+ // 在这里添加你的自定义方法
296
+ async customMethod() {
297
+ // ...
298
+ }
299
+ }
300
+ ```
301
+
302
+ ## 编程式 API
303
+
304
+ 除了 CLI,也可以在代码中直接调用:
305
+
306
+ ```typescript
307
+ import { buildFiles, createRenderer, loadConfig } from '@shys/crud';
308
+ import { writeFileSync } from 'node:fs';
309
+
310
+ // 1. 使用 buildFiles
311
+ const result = buildFiles({
312
+ moduleName: 'home',
313
+ tableName: 'sys_user',
314
+ baseSrcPath: './src',
315
+ ormInfo: { /* ... */ },
316
+ fields: [ /* ... */ ],
317
+ onlyEntity: false,
318
+ });
319
+
320
+ result.files.forEach((f) => {
321
+ writeFileSync(f.path, f.content);
322
+ });
323
+
324
+ // 2. 使用模板渲染器
325
+ const renderer = createRenderer({
326
+ customTemplatesPath: './my-templates',
327
+ });
328
+
329
+ const code = renderer.render('entity', {
330
+ orm: 'typeorm',
331
+ fields: [ /* ... */ ],
332
+ Pascal: 'SysUser',
333
+ // ...
334
+ });
335
+
336
+ // 3. 加载配置文件
337
+ const config = await loadConfig(process.cwd());
338
+ ```
339
+
340
+ ## License
341
+
342
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shys/crud",
3
- "version": "1.0.1-beta.0",
3
+ "version": "1.0.1-beta.2",
4
4
  "description": "MidwayJS v4 模块化 CRUD CLI 生成器",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "files": [
16
16
  "dist",
17
- "templates"
17
+ "templates",
18
+ "README.md"
18
19
  ],
19
20
  "scripts": {
20
21
  "build": "tsc",
@@ -6,7 +6,7 @@ import { Entity, Column{% if hasPk %}, PrimaryGeneratedColumn{% endif %}{% if id
6
6
  import { Expose{% if hasDateField %}, Transform{% endif %} } from 'class-transformer';
7
7
  import { ApiProperty, ApiPropertyOptional } from '@midwayjs/swagger';
8
8
  import { Rule } from '@midwayjs/validation';
9
- import { z } from 'zod';
9
+ import * as Joi from 'joi';
10
10
  import { BaseEntity } from '../../../framework/entity/base.entity';
11
11
 
12
12
  @Entity({{ tableName | json }}, {
@@ -24,7 +24,7 @@ export class {{ Pascal }} extends BaseEntity {
24
24
  description: {{ (pkInfo.comment or '主键ID') | json }},
25
25
  })
26
26
  @Expose()
27
- @Rule(z.number().int().describe({{ (pkInfo.comment or '主键ID') | json }}))
27
+ @Rule(Joi.number().integer().required())
28
28
  {{ pkInfo.camel }}: number;
29
29
 
30
30
  {% endif -%}
@@ -46,7 +46,7 @@ export class {{ Pascal }} extends BaseEntity {
46
46
  {% if f.defaultVal != null %} example: {{ f.defaultVal | json }},
47
47
  {% endif %} })
48
48
  @Expose()
49
- @Rule({{ f.zodRule }}.nullable().optional())
49
+ @Rule({{ f.joiRule }})
50
50
  {% if f.isDate %} @Transform(({ value }) => {
51
51
  if (value == null) return null;
52
52
  const d = value instanceof Date ? value : new Date(value);