@bearei/nest 0.0.0-stage → 2.0.0-dev.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/CHANGELOG.md +84 -0
- package/LICENSE +21 -0
- package/README.md +100 -2
- package/README.zh-CN.md +103 -0
- package/dist/action-log/action-log.interface.d.ts +12 -0
- package/dist/action-log/action-log.interface.js +2 -0
- package/dist/action-log/action-log.module.d.ts +2 -0
- package/dist/action-log/action-log.module.js +22 -0
- package/dist/action-log/action-log.service.d.ts +10 -0
- package/dist/action-log/action-log.service.js +42 -0
- package/dist/action-log/index.d.ts +3 -0
- package/dist/action-log/index.js +19 -0
- package/dist/authentication/authentication-context.interceptor.d.ts +7 -0
- package/dist/authentication/authentication-context.interceptor.js +70 -0
- package/dist/authentication/authentication.enum.d.ts +6 -0
- package/dist/authentication/authentication.enum.js +9 -0
- package/dist/authentication/authentication.guard.d.ts +13 -0
- package/dist/authentication/authentication.guard.js +92 -0
- package/dist/authentication/authentication.interface.d.ts +2 -0
- package/dist/authentication/authentication.interface.js +2 -0
- package/dist/authentication/index.d.ts +4 -0
- package/dist/authentication/index.js +20 -0
- package/dist/authorization/authorization.interface.d.ts +3 -0
- package/dist/authorization/authorization.interface.js +2 -0
- package/dist/authorization/authorization.module.d.ts +2 -0
- package/dist/authorization/authorization.module.js +22 -0
- package/dist/authorization/authorization.service.d.ts +10 -0
- package/dist/authorization/authorization.service.js +56 -0
- package/dist/authorization/index.d.ts +3 -0
- package/dist/authorization/index.js +19 -0
- package/dist/base-service/base-service.interface.d.ts +84 -0
- package/dist/base-service/base-service.interface.js +2 -0
- package/dist/base-service/base-service.module.d.ts +2 -0
- package/dist/base-service/base-service.module.js +22 -0
- package/dist/base-service/base-service.service.d.ts +27 -0
- package/dist/base-service/base-service.service.js +517 -0
- package/dist/base-service/index.d.ts +3 -0
- package/dist/base-service/index.js +19 -0
- package/dist/common.dto.d.ts +19 -0
- package/dist/common.dto.js +111 -0
- package/dist/common.entity.d.ts +11 -0
- package/dist/common.entity.js +76 -0
- package/dist/common.enum.d.ts +19 -0
- package/dist/common.enum.js +24 -0
- package/dist/common.interface.d.ts +19 -0
- package/dist/common.interface.js +2 -0
- package/dist/database/database.module.d.ts +5 -0
- package/dist/database/database.module.js +58 -0
- package/dist/database/index.d.ts +1 -0
- package/dist/database/index.js +17 -0
- package/dist/decorators/allow-access.decorator.d.ts +3 -0
- package/dist/decorators/allow-access.decorator.js +7 -0
- package/dist/decorators/index.d.ts +8 -0
- package/dist/decorators/index.js +24 -0
- package/dist/decorators/is-captcha.decorator.d.ts +2 -0
- package/dist/decorators/is-captcha.decorator.js +23 -0
- package/dist/decorators/is-nano-id.decorator.d.ts +2 -0
- package/dist/decorators/is-nano-id.decorator.js +22 -0
- package/dist/decorators/is-password.decorator.d.ts +2 -0
- package/dist/decorators/is-password.decorator.js +23 -0
- package/dist/decorators/is-version.decorator.d.ts +2 -0
- package/dist/decorators/is-version.decorator.js +22 -0
- package/dist/decorators/omit-entity-keys.decorator.d.ts +2 -0
- package/dist/decorators/omit-entity-keys.decorator.js +7 -0
- package/dist/decorators/require-permissions.decorator.d.ts +3 -0
- package/dist/decorators/require-permissions.decorator.js +7 -0
- package/dist/decorators/require-subscription-features.decorator.d.ts +3 -0
- package/dist/decorators/require-subscription-features.decorator.js +7 -0
- package/dist/exception/exception.enum.d.ts +12 -0
- package/dist/exception/exception.enum.js +16 -0
- package/dist/exception/exception.interface.d.ts +9 -0
- package/dist/exception/exception.interface.js +2 -0
- package/dist/exception/http.exception.d.ts +4 -0
- package/dist/exception/http.exception.js +47 -0
- package/dist/exception/index.d.ts +3 -0
- package/dist/exception/index.js +19 -0
- package/dist/external/external.interface.d.ts +58 -0
- package/dist/external/external.interface.js +2 -0
- package/dist/external/external.module.d.ts +2 -0
- package/dist/external/external.module.js +24 -0
- package/dist/external/external.service.d.ts +15 -0
- package/dist/external/external.service.js +160 -0
- package/dist/external/index.d.ts +3 -0
- package/dist/external/index.js +19 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +39 -0
- package/dist/jwt/index.d.ts +3 -0
- package/dist/jwt/index.js +19 -0
- package/dist/jwt/jwt.interface.d.ts +15 -0
- package/dist/jwt/jwt.interface.js +2 -0
- package/dist/jwt/jwt.module.d.ts +2 -0
- package/dist/jwt/jwt.module.js +43 -0
- package/dist/jwt/jwt.service.d.ts +10 -0
- package/dist/jwt/jwt.service.js +52 -0
- package/dist/permission/index.d.ts +3 -0
- package/dist/permission/index.js +19 -0
- package/dist/permission/permission.enum.d.ts +70 -0
- package/dist/permission/permission.enum.js +73 -0
- package/dist/permission/permission.guard.d.ts +9 -0
- package/dist/permission/permission.guard.js +55 -0
- package/dist/permission/permission.interface.d.ts +2 -0
- package/dist/permission/permission.interface.js +2 -0
- package/dist/redis/index.d.ts +3 -0
- package/dist/redis/index.js +19 -0
- package/dist/redis/redis.interface.d.ts +4 -0
- package/dist/redis/redis.interface.js +2 -0
- package/dist/redis/redis.module.d.ts +2 -0
- package/dist/redis/redis.module.js +22 -0
- package/dist/redis/redis.service.d.ts +14 -0
- package/dist/redis/redis.service.js +51 -0
- package/dist/subscription-feature/index.d.ts +3 -0
- package/dist/subscription-feature/index.js +19 -0
- package/dist/subscription-feature/subscription-feature.enum.d.ts +3 -0
- package/dist/subscription-feature/subscription-feature.enum.js +6 -0
- package/dist/subscription-feature/subscription-feature.interceptor.d.ts +9 -0
- package/dist/subscription-feature/subscription-feature.interceptor.js +68 -0
- package/dist/subscription-feature/subscription-feature.interface.d.ts +2 -0
- package/dist/subscription-feature/subscription-feature.interface.js +2 -0
- package/dist/utils/create-response-sanitizer/create-response-sanitizer.utils.d.ts +1 -0
- package/dist/utils/create-response-sanitizer/create-response-sanitizer.utils.js +23 -0
- package/dist/utils/create-response-sanitizer/index.d.ts +1 -0
- package/dist/utils/create-response-sanitizer/index.js +17 -0
- package/dist/utils/extract-bearer-token/extract-bearer-token.utils.d.ts +1 -0
- package/dist/utils/extract-bearer-token/extract-bearer-token.utils.js +13 -0
- package/dist/utils/extract-bearer-token/index.d.ts +1 -0
- package/dist/utils/extract-bearer-token/index.js +17 -0
- package/dist/utils/format-mobile-number/format-mobile-number.utils.d.ts +1 -0
- package/dist/utils/format-mobile-number/format-mobile-number.utils.js +5 -0
- package/dist/utils/format-mobile-number/index.d.ts +1 -0
- package/dist/utils/format-mobile-number/index.js +17 -0
- package/dist/utils/generate-random-number-string/generate-random-number-string.utils.d.ts +1 -0
- package/dist/utils/generate-random-number-string/generate-random-number-string.utils.js +6 -0
- package/dist/utils/generate-random-number-string/index.d.ts +1 -0
- package/dist/utils/generate-random-number-string/index.js +17 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +22 -0
- package/dist/utils/run-with-database-retry/index.d.ts +1 -0
- package/dist/utils/run-with-database-retry/index.js +17 -0
- package/dist/utils/run-with-database-retry/run-with-database-retry.utils.d.ts +1 -0
- package/dist/utils/run-with-database-retry/run-with-database-retry.utils.js +23 -0
- package/dist/utils/sign/index.d.ts +1 -0
- package/dist/utils/sign/index.js +17 -0
- package/dist/utils/sign/sign.utils.d.ts +5 -0
- package/dist/utils/sign/sign.utils.js +82 -0
- package/package.json +126 -3
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.BaseService = void 0;
|
|
16
|
+
const contracts_1 = require("@bearei/contracts");
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
19
|
+
const typeorm_1 = require("typeorm");
|
|
20
|
+
const action_log_1 = require("../action-log");
|
|
21
|
+
const common_enum_1 = require("../common.enum");
|
|
22
|
+
const exception_1 = require("../exception");
|
|
23
|
+
const utils_1 = require("../utils");
|
|
24
|
+
const IMMUTABLE_ENTITY_KEYS = ['createdAt', 'deletedAt', 'id', 'internalId', 'updatedAt', 'version'];
|
|
25
|
+
const SERVER_MANAGED_CREATE_KEYS = ['deletedAt', 'internalId', 'version'];
|
|
26
|
+
const ASSOCIATION_FIND_OPTION_KEYS = [
|
|
27
|
+
'createdAtRange',
|
|
28
|
+
'ids',
|
|
29
|
+
'innerJoin',
|
|
30
|
+
'page',
|
|
31
|
+
'pageSize',
|
|
32
|
+
'queryBuilderWhere',
|
|
33
|
+
'sortOrder',
|
|
34
|
+
'totalFindOptions',
|
|
35
|
+
'withTotal'
|
|
36
|
+
];
|
|
37
|
+
const ASSOCIATION_BATCH_SIZE = 1024;
|
|
38
|
+
const isNotFoundException = (error) => error instanceof common_1.HttpException && error.getStatus() === common_1.HttpStatus.NOT_FOUND;
|
|
39
|
+
const normalizePagination = (page, pageSize) => {
|
|
40
|
+
const normalizedPage = Math.max(1, Math.trunc(Number(page) || 1));
|
|
41
|
+
const normalizedPageSize = Math.min(contracts_1.MAX_PAGE_SIZE, Math.max(1, Math.trunc(Number(pageSize) || contracts_1.DEFAULT_PAGE_SIZE)));
|
|
42
|
+
return { page: normalizedPage, pageSize: normalizedPageSize };
|
|
43
|
+
};
|
|
44
|
+
const buildDefinedWhere = (source) => {
|
|
45
|
+
const where = {};
|
|
46
|
+
for (const [key, value] of Object.entries(source)) {
|
|
47
|
+
if (typeof value !== 'undefined') {
|
|
48
|
+
where[key] = value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return where;
|
|
52
|
+
};
|
|
53
|
+
const omitKeys = (source, keys) => {
|
|
54
|
+
const result = {};
|
|
55
|
+
const keySet = new Set(keys);
|
|
56
|
+
for (const [key, value] of Object.entries(source)) {
|
|
57
|
+
if (!keySet.has(key)) {
|
|
58
|
+
result[key] = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
let BaseService = class BaseService {
|
|
64
|
+
actionLogService;
|
|
65
|
+
constructor(actionLogService) {
|
|
66
|
+
this.actionLogService = actionLogService;
|
|
67
|
+
}
|
|
68
|
+
create(repository, { entity, headers, isLogEnabled = true, preValidationOptions, serviceName }, manager) {
|
|
69
|
+
const actionLogOptions = {
|
|
70
|
+
action: common_enum_1.ACTION.CREATE,
|
|
71
|
+
headers,
|
|
72
|
+
isLogEnabled,
|
|
73
|
+
message: `Create a ${serviceName}.`,
|
|
74
|
+
raw: { entity },
|
|
75
|
+
serviceName
|
|
76
|
+
};
|
|
77
|
+
return (0, utils_1.runWithDatabaseRetry)(async () => {
|
|
78
|
+
const existingEntity = entity.id ?
|
|
79
|
+
await this.findOne(repository, {
|
|
80
|
+
actionLogOptions,
|
|
81
|
+
serviceName,
|
|
82
|
+
where: { id: entity.id }
|
|
83
|
+
}).catch(error => {
|
|
84
|
+
if (!isNotFoundException(error)) {
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
})
|
|
89
|
+
: undefined;
|
|
90
|
+
if (existingEntity) {
|
|
91
|
+
return existingEntity;
|
|
92
|
+
}
|
|
93
|
+
if (preValidationOptions) {
|
|
94
|
+
const definedPreValidationEntries = Object.entries(preValidationOptions.where).filter(([, value]) => typeof value !== 'undefined');
|
|
95
|
+
if (definedPreValidationEntries.length) {
|
|
96
|
+
await this.preValidate(repository, { ...preValidationOptions, actionLogOptions, serviceName });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const createPayload = omitKeys(entity, SERVER_MANAGED_CREATE_KEYS);
|
|
100
|
+
const createdEntity = repository.create(createPayload);
|
|
101
|
+
const savedEntity = await (manager ? manager.save(createdEntity) : createdEntity.save());
|
|
102
|
+
void this.createSuccessActionLog(savedEntity, actionLogOptions);
|
|
103
|
+
return savedEntity;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
createMany(repository, entities, manager) {
|
|
107
|
+
const createPayloads = entities.map(entity => omitKeys(entity, SERVER_MANAGED_CREATE_KEYS));
|
|
108
|
+
const createdEntities = repository.create(createPayloads);
|
|
109
|
+
return manager ? manager.save(createdEntities) : repository.save(createdEntities);
|
|
110
|
+
}
|
|
111
|
+
delete(repository, { headers, isLogEnabled = true, serviceName, where }, manager) {
|
|
112
|
+
const actionLogOptions = {
|
|
113
|
+
action: common_enum_1.ACTION.DELETE,
|
|
114
|
+
headers,
|
|
115
|
+
isLogEnabled,
|
|
116
|
+
message: `Delete a ${serviceName}.`,
|
|
117
|
+
raw: { where },
|
|
118
|
+
serviceName
|
|
119
|
+
};
|
|
120
|
+
return (0, utils_1.runWithDatabaseRetry)(async () => {
|
|
121
|
+
const entity = await this.findOne(repository, { actionLogOptions, serviceName, where });
|
|
122
|
+
const raw = isLogEnabled ? { ...actionLogOptions.raw, entity: { ...entity } } : {};
|
|
123
|
+
await this.assertNotProhibited(entity, actionLogOptions);
|
|
124
|
+
const result = await (manager ? manager.softRemove(entity) : entity.softRemove());
|
|
125
|
+
void this.createSuccessActionLog(entity, { ...actionLogOptions, raw });
|
|
126
|
+
return result;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
update(repository, { entity, existingEntity, headers, isLogEnabled = true, preValidationOptions, serviceName, where: rawWhere }, manager) {
|
|
130
|
+
const rawActionLogOptions = {
|
|
131
|
+
action: common_enum_1.ACTION.UPDATE,
|
|
132
|
+
headers,
|
|
133
|
+
isLogEnabled,
|
|
134
|
+
message: `Update a ${serviceName}.`,
|
|
135
|
+
raw: { where: rawWhere },
|
|
136
|
+
serviceName
|
|
137
|
+
};
|
|
138
|
+
return (0, utils_1.runWithDatabaseRetry)(async () => {
|
|
139
|
+
const currentEntity = existingEntity ??
|
|
140
|
+
(await this.findOne(repository, {
|
|
141
|
+
actionLogOptions: rawActionLogOptions,
|
|
142
|
+
serviceName,
|
|
143
|
+
where: rawWhere
|
|
144
|
+
}));
|
|
145
|
+
const isOutdatedByUpdatedAt = entity.updatedAt &&
|
|
146
|
+
(0, dayjs_1.default)(entity.updatedAt)
|
|
147
|
+
.utc()
|
|
148
|
+
.isBefore((0, dayjs_1.default)(currentEntity.updatedAt).utc());
|
|
149
|
+
const isOutdatedByVersion = typeof entity.version === 'number' && entity.version < currentEntity.version;
|
|
150
|
+
if (isOutdatedByUpdatedAt || isOutdatedByVersion) {
|
|
151
|
+
return currentEntity;
|
|
152
|
+
}
|
|
153
|
+
const raw = isLogEnabled ? { ...rawActionLogOptions.raw, changes: entity, entity: { ...currentEntity } } : {};
|
|
154
|
+
const actionLogOptions = { ...rawActionLogOptions, raw };
|
|
155
|
+
await this.assertNotProhibited(currentEntity, actionLogOptions);
|
|
156
|
+
if (preValidationOptions) {
|
|
157
|
+
await this.preValidateUpdate({
|
|
158
|
+
actionLogOptions,
|
|
159
|
+
currentEntity,
|
|
160
|
+
preValidationOptions,
|
|
161
|
+
repository,
|
|
162
|
+
serviceName,
|
|
163
|
+
where: rawWhere
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
const updatePayload = omitKeys(entity, IMMUTABLE_ENTITY_KEYS);
|
|
167
|
+
repository.merge(currentEntity, updatePayload);
|
|
168
|
+
await (manager ? manager.save(currentEntity) : currentEntity.save());
|
|
169
|
+
void this.createSuccessActionLog(currentEntity, actionLogOptions);
|
|
170
|
+
return currentEntity;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
find(repository, { findManyOptions = {}, findOptions }) {
|
|
174
|
+
return (0, utils_1.runWithDatabaseRetry)(async () => {
|
|
175
|
+
const { createdAtRange, ids, innerJoin, page: rawPage = 1, pageSize: rawPageSize = contracts_1.DEFAULT_PAGE_SIZE, queryBuilderWhere: rawQueryBuilderWhere, sortOrder = common_enum_1.ORDER.ASC, totalFindOptions, withTotal: isWithTotalRequested = false, ...restWhere } = findOptions;
|
|
176
|
+
const { page, pageSize } = normalizePagination(rawPage, rawPageSize);
|
|
177
|
+
const isWithTotal = isWithTotalRequested && page === 1;
|
|
178
|
+
const limit = pageSize;
|
|
179
|
+
const offset = (page - 1) * pageSize;
|
|
180
|
+
if (ids && !ids.length) {
|
|
181
|
+
return { page, pageSize, results: [], total: isWithTotal ? 0 : undefined };
|
|
182
|
+
}
|
|
183
|
+
const where = buildDefinedWhere(restWhere);
|
|
184
|
+
if (ids) {
|
|
185
|
+
where.id = (0, typeorm_1.In)(ids);
|
|
186
|
+
}
|
|
187
|
+
if (createdAtRange) {
|
|
188
|
+
where.createdAt = (0, typeorm_1.Between)(createdAtRange[0], createdAtRange[1]);
|
|
189
|
+
}
|
|
190
|
+
const { alias, distinctOnFields, sortBy = 'internalId', withDeleted: isWithDeleted = false } = findManyOptions;
|
|
191
|
+
const entityName = alias ?? repository.metadata.name;
|
|
192
|
+
const findQueryBuilder = repository.createQueryBuilder(entityName);
|
|
193
|
+
const distinctOnAliasFields = distinctOnFields ? distinctOnFields.map(field => `${entityName}.${field}`) : undefined;
|
|
194
|
+
const orderByCondition = {};
|
|
195
|
+
for (const field of distinctOnAliasFields ?? []) {
|
|
196
|
+
orderByCondition[field] = common_enum_1.ORDER.ASC;
|
|
197
|
+
}
|
|
198
|
+
orderByCondition[`${entityName}.${sortBy}`] = sortOrder;
|
|
199
|
+
findQueryBuilder.orderBy(orderByCondition);
|
|
200
|
+
if (distinctOnAliasFields) {
|
|
201
|
+
findQueryBuilder.distinctOn(distinctOnAliasFields);
|
|
202
|
+
}
|
|
203
|
+
if (isWithDeleted) {
|
|
204
|
+
findQueryBuilder.withDeleted();
|
|
205
|
+
}
|
|
206
|
+
if (rawQueryBuilderWhere) {
|
|
207
|
+
const { expression, parameters } = rawQueryBuilderWhere;
|
|
208
|
+
findQueryBuilder.where(expression, parameters);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
findQueryBuilder.where(where);
|
|
212
|
+
}
|
|
213
|
+
if (innerJoin) {
|
|
214
|
+
const { alias: innerJoinAlias, condition, parameters, property } = innerJoin;
|
|
215
|
+
findQueryBuilder.innerJoin(property, innerJoinAlias, condition, parameters);
|
|
216
|
+
}
|
|
217
|
+
const totalPromise = isWithTotal ?
|
|
218
|
+
this.count(repository, {
|
|
219
|
+
findManyOptions,
|
|
220
|
+
findOptions: totalFindOptions ?? {
|
|
221
|
+
createdAtRange,
|
|
222
|
+
ids,
|
|
223
|
+
...(innerJoin && { innerJoin }),
|
|
224
|
+
queryBuilderWhere: rawQueryBuilderWhere,
|
|
225
|
+
...restWhere
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
: undefined;
|
|
229
|
+
const [entities, countResult] = await Promise.all([
|
|
230
|
+
findQueryBuilder.limit(limit).offset(offset).getMany(),
|
|
231
|
+
totalPromise
|
|
232
|
+
]);
|
|
233
|
+
const total = countResult?.total ?? 0;
|
|
234
|
+
return { page, pageSize, results: entities, total: isWithTotal ? total : undefined };
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
count(repository, { findManyOptions = {}, findOptions }) {
|
|
238
|
+
const { createdAtRange, ids, innerJoin, queryBuilderWhere: rawQueryBuilderWhere, rawQuery, ...restWhere } = findOptions;
|
|
239
|
+
const { alias, distinctOnFields, withDeleted: isWithDeleted = false } = findManyOptions;
|
|
240
|
+
return (0, utils_1.runWithDatabaseRetry)(async () => {
|
|
241
|
+
if (rawQuery) {
|
|
242
|
+
const { parameters, sql } = rawQuery;
|
|
243
|
+
const results = await repository.query(sql, parameters);
|
|
244
|
+
const firstResult = results.at(0);
|
|
245
|
+
return { total: Number(firstResult ? firstResult.total : 0) };
|
|
246
|
+
}
|
|
247
|
+
if (ids && !ids.length) {
|
|
248
|
+
return { total: 0 };
|
|
249
|
+
}
|
|
250
|
+
const where = buildDefinedWhere(restWhere);
|
|
251
|
+
if (ids) {
|
|
252
|
+
where.id = (0, typeorm_1.In)(ids);
|
|
253
|
+
}
|
|
254
|
+
if (createdAtRange) {
|
|
255
|
+
where.createdAt = (0, typeorm_1.Between)(createdAtRange[0], createdAtRange[1]);
|
|
256
|
+
}
|
|
257
|
+
const entityName = alias ?? repository.metadata.name;
|
|
258
|
+
const countQueryBuilder = repository.createQueryBuilder(entityName);
|
|
259
|
+
if (rawQueryBuilderWhere) {
|
|
260
|
+
const { expression, parameters } = rawQueryBuilderWhere;
|
|
261
|
+
countQueryBuilder.where(expression, parameters);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
countQueryBuilder.where(where);
|
|
265
|
+
}
|
|
266
|
+
if (isWithDeleted) {
|
|
267
|
+
countQueryBuilder.withDeleted();
|
|
268
|
+
}
|
|
269
|
+
if (innerJoin) {
|
|
270
|
+
const { alias: innerJoinAlias, condition, parameters, property } = innerJoin;
|
|
271
|
+
countQueryBuilder.innerJoin(property, innerJoinAlias, condition, parameters);
|
|
272
|
+
}
|
|
273
|
+
const distinctOnAliasFields = distinctOnFields ? distinctOnFields.map(field => `${entityName}.${field}`) : undefined;
|
|
274
|
+
if (distinctOnAliasFields) {
|
|
275
|
+
const distinctExpression = distinctOnAliasFields.length === 1 ?
|
|
276
|
+
`COUNT(DISTINCT ${distinctOnAliasFields[0]})`
|
|
277
|
+
: `COUNT(DISTINCT (${distinctOnAliasFields.join(', ')}))`;
|
|
278
|
+
const countResult = await countQueryBuilder
|
|
279
|
+
.select(distinctExpression, 'count')
|
|
280
|
+
.getRawOne();
|
|
281
|
+
return { total: Number(countResult?.count ?? 0) };
|
|
282
|
+
}
|
|
283
|
+
return { total: await countQueryBuilder.getCount() };
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
findOne(repository, { actionLogOptions, serviceName, where }) {
|
|
287
|
+
return (0, utils_1.runWithDatabaseRetry)(async () => {
|
|
288
|
+
const definedWhere = buildDefinedWhere(where);
|
|
289
|
+
const fields = Object.keys(definedWhere);
|
|
290
|
+
if (!fields.length) {
|
|
291
|
+
(0, exception_1.throwHttpException)(exception_1.HTTP_EXCEPTION.BAD_REQUEST, {
|
|
292
|
+
message: `The ${serviceName} cannot be queried without defined conditions.`
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
const entity = await repository.findOne({ where: definedWhere });
|
|
296
|
+
if (!entity) {
|
|
297
|
+
return this.throwError({
|
|
298
|
+
httpExceptionKind: exception_1.HTTP_EXCEPTION.NOT_FOUND,
|
|
299
|
+
message: `The ${serviceName} does not exist. Find by fields ${fields.join('、')}.`
|
|
300
|
+
}, actionLogOptions);
|
|
301
|
+
}
|
|
302
|
+
return entity;
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
updateAssociation(repository, { associationIds: rawAssociationIds, associationKey, findOptions, headers, isLogEnabled = true, serviceName, updateOptionsByAssociationId = {} }, entityManager) {
|
|
306
|
+
const { page: _page, pageSize: _pageSize, ...restFindOptions } = findOptions;
|
|
307
|
+
const associationFields = omitKeys(restFindOptions, ASSOCIATION_FIND_OPTION_KEYS);
|
|
308
|
+
const associationIdsSet = new Set(rawAssociationIds);
|
|
309
|
+
const associationIds = [...associationIdsSet];
|
|
310
|
+
const filterResult = (entity) => !entity.deletedAt;
|
|
311
|
+
const actionLogOptions = {
|
|
312
|
+
action: common_enum_1.ACTION.UPDATE,
|
|
313
|
+
headers,
|
|
314
|
+
isLogEnabled,
|
|
315
|
+
message: `Update ${serviceName} and ${associationKey} associations.`,
|
|
316
|
+
raw: { findOptions },
|
|
317
|
+
serviceName
|
|
318
|
+
};
|
|
319
|
+
return (0, utils_1.runWithDatabaseRetry)(async () => {
|
|
320
|
+
const rawEntities = [];
|
|
321
|
+
for (let page = 1;; page += 1) {
|
|
322
|
+
const { results } = await this.find(repository, {
|
|
323
|
+
findManyOptions: { withDeleted: true },
|
|
324
|
+
findOptions: { ...restFindOptions, page, pageSize: ASSOCIATION_BATCH_SIZE, withTotal: false }
|
|
325
|
+
});
|
|
326
|
+
rawEntities.push(...results);
|
|
327
|
+
if (results.length < ASSOCIATION_BATCH_SIZE) {
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const raw = isLogEnabled ?
|
|
332
|
+
{
|
|
333
|
+
...actionLogOptions.raw,
|
|
334
|
+
associationIds,
|
|
335
|
+
associationKey,
|
|
336
|
+
entities: rawEntities.map(entity => ({ ...entity }))
|
|
337
|
+
}
|
|
338
|
+
: {};
|
|
339
|
+
const existingIdsSet = new Set(rawEntities.map(entity => String(entity[associationKey])));
|
|
340
|
+
const entitiesToAdd = [];
|
|
341
|
+
const entitiesToRemove = [];
|
|
342
|
+
const entitiesToRecover = [];
|
|
343
|
+
for (const id of associationIds) {
|
|
344
|
+
if (existingIdsSet.has(id)) {
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const updateOptions = updateOptionsByAssociationId[id];
|
|
348
|
+
entitiesToAdd.push(repository.create({
|
|
349
|
+
...(updateOptions ?? {}),
|
|
350
|
+
...associationFields,
|
|
351
|
+
[associationKey]: id,
|
|
352
|
+
deletedAt: null
|
|
353
|
+
}));
|
|
354
|
+
}
|
|
355
|
+
for (const entity of rawEntities) {
|
|
356
|
+
if (!associationIdsSet.has(String(entity[associationKey]))) {
|
|
357
|
+
entitiesToRemove.push(entity);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (entitiesToRemove.length) {
|
|
361
|
+
await Promise.all(entitiesToRemove.map(entity => this.assertNotProhibited(entity, actionLogOptions)));
|
|
362
|
+
}
|
|
363
|
+
for (const entity of rawEntities) {
|
|
364
|
+
const associationId = String(entity[associationKey]);
|
|
365
|
+
const isRecover = associationIdsSet.has(associationId) && Boolean(entity.deletedAt);
|
|
366
|
+
if (isRecover) {
|
|
367
|
+
const updateOptions = updateOptionsByAssociationId[associationId];
|
|
368
|
+
if (updateOptions) {
|
|
369
|
+
repository.merge(entity, updateOptions);
|
|
370
|
+
}
|
|
371
|
+
entitiesToRecover.push(entity);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const manager = (entityManager ?? repository);
|
|
375
|
+
if (entitiesToAdd.length) {
|
|
376
|
+
await manager.save(entitiesToAdd);
|
|
377
|
+
}
|
|
378
|
+
if (entitiesToRecover.length) {
|
|
379
|
+
await manager.recover(entitiesToRecover);
|
|
380
|
+
for (const entity of entitiesToRecover) {
|
|
381
|
+
entity.deletedAt = null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (entitiesToRemove.length) {
|
|
385
|
+
await manager.softRemove(entitiesToRemove);
|
|
386
|
+
}
|
|
387
|
+
void this.createSuccessActionLog([...entitiesToAdd, ...entitiesToRecover, ...entitiesToRemove], {
|
|
388
|
+
...actionLogOptions,
|
|
389
|
+
raw
|
|
390
|
+
});
|
|
391
|
+
return [...rawEntities, ...entitiesToAdd].filter(filterResult);
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
preValidate(repository, { actionLogOptions, orValidationKeyGroups: rawOrValidationKeyGroups, serviceName, validationMethod = common_enum_1.VALIDATION_METHOD.AND, where: rawWhere }) {
|
|
395
|
+
return (0, utils_1.runWithDatabaseRetry)(async () => {
|
|
396
|
+
const { excludeId, ...rawRestWhere } = rawWhere;
|
|
397
|
+
const restWhere = {};
|
|
398
|
+
for (const [key, value] of Object.entries(rawRestWhere)) {
|
|
399
|
+
if (typeof value !== 'undefined') {
|
|
400
|
+
restWhere[key] = value;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const selectKeys = Object.keys(restWhere);
|
|
404
|
+
if (!selectKeys.length) {
|
|
405
|
+
(0, exception_1.throwHttpException)(exception_1.HTTP_EXCEPTION.BAD_REQUEST, {
|
|
406
|
+
message: `Pre-validation of ${serviceName} requires at least one defined condition.`
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
const isOrValidation = validationMethod === common_enum_1.VALIDATION_METHOD.OR;
|
|
410
|
+
let normalizedGroups = [];
|
|
411
|
+
if (isOrValidation) {
|
|
412
|
+
const groups = rawOrValidationKeyGroups ?? [];
|
|
413
|
+
const isGroupsShapeValid = groups.length > 0 && groups.every(keys => Array.isArray(keys) && keys.length > 0);
|
|
414
|
+
const filteredGroups = isGroupsShapeValid ?
|
|
415
|
+
groups.map(keys => keys.map(String).filter(key => typeof restWhere[key] !== 'undefined'))
|
|
416
|
+
: [];
|
|
417
|
+
const isGroupsInvalid = !isGroupsShapeValid || filteredGroups.some(keys => !keys.length);
|
|
418
|
+
if (isGroupsInvalid) {
|
|
419
|
+
await this.throwError({
|
|
420
|
+
code: exception_1.HTTP_EXCEPTION_CODE.OR_VALIDATION_PARAMETER_INVALID,
|
|
421
|
+
httpExceptionKind: exception_1.HTTP_EXCEPTION.BAD_REQUEST,
|
|
422
|
+
message: 'When using "or" as the validation method, orValidationKeyGroups must be a non-empty two-dimensional array and every group must contain at least one defined condition. Example: [["key1","key2"],["key1","key3"]].'
|
|
423
|
+
}, actionLogOptions);
|
|
424
|
+
}
|
|
425
|
+
normalizedGroups = filteredGroups;
|
|
426
|
+
}
|
|
427
|
+
const orValidationKeysSet = new Set(normalizedGroups.flat());
|
|
428
|
+
const baseWhere = {};
|
|
429
|
+
for (const [key, value] of Object.entries(restWhere)) {
|
|
430
|
+
if (!orValidationKeysSet.has(key)) {
|
|
431
|
+
baseWhere[key] = value;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (excludeId) {
|
|
435
|
+
baseWhere.id = (0, typeorm_1.Not)(excludeId);
|
|
436
|
+
}
|
|
437
|
+
const where = isOrValidation ?
|
|
438
|
+
normalizedGroups.map(keys => {
|
|
439
|
+
const groupWhere = { ...baseWhere };
|
|
440
|
+
for (const key of keys) {
|
|
441
|
+
groupWhere[key] = restWhere[key];
|
|
442
|
+
}
|
|
443
|
+
return groupWhere;
|
|
444
|
+
})
|
|
445
|
+
: baseWhere;
|
|
446
|
+
const select = {};
|
|
447
|
+
for (const key of selectKeys) {
|
|
448
|
+
select[key] = true;
|
|
449
|
+
}
|
|
450
|
+
const entity = await repository.findOne({
|
|
451
|
+
select: select,
|
|
452
|
+
where: where
|
|
453
|
+
});
|
|
454
|
+
if (entity) {
|
|
455
|
+
await this.throwError({
|
|
456
|
+
code: exception_1.HTTP_EXCEPTION_CODE.SERVICE_FIELDS_ALREADY_EXISTS,
|
|
457
|
+
httpExceptionKind: exception_1.HTTP_EXCEPTION.BAD_REQUEST,
|
|
458
|
+
message: `The ${serviceName} fields already exists. ${selectKeys.join('、')}.`
|
|
459
|
+
}, actionLogOptions);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
async assertNotProhibited(entity, actionLogOptions) {
|
|
464
|
+
if (entity.protected !== true) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
const serviceNameForMessage = actionLogOptions && actionLogOptions.serviceName ? actionLogOptions.serviceName : 'entity';
|
|
468
|
+
await this.throwError({
|
|
469
|
+
code: exception_1.HTTP_EXCEPTION_CODE.PROHIBITED_OPERATIONS,
|
|
470
|
+
httpExceptionKind: exception_1.HTTP_EXCEPTION.FORBIDDEN,
|
|
471
|
+
message: `The ${serviceNameForMessage} prohibits all operations.`
|
|
472
|
+
}, actionLogOptions);
|
|
473
|
+
}
|
|
474
|
+
createSuccessActionLog(entities, actionLogOptions) {
|
|
475
|
+
return this.actionLogService.success({ entity: entities }, actionLogOptions);
|
|
476
|
+
}
|
|
477
|
+
async throwError({ httpExceptionKind, ...restOptions }, actionLogOptions) {
|
|
478
|
+
const error = (0, exception_1.createHttpException)(httpExceptionKind, restOptions);
|
|
479
|
+
if (actionLogOptions) {
|
|
480
|
+
await this.actionLogService.failure({ error }, { ...actionLogOptions, message: error.message });
|
|
481
|
+
}
|
|
482
|
+
throw error;
|
|
483
|
+
}
|
|
484
|
+
async preValidateUpdate({ actionLogOptions, currentEntity, preValidationOptions, repository, serviceName, where }) {
|
|
485
|
+
const { validationKeys = [], where: preValidationWhere, ...restOptions } = preValidationOptions;
|
|
486
|
+
const validationKeysSet = new Set(validationKeys.map(String));
|
|
487
|
+
for (const [key, value] of Object.entries(preValidationWhere)) {
|
|
488
|
+
if (typeof value !== 'undefined') {
|
|
489
|
+
validationKeysSet.add(key);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
if (!validationKeysSet.size) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
const nextWhere = {};
|
|
496
|
+
for (const key of validationKeysSet) {
|
|
497
|
+
const preValidationValue = preValidationWhere[key];
|
|
498
|
+
const whereValue = where[key];
|
|
499
|
+
nextWhere[key] =
|
|
500
|
+
typeof preValidationValue !== 'undefined' ? preValidationValue
|
|
501
|
+
: typeof whereValue !== 'undefined' ? whereValue
|
|
502
|
+
: currentEntity[key];
|
|
503
|
+
}
|
|
504
|
+
nextWhere.excludeId = currentEntity.id;
|
|
505
|
+
await this.preValidate(repository, {
|
|
506
|
+
...restOptions,
|
|
507
|
+
actionLogOptions,
|
|
508
|
+
serviceName,
|
|
509
|
+
where: nextWhere
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
exports.BaseService = BaseService;
|
|
514
|
+
exports.BaseService = BaseService = __decorate([
|
|
515
|
+
(0, common_1.Injectable)(),
|
|
516
|
+
__metadata("design:paramtypes", [action_log_1.ActionLogService])
|
|
517
|
+
], BaseService);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./base-service.interface"), exports);
|
|
18
|
+
__exportStar(require("./base-service.module"), exports);
|
|
19
|
+
__exportStar(require("./base-service.service"), exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type PaginationQuery } from '@bearei/contracts';
|
|
2
|
+
import type { Order } from './common.interface';
|
|
3
|
+
export declare class ListQueryDto implements PaginationQuery {
|
|
4
|
+
page?: number;
|
|
5
|
+
pageSize?: number;
|
|
6
|
+
withTotal?: boolean;
|
|
7
|
+
sortOrder?: Order;
|
|
8
|
+
ids?: string[];
|
|
9
|
+
createdAtRange?: (Date | string)[];
|
|
10
|
+
}
|
|
11
|
+
export declare class ByIdDto {
|
|
12
|
+
id: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class ByEmailDto {
|
|
15
|
+
email: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class ExcludeIdDto {
|
|
18
|
+
excludeId?: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ExcludeIdDto = exports.ByEmailDto = exports.ByIdDto = exports.ListQueryDto = void 0;
|
|
16
|
+
const contracts_1 = require("@bearei/contracts");
|
|
17
|
+
const class_transformer_1 = require("class-transformer");
|
|
18
|
+
const class_validator_1 = require("class-validator");
|
|
19
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
20
|
+
const common_enum_1 = require("./common.enum");
|
|
21
|
+
const decorators_1 = require("./decorators");
|
|
22
|
+
const toNumber = ({ value }) => value === '' || value === undefined || value === null ? value : Number(value);
|
|
23
|
+
class ListQueryDto {
|
|
24
|
+
page;
|
|
25
|
+
pageSize;
|
|
26
|
+
withTotal;
|
|
27
|
+
sortOrder;
|
|
28
|
+
ids;
|
|
29
|
+
createdAtRange;
|
|
30
|
+
}
|
|
31
|
+
exports.ListQueryDto = ListQueryDto;
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_validator_1.IsOptional)(),
|
|
34
|
+
(0, class_validator_1.Min)(1),
|
|
35
|
+
(0, class_validator_1.IsInt)(),
|
|
36
|
+
(0, class_transformer_1.Transform)(toNumber),
|
|
37
|
+
__metadata("design:type", Number)
|
|
38
|
+
], ListQueryDto.prototype, "page", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
(0, class_validator_1.IsOptional)(),
|
|
41
|
+
(0, class_validator_1.Max)(contracts_1.MAX_PAGE_SIZE),
|
|
42
|
+
(0, class_validator_1.Min)(1),
|
|
43
|
+
(0, class_validator_1.IsInt)(),
|
|
44
|
+
(0, class_transformer_1.Transform)(toNumber),
|
|
45
|
+
__metadata("design:type", Number)
|
|
46
|
+
], ListQueryDto.prototype, "pageSize", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, class_validator_1.IsOptional)(),
|
|
49
|
+
(0, class_validator_1.IsBoolean)(),
|
|
50
|
+
(0, class_transformer_1.Transform)(({ value }) => (typeof value === 'string' ? value === 'true' : value)),
|
|
51
|
+
__metadata("design:type", Boolean)
|
|
52
|
+
], ListQueryDto.prototype, "withTotal", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
(0, class_validator_1.IsOptional)(),
|
|
55
|
+
(0, class_validator_1.IsEnum)(common_enum_1.ORDER),
|
|
56
|
+
__metadata("design:type", String)
|
|
57
|
+
], ListQueryDto.prototype, "sortOrder", void 0);
|
|
58
|
+
__decorate([
|
|
59
|
+
(0, class_validator_1.IsOptional)(),
|
|
60
|
+
(0, class_validator_1.ArrayMaxSize)(1024),
|
|
61
|
+
(0, class_validator_1.ArrayMinSize)(1),
|
|
62
|
+
(0, decorators_1.IsNanoId)({ each: true }),
|
|
63
|
+
(0, class_transformer_1.Transform)(({ value }) => (typeof value === 'string' ? value.split(',').filter(item => item) : value)),
|
|
64
|
+
__metadata("design:type", Array)
|
|
65
|
+
], ListQueryDto.prototype, "ids", void 0);
|
|
66
|
+
__decorate([
|
|
67
|
+
(0, class_validator_1.IsOptional)(),
|
|
68
|
+
(0, class_validator_1.ArrayMaxSize)(2),
|
|
69
|
+
(0, class_validator_1.ArrayMinSize)(2),
|
|
70
|
+
(0, class_validator_1.IsDate)({ each: true }),
|
|
71
|
+
(0, class_transformer_1.Transform)(({ value }) => {
|
|
72
|
+
if (typeof value === 'string') {
|
|
73
|
+
return value
|
|
74
|
+
.split(',')
|
|
75
|
+
.filter(item => item)
|
|
76
|
+
.map(item => dayjs_1.default.utc(item).toDate());
|
|
77
|
+
}
|
|
78
|
+
if (Array.isArray(value)) {
|
|
79
|
+
return value.map(item => (item instanceof Date ? item : dayjs_1.default.utc(item).toDate()));
|
|
80
|
+
}
|
|
81
|
+
return value;
|
|
82
|
+
}),
|
|
83
|
+
__metadata("design:type", Array)
|
|
84
|
+
], ListQueryDto.prototype, "createdAtRange", void 0);
|
|
85
|
+
class ByIdDto {
|
|
86
|
+
id;
|
|
87
|
+
}
|
|
88
|
+
exports.ByIdDto = ByIdDto;
|
|
89
|
+
__decorate([
|
|
90
|
+
(0, decorators_1.IsNanoId)(),
|
|
91
|
+
(0, class_validator_1.IsDefined)(),
|
|
92
|
+
__metadata("design:type", String)
|
|
93
|
+
], ByIdDto.prototype, "id", void 0);
|
|
94
|
+
class ByEmailDto {
|
|
95
|
+
email;
|
|
96
|
+
}
|
|
97
|
+
exports.ByEmailDto = ByEmailDto;
|
|
98
|
+
__decorate([
|
|
99
|
+
(0, class_validator_1.IsEmail)(),
|
|
100
|
+
(0, class_validator_1.IsDefined)(),
|
|
101
|
+
__metadata("design:type", String)
|
|
102
|
+
], ByEmailDto.prototype, "email", void 0);
|
|
103
|
+
class ExcludeIdDto {
|
|
104
|
+
excludeId;
|
|
105
|
+
}
|
|
106
|
+
exports.ExcludeIdDto = ExcludeIdDto;
|
|
107
|
+
__decorate([
|
|
108
|
+
(0, class_validator_1.IsOptional)(),
|
|
109
|
+
(0, decorators_1.IsNanoId)(),
|
|
110
|
+
__metadata("design:type", String)
|
|
111
|
+
], ExcludeIdDto.prototype, "excludeId", void 0);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseEntity } from 'typeorm';
|
|
2
|
+
export declare class CommonEntity extends BaseEntity {
|
|
3
|
+
internalId: number;
|
|
4
|
+
id: string;
|
|
5
|
+
version: number;
|
|
6
|
+
createdAt: Date | string;
|
|
7
|
+
updatedAt: Date | string;
|
|
8
|
+
deletedAt: Date | string | null;
|
|
9
|
+
beforeInsert(): void;
|
|
10
|
+
beforeUpdate(): void;
|
|
11
|
+
}
|