@decaf-ts/for-nest 0.0.4 → 0.0.5
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/for-nest.cjs +573 -6
- package/dist/for-nest.esm.cjs +549 -6
- package/lib/esm/factory/NestBootstraper.d.ts +214 -0
- package/lib/esm/factory/NestBootstraper.js +269 -0
- package/lib/esm/factory/errors/cors.d.ts +4 -0
- package/lib/esm/factory/errors/cors.js +7 -0
- package/lib/esm/factory/errors/index.d.ts +1 -0
- package/lib/esm/factory/errors/index.js +2 -0
- package/lib/esm/factory/exceptions/AuthorizationExceptionFilter.d.ts +9 -0
- package/lib/esm/factory/exceptions/AuthorizationExceptionFilter.js +35 -0
- package/lib/esm/factory/exceptions/ConflictExceptionFilter.d.ts +9 -0
- package/lib/esm/factory/exceptions/ConflictExceptionFilter.js +35 -0
- package/lib/esm/factory/exceptions/GlobalExceptionFilter.d.ts +4 -0
- package/lib/esm/factory/exceptions/GlobalExceptionFilter.js +35 -0
- package/lib/esm/factory/exceptions/HttpExceptionFilter.d.ts +4 -0
- package/lib/esm/factory/exceptions/HttpExceptionFilter.js +27 -0
- package/lib/esm/factory/exceptions/HttpResponseError.d.ts +14 -0
- package/lib/esm/factory/exceptions/HttpResponseError.js +19 -0
- package/lib/esm/factory/exceptions/NotFoundExceptionFilter.d.ts +9 -0
- package/lib/esm/factory/exceptions/NotFoundExceptionFilter.js +35 -0
- package/lib/esm/factory/exceptions/ValidationExceptionFilter.d.ts +9 -0
- package/lib/esm/factory/exceptions/ValidationExceptionFilter.js +35 -0
- package/lib/esm/factory/exceptions/index.d.ts +6 -0
- package/lib/esm/factory/exceptions/index.js +7 -0
- package/lib/esm/factory/index.d.ts +4 -0
- package/lib/esm/factory/index.js +5 -0
- package/lib/esm/factory/openapi/SwaggerBuilder.d.ts +9 -0
- package/lib/esm/factory/openapi/SwaggerBuilder.js +42 -0
- package/lib/esm/factory/openapi/SwaggerCustomUI.d.ts +24 -0
- package/lib/esm/factory/openapi/SwaggerCustomUI.js +55 -0
- package/lib/esm/factory/openapi/constants.d.ts +16 -0
- package/lib/esm/factory/openapi/constants.js +19 -0
- package/lib/esm/factory/openapi/index.d.ts +1 -0
- package/lib/esm/factory/openapi/index.js +2 -0
- package/lib/esm/index.d.ts +2 -1
- package/lib/esm/index.js +3 -2
- package/lib/factory/NestBootstraper.cjs +273 -0
- package/lib/factory/NestBootstraper.d.ts +214 -0
- package/lib/factory/errors/cors.cjs +11 -0
- package/lib/factory/errors/cors.d.ts +4 -0
- package/lib/factory/errors/index.cjs +18 -0
- package/lib/factory/errors/index.d.ts +1 -0
- package/lib/factory/exceptions/AuthorizationExceptionFilter.cjs +39 -0
- package/lib/factory/exceptions/AuthorizationExceptionFilter.d.ts +9 -0
- package/lib/factory/exceptions/ConflictExceptionFilter.cjs +39 -0
- package/lib/factory/exceptions/ConflictExceptionFilter.d.ts +9 -0
- package/lib/factory/exceptions/GlobalExceptionFilter.cjs +38 -0
- package/lib/factory/exceptions/GlobalExceptionFilter.d.ts +4 -0
- package/lib/factory/exceptions/HttpExceptionFilter.cjs +30 -0
- package/lib/factory/exceptions/HttpExceptionFilter.d.ts +4 -0
- package/lib/factory/exceptions/HttpResponseError.cjs +23 -0
- package/lib/factory/exceptions/HttpResponseError.d.ts +14 -0
- package/lib/factory/exceptions/NotFoundExceptionFilter.cjs +39 -0
- package/lib/factory/exceptions/NotFoundExceptionFilter.d.ts +9 -0
- package/lib/factory/exceptions/ValidationExceptionFilter.cjs +39 -0
- package/lib/factory/exceptions/ValidationExceptionFilter.d.ts +9 -0
- package/lib/factory/exceptions/index.cjs +23 -0
- package/lib/factory/exceptions/index.d.ts +6 -0
- package/lib/factory/index.cjs +21 -0
- package/lib/factory/index.d.ts +4 -0
- package/lib/factory/openapi/SwaggerBuilder.cjs +46 -0
- package/lib/factory/openapi/SwaggerBuilder.d.ts +9 -0
- package/lib/factory/openapi/SwaggerCustomUI.cjs +92 -0
- package/lib/factory/openapi/SwaggerCustomUI.d.ts +24 -0
- package/lib/factory/openapi/constants.cjs +22 -0
- package/lib/factory/openapi/constants.d.ts +16 -0
- package/lib/factory/openapi/index.cjs +18 -0
- package/lib/factory/openapi/index.d.ts +1 -0
- package/lib/index.cjs +3 -2
- package/lib/index.d.ts +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { INestApplication, Logger, NestInterceptor, PipeTransform } from "@nestjs/common";
|
|
2
|
+
/**
|
|
3
|
+
* @description
|
|
4
|
+
* Defines all customizable parameters for Swagger setup.
|
|
5
|
+
*
|
|
6
|
+
* @summary
|
|
7
|
+
* This interface allows developers to customize how Swagger UI is configured
|
|
8
|
+
* within the NestJS application. It includes parameters for titles, paths,
|
|
9
|
+
* color schemes, and asset paths to tailor the API documentation experience.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} title - Title displayed in Swagger UI.
|
|
12
|
+
* @param {string} description - Description shown below the title.
|
|
13
|
+
* @param {string} version - API version displayed in the documentation.
|
|
14
|
+
* @param {string} [path] - Optional path where Swagger will be available.
|
|
15
|
+
* @param {boolean} [persistAuthorization] - Whether authorization tokens persist across reloads.
|
|
16
|
+
* @param {string} [assetsPath] - Path to custom assets for Swagger UI.
|
|
17
|
+
* @param {string} [topbarBgColor] - Custom background color for the Swagger top bar.
|
|
18
|
+
* @param {string} [topbarIconPath] - Path to a custom icon displayed in the top bar.
|
|
19
|
+
* @param {string} [faviconPath] - Path to a custom favicon.
|
|
20
|
+
*/
|
|
21
|
+
export interface SwaggerSetupOptions {
|
|
22
|
+
title: string;
|
|
23
|
+
description: string;
|
|
24
|
+
version: string;
|
|
25
|
+
path?: string;
|
|
26
|
+
persistAuthorization?: boolean;
|
|
27
|
+
assetsPath?: string;
|
|
28
|
+
topbarBgColor?: string;
|
|
29
|
+
topbarIconPath?: string;
|
|
30
|
+
faviconPath?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @description
|
|
34
|
+
* A fluent, static bootstrap class for initializing and configuring a NestJS application.
|
|
35
|
+
*
|
|
36
|
+
* @summary
|
|
37
|
+
* The `NestBootstraper` class provides a chainable API for configuring
|
|
38
|
+
* a NestJS application instance. It includes built-in methods for enabling
|
|
39
|
+
* CORS, Helmet security, Swagger documentation, global pipes, filters,
|
|
40
|
+
* interceptors, and starting the server.
|
|
41
|
+
*
|
|
42
|
+
* This class promotes consistency and reduces repetitive setup code
|
|
43
|
+
* across multiple NestJS projects.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* import { NestFactory } from "@nestjs/core";
|
|
48
|
+
* import { AppModule } from "./app.module";
|
|
49
|
+
* import { MyLogger } from "./MyLogger";
|
|
50
|
+
* import { NestBootstraper } from "@decaf-ts/for-nest";
|
|
51
|
+
*
|
|
52
|
+
* async function bootstrap() {
|
|
53
|
+
* const app = await NestFactory.create(AppModule);
|
|
54
|
+
*
|
|
55
|
+
* await NestBootstraper
|
|
56
|
+
* .initialize(app)
|
|
57
|
+
* .enableLogger(new MyLogger())
|
|
58
|
+
* .enableCors(["http://localhost:4200"])
|
|
59
|
+
* .useHelmet()
|
|
60
|
+
* .setupSwagger({
|
|
61
|
+
* title: "OpenAPI by TradeMark™",
|
|
62
|
+
* description: "TradeMark™ API documentation",
|
|
63
|
+
* version: "1.0.0",
|
|
64
|
+
* path: "api",
|
|
65
|
+
* persistAuthorization: true,
|
|
66
|
+
* topbarBgColor: "#2C3E50",
|
|
67
|
+
* topbarIconPath: "/assets/logo.svg",
|
|
68
|
+
* faviconPath: "/assets/favicon.ico"
|
|
69
|
+
* })
|
|
70
|
+
* .useGlobalFilters()
|
|
71
|
+
* .useGlobalPipes(...)
|
|
72
|
+
* .useGlobalInterceptors(...)
|
|
73
|
+
* .start(3000);
|
|
74
|
+
* }
|
|
75
|
+
*
|
|
76
|
+
* bootstrap();
|
|
77
|
+
* ```
|
|
78
|
+
* @class
|
|
79
|
+
*/
|
|
80
|
+
export declare class NestBootstraper {
|
|
81
|
+
private static app;
|
|
82
|
+
private static _logger;
|
|
83
|
+
/**
|
|
84
|
+
* @description
|
|
85
|
+
* Returns the current logger instance, creating a default one if not set.
|
|
86
|
+
*
|
|
87
|
+
* @summary
|
|
88
|
+
* Ensures that a valid `Logger` instance is always available
|
|
89
|
+
* for logging bootstrap-related messages.
|
|
90
|
+
*
|
|
91
|
+
* @return {Logger} The active logger instance.
|
|
92
|
+
*/
|
|
93
|
+
private static get logger();
|
|
94
|
+
/**
|
|
95
|
+
* @description
|
|
96
|
+
* Initializes the bootstrapper with a given NestJS application.
|
|
97
|
+
*
|
|
98
|
+
* @summary
|
|
99
|
+
* Binds the provided NestJS app instance to the bootstrapper, enabling
|
|
100
|
+
* chained configuration methods.
|
|
101
|
+
*
|
|
102
|
+
* @param {INestApplication} app - The NestJS application instance to initialize.
|
|
103
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration methods.
|
|
104
|
+
*/
|
|
105
|
+
static initialize(app: INestApplication): typeof NestBootstraper;
|
|
106
|
+
/**
|
|
107
|
+
* @description
|
|
108
|
+
* Enables or replaces the global logger for the NestJS application.
|
|
109
|
+
*
|
|
110
|
+
* @summary
|
|
111
|
+
* If a custom logger is provided, it replaces the default logger. Otherwise,
|
|
112
|
+
* a new logger named `"NestBootstrap"` is used. This logger is also registered
|
|
113
|
+
* with the NestJS application.
|
|
114
|
+
*
|
|
115
|
+
* @param {Logger} [customLogger] - Optional custom logger instance.
|
|
116
|
+
* @return {typeof NestBootstraper} Returns the class for chaining.
|
|
117
|
+
*/
|
|
118
|
+
static enableLogger(customLogger?: Logger): typeof NestBootstraper;
|
|
119
|
+
/**
|
|
120
|
+
* @description
|
|
121
|
+
* Enables Cross-Origin Resource Sharing (CORS) for the application.
|
|
122
|
+
*
|
|
123
|
+
* @summary
|
|
124
|
+
* Allows defining either a wildcard origin (`"*"`) or a list of allowed origins.
|
|
125
|
+
* Automatically accepts local development requests and those without origin headers.
|
|
126
|
+
* Throws a `CorsError` for unauthorized origins.
|
|
127
|
+
*
|
|
128
|
+
* @param {'*' | string[]} [origins=[]] - List of allowed origins or `"*"` to allow all.
|
|
129
|
+
* @param {string[]} [allowMethods=['GET', 'POST', 'PUT', 'DELETE']] - Allowed HTTP methods.
|
|
130
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
131
|
+
*
|
|
132
|
+
*/
|
|
133
|
+
static enableCors(origins?: "*" | string[], allowMethods?: string[]): typeof NestBootstraper;
|
|
134
|
+
/**
|
|
135
|
+
* @description
|
|
136
|
+
* Applies the Helmet middleware for enhanced security.
|
|
137
|
+
*
|
|
138
|
+
* @summary
|
|
139
|
+
* Dynamically loads the `helmet` package if available and registers it
|
|
140
|
+
* as middleware to improve HTTP header security. If not installed, logs a warning
|
|
141
|
+
* and continues execution without throwing errors.
|
|
142
|
+
*
|
|
143
|
+
* @param {Record<string, any>} [options] - Optional configuration passed to Helmet.
|
|
144
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
145
|
+
*/
|
|
146
|
+
static useHelmet(options?: Record<string, any>): typeof NestBootstraper;
|
|
147
|
+
/**
|
|
148
|
+
* @description
|
|
149
|
+
* Configures and initializes Swagger UI for API documentation.
|
|
150
|
+
*
|
|
151
|
+
* @summary
|
|
152
|
+
* Uses the `SwaggerBuilder` utility to configure API documentation
|
|
153
|
+
* with detailed customization for title, version, paths, and colors.
|
|
154
|
+
* Swagger is automatically exposed at the configured path.
|
|
155
|
+
*
|
|
156
|
+
* @param {SwaggerSetupOptions} options - Swagger configuration options.
|
|
157
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
158
|
+
*/
|
|
159
|
+
static setupSwagger(options: SwaggerSetupOptions): typeof NestBootstraper;
|
|
160
|
+
/**
|
|
161
|
+
* @description
|
|
162
|
+
* Registers one or more global validation pipes.
|
|
163
|
+
*
|
|
164
|
+
* @summary
|
|
165
|
+
* Enables request payload validation and transformation globally across
|
|
166
|
+
* the entire NestJS application. Multiple pipes can be chained together
|
|
167
|
+
* for modular input validation.
|
|
168
|
+
*
|
|
169
|
+
* @param {...PipeTransform[]} pipes - Pipe instances to register globally.
|
|
170
|
+
* @return {typeof NestBootstraper} Returns the class for chaining.
|
|
171
|
+
*/
|
|
172
|
+
static useGlobalPipes(...pipes: PipeTransform[]): typeof NestBootstraper;
|
|
173
|
+
/**
|
|
174
|
+
* @description
|
|
175
|
+
* Registers one or more global exception filters.
|
|
176
|
+
*
|
|
177
|
+
* @summary
|
|
178
|
+
* If no filters are provided, it automatically registers a default
|
|
179
|
+
* set of standard exception filters for common error types like
|
|
180
|
+
* `HttpException`, `ValidationException`, `ConflictException`, and others.
|
|
181
|
+
*
|
|
182
|
+
* @param {...ExceptionFilter[]} filters - Optional filters to apply globally.
|
|
183
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
184
|
+
*/
|
|
185
|
+
static useGlobalFilters(...filters: any[]): typeof NestBootstraper;
|
|
186
|
+
/**
|
|
187
|
+
* @description
|
|
188
|
+
* Registers global interceptors for request and response transformation.
|
|
189
|
+
*
|
|
190
|
+
* @summary
|
|
191
|
+
* Interceptors allow advanced request/response manipulation such as
|
|
192
|
+
* serialization, logging, or transformation. Multiple interceptors
|
|
193
|
+
* can be added for modular configuration.
|
|
194
|
+
*
|
|
195
|
+
* @param {...NestInterceptor[]} interceptors - Interceptor instances to register.
|
|
196
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
197
|
+
*/
|
|
198
|
+
static useGlobalInterceptors(...interceptors: NestInterceptor[]): typeof NestBootstraper;
|
|
199
|
+
/**
|
|
200
|
+
* @description
|
|
201
|
+
* Starts the NestJS application and binds it to the given port and host.
|
|
202
|
+
*
|
|
203
|
+
* @summary
|
|
204
|
+
* Listens on the specified port and optionally a host. Once started,
|
|
205
|
+
* logs the application URL for easy access. The startup process resolves
|
|
206
|
+
* once the application is successfully running.
|
|
207
|
+
*
|
|
208
|
+
* @param {number} [port=3000] - Port number to listen on.
|
|
209
|
+
* @param {string} [host] - Optional host or IP address to bind to.
|
|
210
|
+
* @param {boolean} [log=true] - Whether to log the application URL upon startup.
|
|
211
|
+
* @return {Promise<void>} Resolves once the application starts successfully.
|
|
212
|
+
*/
|
|
213
|
+
static start(port?: number, host?: string | undefined, log?: boolean): Promise<void>;
|
|
214
|
+
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { Logger, } from "@nestjs/common";
|
|
2
|
+
import { AuthorizationExceptionFilter, ConflictExceptionFilter, GlobalExceptionFilter, HttpExceptionFilter, NotFoundExceptionFilter, ValidationExceptionFilter, } from "./exceptions/index.js";
|
|
3
|
+
import { SwaggerBuilder } from "./openapi/index.js";
|
|
4
|
+
import { CorsError } from "./errors/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* A fluent, static bootstrap class for initializing and configuring a NestJS application.
|
|
8
|
+
*
|
|
9
|
+
* @summary
|
|
10
|
+
* The `NestBootstraper` class provides a chainable API for configuring
|
|
11
|
+
* a NestJS application instance. It includes built-in methods for enabling
|
|
12
|
+
* CORS, Helmet security, Swagger documentation, global pipes, filters,
|
|
13
|
+
* interceptors, and starting the server.
|
|
14
|
+
*
|
|
15
|
+
* This class promotes consistency and reduces repetitive setup code
|
|
16
|
+
* across multiple NestJS projects.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { NestFactory } from "@nestjs/core";
|
|
21
|
+
* import { AppModule } from "./app.module";
|
|
22
|
+
* import { MyLogger } from "./MyLogger";
|
|
23
|
+
* import { NestBootstraper } from "@decaf-ts/for-nest";
|
|
24
|
+
*
|
|
25
|
+
* async function bootstrap() {
|
|
26
|
+
* const app = await NestFactory.create(AppModule);
|
|
27
|
+
*
|
|
28
|
+
* await NestBootstraper
|
|
29
|
+
* .initialize(app)
|
|
30
|
+
* .enableLogger(new MyLogger())
|
|
31
|
+
* .enableCors(["http://localhost:4200"])
|
|
32
|
+
* .useHelmet()
|
|
33
|
+
* .setupSwagger({
|
|
34
|
+
* title: "OpenAPI by TradeMark™",
|
|
35
|
+
* description: "TradeMark™ API documentation",
|
|
36
|
+
* version: "1.0.0",
|
|
37
|
+
* path: "api",
|
|
38
|
+
* persistAuthorization: true,
|
|
39
|
+
* topbarBgColor: "#2C3E50",
|
|
40
|
+
* topbarIconPath: "/assets/logo.svg",
|
|
41
|
+
* faviconPath: "/assets/favicon.ico"
|
|
42
|
+
* })
|
|
43
|
+
* .useGlobalFilters()
|
|
44
|
+
* .useGlobalPipes(...)
|
|
45
|
+
* .useGlobalInterceptors(...)
|
|
46
|
+
* .start(3000);
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* bootstrap();
|
|
50
|
+
* ```
|
|
51
|
+
* @class
|
|
52
|
+
*/
|
|
53
|
+
export class NestBootstraper {
|
|
54
|
+
/**
|
|
55
|
+
* @description
|
|
56
|
+
* Returns the current logger instance, creating a default one if not set.
|
|
57
|
+
*
|
|
58
|
+
* @summary
|
|
59
|
+
* Ensures that a valid `Logger` instance is always available
|
|
60
|
+
* for logging bootstrap-related messages.
|
|
61
|
+
*
|
|
62
|
+
* @return {Logger} The active logger instance.
|
|
63
|
+
*/
|
|
64
|
+
static get logger() {
|
|
65
|
+
if (!this._logger) {
|
|
66
|
+
// fallback
|
|
67
|
+
this._logger = new Logger("NestBootstrap");
|
|
68
|
+
}
|
|
69
|
+
return this._logger;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* @description
|
|
73
|
+
* Initializes the bootstrapper with a given NestJS application.
|
|
74
|
+
*
|
|
75
|
+
* @summary
|
|
76
|
+
* Binds the provided NestJS app instance to the bootstrapper, enabling
|
|
77
|
+
* chained configuration methods.
|
|
78
|
+
*
|
|
79
|
+
* @param {INestApplication} app - The NestJS application instance to initialize.
|
|
80
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration methods.
|
|
81
|
+
*/
|
|
82
|
+
static initialize(app) {
|
|
83
|
+
this.app = app;
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* @description
|
|
88
|
+
* Enables or replaces the global logger for the NestJS application.
|
|
89
|
+
*
|
|
90
|
+
* @summary
|
|
91
|
+
* If a custom logger is provided, it replaces the default logger. Otherwise,
|
|
92
|
+
* a new logger named `"NestBootstrap"` is used. This logger is also registered
|
|
93
|
+
* with the NestJS application.
|
|
94
|
+
*
|
|
95
|
+
* @param {Logger} [customLogger] - Optional custom logger instance.
|
|
96
|
+
* @return {typeof NestBootstraper} Returns the class for chaining.
|
|
97
|
+
*/
|
|
98
|
+
static enableLogger(customLogger) {
|
|
99
|
+
this._logger = customLogger || new Logger("NestBootstrap");
|
|
100
|
+
this.app.useLogger(this._logger);
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* @description
|
|
105
|
+
* Enables Cross-Origin Resource Sharing (CORS) for the application.
|
|
106
|
+
*
|
|
107
|
+
* @summary
|
|
108
|
+
* Allows defining either a wildcard origin (`"*"`) or a list of allowed origins.
|
|
109
|
+
* Automatically accepts local development requests and those without origin headers.
|
|
110
|
+
* Throws a `CorsError` for unauthorized origins.
|
|
111
|
+
*
|
|
112
|
+
* @param {'*' | string[]} [origins=[]] - List of allowed origins or `"*"` to allow all.
|
|
113
|
+
* @param {string[]} [allowMethods=['GET', 'POST', 'PUT', 'DELETE']] - Allowed HTTP methods.
|
|
114
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
115
|
+
*
|
|
116
|
+
*/
|
|
117
|
+
static enableCors(origins = [], allowMethods = ["GET", "POST", "PUT", "DELETE"]) {
|
|
118
|
+
const allowedOrigins = origins === "*" ? "*" : origins.map((o) => o.trim().toLowerCase());
|
|
119
|
+
const corsOptions = {
|
|
120
|
+
origin: (origin, callback) => {
|
|
121
|
+
// Allow request without origin...
|
|
122
|
+
if (!origin)
|
|
123
|
+
return callback(null, true);
|
|
124
|
+
if (allowedOrigins === "*" ||
|
|
125
|
+
(Array.isArray(allowedOrigins) &&
|
|
126
|
+
allowedOrigins.includes(origin.toLowerCase()))) {
|
|
127
|
+
return callback(null, true);
|
|
128
|
+
}
|
|
129
|
+
callback(new CorsError(`Origin ${origin} not allowed`));
|
|
130
|
+
},
|
|
131
|
+
credentials: true,
|
|
132
|
+
methods: allowMethods.join(","),
|
|
133
|
+
};
|
|
134
|
+
this.app.enableCors(corsOptions);
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* @description
|
|
139
|
+
* Applies the Helmet middleware for enhanced security.
|
|
140
|
+
*
|
|
141
|
+
* @summary
|
|
142
|
+
* Dynamically loads the `helmet` package if available and registers it
|
|
143
|
+
* as middleware to improve HTTP header security. If not installed, logs a warning
|
|
144
|
+
* and continues execution without throwing errors.
|
|
145
|
+
*
|
|
146
|
+
* @param {Record<string, any>} [options] - Optional configuration passed to Helmet.
|
|
147
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
148
|
+
*/
|
|
149
|
+
static useHelmet(options) {
|
|
150
|
+
try {
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
152
|
+
const helmet = require("helmet"); // Dynamic import to avoid hard dependency
|
|
153
|
+
this.app.use(helmet(options));
|
|
154
|
+
this.logger.log("Helmet middleware enabled successfully.");
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
this.logger.warn("Helmet not installed. Skipping middleware.");
|
|
158
|
+
}
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* @description
|
|
163
|
+
* Configures and initializes Swagger UI for API documentation.
|
|
164
|
+
*
|
|
165
|
+
* @summary
|
|
166
|
+
* Uses the `SwaggerBuilder` utility to configure API documentation
|
|
167
|
+
* with detailed customization for title, version, paths, and colors.
|
|
168
|
+
* Swagger is automatically exposed at the configured path.
|
|
169
|
+
*
|
|
170
|
+
* @param {SwaggerSetupOptions} options - Swagger configuration options.
|
|
171
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
172
|
+
*/
|
|
173
|
+
static setupSwagger(options) {
|
|
174
|
+
const swagger = new SwaggerBuilder(this.app, {
|
|
175
|
+
title: options.title,
|
|
176
|
+
description: options.description,
|
|
177
|
+
version: options.version,
|
|
178
|
+
path: options.path || "api",
|
|
179
|
+
persistAuthorization: options.persistAuthorization ?? true,
|
|
180
|
+
assetsPath: options.assetsPath,
|
|
181
|
+
faviconFilePath: options.faviconPath,
|
|
182
|
+
topbarIconFilePath: options.topbarIconPath,
|
|
183
|
+
topbarBgColor: options.topbarBgColor,
|
|
184
|
+
});
|
|
185
|
+
swagger.setupSwagger();
|
|
186
|
+
return this;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* @description
|
|
190
|
+
* Registers one or more global validation pipes.
|
|
191
|
+
*
|
|
192
|
+
* @summary
|
|
193
|
+
* Enables request payload validation and transformation globally across
|
|
194
|
+
* the entire NestJS application. Multiple pipes can be chained together
|
|
195
|
+
* for modular input validation.
|
|
196
|
+
*
|
|
197
|
+
* @param {...PipeTransform[]} pipes - Pipe instances to register globally.
|
|
198
|
+
* @return {typeof NestBootstraper} Returns the class for chaining.
|
|
199
|
+
*/
|
|
200
|
+
static useGlobalPipes(...pipes) {
|
|
201
|
+
if (pipes.length > 0)
|
|
202
|
+
this.app.useGlobalPipes(...pipes);
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* @description
|
|
207
|
+
* Registers one or more global exception filters.
|
|
208
|
+
*
|
|
209
|
+
* @summary
|
|
210
|
+
* If no filters are provided, it automatically registers a default
|
|
211
|
+
* set of standard exception filters for common error types like
|
|
212
|
+
* `HttpException`, `ValidationException`, `ConflictException`, and others.
|
|
213
|
+
*
|
|
214
|
+
* @param {...ExceptionFilter[]} filters - Optional filters to apply globally.
|
|
215
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
216
|
+
*/
|
|
217
|
+
static useGlobalFilters(...filters) {
|
|
218
|
+
const defaultFilters = [
|
|
219
|
+
new HttpExceptionFilter(),
|
|
220
|
+
new ValidationExceptionFilter(),
|
|
221
|
+
new NotFoundExceptionFilter(),
|
|
222
|
+
new ConflictExceptionFilter(),
|
|
223
|
+
new AuthorizationExceptionFilter(),
|
|
224
|
+
new GlobalExceptionFilter(),
|
|
225
|
+
];
|
|
226
|
+
this.app.useGlobalFilters(...(filters.length > 0 ? filters : defaultFilters));
|
|
227
|
+
return this;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* @description
|
|
231
|
+
* Registers global interceptors for request and response transformation.
|
|
232
|
+
*
|
|
233
|
+
* @summary
|
|
234
|
+
* Interceptors allow advanced request/response manipulation such as
|
|
235
|
+
* serialization, logging, or transformation. Multiple interceptors
|
|
236
|
+
* can be added for modular configuration.
|
|
237
|
+
*
|
|
238
|
+
* @param {...NestInterceptor[]} interceptors - Interceptor instances to register.
|
|
239
|
+
* @return {typeof NestBootstraper} Returns the class for chaining configuration.
|
|
240
|
+
*/
|
|
241
|
+
static useGlobalInterceptors(...interceptors) {
|
|
242
|
+
if (interceptors.length > 0)
|
|
243
|
+
this.app.useGlobalInterceptors(...interceptors);
|
|
244
|
+
return this;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* @description
|
|
248
|
+
* Starts the NestJS application and binds it to the given port and host.
|
|
249
|
+
*
|
|
250
|
+
* @summary
|
|
251
|
+
* Listens on the specified port and optionally a host. Once started,
|
|
252
|
+
* logs the application URL for easy access. The startup process resolves
|
|
253
|
+
* once the application is successfully running.
|
|
254
|
+
*
|
|
255
|
+
* @param {number} [port=3000] - Port number to listen on.
|
|
256
|
+
* @param {string} [host] - Optional host or IP address to bind to.
|
|
257
|
+
* @param {boolean} [log=true] - Whether to log the application URL upon startup.
|
|
258
|
+
* @return {Promise<void>} Resolves once the application starts successfully.
|
|
259
|
+
*/
|
|
260
|
+
static async start(port = Number(process.env.PORT) || 3000, host = undefined, log = true) {
|
|
261
|
+
this.app.listen(port, host).then(async () => {
|
|
262
|
+
if (log) {
|
|
263
|
+
const url = await this.app.getUrl();
|
|
264
|
+
this.logger.log(`🚀 Application is running at: ${url}`);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTmVzdEJvb3RzdHJhcGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2ZhY3RvcnkvTmVzdEJvb3RzdHJhcGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFHTCxNQUFNLEdBR1AsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQ0wsNEJBQTRCLEVBQzVCLHVCQUF1QixFQUN2QixxQkFBcUIsRUFDckIsbUJBQW1CLEVBQ25CLHVCQUF1QixFQUN2Qix5QkFBeUIsR0FDMUIsOEJBQXFCO0FBQ3RCLE9BQU8sRUFBRSxjQUFjLEVBQUUsMkJBQWtCO0FBRTNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsMEJBQWlCO0FBaUNyQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0ErQ0c7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUkxQjs7Ozs7Ozs7O09BU0c7SUFDSyxNQUFNLEtBQUssTUFBTTtRQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLFdBQVc7WUFDWCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSCxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQXFCO1FBQ3JDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBQ2YsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7O09BV0c7SUFDSCxNQUFNLENBQUMsWUFBWSxDQUFDLFlBQXFCO1FBQ3ZDLElBQUksQ0FBQyxPQUFPLEdBQUcsWUFBWSxJQUFJLElBQUksTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxP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LElBQUksRUFBRSxJQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDakQsSUFBSSxHQUFHLEVBQUUsQ0FBQztnQkFDUixNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3BDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLGlDQUFpQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQzFELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEV4Y2VwdGlvbkZpbHRlcixcbiAgSU5lc3RBcHBsaWNhdGlvbixcbiAgTG9nZ2VyLFxuICBOZXN0SW50ZXJjZXB0b3IsXG4gIFBpcGVUcmFuc2Zvcm0sXG59IGZyb20gXCJAbmVzdGpzL2NvbW1vblwiO1xuaW1wb3J0IHtcbiAgQXV0aG9yaXphdGlvbkV4Y2VwdGlvbkZpbHRlcixcbiAgQ29uZmxpY3RFeGNlcHRpb25GaWx0ZXIsXG4gIEdsb2JhbEV4Y2VwdGlvbkZpbHRlcixcbiAgSHR0cEV4Y2VwdGlvbkZpbHRlcixcbiAgTm90Rm91bmRFeGNlcHRpb25GaWx0ZXIsXG4gIFZhbGlkYXRpb25FeGNlcHRpb25GaWx0ZXIsXG59IGZyb20gXCIuL2V4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IFN3YWdnZXJCdWlsZGVyIH0gZnJvbSBcIi4vb3BlbmFwaVwiO1xuaW1wb3J0IHsgQ29yc09wdGlvbnMgfSBmcm9tIFwiQG5lc3Rqcy9jb21tb24vaW50ZXJmYWNlcy9leHRlcm5hbC9jb3JzLW9wdGlvbnMuaW50ZXJmYWNlXCI7XG5pbXBvcnQgeyBDb3JzRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqIERlZmluZXMgYWxsIGN1c3RvbWl6YWJsZSBwYXJhbWV0ZXJzIGZvciBTd2FnZ2VyIHNldHVwLlxuICpcbiAqIEBzdW1tYXJ5XG4gKiBUaGlzIGludGVyZmFjZSBhbGxvd3MgZGV2ZWxvcGVycyB0byBjdXN0b21pemUgaG93IFN3YWdnZXIgVUkgaXMgY29uZmlndXJlZFxuICogd2l0aGluIHRoZSBOZXN0SlMgYXBwbGljYXRpb24uIEl0IGluY2x1ZGVzIHBhcmFtZXRlcnMgZm9yIHRpdGxlcywgcGF0aHMsXG4gKiBjb2xvciBzY2hlbWVzLCBhbmQgYXNzZXQgcGF0aHMgdG8gdGFpbG9yIHRoZSBBUEkgZG9jdW1lbnRhdGlvbiBleHBlcmllbmNlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZSAtIFRpdGxlIGRpc3BsYXllZCBpbiBTd2FnZ2VyIFVJLlxuICogQHBhcmFtIHtzdHJpbmd9IGRlc2NyaXB0aW9uIC0gRGVzY3JpcHRpb24gc2hvd24gYmVsb3cgdGhlIHRpdGxlLlxuICogQHBhcmFtIHtzdHJpbmd9IHZlcnNpb24gLSBBUEkgdmVyc2lvbiBkaXNwbGF5ZWQgaW4gdGhlIGRvY3VtZW50YXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gW3BhdGhdIC0gT3B0aW9uYWwgcGF0aCB3aGVyZSBTd2FnZ2VyIHdpbGwgYmUgYXZhaWxhYmxlLlxuICogQHBhcmFtIHtib29sZWFufSBbcGVyc2lzdEF1dGhvcml6YXRpb25dIC0gV2hldGhlciBhdXRob3JpemF0aW9uIHRva2VucyBwZXJzaXN0IGFjcm9zcyByZWxvYWRzLlxuICogQHBhcmFtIHtzdHJpbmd9IFthc3NldHNQYXRoXSAtIFBhdGggdG8gY3VzdG9tIGFzc2V0cyBmb3IgU3dhZ2dlciBVSS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbdG9wYmFyQmdDb2xvcl0gLSBDdXN0b20gYmFja2dyb3VuZCBjb2xvciBmb3IgdGhlIFN3YWdnZXIgdG9wIGJhci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbdG9wYmFySWNvblBhdGhdIC0gUGF0aCB0byBhIGN1c3RvbSBpY29uIGRpc3BsYXllZCBpbiB0aGUgdG9wIGJhci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbZmF2aWNvblBhdGhdIC0gUGF0aCB0byBhIGN1c3RvbSBmYXZpY29uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN3YWdnZXJTZXR1cE9wdGlvbnMge1xuICB0aXRsZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICB2ZXJzaW9uOiBzdHJpbmc7XG4gIHBhdGg/OiBzdHJpbmc7XG4gIHBlcnNpc3RBdXRob3JpemF0aW9uPzogYm9vbGVhbjtcbiAgYXNzZXRzUGF0aD86IHN0cmluZztcbiAgdG9wYmFyQmdDb2xvcj86IHN0cmluZztcbiAgdG9wYmFySWNvblBhdGg/OiBzdHJpbmc7XG4gIGZhdmljb25QYXRoPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvblxuICogQSBmbHVlbnQsIHN0YXRpYyBib290c3RyYXAgY2xhc3MgZm9yIGluaXRpYWxpemluZyBhbmQgY29uZmlndXJpbmcgYSBOZXN0SlMgYXBwbGljYXRpb24uXG4gKlxuICogQHN1bW1hcnlcbiAqIFRoZSBgTmVzdEJvb3RzdHJhcGVyYCBjbGFzcyBwcm92aWRlcyBhIGNoYWluYWJsZSBBUEkgZm9yIGNvbmZpZ3VyaW5nXG4gKiBhIE5lc3RKUyBhcHBsaWNhdGlvbiBpbnN0YW5jZS4gSXQgaW5jbHVkZXMgYnVpbHQtaW4gbWV0aG9kcyBmb3IgZW5hYmxpbmdcbiAqIENPUlMsIEhlbG1ldCBzZWN1cml0eSwgU3dhZ2dlciBkb2N1bWVudGF0aW9uLCBnbG9iYWwgcGlwZXMsIGZpbHRlcnMsXG4gKiBpbnRlcmNlcHRvcnMsIGFuZCBzdGFydGluZyB0aGUgc2VydmVyLlxuICpcbiAqIFRoaXMgY2xhc3MgcHJvbW90ZXMgY29uc2lzdGVuY3kgYW5kIHJlZHVjZXMgcmVwZXRpdGl2ZSBzZXR1cCBjb2RlXG4gKiBhY3Jvc3MgbXVsdGlwbGUgTmVzdEpTIHByb2plY3RzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogaW1wb3J0IHsgTmVzdEZhY3RvcnkgfSBmcm9tIFwiQG5lc3Rqcy9jb3JlXCI7XG4gKiBpbXBvcnQgeyBBcHBNb2R1bGUgfSBmcm9tIFwiLi9hcHAubW9kdWxlXCI7XG4gKiBpbXBvcnQgeyBNeUxvZ2dlciB9IGZyb20gXCIuL015TG9nZ2VyXCI7XG4gKiBpbXBvcnQgeyBOZXN0Qm9vdHN0cmFwZXIgfSBmcm9tIFwiQGRlY2FmLXRzL2Zvci1uZXN0XCI7XG4gKlxuICogYXN5bmMgZnVuY3Rpb24gYm9vdHN0cmFwKCkge1xuICogICBjb25zdCBhcHAgPSBhd2FpdCBOZXN0RmFjdG9yeS5jcmVhdGUoQXBwTW9kdWxlKTtcbiAqXG4gKiAgIGF3YWl0IE5lc3RCb290c3RyYXBlclxuICogICAgIC5pbml0aWFsaXplKGFwcClcbiAqICAgICAuZW5hYmxlTG9nZ2VyKG5ldyBNeUxvZ2dlcigpKVxuICogICAgIC5lbmFibGVDb3JzKFtcImh0dHA6Ly9sb2NhbGhvc3Q6NDIwMFwiXSlcbiAqICAgICAudXNlSGVsbWV0KClcbiAqICAgICAuc2V0dXBTd2FnZ2VyKHtcbiAqICAgICAgIHRpdGxlOiBcIk9wZW5BUEkgYnkgVHJhZGVNYXJr4oSiXCIsXG4gKiAgICAgICBkZXNjcmlwdGlvbjogXCJUcmFkZU1hcmvihKIgQVBJIGRvY3VtZW50YXRpb25cIixcbiAqICAgICAgIHZlcnNpb246IFwiMS4wLjBcIixcbiAqICAgICAgIHBhdGg6IFwiYXBpXCIsXG4gKiAgICAgICBwZXJzaXN0QXV0aG9yaXphdGlvbjogdHJ1ZSxcbiAqICAgICAgIHRvcGJhckJnQ29sb3I6IFwiIzJDM0U1MFwiLFxuICogICAgICAgdG9wYmFySWNvblBhdGg6IFwiL2Fzc2V0cy9sb2dvLnN2Z1wiLFxuICogICAgICAgZmF2aWNvblBhdGg6IFwiL2Fzc2V0cy9mYXZpY29uLmljb1wiXG4gKiAgICAgfSlcbiAqICAgICAudXNlR2xvYmFsRmlsdGVycygpXG4gKiAgICAgLnVzZUdsb2JhbFBpcGVzKC4uLilcbiAqICAgICAudXNlR2xvYmFsSW50ZXJjZXB0b3JzKC4uLilcbiAqICAgICAuc3RhcnQoMzAwMCk7XG4gKiB9XG4gKlxuICogYm9vdHN0cmFwKCk7XG4gKiBgYGBcbiAqIEBjbGFzc1xuICovXG5leHBvcnQgY2xhc3MgTmVzdEJvb3RzdHJhcGVyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgYXBwOiBJTmVzdEFwcGxpY2F0aW9uO1xuICBwcml2YXRlIHN0YXRpYyBfbG9nZ2VyOiBMb2dnZXI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IGxvZ2dlciBpbnN0YW5jZSwgY3JlYXRpbmcgYSBkZWZhdWx0IG9uZSBpZiBub3Qgc2V0LlxuICAgKlxuICAgKiBAc3VtbWFyeVxuICAgKiBFbnN1cmVzIHRoYXQgYSB2YWxpZCBgTG9nZ2VyYCBpbnN0YW5jZSBpcyBhbHdheXMgYXZhaWxhYmxlXG4gICAqIGZvciBsb2dnaW5nIGJvb3RzdHJhcC1yZWxhdGVkIG1lc3NhZ2VzLlxuICAgKlxuICAgKiBAcmV0dXJuIHtMb2dnZXJ9IFRoZSBhY3RpdmUgbG9nZ2VyIGluc3RhbmNlLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0IGxvZ2dlcigpOiBMb2dnZXIge1xuICAgIGlmICghdGhpcy5fbG9nZ2VyKSB7XG4gICAgICAvLyBmYWxsYmFja1xuICAgICAgdGhpcy5fbG9nZ2VyID0gbmV3IExvZ2dlcihcIk5lc3RCb290c3RyYXBcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9sb2dnZXI7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIEluaXRpYWxpemVzIHRoZSBib290c3RyYXBwZXIgd2l0aCBhIGdpdmVuIE5lc3RKUyBhcHBsaWNhdGlvbi5cbiAgICpcbiAgICogQHN1bW1hcnlcbiAgICogQmluZHMgdGhlIHByb3ZpZGVkIE5lc3RKUyBhcHAgaW5zdGFuY2UgdG8gdGhlIGJvb3RzdHJhcHBlciwgZW5hYmxpbmdcbiAgICogY2hhaW5lZCBjb25maWd1cmF0aW9uIG1ldGhvZHMuXG4gICAqXG4gICAqIEBwYXJhbSB7SU5lc3RBcHBsaWNhdGlvbn0gYXBwIC0gVGhlIE5lc3RKUyBhcHBsaWNhdGlvbiBpbnN0YW5jZSB0byBpbml0aWFsaXplLlxuICAgKiBAcmV0dXJuIHt0eXBlb2YgTmVzdEJvb3RzdHJhcGVyfSBSZXR1cm5zIHRoZSBjbGFzcyBmb3IgY2hhaW5pbmcgY29uZmlndXJhdGlvbiBtZXRob2RzLlxuICAgKi9cbiAgc3RhdGljIGluaXRpYWxpemUoYXBwOiBJTmVzdEFwcGxpY2F0aW9uKSB7XG4gICAgdGhpcy5hcHAgPSBhcHA7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIEVuYWJsZXMgb3IgcmVwbGFjZXMgdGhlIGdsb2JhbCBsb2dnZXIgZm9yIHRoZSBOZXN0SlMgYXBwbGljYXRpb24uXG4gICAqXG4gICAqIEBzdW1tYXJ5XG4gICAqIElmIGEgY3VzdG9tIGxvZ2dlciBpcyBwcm92aWRlZCwgaXQgcmVwbGFjZXMgdGhlIGRlZmF1bHQgbG9nZ2VyLiBPdGhlcndpc2UsXG4gICAqIGEgbmV3IGxvZ2dlciBuYW1lZCBgXCJOZXN0Qm9vdHN0cmFwXCJgIGlzIHVzZWQuIFRoaXMgbG9nZ2VyIGlzIGFsc28gcmVnaXN0ZXJlZFxuICAgKiB3aXRoIHRoZSBOZXN0SlMgYXBwbGljYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7TG9nZ2VyfSBbY3VzdG9tTG9nZ2VyXSAtIE9wdGlvbmFsIGN1c3RvbSBsb2dnZXIgaW5zdGFuY2UuXG4gICAqIEByZXR1cm4ge3R5cGVvZiBOZXN0Qm9vdHN0cmFwZXJ9IFJldHVybnMgdGhlIGNsYXNzIGZvciBjaGFpbmluZy5cbiAgICovXG4gIHN0YXRpYyBlbmFibGVMb2dnZXIoY3VzdG9tTG9nZ2VyPzogTG9nZ2VyKSB7XG4gICAgdGhpcy5fbG9nZ2VyID0gY3VzdG9tTG9nZ2VyIHx8IG5ldyBMb2dnZXIoXCJOZXN0Qm9vdHN0cmFwXCIpO1xuICAgIHRoaXMuYXBwLnVzZUxvZ2dlcih0aGlzLl9sb2dnZXIpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBFbmFibGVzIENyb3NzLU9yaWdpbiBSZXNvdXJjZSBTaGFyaW5nIChDT1JTKSBmb3IgdGhlIGFwcGxpY2F0aW9uLlxuICAgKlxuICAgKiBAc3VtbWFyeVxuICAgKiBBbGxvd3MgZGVmaW5pbmcgZWl0aGVyIGEgd2lsZGNhcmQgb3JpZ2luIChgXCIqXCJgKSBvciBhIGxpc3Qgb2YgYWxsb3dlZCBvcmlnaW5zLlxuICAgKiBBdXRvbWF0aWNhbGx5IGFjY2VwdHMgbG9jYWwgZGV2ZWxvcG1lbnQgcmVxdWVzdHMgYW5kIHRob3NlIHdpdGhvdXQgb3JpZ2luIGhlYWRlcnMuXG4gICAqIFRocm93cyBhIGBDb3JzRXJyb3JgIGZvciB1bmF1dGhvcml6ZWQgb3JpZ2lucy5cbiAgICpcbiAgICogQHBhcmFtIHsnKicgfCBzdHJpbmdbXX0gW29yaWdpbnM9W11dIC0gTGlzdCBvZiBhbGxvd2VkIG9yaWdpbnMgb3IgYFwiKlwiYCB0byBhbGxvdyBhbGwuXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFthbGxvd01ldGhvZHM9WydHRVQnLCAnUE9TVCcsICdQVVQnLCAnREVMRVRFJ11dIC0gQWxsb3dlZCBIVFRQIG1ldGhvZHMuXG4gICAqIEByZXR1cm4ge3R5cGVvZiBOZXN0Qm9vdHN0cmFwZXJ9IFJldHVybnMgdGhlIGNsYXNzIGZvciBjaGFpbmluZyBjb25maWd1cmF0aW9uLlxuICAgKlxuICAgKi9cbiAgc3RhdGljIGVuYWJsZUNvcnMoXG4gICAgb3JpZ2luczogXCIqXCIgfCBzdHJpbmdbXSA9IFtdLFxuICAgIGFsbG93TWV0aG9kczogc3RyaW5nW10gPSBbXCJHRVRcIiwgXCJQT1NUXCIsIFwiUFVUXCIsIFwiREVMRVRFXCJdXG4gICkge1xuICAgIGNvbnN0IGFsbG93ZWRPcmlnaW5zID1cbiAgICAgIG9yaWdpbnMgPT09IFwiKlwiID8gXCIqXCIgOiBvcmlnaW5zLm1hcCgobykgPT4gby50cmltKCkudG9Mb3dlckNhc2UoKSk7XG5cbiAgICBjb25zdCBjb3JzT3B0aW9uczogQ29yc09wdGlvbnMgPSB7XG4gICAgICBvcmlnaW46IChvcmlnaW4sIGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIC8vIEFsbG93IHJlcXVlc3Qgd2l0aG91dCBvcmlnaW4uLi5cbiAgICAgICAgaWYgKCFvcmlnaW4pIHJldHVybiBjYWxsYmFjayhudWxsLCB0cnVlKTtcblxuICAgICAgICBpZiAoXG4gICAgICAgICAgYWxsb3dlZE9yaWdpbnMgPT09IFwiKlwiIHx8XG4gICAgICAgICAgKEFycmF5LmlzQXJyYXkoYWxsb3dlZE9yaWdpbnMpICYmXG4gICAgICAgICAgICBhbGxvd2VkT3JpZ2lucy5pbmNsdWRlcyhvcmlnaW4udG9Mb3dlckNhc2UoKSkpXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrKG5ldyBDb3JzRXJyb3IoYE9yaWdpbiAke29yaWdpbn0gbm90IGFsbG93ZWRgKSk7XG4gICAgICB9LFxuICAgICAgY3JlZGVudGlhbHM6IHRydWUsXG4gICAgICBtZXRob2RzOiBhbGxvd01ldGhvZHMuam9pbihcIixcIiksXG4gICAgfTtcblxuICAgIHRoaXMuYXBwLmVuYWJsZUNvcnMoY29yc09wdGlvbnMpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBBcHBsaWVzIHRoZSBIZWxtZXQgbWlkZGxld2FyZSBmb3IgZW5oYW5jZWQgc2VjdXJpdHkuXG4gICAqXG4gICAqIEBzdW1tYXJ5XG4gICAqIER5bmFtaWNhbGx5IGxvYWRzIHRoZSBgaGVsbWV0YCBwYWNrYWdlIGlmIGF2YWlsYWJsZSBhbmQgcmVnaXN0ZXJzIGl0XG4gICAqIGFzIG1pZGRsZXdhcmUgdG8gaW1wcm92ZSBIVFRQIGhlYWRlciBzZWN1cml0eS4gSWYgbm90IGluc3RhbGxlZCwgbG9ncyBhIHdhcm5pbmdcbiAgICogYW5kIGNvbnRpbnVlcyBleGVjdXRpb24gd2l0aG91dCB0aHJvd2luZyBlcnJvcnMuXG4gICAqXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW29wdGlvbnNdIC0gT3B0aW9uYWwgY29uZmlndXJhdGlvbiBwYXNzZWQgdG8gSGVsbWV0LlxuICAgKiBAcmV0dXJuIHt0eXBlb2YgTmVzdEJvb3RzdHJhcGVyfSBSZXR1cm5zIHRoZSBjbGFzcyBmb3IgY2hhaW5pbmcgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHN0YXRpYyB1c2VIZWxtZXQob3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pIHtcbiAgICB0cnkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICAgIGNvbnN0IGhlbG1ldCA9IHJlcXVpcmUoXCJoZWxtZXRcIik7IC8vIER5bmFtaWMgaW1wb3J0IHRvIGF2b2lkIGhhcmQgZGVwZW5kZW5jeVxuICAgICAgdGhpcy5hcHAudXNlKGhlbG1ldChvcHRpb25zKSk7XG4gICAgICB0aGlzLmxvZ2dlci5sb2coXCJIZWxtZXQgbWlkZGxld2FyZSBlbmFibGVkIHN1Y2Nlc3NmdWxseS5cIik7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKFwiSGVsbWV0IG5vdCBpbnN0YWxsZWQuIFNraXBwaW5nIG1pZGRsZXdhcmUuXCIpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBDb25maWd1cmVzIGFuZCBpbml0aWFsaXplcyBTd2FnZ2VyIFVJIGZvciBBUEkgZG9jdW1lbnRhdGlvbi5cbiAgICpcbiAgICogQHN1bW1hcnlcbiAgICogVXNlcyB0aGUgYFN3YWdnZXJCdWlsZGVyYCB1dGlsaXR5IHRvIGNvbmZpZ3VyZSBBUEkgZG9jdW1lbnRhdGlvblxuICAgKiB3aXRoIGRldGFpbGVkIGN1c3RvbWl6YXRpb24gZm9yIHRpdGxlLCB2ZXJzaW9uLCBwYXRocywgYW5kIGNvbG9ycy5cbiAgICogU3dhZ2dlciBpcyBhdXRvbWF0aWNhbGx5IGV4cG9zZWQgYXQgdGhlIGNvbmZpZ3VyZWQgcGF0aC5cbiAgICpcbiAgICogQHBhcmFtIHtTd2FnZ2VyU2V0dXBPcHRpb25zfSBvcHRpb25zIC0gU3dhZ2dlciBjb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gICAqIEByZXR1cm4ge3R5cGVvZiBOZXN0Qm9vdHN0cmFwZXJ9IFJldHVybnMgdGhlIGNsYXNzIGZvciBjaGFpbmluZyBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgc3RhdGljIHNldHVwU3dhZ2dlcihvcHRpb25zOiBTd2FnZ2VyU2V0dXBPcHRpb25zKSB7XG4gICAgY29uc3Qgc3dhZ2dlciA9IG5ldyBTd2FnZ2VyQnVpbGRlcih0aGlzLmFwcCwge1xuICAgICAgdGl0bGU6IG9wdGlvbnMudGl0bGUsXG4gICAgICBkZXNjcmlwdGlvbjogb3B0aW9ucy5kZXNjcmlwdGlvbixcbiAgICAgIHZlcnNpb246IG9wdGlvbnMudmVyc2lvbixcbiAgICAgIHBhdGg6IG9wdGlvbnMucGF0aCB8fCBcImFwaVwiLFxuICAgICAgcGVyc2lzdEF1dGhvcml6YXRpb246IG9wdGlvbnMucGVyc2lzdEF1dGhvcml6YXRpb24gPz8gdHJ1ZSxcbiAgICAgIGFzc2V0c1BhdGg6IG9wdGlvbnMuYXNzZXRzUGF0aCxcbiAgICAgIGZhdmljb25GaWxlUGF0aDogb3B0aW9ucy5mYXZpY29uUGF0aCxcbiAgICAgIHRvcGJhckljb25GaWxlUGF0aDogb3B0aW9ucy50b3BiYXJJY29uUGF0aCxcbiAgICAgIHRvcGJhckJnQ29sb3I6IG9wdGlvbnMudG9wYmFyQmdDb2xvcixcbiAgICB9KTtcbiAgICBzd2FnZ2VyLnNldHVwU3dhZ2dlcigpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBSZWdpc3RlcnMgb25lIG9yIG1vcmUgZ2xvYmFsIHZhbGlkYXRpb24gcGlwZXMuXG4gICAqXG4gICAqIEBzdW1tYXJ5XG4gICAqIEVuYWJsZXMgcmVxdWVzdCBwYXlsb2FkIHZhbGlkYXRpb24gYW5kIHRyYW5zZm9ybWF0aW9uIGdsb2JhbGx5IGFjcm9zc1xuICAgKiB0aGUgZW50aXJlIE5lc3RKUyBhcHBsaWNhdGlvbi4gTXVsdGlwbGUgcGlwZXMgY2FuIGJlIGNoYWluZWQgdG9nZXRoZXJcbiAgICogZm9yIG1vZHVsYXIgaW5wdXQgdmFsaWRhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHsuLi5QaXBlVHJhbnNmb3JtW119IHBpcGVzIC0gUGlwZSBpbnN0YW5jZXMgdG8gcmVnaXN0ZXIgZ2xvYmFsbHkuXG4gICAqIEByZXR1cm4ge3R5cGVvZiBOZXN0Qm9vdHN0cmFwZXJ9IFJldHVybnMgdGhlIGNsYXNzIGZvciBjaGFpbmluZy5cbiAgICovXG4gIHN0YXRpYyB1c2VHbG9iYWxQaXBlcyguLi5waXBlczogUGlwZVRyYW5zZm9ybVtdKSB7XG4gICAgaWYgKHBpcGVzLmxlbmd0aCA+IDApIHRoaXMuYXBwLnVzZUdsb2JhbFBpcGVzKC4uLnBpcGVzKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogUmVnaXN0ZXJzIG9uZSBvciBtb3JlIGdsb2JhbCBleGNlcHRpb24gZmlsdGVycy5cbiAgICpcbiAgICogQHN1bW1hcnlcbiAgICogSWYgbm8gZmlsdGVycyBhcmUgcHJvdmlkZWQsIGl0IGF1dG9tYXRpY2FsbHkgcmVnaXN0ZXJzIGEgZGVmYXVsdFxuICAgKiBzZXQgb2Ygc3RhbmRhcmQgZXhjZXB0aW9uIGZpbHRlcnMgZm9yIGNvbW1vbiBlcnJvciB0eXBlcyBsaWtlXG4gICAqIGBIdHRwRXhjZXB0aW9uYCwgYFZhbGlkYXRpb25FeGNlcHRpb25gLCBgQ29uZmxpY3RFeGNlcHRpb25gLCBhbmQgb3RoZXJzLlxuICAgKlxuICAgKiBAcGFyYW0gey4uLkV4Y2VwdGlvbkZpbHRlcltdfSBmaWx0ZXJzIC0gT3B0aW9uYWwgZmlsdGVycyB0byBhcHBseSBnbG9iYWxseS5cbiAgICogQHJldHVybiB7dHlwZW9mIE5lc3RCb290c3RyYXBlcn0gUmV0dXJucyB0aGUgY2xhc3MgZm9yIGNoYWluaW5nIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBzdGF0aWMgdXNlR2xvYmFsRmlsdGVycyguLi5maWx0ZXJzOiBhbnlbXSkge1xuICAgIGNvbnN0IGRlZmF1bHRGaWx0ZXJzID0gW1xuICAgICAgbmV3IEh0dHBFeGNlcHRpb25GaWx0ZXIoKSxcbiAgICAgIG5ldyBWYWxpZGF0aW9uRXhjZXB0aW9uRmlsdGVyKCksXG4gICAgICBuZXcgTm90Rm91bmRFeGNlcHRpb25GaWx0ZXIoKSxcbiAgICAgIG5ldyBDb25mbGljdEV4Y2VwdGlvbkZpbHRlcigpLFxuICAgICAgbmV3IEF1dGhvcml6YXRpb25FeGNlcHRpb25GaWx0ZXIoKSxcbiAgICAgIG5ldyBHbG9iYWxFeGNlcHRpb25GaWx0ZXIoKSxcbiAgICBdO1xuXG4gICAgdGhpcy5hcHAudXNlR2xvYmFsRmlsdGVycyhcbiAgICAgIC4uLihmaWx0ZXJzLmxlbmd0aCA+IDAgPyBmaWx0ZXJzIDogZGVmYXVsdEZpbHRlcnMpXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogUmVnaXN0ZXJzIGdsb2JhbCBpbnRlcmNlcHRvcnMgZm9yIHJlcXVlc3QgYW5kIHJlc3BvbnNlIHRyYW5zZm9ybWF0aW9uLlxuICAgKlxuICAgKiBAc3VtbWFyeVxuICAgKiBJbnRlcmNlcHRvcnMgYWxsb3cgYWR2YW5jZWQgcmVxdWVzdC9yZXNwb25zZSBtYW5pcHVsYXRpb24gc3VjaCBhc1xuICAgKiBzZXJpYWxpemF0aW9uLCBsb2dnaW5nLCBvciB0cmFuc2Zvcm1hdGlvbi4gTXVsdGlwbGUgaW50ZXJjZXB0b3JzXG4gICAqIGNhbiBiZSBhZGRlZCBmb3IgbW9kdWxhciBjb25maWd1cmF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gey4uLk5lc3RJbnRlcmNlcHRvcltdfSBpbnRlcmNlcHRvcnMgLSBJbnRlcmNlcHRvciBpbnN0YW5jZXMgdG8gcmVnaXN0ZXIuXG4gICAqIEByZXR1cm4ge3R5cGVvZiBOZXN0Qm9vdHN0cmFwZXJ9IFJldHVybnMgdGhlIGNsYXNzIGZvciBjaGFpbmluZyBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgc3RhdGljIHVzZUdsb2JhbEludGVyY2VwdG9ycyguLi5pbnRlcmNlcHRvcnM6IE5lc3RJbnRlcmNlcHRvcltdKSB7XG4gICAgaWYgKGludGVyY2VwdG9ycy5sZW5ndGggPiAwKVxuICAgICAgdGhpcy5hcHAudXNlR2xvYmFsSW50ZXJjZXB0b3JzKC4uLmludGVyY2VwdG9ycyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFN0YXJ0cyB0aGUgTmVzdEpTIGFwcGxpY2F0aW9uIGFuZCBiaW5kcyBpdCB0byB0aGUgZ2l2ZW4gcG9ydCBhbmQgaG9zdC5cbiAgICpcbiAgICogQHN1bW1hcnlcbiAgICogTGlzdGVucyBvbiB0aGUgc3BlY2lmaWVkIHBvcnQgYW5kIG9wdGlvbmFsbHkgYSBob3N0LiBPbmNlIHN0YXJ0ZWQsXG4gICAqIGxvZ3MgdGhlIGFwcGxpY2F0aW9uIFVSTCBmb3IgZWFzeSBhY2Nlc3MuIFRoZSBzdGFydHVwIHByb2Nlc3MgcmVzb2x2ZXNcbiAgICogb25jZSB0aGUgYXBwbGljYXRpb24gaXMgc3VjY2Vzc2Z1bGx5IHJ1bm5pbmcuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbcG9ydD0zMDAwXSAtIFBvcnQgbnVtYmVyIHRvIGxpc3RlbiBvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtob3N0XSAtIE9wdGlvbmFsIGhvc3Qgb3IgSVAgYWRkcmVzcyB0byBiaW5kIHRvLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtsb2c9dHJ1ZV0gLSBXaGV0aGVyIHRvIGxvZyB0aGUgYXBwbGljYXRpb24gVVJMIHVwb24gc3RhcnR1cC5cbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUmVzb2x2ZXMgb25jZSB0aGUgYXBwbGljYXRpb24gc3RhcnRzIHN1Y2Nlc3NmdWxseS5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBzdGFydChcbiAgICBwb3J0OiBudW1iZXIgPSBOdW1iZXIocHJvY2Vzcy5lbnYuUE9SVCkgfHwgMzAwMCxcbiAgICBob3N0OiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4gICAgbG9nOiBib29sZWFuID0gdHJ1ZVxuICApIHtcbiAgICB0aGlzLmFwcC5saXN0ZW4ocG9ydCwgaG9zdCBhcyBhbnkpLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKGxvZykge1xuICAgICAgICBjb25zdCB1cmwgPSBhd2FpdCB0aGlzLmFwcC5nZXRVcmwoKTtcbiAgICAgICAgdGhpcy5sb2dnZXIubG9nKGDwn5qAIEFwcGxpY2F0aW9uIGlzIHJ1bm5pbmcgYXQ6ICR7dXJsfWApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ForbiddenError } from "@decaf-ts/core";
|
|
2
|
+
export class CorsError extends ForbiddenError {
|
|
3
|
+
constructor(msg) {
|
|
4
|
+
super(msg, CorsError.name);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9mYWN0b3J5L2Vycm9ycy9jb3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBa0IsY0FBYyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFFL0QsTUFBTSxPQUFPLFNBQVUsU0FBUSxjQUFjO0lBQzVDLFlBQVksR0FBbUI7UUFDOUIsS0FBSyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUIsQ0FBQztDQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtDb25uZWN0aW9uRXJyb3IsIEZvcmJpZGRlbkVycm9yfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcblxuZXhwb3J0IGNsYXNzIENvcnNFcnJvciBleHRlbmRzIEZvcmJpZGRlbkVycm9yIHtcblx0Y29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuXHRcdHN1cGVyKG1zZywgQ29yc0Vycm9yLm5hbWUpO1xuXHR9XG59Il19
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./cors";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export * from "./cors.js";
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZmFjdG9yeS9lcnJvcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsMEJBQXVCIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSBcIi4vY29yc1wiO1xuIl19
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ArgumentsHost, ExceptionFilter } from "@nestjs/common";
|
|
2
|
+
export declare class AuthorizationError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly code: string;
|
|
5
|
+
constructor(message?: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class AuthorizationExceptionFilter implements ExceptionFilter {
|
|
8
|
+
catch(exception: AuthorizationError, host: ArgumentsHost): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Catch, HttpStatus } from "@nestjs/common";
|
|
8
|
+
import { HttpResponseError } from "./HttpResponseError.js";
|
|
9
|
+
export class AuthorizationError extends Error {
|
|
10
|
+
constructor(message = "Unauthorized") {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "AuthorizationError";
|
|
13
|
+
this.status = 401;
|
|
14
|
+
this.code = "UNAUTHORIZED";
|
|
15
|
+
Object.setPrototypeOf(this, AuthorizationError.prototype);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
let AuthorizationExceptionFilter = class AuthorizationExceptionFilter {
|
|
19
|
+
catch(exception, host) {
|
|
20
|
+
const ctx = host.switchToHttp();
|
|
21
|
+
const request = ctx.getRequest();
|
|
22
|
+
const response = ctx.getResponse();
|
|
23
|
+
const httpResponseError = new HttpResponseError(request, {
|
|
24
|
+
error: "UNAUTHORIZED",
|
|
25
|
+
status: HttpStatus.UNAUTHORIZED,
|
|
26
|
+
message: exception.message,
|
|
27
|
+
});
|
|
28
|
+
response.status(HttpStatus.UNAUTHORIZED).json(httpResponseError);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
AuthorizationExceptionFilter = __decorate([
|
|
32
|
+
Catch(AuthorizationError)
|
|
33
|
+
], AuthorizationExceptionFilter);
|
|
34
|
+
export { AuthorizationExceptionFilter };
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXV0aG9yaXphdGlvbkV4Y2VwdGlvbkZpbHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9mYWN0b3J5L2V4Y2VwdGlvbnMvQXV0aG9yaXphdGlvbkV4Y2VwdGlvbkZpbHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxPQUFPLEVBQWdCLEtBQUssRUFBbUIsVUFBVSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFFakYsT0FBTyxFQUFDLGlCQUFpQixFQUFDLCtCQUE0QjtBQUV0RCxNQUFNLE9BQU8sa0JBQW1CLFNBQVEsS0FBSztJQUl6QyxZQUFZLE9BQU8sR0FBRyxjQUFjO1FBQ2hDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsb0JBQW9CLENBQUM7UUFDakMsSUFBSSxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUM7UUFDbEIsSUFBSSxDQUFDLElBQUksR0FBRyxjQUFjLENBQUM7UUFDM0IsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDOUQsQ0FBQztDQUNKO0FBR00sSUFBTSw0QkFBNEIsR0FBbEMsTUFBTSw0QkFBNEI7SUFDckMsS0FBSyxDQUFDLFNBQTZCLEVBQUUsSUFBbUI7UUFDcEQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ2hDLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxVQUFVLEVBQVcsQ0FBQztRQUMxQyxNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsV0FBVyxFQUFZLENBQUM7UUFFN0MsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLGlCQUFpQixDQUFDLE9BQU8sRUFBRTtZQUNyRCxLQUFLLEVBQUUsY0FBYztZQUNyQixNQUFNLEVBQUUsVUFBVSxDQUFDLFlBQVk7WUFDL0IsT0FBTyxFQUFFLFNBQVMsQ0FBQyxPQUFPO1NBQzdCLENBQUMsQ0FBQztRQUVILFFBQVEsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7Q0FDSixDQUFBO0FBZFksNEJBQTRCO0lBRHhDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztHQUNiLDRCQUE0QixDQWN4QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7QXJndW1lbnRzSG9zdCwgQ2F0Y2gsIEV4Y2VwdGlvbkZpbHRlciwgSHR0cFN0YXR1c30gZnJvbSBcIkBuZXN0anMvY29tbW9uXCI7XG5pbXBvcnQge1JlcXVlc3QsIFJlc3BvbnNlfSBmcm9tIFwiZXhwcmVzc1wiO1xuaW1wb3J0IHtIdHRwUmVzcG9uc2VFcnJvcn0gZnJvbSBcIi4vSHR0cFJlc3BvbnNlRXJyb3JcIjtcblxuZXhwb3J0IGNsYXNzIEF1dGhvcml6YXRpb25FcnJvciBleHRlbmRzIEVycm9yIHtcbiAgICByZWFkb25seSBzdGF0dXM6IG51bWJlcjtcbiAgICByZWFkb25seSBjb2RlOiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlID0gXCJVbmF1dGhvcml6ZWRcIikge1xuICAgICAgICBzdXBlcihtZXNzYWdlKTtcbiAgICAgICAgdGhpcy5uYW1lID0gXCJBdXRob3JpemF0aW9uRXJyb3JcIjtcbiAgICAgICAgdGhpcy5zdGF0dXMgPSA0MDE7XG4gICAgICAgIHRoaXMuY29kZSA9IFwiVU5BVVRIT1JJWkVEXCI7XG4gICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBBdXRob3JpemF0aW9uRXJyb3IucHJvdG90eXBlKTtcbiAgICB9XG59XG5cbkBDYXRjaChBdXRob3JpemF0aW9uRXJyb3IpXG5leHBvcnQgY2xhc3MgQXV0aG9yaXphdGlvbkV4Y2VwdGlvbkZpbHRlciBpbXBsZW1lbnRzIEV4Y2VwdGlvbkZpbHRlciB7XG4gICAgY2F0Y2goZXhjZXB0aW9uOiBBdXRob3JpemF0aW9uRXJyb3IsIGhvc3Q6IEFyZ3VtZW50c0hvc3QpIHtcbiAgICAgICAgY29uc3QgY3R4ID0gaG9zdC5zd2l0Y2hUb0h0dHAoKTtcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IGN0eC5nZXRSZXF1ZXN0PFJlcXVlc3Q+KCk7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gY3R4LmdldFJlc3BvbnNlPFJlc3BvbnNlPigpO1xuXG4gICAgICAgIGNvbnN0IGh0dHBSZXNwb25zZUVycm9yID0gbmV3IEh0dHBSZXNwb25zZUVycm9yKHJlcXVlc3QsIHtcbiAgICAgICAgICAgIGVycm9yOiBcIlVOQVVUSE9SSVpFRFwiLFxuICAgICAgICAgICAgc3RhdHVzOiBIdHRwU3RhdHVzLlVOQVVUSE9SSVpFRCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGV4Y2VwdGlvbi5tZXNzYWdlLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXNwb25zZS5zdGF0dXMoSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQpLmpzb24oaHR0cFJlc3BvbnNlRXJyb3IpO1xuICAgIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ArgumentsHost, ExceptionFilter } from "@nestjs/common";
|
|
2
|
+
export declare class ConflictError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly code: string;
|
|
5
|
+
constructor(message?: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class ConflictExceptionFilter implements ExceptionFilter {
|
|
8
|
+
catch(exception: ConflictError, host: ArgumentsHost): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Catch, HttpStatus } from "@nestjs/common";
|
|
8
|
+
import { HttpResponseError } from "./HttpResponseError.js";
|
|
9
|
+
export class ConflictError extends Error {
|
|
10
|
+
constructor(message = "Conflict") {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "ConflictError";
|
|
13
|
+
this.status = 409;
|
|
14
|
+
this.code = "CONFLICT";
|
|
15
|
+
Object.setPrototypeOf(this, ConflictError.prototype);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
let ConflictExceptionFilter = class ConflictExceptionFilter {
|
|
19
|
+
catch(exception, host) {
|
|
20
|
+
const ctx = host.switchToHttp();
|
|
21
|
+
const response = ctx.getResponse();
|
|
22
|
+
const request = ctx.getRequest();
|
|
23
|
+
const httpResponseError = new HttpResponseError(request, {
|
|
24
|
+
status: HttpStatus.CONFLICT,
|
|
25
|
+
message: exception.message,
|
|
26
|
+
error: "CONFLICT"
|
|
27
|
+
});
|
|
28
|
+
response.status(httpResponseError.status).json(httpResponseError);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
ConflictExceptionFilter = __decorate([
|
|
32
|
+
Catch(ConflictError)
|
|
33
|
+
], ConflictExceptionFilter);
|
|
34
|
+
export { ConflictExceptionFilter };
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29uZmxpY3RFeGNlcHRpb25GaWx0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZmFjdG9yeS9leGNlcHRpb25zL0NvbmZsaWN0RXhjZXB0aW9uRmlsdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLE9BQU8sRUFBZ0IsS0FBSyxFQUFtQixVQUFVLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsK0JBQTRCO0FBRXRELE1BQU0sT0FBTyxhQUFjLFNBQVEsS0FBSztJQUlwQyxZQUFZLE9BQU8sR0FBRyxVQUFVO1FBQzVCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsZUFBZSxDQUFDO1FBQzVCLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO1FBQ2xCLElBQUksQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDO1FBRXZCLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN6RCxDQUFDO0NBQ0o7QUFHTSxJQUFNLHVCQUF1QixHQUE3QixNQUFNLHVCQUF1QjtJQUNoQyxLQUFLLENBQUMsU0FBd0IsRUFBRSxJQUFtQjtRQUMvQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDaEMsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLFdBQVcsRUFBWSxDQUFDO1FBQzdDLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxVQUFVLEVBQVcsQ0FBQztRQUUxQyxNQUFNLGlCQUFpQixHQUFHLElBQUksaUJBQWlCLENBQUMsT0FBTyxFQUFFO1lBQ3JELE1BQU0sRUFBRSxVQUFVLENBQUMsUUFBUTtZQUMzQixPQUFPLEVBQUUsU0FBUyxDQUFDLE9BQU87WUFDMUIsS0FBSyxFQUFFLFVBQVU7U0FDcEIsQ0FBQyxDQUFDO1FBRUgsUUFBUSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUN0RSxDQUFDO0NBQ0osQ0FBQTtBQWRZLHVCQUF1QjtJQURuQyxLQUFLLENBQUMsYUFBYSxDQUFDO0dBQ1IsdUJBQXVCLENBY25DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtBcmd1bWVudHNIb3N0LCBDYXRjaCwgRXhjZXB0aW9uRmlsdGVyLCBIdHRwU3RhdHVzfSBmcm9tIFwiQG5lc3Rqcy9jb21tb25cIjtcbmltcG9ydCB7UmVxdWVzdCwgUmVzcG9uc2V9IGZyb20gXCJleHByZXNzXCI7XG5pbXBvcnQge0h0dHBSZXNwb25zZUVycm9yfSBmcm9tIFwiLi9IdHRwUmVzcG9uc2VFcnJvclwiO1xuXG5leHBvcnQgY2xhc3MgQ29uZmxpY3RFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgICByZWFkb25seSBzdGF0dXM6IG51bWJlcjtcbiAgICByZWFkb25seSBjb2RlOiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlID0gXCJDb25mbGljdFwiKSB7XG4gICAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgICAgICB0aGlzLm5hbWUgPSBcIkNvbmZsaWN0RXJyb3JcIjtcbiAgICAgICAgdGhpcy5zdGF0dXMgPSA0MDk7XG4gICAgICAgIHRoaXMuY29kZSA9IFwiQ09ORkxJQ1RcIjtcblxuICAgICAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgQ29uZmxpY3RFcnJvci5wcm90b3R5cGUpO1xuICAgIH1cbn1cblxuQENhdGNoKENvbmZsaWN0RXJyb3IpXG5leHBvcnQgY2xhc3MgQ29uZmxpY3RFeGNlcHRpb25GaWx0ZXIgaW1wbGVtZW50cyBFeGNlcHRpb25GaWx0ZXIge1xuICAgIGNhdGNoKGV4Y2VwdGlvbjogQ29uZmxpY3RFcnJvciwgaG9zdDogQXJndW1lbnRzSG9zdCkge1xuICAgICAgICBjb25zdCBjdHggPSBob3N0LnN3aXRjaFRvSHR0cCgpO1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGN0eC5nZXRSZXNwb25zZTxSZXNwb25zZT4oKTtcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IGN0eC5nZXRSZXF1ZXN0PFJlcXVlc3Q+KCk7XG5cbiAgICAgICAgY29uc3QgaHR0cFJlc3BvbnNlRXJyb3IgPSBuZXcgSHR0cFJlc3BvbnNlRXJyb3IocmVxdWVzdCwge1xuICAgICAgICAgICAgc3RhdHVzOiBIdHRwU3RhdHVzLkNPTkZMSUNULFxuICAgICAgICAgICAgbWVzc2FnZTogZXhjZXB0aW9uLm1lc3NhZ2UsXG4gICAgICAgICAgICBlcnJvcjogXCJDT05GTElDVFwiXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJlc3BvbnNlLnN0YXR1cyhodHRwUmVzcG9uc2VFcnJvci5zdGF0dXMpLmpzb24oaHR0cFJlc3BvbnNlRXJyb3IpO1xuICAgIH1cbn1cbiJdfQ==
|