@pcg/core 1.0.0-alpha.1 → 1.0.0-alpha.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/dist/index.d.ts +21 -1179
- package/dist/index.js +76 -1856
- package/dist/index.js.map +1 -1
- package/package.json +16 -4
- package/.turbo/turbo-build.log +0 -16
- package/CHANGELOG.md +0 -14
- package/src/abstracts/index.ts +0 -3
- package/src/abstracts/nestjs-resource-service.ts +0 -154
- package/src/abstracts/nestjs-service.ts +0 -25
- package/src/configs/app.config.ts +0 -185
- package/src/configs/db.config.ts +0 -122
- package/src/configs/index.ts +0 -4
- package/src/configs/logger.config.ts +0 -62
- package/src/context/action-context.ts +0 -34
- package/src/context/current-user.ts +0 -49
- package/src/context/index.ts +0 -5
- package/src/context/platform-method-context.ts +0 -5
- package/src/context/service-method-context.ts +0 -47
- package/src/db/snake-naming.strategy.ts +0 -277
- package/src/enums/app-env.enum.ts +0 -36
- package/src/enums/app-mode.enum.ts +0 -5
- package/src/enums/app-server.enum.ts +0 -39
- package/src/enums/index.ts +0 -4
- package/src/enums/worker-mode.enum.ts +0 -11
- package/src/errors/access-denied.error.ts +0 -18
- package/src/errors/bad-request.error.ts +0 -9
- package/src/errors/forbidden.error.ts +0 -9
- package/src/errors/index.ts +0 -8
- package/src/errors/input-validation.error.ts +0 -16
- package/src/errors/nest-error.filter.ts +0 -70
- package/src/errors/nest-error.ts +0 -63
- package/src/errors/not-found.error.ts +0 -9
- package/src/errors/unauthorized.error.ts +0 -9
- package/src/exceptions/http-exception-response.ts +0 -34
- package/src/exceptions/http-exceptions.filter.ts +0 -95
- package/src/index.ts +0 -32
- package/src/jwt/extractors.ts +0 -80
- package/src/jwt/types.ts +0 -209
- package/src/logger/classes/logger-factory.ts +0 -54
- package/src/logger/classes/logger.ts +0 -340
- package/src/logger/classes/nest-system-logger.ts +0 -63
- package/src/logger/classes/typeorm-logger.ts +0 -83
- package/src/logger/index.ts +0 -20
- package/src/logger/logger.constants.ts +0 -24
- package/src/logger/logger.interfaces.ts +0 -98
- package/src/logger/logger.module.ts +0 -45
- package/src/logger/logger.providers.ts +0 -140
- package/src/logger/winston.tools.ts +0 -241
- package/src/middlewares/app.middleware.ts +0 -26
- package/src/middlewares/index.ts +0 -1
- package/src/modules/hooks/base-hook.ts +0 -64
- package/src/modules/hooks/decorators/on-hook.decorator.ts +0 -19
- package/src/modules/hooks/hooks.module.ts +0 -10
- package/src/modules/hooks/hooks.service.ts +0 -28
- package/src/modules/hooks/index.ts +0 -11
- package/src/modules/id/id.module.ts +0 -26
- package/src/modules/id/id.service.ts +0 -57
- package/src/modules/id/index.ts +0 -2
- package/src/modules/postgres-pubsub/index.ts +0 -3
- package/src/modules/postgres-pubsub/postgres-pubsub.module.ts +0 -14
- package/src/modules/postgres-pubsub/postgres-pubsub.ts +0 -461
- package/src/pagination/constants.ts +0 -9
- package/src/pagination/cursor/cursor-pagination.exception.ts +0 -16
- package/src/pagination/cursor/cursor-pagination.helpers.ts +0 -145
- package/src/pagination/cursor/cursor-pagination.input.ts +0 -96
- package/src/pagination/cursor/cursor-pagination.types.ts +0 -127
- package/src/pagination/index.ts +0 -9
- package/src/pagination/offset/offset-pagination.exception.ts +0 -15
- package/src/pagination/offset/offset-pagination.helpers.ts +0 -122
- package/src/pagination/offset/offset-pagination.input.ts +0 -30
- package/src/pagination/offset/offset-pagination.types.ts +0 -82
- package/src/pagination/tools.ts +0 -53
- package/src/tools/compose.ts +0 -92
- package/src/tools/convert-to-bigint.ts +0 -27
- package/src/tools/create-list-meta.ts +0 -64
- package/src/tools/define-statuses.ts +0 -15
- package/src/tools/env.ts +0 -139
- package/src/tools/fetch-total-with-query.ts +0 -48
- package/src/tools/generate-entity-id.ts +0 -23
- package/src/tools/get-request-language.ts +0 -13
- package/src/tools/is-object.ts +0 -1
- package/src/tools/postgres/locale-to-pg-collate.ts +0 -21
- package/src/tools/remove-undefined-properties.ts +0 -20
- package/src/tools/request-id.ts +0 -25
- package/src/tools/stringify-opts.ts +0 -20
- package/src/tools/typeorm/add-filter.ts +0 -164
- package/src/tools/typeorm/ensure-inner-join.ts +0 -36
- package/src/tools/typeorm/ensure-left-join.ts +0 -36
- package/src/tools/typeorm/is-alias-already-busy.ts +0 -25
- package/src/tools/wait.ts +0 -26
- package/src/types/express-request.ts +0 -8
- package/src/types/list-mehod-options.ts +0 -32
- package/src/types/list-meta.ts +0 -16
- package/src/types/maybe.ts +0 -2
- package/src/validation/index.ts +0 -1
- package/src/validation/validation-pipe.ts +0 -14
- package/tsconfig.lib.json +0 -9
- package/tsdown.config.ts +0 -15
package/dist/index.js
CHANGED
|
@@ -1,65 +1,49 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { getConfigToken, registerAs } from "@nestjs/config";
|
|
5
|
-
import { createRandomString, pluralToSingular, singularToPlural, snakeCase } from "@pcg/text-kit";
|
|
6
|
-
import { Type as Type$1, plainToInstance } from "class-transformer";
|
|
7
|
-
import { IsBoolean, IsEnum, IsNumber, IsOptional, IsString, Min, validateSync } from "class-validator";
|
|
8
|
-
import { ArgsType, Field, Int, ObjectType } from "@nestjs/graphql";
|
|
9
|
-
import { isFunction, isObject as isObject$1, isPlainObject } from "@nestjs/common/utils/shared.utils";
|
|
10
|
-
import { isObject } from "@pcg/predicates";
|
|
11
|
-
import { GraphQLError } from "graphql";
|
|
12
|
-
import { AbstractLogger } from "typeorm/logger/AbstractLogger.js";
|
|
13
|
-
import * as winston from "winston";
|
|
14
|
-
import { Logger as Logger$1, createLogger, format } from "winston";
|
|
15
|
-
import clc from "cli-color";
|
|
16
|
-
import fg from "fast-glob";
|
|
1
|
+
import { plainToInstance } from "class-transformer";
|
|
2
|
+
import { validateSync } from "class-validator";
|
|
3
|
+
import { createRandomString } from "@pcg/text-kit";
|
|
17
4
|
import { parse } from "accept-language-parser";
|
|
18
|
-
import {
|
|
5
|
+
import { Brackets, In, IsNull } from "typeorm";
|
|
19
6
|
|
|
20
|
-
//#region src/
|
|
7
|
+
//#region src/tools/convert-to-bigint.ts
|
|
21
8
|
/**
|
|
22
|
-
*
|
|
9
|
+
* Converts a number or string value to a BigInt, preserving null and undefined values.
|
|
10
|
+
*
|
|
11
|
+
* @param value - The value to convert. Can be a number, string, undefined, or null.
|
|
12
|
+
* @returns The converted BigInt value, or the original value if it was null or undefined.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* convertToBigInt(123) // returns 123n
|
|
17
|
+
* convertToBigInt("456") // returns 456n
|
|
18
|
+
* convertToBigInt(null) // returns null
|
|
19
|
+
* convertToBigInt(undefined) // returns undefined
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @throws {RangeError} Throws when the input cannot be converted to a valid BigInt.
|
|
23
23
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
AppEnv$1["LOCAL"] = "local";
|
|
30
|
-
/**
|
|
31
|
-
* Test environment.
|
|
32
|
-
* Used when running tests.
|
|
33
|
-
*/
|
|
34
|
-
AppEnv$1["TEST"] = "test";
|
|
35
|
-
/**
|
|
36
|
-
* Development environment.
|
|
37
|
-
* Used when deploying to a development server.
|
|
38
|
-
* Development server provide early access to new features.
|
|
39
|
-
*/
|
|
40
|
-
AppEnv$1["DEVELOPMENT"] = "development";
|
|
41
|
-
/**
|
|
42
|
-
* Stage environment.
|
|
43
|
-
* Used when deploying to a stage server.
|
|
44
|
-
* Stage is a pre-production environment.
|
|
45
|
-
*/
|
|
46
|
-
AppEnv$1["STAGE"] = "stage";
|
|
47
|
-
/**
|
|
48
|
-
* Production environment.
|
|
49
|
-
* Used when deploying to a production server.
|
|
50
|
-
*/
|
|
51
|
-
AppEnv$1["PRODUCTION"] = "production";
|
|
52
|
-
return AppEnv$1;
|
|
53
|
-
}({});
|
|
24
|
+
const convertToBigInt = (value) => {
|
|
25
|
+
if (value === null) return value;
|
|
26
|
+
if (typeof value === "undefined") return value;
|
|
27
|
+
return BigInt(value);
|
|
28
|
+
};
|
|
54
29
|
|
|
55
30
|
//#endregion
|
|
56
|
-
//#region src/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
31
|
+
//#region src/tools/define-statuses.ts
|
|
32
|
+
/**
|
|
33
|
+
* Define statuses. Returns array of statuses from filter or default statuses
|
|
34
|
+
* @param statuses - array of statuses from filter. Can be undefined
|
|
35
|
+
* @param defaultStatuses - array of default statuses
|
|
36
|
+
* @returns final array of statuses
|
|
37
|
+
* @example
|
|
38
|
+
* const statuses = defineStatuses(['active', 'pending'], ['active']);
|
|
39
|
+
* // statuses = ['active', 'pending']
|
|
40
|
+
*
|
|
41
|
+
* const statuses = defineStatuses(undefined, ['active']);
|
|
42
|
+
* // statuses = ['active']
|
|
43
|
+
*/
|
|
44
|
+
const defineStatuses = (statuses, defaultStatuses) => {
|
|
45
|
+
return Array.isArray(statuses) ? statuses : defaultStatuses;
|
|
46
|
+
};
|
|
63
47
|
|
|
64
48
|
//#endregion
|
|
65
49
|
//#region src/tools/env.ts
|
|
@@ -87,262 +71,6 @@ const validateEnv = (cls) => {
|
|
|
87
71
|
if (errors.length > 0) throw new Error(errors.toString());
|
|
88
72
|
return validatedConfig;
|
|
89
73
|
};
|
|
90
|
-
/**
|
|
91
|
-
* Returns a string with a dash prefix based on the current environment.
|
|
92
|
-
* If the environment is development or local, returns '-dev'.
|
|
93
|
-
* If the environment is stage, returns '-stage'.
|
|
94
|
-
* Otherwise, returns an empty string.
|
|
95
|
-
*
|
|
96
|
-
* @returns a string with a dash prefix based on the current environment
|
|
97
|
-
* @example
|
|
98
|
-
* ```typescript
|
|
99
|
-
* const name = `my-app${withDashEnv()}`;
|
|
100
|
-
* ```
|
|
101
|
-
*/
|
|
102
|
-
const withDashEnv = () => {
|
|
103
|
-
if (process.env.APP_ENV === AppEnv.DEVELOPMENT || process.env.APP_ENV === AppEnv.LOCAL || process.env.APP_ENV === AppEnv.TEST) return "-dev";
|
|
104
|
-
if (process.env.APP_ENV === AppEnv.STAGE) return "-stage";
|
|
105
|
-
return "";
|
|
106
|
-
};
|
|
107
|
-
/**
|
|
108
|
-
* Returns a string with a dash prefix based on the current environment.
|
|
109
|
-
* If the environment is development or local, returns '.dev'.
|
|
110
|
-
* If the environment is stage, returns '.stage'.
|
|
111
|
-
* Otherwise, returns an empty string.
|
|
112
|
-
*
|
|
113
|
-
* @returns a string with a dot prefix based on the current environment
|
|
114
|
-
* @example
|
|
115
|
-
* ```typescript
|
|
116
|
-
* const name = `config${withDotEnv()}`;
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
const withDotEnv = () => {
|
|
120
|
-
if (process.env.APP_ENV === AppEnv.DEVELOPMENT || process.env.APP_ENV === AppEnv.LOCAL || process.env.APP_ENV === AppEnv.TEST) return ".dev";
|
|
121
|
-
if (process.env.APP_ENV === AppEnv.STAGE) return ".stage";
|
|
122
|
-
return "";
|
|
123
|
-
};
|
|
124
|
-
/**
|
|
125
|
-
* Returns a string with a colon prefix based on the current environment.
|
|
126
|
-
* If the environment is development or local, returns ':dev'.
|
|
127
|
-
* If the environment is stage, returns ':stage'.
|
|
128
|
-
* Otherwise, returns an empty string.
|
|
129
|
-
*
|
|
130
|
-
* @returns a string with a colon prefix based on the current environment
|
|
131
|
-
* @example
|
|
132
|
-
* ```typescript
|
|
133
|
-
* const name = `my:app${withColonEnv()}`;
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
const withColonEnv = () => {
|
|
137
|
-
if (process.env.APP_ENV === AppEnv.DEVELOPMENT || process.env.APP_ENV === AppEnv.LOCAL || process.env.APP_ENV === AppEnv.TEST) return ":dev";
|
|
138
|
-
if (process.env.APP_ENV === AppEnv.STAGE) return ":stage";
|
|
139
|
-
return "";
|
|
140
|
-
};
|
|
141
|
-
/**
|
|
142
|
-
* Returns a string with an underscore prefix based on the current environment.
|
|
143
|
-
* If the environment is development or local, returns '_dev'.
|
|
144
|
-
* If the environment is stage, returns '_stage'.
|
|
145
|
-
* Otherwise, returns an empty string.
|
|
146
|
-
*
|
|
147
|
-
* @returns a string with an underscore prefix based on the current environment
|
|
148
|
-
* @example
|
|
149
|
-
* ```typescript
|
|
150
|
-
* const name = `my_app${withUnderscoreEnv()}`;
|
|
151
|
-
* ```
|
|
152
|
-
*/
|
|
153
|
-
const withUnderscoreEnv = () => {
|
|
154
|
-
if (process.env.APP_ENV === AppEnv.DEVELOPMENT || process.env.APP_ENV === AppEnv.LOCAL || process.env.APP_ENV === AppEnv.TEST) return "_dev";
|
|
155
|
-
if (process.env.APP_ENV === AppEnv.STAGE) return "_stage";
|
|
156
|
-
return "";
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
//#endregion
|
|
160
|
-
//#region \0@oxc-project+runtime@0.95.0/helpers/decorateMetadata.js
|
|
161
|
-
function __decorateMetadata(k, v) {
|
|
162
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
//#endregion
|
|
166
|
-
//#region \0@oxc-project+runtime@0.95.0/helpers/decorate.js
|
|
167
|
-
function __decorate(decorators, target, key, desc) {
|
|
168
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
169
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
170
|
-
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;
|
|
171
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
//#endregion
|
|
175
|
-
//#region src/configs/app.config.ts
|
|
176
|
-
var _ref$4;
|
|
177
|
-
/**
|
|
178
|
-
* NestJS injection token for app config
|
|
179
|
-
*/
|
|
180
|
-
const APP_CONFIG_TOKEN = "APP_CONFIG_TOKEN";
|
|
181
|
-
const InjectAppConfig = () => Inject(getConfigToken(APP_CONFIG_TOKEN));
|
|
182
|
-
/**
|
|
183
|
-
* Application config environment variables
|
|
184
|
-
*/
|
|
185
|
-
var AppConfigEnvironmentVariables = class {
|
|
186
|
-
/**
|
|
187
|
-
* Application port
|
|
188
|
-
* @example
|
|
189
|
-
* ```yaml
|
|
190
|
-
* PORT: 3000
|
|
191
|
-
* ```
|
|
192
|
-
*/
|
|
193
|
-
PORT = 3e3;
|
|
194
|
-
/**
|
|
195
|
-
* Application host
|
|
196
|
-
* @example
|
|
197
|
-
* ```yaml
|
|
198
|
-
* APP_HOST: 'https://app-api.example.com'
|
|
199
|
-
* # or
|
|
200
|
-
* APP_HOST: 'http://localhost:3000'
|
|
201
|
-
* ```
|
|
202
|
-
*/
|
|
203
|
-
APP_HOST;
|
|
204
|
-
/**
|
|
205
|
-
* Application UI host
|
|
206
|
-
* @example
|
|
207
|
-
* ```yaml
|
|
208
|
-
* APP_UI_HOST: 'https://app.example.com'
|
|
209
|
-
* # or
|
|
210
|
-
* APP_UI_HOST: 'http://localhost:4200'
|
|
211
|
-
* ```
|
|
212
|
-
*/
|
|
213
|
-
APP_UI_HOST;
|
|
214
|
-
/**
|
|
215
|
-
* Application environment. Can be 'local', 'development', 'stage', 'production'
|
|
216
|
-
* @example
|
|
217
|
-
* ```yaml
|
|
218
|
-
* APP_ENV: 'local'
|
|
219
|
-
* ```
|
|
220
|
-
*/
|
|
221
|
-
APP_ENV;
|
|
222
|
-
/**
|
|
223
|
-
* Application service account id (user with type SA in users table)
|
|
224
|
-
* @example
|
|
225
|
-
* ```yaml
|
|
226
|
-
* APP_SERVICE_ACCOUNT_ID: 'hcu:xxxxxxxxxxx'
|
|
227
|
-
* ```
|
|
228
|
-
*/
|
|
229
|
-
APP_SERVICE_ACCOUNT_ID;
|
|
230
|
-
/**
|
|
231
|
-
* Application fallback language
|
|
232
|
-
* @example
|
|
233
|
-
* ```yaml
|
|
234
|
-
* FALLBACK_LANGUAGE: 'es'
|
|
235
|
-
* ```
|
|
236
|
-
*/
|
|
237
|
-
FALLBACK_LANGUAGE = "en";
|
|
238
|
-
};
|
|
239
|
-
__decorate([
|
|
240
|
-
Type$1(() => Number),
|
|
241
|
-
IsNumber(),
|
|
242
|
-
__decorateMetadata("design:type", Object)
|
|
243
|
-
], AppConfigEnvironmentVariables.prototype, "PORT", void 0);
|
|
244
|
-
__decorate([
|
|
245
|
-
IsOptional(),
|
|
246
|
-
IsString(),
|
|
247
|
-
__decorateMetadata("design:type", String)
|
|
248
|
-
], AppConfigEnvironmentVariables.prototype, "APP_HOST", void 0);
|
|
249
|
-
__decorate([
|
|
250
|
-
IsOptional(),
|
|
251
|
-
IsString(),
|
|
252
|
-
__decorateMetadata("design:type", String)
|
|
253
|
-
], AppConfigEnvironmentVariables.prototype, "APP_UI_HOST", void 0);
|
|
254
|
-
__decorate([IsEnum(AppEnv), __decorateMetadata("design:type", typeof (_ref$4 = typeof AppEnv !== "undefined" && AppEnv) === "function" ? _ref$4 : Object)], AppConfigEnvironmentVariables.prototype, "APP_ENV", void 0);
|
|
255
|
-
__decorate([
|
|
256
|
-
IsOptional(),
|
|
257
|
-
IsString(),
|
|
258
|
-
__decorateMetadata("design:type", String)
|
|
259
|
-
], AppConfigEnvironmentVariables.prototype, "APP_SERVICE_ACCOUNT_ID", void 0);
|
|
260
|
-
__decorate([
|
|
261
|
-
IsOptional(),
|
|
262
|
-
IsString(),
|
|
263
|
-
__decorateMetadata("design:type", Object)
|
|
264
|
-
], AppConfigEnvironmentVariables.prototype, "FALLBACK_LANGUAGE", void 0);
|
|
265
|
-
/**
|
|
266
|
-
* Create Main Application Config
|
|
267
|
-
* @example
|
|
268
|
-
* ```ts
|
|
269
|
-
* // src/config/index.ts
|
|
270
|
-
*
|
|
271
|
-
* import { createAppConfig } from '#/dist/configs';
|
|
272
|
-
*
|
|
273
|
-
* export const appConfig = createAppConfig({
|
|
274
|
-
* name: 'Jetstream',
|
|
275
|
-
* shortname: 'js',
|
|
276
|
-
* });
|
|
277
|
-
* ```
|
|
278
|
-
*/
|
|
279
|
-
const createAppConfig = (opts) => {
|
|
280
|
-
return registerAs(APP_CONFIG_TOKEN, () => {
|
|
281
|
-
const env = validateEnv(AppConfigEnvironmentVariables);
|
|
282
|
-
return {
|
|
283
|
-
env: env.APP_ENV,
|
|
284
|
-
name: opts.name,
|
|
285
|
-
shortname: opts.shortname,
|
|
286
|
-
port: env.PORT,
|
|
287
|
-
host: env.APP_HOST,
|
|
288
|
-
mode: opts.mode || AppMode.STANDALONE,
|
|
289
|
-
uiHost: env.APP_UI_HOST,
|
|
290
|
-
appServiceAccountId: env.APP_SERVICE_ACCOUNT_ID,
|
|
291
|
-
fallbackLanguage: env.FALLBACK_LANGUAGE
|
|
292
|
-
};
|
|
293
|
-
});
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
//#endregion
|
|
297
|
-
//#region src/enums/app-server.enum.ts
|
|
298
|
-
/**
|
|
299
|
-
* Enum for the NestJS server mode
|
|
300
|
-
*/
|
|
301
|
-
let AppServer = /* @__PURE__ */ function(AppServer$1) {
|
|
302
|
-
/**
|
|
303
|
-
* NestJS HTTP server with GraphQL
|
|
304
|
-
*/
|
|
305
|
-
AppServer$1["HTTP"] = "http";
|
|
306
|
-
/**
|
|
307
|
-
* NestJS gRPC server
|
|
308
|
-
*/
|
|
309
|
-
AppServer$1["GRPC"] = "grpc";
|
|
310
|
-
/**
|
|
311
|
-
* NestJS WebSocket server
|
|
312
|
-
*/
|
|
313
|
-
AppServer$1["WS"] = "ws";
|
|
314
|
-
/**
|
|
315
|
-
* Run as a worker
|
|
316
|
-
*/
|
|
317
|
-
AppServer$1["WORKER"] = "worker";
|
|
318
|
-
/**
|
|
319
|
-
* Run as an agent
|
|
320
|
-
*/
|
|
321
|
-
AppServer$1["AGENT"] = "agent";
|
|
322
|
-
/**
|
|
323
|
-
* Run as an bot (e.g. Slack bot)
|
|
324
|
-
*/
|
|
325
|
-
AppServer$1["BOT"] = "bot";
|
|
326
|
-
/**
|
|
327
|
-
* Run as Cloud Run job
|
|
328
|
-
*/
|
|
329
|
-
AppServer$1["CLOUDRUN_JOB"] = "cloudrun-job";
|
|
330
|
-
return AppServer$1;
|
|
331
|
-
}({});
|
|
332
|
-
|
|
333
|
-
//#endregion
|
|
334
|
-
//#region src/enums/worker-mode.enum.ts
|
|
335
|
-
let WorkerMode = /* @__PURE__ */ function(WorkerMode$1) {
|
|
336
|
-
/**
|
|
337
|
-
* Run jobs in loop
|
|
338
|
-
*/
|
|
339
|
-
WorkerMode$1["LOOP"] = "loop";
|
|
340
|
-
/**
|
|
341
|
-
* Run one job and exit
|
|
342
|
-
*/
|
|
343
|
-
WorkerMode$1["ONE_JOB"] = "one-job";
|
|
344
|
-
return WorkerMode$1;
|
|
345
|
-
}({});
|
|
346
74
|
|
|
347
75
|
//#endregion
|
|
348
76
|
//#region src/tools/generate-entity-id.ts
|
|
@@ -369,356 +97,31 @@ const generateEntityId = (product, prefix, delimiter = ":", size = 11) => {
|
|
|
369
97
|
};
|
|
370
98
|
|
|
371
99
|
//#endregion
|
|
372
|
-
//#region
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
//#endregion
|
|
380
|
-
//#region src/modules/id/id.service.ts
|
|
381
|
-
let IdService = class IdService$1 {
|
|
382
|
-
constructor(appConfig) {
|
|
383
|
-
this.appConfig = appConfig;
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Returns a delimiter string based on the current environment.
|
|
387
|
-
* This delimiter is used in constructing the entity IDs.
|
|
388
|
-
* The delimiter is ':dev:' for development environments,
|
|
389
|
-
* :stage:' for staging environments and ':' for other environments.
|
|
390
|
-
*
|
|
391
|
-
* This allows for better differentiation and traceability of entities across various environments.
|
|
392
|
-
*/
|
|
393
|
-
get delimiter() {
|
|
394
|
-
switch (this.appConfig.env) {
|
|
395
|
-
case AppEnv.TEST: return ":test:";
|
|
396
|
-
case AppEnv.DEVELOPMENT: return ":dev:";
|
|
397
|
-
case AppEnv.STAGE: return ":stage:";
|
|
398
|
-
default: return ":";
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Generates unique id for entity
|
|
403
|
-
* @param prefix - entity id prefix in database (e.g. 'u' for users)
|
|
404
|
-
* @param app - app shortname (e.g. 'js')
|
|
405
|
-
* @returns id in format 'jsu:xxxxxxxxxxx' or 'jsu:stage:xxxxxxxxxxx' for staging environment
|
|
406
|
-
*/
|
|
407
|
-
generateEntityId(prefix, app) {
|
|
408
|
-
return generateEntityId(app ?? this.appConfig.shortname, prefix, this.delimiter, 11);
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Generates unique id with length 11
|
|
412
|
-
* @returns id in format 'xxxxxxxxxxx'
|
|
413
|
-
*/
|
|
414
|
-
generateId(size) {
|
|
415
|
-
return createRandomString(size);
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
IdService = __decorate([
|
|
419
|
-
Injectable(),
|
|
420
|
-
__decorateParam(0, Inject(getConfigToken(APP_CONFIG_TOKEN))),
|
|
421
|
-
__decorateMetadata("design:paramtypes", [Object])
|
|
422
|
-
], IdService);
|
|
423
|
-
|
|
424
|
-
//#endregion
|
|
425
|
-
//#region src/modules/id/id.module.ts
|
|
426
|
-
let IdModule = class IdModule$1 {};
|
|
427
|
-
IdModule = __decorate([Global(), Module({
|
|
428
|
-
providers: [IdService],
|
|
429
|
-
exports: [IdService]
|
|
430
|
-
})], IdModule);
|
|
431
|
-
|
|
432
|
-
//#endregion
|
|
433
|
-
//#region src/errors/nest-error.ts
|
|
434
|
-
/**
|
|
435
|
-
* Custom error class for NestJS applications that extends the native Error class.
|
|
436
|
-
*
|
|
437
|
-
* This error class provides additional context and structured error handling
|
|
438
|
-
* capabilities beyond the standard Error object.
|
|
439
|
-
*
|
|
440
|
-
* @example
|
|
441
|
-
* ```typescript
|
|
442
|
-
* throw new NestError({
|
|
443
|
-
* key: 'AUTH_USER_NOT_FOUND',
|
|
444
|
-
* message: 'User with the specified ID was not found',
|
|
445
|
-
* context: { userId: '123' },
|
|
446
|
-
* cause: originalError
|
|
447
|
-
* });
|
|
448
|
-
* ```
|
|
449
|
-
*/
|
|
450
|
-
var NestError = class extends Error {
|
|
451
|
-
key;
|
|
452
|
-
context;
|
|
453
|
-
httpStatusCode = HttpStatus.INTERNAL_SERVER_ERROR;
|
|
454
|
-
silent;
|
|
455
|
-
constructor(opts) {
|
|
456
|
-
super(opts.message, opts.cause instanceof Error ? { cause: opts.cause } : void 0);
|
|
457
|
-
this.name = "NestError";
|
|
458
|
-
this.key = opts.key;
|
|
459
|
-
this.context = opts.context;
|
|
460
|
-
this.silent = opts.silent ?? false;
|
|
461
|
-
}
|
|
462
|
-
};
|
|
463
|
-
|
|
464
|
-
//#endregion
|
|
465
|
-
//#region src/errors/bad-request.error.ts
|
|
466
|
-
var BadRequestError = class extends NestError {
|
|
467
|
-
constructor(opts) {
|
|
468
|
-
super(opts);
|
|
469
|
-
this.name = "BadRequestError";
|
|
470
|
-
this.httpStatusCode = 400;
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
|
|
474
|
-
//#endregion
|
|
475
|
-
//#region src/errors/not-found.error.ts
|
|
476
|
-
var NotFoundError = class extends NestError {
|
|
477
|
-
constructor(opts) {
|
|
478
|
-
super(opts);
|
|
479
|
-
this.name = "NotFoundError";
|
|
480
|
-
this.httpStatusCode = 404;
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
//#endregion
|
|
485
|
-
//#region src/pagination/constants.ts
|
|
486
|
-
/**
|
|
487
|
-
* Pagination default limit value
|
|
488
|
-
*/
|
|
489
|
-
const PAGINATION_DEFAULT_LIMIT = 20;
|
|
490
|
-
|
|
491
|
-
//#endregion
|
|
492
|
-
//#region src/errors/forbidden.error.ts
|
|
493
|
-
var ForbiddenError = class extends NestError {
|
|
494
|
-
constructor(opts) {
|
|
495
|
-
super(opts);
|
|
496
|
-
this.name = "ForbiddenError";
|
|
497
|
-
this.httpStatusCode = 403;
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
//#endregion
|
|
502
|
-
//#region src/errors/access-denied.error.ts
|
|
503
|
-
var AccessDeniedError = class extends ForbiddenError {
|
|
504
|
-
constructor(opts) {
|
|
505
|
-
super({
|
|
506
|
-
key: "AUTH_ACCESS_DENIED",
|
|
507
|
-
message: opts.message || `Access denied: you don't have permission to perform "${opts.action}" action`,
|
|
508
|
-
context: opts.context
|
|
509
|
-
});
|
|
510
|
-
this.name = "AccessDeniedError";
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
//#endregion
|
|
515
|
-
//#region src/errors/input-validation.error.ts
|
|
516
|
-
var InputValidationError = class extends NestError {
|
|
517
|
-
constructor(errors) {
|
|
518
|
-
super({
|
|
519
|
-
message: "Input validation failed",
|
|
520
|
-
key: "NST_INPUT_VALIDATION_ERROR",
|
|
521
|
-
context: errors ? { errors } : void 0
|
|
522
|
-
});
|
|
523
|
-
this.name = "InputValidationError";
|
|
524
|
-
this.httpStatusCode = 400;
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
|
|
528
|
-
//#endregion
|
|
529
|
-
//#region src/errors/unauthorized.error.ts
|
|
530
|
-
var UnauthorizedError = class extends NestError {
|
|
531
|
-
constructor(opts) {
|
|
532
|
-
super(opts);
|
|
533
|
-
this.name = "UnauthorizedError";
|
|
534
|
-
this.httpStatusCode = 401;
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
//#endregion
|
|
539
|
-
//#region src/pagination/cursor/cursor-pagination.types.ts
|
|
540
|
-
let CursorPaginationPageInfo = class CursorPaginationPageInfo$1 {
|
|
541
|
-
/**
|
|
542
|
-
* The cursor to the first item in the list
|
|
543
|
-
*/
|
|
544
|
-
startCursor;
|
|
545
|
-
/**
|
|
546
|
-
* The cursor to the last item in the list
|
|
547
|
-
*/
|
|
548
|
-
endCursor;
|
|
549
|
-
/**
|
|
550
|
-
* Whether there are more items in the list before the start cursor
|
|
551
|
-
*/
|
|
552
|
-
hasPreviousPage;
|
|
553
|
-
/**
|
|
554
|
-
* Whether there are more items in the list after the end cursor
|
|
555
|
-
*/
|
|
556
|
-
hasNextPage;
|
|
557
|
-
};
|
|
558
|
-
__decorate([Field(() => String, { nullable: true }), __decorateMetadata("design:type", Object)], CursorPaginationPageInfo.prototype, "startCursor", void 0);
|
|
559
|
-
__decorate([Field(() => String, { nullable: true }), __decorateMetadata("design:type", Object)], CursorPaginationPageInfo.prototype, "endCursor", void 0);
|
|
560
|
-
__decorate([Field(() => Boolean, { nullable: true }), __decorateMetadata("design:type", Boolean)], CursorPaginationPageInfo.prototype, "hasPreviousPage", void 0);
|
|
561
|
-
__decorate([Field(() => Boolean, { nullable: true }), __decorateMetadata("design:type", Boolean)], CursorPaginationPageInfo.prototype, "hasNextPage", void 0);
|
|
562
|
-
CursorPaginationPageInfo = __decorate([ObjectType()], CursorPaginationPageInfo);
|
|
563
|
-
|
|
564
|
-
//#endregion
|
|
565
|
-
//#region src/pagination/cursor/cursor-pagination.input.ts
|
|
566
|
-
let CursorPaginationInput = class CursorPaginationInput$1 {
|
|
567
|
-
/**
|
|
568
|
-
* The amount of items to be requested per page from the start
|
|
569
|
-
* @example
|
|
570
|
-
* ```graphql
|
|
571
|
-
* query {
|
|
572
|
-
* messages(first: 3) {
|
|
573
|
-
* edges {
|
|
574
|
-
* cursor
|
|
575
|
-
* node {
|
|
576
|
-
* id
|
|
577
|
-
* }
|
|
578
|
-
* }
|
|
579
|
-
* }
|
|
580
|
-
* }
|
|
581
|
-
* ```
|
|
582
|
-
*/
|
|
583
|
-
first;
|
|
584
|
-
/**
|
|
585
|
-
* The cursor to start the pagination
|
|
586
|
-
* @example
|
|
587
|
-
* ```graphql
|
|
588
|
-
* query {
|
|
589
|
-
* messages(first: 3, after: "xxx") {
|
|
590
|
-
* edges {
|
|
591
|
-
* cursor
|
|
592
|
-
* node {
|
|
593
|
-
* id
|
|
594
|
-
* }
|
|
595
|
-
* }
|
|
596
|
-
* }
|
|
597
|
-
* }
|
|
598
|
-
* ```
|
|
599
|
-
*/
|
|
600
|
-
after;
|
|
601
|
-
/**
|
|
602
|
-
* The amount of items to be requested per page from the end
|
|
603
|
-
* @example
|
|
604
|
-
* ```graphql
|
|
605
|
-
* query {
|
|
606
|
-
* messages(last: 2) {
|
|
607
|
-
* edges {
|
|
608
|
-
* cursor
|
|
609
|
-
* node {
|
|
610
|
-
* id
|
|
611
|
-
* }
|
|
612
|
-
* }
|
|
613
|
-
* }
|
|
614
|
-
* }
|
|
615
|
-
* ```
|
|
616
|
-
*/
|
|
617
|
-
last;
|
|
618
|
-
/**
|
|
619
|
-
* The cursor to end the pagination
|
|
620
|
-
* @example
|
|
621
|
-
* ```graphql
|
|
622
|
-
* query {
|
|
623
|
-
* messages(last: 2, before: "xxx") {
|
|
624
|
-
* edges {
|
|
625
|
-
* cursor
|
|
626
|
-
* node {
|
|
627
|
-
* id
|
|
628
|
-
* }
|
|
629
|
-
* }
|
|
630
|
-
* }
|
|
631
|
-
* }
|
|
632
|
-
* ```
|
|
633
|
-
*/
|
|
634
|
-
before;
|
|
100
|
+
//#region src/tools/get-request-language.ts
|
|
101
|
+
const getRequestLanguage = (req, fallbackLanguage) => {
|
|
102
|
+
const headers = req.headers;
|
|
103
|
+
return parse(headers["accept-language"])[0]?.code ?? fallbackLanguage;
|
|
635
104
|
};
|
|
636
|
-
__decorate([
|
|
637
|
-
Field(() => Int, { nullable: true }),
|
|
638
|
-
Min(1),
|
|
639
|
-
IsOptional(),
|
|
640
|
-
__decorateMetadata("design:type", Number)
|
|
641
|
-
], CursorPaginationInput.prototype, "first", void 0);
|
|
642
|
-
__decorate([Field(() => String, { nullable: true }), __decorateMetadata("design:type", String)], CursorPaginationInput.prototype, "after", void 0);
|
|
643
|
-
__decorate([
|
|
644
|
-
Field(() => Int, { nullable: true }),
|
|
645
|
-
Min(1),
|
|
646
|
-
IsOptional(),
|
|
647
|
-
__decorateMetadata("design:type", Number)
|
|
648
|
-
], CursorPaginationInput.prototype, "last", void 0);
|
|
649
|
-
__decorate([Field(() => String, { nullable: true }), __decorateMetadata("design:type", String)], CursorPaginationInput.prototype, "before", void 0);
|
|
650
|
-
CursorPaginationInput = __decorate([ArgsType()], CursorPaginationInput);
|
|
651
105
|
|
|
652
106
|
//#endregion
|
|
653
|
-
//#region src/
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
*
|
|
659
|
-
* // sort.fieldName = 'createdAt', sort.direction = 'ASC'; sort.columnName = 'created_at';
|
|
660
|
-
* const sort = extractSortParams(orderBy);
|
|
661
|
-
*/
|
|
662
|
-
const extractSortParams = (orderBy) => {
|
|
663
|
-
const slices = orderBy.split("_");
|
|
664
|
-
if (slices.length !== 2) throw new Error("Invalid orderBy argument");
|
|
665
|
-
return {
|
|
666
|
-
fieldName: slices[0],
|
|
667
|
-
direction: slices[1],
|
|
668
|
-
columnName: snakeCase(slices[0])
|
|
669
|
-
};
|
|
107
|
+
//#region src/tools/remove-undefined-properties.ts
|
|
108
|
+
const removeUndefinedProperties = (obj) => {
|
|
109
|
+
const result = {};
|
|
110
|
+
for (const key in obj) if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== void 0) result[key] = obj[key];
|
|
111
|
+
return result;
|
|
670
112
|
};
|
|
671
113
|
|
|
672
114
|
//#endregion
|
|
673
|
-
//#region src/
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
* the amount of items to be requested per page
|
|
677
|
-
*/
|
|
678
|
-
limit;
|
|
679
|
-
/**
|
|
680
|
-
* @default 1
|
|
681
|
-
* the page that is requested
|
|
682
|
-
*/
|
|
683
|
-
page = 1;
|
|
115
|
+
//#region src/tools/request-id.ts
|
|
116
|
+
const generateRequestId = (appShortName) => {
|
|
117
|
+
return `${appShortName}req:${createRandomString()}`;
|
|
684
118
|
};
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
__decorate([Field(() => Int, {
|
|
691
|
-
defaultValue: 1,
|
|
692
|
-
description: "the page that is requested"
|
|
693
|
-
}), __decorateMetadata("design:type", Number)], OffsetPaginationInput.prototype, "page", void 0);
|
|
694
|
-
OffsetPaginationInput = __decorate([ArgsType()], OffsetPaginationInput);
|
|
695
|
-
|
|
696
|
-
//#endregion
|
|
697
|
-
//#region src/pagination/offset/offset-pagination.types.ts
|
|
698
|
-
let OffsetPaginationPageInfo = class OffsetPaginationPageInfo$1 {
|
|
699
|
-
/**
|
|
700
|
-
* The total amount of pages
|
|
701
|
-
* (total items / limit)
|
|
702
|
-
*/
|
|
703
|
-
totalPages;
|
|
704
|
-
/**
|
|
705
|
-
* The total amount of items
|
|
706
|
-
*/
|
|
707
|
-
totalItems;
|
|
708
|
-
/**
|
|
709
|
-
* The current page
|
|
710
|
-
*/
|
|
711
|
-
page;
|
|
712
|
-
/**
|
|
713
|
-
* The amount of items to be requested per page
|
|
714
|
-
*/
|
|
715
|
-
limit;
|
|
119
|
+
const extractRequestId = (req) => {
|
|
120
|
+
const headers = req.headers;
|
|
121
|
+
if (headers["x-request-id"]) return headers["x-request-id"];
|
|
122
|
+
if (headers["x-cloud-trace-context"]) return req.appShortname + `req:${headers["x-cloud-trace-context"]}`;
|
|
123
|
+
return generateRequestId(req.appShortname);
|
|
716
124
|
};
|
|
717
|
-
__decorate([Field(() => Int, { description: "The total amount of pages (total items / limit)" }), __decorateMetadata("design:type", Number)], OffsetPaginationPageInfo.prototype, "totalPages", void 0);
|
|
718
|
-
__decorate([Field(() => Int, { description: "The total amount of items" }), __decorateMetadata("design:type", Number)], OffsetPaginationPageInfo.prototype, "totalItems", void 0);
|
|
719
|
-
__decorate([Field(() => Int, { description: "The current page" }), __decorateMetadata("design:type", Number)], OffsetPaginationPageInfo.prototype, "page", void 0);
|
|
720
|
-
__decorate([Field(() => Int, { description: "The amount of items to be requested per page" }), __decorateMetadata("design:type", Number)], OffsetPaginationPageInfo.prototype, "limit", void 0);
|
|
721
|
-
OffsetPaginationPageInfo = __decorate([ObjectType()], OffsetPaginationPageInfo);
|
|
722
125
|
|
|
723
126
|
//#endregion
|
|
724
127
|
//#region src/tools/stringify-opts.ts
|
|
@@ -742,1091 +145,33 @@ const stringifyOpts = (opts) => {
|
|
|
742
145
|
};
|
|
743
146
|
|
|
744
147
|
//#endregion
|
|
745
|
-
//#region src/
|
|
746
|
-
/**
|
|
747
|
-
* Injection token for Winston logger module configuration options
|
|
748
|
-
*/
|
|
749
|
-
const NESTKIT_LOGGER_MODULE_OPTIONS = "NestKitLoggerModuleOptions";
|
|
750
|
-
/**
|
|
751
|
-
* Injection token for the Winston logger instance provider
|
|
752
|
-
*/
|
|
753
|
-
const NESTKIT_WINSTON_LOGGER_PROVIDER = "NestKitLogger";
|
|
754
|
-
/**
|
|
755
|
-
* Injection token for the main NestKit logger provider
|
|
756
|
-
*/
|
|
757
|
-
const NESTKIT_LOGGER_PROVIDER = "NestKitLogger";
|
|
758
|
-
/**
|
|
759
|
-
* Injection token for the NestJS system logger provider
|
|
760
|
-
*/
|
|
761
|
-
const NESTKIT_SYSTEM_LOGGER_PROVIDER = "NestKitSystemLogger";
|
|
762
|
-
/**
|
|
763
|
-
* Injection token for the logger factory provider
|
|
764
|
-
*/
|
|
765
|
-
const NESTKIT_LOGGER_FACTORY_PROVIDER = "NestKitLoggerFactory";
|
|
766
|
-
|
|
767
|
-
//#endregion
|
|
768
|
-
//#region src/logger/classes/logger.ts
|
|
769
|
-
/**
|
|
770
|
-
* Logger with context for NestJS (from NestKit)
|
|
771
|
-
*/
|
|
772
|
-
var Logger = class Logger {
|
|
773
|
-
constructor(winstonLogger, context = {}) {
|
|
774
|
-
this.winstonLogger = winstonLogger;
|
|
775
|
-
this.context = context;
|
|
776
|
-
}
|
|
777
|
-
/**
|
|
778
|
-
* Created child logger with specific context
|
|
779
|
-
* @param context - object with scope, action and other data
|
|
780
|
-
* @returns - new logger with context
|
|
781
|
-
* @example
|
|
782
|
-
* ```ts
|
|
783
|
-
* class SomeService {
|
|
784
|
-
* logger: Logger;
|
|
785
|
-
*
|
|
786
|
-
* constructor(
|
|
787
|
-
* @InjectLoggerFactory() private readonly loggerFactory: LoggerFactory,
|
|
788
|
-
* ) {
|
|
789
|
-
* // Create logger for this service
|
|
790
|
-
* this.winstonLogger = this.winstonLoggerFactory.create({
|
|
791
|
-
* scope: SomeService.name,
|
|
792
|
-
* })
|
|
793
|
-
* }
|
|
794
|
-
*
|
|
795
|
-
* // Create child logger for some method
|
|
796
|
-
* getOne(id: string) {
|
|
797
|
-
* const logger = this.winstonLogger.child({
|
|
798
|
-
* action: this.someMethod.name,
|
|
799
|
-
* id,
|
|
800
|
-
* });
|
|
801
|
-
* }
|
|
802
|
-
* ```
|
|
803
|
-
*/
|
|
804
|
-
child(context) {
|
|
805
|
-
return new Logger(this.winstonLogger, {
|
|
806
|
-
...this.context,
|
|
807
|
-
...context
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
/**
|
|
811
|
-
* Created child logger for nest service method
|
|
812
|
-
* Automatically parse service method context and add it to logger context
|
|
813
|
-
* @param name - service method name
|
|
814
|
-
* @param ctx - service method context
|
|
815
|
-
* @param other - custom logger context
|
|
816
|
-
* @returns - new logger with context
|
|
817
|
-
*/
|
|
818
|
-
forMethod(name, ctx, other) {
|
|
819
|
-
const context = { action: name };
|
|
820
|
-
if (ctx) {
|
|
821
|
-
Object.assign(context, { requestId: ctx.requestId });
|
|
822
|
-
if (!ctx.user) throw new Error("User is required for strict method context. Use guards: @UseGuards(JwtAuthGuard) or @UseGuards(GraphQLJwtAuthGuard)");
|
|
823
|
-
Object.assign(context, {
|
|
824
|
-
requestId: ctx.requestId,
|
|
825
|
-
userId: ctx.user.id
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
if (other) Object.assign(context, other);
|
|
829
|
-
return this.child(context);
|
|
830
|
-
}
|
|
831
|
-
setContext(...args) {
|
|
832
|
-
if (args.length === 2 && typeof args[0] === "string" && typeof args[1] !== "undefined") {
|
|
833
|
-
const key = args[0];
|
|
834
|
-
const value = args[1];
|
|
835
|
-
this.context[key] = value;
|
|
836
|
-
} else this.context = {
|
|
837
|
-
...this.context,
|
|
838
|
-
...args[0]
|
|
839
|
-
};
|
|
840
|
-
}
|
|
841
|
-
/**
|
|
842
|
-
* Get logger context data
|
|
843
|
-
* @returns - logger context
|
|
844
|
-
*/
|
|
845
|
-
getContext() {
|
|
846
|
-
return structuredClone(this.context);
|
|
847
|
-
}
|
|
848
|
-
log(...args) {
|
|
849
|
-
if (isObject(args[0])) this.winstonLogger.log({
|
|
850
|
-
...this.context,
|
|
851
|
-
...args[0]
|
|
852
|
-
});
|
|
853
|
-
else this.winstonLogger.log({
|
|
854
|
-
level: args[0],
|
|
855
|
-
message: args[1],
|
|
856
|
-
...this.context,
|
|
857
|
-
...args[2]
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
info(...args) {
|
|
861
|
-
if (typeof args[0] === "string") this.winstonLogger.info({
|
|
862
|
-
message: args[0],
|
|
863
|
-
...this.context,
|
|
864
|
-
...args[1]
|
|
865
|
-
});
|
|
866
|
-
else this.winstonLogger.info({
|
|
867
|
-
...this.context,
|
|
868
|
-
...args[0]
|
|
869
|
-
});
|
|
870
|
-
}
|
|
871
|
-
error(...args) {
|
|
872
|
-
if (args[0] instanceof NestError) {
|
|
873
|
-
const err = args[0];
|
|
874
|
-
this.winstonLogger.error({
|
|
875
|
-
...this.context,
|
|
876
|
-
...args[1],
|
|
877
|
-
...this.destructureError(err)
|
|
878
|
-
});
|
|
879
|
-
} else if (args[0] instanceof Error) {
|
|
880
|
-
const err = args[0];
|
|
881
|
-
this.winstonLogger.error({
|
|
882
|
-
...this.context,
|
|
883
|
-
...args[1],
|
|
884
|
-
...this.destructureError(err)
|
|
885
|
-
});
|
|
886
|
-
} else if (typeof args[0] === "string" && args[1] instanceof Error) {
|
|
887
|
-
const message = args[0];
|
|
888
|
-
const err = args[1];
|
|
889
|
-
this.winstonLogger.error({
|
|
890
|
-
message,
|
|
891
|
-
...this.context,
|
|
892
|
-
...args[2],
|
|
893
|
-
error: this.destructureError(err)
|
|
894
|
-
});
|
|
895
|
-
} else if (typeof args[0] === "string") {
|
|
896
|
-
const message = args[0];
|
|
897
|
-
this.winstonLogger.error({
|
|
898
|
-
message,
|
|
899
|
-
...this.context,
|
|
900
|
-
...args[1]
|
|
901
|
-
});
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
/**
|
|
905
|
-
* Creates plain object from error
|
|
906
|
-
* @see {@link DestructuredError}
|
|
907
|
-
*/
|
|
908
|
-
destructureError(error) {
|
|
909
|
-
const errorObject = {};
|
|
910
|
-
if (error instanceof NestError) {
|
|
911
|
-
errorObject.message = error.message;
|
|
912
|
-
errorObject.stack = error.stack;
|
|
913
|
-
errorObject.context = error.context;
|
|
914
|
-
errorObject.statusCode = error.httpStatusCode;
|
|
915
|
-
errorObject.errorKey = error.key;
|
|
916
|
-
if (error.cause instanceof Error) errorObject.cause = this.destructureError(error.cause);
|
|
917
|
-
} else if (error instanceof Error) {
|
|
918
|
-
errorObject.message = error.message;
|
|
919
|
-
errorObject.stack = error.stack;
|
|
920
|
-
}
|
|
921
|
-
if (error instanceof HttpException) {
|
|
922
|
-
errorObject.statusCode = error.getStatus();
|
|
923
|
-
const response = error.getResponse();
|
|
924
|
-
if (isObject(response)) {
|
|
925
|
-
if (response.key) errorObject.errorKey = response.key;
|
|
926
|
-
if (response.context) {
|
|
927
|
-
if (!errorObject.context) errorObject.context = {};
|
|
928
|
-
errorObject.context = {
|
|
929
|
-
...errorObject.context,
|
|
930
|
-
...response.context
|
|
931
|
-
};
|
|
932
|
-
}
|
|
933
|
-
if (response.error) errorObject.cause = this.destructureError(response.error);
|
|
934
|
-
}
|
|
935
|
-
return errorObject;
|
|
936
|
-
} else if (error instanceof GraphQLError) {
|
|
937
|
-
const ctx = JSON.parse(JSON.stringify({
|
|
938
|
-
locations: error.locations,
|
|
939
|
-
positions: error.positions,
|
|
940
|
-
source: error.source
|
|
941
|
-
}));
|
|
942
|
-
errorObject.context = {
|
|
943
|
-
...errorObject.context,
|
|
944
|
-
...ctx
|
|
945
|
-
};
|
|
946
|
-
}
|
|
947
|
-
return errorObject;
|
|
948
|
-
}
|
|
949
|
-
warn(...args) {
|
|
950
|
-
if (typeof args[0] === "string") this.winstonLogger.warn({
|
|
951
|
-
message: args[0],
|
|
952
|
-
...this.context,
|
|
953
|
-
...args[1]
|
|
954
|
-
});
|
|
955
|
-
else this.winstonLogger.warn({
|
|
956
|
-
...this.context,
|
|
957
|
-
...args[0]
|
|
958
|
-
});
|
|
959
|
-
}
|
|
960
|
-
debug(...args) {
|
|
961
|
-
if (typeof args[0] === "string") this.winstonLogger.debug({
|
|
962
|
-
message: args[0],
|
|
963
|
-
...this.context,
|
|
964
|
-
...args[1]
|
|
965
|
-
});
|
|
966
|
-
else this.winstonLogger.debug({
|
|
967
|
-
...this.context,
|
|
968
|
-
...args[0]
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
verbose(...args) {
|
|
972
|
-
if (typeof args[0] === "string") this.winstonLogger.verbose({
|
|
973
|
-
message: args[0],
|
|
974
|
-
...this.context,
|
|
975
|
-
...args[1]
|
|
976
|
-
});
|
|
977
|
-
else this.winstonLogger.verbose({
|
|
978
|
-
...this.context,
|
|
979
|
-
...args[0]
|
|
980
|
-
});
|
|
981
|
-
}
|
|
982
|
-
};
|
|
983
|
-
|
|
984
|
-
//#endregion
|
|
985
|
-
//#region src/logger/classes/nest-system-logger.ts
|
|
986
|
-
var _ref$3;
|
|
987
|
-
let NestSystemLogger = class NestSystemLogger$1 extends ConsoleLogger {
|
|
988
|
-
logger;
|
|
989
|
-
printMessages(messages, context, logLevel) {
|
|
990
|
-
for (const message of messages) this.logger.log(this.getWinstonLogLevel(logLevel), this.stringifyMessage(message), { scope: context });
|
|
991
|
-
}
|
|
992
|
-
stringifyMessage(message) {
|
|
993
|
-
if (isFunction(message)) return this.stringifyMessage(message());
|
|
994
|
-
if (isPlainObject(message) || Array.isArray(message)) return JSON.stringify(message, (key, value) => typeof value === "bigint" ? value.toString() : value, 2);
|
|
995
|
-
return String(message);
|
|
996
|
-
}
|
|
997
|
-
getWinstonLogLevel(level) {
|
|
998
|
-
switch (level) {
|
|
999
|
-
case "log": return "info";
|
|
1000
|
-
case "verbose": return "verbose";
|
|
1001
|
-
case "debug": return "debug";
|
|
1002
|
-
case "warn": return "warn";
|
|
1003
|
-
case "error": return "error";
|
|
1004
|
-
default: return "info";
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
};
|
|
1008
|
-
__decorate([Inject(NESTKIT_LOGGER_PROVIDER), __decorateMetadata("design:type", typeof (_ref$3 = typeof Logger !== "undefined" && Logger) === "function" ? _ref$3 : Object)], NestSystemLogger.prototype, "logger", void 0);
|
|
1009
|
-
NestSystemLogger = __decorate([Injectable()], NestSystemLogger);
|
|
1010
|
-
|
|
1011
|
-
//#endregion
|
|
1012
|
-
//#region src/logger/classes/typeorm-logger.ts
|
|
1013
|
-
var TypeOrmLoggerOptions = class {
|
|
1014
|
-
enabled;
|
|
1015
|
-
logger;
|
|
1016
|
-
levels;
|
|
1017
|
-
};
|
|
1018
|
-
var TypeOrmLogger = class extends AbstractLogger {
|
|
1019
|
-
logger;
|
|
1020
|
-
constructor(opts) {
|
|
1021
|
-
super(opts.enabled && opts.levels ? opts.levels : false);
|
|
1022
|
-
this.logger = opts.logger;
|
|
1023
|
-
}
|
|
1024
|
-
/**
|
|
1025
|
-
* Write log to specific output.
|
|
1026
|
-
*/
|
|
1027
|
-
writeLog(level, logMessage) {
|
|
1028
|
-
const messages = this.prepareLogMessages(logMessage, { highlightSql: false });
|
|
1029
|
-
for (const message of messages) switch (message.type ?? level) {
|
|
1030
|
-
case "log":
|
|
1031
|
-
case "query":
|
|
1032
|
-
case "schema-build":
|
|
1033
|
-
this.logger.debug(String(message.message), this.getCtx(message));
|
|
1034
|
-
break;
|
|
1035
|
-
case "migration":
|
|
1036
|
-
case "info":
|
|
1037
|
-
if (message.prefix) this.logger.info(`${message.prefix} ${message.message}`, this.getCtx(message));
|
|
1038
|
-
else this.logger.info(String(message.message), this.getCtx(message));
|
|
1039
|
-
break;
|
|
1040
|
-
case "warn":
|
|
1041
|
-
case "query-slow":
|
|
1042
|
-
if (message.prefix) this.logger.warn(`${message.prefix} ${message.message}`, this.getCtx(message));
|
|
1043
|
-
else this.logger.warn(String(message.message), this.getCtx(message));
|
|
1044
|
-
break;
|
|
1045
|
-
case "error":
|
|
1046
|
-
case "query-error":
|
|
1047
|
-
if (message.prefix) this.logger.error(`[${message.prefix}] ${message.message}`, this.getCtx(message));
|
|
1048
|
-
else this.logger.error(String(message.message), this.getCtx(message));
|
|
1049
|
-
break;
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
getCtx(message) {
|
|
1053
|
-
const ctx = { ...message.additionalInfo };
|
|
1054
|
-
if (Array.isArray(ctx.parameters)) ctx.parameters = message.parameters;
|
|
1055
|
-
return ctx;
|
|
1056
|
-
}
|
|
1057
|
-
};
|
|
1058
|
-
|
|
1059
|
-
//#endregion
|
|
1060
|
-
//#region src/logger/classes/logger-factory.ts
|
|
1061
|
-
/**
|
|
1062
|
-
* Logger factory for creating loggers with predefined context
|
|
1063
|
-
* Factory is singleton, so it keep original winston `Logger` instance
|
|
1064
|
-
* and is can be injected to any service
|
|
1065
|
-
*/
|
|
1066
|
-
var LoggerFactory = class {
|
|
1067
|
-
constructor(winstonLogger, context = {}) {
|
|
1068
|
-
this.winstonLogger = winstonLogger;
|
|
1069
|
-
this.context = context;
|
|
1070
|
-
}
|
|
1071
|
-
/**
|
|
1072
|
-
* Created new logger with specific context merge it with global context
|
|
1073
|
-
* @param context - specific action with scope, and other data
|
|
1074
|
-
* @returns - new logger with context
|
|
1075
|
-
* @example
|
|
1076
|
-
* ```ts
|
|
1077
|
-
* class SomeService {
|
|
1078
|
-
* logger: Logger;
|
|
1079
|
-
*
|
|
1080
|
-
* constructor(
|
|
1081
|
-
* @InjectLoggerFactory() private readonly loggerFactory: LoggerFactory,
|
|
1082
|
-
* ) {
|
|
1083
|
-
* // Create logger for this service
|
|
1084
|
-
* this.logger = this.loggerFactory.create({
|
|
1085
|
-
* scope: SomeService.name,
|
|
1086
|
-
* })
|
|
1087
|
-
* }
|
|
1088
|
-
* ```
|
|
1089
|
-
*/
|
|
1090
|
-
create(context = {}) {
|
|
1091
|
-
return new Logger(this.winstonLogger, {
|
|
1092
|
-
...this.context,
|
|
1093
|
-
...context
|
|
1094
|
-
});
|
|
1095
|
-
}
|
|
1096
|
-
createTypeOrmLogger(opts) {
|
|
1097
|
-
return new TypeOrmLogger({
|
|
1098
|
-
logger: this.create({ scope: "TypeORM" }),
|
|
1099
|
-
...opts
|
|
1100
|
-
});
|
|
1101
|
-
}
|
|
1102
|
-
};
|
|
1103
|
-
|
|
1104
|
-
//#endregion
|
|
1105
|
-
//#region src/logger/logger.providers.ts
|
|
1106
|
-
/**
|
|
1107
|
-
* Syntax sugar. Injects logger via NESTKIT_LOGGER_PROVIDER token
|
|
1108
|
-
* @example
|
|
1109
|
-
* ```ts
|
|
1110
|
-
* class SomeService {
|
|
1111
|
-
* constructor(
|
|
1112
|
-
* @InjectLogger() private readonly logger: Logger
|
|
1113
|
-
* ) {}
|
|
1114
|
-
* ```
|
|
1115
|
-
*/
|
|
1116
|
-
const InjectLogger = () => Inject(NESTKIT_LOGGER_PROVIDER);
|
|
1117
|
-
/**
|
|
1118
|
-
* Syntax sugar. Injects winston logger factory by WINSTON_MODULE_FACTORY_PROVIDER token
|
|
1119
|
-
* @example
|
|
1120
|
-
* ```ts
|
|
1121
|
-
* class SomeService {
|
|
1122
|
-
* constructor(
|
|
1123
|
-
* @InjectLoggerFactory() private readonly loggerFactory: LoggerFactory
|
|
1124
|
-
* ) {}
|
|
1125
|
-
* ```
|
|
1126
|
-
*/
|
|
1127
|
-
const InjectLoggerFactory = () => Inject(NESTKIT_LOGGER_FACTORY_PROVIDER);
|
|
1128
|
-
const createNestLogger = (loggerOpts) => {
|
|
1129
|
-
return new Logger$1(createLogger(loggerOpts));
|
|
1130
|
-
};
|
|
1131
|
-
const createLoggerProviders = (loggerOpts) => {
|
|
1132
|
-
return [
|
|
1133
|
-
{
|
|
1134
|
-
provide: NESTKIT_WINSTON_LOGGER_PROVIDER,
|
|
1135
|
-
useFactory: () => createLogger(loggerOpts)
|
|
1136
|
-
},
|
|
1137
|
-
{
|
|
1138
|
-
provide: NESTKIT_LOGGER_PROVIDER,
|
|
1139
|
-
useFactory: (logger) => {
|
|
1140
|
-
return new Logger$1(logger);
|
|
1141
|
-
},
|
|
1142
|
-
inject: [NESTKIT_WINSTON_LOGGER_PROVIDER]
|
|
1143
|
-
},
|
|
1144
|
-
{
|
|
1145
|
-
provide: NESTKIT_SYSTEM_LOGGER_PROVIDER,
|
|
1146
|
-
useClass: NestSystemLogger
|
|
1147
|
-
},
|
|
1148
|
-
{
|
|
1149
|
-
provide: NESTKIT_LOGGER_FACTORY_PROVIDER,
|
|
1150
|
-
useFactory: (logger) => {
|
|
1151
|
-
return new LoggerFactory(logger);
|
|
1152
|
-
},
|
|
1153
|
-
inject: [NESTKIT_WINSTON_LOGGER_PROVIDER]
|
|
1154
|
-
}
|
|
1155
|
-
];
|
|
1156
|
-
};
|
|
1157
|
-
const createLoggerAsyncProviders = (options) => {
|
|
1158
|
-
const providers = [
|
|
1159
|
-
{
|
|
1160
|
-
provide: NESTKIT_WINSTON_LOGGER_PROVIDER,
|
|
1161
|
-
useFactory: (loggerOpts) => createLogger(loggerOpts),
|
|
1162
|
-
inject: [NESTKIT_LOGGER_MODULE_OPTIONS]
|
|
1163
|
-
},
|
|
1164
|
-
{
|
|
1165
|
-
provide: NESTKIT_LOGGER_PROVIDER,
|
|
1166
|
-
useFactory: (logger) => {
|
|
1167
|
-
return new Logger$1(logger);
|
|
1168
|
-
},
|
|
1169
|
-
inject: [NESTKIT_WINSTON_LOGGER_PROVIDER]
|
|
1170
|
-
},
|
|
1171
|
-
{
|
|
1172
|
-
provide: NESTKIT_SYSTEM_LOGGER_PROVIDER,
|
|
1173
|
-
useClass: NestSystemLogger
|
|
1174
|
-
},
|
|
1175
|
-
{
|
|
1176
|
-
provide: NESTKIT_LOGGER_FACTORY_PROVIDER,
|
|
1177
|
-
useFactory: (logger) => {
|
|
1178
|
-
return new LoggerFactory(logger);
|
|
1179
|
-
},
|
|
1180
|
-
inject: [NESTKIT_WINSTON_LOGGER_PROVIDER]
|
|
1181
|
-
}
|
|
1182
|
-
];
|
|
1183
|
-
if (options.useClass) {
|
|
1184
|
-
const useClass = options.useClass;
|
|
1185
|
-
providers.push(...[{
|
|
1186
|
-
provide: NESTKIT_LOGGER_MODULE_OPTIONS,
|
|
1187
|
-
useFactory: async (optionsFactory) => await optionsFactory.createLoggerModuleOptions(),
|
|
1188
|
-
inject: [useClass]
|
|
1189
|
-
}, {
|
|
1190
|
-
provide: useClass,
|
|
1191
|
-
useClass
|
|
1192
|
-
}]);
|
|
1193
|
-
}
|
|
1194
|
-
if (options.useFactory) providers.push({
|
|
1195
|
-
provide: NESTKIT_LOGGER_MODULE_OPTIONS,
|
|
1196
|
-
useFactory: options.useFactory,
|
|
1197
|
-
inject: options.inject || []
|
|
1198
|
-
});
|
|
1199
|
-
return providers;
|
|
1200
|
-
};
|
|
1201
|
-
|
|
1202
|
-
//#endregion
|
|
1203
|
-
//#region src/logger/logger.module.ts
|
|
1204
|
-
var _LoggerModule;
|
|
1205
|
-
let LoggerModule = _LoggerModule = class LoggerModule$1 {
|
|
1206
|
-
static forRoot(options) {
|
|
1207
|
-
const providers = createLoggerProviders(options);
|
|
1208
|
-
return {
|
|
1209
|
-
module: _LoggerModule,
|
|
1210
|
-
providers,
|
|
1211
|
-
exports: providers
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
static forRootAsync(options) {
|
|
1215
|
-
const providers = createLoggerAsyncProviders(options);
|
|
1216
|
-
return {
|
|
1217
|
-
module: _LoggerModule,
|
|
1218
|
-
imports: options.imports,
|
|
1219
|
-
providers,
|
|
1220
|
-
exports: providers
|
|
1221
|
-
};
|
|
1222
|
-
}
|
|
1223
|
-
static createLogger(options) {
|
|
1224
|
-
return createNestLogger(options);
|
|
1225
|
-
}
|
|
1226
|
-
};
|
|
1227
|
-
LoggerModule = _LoggerModule = __decorate([Global(), Module({})], LoggerModule);
|
|
1228
|
-
|
|
1229
|
-
//#endregion
|
|
1230
|
-
//#region src/logger/winston.tools.ts
|
|
1231
|
-
const nestLikeColorScheme = {
|
|
1232
|
-
log: clc.greenBright,
|
|
1233
|
-
info: clc.greenBright,
|
|
1234
|
-
error: clc.red,
|
|
1235
|
-
warn: clc.yellow,
|
|
1236
|
-
debug: clc.magentaBright,
|
|
1237
|
-
verbose: clc.cyanBright
|
|
1238
|
-
};
|
|
1239
|
-
/**
|
|
1240
|
-
* Create a pretty message for the logger with nest-like formatting
|
|
1241
|
-
* Use recursion to print child errors
|
|
1242
|
-
* @param vars - message variables
|
|
1243
|
-
* @returns - formatted message
|
|
1244
|
-
* @example
|
|
1245
|
-
* [Jetstream] - 6/10/2022, 4:33:42 PM ERROR [VideoService.createOutput] Failed to create cloudlfare output
|
|
1246
|
-
*/
|
|
1247
|
-
const createPrettyMessage = ({ appName, action, level, timestamp, message, scope, stack, errorKey, context, parentPath, cause, deep = 0 }) => {
|
|
1248
|
-
if ("undefined" !== typeof timestamp) try {
|
|
1249
|
-
if (timestamp === new Date(timestamp).toISOString()) timestamp = new Date(timestamp).toLocaleString();
|
|
1250
|
-
} catch {}
|
|
1251
|
-
const color = nestLikeColorScheme[level] || ((text) => text);
|
|
1252
|
-
if (errorKey) message += ` [${errorKey}]`;
|
|
1253
|
-
const sAppName = color(`[${appName}]`);
|
|
1254
|
-
const sTimestamp = timestamp ? `${timestamp} ` : "";
|
|
1255
|
-
const sLevel = color(level.toUpperCase());
|
|
1256
|
-
let path = "";
|
|
1257
|
-
let sPath = "";
|
|
1258
|
-
if ("undefined" !== typeof scope && "undefined" !== typeof action) path = `${scope}.${action}`;
|
|
1259
|
-
else if ("undefined" !== typeof scope) path = scope;
|
|
1260
|
-
else if ("undefined" !== typeof action) path = action;
|
|
1261
|
-
if (path && parentPath) path = `${parentPath} --> ${path}`;
|
|
1262
|
-
else if (parentPath) path = parentPath;
|
|
1263
|
-
if (path) sPath = clc.yellow(` [${path}]`);
|
|
1264
|
-
const sMessage = color(` ${message}`);
|
|
1265
|
-
const sStack = "undefined" !== typeof stack ? color(`\n ${stack}`) : "";
|
|
1266
|
-
let sRecursion = "";
|
|
1267
|
-
if (cause) {
|
|
1268
|
-
const { action: action$1, scope: scope$1,...context$1 } = cause?.context || {};
|
|
1269
|
-
/**
|
|
1270
|
-
* Print child errors recursively
|
|
1271
|
-
*/
|
|
1272
|
-
sRecursion = cause ? `\n${createPrettyMessage({
|
|
1273
|
-
appName,
|
|
1274
|
-
action: action$1,
|
|
1275
|
-
level,
|
|
1276
|
-
timestamp,
|
|
1277
|
-
message: cause.message ?? message,
|
|
1278
|
-
scope: scope$1,
|
|
1279
|
-
stack: cause.stack,
|
|
1280
|
-
errorKey: cause.errorKey,
|
|
1281
|
-
context: context$1,
|
|
1282
|
-
parentPath: path,
|
|
1283
|
-
cause: cause.cause,
|
|
1284
|
-
deep: deep + 1
|
|
1285
|
-
})}` : "";
|
|
1286
|
-
}
|
|
1287
|
-
const sContext = context && Object.keys(context).length > 0 ? color(` -- ${JSON.stringify(context, null, 2)}`) : "";
|
|
1288
|
-
return `${sAppName} - ${sTimestamp} ${sLevel}${sPath}${sMessage}${sStack}${sContext}${sRecursion}`;
|
|
1289
|
-
};
|
|
1290
|
-
/**
|
|
1291
|
-
* Create a nest-like console format
|
|
1292
|
-
* @param appName - App name (Jetstream, WHATSBIBLE, etc.)
|
|
1293
|
-
* @returns Winston format
|
|
1294
|
-
*/
|
|
1295
|
-
const nestLikeConsoleFormat = (appName = "Nest") => format.printf(({ level, timestamp, message, scope, action, stack, errorKey, statusCode, error: cause,...context }) => {
|
|
1296
|
-
return createPrettyMessage({
|
|
1297
|
-
appName,
|
|
1298
|
-
action,
|
|
1299
|
-
level,
|
|
1300
|
-
timestamp,
|
|
1301
|
-
message,
|
|
1302
|
-
stack,
|
|
1303
|
-
context,
|
|
1304
|
-
scope,
|
|
1305
|
-
errorKey,
|
|
1306
|
-
statusCode,
|
|
1307
|
-
cause,
|
|
1308
|
-
deep: 0
|
|
1309
|
-
});
|
|
1310
|
-
});
|
|
1311
|
-
|
|
1312
|
-
//#endregion
|
|
1313
|
-
//#region src/configs/logger.config.ts
|
|
1314
|
-
/**
|
|
1315
|
-
* NestJS injection token for Logger config
|
|
1316
|
-
*/
|
|
1317
|
-
const LOGGER_CONFIG_TOKEN = "LOGGER_CONFIG_TOKEN";
|
|
1318
|
-
const InjectLoggerConfig = () => Inject(getConfigToken(LOGGER_CONFIG_TOKEN));
|
|
148
|
+
//#region src/tools/wait.ts
|
|
1319
149
|
/**
|
|
1320
|
-
*
|
|
1321
|
-
* @
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1324
|
-
*
|
|
1325
|
-
* import { createLoggerConfig } from '#/dist/configs';
|
|
1326
|
-
*
|
|
1327
|
-
* export const LoggerConfig = createLoggerConfig();
|
|
1328
|
-
* ```
|
|
150
|
+
* Pauses execution for a specified amount of time using a Promise.
|
|
151
|
+
* @param ms - The amount of time to pause in milliseconds.
|
|
152
|
+
* @returns A Promise that resolves after the specified amount of time has elapsed.
|
|
153
|
+
* @deprecated use wait instead
|
|
1329
154
|
*/
|
|
1330
|
-
const
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
nestLikeConsoleFormat(opts.appName)
|
|
1336
|
-
];
|
|
1337
|
-
const winstonOptions = { transports: [] };
|
|
1338
|
-
if (!Array.isArray(winstonOptions.transports)) return winstonOptions;
|
|
1339
|
-
if (opts.useConsole) winstonOptions.transports.push(new winston.transports.Console({
|
|
1340
|
-
level: opts.consoleLevel ?? "debug",
|
|
1341
|
-
format: winston.format.combine(...format$1)
|
|
1342
|
-
}));
|
|
1343
|
-
if (opts.transports) winstonOptions.transports.push(...opts.transports);
|
|
1344
|
-
return winstonOptions;
|
|
155
|
+
const pauseWithPromise = async (ms) => {
|
|
156
|
+
await new Promise((resolve) => {
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
resolve(null);
|
|
159
|
+
}, ms);
|
|
1345
160
|
});
|
|
1346
161
|
};
|
|
1347
|
-
|
|
1348
|
-
//#endregion
|
|
1349
|
-
//#region src/abstracts/nestjs-service.ts
|
|
1350
|
-
var _ref$2;
|
|
1351
|
-
/**
|
|
1352
|
-
* Abstract service class for NestJS services
|
|
1353
|
-
* Automatically initializes logger with the constructor name as scope
|
|
1354
|
-
*/
|
|
1355
|
-
var NestJsService = class {
|
|
1356
|
-
loggerFactory;
|
|
1357
|
-
logger;
|
|
1358
|
-
/**
|
|
1359
|
-
* Initialize logger using the constructor name as scope
|
|
1360
|
-
*/
|
|
1361
|
-
onModuleInit() {
|
|
1362
|
-
this.logger = this.loggerFactory.create({ scope: this.constructor.name });
|
|
1363
|
-
}
|
|
1364
|
-
};
|
|
1365
|
-
__decorate([InjectLoggerFactory(), __decorateMetadata("design:type", typeof (_ref$2 = typeof LoggerFactory !== "undefined" && LoggerFactory) === "function" ? _ref$2 : Object)], NestJsService.prototype, "loggerFactory", void 0);
|
|
1366
|
-
|
|
1367
|
-
//#endregion
|
|
1368
|
-
//#region src/abstracts/nestjs-resource-service.ts
|
|
1369
|
-
var _ref$1, _ref2$1;
|
|
1370
|
-
var NestJsResourceService = class extends NestJsService {
|
|
1371
|
-
constructor(params) {
|
|
1372
|
-
super();
|
|
1373
|
-
this.params = params;
|
|
1374
|
-
}
|
|
1375
|
-
idService;
|
|
1376
|
-
dataSource;
|
|
1377
|
-
get repository() {
|
|
1378
|
-
return this.dataSource.getRepository(this.params.entity.type);
|
|
1379
|
-
}
|
|
1380
|
-
generateEntityId() {
|
|
1381
|
-
return this.idService.generateEntityId(this.params.entity.idPrefix);
|
|
1382
|
-
}
|
|
1383
|
-
get entityName() {
|
|
1384
|
-
return this.params.entity.type.name;
|
|
1385
|
-
}
|
|
1386
|
-
get alias() {
|
|
1387
|
-
return this.params.entity.alias;
|
|
1388
|
-
}
|
|
1389
|
-
async getOneBy(opts) {
|
|
1390
|
-
const logger = this.logger.child({
|
|
1391
|
-
action: this.getOneBy.name,
|
|
1392
|
-
...opts
|
|
1393
|
-
});
|
|
1394
|
-
if (Object.values(opts).filter((v) => v).length === 0) throw new BadRequestError({
|
|
1395
|
-
message: "Empty options",
|
|
1396
|
-
key: "NST_GET_ONE_BY_EMPTY_OPTIONS",
|
|
1397
|
-
context: logger.getContext()
|
|
1398
|
-
});
|
|
1399
|
-
return await this.repository.findOneBy({ ...opts });
|
|
1400
|
-
}
|
|
1401
|
-
async getOne(id) {
|
|
1402
|
-
return await this.getOneBy({ id });
|
|
1403
|
-
}
|
|
1404
|
-
async getOneByOrFail(opts, ctx) {
|
|
1405
|
-
const logger = this.logger.forMethod(this.getOneByOrFail.name, ctx, { ...opts });
|
|
1406
|
-
const item = await this.getOneBy(opts);
|
|
1407
|
-
if (!item) throw new NotFoundError({
|
|
1408
|
-
message: `${this.entityName} with ${stringifyOpts(opts)} not found`,
|
|
1409
|
-
key: "NST_CHANNELS_NOT_FOUND",
|
|
1410
|
-
context: logger.getContext()
|
|
1411
|
-
});
|
|
1412
|
-
return item;
|
|
1413
|
-
}
|
|
1414
|
-
async getOneOrFail(id, ctx) {
|
|
1415
|
-
return await this.getOneByOrFail({ id }, ctx);
|
|
1416
|
-
}
|
|
1417
|
-
applyFilterToQuery(query, filter) {
|
|
1418
|
-
if (!filter) return;
|
|
1419
|
-
if (filter.search) query.andWhere(`${this.alias}.title LIKE :search`, { search: `%${filter.search}%` });
|
|
1420
|
-
}
|
|
1421
|
-
applySearchToQuery(query, search) {
|
|
1422
|
-
if (!search) return;
|
|
1423
|
-
query.andWhere(`${this.alias}.title LIKE :search`, { search: `%${search}%` });
|
|
1424
|
-
}
|
|
1425
|
-
applyOrderByToQuery(query, orderBy) {
|
|
1426
|
-
const sort = extractSortParams(orderBy);
|
|
1427
|
-
query.addOrderBy(`${this.alias}.${sort.columnName}`, sort.direction);
|
|
1428
|
-
}
|
|
1429
|
-
};
|
|
1430
|
-
__decorate([Inject(IdService), __decorateMetadata("design:type", typeof (_ref$1 = typeof IdService !== "undefined" && IdService) === "function" ? _ref$1 : Object)], NestJsResourceService.prototype, "idService", void 0);
|
|
1431
|
-
__decorate([InjectDataSource(), __decorateMetadata("design:type", typeof (_ref2$1 = typeof DataSource !== "undefined" && DataSource) === "function" ? _ref2$1 : Object)], NestJsResourceService.prototype, "dataSource", void 0);
|
|
1432
|
-
|
|
1433
|
-
//#endregion
|
|
1434
|
-
//#region src/db/snake-naming.strategy.ts
|
|
1435
|
-
/**
|
|
1436
|
-
* Snake case naming strategy for typeorm.
|
|
1437
|
-
* Determines table and column names from class and property names.
|
|
1438
|
-
*/
|
|
1439
|
-
var SnakeNamingStrategy = class extends DefaultNamingStrategy {
|
|
1440
|
-
/**
|
|
1441
|
-
* Create a table name from a class name.
|
|
1442
|
-
* @param className - The class name of the entity
|
|
1443
|
-
* @param customName - The custom table name
|
|
1444
|
-
* @returns The table name
|
|
1445
|
-
* @example Create table name from class name
|
|
1446
|
-
* ```ts
|
|
1447
|
-
* @Entity()
|
|
1448
|
-
* class User {}
|
|
1449
|
-
* // returns 'users'
|
|
1450
|
-
*
|
|
1451
|
-
* @Entity('custom_table_name')
|
|
1452
|
-
* class User {}
|
|
1453
|
-
* // returns 'custom_table_name'
|
|
1454
|
-
*
|
|
1455
|
-
*```
|
|
1456
|
-
*/
|
|
1457
|
-
tableName(className, customName) {
|
|
1458
|
-
if (customName) return customName;
|
|
1459
|
-
const snakeClassName = snakeCase(className);
|
|
1460
|
-
if (snakeClassName.includes("_to_")) return snakeClassName;
|
|
1461
|
-
const parts = snakeClassName.split("_");
|
|
1462
|
-
if (parts.length === 1) return singularToPlural(snakeClassName);
|
|
1463
|
-
return parts.map((name, i) => i === 0 ? name : singularToPlural(name)).join("_");
|
|
1464
|
-
}
|
|
1465
|
-
/**
|
|
1466
|
-
* Create a column name from a property name.
|
|
1467
|
-
* @param propertyName - The property name of the entity
|
|
1468
|
-
* @param customName - The custom column name
|
|
1469
|
-
* @param embeddedPrefixes - The embedded prefixes
|
|
1470
|
-
* @returns The table column name
|
|
1471
|
-
* @example Create column name from property name
|
|
1472
|
-
* ```ts
|
|
1473
|
-
* @Entity()
|
|
1474
|
-
* class User {
|
|
1475
|
-
* @Column()
|
|
1476
|
-
* firstName: string; // returns 'first_name'
|
|
1477
|
-
*
|
|
1478
|
-
* @Column('custom_last_name')
|
|
1479
|
-
* lastName: string; // returns 'custom_last_name'
|
|
1480
|
-
* }
|
|
1481
|
-
* ```
|
|
1482
|
-
*/
|
|
1483
|
-
columnName(propertyName, customName, embeddedPrefixes = []) {
|
|
1484
|
-
return snakeCase(embeddedPrefixes.concat("").join("_")) + (customName ? customName : snakeCase(propertyName));
|
|
1485
|
-
}
|
|
1486
|
-
relationName(propertyName) {
|
|
1487
|
-
return snakeCase(propertyName);
|
|
1488
|
-
}
|
|
1489
|
-
joinColumnName(relationName, referencedColumnName) {
|
|
1490
|
-
return snakeCase(relationName + "_" + referencedColumnName);
|
|
1491
|
-
}
|
|
1492
|
-
/**
|
|
1493
|
-
* Create join table name for many-to-many relations.
|
|
1494
|
-
* @returns join table name
|
|
1495
|
-
* @example
|
|
1496
|
-
* ```ts
|
|
1497
|
-
* @Entity()
|
|
1498
|
-
* class Post {
|
|
1499
|
-
* @ManyToMany(() => Theme) // post_to_theme
|
|
1500
|
-
* themes: Theme[];
|
|
1501
|
-
* }
|
|
1502
|
-
*
|
|
1503
|
-
*/
|
|
1504
|
-
joinTableName(firstTableName, secondTableName) {
|
|
1505
|
-
return snakeCase(pluralToSingular(firstTableName) + "_to_" + pluralToSingular(secondTableName));
|
|
1506
|
-
}
|
|
1507
|
-
joinTableColumnName(tableName, propertyName, columnName) {
|
|
1508
|
-
return snakeCase(pluralToSingular(tableName) + "_" + (columnName ? columnName : propertyName));
|
|
1509
|
-
}
|
|
1510
|
-
eagerJoinRelationAlias(alias, propertyPath) {
|
|
1511
|
-
return alias + "__" + propertyPath.replace(".", "_");
|
|
1512
|
-
}
|
|
1513
|
-
/**
|
|
1514
|
-
* Create a primary key name.
|
|
1515
|
-
* @param tableOrName - The table or table name
|
|
1516
|
-
* @param columnNames - The column names
|
|
1517
|
-
* @returns The primary key name
|
|
1518
|
-
* @example
|
|
1519
|
-
* ```ts
|
|
1520
|
-
* @Entity()
|
|
1521
|
-
* class User {
|
|
1522
|
-
* @PrimaryColumn()
|
|
1523
|
-
* id: string;
|
|
1524
|
-
* }
|
|
1525
|
-
*
|
|
1526
|
-
* // returns 'pk_users__id'
|
|
1527
|
-
*/
|
|
1528
|
-
primaryKeyName(tableOrName, columnNames) {
|
|
1529
|
-
tableOrName = typeof tableOrName === "string" ? tableOrName : tableOrName.name;
|
|
1530
|
-
let name = tableOrName;
|
|
1531
|
-
for (const column of columnNames) name += `__${column}`;
|
|
1532
|
-
name = this.simplifyName(name);
|
|
1533
|
-
return `pk_${name}`;
|
|
1534
|
-
}
|
|
1535
|
-
/**
|
|
1536
|
-
* Create a foreign key name.
|
|
1537
|
-
* @param tableOrName - The table or table name
|
|
1538
|
-
* @param columnNames - The column names
|
|
1539
|
-
* @returns The foreign key name
|
|
1540
|
-
* @example
|
|
1541
|
-
* ```ts
|
|
1542
|
-
* @Entity()
|
|
1543
|
-
* class User {
|
|
1544
|
-
* @PrimaryColumn()
|
|
1545
|
-
* id: string;
|
|
1546
|
-
* }
|
|
1547
|
-
* @Entity()
|
|
1548
|
-
* class Post {
|
|
1549
|
-
* @PrimaryColumn()
|
|
1550
|
-
* id: string;
|
|
1551
|
-
*
|
|
1552
|
-
* @ManyToOne(() => User, user => user.posts)
|
|
1553
|
-
* user: User;
|
|
1554
|
-
* }
|
|
1555
|
-
*
|
|
1556
|
-
* // returns 'fk_posts__user_id__users__id'
|
|
1557
|
-
* ```
|
|
1558
|
-
*/
|
|
1559
|
-
foreignKeyName(tableOrName, columnNames) {
|
|
1560
|
-
tableOrName = typeof tableOrName === "string" ? tableOrName : tableOrName.name;
|
|
1561
|
-
let name = tableOrName;
|
|
1562
|
-
for (const column of columnNames) name += `__${column}`;
|
|
1563
|
-
name = this.simplifyName(name);
|
|
1564
|
-
return `fk_${name}`;
|
|
1565
|
-
}
|
|
1566
|
-
/**
|
|
1567
|
-
* Create an index name.
|
|
1568
|
-
* @param tableOrName - The table or table name
|
|
1569
|
-
* @param columnNames - The column names
|
|
1570
|
-
* @returns The index name
|
|
1571
|
-
* @example
|
|
1572
|
-
* ```ts
|
|
1573
|
-
* @Entity()
|
|
1574
|
-
* class User {
|
|
1575
|
-
* @Index()
|
|
1576
|
-
* @Column()
|
|
1577
|
-
* email: string;
|
|
1578
|
-
* }
|
|
1579
|
-
* // returns 'idx_users__email'
|
|
1580
|
-
* ```
|
|
1581
|
-
*/
|
|
1582
|
-
indexName(tableOrName, columnNames) {
|
|
1583
|
-
tableOrName = typeof tableOrName === "string" ? tableOrName : tableOrName.name;
|
|
1584
|
-
let name = tableOrName;
|
|
1585
|
-
for (const column of columnNames) name += `__${column}`;
|
|
1586
|
-
name = this.simplifyName(name);
|
|
1587
|
-
return `idx_${name}`;
|
|
1588
|
-
}
|
|
1589
|
-
/**
|
|
1590
|
-
* Create a unique constraint name.
|
|
1591
|
-
* @param tableOrName - The table or table name
|
|
1592
|
-
* @param columnNames - The column names
|
|
1593
|
-
* @returns The unique constraint name
|
|
1594
|
-
* @example
|
|
1595
|
-
* ```ts
|
|
1596
|
-
* @Entity()
|
|
1597
|
-
* class User {
|
|
1598
|
-
* @Unique()
|
|
1599
|
-
* @Column()
|
|
1600
|
-
* email: string;
|
|
1601
|
-
* }
|
|
1602
|
-
* // returns 'uq_users__email'
|
|
1603
|
-
* ```
|
|
1604
|
-
*/
|
|
1605
|
-
uniqueConstraintName(tableOrName, columnNames) {
|
|
1606
|
-
tableOrName = typeof tableOrName === "string" ? tableOrName : tableOrName.name;
|
|
1607
|
-
let name = tableOrName;
|
|
1608
|
-
for (const column of columnNames) name += `__${column}`;
|
|
1609
|
-
name = this.simplifyName(name);
|
|
1610
|
-
return `uq_${name}`;
|
|
1611
|
-
}
|
|
1612
|
-
simplifyName(name) {
|
|
1613
|
-
if (name.length > 50) return name.split("__").map((piece) => {
|
|
1614
|
-
if (piece.includes("_to_")) return piece.split("_").map((p) => p[0]).join("");
|
|
1615
|
-
return piece;
|
|
1616
|
-
}).join("__");
|
|
1617
|
-
return name;
|
|
1618
|
-
}
|
|
1619
|
-
};
|
|
1620
|
-
|
|
1621
|
-
//#endregion
|
|
1622
|
-
//#region src/configs/db.config.ts
|
|
1623
|
-
/**
|
|
1624
|
-
* NestJS injection token for postgres db config
|
|
1625
|
-
*/
|
|
1626
|
-
const DB_CONFIG_TOKEN = "DB_CONFIG_TOKEN";
|
|
1627
|
-
const InjectDbConfig = () => Inject(getConfigToken(DB_CONFIG_TOKEN));
|
|
1628
|
-
/**
|
|
1629
|
-
* Postgres db config environment variables
|
|
1630
|
-
*/
|
|
1631
|
-
var DbConfigEnvironmentVariables = class {
|
|
1632
|
-
/**
|
|
1633
|
-
* Postgres host
|
|
1634
|
-
* @example
|
|
1635
|
-
* ```yaml
|
|
1636
|
-
* POSTGRES_HOST: 'localhost'
|
|
1637
|
-
* ```
|
|
1638
|
-
*/
|
|
1639
|
-
POSTGRES_HOST;
|
|
1640
|
-
/**
|
|
1641
|
-
* Postgres port
|
|
1642
|
-
* @example
|
|
1643
|
-
* ```yaml
|
|
1644
|
-
* POSTGRES_PORT: 5432
|
|
1645
|
-
* ```
|
|
1646
|
-
*/
|
|
1647
|
-
POSTGRES_PORT;
|
|
1648
|
-
/**
|
|
1649
|
-
* Postgres user
|
|
1650
|
-
* @example
|
|
1651
|
-
* ```yaml
|
|
1652
|
-
* POSTGRES_USER: 'app'
|
|
1653
|
-
* ```
|
|
1654
|
-
*/
|
|
1655
|
-
POSTGRES_USER;
|
|
1656
|
-
/**
|
|
1657
|
-
* Postgres password
|
|
1658
|
-
* @example
|
|
1659
|
-
* ```yaml
|
|
1660
|
-
* POSTGRES_PASS: 'qwerty'
|
|
1661
|
-
* ```
|
|
1662
|
-
*/
|
|
1663
|
-
POSTGRES_PASS;
|
|
1664
|
-
/**
|
|
1665
|
-
* Postgres database name
|
|
1666
|
-
* @example
|
|
1667
|
-
* ```yaml
|
|
1668
|
-
* POSTGRES_DB: 'jetstream'
|
|
1669
|
-
* ```
|
|
1670
|
-
*/
|
|
1671
|
-
POSTGRES_DB;
|
|
1672
|
-
/**
|
|
1673
|
-
* Enable postgres logging
|
|
1674
|
-
* @example
|
|
1675
|
-
* ```yaml
|
|
1676
|
-
* POSTGRES_IS_LOGGING_ENABLED: "true"
|
|
1677
|
-
* ```
|
|
1678
|
-
*/
|
|
1679
|
-
POSTGRES_IS_LOGGING_ENABLED;
|
|
1680
|
-
};
|
|
1681
|
-
__decorate([IsString(), __decorateMetadata("design:type", String)], DbConfigEnvironmentVariables.prototype, "POSTGRES_HOST", void 0);
|
|
1682
|
-
__decorate([
|
|
1683
|
-
Type$1(() => Number),
|
|
1684
|
-
IsNumber(),
|
|
1685
|
-
__decorateMetadata("design:type", Number)
|
|
1686
|
-
], DbConfigEnvironmentVariables.prototype, "POSTGRES_PORT", void 0);
|
|
1687
|
-
__decorate([IsString(), __decorateMetadata("design:type", String)], DbConfigEnvironmentVariables.prototype, "POSTGRES_USER", void 0);
|
|
1688
|
-
__decorate([IsString(), __decorateMetadata("design:type", String)], DbConfigEnvironmentVariables.prototype, "POSTGRES_PASS", void 0);
|
|
1689
|
-
__decorate([IsString(), __decorateMetadata("design:type", String)], DbConfigEnvironmentVariables.prototype, "POSTGRES_DB", void 0);
|
|
1690
|
-
__decorate([
|
|
1691
|
-
Type$1(() => Boolean),
|
|
1692
|
-
IsOptional(),
|
|
1693
|
-
IsBoolean(),
|
|
1694
|
-
__decorateMetadata("design:type", Boolean)
|
|
1695
|
-
], DbConfigEnvironmentVariables.prototype, "POSTGRES_IS_LOGGING_ENABLED", void 0);
|
|
1696
162
|
/**
|
|
1697
|
-
*
|
|
163
|
+
* Pauses execution for a specified amount of time using a Promise.
|
|
164
|
+
* @param ms - The amount of time to pause in milliseconds.
|
|
165
|
+
* @returns A Promise that resolves after the specified amount of time has elapsed.
|
|
1698
166
|
*/
|
|
1699
|
-
const
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
type: "postgres",
|
|
1705
|
-
logging: env.POSTGRES_IS_LOGGING_ENABLED,
|
|
1706
|
-
host: env.POSTGRES_HOST,
|
|
1707
|
-
port: env.POSTGRES_PORT,
|
|
1708
|
-
username: env.POSTGRES_USER,
|
|
1709
|
-
password: env.POSTGRES_PASS,
|
|
1710
|
-
database: env.POSTGRES_DB,
|
|
1711
|
-
synchronize: false,
|
|
1712
|
-
migrations: ["dist/migrations/*.js"],
|
|
1713
|
-
subscribers: ["dist/**/*.entity-subscriber.js"],
|
|
1714
|
-
migrationsRun: true,
|
|
1715
|
-
namingStrategy: new SnakeNamingStrategy(),
|
|
1716
|
-
...opts,
|
|
1717
|
-
entities: fg.sync(entities)
|
|
1718
|
-
};
|
|
167
|
+
const wait = async (ms) => {
|
|
168
|
+
await new Promise((resolve) => {
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
resolve(null);
|
|
171
|
+
}, ms);
|
|
1719
172
|
});
|
|
1720
173
|
};
|
|
1721
174
|
|
|
1722
|
-
//#endregion
|
|
1723
|
-
//#region src/tools/compose.ts
|
|
1724
|
-
function compose(baseClass, ...mixins) {
|
|
1725
|
-
return mixins.reduce((currentClass, mixin) => mixin(currentClass), baseClass);
|
|
1726
|
-
}
|
|
1727
|
-
|
|
1728
|
-
//#endregion
|
|
1729
|
-
//#region src/tools/convert-to-bigint.ts
|
|
1730
|
-
/**
|
|
1731
|
-
* Converts a number or string value to a BigInt, preserving null and undefined values.
|
|
1732
|
-
*
|
|
1733
|
-
* @param value - The value to convert. Can be a number, string, undefined, or null.
|
|
1734
|
-
* @returns The converted BigInt value, or the original value if it was null or undefined.
|
|
1735
|
-
*
|
|
1736
|
-
* @example
|
|
1737
|
-
* ```typescript
|
|
1738
|
-
* convertToBigInt(123) // returns 123n
|
|
1739
|
-
* convertToBigInt("456") // returns 456n
|
|
1740
|
-
* convertToBigInt(null) // returns null
|
|
1741
|
-
* convertToBigInt(undefined) // returns undefined
|
|
1742
|
-
* ```
|
|
1743
|
-
*
|
|
1744
|
-
* @throws {RangeError} Throws when the input cannot be converted to a valid BigInt.
|
|
1745
|
-
*/
|
|
1746
|
-
const convertToBigInt = (value) => {
|
|
1747
|
-
if (value === null) return value;
|
|
1748
|
-
if (typeof value === "undefined") return value;
|
|
1749
|
-
return BigInt(value);
|
|
1750
|
-
};
|
|
1751
|
-
|
|
1752
|
-
//#endregion
|
|
1753
|
-
//#region src/tools/fetch-total-with-query.ts
|
|
1754
|
-
/**
|
|
1755
|
-
* Returns total count of items with typeorm query
|
|
1756
|
-
* @param query - typeorm query builder
|
|
1757
|
-
* @returns total count of items
|
|
1758
|
-
*/
|
|
1759
|
-
/**
|
|
1760
|
-
* Returns total count of items with typeorm query
|
|
1761
|
-
* @param query - typeorm query builder
|
|
1762
|
-
* @returns total count of items
|
|
1763
|
-
*/
|
|
1764
|
-
const fetchTotalWithQuery = async (query) => {
|
|
1765
|
-
const totalQueryBuilder = query.clone();
|
|
1766
|
-
totalQueryBuilder.offset(void 0).limit(void 0).skip(void 0).take(void 0).orderBy();
|
|
1767
|
-
const hasDistinctOn = totalQueryBuilder.expressionMap.selectDistinctOn && totalQueryBuilder.expressionMap.selectDistinctOn.length > 0;
|
|
1768
|
-
const isGrouped = totalQueryBuilder.expressionMap.groupBys && totalQueryBuilder.expressionMap.groupBys.length > 0;
|
|
1769
|
-
if (hasDistinctOn || isGrouped) {
|
|
1770
|
-
const subQuery = totalQueryBuilder.getQuery();
|
|
1771
|
-
return (await query.connection.createQueryBuilder().select("COUNT(*)", "rowsCount").from(`(${subQuery})`, "subQuery").setParameters(totalQueryBuilder.getParameters()).getRawOne())?.rowsCount ?? 0;
|
|
1772
|
-
}
|
|
1773
|
-
return await totalQueryBuilder.getCount();
|
|
1774
|
-
};
|
|
1775
|
-
|
|
1776
|
-
//#endregion
|
|
1777
|
-
//#region src/tools/create-list-meta.ts
|
|
1778
|
-
/**
|
|
1779
|
-
* Create list meta object
|
|
1780
|
-
* @returns list meta object
|
|
1781
|
-
* @example
|
|
1782
|
-
* class UsersService {
|
|
1783
|
-
* async getMany(opts: GetManyUsersOptions): Promise<[User[], ListMeta]> {
|
|
1784
|
-
* ...
|
|
1785
|
-
* return Promise.all([
|
|
1786
|
-
* query.getMany(),
|
|
1787
|
-
* createListMeta<User>({
|
|
1788
|
-
* query,
|
|
1789
|
-
* needCountTotal,
|
|
1790
|
-
* limit,
|
|
1791
|
-
* offset,
|
|
1792
|
-
* }),
|
|
1793
|
-
* ]);
|
|
1794
|
-
* }
|
|
1795
|
-
*/
|
|
1796
|
-
const createListMeta = async ({ query, needCountTotal = false, limit, offset }) => {
|
|
1797
|
-
const meta = {
|
|
1798
|
-
limit,
|
|
1799
|
-
offset
|
|
1800
|
-
};
|
|
1801
|
-
if (needCountTotal) meta.total = await fetchTotalWithQuery(query);
|
|
1802
|
-
return meta;
|
|
1803
|
-
};
|
|
1804
|
-
|
|
1805
|
-
//#endregion
|
|
1806
|
-
//#region src/tools/define-statuses.ts
|
|
1807
|
-
/**
|
|
1808
|
-
* Define statuses. Returns array of statuses from filter or default statuses
|
|
1809
|
-
* @param statuses - array of statuses from filter. Can be undefined
|
|
1810
|
-
* @param defaultStatuses - array of default statuses
|
|
1811
|
-
* @returns final array of statuses
|
|
1812
|
-
* @example
|
|
1813
|
-
* const statuses = defineStatuses(['active', 'pending'], ['active']);
|
|
1814
|
-
* // statuses = ['active', 'pending']
|
|
1815
|
-
*
|
|
1816
|
-
* const statuses = defineStatuses(undefined, ['active']);
|
|
1817
|
-
* // statuses = ['active']
|
|
1818
|
-
*/
|
|
1819
|
-
const defineStatuses = (statuses, defaultStatuses) => {
|
|
1820
|
-
return Array.isArray(statuses) ? statuses : defaultStatuses;
|
|
1821
|
-
};
|
|
1822
|
-
|
|
1823
|
-
//#endregion
|
|
1824
|
-
//#region src/tools/get-request-language.ts
|
|
1825
|
-
const getRequestLanguage = (req, fallbackLanguage) => {
|
|
1826
|
-
const headers = req?.headers;
|
|
1827
|
-
return parse(headers["accept-language"])?.[0]?.code ?? fallbackLanguage;
|
|
1828
|
-
};
|
|
1829
|
-
|
|
1830
175
|
//#endregion
|
|
1831
176
|
//#region src/tools/postgres/locale-to-pg-collate.ts
|
|
1832
177
|
/**
|
|
@@ -1847,54 +192,6 @@ const localeToPgCollate = (locale) => {
|
|
|
1847
192
|
return collate;
|
|
1848
193
|
};
|
|
1849
194
|
|
|
1850
|
-
//#endregion
|
|
1851
|
-
//#region src/tools/remove-undefined-properties.ts
|
|
1852
|
-
const removeUndefinedProperties = (obj) => {
|
|
1853
|
-
const result = {};
|
|
1854
|
-
for (const key in obj) if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== void 0) result[key] = obj[key];
|
|
1855
|
-
return result;
|
|
1856
|
-
};
|
|
1857
|
-
|
|
1858
|
-
//#endregion
|
|
1859
|
-
//#region src/tools/request-id.ts
|
|
1860
|
-
const generateRequestId = (appShortName) => {
|
|
1861
|
-
return `${appShortName}req:${createRandomString()}`;
|
|
1862
|
-
};
|
|
1863
|
-
const extractRequestId = (req) => {
|
|
1864
|
-
const headers = req?.headers;
|
|
1865
|
-
if (headers?.["x-request-id"]) return headers["x-request-id"];
|
|
1866
|
-
if (headers["x-cloud-trace-context"]) return req.appShortname + `req:${headers["x-cloud-trace-context"]}`;
|
|
1867
|
-
return generateRequestId(req.appShortname);
|
|
1868
|
-
};
|
|
1869
|
-
|
|
1870
|
-
//#endregion
|
|
1871
|
-
//#region src/tools/wait.ts
|
|
1872
|
-
/**
|
|
1873
|
-
* Pauses execution for a specified amount of time using a Promise.
|
|
1874
|
-
* @param ms - The amount of time to pause in milliseconds.
|
|
1875
|
-
* @returns A Promise that resolves after the specified amount of time has elapsed.
|
|
1876
|
-
* @deprecated use wait instead
|
|
1877
|
-
*/
|
|
1878
|
-
const pauseWithPromise = async (ms) => {
|
|
1879
|
-
return await new Promise((resolve) => {
|
|
1880
|
-
setTimeout(() => {
|
|
1881
|
-
resolve();
|
|
1882
|
-
}, ms);
|
|
1883
|
-
});
|
|
1884
|
-
};
|
|
1885
|
-
/**
|
|
1886
|
-
* Pauses execution for a specified amount of time using a Promise.
|
|
1887
|
-
* @param ms - The amount of time to pause in milliseconds.
|
|
1888
|
-
* @returns A Promise that resolves after the specified amount of time has elapsed.
|
|
1889
|
-
*/
|
|
1890
|
-
const wait = async (ms) => {
|
|
1891
|
-
return await new Promise((resolve) => {
|
|
1892
|
-
setTimeout(() => {
|
|
1893
|
-
resolve();
|
|
1894
|
-
}, ms);
|
|
1895
|
-
});
|
|
1896
|
-
};
|
|
1897
|
-
|
|
1898
195
|
//#endregion
|
|
1899
196
|
//#region src/tools/typeorm/add-filter.ts
|
|
1900
197
|
/**
|
|
@@ -2079,82 +376,5 @@ const ensureInnerJoin = (query, entity, alias, condition) => {
|
|
|
2079
376
|
};
|
|
2080
377
|
|
|
2081
378
|
//#endregion
|
|
2082
|
-
|
|
2083
|
-
/**
|
|
2084
|
-
* Ensures a left join is added to a TypeORM query builder if the alias is not already in use.
|
|
2085
|
-
*
|
|
2086
|
-
* This function checks if the specified alias is already being used in the query.
|
|
2087
|
-
* If the alias is available, it performs a left join with the provided entity, alias, and optional condition.
|
|
2088
|
-
* If the alias is already busy, the function returns early without modifying the query.
|
|
2089
|
-
*
|
|
2090
|
-
* @template T - The entity type that extends ObjectLiteral
|
|
2091
|
-
* @param query - The TypeORM SelectQueryBuilder instance to add the left join to
|
|
2092
|
-
* @param entity - The entity class (Function) or table name (string) to join
|
|
2093
|
-
* @param alias - The alias name to use for the joined entity
|
|
2094
|
-
* @param condition - Optional join condition as a string (e.g., "alias.id = entity.foreignId")
|
|
2095
|
-
* @returns void
|
|
2096
|
-
*
|
|
2097
|
-
* @example
|
|
2098
|
-
* ```typescript
|
|
2099
|
-
* ensureLeftJoin(queryBuilder, User, 'user', 'user.id = post.userId');
|
|
2100
|
-
* ```
|
|
2101
|
-
*/
|
|
2102
|
-
const ensureLeftJoin = (query, entity, alias, condition) => {
|
|
2103
|
-
if (isAliasAlreadyBusy(query, alias)) return;
|
|
2104
|
-
query.leftJoin(entity, alias, condition);
|
|
2105
|
-
};
|
|
2106
|
-
|
|
2107
|
-
//#endregion
|
|
2108
|
-
//#region src/validation/validation-pipe.ts
|
|
2109
|
-
var NestKitValidationPipe = class extends ValidationPipe {
|
|
2110
|
-
createExceptionFactory() {
|
|
2111
|
-
return (validationErrors = []) => {
|
|
2112
|
-
if (!this.isDetailedOutputDisabled) return new InputValidationError(validationErrors);
|
|
2113
|
-
return new InputValidationError();
|
|
2114
|
-
};
|
|
2115
|
-
}
|
|
2116
|
-
};
|
|
2117
|
-
|
|
2118
|
-
//#endregion
|
|
2119
|
-
//#region src/exceptions/http-exceptions.filter.ts
|
|
2120
|
-
var _ref, _ref2, _HttpExceptionFilter;
|
|
2121
|
-
let HttpExceptionFilter = _HttpExceptionFilter = class HttpExceptionFilter$1 {
|
|
2122
|
-
logger;
|
|
2123
|
-
constructor(applicationRef, loggerFactory) {
|
|
2124
|
-
this.applicationRef = applicationRef;
|
|
2125
|
-
this.loggerFactory = loggerFactory;
|
|
2126
|
-
this.logger = this.loggerFactory.create({ scope: _HttpExceptionFilter.name });
|
|
2127
|
-
}
|
|
2128
|
-
catch(exception, host) {
|
|
2129
|
-
const type = GqlArgumentsHost.create(host).getType();
|
|
2130
|
-
const response = exception.getResponse();
|
|
2131
|
-
if (!response?.silent) if (isObject$1(response)) {
|
|
2132
|
-
const logger = this.loggerFactory.create(response.context);
|
|
2133
|
-
if (response.error instanceof Error) logger.error(response.message, response.error);
|
|
2134
|
-
else logger.error(exception);
|
|
2135
|
-
} else this.logger.error(exception);
|
|
2136
|
-
if (type !== "http") return exception;
|
|
2137
|
-
/**
|
|
2138
|
-
* If request is http, then we need to send response to client
|
|
2139
|
-
*/
|
|
2140
|
-
let body;
|
|
2141
|
-
if (isObject$1(response)) {
|
|
2142
|
-
body = {
|
|
2143
|
-
key: response.key,
|
|
2144
|
-
message: response.message,
|
|
2145
|
-
context: response.context,
|
|
2146
|
-
statusCode: exception.getStatus()
|
|
2147
|
-
};
|
|
2148
|
-
if (response.error instanceof Error && process.env.NODE_ENV !== AppEnv.PRODUCTION) body.stack = response.error.stack;
|
|
2149
|
-
} else body = {
|
|
2150
|
-
statusCode: exception.getStatus(),
|
|
2151
|
-
message: response
|
|
2152
|
-
};
|
|
2153
|
-
this.applicationRef.reply(host.getArgByIndex(1), body, exception.getStatus());
|
|
2154
|
-
}
|
|
2155
|
-
};
|
|
2156
|
-
HttpExceptionFilter = _HttpExceptionFilter = __decorate([Catch(HttpException), __decorateMetadata("design:paramtypes", [typeof (_ref = typeof HttpServer !== "undefined" && HttpServer) === "function" ? _ref : Object, typeof (_ref2 = typeof LoggerFactory !== "undefined" && LoggerFactory) === "function" ? _ref2 : Object])], HttpExceptionFilter);
|
|
2157
|
-
|
|
2158
|
-
//#endregion
|
|
2159
|
-
export { APP_CONFIG_TOKEN, AccessDeniedError, AppConfigEnvironmentVariables, AppEnv, AppMode, AppServer, BadRequestError, DB_CONFIG_TOKEN, ForbiddenError, HttpExceptionFilter, InjectAppConfig, InjectDbConfig, InjectLogger, InjectLoggerConfig, InjectLoggerFactory, InputValidationError, LOGGER_CONFIG_TOKEN, Logger, LoggerFactory, LoggerModule, NESTKIT_LOGGER_FACTORY_PROVIDER, NESTKIT_LOGGER_MODULE_OPTIONS, NESTKIT_LOGGER_PROVIDER, NESTKIT_SYSTEM_LOGGER_PROVIDER, NESTKIT_WINSTON_LOGGER_PROVIDER, NestError, NestJsResourceService, NestJsService, NestKitValidationPipe, NestSystemLogger, NotFoundError, TypeOrmLogger, TypeOrmLoggerOptions, UnauthorizedError, WorkerMode, addFilterByField, compose, convertToBigInt, createAppConfig, createDbConfig, createListMeta, createLoggerAsyncProviders, createLoggerConfig, createLoggerProviders, createNestLogger, createPrettyMessage, defineStatuses, ensureInnerJoin, ensureLeftJoin, extractRequestId, fetchTotalWithQuery, generateEntityId, generateRequestId, getRequestLanguage, isAliasAlreadyBusy, isObject, localeToPgCollate, nestLikeConsoleFormat, pauseWithPromise, removeUndefinedProperties, stringifyOpts, validateEnv, wait, withColonEnv, withDashEnv, withDotEnv, withUnderscoreEnv };
|
|
379
|
+
export { addFilterByField, convertToBigInt, defineStatuses, ensureInnerJoin, extractRequestId, generateEntityId, generateRequestId, getRequestLanguage, isAliasAlreadyBusy, localeToPgCollate, pauseWithPromise, removeUndefinedProperties, stringifyOpts, validateEnv, wait };
|
|
2160
380
|
//# sourceMappingURL=index.js.map
|