@galeh/chuka 1.1.2 → 1.1.4

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.
Files changed (65) hide show
  1. package/decorators.d.ts +8 -0
  2. package/index.d.ts +270 -0
  3. package/index.js +217 -0
  4. package/middlewares.d.ts +20 -0
  5. package/package.json +40 -49
  6. package/validators.d.ts +60 -0
  7. package/.github/workflows/webpack.yml +0 -34
  8. package/config/api-extractor.decorators.json +0 -427
  9. package/config/api-extractor.index.json +0 -427
  10. package/config/api-extractor.middlewares.json +0 -427
  11. package/config/api-extractor.validators.json +0 -427
  12. package/sample/01-cats-app/package-lock.json +0 -283
  13. package/sample/01-cats-app/package.json +0 -19
  14. package/sample/01-cats-app/src/cats/cat-model.ts +0 -9
  15. package/sample/01-cats-app/src/cats/cats-controller.ts +0 -44
  16. package/sample/01-cats-app/src/cats/cats-service-interface.ts +0 -7
  17. package/sample/01-cats-app/src/cats/cats-service.ts +0 -27
  18. package/sample/01-cats-app/src/cats/create-logger.ts +0 -8
  19. package/sample/01-cats-app/src/main.ts +0 -30
  20. package/sample/01-cats-app/tsconfig.json +0 -112
  21. package/sample/02-socket/package-lock.json +0 -442
  22. package/sample/02-socket/package.json +0 -20
  23. package/sample/02-socket/src/controllers/http-controller.ts +0 -14
  24. package/sample/02-socket/src/controllers/socket-controller.ts +0 -18
  25. package/sample/02-socket/src/main.ts +0 -46
  26. package/sample/02-socket/src/middleware/create-session.ts +0 -9
  27. package/sample/02-socket/tsconfig.json +0 -112
  28. package/sample/03-authentication/db/create.sql +0 -6
  29. package/sample/03-authentication/package-lock.json +0 -1832
  30. package/sample/03-authentication/package.json +0 -23
  31. package/sample/03-authentication/src/config.ts +0 -21
  32. package/sample/03-authentication/src/controllers/auth-controller.ts +0 -54
  33. package/sample/03-authentication/src/enums/injection-tokens.ts +0 -5
  34. package/sample/03-authentication/src/enums/result-codes.ts +0 -4
  35. package/sample/03-authentication/src/exceptions/error.ts +0 -7
  36. package/sample/03-authentication/src/exceptions/password-not-found-exception.ts +0 -9
  37. package/sample/03-authentication/src/exceptions/unauthorized-exception.ts +0 -9
  38. package/sample/03-authentication/src/exceptions/user-already-exist.ts +0 -9
  39. package/sample/03-authentication/src/exceptions/user-not-found.ts +0 -9
  40. package/sample/03-authentication/src/exceptions/wrong-login-info-exception.ts +0 -8
  41. package/sample/03-authentication/src/main.ts +0 -42
  42. package/sample/03-authentication/src/middlewares/auth-handler.ts +0 -17
  43. package/sample/03-authentication/src/middlewares/global-error-handler.ts +0 -21
  44. package/sample/03-authentication/src/models/user-model.ts +0 -6
  45. package/sample/03-authentication/src/services/auth-service.ts +0 -50
  46. package/sample/03-authentication/src/services/interfaces/auth-service-interface.ts +0 -7
  47. package/sample/03-authentication/src/services/interfaces/user-service-interface.ts +0 -7
  48. package/sample/03-authentication/src/services/user-service.ts +0 -75
  49. package/sample/03-authentication/src/types/connection.ts +0 -3
  50. package/sample/03-authentication/src/types/token.ts +0 -3
  51. package/sample/03-authentication/src/utils/crypto.ts +0 -26
  52. package/sample/03-authentication/tsconfig.json +0 -112
  53. package/scripts/build.bash +0 -17
  54. package/scripts/create-package-json.js +0 -15
  55. package/src/app.ts +0 -197
  56. package/src/controller.ts +0 -204
  57. package/src/decorators/index.ts +0 -1
  58. package/src/index.ts +0 -3
  59. package/src/middlewares/index.ts +0 -1
  60. package/src/validators/body-validator.ts +0 -9
  61. package/src/validators/index.ts +0 -2
  62. package/src/validators/query-validator.ts +0 -9
  63. package/src/validators/validators.ts +0 -216
  64. package/tsconfig.json +0 -112
  65. package/webpack.config.js +0 -46
