nicot 1.1.7 → 1.1.9
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 +742 -86
- package/dist/src/bases/id-base.js +3 -8
- package/dist/src/bases/id-base.js.map +1 -1
- package/dist/src/decorators/property.d.ts +2 -0
- package/dist/src/decorators/property.js +14 -1
- package/dist/src/decorators/property.js.map +1 -1
- package/dist/src/decorators/restful.d.ts +2 -0
- package/dist/src/decorators/restful.js +57 -9
- package/dist/src/decorators/restful.js.map +1 -1
- package/dist/src/utility/get-typeorm-relations.js +17 -1
- package/dist/src/utility/get-typeorm-relations.js.map +1 -1
- package/dist/src/utility/metadata.d.ts +5 -0
- package/dist/src/utility/metadata.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,161 +1,817 @@
|
|
|
1
|
-
#
|
|
1
|
+
# NICOT
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**NICOT** 是一个基于 NestJS + TypeORM 的后端开发框架。通过实体定义即生成:
|
|
4
|
+
- 数据库模型(TypeORM)
|
|
5
|
+
- 字段校验(class-validator)
|
|
6
|
+
- 请求 DTO(Create / Update / Query)
|
|
7
|
+
- RESTful 接口与文档(Swagger)
|
|
8
|
+
- 统一返回结构、查询控制、权限注入等
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
适用于希望快速搭建标准化接口、减少重复代码的后端项目。
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 📦 安装
|
|
8
15
|
|
|
9
16
|
```bash
|
|
10
|
-
npm install
|
|
17
|
+
npm install nicot typeorm @nestjs/typeorm class-validator class-transformer reflect-metadata @nestjs/swagger
|
|
11
18
|
```
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Those decorators would all decorate the following, with the SAME settings.
|
|
20
|
+
---
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
- class-validator validation settings.
|
|
19
|
-
- `@nestjs/swagger` `@ApiProperty()` settings.
|
|
22
|
+
## 🧱 定义实体 Entity
|
|
20
23
|
|
|
21
24
|
```ts
|
|
22
25
|
@Entity()
|
|
23
|
-
|
|
24
|
-
@
|
|
25
|
-
@
|
|
26
|
-
@StringColumn(5, {
|
|
26
|
+
class User extends IdBase() {
|
|
27
|
+
@QueryEqual()
|
|
28
|
+
@StringColumn(255, {
|
|
27
29
|
required: true,
|
|
28
|
-
description: '
|
|
30
|
+
description: '用户名',
|
|
29
31
|
})
|
|
30
32
|
name: string;
|
|
31
33
|
|
|
32
|
-
@
|
|
33
|
-
@IntColumn('int', { unsigned: true, description: 'User age', default: 20 })
|
|
34
|
+
@IntColumn('int', { unsigned: true })
|
|
34
35
|
age: number;
|
|
35
36
|
|
|
36
|
-
@
|
|
37
|
-
|
|
37
|
+
@StringColumn(255)
|
|
38
|
+
@NotInResult()
|
|
39
|
+
password: string;
|
|
40
|
+
|
|
41
|
+
@DateColumn()
|
|
42
|
+
@NotWritable()
|
|
43
|
+
createdAt: Date;
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 🧾 主键基础类:IdBase / StringIdBase
|
|
50
|
+
|
|
51
|
+
在定义实体时,NICOT 提供了两种基础类 `IdBase` 与 `StringIdBase`,可作为实体的继承基类,为你自动处理:
|
|
52
|
+
|
|
53
|
+
- 主键字段定义(自增或字符串主键)
|
|
54
|
+
- 主键字段的权限控制与文档注解
|
|
55
|
+
- 默认排序逻辑(id 降序 / 升序)
|
|
56
|
+
- 支持 queryBuilder 查询条件注入
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### 1. `IdBase()` - 数字主键(自增)
|
|
61
|
+
|
|
62
|
+
适合常见的自增整型主键使用场景。
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
@Entity()
|
|
66
|
+
class User extends IdBase() {
|
|
67
|
+
// 继承字段:id: number (bigint unsigned, primary key, auto-increment)
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- 自动添加字段:`id: number`
|
|
72
|
+
- 默认排序为 `ORDER BY id DESC`
|
|
73
|
+
- 使用 `Generated('increment')` 作为主键生成策略
|
|
74
|
+
- 搭配 `@IntColumn` + `@NotWritable()`,在创建 / 修改时不可写
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### 2. `StringIdBase()` - 字符串主键(手动或 UUID)
|
|
79
|
+
|
|
80
|
+
适合你希望使用业务主键或 UUID 作为主键的场景。传入 `uuid: true` 参数后自动生成 UUID 主键。
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
@Entity()
|
|
84
|
+
class ApiKey extends StringIdBase({ uuid: true, description: 'API 密钥 ID' }) {
|
|
85
|
+
// 继承字段:id: string (uuid, primary key)
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- 自动添加字段:`id: string`
|
|
90
|
+
- 默认排序为 `ORDER BY id ASC`
|
|
91
|
+
- 支持配置长度(`length`)和描述(`description`)
|
|
92
|
+
- `uuid: true` 时自动添加 `@Generated('uuid')`
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### 3. 示例对比
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
@Entity()
|
|
100
|
+
class Article extends IdBase({ description: '文章 ID' }) {
|
|
101
|
+
// id: number 自动生成
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@Entity()
|
|
105
|
+
class Token extends StringIdBase({
|
|
106
|
+
uuid: true,
|
|
107
|
+
description: '访问令牌',
|
|
108
|
+
}) {
|
|
109
|
+
// id: string,自动生成 UUID
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### 小结
|
|
116
|
+
|
|
117
|
+
| 基类 | 主键类型 | 排序默认 | ID 生成策略 | 使用场景 |
|
|
118
|
+
|-----------------|------------|----------|----------------------|------------------------|
|
|
119
|
+
| `IdBase()` | number | DESC | 自增 `Generated('increment')` | 常规实体 ID |
|
|
120
|
+
| `StringIdBase()`| string | ASC | 可选 UUID / 手动输入 | UUID 主键、业务主键等 |
|
|
121
|
+
|
|
122
|
+
建议你为每个实体都继承其中一个基类,以统一主键结构和查询逻辑。
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 🧠 字段装饰器总览
|
|
127
|
+
|
|
128
|
+
NICOT 提供了一系列 `***Column()` 装饰器,统一处理字段的:
|
|
129
|
+
|
|
130
|
+
- 数据类型定义(TypeORM)
|
|
131
|
+
- 输入校验(class-validator)
|
|
132
|
+
- 文档描述(@nestjs/swagger)
|
|
133
|
+
|
|
134
|
+
### 字段类型装饰器(`***Column()`)
|
|
135
|
+
|
|
136
|
+
| 装饰器名 | 数据类型 | 自动添加的验证与文档 |
|
|
137
|
+
|----------------------|----------------|---------------------------------|
|
|
138
|
+
| `@StringColumn(len)` | string | `@IsString()` + `@Length()` |
|
|
139
|
+
| `@IntColumn(type)` | int/bigint/... | `@IsInt()` + Swagger number 类型 |
|
|
140
|
+
| `@FloatColumn(type)` | float/decimal | `@IsNumber()` |
|
|
141
|
+
| `@BoolColumn()` | boolean | `@IsBoolean()` |
|
|
142
|
+
| `@DateColumn()` | Date | `@IsDate()` |
|
|
143
|
+
| `@JsonColumn(T)` | 任意对象/数组 | `@IsObject()` / `@ValidateNested()` 等 |
|
|
144
|
+
|
|
145
|
+
所有字段装饰器都支持第二个参数 `options`:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
@StringColumn(255, {
|
|
149
|
+
required: true,
|
|
150
|
+
description: '用户名',
|
|
151
|
+
default: 'Anonymous',
|
|
152
|
+
})
|
|
153
|
+
name: string;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 🔒 字段访问限制装饰器(行为控制)
|
|
159
|
+
|
|
160
|
+
NICOT 提供以下装饰器用于控制字段在不同接口中的表现:
|
|
161
|
+
|
|
162
|
+
| 装饰器名 | 行为控制说明 |
|
|
163
|
+
|----------------------------------------|-------------------------------|
|
|
164
|
+
| `@NotWritable()` | 不允许在创建(POST)或修改(PATCH)时传入 |
|
|
165
|
+
| `@NotChangeable()` | 不允许在修改(PATCH)时更新(只可创建) |
|
|
166
|
+
| `@NotQueryable()` | 不允许在 GET 查询参数中使用该字段 |
|
|
167
|
+
| `@NotInResult()` | 不会出现在任何返回结果中(如密码字段) |
|
|
168
|
+
| `@NotColumn()` | 不是数据库字段(仅逻辑字段,如计算用字段) |
|
|
169
|
+
| `@RelationComputed(() => EntityClass)` | 标识该字段依赖关系字段推导而来(通常在 afterGet) |
|
|
170
|
+
|
|
171
|
+
RestfulFactory 处理 Entity 类的时候,会以这些装饰器为依据,裁剪生成的 DTO 和查询参数。
|
|
172
|
+
|
|
173
|
+
这些限制装饰器非常适合处理:
|
|
174
|
+
|
|
175
|
+
- 安全字段(如密码、Token)
|
|
176
|
+
- 系统字段(如创建时间、创建者 ID)
|
|
177
|
+
- 只读字段(如 auto-increment 主键)
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### 示例:完整字段定义
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
@StringColumn(255, {
|
|
185
|
+
required: true,
|
|
186
|
+
description: '用户昵称',
|
|
187
|
+
})
|
|
188
|
+
@NotWritable()
|
|
189
|
+
nickname: string;
|
|
190
|
+
|
|
191
|
+
@BoolColumn()
|
|
192
|
+
@QueryMatchBoolean()
|
|
193
|
+
isActive: boolean;
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 🔍 查询装饰器总览(Query 系列)
|
|
199
|
+
|
|
200
|
+
NICOT 提供了一套查询装饰器,用于在 Entity 字段上声明支持的 GET 查询条件。它们会自动应用到 `findAll()` 中的 queryBuilder。
|
|
38
201
|
|
|
39
|
-
|
|
40
|
-
somethingElse: any; // Would not come from client input, and would not go into OpenAPI document.
|
|
202
|
+
### ✅ 内建查询装饰器
|
|
41
203
|
|
|
42
|
-
|
|
204
|
+
| 装饰器名 | 查询效果 |
|
|
205
|
+
|-----------------------------|------------------------------------------------|
|
|
206
|
+
| `@QueryEqual()` | 精确匹配:`WHERE field = :value` |
|
|
207
|
+
| `@QueryLike()` | 前缀模糊匹配:`WHERE field LIKE :value%` |
|
|
208
|
+
| `@QuerySearch()` | 宽泛模糊搜索:`WHERE field LIKE %:value%` |
|
|
209
|
+
| `@QueryMatchBoolean()` | `true/false/1/0` 转换为布尔类型查询 |
|
|
210
|
+
| `@QueryEqualZeroNullable()` | `0 → IS NULL`,否则 `= :value`(适合 nullable)|
|
|
211
|
+
| `@QueryGreater()` | 大于查询:`WHERE field > :value` |
|
|
212
|
+
| `@QueryOrderBy()` | 排序字段控制:`ORDER BY field ASC|DESC` |
|
|
43
213
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 🛠 自定义查询装饰器:`QueryCondition()`
|
|
217
|
+
|
|
218
|
+
如果你需要构建更复杂或专用的查询逻辑,可以使用 `QueryCondition()` 创建自己的装饰器:
|
|
219
|
+
|
|
220
|
+
### 示例:大于查询
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
export const QueryGreater = () =>
|
|
224
|
+
QueryCondition((dto, qb, alias, key) => {
|
|
225
|
+
if (dto[key] != null) {
|
|
226
|
+
qb.andWhere(`${alias}.${key} > :${key}`, { [key]: dto[key] });
|
|
47
227
|
}
|
|
48
|
-
}
|
|
228
|
+
});
|
|
229
|
+
```
|
|
49
230
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
231
|
+
### 示例:动态排序字段(带字段名映射)
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
export const QueryOrderBy = () =>
|
|
235
|
+
QueryCondition((dto, qb, alias, key) => {
|
|
236
|
+
const orderValue = dto[key];
|
|
237
|
+
if (orderValue) {
|
|
238
|
+
const originalKey = key.replace(/OrderBy$/, '');
|
|
239
|
+
qb.addOrderBy(`${alias}.${originalKey}`, orderValue);
|
|
53
240
|
}
|
|
54
|
-
}
|
|
241
|
+
});
|
|
242
|
+
```
|
|
55
243
|
|
|
56
|
-
|
|
57
|
-
this.name = this.name.toLowerCase(); // Do something before create.
|
|
58
|
-
}
|
|
244
|
+
> 使用方式与普通装饰器一致,应用在实体字段上即可。
|
|
59
245
|
|
|
60
|
-
|
|
61
|
-
this.name = this.name.toUpperCase(); // Do something after create before sending to user.
|
|
62
|
-
}
|
|
246
|
+
---
|
|
63
247
|
|
|
64
|
-
|
|
65
|
-
}
|
|
248
|
+
### 使用效果示例
|
|
66
249
|
|
|
67
|
-
|
|
68
|
-
|
|
250
|
+
```ts
|
|
251
|
+
@IntColumn('int', { unsigned: true })
|
|
252
|
+
@QueryGreater()
|
|
253
|
+
views: number;
|
|
254
|
+
|
|
255
|
+
@StringColumn(255)
|
|
256
|
+
@QueryLike()
|
|
257
|
+
title: string;
|
|
258
|
+
|
|
259
|
+
@BoolColumn()
|
|
260
|
+
@QueryMatchBoolean()
|
|
261
|
+
isPublished: boolean;
|
|
262
|
+
|
|
263
|
+
@NotWritable()
|
|
264
|
+
@NotInResult()
|
|
265
|
+
@QueryOrderBy()
|
|
266
|
+
@IsIn(['ASC', 'DESC'])
|
|
267
|
+
@ApiProperty({ enum: ['ASC', 'DESC'], description: 'Order by views' })
|
|
268
|
+
viewsOrderBy?: 'ASC' | 'DESC';
|
|
269
|
+
```
|
|
69
270
|
|
|
70
|
-
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 🔁 生命周期钩子
|
|
276
|
+
|
|
277
|
+
支持在实体中定义以下方法:
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
class User {
|
|
281
|
+
async beforeCreate() {}
|
|
282
|
+
async afterCreate() {}
|
|
283
|
+
async beforeUpdate() {}
|
|
284
|
+
async afterUpdate() {}
|
|
285
|
+
async beforeGet() {}
|
|
286
|
+
async afterGet() {}
|
|
287
|
+
|
|
288
|
+
isValidInCreate(): string | undefined {
|
|
289
|
+
return this.name ? undefined : '必须填写名称';
|
|
71
290
|
}
|
|
72
291
|
}
|
|
73
292
|
```
|
|
74
293
|
|
|
75
|
-
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## 🛠 使用 CrudService(服务层标准写法)
|
|
297
|
+
|
|
298
|
+
NICOT 提供了 `CrudService(Entity, options)`,是所有资源的标准服务实现方式。
|
|
76
299
|
|
|
77
|
-
|
|
78
|
-
-
|
|
300
|
+
你只需继承它,并传入对应的实体和配置,即可拥有完整的:
|
|
301
|
+
- 查询(支持分页、排序、过滤、关系)
|
|
302
|
+
- 创建、更新、删除(带钩子、校验、字段控制)
|
|
303
|
+
- 统一返回结构
|
|
79
304
|
|
|
80
|
-
|
|
305
|
+
---
|
|
81
306
|
|
|
82
|
-
|
|
307
|
+
### 定义 Service
|
|
83
308
|
|
|
84
309
|
```ts
|
|
310
|
+
import { CrudService } from 'nicot';
|
|
311
|
+
|
|
85
312
|
@Injectable()
|
|
86
|
-
export class
|
|
87
|
-
|
|
88
|
-
|
|
313
|
+
export class ArticleService extends CrudService(Article, {
|
|
314
|
+
relations: ['user'], // 自动关联 user 实体(LEFT JOIN)
|
|
315
|
+
}) {
|
|
316
|
+
constructor(@InjectRepository(Article) repo) {
|
|
317
|
+
super(repo);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// 可根据需要添加业务方法(非覆盖)
|
|
321
|
+
async downloadArticle(id: number): Promise<Buffer> {
|
|
322
|
+
const res = await this.findOne(id);
|
|
323
|
+
return res.data.getContentAsBuffer();
|
|
89
324
|
}
|
|
90
325
|
}
|
|
91
326
|
```
|
|
92
327
|
|
|
93
|
-
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### 关于 relations
|
|
331
|
+
|
|
332
|
+
`relations: string[]` 是 `CrudService` 的核心配置项之一。它用于在查询中自动加载关联实体(即 TypeORM 的 `leftJoinAndSelect`)。
|
|
333
|
+
|
|
334
|
+
- `'user'` 表示加载 `article.user`
|
|
335
|
+
- `'user.articles'` 表示递归加载嵌套关系
|
|
336
|
+
- 默认使用 `LEFT JOIN`,如需 `INNER JOIN` 可通过 `Inner('user')` 指定
|
|
337
|
+
|
|
338
|
+
这能确保你在 Controller 中无需手动构建复杂的 join 查询。
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
### 方法列表
|
|
343
|
+
|
|
344
|
+
| 方法名 | 说明 |
|
|
345
|
+
|------------------|----------------------------------------|
|
|
346
|
+
| `findAll(dto, qb?)` | 查询列表(支持查询装饰器 / 分页) |
|
|
347
|
+
| `findOne(id, qb?)` | 查单条数据,自动关联 / 过滤 / 封装 |
|
|
348
|
+
| `create(dto)` | 创建数据,带验证、钩子处理 |
|
|
349
|
+
| `update(id, dto, extraConditions?)` | 更新数据并支持条件限制 |
|
|
350
|
+
| `delete(id, extraConditions?)` | 删除数据(软删) |
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
### 示例:条件限制用户只能操作自己数据
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
async findOne(id: number, user: User) {
|
|
358
|
+
return this.service.findOne(id, qb => qb.andWhere('userId = :uid', { uid: user.id }));
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
async update(id: number, dto: UpdateDto, user: User) {
|
|
362
|
+
return this.service.update(id, dto, { userId: user.id }); // 附加 where 条件
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
### 建议实践
|
|
369
|
+
|
|
370
|
+
- 所有实体的服务类都应继承 `CrudService(Entity, options)`
|
|
371
|
+
- `relations` 是推荐使用的配置方式,替代手动 join
|
|
372
|
+
- 如果你有定制查询逻辑,建议用 `super.findAll(...)` + `.data` 进行后处理
|
|
373
|
+
- 避免直接使用 `repo`,使用封装后的方法保持一致性与钩子逻辑生效
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## 🧩 Controller 自动生成(RestfulFactory)
|
|
378
|
+
|
|
379
|
+
NICOT 提供了 `RestfulFactory(Entity)` 工厂函数,自动为实体生成标准 RESTful Controller 接口装饰器及参数提取器。
|
|
380
|
+
|
|
381
|
+
你不再需要手动定义每个路由,只需:
|
|
382
|
+
|
|
383
|
+
1. 创建 DTO(工厂生成)
|
|
384
|
+
2. 使用工厂提供的装饰器
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
### 一键生成的接口说明
|
|
389
|
+
|
|
390
|
+
| 方法 | 路径 | 功能说明 |
|
|
391
|
+
|--------------------------|-------------------------|---------------------------|
|
|
392
|
+
| `@factory.create()` | `POST /` | 创建,使用 `createDto` |
|
|
393
|
+
| `@factory.findOne()` | `GET /:id` | 获取单条数据 |
|
|
394
|
+
| `@factory.findAll()` | `GET /` | 查询列表,支持过滤 / 分页 |
|
|
395
|
+
| `@factory.update()` | `PATCH /:id` | 修改单条数据 |
|
|
396
|
+
| `@factory.delete()` | `DELETE /:id` | 删除单条数据(软删) |
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
### 参数提取装饰器一览
|
|
401
|
+
|
|
402
|
+
| 装饰器 | 用途说明 |
|
|
403
|
+
|----------------------------|-----------------------------------------|
|
|
404
|
+
| `@factory.createParam()` | 注入 `createDto`,自动校验 body |
|
|
405
|
+
| `@factory.updateParam()` | 注入 `updateDto`,自动校验 body |
|
|
406
|
+
| `@factory.findAllParam()` | 注入 `queryDto`,自动校验 query |
|
|
407
|
+
| `@factory.idParam()` | 注入路径参数中的 id |
|
|
408
|
+
|
|
409
|
+
这些参数装饰器全部内建了 `ValidationPipe`,支持自动转换与校验。
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
### 查询能力:基于实体字段的装饰器
|
|
414
|
+
|
|
415
|
+
`@factory.findAll()` 所生成的接口具有完整的查询能力,其行为由实体字段上的 `@QueryXXX()` 装饰器控制:
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
@StringColumn(255)
|
|
419
|
+
@QueryEqual()
|
|
420
|
+
name: string;
|
|
421
|
+
|
|
422
|
+
@BoolColumn()
|
|
423
|
+
@QueryMatchBoolean()
|
|
424
|
+
isActive: boolean;
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
则生成的 `GET /resource?name=Tom&isActive=true` 接口会自动构建对应的 SQL 条件。
|
|
428
|
+
|
|
429
|
+
---
|
|
94
430
|
|
|
95
|
-
|
|
431
|
+
### 示例 Controller
|
|
96
432
|
|
|
97
433
|
```ts
|
|
98
|
-
const
|
|
99
|
-
class
|
|
100
|
-
class UpdateUserDto extends
|
|
434
|
+
const factory = new RestfulFactory(User, { relations: ['articles'] });
|
|
435
|
+
class CreateUserDto extends factory.createDto {}
|
|
436
|
+
class UpdateUserDto extends factory.updateDto {}
|
|
437
|
+
class FindAllUserDto extends factory.findAllDto {}
|
|
101
438
|
|
|
102
439
|
@Controller('user')
|
|
103
440
|
export class UserController {
|
|
104
|
-
constructor(private
|
|
441
|
+
constructor(private readonly service: UserService) {}
|
|
105
442
|
|
|
106
|
-
@
|
|
107
|
-
create(@
|
|
108
|
-
return this.
|
|
443
|
+
@factory.create()
|
|
444
|
+
async create(@factory.createParam() dto: CreateUserDto) {
|
|
445
|
+
return this.service.create(dto);
|
|
109
446
|
}
|
|
110
447
|
|
|
111
|
-
@
|
|
112
|
-
|
|
113
|
-
return this.
|
|
448
|
+
@factory.findAll()
|
|
449
|
+
async findAll(@factory.findAllParam() dto: FindAllUserDto) {
|
|
450
|
+
return this.service.findAll(dto);
|
|
114
451
|
}
|
|
115
452
|
|
|
116
|
-
@
|
|
117
|
-
|
|
118
|
-
return this.
|
|
453
|
+
@factory.findOne()
|
|
454
|
+
async findOne(@factory.idParam() id: number) {
|
|
455
|
+
return this.service.findOne(id);
|
|
119
456
|
}
|
|
120
457
|
|
|
121
|
-
@
|
|
122
|
-
update(@
|
|
123
|
-
return this.
|
|
458
|
+
@factory.update()
|
|
459
|
+
async update(@factory.idParam() id: number, @factory.updateParam() dto: UpdateUserDto) {
|
|
460
|
+
return this.service.update(id, dto);
|
|
124
461
|
}
|
|
125
462
|
|
|
126
|
-
@
|
|
127
|
-
delete(@
|
|
128
|
-
return this.
|
|
463
|
+
@factory.delete()
|
|
464
|
+
async delete(@factory.idParam() id: number) {
|
|
465
|
+
return this.service.delete(id);
|
|
129
466
|
}
|
|
130
467
|
}
|
|
131
468
|
```
|
|
132
469
|
|
|
133
|
-
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
### 补充说明
|
|
473
|
+
|
|
474
|
+
- 所有路由默认返回统一结构(`GenericReturnMessageDto` / `BlankReturnMessageDto`)
|
|
475
|
+
- 所有参数自动校验,无需手动加 `ValidationPipe`
|
|
476
|
+
- `findAll()` 自动支持分页、排序、模糊查询、布尔匹配等
|
|
477
|
+
- 如果你使用了实体关系(relations),则 `findOne()` / `findAll()` 也自动关联查询
|
|
478
|
+
- 所有的接口都是返回状态码 200。
|
|
479
|
+
- OpenAPI 文档会自动生成,包含所有 DTO 类型与查询参数。
|
|
480
|
+
- Service 需要使用 `CrudService(Entity, options)` 进行标准化实现。
|
|
481
|
+
- `RestfulFactory` 的选项 `options` 支持传入 `relations`,形式和 `CrudService` 一致,用于自动裁剪结果 DTO 字段。
|
|
482
|
+
- 如果本内容的 `CrudService` 不查询任何关系字段,那么请设置 `{ relations: [] }` 以裁剪所有关系字段。
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## 📄 分页查询(自动支持)
|
|
487
|
+
|
|
488
|
+
NICOT 的 `findAll()` 方法默认支持分页,**无需你手动声明分页字段**,框架内部已内置分页 DTO 与逻辑。
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
### ✅ 默认分页行为
|
|
134
493
|
|
|
135
|
-
|
|
494
|
+
所有 `findAll()` 查询接口会自动识别以下 query 参数:
|
|
495
|
+
|
|
496
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
497
|
+
|------------------|----------|--------|---------------------------------|
|
|
498
|
+
| `pageCount` | number | `1` | 第几页,从 1 开始 |
|
|
499
|
+
| `recordsPerPage` | number | `25` | 每页多少条数据 |
|
|
500
|
+
|
|
501
|
+
这些字段由框架内置的 `PageSettingsDto` 管理,自动注入到 `findAllParam()` 的 DTO 中,无需你自己定义。
|
|
502
|
+
|
|
503
|
+
分页逻辑最终会转化为:
|
|
136
504
|
|
|
137
505
|
```ts
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
506
|
+
qb.take(recordsPerPage).skip((pageCount - 1) * recordsPerPage);
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
### 🔧 如何更改分页行为
|
|
512
|
+
|
|
513
|
+
分页逻辑由实体继承类中的方法控制(如 `getRecordsPerPage()`),如果你希望关闭分页或调高上限,可以 override 这些方法:
|
|
514
|
+
|
|
515
|
+
```ts
|
|
516
|
+
@Entity()
|
|
517
|
+
class LogEntry extends IdBase() {
|
|
518
|
+
// ...其他字段
|
|
519
|
+
|
|
520
|
+
override getRecordsPerPage() {
|
|
521
|
+
return this.recordsPerPage || 99999; // 禁用分页(或返回极大值)
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
这样处理后,该实体的 `findAll()` 查询将默认返回所有数据。
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
### 示例:分页 + 条件查询
|
|
531
|
+
|
|
532
|
+
```ts
|
|
533
|
+
GET /user?name=Tom&pageCount=2&recordsPerPage=10
|
|
534
|
+
// 查询第 2 页,每页 10 条,筛选 name = Tom 的用户
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
你可以在 Controller 中完全不关心这些字段,它们已由 NICOT 自动注入、处理并应用在 QueryBuilder 上。
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
## 📦 统一返回结构与接口注解
|
|
542
|
+
|
|
543
|
+
NICOT 默认提供统一的接口返回格式与 Swagger 自动注解能力,便于前后端标准化对接。
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
### ✅ 返回结构 DTO 类型(用于 Swagger 类型标注)
|
|
548
|
+
|
|
549
|
+
#### `ReturnMessageDto(EntityClass)`
|
|
550
|
+
用于生成带数据的标准返回结构类型(**不是直接返回值**,用于 `@nestjs/swagger`)。
|
|
551
|
+
|
|
552
|
+
返回结构样式:
|
|
553
|
+
|
|
554
|
+
```json
|
|
555
|
+
{
|
|
556
|
+
"statusCode": 200,
|
|
557
|
+
"success": true,
|
|
558
|
+
"message": "success",
|
|
559
|
+
"timestamp": "2025-04-25T12:00:00.000Z",
|
|
560
|
+
"data": { ... }
|
|
143
561
|
}
|
|
144
562
|
```
|
|
145
563
|
|
|
146
|
-
|
|
564
|
+
#### `BlankReturnMessageDto`
|
|
565
|
+
无数据返回结构的类型(用于 DELETE、UPDATE 等空响应)。
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
### 📊 实际返回结构
|
|
570
|
+
|
|
571
|
+
- **返回数据:**
|
|
147
572
|
|
|
148
573
|
```ts
|
|
149
|
-
|
|
574
|
+
import { GenericReturnMessageDto } from 'nicot';
|
|
575
|
+
|
|
576
|
+
return new GenericReturnMessageDto(200, '操作成功', data);
|
|
150
577
|
```
|
|
151
578
|
|
|
152
|
-
|
|
579
|
+
- **返回空结构:**
|
|
153
580
|
|
|
154
581
|
```ts
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
582
|
+
import { BlankReturnMessageDto } from 'nicot';
|
|
583
|
+
|
|
584
|
+
return new BlankReturnMessageDto(204, '删除成功');
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
- **抛出异常结构:**
|
|
588
|
+
|
|
589
|
+
```ts
|
|
590
|
+
throw new BlankReturnMessageDto(404, '未找到资源').toException();
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
### 📚 Swagger 注解装饰器
|
|
596
|
+
|
|
597
|
+
NICOT 提供以下装饰器帮助你自动声明接口返回结构,无需手动写复杂的 `@ApiResponse(...)`:
|
|
598
|
+
|
|
599
|
+
#### `@ApiTypeResponse(EntityClass)`
|
|
600
|
+
|
|
601
|
+
等价于:
|
|
602
|
+
|
|
603
|
+
```ts
|
|
604
|
+
@ApiOkResponse({
|
|
605
|
+
type: ReturnMessageDto(EntityClass),
|
|
606
|
+
description: '成功响应结构',
|
|
607
|
+
})
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
#### `@ApiError(code, message)`
|
|
611
|
+
|
|
612
|
+
等价于:
|
|
613
|
+
|
|
614
|
+
```ts
|
|
615
|
+
@ApiResponse({
|
|
616
|
+
status: code,
|
|
617
|
+
description: message,
|
|
618
|
+
type: BlankReturnMessageDto,
|
|
619
|
+
})
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
---
|
|
623
|
+
|
|
624
|
+
### 示例用法
|
|
625
|
+
|
|
626
|
+
```ts
|
|
627
|
+
@Get()
|
|
628
|
+
@ApiTypeResponse(User)
|
|
629
|
+
@ApiError(404, '未找到用户')
|
|
630
|
+
async findOne(@Query() dto: SearchDto) {
|
|
631
|
+
const user = await this.service.findOne(dto);
|
|
632
|
+
if (!user) {
|
|
633
|
+
throw new BlankReturnMessageDto(404, '未找到用户').toException();
|
|
634
|
+
}
|
|
635
|
+
return new GenericReturnMessageDto(200, '成功', user);
|
|
160
636
|
}
|
|
161
637
|
```
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## 📥 参数解析 + 验证(DataQuery / DataBody)
|
|
642
|
+
|
|
643
|
+
NICOT 提供便捷装饰器 `@DataQuery()` 与 `@DataBody()`,用于自动完成:
|
|
644
|
+
|
|
645
|
+
- 参数绑定(从 query 或 body)
|
|
646
|
+
- 数据校验(class-validator)
|
|
647
|
+
- 类型转换(`transform: true`)
|
|
648
|
+
- 避免重复书写 ValidationPipe
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
### ✅ 装饰器对照说明
|
|
653
|
+
|
|
654
|
+
| 装饰器 | 等价于标准写法 |
|
|
655
|
+
|----------------|-------------------------------------------------------------------------------|
|
|
656
|
+
| `@DataQuery()` | `@Query(new ValidationPipe({ transform: true }))` |
|
|
657
|
+
| `@DataBody()` | `@Body(new ValidationPipe({ transform: true }))` |
|
|
658
|
+
|
|
659
|
+
这些装饰器默认启用了:
|
|
660
|
+
- 自动类型转换(如 query string 转 number)
|
|
661
|
+
- 自动剔除未声明字段(`whitelist: true`)
|
|
662
|
+
- 自动抛出校验异常(422)
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
### 示例用法
|
|
667
|
+
|
|
668
|
+
```ts
|
|
669
|
+
@Get()
|
|
670
|
+
async findAll(@DataQuery() dto: SearchUserDto) {
|
|
671
|
+
return this.service.findAll(dto);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
@Post()
|
|
675
|
+
async create(@DataBody() dto: CreateUserDto) {
|
|
676
|
+
return this.service.create(dto);
|
|
677
|
+
}
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
你无需手动加 `ValidationPipe`,也无需手动处理转换错误或格式校验,NICOT 帮你做好了这一切。
|
|
681
|
+
|
|
682
|
+
---
|
|
683
|
+
|
|
684
|
+
## 🧩 实体关系示例
|
|
685
|
+
|
|
686
|
+
```ts
|
|
687
|
+
@Entity()
|
|
688
|
+
class Article extends IdBase() {
|
|
689
|
+
@QueryEqual()
|
|
690
|
+
@IntColumn('bigint', { unsigned: true })
|
|
691
|
+
userId: number;
|
|
692
|
+
|
|
693
|
+
@ManyToOne(() => User, user => user.articles, { onDelete: 'CASCADE' })
|
|
694
|
+
user: User;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
@Entity()
|
|
698
|
+
class User extends IdBase() {
|
|
699
|
+
@OneToMany(() => Article, article => article.user)
|
|
700
|
+
articles: Article[];
|
|
701
|
+
|
|
702
|
+
async afterGet() {
|
|
703
|
+
this.articleCount = this.articles.length;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
---
|
|
709
|
+
|
|
710
|
+
## 📊 和同类框架的对比
|
|
711
|
+
|
|
712
|
+
在实际开发中,很多框架也提供了 CRUD 接口构建能力,但存在不同程度的痛点。NICOT 从底层设计上解决了这些问题,适合长期维护的中大型后端项目。
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
### ✅ FastAPI / SQLModel(Python)
|
|
717
|
+
|
|
718
|
+
- ✅ 代码简洁,自动生成 OpenAPI 文档
|
|
719
|
+
- ❌ 无字段权限控制(不能区分不可写/不可查)
|
|
720
|
+
- ❌ 查询能力不够细致,字段粒度控制弱
|
|
721
|
+
- ❌ DTO 拆分需手动处理,复杂模型重复多
|
|
722
|
+
|
|
723
|
+
🔹 **NICOT 优势:**
|
|
724
|
+
- 字段级别控制查询/写入/输出行为
|
|
725
|
+
- 自动生成 DTO + 查询 + OpenAPI + 验证
|
|
726
|
+
- 生命周期钩子和逻辑注入更灵活
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
### ✅ @nestjsx/crud(NestJS)
|
|
731
|
+
|
|
732
|
+
- ✅ 快速生成接口
|
|
733
|
+
- ❌ 安全性差:字段查询/排序过于开放
|
|
734
|
+
- ❌ 控制力弱:很难注入逻辑或自定义查询
|
|
735
|
+
- ❌ Swagger 文档支持不完整
|
|
736
|
+
|
|
737
|
+
🔹 **NICOT 优势:**
|
|
738
|
+
- 每个字段查询能力需显式声明(不开放默认)
|
|
739
|
+
- 完全类型安全 + 文档自动生成
|
|
740
|
+
- 逻辑钩子、权限注入、返回结构标准化
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
### ✅ nestjs-query
|
|
745
|
+
|
|
746
|
+
- ✅ 支持 GraphQL / REST,类型安全强
|
|
747
|
+
- ❌ 学习曲线陡峭,文档不友好
|
|
748
|
+
- ❌ 查询逻辑复杂,难以上手
|
|
749
|
+
- ❌ 重度依赖 GraphQL 思维模式
|
|
750
|
+
|
|
751
|
+
🔹 **NICOT 优势:**
|
|
752
|
+
- 更贴合 REST 直觉思维
|
|
753
|
+
- 默认封装,低学习成本
|
|
754
|
+
- 保留足够扩展点,轻松注入业务逻辑
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
758
|
+
### ✅ GraphQL
|
|
759
|
+
|
|
760
|
+
- ✅ 查询自由,前端控制力强
|
|
761
|
+
- ❌ 后端控制弱,权限处理复杂
|
|
762
|
+
- ❌ 易产生过度查询,性能不稳定
|
|
763
|
+
- ❌ 每个字段都必须写解析器,开发成本高
|
|
764
|
+
|
|
765
|
+
🔹 **NICOT 优势:**
|
|
766
|
+
- 后端主导接口结构,前端只调 REST
|
|
767
|
+
- 查询能力与字段权限完全可控
|
|
768
|
+
- 无需额外解析器,开发更快速
|
|
769
|
+
|
|
770
|
+
---
|
|
771
|
+
|
|
772
|
+
### ✅ MyBatis-Plus / Hibernate(Java)
|
|
773
|
+
|
|
774
|
+
- ✅ 成熟,生态强,Java 企业常用
|
|
775
|
+
- ❌ 配置繁杂,样板代码多
|
|
776
|
+
- ❌ 缺乏统一的返回结构与接口注解
|
|
777
|
+
- ❌ 参数校验 / DTO 拆分手动重复
|
|
778
|
+
|
|
779
|
+
🔹 **NICOT 优势:**
|
|
780
|
+
- 一套装饰器统一字段校验 + ORM + 文档
|
|
781
|
+
- 自动 DTO 拆分,减少重复代码
|
|
782
|
+
- 全自动接口 + 验证 + 注解集成
|
|
783
|
+
|
|
784
|
+
---
|
|
785
|
+
|
|
786
|
+
### 🏆 框架能力矩阵对比
|
|
787
|
+
|
|
788
|
+
| 框架 | 自动接口 | 安全性 | 文档支持 | 类型安全 | 查询控制 | 关系联查支持 | 开发效率 |
|
|
789
|
+
|-----------------------------|----------------|----------------|----------------|----------------|------------------|------------------|----------------|
|
|
790
|
+
| **NICOT** | ✅ 全自动 | ✅ 字段级控制 | ✅ 实体即文档 | ✅ 完整类型推导 | ✅ 装饰器精细控制 | ✅ 自动 relations | ✅ 极高 |
|
|
791
|
+
| FastAPI + SQLModel | ✅ 模型映射生成 | ❌ 缺乏限制 | ✅ 自动生成 | ❌ 运行时类型 | ❌ 查询不受控 | 🟡 手写关系加载 | ✅ 高 |
|
|
792
|
+
| @nestjsx/crud | ✅ 快速注册 | ❌ 默认全暴露 | ❌ Swagger 不完整 | ✅ Nest 类型系统 | ❌ 全字段可查 | 🟡 需手动配置 | ✅ 快速上手 |
|
|
793
|
+
| nestjs-query | ✅ 自动暴露接口 | 🟡 DTO 控权限 | 🟡 手动标注文档 | ✅ 强类型推导 | 🟡 灵活但复杂 | ✅ 关系抽象良好 | ❌ 配置繁琐 |
|
|
794
|
+
| GraphQL(code-first) | ❌ Resolver 必写| ❌ 查询不受控 | ✅ 类型强大 | ✅ 静态推导 | ❌ 查询过度灵活 | ✅ 查询关系强 | ❌ 繁琐/易错 |
|
|
795
|
+
| Hibernate(Java) | ❌ 需配 Service | 🟡 靠注解控制 | ❌ 文档需插件 | 🟡 Java 泛型弱 | 🟡 XML/HQL 控制 | ✅ JPA 级联支持 | ❌ 模板代码多 |
|
|
796
|
+
| MyBatis-Plus(Java) | ✅ 注解生成 | ✅ 手写控制 | ❌ 文档缺失 | ❌ 运行期校验 | ❌ 手写 SQL | ❌ 需 JOIN SQL | ❌ 重复手写多 |
|
|
797
|
+
| NestJS + TypeORM + 手动 DTO | ❌ 全手写 | ✅ 自由控制 | ✅ 自己写 | ✅ 类型安全 | 🟡 逻辑自己处理 | 🟡 手写 relations | ❌ 重复代码多 |
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
801
|
+
NICOT 作为一个 “Entity 驱动” 的框架,在开发体验、安全性、自动化程度之间找到了平衡,真正做到:
|
|
802
|
+
|
|
803
|
+
> 一份实体定义 → 自动生成完整、安全、文档完备的接口系统
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
---
|
|
807
|
+
|
|
808
|
+
## ✅ 总结
|
|
809
|
+
|
|
810
|
+
**NICOT = Entity 驱动 + 自动生成的一体化后端框架**,涵盖:
|
|
811
|
+
|
|
812
|
+
- 实体建模 → 校验规则 → DTO → OpenAPI
|
|
813
|
+
- 自动生成 Controller / Service
|
|
814
|
+
- 灵活字段控制、查询扩展、用户注入、生命周期钩子
|
|
815
|
+
- 内建返回结构、Swagger 注解、守卫装饰器等功能
|
|
816
|
+
|
|
817
|
+
是构建 NestJS 标准化、低重复、文档完善的后端服务的理想选择。
|
|
@@ -44,14 +44,9 @@ function StringIdBase(idOptions) {
|
|
|
44
44
|
columnExtras: { primary: true, nullable: false },
|
|
45
45
|
}),
|
|
46
46
|
Reflect.metadata('design:type', String),
|
|
47
|
-
...(idOptions.uuid
|
|
48
|
-
(0, typeorm_1.Generated)('uuid'),
|
|
49
|
-
(0, decorators_1.
|
|
50
|
-
] : [
|
|
51
|
-
(0, class_validator_1.IsString)(),
|
|
52
|
-
(0, class_validator_1.IsNotEmpty)(),
|
|
53
|
-
(0, decorators_1.NotChangeable)(),
|
|
54
|
-
])
|
|
47
|
+
...(idOptions.uuid
|
|
48
|
+
? [(0, typeorm_1.Generated)('uuid'), (0, decorators_1.NotWritable)()]
|
|
49
|
+
: [(0, class_validator_1.IsString)(), (0, class_validator_1.IsNotEmpty)(), (0, decorators_1.NotChangeable)()]),
|
|
55
50
|
];
|
|
56
51
|
const dec = (0, nesties_1.MergePropertyDecorators)(decs);
|
|
57
52
|
dec(cl.prototype, 'id');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id-base.js","sourceRoot":"","sources":["../../../src/bases/id-base.ts"],"names":[],"mappings":";;;AAAA,2CAAuC;AACvC,qCAAwD;AACxD,wCAAgD;AAChD,8CAKuB;AACvB,qDAAuD;AACvD,qCAAkD;AAMlD,SAAgB,MAAM,CAAC,YAAuB,EAAE;IAC9C,MAAM,EAAE,GAAG,MAAM,MAAO,SAAQ,oBAAQ;QAE7B,UAAU,CAAC,EAA8B,EAAE,UAAkB;YACpE,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACjC,EAAE,CAAC,OAAO,CAAC,GAAG,UAAU,KAAK,EAAE,MAAM,CAAC,CAAC;YACvC,IAAA,4BAAkB,EAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;IACF,MAAM,GAAG,GAAG,IAAA,iCAAuB,EAAC;QAClC,IAAA,wBAAW,GAAE;QACb,IAAA,sBAAS,EAAC,QAAQ,EAAE;YAClB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,YAAY,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE;SACjD,CAAC;QACF,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QACvC,IAAA,mBAAS,EAAC,WAAW,CAAC;KACvB,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACxB,OAAO,EAAE,CAAC;AACZ,CAAC;AArBD,wBAqBC;AAOD,SAAgB,YAAY,CAAC,SAA0B;IACrD,MAAM,EAAE,GAAG,MAAM,YAAa,SAAQ,oBAAQ;QAGnC,UAAU,CACjB,EAAoC,EACpC,UAAkB;YAElB,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACjC,EAAE,CAAC,OAAO,CAAC,GAAG,UAAU,KAAK,EAAE,KAAK,CAAC,CAAC;YACtC,IAAA,4BAAkB,EAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;IACF,MAAM,IAAI,GAAG;QACX,IAAA,yBAAY,EAAC,SAAS,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;YAC5D,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI;YACzB,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE;SACjD,CAAC;QACF,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QACvC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC
|
|
1
|
+
{"version":3,"file":"id-base.js","sourceRoot":"","sources":["../../../src/bases/id-base.ts"],"names":[],"mappings":";;;AAAA,2CAAuC;AACvC,qCAAwD;AACxD,wCAAgD;AAChD,8CAKuB;AACvB,qDAAuD;AACvD,qCAAkD;AAMlD,SAAgB,MAAM,CAAC,YAAuB,EAAE;IAC9C,MAAM,EAAE,GAAG,MAAM,MAAO,SAAQ,oBAAQ;QAE7B,UAAU,CAAC,EAA8B,EAAE,UAAkB;YACpE,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACjC,EAAE,CAAC,OAAO,CAAC,GAAG,UAAU,KAAK,EAAE,MAAM,CAAC,CAAC;YACvC,IAAA,4BAAkB,EAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;IACF,MAAM,GAAG,GAAG,IAAA,iCAAuB,EAAC;QAClC,IAAA,wBAAW,GAAE;QACb,IAAA,sBAAS,EAAC,QAAQ,EAAE;YAClB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,YAAY,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE;SACjD,CAAC;QACF,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QACvC,IAAA,mBAAS,EAAC,WAAW,CAAC;KACvB,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACxB,OAAO,EAAE,CAAC;AACZ,CAAC;AArBD,wBAqBC;AAOD,SAAgB,YAAY,CAAC,SAA0B;IACrD,MAAM,EAAE,GAAG,MAAM,YAAa,SAAQ,oBAAQ;QAGnC,UAAU,CACjB,EAAoC,EACpC,UAAkB;YAElB,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACjC,EAAE,CAAC,OAAO,CAAC,GAAG,UAAU,KAAK,EAAE,KAAK,CAAC,CAAC;YACtC,IAAA,4BAAkB,EAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;IACF,MAAM,IAAI,GAAG;QACX,IAAA,yBAAY,EAAC,SAAS,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;YAC5D,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI;YACzB,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE;SACjD,CAAC;QACF,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QACvC,GAAG,CAAC,SAAS,CAAC,IAAI;YAChB,CAAC,CAAC,CAAC,IAAA,mBAAS,EAAC,MAAM,CAAC,EAAE,IAAA,wBAAW,GAAE,CAAC;YACpC,CAAC,CAAC,CAAC,IAAA,0BAAQ,GAAE,EAAE,IAAA,4BAAU,GAAE,EAAE,IAAA,0BAAa,GAAE,CAAC,CAAC;KACjD,CAAC;IACF,MAAM,GAAG,GAAG,IAAA,iCAAuB,EAAC,IAAI,CAAC,CAAC;IAC1C,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACxB,OAAO,EAAE,CAAC;AACZ,CAAC;AA3BD,oCA2BC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ColumnCommonOptions } from 'typeorm/decorator/options/ColumnCommonOptions';
|
|
2
2
|
import { ApiPropertyOptions } from '@nestjs/swagger';
|
|
3
3
|
import { ColumnWithLengthOptions } from 'typeorm/decorator/options/ColumnWithLengthOptions';
|
|
4
|
+
import { AnyClass } from 'nesties';
|
|
4
5
|
import { WithPrecisionColumnType, WithWidthColumnType } from 'typeorm/driver/types/ColumnTypes';
|
|
5
6
|
import { ColumnWithWidthOptions } from 'typeorm/decorator/options/ColumnWithWidthOptions';
|
|
6
7
|
import { ColumnNumericOptions } from 'typeorm/decorator/options/ColumnNumericOptions';
|
|
@@ -26,3 +27,4 @@ export declare const EnumColumn: <T>(targetEnum: Record<string, T>, options?: Pr
|
|
|
26
27
|
export declare const BoolColumn: (options?: PropertyOptions<boolean>) => PropertyDecorator;
|
|
27
28
|
export declare const JsonColumn: <C extends ClassOrArray>(definition: C, options?: PropertyOptions<ParseType<C>, unknown>) => PropertyDecorator;
|
|
28
29
|
export declare const NotColumn: (options?: OpenAPIOptions<any>) => PropertyDecorator;
|
|
30
|
+
export declare const RelationComputed: (type?: () => AnyClass) => PropertyDecorator;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NotColumn = exports.JsonColumn = exports.BoolColumn = exports.EnumColumn = exports.DateColumn = exports.FloatColumn = exports.IntColumn = exports.StringColumn = void 0;
|
|
3
|
+
exports.RelationComputed = exports.NotColumn = exports.JsonColumn = exports.BoolColumn = exports.EnumColumn = exports.DateColumn = exports.FloatColumn = exports.IntColumn = exports.StringColumn = void 0;
|
|
4
4
|
const swagger_1 = require("@nestjs/swagger");
|
|
5
5
|
const nesties_1 = require("nesties");
|
|
6
6
|
const typeorm_1 = require("typeorm");
|
|
@@ -166,4 +166,17 @@ const NotColumn = (options = {}) => (0, nesties_1.MergePropertyDecorators)([
|
|
|
166
166
|
metadata_1.Metadata.set('notColumn', true, 'notColumnFields'),
|
|
167
167
|
]);
|
|
168
168
|
exports.NotColumn = NotColumn;
|
|
169
|
+
const RelationComputed = (type) => (obj, propertyKey) => {
|
|
170
|
+
const fun = () => {
|
|
171
|
+
const designType = Reflect.getMetadata('design:type', obj, propertyKey);
|
|
172
|
+
const entityClass = type ? type() : designType;
|
|
173
|
+
return {
|
|
174
|
+
entityClass,
|
|
175
|
+
isArray: designType === Array,
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
const dec = metadata_1.Metadata.set('relationComputed', fun, 'relationComputedFields');
|
|
179
|
+
return dec(obj, propertyKey);
|
|
180
|
+
};
|
|
181
|
+
exports.RelationComputed = RelationComputed;
|
|
169
182
|
//# sourceMappingURL=property.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"property.js","sourceRoot":"","sources":["../../../src/decorators/property.ts"],"names":[],"mappings":";;;AACA,6CAAkE;AAElE,
|
|
1
|
+
{"version":3,"file":"property.js","sourceRoot":"","sources":["../../../src/decorators/property.ts"],"names":[],"mappings":";;;AACA,6CAAkE;AAElE,qCAA4D;AAC5D,qCAAwC;AACxC,qDAUyB;AAOzB,yDAA6D;AAC7D,8CAAsD;AACtD,kDAA+C;AAC/C,qCAA4E;AAC5E,kEAA8D;AAC9D,qCAAwC;AASxC,SAAS,gBAAgB,CACvB,OAA4B,EAC5B,WAA+B,EAAE;IAEjC,OAAO,IAAA,qBAAW,EAAC;QACjB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC;QACzD,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,GAAG,QAAQ;QACX,GAAG,CAAC,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;KACZ,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,kBAAkB,CAAC,OAA4B;IACtD,MAAM,IAAI,GAAwB,EAAE,CAAC;IACrC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;QACrB,IAAI,CAAC,IAAI,CAAC,IAAA,4BAAU,GAAE,CAAC,CAAC;KACzB;IACD,OAAO,IAAA,iCAAuB,EAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAOD,SAAS,sBAAsB,CAC7B,OAA2B;IAE3B,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,QAAQ,EAAE,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,IAAI,IAAI;QACtD,OAAO,EAAE,OAAO,CAAC,WAAW;QAC5B,GAAG,OAAO,CAAC,YAAY;KACxB,CAAC;AACJ,CAAC;AAEM,MAAM,YAAY,GAAG,CAC1B,MAAc,EACd,UAA4D,EAAE,EAC3C,EAAE;IACrB,OAAO,IAAA,iCAAuB,EAAC;QAC7B,IAAA,gBAAM,EAAC,SAAS,EAAE,EAAE,MAAM,EAAE,GAAG,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;QACjE,IAAA,0BAAQ,GAAE;QACV,IAAA,2BAAS,EAAC,MAAM,CAAC;QACjB,kBAAkB,CAAC,OAAO,CAAC;QAC3B,gBAAgB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;KAC/D,CAAC,CAAC;AACL,CAAC,CAAC;AAXW,QAAA,YAAY,gBAWvB;AAEK,MAAM,SAAS,GAAG,CACvB,IAAyB,EACzB,UAEI,EAAE,EACa,EAAE;IACrB,MAAM,IAAI,GAAG;QACX,IAAA,gBAAM,EAAC,IAAI,EAAE;YACX,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,0BAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,GAAG,sBAAsB,CAAC,OAAO,CAAC;SACnC,CAAC;QACF,IAAA,uBAAK,GAAE;QACP,kBAAkB,CAAC,OAAO,CAAC;QAC3B,gBAAgB,CAAC,OAAO,EAAE;YACxB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;SAC1C,CAAC;KACH,CAAC;IACF,IAAI,OAAO,CAAC,QAAQ,EAAE;QACpB,IAAI,CAAC,IAAI,CAAC,IAAA,qBAAG,EAAC,CAAC,CAAC,CAAC,CAAC;KACnB;IACD,OAAO,IAAA,iCAAuB,EAAC,IAAI,CAAC,CAAC;AACvC,CAAC,CAAC;AAxBW,QAAA,SAAS,aAwBpB;AAEK,MAAM,WAAW,GAAG,CACzB,IAA6B,EAC7B,UAEI,EAAE,EACa,EAAE;IACrB,MAAM,IAAI,GAAG;QACX,IAAA,gBAAM,EAAC,IAAI,EAAE;YACX,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,GAAG,sBAAsB,CAAC,OAAO,CAAC;SACnC,CAAC;QACF,IAAA,0BAAQ,GAAE;QACV,kBAAkB,CAAC,OAAO,CAAC;QAC3B,gBAAgB,CAAC,OAAO,EAAE;YACxB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;SAC1C,CAAC;KACH,CAAC;IACF,IAAI,OAAO,CAAC,QAAQ,EAAE;QACpB,IAAI,CAAC,IAAI,CAAC,IAAA,qBAAG,EAAC,CAAC,CAAC,CAAC,CAAC;KACnB;IACD,OAAO,IAAA,iCAAuB,EAAC,IAAI,CAAC,CAAC;AACvC,CAAC,CAAC;AAvBW,QAAA,WAAW,eAuBtB;AAEK,MAAM,UAAU,GAAG,CACxB,UAAiC,EAAE,EAChB,EAAE;IACrB,OAAO,IAAA,iCAAuB,EAAC;QAC7B,IAAA,gBAAM,EAAC,WAAW,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;QACpD,IAAA,wBAAM,GAAE;QACR,IAAA,6BAAS,EACP,CAAC,CAAC,EAAE,EAAE;YACJ,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;YACtB,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,YAAY,IAAI;gBAAE,OAAO,KAAK,CAAC;YAEzD,MAAM,eAAe,GAAG,CAAC,CAAS,EAAE,SAAkB,EAAE,EAAE,CACxD,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAErC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAC7B,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC;gBAC3D,OAAO,eAAe,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;aAC1C;YAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;gBAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;gBAClE,OAAO,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC;aACtD;YAED,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,4BAA4B;QACtD,CAAC,EACD;YACE,WAAW,EAAE,IAAI;SAClB,CACF;QACD,kBAAkB,CAAC,OAAO,CAAC;QAC3B,gBAAgB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;KAC1C,CAAC,CAAC;AACL,CAAC,CAAC;AAjCW,QAAA,UAAU,cAiCrB;AAEK,MAAM,UAAU,GAAG,CACxB,UAA6B,EAC7B,UAA8B,EAAE,EACb,EAAE;IACrB,OAAO,IAAA,iCAAuB,EAAC;QAC7B,IAAA,eAAK,GAAE;QACP,IAAA,gBAAM,EAAC,MAAM,EAAE;YACb,IAAI,EAAE,UAAU;YAChB,GAAG,sBAAsB,CAAC,OAAO,CAAC;SACnC,CAAC;QACF,IAAA,wBAAM,EAAC,UAAU,CAAC;QAClB,kBAAkB,CAAC,OAAO,CAAC;QAC3B,gBAAgB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;KAChD,CAAC,CAAC;AACL,CAAC,CAAC;AAdW,QAAA,UAAU,cAcrB;AAEK,MAAM,UAAU,GAAG,CACxB,UAAoC,EAAE,EACnB,EAAE,CACrB,IAAA,iCAAuB,EAAC;IACtB,IAAA,eAAK,GAAE;IACP,IAAA,6BAAS,EAAC,CAAC,CAAC,EAAE,EAAE;QACd,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvD,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1D,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpD,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACtD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,IAAA,gBAAM,EAAC,SAAS,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAClD,kBAAkB,CAAC,OAAO,CAAC;IAC3B,gBAAgB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;CAC7C,CAAC,CAAC;AAfQ,QAAA,UAAU,cAelB;AAEE,MAAM,UAAU,GAAG,CACxB,UAAa,EACb,UAAyC,EAAE,EACxB,EAAE;IACrB,MAAM,EAAE,GAAG,IAAA,kCAAwB,EAAC,UAAU,CAAC,CAAC;IAChD,OAAO,IAAA,iCAAuB,EAAC;QAC7B,IAAA,qBAAY,GAAE;QACd,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QACd,IAAA,gCAAc,GAAE;QAChB,IAAA,gBAAM,EAAC,OAAO,EAAE;YACd,GAAG,sBAAsB,CAAC,OAAO,CAAC;YAClC,WAAW,EAAE,IAAI,kCAAe,CAAC,UAAU,CAAC;SAC7C,CAAC;QACF,kBAAkB,CAAC,OAAO,CAAC;QAC3B,gBAAgB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;KAChD,CAAC,CAAC;AACL,CAAC,CAAC;AAhBW,QAAA,UAAU,cAgBrB;AAEK,MAAM,SAAS,GAAG,CACvB,UAA+B,EAAE,EACd,EAAE,CACrB,IAAA,iCAAuB,EAAC;IACtB,IAAA,2BAAO,GAAE;IACT,gBAAgB,CAAC;QACf,QAAQ,EAAE,KAAK;QACf,GAAG,OAAO;KACX,CAAC;IACF,mBAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,iBAAiB,CAAC;CACnD,CAAC,CAAC;AAVQ,QAAA,SAAS,aAUjB;AAEE,MAAM,gBAAgB,GAC3B,CAAC,IAAqB,EAAqB,EAAE,CAC7C,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE;IACnB,MAAM,GAAG,GAAG,GAAG,EAAE;QACf,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;QAC/C,OAAO;YACL,WAAW;YACX,OAAO,EAAE,UAAU,KAAK,KAAK;SAC9B,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,GAAG,GAAG,mBAAQ,CAAC,GAAG,CAAC,kBAAkB,EAAE,GAAG,EAAE,wBAAwB,CAAC,CAAC;IAC5E,OAAO,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AAC/B,CAAC,CAAC;AAdS,QAAA,gBAAgB,oBAczB"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { AnyClass, ClassType } from 'nesties';
|
|
2
2
|
import { OperationObject } from '@nestjs/swagger/dist/interfaces/open-api-spec.interface';
|
|
3
|
+
import { RelationDef } from '../crud-base';
|
|
3
4
|
export interface RestfulFactoryOptions<T> {
|
|
4
5
|
fieldsToOmit?: (keyof T)[];
|
|
5
6
|
prefix?: string;
|
|
6
7
|
keepEntityVersioningDates?: boolean;
|
|
7
8
|
outputFieldsToOmit?: (keyof T)[];
|
|
8
9
|
entityClassName?: string;
|
|
10
|
+
relations?: (string | RelationDef)[];
|
|
9
11
|
}
|
|
10
12
|
export declare class RestfulFactory<T> {
|
|
11
13
|
readonly entityClass: ClassType<T>;
|
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
4
24
|
};
|
|
5
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
26
|
exports.RestfulFactory = void 0;
|
|
@@ -9,11 +29,23 @@ const dto_1 = require("../dto");
|
|
|
9
29
|
const nesties_1 = require("nesties");
|
|
10
30
|
const swagger_1 = require("@nestjs/swagger");
|
|
11
31
|
const pipes_1 = require("./pipes");
|
|
12
|
-
const lodash_1 =
|
|
32
|
+
const lodash_1 = __importStar(require("lodash"));
|
|
13
33
|
const metadata_1 = require("../utility/metadata");
|
|
14
34
|
const rename_class_1 = require("../utility/rename-class");
|
|
15
35
|
const constants_1 = require("@nestjs/swagger/dist/constants");
|
|
16
36
|
const get_typeorm_relations_1 = require("../utility/get-typeorm-relations");
|
|
37
|
+
const extractRelationName = (relation) => {
|
|
38
|
+
if (typeof relation === 'string') {
|
|
39
|
+
return relation;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
return relation.name;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const getCurrentLevelRelations = (relations) => relations.filter((r) => !r.includes('.'));
|
|
46
|
+
const getNextLevelRelations = (relations, enteringField) => relations
|
|
47
|
+
.filter((r) => r.includes('.') && r.startsWith(`${enteringField}.`))
|
|
48
|
+
.map((r) => r.split('.').slice(1).join('.'));
|
|
17
49
|
class RestfulFactory {
|
|
18
50
|
constructor(entityClass, options = {}, __resolveVisited = new Map()) {
|
|
19
51
|
this.entityClass = entityClass;
|
|
@@ -26,7 +58,7 @@ class RestfulFactory {
|
|
|
26
58
|
]);
|
|
27
59
|
this.basicInputDto = (0, swagger_1.OmitType)(this.entityClass, this.fieldsToOmit);
|
|
28
60
|
this.createDto = (0, rename_class_1.RenameClass)((0, swagger_1.OmitType)(this.basicInputDto, (0, metadata_1.getSpecificFields)(this.entityClass, 'notWritable')), `Create${this.entityClass.name}Dto`);
|
|
29
|
-
this.importDto = (0, dto_1.ImportDataDto)(this.
|
|
61
|
+
this.importDto = (0, dto_1.ImportDataDto)(this.createDto);
|
|
30
62
|
this.findAllDto = (0, rename_class_1.RenameClass)((0, swagger_1.PartialType)((0, swagger_1.OmitType)(this.basicInputDto, (0, metadata_1.getSpecificFields)(this.entityClass, 'notQueryable'))), `Find${this.entityClass.name}Dto`);
|
|
31
63
|
this.updateDto = (0, rename_class_1.RenameClass)((0, swagger_1.PartialType)((0, swagger_1.OmitType)(this.createDto, (0, metadata_1.getSpecificFields)(this.entityClass, 'notChangeable'))), `Update${this.entityClass.name}Dto`);
|
|
32
64
|
this.entityResultDto = this.resolveEntityResultDto();
|
|
@@ -47,12 +79,19 @@ class RestfulFactory {
|
|
|
47
79
|
return this.options.entityClassName || this.entityClass.name;
|
|
48
80
|
}
|
|
49
81
|
resolveEntityResultDto() {
|
|
82
|
+
const relations = (0, get_typeorm_relations_1.getTypeormRelations)(this.entityClass);
|
|
83
|
+
const currentLevelRelations = this.options.relations &&
|
|
84
|
+
new Set(getCurrentLevelRelations(this.options.relations.map(extractRelationName)));
|
|
50
85
|
const outputFieldsToOmit = new Set([
|
|
51
86
|
...(0, metadata_1.getNotInResultFields)(this.entityClass, this.options.keepEntityVersioningDates),
|
|
52
87
|
...(this.options.outputFieldsToOmit || []),
|
|
88
|
+
...(this.options.relations
|
|
89
|
+
? relations
|
|
90
|
+
.map((r) => r.propertyName)
|
|
91
|
+
.filter((r) => !currentLevelRelations.has(r))
|
|
92
|
+
: []),
|
|
53
93
|
]);
|
|
54
94
|
const resultDto = (0, swagger_1.OmitType)(this.entityClass, [...outputFieldsToOmit]);
|
|
55
|
-
const relations = (0, get_typeorm_relations_1.getTypeormRelations)(this.entityClass);
|
|
56
95
|
for (const relation of relations) {
|
|
57
96
|
if (outputFieldsToOmit.has(relation.propertyName))
|
|
58
97
|
continue;
|
|
@@ -69,15 +108,24 @@ class RestfulFactory {
|
|
|
69
108
|
replace(existing);
|
|
70
109
|
}
|
|
71
110
|
else {
|
|
72
|
-
if (!this.__resolveVisited.has(this.entityClass)
|
|
111
|
+
if (!this.__resolveVisited.has(this.entityClass) &&
|
|
112
|
+
!this.options.relations) {
|
|
73
113
|
this.__resolveVisited.set(this.entityClass, [null]);
|
|
74
114
|
}
|
|
75
115
|
const relationFactory = new RestfulFactory(relation.propertyClass, {
|
|
76
|
-
entityClassName: `${this.getEntityClassName()}${
|
|
116
|
+
entityClassName: `${this.getEntityClassName()}${this.options.relations
|
|
117
|
+
? (0, lodash_1.upperFirst)(relation.propertyName)
|
|
118
|
+
: relation.propertyClass.name}`,
|
|
119
|
+
relations: this.options.relations &&
|
|
120
|
+
getNextLevelRelations(this.options.relations.map(extractRelationName), relation.propertyName),
|
|
77
121
|
}, this.__resolveVisited);
|
|
78
122
|
const relationResultDto = relationFactory.entityResultDto;
|
|
79
123
|
replace([relationResultDto]);
|
|
80
|
-
this.
|
|
124
|
+
if (!this.options.relations) {
|
|
125
|
+
this.__resolveVisited.set(relation.propertyClass, [
|
|
126
|
+
relationResultDto,
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
81
129
|
}
|
|
82
130
|
}
|
|
83
131
|
const res = (0, rename_class_1.RenameClass)(resultDto, `${this.getEntityClassName()}ResultDto`);
|
|
@@ -215,7 +263,7 @@ class RestfulFactory {
|
|
|
215
263
|
summary: `Import ${this.getEntityClassName()}`,
|
|
216
264
|
...extras,
|
|
217
265
|
}),
|
|
218
|
-
(0, swagger_1.ApiBody)({ type:
|
|
266
|
+
(0, swagger_1.ApiBody)({ type: this.importDto }),
|
|
219
267
|
(0, swagger_1.ApiOkResponse)({ type: this.importReturnMessageDto }),
|
|
220
268
|
(0, swagger_1.ApiInternalServerErrorResponse)({
|
|
221
269
|
type: nesties_1.BlankReturnMessageDto,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restful.js","sourceRoot":"","sources":["../../../src/decorators/restful.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"restful.js","sourceRoot":"","sources":["../../../src/decorators/restful.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.getTypeormRelationsMap = exports.getTypeormRelations = void 0;
|
|
4
7
|
const typeorm_1 = require("typeorm");
|
|
8
|
+
const metadata_1 = require("./metadata");
|
|
9
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
5
10
|
function getTypeormRelations(cl) {
|
|
6
11
|
const relations = (0, typeorm_1.getMetadataArgsStorage)().relations.filter((r) => r.target === cl);
|
|
7
|
-
|
|
12
|
+
const typeormRelations = relations.map((relation) => {
|
|
8
13
|
const isArray = relation.relationType.endsWith('-many');
|
|
9
14
|
const relationClassFactory = relation.type;
|
|
10
15
|
// check if it's a callable function
|
|
@@ -24,6 +29,17 @@ function getTypeormRelations(cl) {
|
|
|
24
29
|
propertyName: relation.propertyName,
|
|
25
30
|
};
|
|
26
31
|
});
|
|
32
|
+
const computedRelations = (0, metadata_1.getSpecificFields)(cl, 'relationComputed').map((field) => {
|
|
33
|
+
const meta = metadata_1.reflector.get('relationComputed', cl, field);
|
|
34
|
+
const res = meta();
|
|
35
|
+
return {
|
|
36
|
+
isArray: res.isArray,
|
|
37
|
+
propertyClass: res.entityClass,
|
|
38
|
+
propertyName: field,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
return lodash_1.default.uniqBy([...typeormRelations, ...computedRelations], // Merge typeorm relations and computed relations
|
|
42
|
+
(r) => r.propertyName);
|
|
27
43
|
}
|
|
28
44
|
exports.getTypeormRelations = getTypeormRelations;
|
|
29
45
|
function getTypeormRelationsMap(cl) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-typeorm-relations.js","sourceRoot":"","sources":["../../../src/utility/get-typeorm-relations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-typeorm-relations.js","sourceRoot":"","sources":["../../../src/utility/get-typeorm-relations.ts"],"names":[],"mappings":";;;;;;AACA,qCAAiD;AACjD,yCAA0D;AAC1D,oDAAuB;AAEvB,SAAgB,mBAAmB,CAAI,EAAgB;IACrD,MAAM,SAAS,GAAG,IAAA,gCAAsB,GAAE,CAAC,SAAS,CAAC,MAAM,CACzD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,CACvB,CAAC;IAEF,MAAM,gBAAgB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAClD,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,oBAAoB,GAAG,QAAQ,CAAC,IAAI,CAAC;QAC3C,oCAAoC;QACpC,IAAI,aAAuB,CAAC;QAC5B,IAAI,OAAO,oBAAoB,KAAK,UAAU,EAAE;YAC9C,MAAM,aAAa,GAAI,oBAAuC,EAAE,CAAC;YACjE,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE;gBACvC,aAAa,GAAG,aAAa,CAAC;aAC/B;SACF;QACD,IAAI,CAAC,aAAa,EAAE;YAClB,aAAa,GAAG,OAAO,CAAC,WAAW,CACjC,aAAa,EACb,EAAE,CAAC,SAAS,EACZ,QAAQ,CAAC,YAAY,CACtB,CAAC;SACH;QACD,OAAO;YACL,OAAO;YACP,aAAa;YACb,YAAY,EAAE,QAAQ,CAAC,YAAY;SACpC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,iBAAiB,GAAG,IAAA,4BAAiB,EAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC,GAAG,CACrE,CAAC,KAAK,EAAE,EAAE;QACR,MAAM,IAAI,GAAG,oBAAS,CAAC,GAAG,CAAC,kBAAkB,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,IAAI,EAAE,CAAC;QACnB,OAAO;YACL,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,aAAa,EAAE,GAAG,CAAC,WAAW;YAC9B,YAAY,EAAE,KAAK;SACpB,CAAC;IACJ,CAAC,CACF,CAAC;IACF,OAAO,gBAAC,CAAC,MAAM,CACb,CAAC,GAAG,gBAAgB,EAAE,GAAG,iBAAiB,CAAC,EAAE,iDAAiD;IAC9F,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CACtB,CAAC;AACJ,CAAC;AA7CD,kDA6CC;AAED,SAAgB,sBAAsB,CAAI,EAAgB;IACxD,OAAO,MAAM,CAAC,WAAW,CACvB,mBAAmB,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAOxD,CAAC;AACJ,CAAC;AAVD,wDAUC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MetadataSetter, Reflector } from 'typed-reflector';
|
|
2
2
|
import { QueryCond } from '../bases';
|
|
3
|
+
import { AnyClass } from 'nesties';
|
|
3
4
|
interface SpecificFields {
|
|
4
5
|
notColumn: boolean;
|
|
5
6
|
notWritable: boolean;
|
|
@@ -7,6 +8,10 @@ interface SpecificFields {
|
|
|
7
8
|
notQueryable: boolean;
|
|
8
9
|
notInResult: boolean;
|
|
9
10
|
entityVersioningDate: boolean;
|
|
11
|
+
relationComputed: () => {
|
|
12
|
+
entityClass: AnyClass;
|
|
13
|
+
isArray: boolean;
|
|
14
|
+
};
|
|
10
15
|
}
|
|
11
16
|
interface MetadataMap extends SpecificFields {
|
|
12
17
|
queryCondition: QueryCond;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/utility/metadata.ts"],"names":[],"mappings":";;;AAAA,qDAA4D;
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/utility/metadata.ts"],"names":[],"mappings":";;;AAAA,qDAA4D;AAwB/C,QAAA,QAAQ,GAAG,IAAI,gCAAc,EAAiC,CAAC;AAC/D,QAAA,SAAS,GAAG,IAAI,2BAAS,EAAiC,CAAC;AAExE,SAAgB,iBAAiB,CAAC,GAAQ,EAAE,IAA0B;IACpE,OAAO,iBAAS;SACb,QAAQ,CAAC,GAAG,IAAI,QAAQ,EAAE,GAAG,CAAC;SAC9B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AACxD,CAAC;AAJD,8CAIC;AAED,SAAgB,oBAAoB,CAClC,GAAQ,EACR,yBAAyB,GAAG,KAAK;IAEjC,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAChE,IAAI,yBAAyB,EAAE;QAC7B,OAAO,iBAAiB,CAAC;KAC1B;IACD,OAAO;QACL,GAAG,iBAAiB;QACpB,GAAG,iBAAiB,CAAC,GAAG,EAAE,sBAAsB,CAAC;KAClD,CAAC;AACJ,CAAC;AAZD,oDAYC"}
|
package/package.json
CHANGED