@sharangyawali/sg-app 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.

Potentially problematic release.


This version of @sharangyawali/sg-app might be problematic. Click here for more details.

Files changed (165) hide show
  1. package/cls/cls.service.d.ts +8 -0
  2. package/cls/cls.service.js +33 -0
  3. package/cls/index.d.ts +1 -0
  4. package/cls/index.js +17 -0
  5. package/common/constants/index.d.ts +1 -0
  6. package/common/constants/index.js +17 -0
  7. package/common/constants/providers.constants.d.ts +1 -0
  8. package/common/constants/providers.constants.js +4 -0
  9. package/common/decorators/component.decorators.d.ts +2 -0
  10. package/common/decorators/component.decorators.js +14 -0
  11. package/common/decorators/controller.decorator.d.ts +2 -0
  12. package/common/decorators/controller.decorator.js +18 -0
  13. package/common/decorators/filters.decorator.d.ts +2 -0
  14. package/common/decorators/filters.decorator.js +19 -0
  15. package/common/decorators/guards.decorator.d.ts +4 -0
  16. package/common/decorators/guards.decorator.js +25 -0
  17. package/common/decorators/index.d.ts +10 -0
  18. package/common/decorators/index.js +26 -0
  19. package/common/decorators/inject.decorators.d.ts +3 -0
  20. package/common/decorators/inject.decorators.js +13 -0
  21. package/common/decorators/interceptors.decorator.d.ts +4 -0
  22. package/common/decorators/interceptors.decorator.js +25 -0
  23. package/common/decorators/middlewares.decorator.d.ts +3 -0
  24. package/common/decorators/middlewares.decorator.js +19 -0
  25. package/common/decorators/module.decorator.d.ts +2 -0
  26. package/common/decorators/module.decorator.js +31 -0
  27. package/common/decorators/parameter-validator.decorator.d.ts +5 -0
  28. package/common/decorators/parameter-validator.decorator.js +21 -0
  29. package/common/decorators/route-mapping.decorator.d.ts +5 -0
  30. package/common/decorators/route-mapping.decorator.js +32 -0
  31. package/common/enum/index.d.ts +3 -0
  32. package/common/enum/index.js +19 -0
  33. package/common/enum/request-method.enum.d.ts +11 -0
  34. package/common/enum/request-method.enum.js +15 -0
  35. package/common/enum/request-parameters.enum.d.ts +7 -0
  36. package/common/enum/request-parameters.enum.js +11 -0
  37. package/common/enum/scope.enum.d.ts +5 -0
  38. package/common/enum/scope.enum.js +9 -0
  39. package/common/http/http-context.d.ts +13 -0
  40. package/common/http/http-context.js +27 -0
  41. package/common/http/http-exception.d.ts +7 -0
  42. package/common/http/http-exception.js +17 -0
  43. package/common/http/index.d.ts +2 -0
  44. package/common/http/index.js +18 -0
  45. package/common/index.d.ts +5 -0
  46. package/common/index.js +21 -0
  47. package/common/interface/controller-method-paramenters.interface.d.ts +6 -0
  48. package/common/interface/controller-method-paramenters.interface.js +2 -0
  49. package/common/interface/controller-methods.interface.d.ts +6 -0
  50. package/common/interface/controller-methods.interface.js +2 -0
  51. package/common/interface/cors.interface.d.ts +14 -0
  52. package/common/interface/cors.interface.js +2 -0
  53. package/common/interface/features/index.d.ts +4 -0
  54. package/common/interface/features/index.js +20 -0
  55. package/common/interface/features/sg-filter.interface.d.ts +4 -0
  56. package/common/interface/features/sg-filter.interface.js +2 -0
  57. package/common/interface/features/sg-guard.interface.d.ts +4 -0
  58. package/common/interface/features/sg-guard.interface.js +2 -0
  59. package/common/interface/features/sg-interceptor.interface.d.ts +4 -0
  60. package/common/interface/features/sg-interceptor.interface.js +2 -0
  61. package/common/interface/features/sg-middleware.interface.d.ts +4 -0
  62. package/common/interface/features/sg-middleware.interface.js +2 -0
  63. package/common/interface/global-middleware-options.interface.d.ts +5 -0
  64. package/common/interface/global-middleware-options.interface.js +2 -0
  65. package/common/interface/global-prefix-options.interface.d.ts +4 -0
  66. package/common/interface/global-prefix-options.interface.js +2 -0
  67. package/common/interface/index.d.ts +15 -0
  68. package/common/interface/index.js +31 -0
  69. package/common/interface/injectable-options.interface.d.ts +5 -0
  70. package/common/interface/injectable-options.interface.js +2 -0
  71. package/common/interface/injection-token.interface.d.ts +2 -0
  72. package/common/interface/injection-token.interface.js +2 -0
  73. package/common/interface/module-options.interface.d.ts +6 -0
  74. package/common/interface/module-options.interface.js +2 -0
  75. package/common/interface/provider.interface.d.ts +30 -0
  76. package/common/interface/provider.interface.js +2 -0
  77. package/common/interface/route-info.interface.d.ts +5 -0
  78. package/common/interface/route-info.interface.js +2 -0
  79. package/common/interface/sg-application.interface.d.ts +8 -0
  80. package/common/interface/sg-application.interface.js +2 -0
  81. package/common/interface/sg-factory.interface.d.ts +8 -0
  82. package/common/interface/sg-factory.interface.js +2 -0
  83. package/common/interface/sg-interceptor.interface.d.ts +3 -0
  84. package/common/interface/sg-interceptor.interface.js +2 -0
  85. package/common/interface/static-route.interface.d.ts +20 -0
  86. package/common/interface/static-route.interface.js +2 -0
  87. package/common/interface/type.interface.d.ts +3 -0
  88. package/common/interface/type.interface.js +2 -0
  89. package/config/config-service.d.ts +3 -0
  90. package/config/config-service.js +11 -0
  91. package/config/index.d.ts +1 -0
  92. package/config/index.js +17 -0
  93. package/di-container.d.ts +15 -0
  94. package/di-container.js +103 -0
  95. package/index.d.ts +9 -0
  96. package/index.js +25 -0
  97. package/logger/index.d.ts +1 -0
  98. package/logger/index.js +17 -0
  99. package/logger/logger-service.d.ts +9 -0
  100. package/logger/logger-service.js +44 -0
  101. package/package.json +24 -0
  102. package/routes-config.d.ts +22 -0
  103. package/routes-config.js +204 -0
  104. package/set-meta-data.d.ts +1 -0
  105. package/set-meta-data.js +35 -0
  106. package/sg-application.d.ts +12 -0
  107. package/sg-application.js +37 -0
  108. package/sg-factory.d.ts +6 -0
  109. package/sg-factory.js +22 -0
  110. package/src/cls/cls.service.ts +31 -0
  111. package/src/cls/index.ts +1 -0
  112. package/src/common/constants/index.ts +1 -0
  113. package/src/common/constants/providers.constants.ts +1 -0
  114. package/src/common/decorators/component.decorators.ts +13 -0
  115. package/src/common/decorators/controller.decorator.ts +16 -0
  116. package/src/common/decorators/filters.decorator.ts +17 -0
  117. package/src/common/decorators/guards.decorator.ts +26 -0
  118. package/src/common/decorators/index.ts +10 -0
  119. package/src/common/decorators/inject.decorators.ts +12 -0
  120. package/src/common/decorators/interceptors.decorator.ts +26 -0
  121. package/src/common/decorators/middlewares.decorator.ts +18 -0
  122. package/src/common/decorators/module.decorator.ts +29 -0
  123. package/src/common/decorators/parameter-validator.decorator.ts +17 -0
  124. package/src/common/decorators/route-mapping.decorator.ts +27 -0
  125. package/src/common/enum/index.ts +3 -0
  126. package/src/common/enum/request-method.enum.ts +11 -0
  127. package/src/common/enum/request-parameters.enum.ts +7 -0
  128. package/src/common/enum/scope.enum.ts +5 -0
  129. package/src/common/http/http-context.ts +25 -0
  130. package/src/common/http/http-exception.ts +12 -0
  131. package/src/common/http/index.ts +2 -0
  132. package/src/common/index.ts +5 -0
  133. package/src/common/interface/controller-method-paramenters.interface.ts +7 -0
  134. package/src/common/interface/controller-methods.interface.ts +7 -0
  135. package/src/common/interface/cors.interface.ts +15 -0
  136. package/src/common/interface/features/index.ts +4 -0
  137. package/src/common/interface/features/sg-filter.interface.ts +5 -0
  138. package/src/common/interface/features/sg-guard.interface.ts +5 -0
  139. package/src/common/interface/features/sg-interceptor.interface.ts +5 -0
  140. package/src/common/interface/features/sg-middleware.interface.ts +5 -0
  141. package/src/common/interface/global-middleware-options.interface.ts +7 -0
  142. package/src/common/interface/global-prefix-options.interface.ts +5 -0
  143. package/src/common/interface/index.ts +15 -0
  144. package/src/common/interface/injectable-options.interface.ts +6 -0
  145. package/src/common/interface/injection-token.interface.ts +2 -0
  146. package/src/common/interface/module-options.interface.ts +7 -0
  147. package/src/common/interface/provider.interface.ts +36 -0
  148. package/src/common/interface/route-info.interface.ts +6 -0
  149. package/src/common/interface/sg-application.interface.ts +9 -0
  150. package/src/common/interface/sg-factory.interface.ts +10 -0
  151. package/src/common/interface/sg-interceptor.interface.ts +3 -0
  152. package/src/common/interface/static-route.interface.ts +22 -0
  153. package/src/common/interface/type.interface.ts +3 -0
  154. package/src/config/config-service.ts +7 -0
  155. package/src/config/index.ts +1 -0
  156. package/src/di-container.ts +135 -0
  157. package/src/index.ts +9 -0
  158. package/src/logger/index.ts +1 -0
  159. package/src/logger/logger-service.ts +48 -0
  160. package/src/routes-config.ts +305 -0
  161. package/src/set-meta-data.ts +30 -0
  162. package/src/sg-application.ts +29 -0
  163. package/src/sg-factory.ts +15 -0
  164. package/tsconfig.json +31 -0
  165. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,305 @@