package/src/app.ts DELETED
@@ -1,197 +0,0 @@
1
- import 'reflect-metadata';
2
- import * as express from 'express';
3
- import { Container, interfaces } from "inversify";
4
- import * as inversify from "inversify";
5
- import { Controller, RequestHandlerParams, getRouterSymbol, setControllerSymbol } from './controller';
6
- import * as ws from 'express-ws';
7
-
8
- export function createApp(config: ApplicationConfig): express.Application {
9
- const app = express.default();
10
-
11
- if (config.on) {
12
- setEventCallbacks(app, config.on);
13
- }
14
-
15
- if (config.set) {
16
- applySettings(app, config.set);
17
- }
18
-
19
- ws.default(app);
20
-
21
- if (config.middlewares) {
22
- app.use.apply(app, config.middlewares as any);
23
- }
24
-
25
- const controllerEmulator = new ControllerEmulator(app);
26
- const container = new Container();
27
- initAllDependencies(config, container);
28
- initControllers(config.routes, container, controllerEmulator as any as Controller);
29
-
30
- return app;
31
- }
32
-
33
- function setEventCallbacks(app: express.Application, settings: EventCallback[]): void {
34
- for (const setting of settings) {
35
- app.on(setting.event, setting.callback);
36
- }
37
- }
38
-
39
- function applySettings(app: express.Application, settings: Partial<Settings>): void {
40
- for (const [key, value] of Object.entries(settings)) {
41
- // @ts-ignore
42
- app.set(SettingsEnum[key], value);
43
- }
44
- }
45
-
46
- function initAllDependencies(config: ApplicationConfig, container: Container): void {
47
- if (config.dependencies) {
48
- initDependencies(config.dependencies, container);
49
- }
50
-
51
- initControllersAsDependency(config.routes, container);
52
- }
53
-
54
- function initDependencies(dependencies: Array<Dependency>, container: Container): void {
55
- for (const dep of dependencies) {
56
- if (dep.useValue) {
57
- bindValue(container, dep.provide, dep.useValue);
58
- continue;
59
- }
60
-
61
- if (dep.useClass) {
62
- bindClass(container, dep.provide, dep.useClass);
63
- continue;
64
- }
65
- }
66
- }
67
-
68
- function initControllersAsDependency(routes: Array<Route>, container: Container): void {
69
- for (const route of routes) {
70
- bindClass(container, route.controller, route.controller);
71
- if (route.children) {
72
- initControllersAsDependency(route.children, container);
73
- }
74
- }
75
- }
76
-
77
- function bindClass<T>(container: Container, token: Type<T> | string, classtype: Type<any>): void {
78
- if (!container.isBound(token)){
79
- container.bind<any>(token).to(classtype as any as interfaces.Newable<any>);
80
- }
81
- }
82
-
83
- function bindValue(container: Container, token: string, value: any): void {
84
- if (!container.isBound(token)) {
85
- container.bind<any>(token).toConstantValue(value);
86
- }
87
- }
88
-
89
- function bindFactory(container: Container, token: string, factory: inversify.interfaces.FactoryCreator<unknown>): void {
90
- if (!container.isBound(token)) {
91
- container.bind<any>(token).toFactory(factory);
92
- }
93
- }
94
-
95
-
96
- function initControllers(routes: Array<Route>, container: Container, app: Controller): void {
97
- for (const route of routes) {
98
- const controller = container.get<Controller>(route.controller);
99
- app[setControllerSymbol](route.path, controller);
100
-
101
- if (route.children) {
102
- initControllers(route.children, container, controller);
103
- }
104
- }
105
- }
106
-
107
- class ControllerEmulator {
108
- constructor(private app: express.Application) {}
109
-
110
- private [setControllerSymbol](path: string, subrouter: Controller): void {
111
- this.app.use(path, subrouter[getRouterSymbol]());
112
- }
113
- }
114
-
115
- interface Type<T> extends Function {
116
- new(...args: any[]): T;
117
- }
118
-
119
- interface Dependency {
120
- provide: string;
121
- useClass?: Type<any>;
122
- useValue?: any;
123
- }
124
-
125
- interface Route {
126
- path: PathParams;
127
- controller: Type<Controller>;
128
- children?: Array<Route>;
129
- }
130
-
131
- interface ApplicationConfig {
132
- routes: Array<Route>;
133
- dependencies?: Array<Dependency>;
134
- middlewares?: Array<RequestHandlerParams<any>>;
135
- on?: EventCallback[];
136
- set?: Partial<Settings>;
137
- }
138
-
139
- type EventCallback = {
140
- event: 'connect' | 'connection' | 'close' | 'error' | 'listening' | 'lookup' | 'ready' | 'timeout' | 'mount';
141
- callback: (parent: express.Application) => void
142
- };
143
-
144
- interface Settings extends Record<SettingsEnumKeys, any>{
145
- caseSensitiveRouting: boolean;
146
- env: string;
147
- etag: any;
148
- jsonpCallbackName: string;
149
- jsonEscape: boolean;
150
- jsonReplacer: any;
151
- jsonSpaces: any;
152
- queryParser: any;
153
- strictRouting: boolean;
154
- subdomainOffset: number;
155
- trustProxy: any;
156
- views: string | string[];
157
- viewCache: boolean;
158
- viewEngine: string;
159
- xPoweredBy: boolean;
160
- }
161
-
162
- class SettingsEnum implements Record<SettingsEnumKeys, string>{
163
- caseSensitiveRouting = 'case sensitive routing';
164
- env = 'env';
165
- etag = 'etag';
166
- jsonpCallbackName = 'jsonp callback name';
167
- jsonEscape = 'json escape'
168
- jsonReplacer = 'json replacer';
169
- jsonSpaces = 'json spaces';
170
- queryParser = 'query parser';
171
- strictRouting = 'strict routing';
172
- subdomainOffset = 'subdomain offset';
173
- trustProxy = 'trust proxy';
174
- views = 'views';
175
- viewCache = 'view cache';
176
- viewEngine = 'view engine';
177
- xPoweredBy = 'x-powered-by';
178
- }
179
-
180
- type SettingsEnumKeys =
181
- 'caseSensitiveRouting' |
182
- 'env' |
183
- 'etag' |
184
- 'jsonpCallbackName' |
185
- 'jsonEscape' |
186
- 'jsonReplacer' |
187
- 'jsonSpaces' |
188
- 'queryParser' |
189
- 'strictRouting' |
190
- 'subdomainOffset' |
191
- 'trustProxy' |
192
- 'views' |
193
- 'viewCache' |
194
- 'viewEngine' |
195
- 'xPoweredBy';
196
-
197
- export type PathParams = string | RegExp | Array<string | RegExp>;
package/src/controller.ts DELETED
@@ -1,204 +0,0 @@
1
- import { Request, Response, NextFunction, Router } from 'express';
2
- import { injectable } from 'inversify';
3
- import { WebSocket } from 'ws';
4
-
5
- export const getRouterSymbol = Symbol();
6
- export const setControllerSymbol = Symbol();
7
-
8
-
9
- export type RequestHandlerParams<T> = Middleware<T> | ErrorHandler<T>;
10
-
11
- export interface Middleware<T> {
12
- (
13
- req: MergePartial<Request, T>,
14
- res: Response,
15
- next: NextFunction
16
- ): void;
17
- }
18
-
19
- export interface ErrorHandler<T> {
20
- (
21
- err: any,
22
- req: MergePartial<Request, T>,
23
- res: Response,
24
- next: NextFunction,
25
- ): void;
26
- }
27
-
28
- @injectable()
29
- export class Controller {
30
- private router: Router;
31
-
32
- constructor() {
33
- this.router = Router();
34
- }
35
-
36
- private [setControllerSymbol](path: any, subrouter: Controller): void {
37
- this.router.use(path, subrouter[getRouterSymbol]());
38
- }
39
-
40
- private [getRouterSymbol](): Router {
41
- return this.router;
42
- }
43
-
44
- protected useWS<M0>(): MiniControllerWS<M0>;
45
- protected useWS<M0>(middleware0: WSMiddleware<M0>): MiniControllerWS<M0>;
46
- protected useWS<M0, M1>(middleware0: WSMiddleware<M0>, middleware1: WSMiddleware<M1>): MiniControllerWS<M0 & M1>;
47
- protected useWS<M0, M1, M2>(middleware0: WSMiddleware<M0>, middleware1: WSMiddleware<M1>, middleware2: WSMiddleware<M2>): MiniControllerWS<M0 & M1 & M2>;
48
- protected useWS<M0, M1, M2, M3>(middleware0: WSMiddleware<M0>, middleware1: WSMiddleware<M1>, middleware2: WSMiddleware<M2>, middleware3: WSMiddleware<M3>): MiniControllerWS<M0 & M1 & M2 & M3>;
49
- protected useWS(...middlewares: Array<unknown>): MiniControllerWS<unknown> {
50
- return (handler) => {
51
- (this.router as any).ws.apply(this.router, ['/', ...middlewares, handler]);
52
- }
53
- }
54
-
55
- protected use<M0>(): MiniController<M0>;
56
- protected use<M0>(middleware0: RequestHandlerParams<M0>): MiniController<M0>;
57
- protected use<M0, M1>(middleware0: RequestHandlerParams<M0>, middleware1: RequestHandlerParams<M1>): MiniController<M0 & M1>;
58
- protected use<M0, M1, M2>(middleware0: RequestHandlerParams<M0>, middleware1: RequestHandlerParams<M1>, middleware2: RequestHandlerParams<M2>): MiniController<M0 & M1 & M2>;
59
- protected use<M0, M1, M2, M3>(middleware0: RequestHandlerParams<M0>, middleware1: RequestHandlerParams<M1>, middleware2: RequestHandlerParams<M2>, middleware3: RequestHandlerParams<M3>): MiniController<M0 & M1 & M2 & M3>;
60
- protected use(...middlewares: Array<unknown>): MiniController<unknown> {
61
- return new MiniController(this.router, middlewares);
62
- }
63
- }
64
-
65
- type WSHandler<T> = (ws: WebSocket, req: Merge<Request, T>) => void;
66
- export type WSMiddleware<T> = (ws: WebSocket, req: MergePartial<Request, T>, next: NextFunction) => void
67
-
68
- interface MiniControllerWS<T> {
69
- (handler: WSHandler<T>): void;
70
- }
71
-
72
- interface MiniControllerInterface<T> {
73
- all: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
74
- get: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
75
- post: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
76
- put: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
77
- delete: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
78
- patch: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
79
- options: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
80
- head: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
81
-
82
- checkout: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
83
- connect: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
84
- copy: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
85
- lock: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
86
- merge: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
87
- mkactivity: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
88
- mkcol: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
89
- move: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
90
- "m-search": <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
91
- notify: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
92
- propfind: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
93
- proppatch: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
94
- purge: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
95
- report: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
96
- search: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
97
- subscribe: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
98
- trace: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
99
- unlock: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
100
- unsubscribe: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
101
- link: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
102
- unlink: <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void;
103
- }
104
-
105
- class MiniController<T> implements MiniControllerInterface<T> {
106
- constructor(
107
- private router: any,
108
- private middlewares: any[]
109
- ) { }
110
-
111
- all = this.methodImplementation('all').bind(this);
112
- get = this.methodImplementation('get').bind(this);
113
- post = this.methodImplementation('post').bind(this);
114
- put = this.methodImplementation('put').bind(this);
115
- delete = this.methodImplementation('delete').bind(this);
116
- patch = this.methodImplementation('patch').bind(this);
117
- options = this.methodImplementation('options').bind(this);
118
- head = this.methodImplementation('head').bind(this);
119
-
120
- checkout = this.methodImplementation('checkout').bind(this);
121
- connect = this.methodImplementation('connect').bind(this);
122
- copy = this.methodImplementation('copy').bind(this);
123
- lock = this.methodImplementation('lock').bind(this);
124
- merge = this.methodImplementation('merge').bind(this);
125
- mkactivity = this.methodImplementation('mkactivity').bind(this);
126
- mkcol = this.methodImplementation('mkcol').bind(this);
127
- move = this.methodImplementation('move').bind(this);
128
- 'm-search' = this.methodImplementation('m-search').bind(this);
129
- notify = this.methodImplementation('notify').bind(this);
130
- propfind = this.methodImplementation('propfind').bind(this);
131
- proppatch = this.methodImplementation('proppatch').bind(this);
132
- purge = this.methodImplementation('purge').bind(this);
133
- report = this.methodImplementation('report').bind(this);
134
- search = this.methodImplementation('search').bind(this);
135
- subscribe = this.methodImplementation('subscribe').bind(this);
136
- trace = this.methodImplementation('trace').bind(this);
137
- unlock = this.methodImplementation('unlock').bind(this);
138
- unsubscribe = this.methodImplementation('unsubscribe').bind(this);
139
- link = this.methodImplementation('link').bind(this);
140
- unlink = this.methodImplementation('unlink').bind(this);
141
-
142
-
143
- private methodImplementation(methodName: PropertyKey): <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>)=> void {
144
- return <Path extends string>(path: Path, handler: RequestHandler<T, RouteParameters<Path>>): void => {
145
- this.router[methodName].apply(this.router, [
146
- path,
147
- ...this.middlewares,
148
- (req: any, res: any, next: any) => {
149
- handler(req, res, next);
150
- }
151
- ]);
152
- }
153
- }
154
-
155
- use<M0>(middleware0: RequestHandlerParams<M0>): MiniController<Merge<T, M0>>;
156
- use<M0, M1>(middleware0: RequestHandlerParams<M0>, middleware1: RequestHandlerParams<M1>): MiniController<Merge<T, M0 & M1>>;
157
- use<M0, M1, M2>(middleware0: RequestHandlerParams<M0>, middleware1: RequestHandlerParams<M1>, middleware2: RequestHandlerParams<M2>): MiniController<Merge<T, M0 & M1 & M2>>;
158
- use<M0, M1, M2, M3>(middleware0: RequestHandlerParams<M0>, middleware1: RequestHandlerParams<M1>, middleware2: RequestHandlerParams<M2>, middleware3: RequestHandlerParams<M3>): MiniController<Merge<T, M0 & M1 & M2 & M3>>;
159
- use<S>(...middlewares: Array<Middleware<S>>): MiniController<S> {
160
- return new MiniController(this.router, this.middlewares.concat(middlewares));
161
- }
162
- }
163
-
164
- interface RequestHandler<
165
- T,
166
- P = ParamsDictionary
167
- > {
168
- (
169
- req: Merge<Request, T & { params: P }>,
170
- res: Response,
171
- next: NextFunction
172
- ): void;
173
- }
174
-
175
-
176
- export type Merge<A, B> = {
177
- [k in keyof A & keyof B]: (A & B)[k] extends never ? B[k] : 0 extends 1 & (A & B)[k] ? B[k] : (A & B)[k];
178
- } & Omit<A, keyof B> & Omit<B, keyof A>;
179
-
180
- export type MergePartial<A, B> = {
181
- [k in keyof A & keyof B]: (A & B)[k] extends never ? B[k] : 0 extends 1 & (A & B)[k] ? B[k] : (A & B)[k];
182
- } & Omit<A, keyof B> & Partial<Omit<B, keyof A>>;
183
-
184
- interface ParamsDictionary {
185
- [key: string]: string;
186
- }
187
-
188
- export type RouteParameters<Route extends string> = string extends Route ? ParamsDictionary
189
- : Route extends `${string}(${string}` ? ParamsDictionary // TODO: handling for regex parameters
190
- : Route extends `${string}:${infer Rest}` ?
191
- & (
192
- GetRouteParameter<Rest> extends never ? ParamsDictionary
193
- : GetRouteParameter<Rest> extends `${infer ParamName}?` ? { [P in ParamName]?: string }
194
- : { [P in GetRouteParameter<Rest>]: string }
195
- )
196
- & (Rest extends `${GetRouteParameter<Rest>}${infer Next}` ? RouteParameters<Next> : unknown)
197
- : {};
198
-
199
- type GetRouteParameter<S extends string> = RemoveTail<
200
- RemoveTail<RemoveTail<S, `/${string}`>, `-${string}`>,
201
- `.${string}`
202
- >;
203
-
204
- type RemoveTail<S extends string, Tail extends string> = S extends `${infer P}${Tail}` ? P : S;
@@ -1 +0,0 @@
1
- export { inject, injectable } from 'inversify';
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export { interfaces } from 'inversify';
2
- export { createApp } from './app';
3
- export { Controller, Middleware, WSMiddleware } from './controller';
@@ -1 +0,0 @@
1
- export { json, static, urlencoded, query, raw, text } from 'express';
@@ -1,9 +0,0 @@
1
- import { Middleware } from "..";
2
- import { validator } from ".";
3
- import { ValidationLogic } from "./validators";
4
-
5
- export function bodyValidator<T>(validationLogic: ValidationLogic<T>): Middleware< { body: T }> {
6
- return (req, res, next) => {
7
- validator(validationLogic, 'body')(req, res, next);
8
- }
9
- }
@@ -1,2 +0,0 @@
1
- export { and, isDefined, isNull, isNumber, isString, isUndefined, not, notNull, or, validator, ValidationLogic, custom } from './validators';
2
- export { bodyValidator } from './body-validator';
@@ -1,9 +0,0 @@
1
- import { Middleware } from "..";
2
- import { validator } from ".";
3
- import { ValidationLogic } from "./validators";
4
-
5
- export function queryValidator<T>(validationLogic: ValidationLogic<T>): Middleware< { query: T }> {
6
- return (req, res, next) => {
7
- validator(validationLogic, 'query')(req, res, next);
8
- }
9
- }
@@ -1,216 +0,0 @@
1
- import { Middleware } from '../controller';
2
-
3
- type RequestField<F extends PropertyKey, T> = Record<F, T>;
4
-
5
- export function validator<T, F extends PropertyKey>(validationLogic: ValidationLogic<T>, requestField: F): Middleware<RequestField<F, T>> {
6
- return (req, res, next) => {
7
- // @ts-ignore
8
- applyValidation(req[requestField], validationLogic).then(errors => {
9
- const result = isThereAnyErrors(errors);
10
- if (result) {
11
- next(errors);
12
- } else {
13
- next();
14
- }
15
- }).catch(next);
16
-
17
- }
18
- }
19
-
20
- async function applyValidation<T>(obj: T, validationLogic: ValidationLogic<T>): Promise<Partial<Record<keyof T, any>>> {
21
- const validationResult: Partial<Record<keyof T, any>> = {};
22
-
23
- for (const key in validationLogic) {
24
- const atomicValidator = validationLogic[key];
25
-
26
- if (atomicValidator) {
27
- if (atomicValidator instanceof Validator) {
28
- try {
29
- validationResult[key] = atomicValidator.validate(obj, key);
30
- if (validationResult[key] as Object instanceof Promise) {
31
- validationResult[key] = await validationResult[key];
32
- console.log(`awaited result: ${validationResult[key]}`);
33
- }
34
- } catch (err) {
35
- validationResult[key] = false;
36
- }
37
- } else {
38
- if (obj[key] instanceof Array) {
39
- validationResult[key] = (obj[key] as Array<any>).map(objj => applyValidation(objj, atomicValidator));
40
- if (validationResult[key][0] instanceof Promise) {
41
- validationResult[key] = Promise.all(validationResult[key]);
42
- }
43
- } else {
44
- validationResult[key] = applyValidation(obj[key], atomicValidator as any);
45
- if (validationResult[key] as Object instanceof Promise) {
46
- validationResult[key] = await validationResult[key];
47
- }
48
- }
49
- }
50
- } else {
51
- validationResult[key] = true;
52
- }
53
- }
54
-
55
- return validationResult;
56
- }
57
-
58
- function isThereAnyErrors(obj: Object): boolean {
59
- for (const [key, value] of Object.entries(obj)) {
60
- if (value === false) {
61
- return true;
62
- } else if (typeof value !== 'boolean') {
63
- const partialRes = isThereAnyErrors(value);
64
- if (partialRes) {
65
- return partialRes;
66
- }
67
- }
68
- }
69
- return false;
70
- }
71
-
72
- type UnArray<T> = T extends Array<infer A> ? A : T;
73
-
74
- type ValidatorReturn = boolean | Promise<boolean>;
75
-
76
- export type ValidationLogic<T> = {
77
- [k in keyof T as T[k] extends Function ? never : k]?: ValidationLogic<UnArray<T[k]>> | Validator<T>;
78
- }
79
-
80
- // type ValidationFunction<T> = (subject: T) => boolean;
81
-
82
- export abstract class Validator<T> {
83
- abstract validate(subject: T, selectedField: keyof T): ValidatorReturn;
84
- }
85
-
86
-
87
- class CustomValidator<T> extends Validator<T> {
88
- constructor(private validator: (obj: T) => ValidatorReturn) {
89
- super();
90
- }
91
-
92
- validate(subject: T, selectedField: keyof T): ValidatorReturn{
93
- return this.validator(subject);
94
- }
95
- }
96
-
97
- export function custom<T>(validator: (obj: T) => ValidatorReturn): Validator<T> {
98
- return new CustomValidator(validator);
99
- }
100
-
101
- export class AtomicValidator<T> extends Validator<T> {
102
- constructor(private implementation: (subject: T | T[keyof T]) => ValidatorReturn, public queryField?: keyof T) {
103
- super();
104
- }
105
-
106
- validate(subject: T, selectedField: keyof T): ValidatorReturn {
107
- return this.implementation(this.queryField ? subject[this.queryField] : subject[selectedField]);
108
- }
109
- }
110
-
111
- export function isString<T>(field?: keyof T): AtomicValidator<T> {
112
- return new AtomicValidator((subject) => {
113
- return typeof subject === 'string';
114
- }, field);
115
- }
116
-
117
- export function isNumber<T>(field?: keyof T): AtomicValidator<T> {
118
- return new AtomicValidator((subject) => {
119
- return typeof subject === 'number';
120
- }, field);
121
- }
122
-
123
- export function isDefined<T>(field?: keyof T): AtomicValidator<T> {
124
- return new AtomicValidator((subject) => {
125
- return subject != undefined;
126
- }, field);
127
- }
128
-
129
- export function isUndefined<T>(field?: keyof T): AtomicValidator<T> {
130
- return new AtomicValidator((subject) => {
131
- return subject === undefined;
132
- }, field);
133
- }
134
-
135
- export function isNull<T>(field?: keyof T): AtomicValidator<T> {
136
- return new AtomicValidator((subject) => {
137
- return subject === null;
138
- }, field);
139
- }
140
-
141
- export function notNull<T>(field?: keyof T): AtomicValidator<T> {
142
- return new AtomicValidator((subject) => {
143
- return subject !== null;
144
- }, field);
145
- }
146
-
147
-
148
- class AndValidator<T> extends Validator<T> {
149
- private validationFunctions: Array<Validator<T>>;
150
-
151
- constructor(...validationFunctions: Array<Validator<T>>) {
152
- super();
153
- this.validationFunctions = validationFunctions;
154
- }
155
-
156
- validate(subject: T, selectedField: keyof T): ValidatorReturn {
157
- return this.validationFunctions.every(eachValidator => eachValidator.validate(subject, selectedField));
158
- }
159
- }
160
-
161
- class AndValidatorAsync<T> extends Validator<T> {
162
- private validationFunctions: Array<Validator<T>>;
163
-
164
- constructor(...validationFunctions: Array<Validator<T>>) {
165
- super();
166
- this.validationFunctions = validationFunctions;
167
- }
168
-
169
- async validate(subject: T, selectedField: keyof T): Promise<boolean> {
170
- const allPromises = this.validationFunctions.map(eachValidator => eachValidator.validate(subject, selectedField));
171
- const allResults = await Promise.all(allPromises);
172
- return allResults.every(val => val);
173
- }
174
- }
175
-
176
- class OrValidator<T> extends Validator<T> {
177
- private validationFunctions: Array<Validator<T>>
178
-
179
- constructor(...validationFunctions: Array<Validator<T>>) {
180
- super();
181
- this.validationFunctions = validationFunctions;
182
- }
183
-
184
- validate(subject: T, selectedField: keyof T): ValidatorReturn {
185
- return this.validationFunctions.some(eachValidator => eachValidator.validate(subject, selectedField));
186
- }
187
- }
188
-
189
- class NotValidator<T> extends Validator<T> {
190
- private validationFunction: Validator<T>;
191
-
192
- constructor(validationFunctions: Validator<T>) {
193
- super();
194
- this.validationFunction = validationFunctions;
195
- }
196
-
197
- validate(subject: T, selectedField: keyof T): ValidatorReturn {
198
- return !this.validationFunction.validate(subject, selectedField);
199
- }
200
- }
201
-
202
- export function and<T>(...validationFunctions: Array<Validator<T>>): Validator<T> {
203
- return new AndValidator(...validationFunctions);
204
- }
205
-
206
- export function andAsync<T>(...validationFunctions: Array<Validator<T>>): Validator<T> {
207
- return new AndValidatorAsync(...validationFunctions);
208
- }
209
-
210
- export function or<T>(...validationFunctions: Array<Validator<T>>): Validator<T> {
211
- return new OrValidator(...validationFunctions);
212
- }
213
-
214
- export function not<T>(validationFunction: Validator<T>): Validator<T> {
215
- return new NotValidator(validationFunction);
216
- }