1
+ import { Express, Request, Response, Router } from "express";
2
+ import { AppLogger } from "./logger";
3
+ import {
4
+ ControllerMethodParams,
5
+ ControllerMethods,
6
+ controllers,
7
+ filters,
8
+ globalGuards,
9
+ globalInterceptors,
10
+ GlobalPrefixOptions,
11
+ HttpContext,
12
+ HttpException,
13
+ MiddlewareOptions,
14
+ middlewares,
15
+ REQUEST,
16
+ RequestMethodEnum,
17
+ RequestParameters,
18
+ RouteInfo,
19
+ Scope,
20
+ SGFilter,
21
+ SGGuard,
22
+ SGInterceptor,
23
+ SGMiddleware
24
+ } from "./common";
25
+ import { plainToInstance } from "class-transformer";
26
+ import { validate } from "class-validator";
27
+ import { CLSService } from "./cls";
28
+ import { ConfigService } from "./config";
29
+ import { container } from "./di-container";
30
+
31
+ export class RoutRegister {
32
+ private readonly logger: AppLogger;
33
+ private router: Router;
34
+ private prefix: string;
35
+ private prefixOptions: GlobalPrefixOptions;
36
+ private app: Express;
37
+ constructor() {
38
+ this.logger = new AppLogger();
39
+ }
40
+
41
+ async register(
42
+ app: Express,
43
+ globalPrefix?: string,
44
+ prefixOptions?: GlobalPrefixOptions
45
+ ) {
46
+ this.app = app;
47
+ this.router = app.router;
48
+ this.prefix = globalPrefix;
49
+ this.prefixOptions = prefixOptions;
50
+ this.registerClasses();
51
+ this.registerMiddleWares();
52
+ this.registerControllerCLasses();
53
+ }
54
+ private registerClasses() {
55
+ container.register({
56
+ scope: Scope.SINGLETON,
57
+ token: ConfigService,
58
+ useClass: ConfigService
59
+ });
60
+ container.register({
61
+ scope: Scope.SINGLETON,
62
+ token: AppLogger,
63
+ useClass: AppLogger
64
+ });
65
+ container.register({
66
+ scope: Scope.SINGLETON,
67
+ token: CLSService,
68
+ useClass: CLSService
69
+ });
70
+ }
71
+
72
+ private registerMiddleWares() {
73
+ for (const middleware of middlewares) {
74
+ this.app.use(async (req, res, next) => {
75
+ let path = req.path;
76
+ if (this.prefix) {
77
+ const splits = path.split(`${this.prefix}`);
78
+ if (splits.length > 1) path = splits[1];
79
+ else path = splits[0];
80
+ }
81
+ const options: MiddlewareOptions = middleware.options;
82
+ if (
83
+ options?.exclude &&
84
+ options?.exclude.length > 0 &&
85
+ this.doContains(options?.exclude, path, req.method)
86
+ ) {
87
+ return next();
88
+ }
89
+ if (
90
+ options?.forRoutes &&
91
+ options?.forRoutes.length > 0 &&
92
+ !this.doContains(options?.forRoutes, path, req.method)
93
+ ) {
94
+ return next();
95
+ }
96
+ const middlewareInstance = container.resolve<SGMiddleware>(
97
+ middleware.target
98
+ );
99
+ await middlewareInstance.use(req, res, next);
100
+ });
101
+ }
102
+ }
103
+
104
+ private doContains(
105
+ excludes: RouteInfo[],
106
+ path: string,
107
+ method: string
108
+ ): Boolean {
109
+ return excludes.some(
110
+ (e) =>
111
+ path.startsWith(e.routePrefix) &&
112
+ (e.method === RequestMethodEnum.ALL ||
113
+ e.method === method.toLowerCase())
114
+ );
115
+ }
116
+
117
+ private registerControllerCLasses() {
118
+ for (const ControllerClass of controllers) {
119
+ const prefix = ControllerClass.prototype.prefix;
120
+ for (const method of ControllerClass.prototype
121
+ .methods as ControllerMethods[]) {
122
+ const guards: any[] = [
123
+ ...(ControllerClass.prototype[method.handler].guards || []),
124
+ ...globalGuards
125
+ ];
126
+ const interceptors: any[] = [
127
+ ...(ControllerClass.prototype[method.handler].interceptors || []),
128
+ ...globalInterceptors
129
+ ];
130
+ const parameters: ControllerMethodParams[] =
131
+ ControllerClass.prototype[method.handler].parameters || [];
132
+ this.registerRoute(
133
+ prefix,
134
+ method,
135
+ guards,
136
+ interceptors,
137
+ parameters,
138
+ ControllerClass
139
+ );
140
+ }
141
+ }
142
+ }
143
+
144
+ private registerRoute(
145
+ prefix: string,
146
+ method: ControllerMethods,
147
+ guards: any[],
148
+ interceptors: any[],
149
+ parameters: ControllerMethodParams[],
150
+ controller: any
151
+ ) {
152
+ let path = method.path ? `${prefix}${method.path}` : prefix;
153
+ if (
154
+ this.prefix &&
155
+ (!this.prefixOptions ||
156
+ !this.prefixOptions.exclude ||
157
+ this.prefixOptions.exclude.length <= 0 ||
158
+ !this.doContains(this.prefixOptions.exclude, path, method.method))
159
+ ) {
160
+ path = this.prefix + path;
161
+ }
162
+ const logString = `[ROUTE] MAPPED{${path}, ${method.method.toUpperCase()}}`;
163
+ this.router[method.method](path, async (req: Request, res: Response) => {
164
+ const cls = container.resolve(CLSService);
165
+ cls.run(req, async () => {
166
+ const httpContext = new HttpContext(req, res, method);
167
+ const controllerInstance = container.resolve<any>(
168
+ controller,
169
+ );
170
+ try {
171
+ await this.routeHandler(
172
+ req,
173
+ res,
174
+ guards,
175
+ interceptors,
176
+ httpContext,
177
+ parameters,
178
+ controllerInstance,
179
+ method
180
+ );
181
+ } catch (error) {
182
+ console.log({ error });
183
+ if (error instanceof HttpException) {
184
+ await this.catchExceptions(httpContext, error);
185
+ } else res.status(500).json({ message: "Internal Server Error!!" });
186
+ }
187
+ finally {
188
+ container.removeRequestInstances(cls.get('instanceId'))
189
+ }
190
+ });
191
+ });
192
+ this.logger.log(logString);
193
+ }
194
+
195
+ private async routeHandler(
196
+ req: Request,
197
+ res: Response,
198
+ guards: any[],
199
+ interceptors: any[],
200
+ httpContext: HttpContext,
201
+ parameters: any[],
202
+ controller: any,
203
+ method: ControllerMethods
204
+ ) {
205
+ await this.registerGuards(guards, httpContext);
206
+ const afterResponseInterceptor = await this.handleRequestInterceptors(
207
+ interceptors,
208
+ httpContext
209
+ );
210
+ const validatedParameters = await this.validateParameters(
211
+ parameters,
212
+ req
213
+ );
214
+ let data = await controller[method.handler](...validatedParameters);
215
+ data = await this.handleResponseInterceptors(
216
+ afterResponseInterceptor,
217
+ data
218
+ );
219
+ res.send(data);
220
+ }
221
+ private async registerGuards(
222
+ guards: any[],
223
+ httpContext: HttpContext,
224
+ ) {
225
+ for (const guard of guards) {
226
+ const guardInstance = container.resolve<SGGuard>(guard);
227
+ const canActive = await guardInstance.canAccess(httpContext);
228
+ if (!canActive) throw new HttpException("Forbidden", 403);
229
+ }
230
+ }
231
+
232
+ private async handleRequestInterceptors(
233
+ interceptors: any[],
234
+ httpContext: HttpContext
235
+ ): Promise<((data: any) => any)[]> {
236
+ const afterInterceptors: ((data: any) => any)[] = [];
237
+ for (const interceptor of interceptors) {
238
+ let interceptorInstance;
239
+ if (typeof interceptor == "object") interceptorInstance = interceptor;
240
+ else
241
+ interceptorInstance = container.resolve<SGInterceptor>(interceptor);
242
+ const afterIntercept = await interceptorInstance.intercept(httpContext);
243
+ if (afterIntercept) afterInterceptors.push(afterIntercept);
244
+ }
245
+ return afterInterceptors;
246
+ }
247
+
248
+ private async handleResponseInterceptors(
249
+ interceptors: ((data: any) => any)[],
250
+ data: any
251
+ ): Promise<any> {
252
+ for (const afterInterceptor of interceptors) {
253
+ data = await afterInterceptor(data);
254
+ }
255
+ return data;
256
+ }
257
+
258
+ private async validateParameters(
259
+ parameters: ControllerMethodParams[],
260
+ request: Request
261
+ ): Promise<any[]> {
262
+ const transformedParameters = [];
263
+ parameters.sort((a, b) => a.index - b.index);
264
+ for (const { paramType, dtoClass } of parameters) {
265
+ let paramData;
266
+ if (paramType == RequestParameters.QUERY) {
267
+ paramData = structuredClone(request.query);
268
+ } else if (paramType == RequestParameters.BODY)
269
+ paramData = structuredClone(request.body);
270
+ else if (paramType == RequestParameters.PARAMS)
271
+ paramData = structuredClone(request.params);
272
+ else if (paramType == RequestParameters.FILE)
273
+ paramData = structuredClone(request["file"]);
274
+ else if (paramType == RequestParameters.FILES)
275
+ paramData = structuredClone(request["files"]);
276
+ if (dtoClass) {
277
+ const transformedClass = plainToInstance(
278
+ dtoClass,
279
+ { ...paramData },
280
+ { enableImplicitConversion: true }
281
+ );
282
+ const errors = await validate(transformedClass, {
283
+ whitelist: true
284
+ });
285
+ if (errors.length > 0) {
286
+ throw new HttpException(errors, 400);
287
+ }
288
+ transformedParameters.push(transformedClass);
289
+ } else {
290
+ transformedParameters.push(paramData);
291
+ }
292
+ }
293
+ return transformedParameters;
294
+ }
295
+
296
+ private async catchExceptions(
297
+ httpContext: HttpContext,
298
+ error: HttpException
299
+ ) {
300
+ for (const filter of filters) {
301
+ const filterInstance = container.resolve<SGFilter>(filter);
302
+ await filterInstance.catch(error, httpContext);
303
+ }
304
+ }
305
+ }
@@ -0,0 +1,30 @@
1
+ export const SetMetaData = (key: string, value: any): MethodDecorator => {
2
+ return function (target: any, propertyKey: string | symbol) {
3
+ if (!target.methods) {
4
+ target.methods = [];
5
+ const data = {
6
+ handler: propertyKey
7
+ };
8
+ data[key] = value;
9
+ target.methods.push(data);
10
+ } else {
11
+ const newMethods = [];
12
+ let include = false;
13
+ for (const r of target.methods) {
14
+ if (r.handler == propertyKey) {
15
+ r[key] = value;
16
+ include = true;
17
+ }
18
+ newMethods.push(r);
19
+ }
20
+ if (!include) {
21
+ const data = {
22
+ handler: propertyKey
23
+ };
24
+ data[key] = value;
25
+ newMethods.push(data);
26
+ }
27
+ target.methods = newMethods;
28
+ }
29
+ };
30
+ };
@@ -0,0 +1,29 @@
1
+ import { Express } from "express";
2
+ import { GlobalPrefixOptions, ISGApplication, RoutRegister, StaticRoutes } from ".";
3
+ import express from "express";
4
+
5
+ export class SGApplication implements ISGApplication {
6
+ private prefixOptions: GlobalPrefixOptions;
7
+ private prefix: string;
8
+ constructor(private app: Express) { }
9
+
10
+ use(...args: any[]): this {
11
+ this.app.use(...args);
12
+ return this;
13
+ }
14
+ setStaticRoutes(options: StaticRoutes[]): this {
15
+ options.forEach((o) => {
16
+ o.prefix ? this.app.use(o.prefix, express.static(o.path, { ...(o.options) })) : this.app.use(express.static(o.path, { ...(o.options) }))
17
+ })
18
+ return this
19
+ }
20
+ setGlobalPrefix(prefix: string, options?: GlobalPrefixOptions): this {
21
+ this.prefix = prefix;
22
+ if (options) this.prefixOptions = options;
23
+ return this;
24
+ }
25
+ async listen(port: number, callback?: (error?: Error) => void): Promise<any> {
26
+ new RoutRegister().register(this.app, this.prefix, this.prefixOptions);
27
+ return this.app.listen(port, callback);
28
+ }
29
+ }
@@ -0,0 +1,15 @@
1
+ import express from "express";
2
+ import { FactoryOptions, ISGApplication, ISGFactory, SGApplication } from ".";
3
+ import cors from 'cors';
4
+ export class SGFactory implements ISGFactory {
5
+ private app;
6
+ constructor() { }
7
+ create(_: any, options?: FactoryOptions): ISGApplication {
8
+ this.app = express();
9
+ this.app.use(express.json())
10
+ this.app.use(express.urlencoded({ extended: true }))
11
+ if (options && options.cors)
12
+ typeof options.cors === 'boolean' ? this.app.use(cors()) : this.app.use(cors({ ...options.cors }))
13
+ return new SGApplication(this.app);
14
+ }
15
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2023",
4
+ "module": "commonjs",
5
+ "noEmit": false,
6
+ "allowArbitraryExtensions": true,
7
+ "rootDir": "./src",
8
+ "outDir": "./",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": false,
13
+ "resolveJsonModule": true,
14
+ "strictPropertyInitialization": false,
15
+ "experimentalDecorators": true,
16
+ "emitDecoratorMetadata": true,
17
+ "declaration": true,
18
+ "allowSyntheticDefaultImports": true,
19
+ "baseUrl": "./",
20
+ "paths": {
21
+ "*": ["src/*"]
22
+ },
23
+ "incremental": true,
24
+ "strictNullChecks": false,
25
+ "noImplicitAny": false,
26
+ "strictBindCallApply": false,
27
+ "noFallthroughCasesInSwitch": false
28
+ },
29
+ "include": ["src/**/*.ts"],
30
+ "exclude": ["node_modules", "dist"]
31
+ }