framework-do-dede 0.0.1

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/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # Framework do Dedé
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ bun run index.ts
13
+ ```
14
+
15
+ This project was created using `bun init` in bun v1.1.42. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
@@ -0,0 +1,13 @@
1
+ import type { AllowedMethods, HttpStatusCode } from '@/http/HttpServer';
2
+
3
+ export declare type Controller = {
4
+ instance: any
5
+ instanceMethod: string
6
+ route: string
7
+ method: AllowedMethods
8
+ middlewares?: HttpMiddleware[]
9
+ statusCode?: HttpStatusCode
10
+ validation?: Validation
11
+ params?: any
12
+ query?: any
13
+ }
@@ -0,0 +1,5 @@
1
+ export declare class FrameworkError extends Error {
2
+ constructor(message: string) {
3
+ super(message)
4
+ }
5
+ }
@@ -0,0 +1,3 @@
1
+ export default interface HttpMiddleware {
2
+ execute(input: any): Promise<any>
3
+ };
@@ -0,0 +1,87 @@
1
+ export declare type HttpStatusCode = 200 | 201 | 204 | 401 | 403 | 404 | 409 | 422 | 500
2
+
3
+ export type AllowedMethods = 'get' | 'post' | 'put' | 'delete' | 'patch'
4
+
5
+ export type HttpServerParams = {
6
+ method: AllowedMethods,
7
+ route: string,
8
+ statusCode?: number,
9
+ params?: string[],
10
+ query?: string[]
11
+ }
12
+
13
+ type FrameworkWeb = {
14
+ listen(port: number): void;
15
+ use(middleware: CallableFunction): void
16
+ get(route: string, handler: CallableFunction): void
17
+ post(route: string, handler: CallableFunction): void
18
+ put(route: string, handler: CallableFunction): void
19
+ delete(route: string, handler: CallableFunction): void
20
+ patch(route: string, handler: CallableFunction): void
21
+ }
22
+
23
+ export default abstract class HttpServer {
24
+ protected framework: FrameworkWeb
25
+ protected frameworkName: string;
26
+ protected defaultMessageError = 'Ops, An unexpected error occurred';
27
+
28
+ constructor(framework: FrameworkWeb, frameworkName: 'elysia' | 'express') {
29
+ if (frameworkName !== 'elysia' && frameworkName !== 'express') throw new FrameworkError('Framework not supported')
30
+ this.framework = framework
31
+ this.frameworkName = frameworkName
32
+ }
33
+
34
+ use(middleware: CallableFunction): HttpServer {
35
+ this.framework.use(middleware)
36
+ return this;
37
+ }
38
+
39
+ register(httpServerParams: HttpServerParams, handler: CallableFunction) {
40
+ const route = this.mountRoute(httpServerParams)
41
+ if (this.frameworkName === 'elysia') return this.elysia(httpServerParams, route, handler)
42
+ }
43
+
44
+ listen(port: number): void {
45
+ this.framework.listen(port)
46
+ }
47
+
48
+ private mountRoute(httpServerParams: HttpServerParams) {
49
+ const params = httpServerParams.params?.map((param) => param.split('|')[0])
50
+ if (params && params.length > 0) {
51
+ const paramsMounted = params.map((v) => {
52
+ return v.includes('_') ? `${v.replace('_', '/')}` : `/:${v}`
53
+ }).join('')
54
+ return `${httpServerParams.route}${paramsMounted}`
55
+ }
56
+ return httpServerParams.route
57
+ }
58
+
59
+ private elysia (httpServerParams: HttpServerParams, route: string, handler: CallableFunction) {
60
+ const method = httpServerParams.method as AllowedMethods
61
+ (this.framework[method])(route, async ({ headers, set, query, params, body, request, path }: any) => {
62
+ try {
63
+ set.status = httpServerParams.statusCode ?? 200
64
+ const output = await handler({
65
+ headers,
66
+ query,
67
+ params,
68
+ body
69
+ })
70
+ return output
71
+ } catch (error: any) {
72
+ if (error instanceof ServerError) {
73
+ set.status = error.getStatusCode()
74
+ return {
75
+ error: error.message,
76
+ statusCode: error.getStatusCode()
77
+ }
78
+ }
79
+ set.status = 500
80
+ return {
81
+ error: this.defaultMessageError,
82
+ statusCode: 500
83
+ }
84
+ }
85
+ })
86
+ }
87
+ }
@@ -0,0 +1,42 @@
1
+ export declare abstract class ServerError extends Error {
2
+ private statusCode: number
3
+ constructor(message: string, statusCode: number) {
4
+ super(message)
5
+ this.name = this.constructor.name
6
+ this.statusCode = statusCode
7
+ }
8
+
9
+ getStatusCode() {
10
+ return this.statusCode
11
+ }
12
+ }
13
+ export declare class NotFound extends ServerError {
14
+ constructor(message: string) {
15
+ super(message, 404)
16
+ }
17
+ }
18
+ export declare class Forbidden extends ServerError {
19
+ constructor(message: string) {
20
+ super(message, 403)
21
+ }
22
+ }
23
+ export declare class UnprocessableEntity extends ServerError {
24
+ constructor(message: string) {
25
+ super(message, 422)
26
+ }
27
+ }
28
+ export declare class Conflict extends ServerError {
29
+ constructor(message: string) {
30
+ super(message, 409)
31
+ }
32
+ }
33
+ export declare class Unauthorized extends ServerError {
34
+ constructor(message: string) {
35
+ super(message, 401)
36
+ }
37
+ }
38
+ export declare class BadRequest extends ServerError {
39
+ constructor(message: string) {
40
+ super(message, 400)
41
+ }
42
+ }
@@ -0,0 +1,3 @@
1
+ export default interface UseCase<Input, Output> {
2
+ execute(input: Input): Promise<Output>
3
+ };
@@ -0,0 +1,3 @@
1
+ export default interface Validation {
2
+ validate(input: any): any;
3
+ };
@@ -0,0 +1,11 @@
1
+ import type { HttpMiddleware } from '@/protocols';
2
+
3
+ declare const middlewares: Map<string, HttpMiddleware>;
4
+ export declare function Controller(basePath: string): void;
5
+ export declare function Middleware(middlewareClass: new ()): void;
6
+ export declare function Post(config: { path?: string,, statusCode?: number,, params?: string[],, query?: string[] }): void;
7
+ export declare function Get(config: { path?: string,, statusCode?: number,, params?: string[],, query?: string[] }): void;
8
+ export declare function Put(config: { path?: string,, statusCode?: number,, params?: string[],, query?: string[] }): void;
9
+ export declare function Patch(config: { path?: string,, statusCode?: number,, params?: string[],, query?: string[] }): void;
10
+ export declare function Delete(config: { path?: string,, statusCode?: number,, params?: string[],, query?: string[] }): void;
11
+ export declare function Validator(validationClass: new ()): void;
@@ -0,0 +1,86 @@
1
+ import type { Controller } from '@/protocols/Controller';
2
+
3
+ declare type Input = {
4
+ headers: any
5
+ body: any
6
+ params: any
7
+ query: any
8
+ }
9
+
10
+ export default class ControllerHandler {
11
+ constructor(httpServer: HttpServer, port: number) {
12
+ for (const { instance, instanceMethod, middlewares, method, route, statusCode, params, query, validation } of this.registryControllers()) {
13
+ httpServer.register(
14
+ {
15
+ method,
16
+ route,
17
+ statusCode,
18
+ params,
19
+ query
20
+ },
21
+ async (input: Input) => {
22
+ const filterParams = this.filter(input.params, params)
23
+ const queryParams = this.filter(input.query, query)
24
+ let mergedParams = { ...filterParams, ...queryParams, ...(input.body || {}) }
25
+ if (validation) mergedParams = validation.validate({ ...filterParams, ...queryParams, ...(input.body || {}) });
26
+ let middlewareData = {}
27
+ if (middlewares) {
28
+ for (const middleware of middlewares) {
29
+ const middlewareResult = await middleware.execute({ headers: input.headers, ...mergedParams })
30
+ middlewareData = { ...middlewareResult, ...middlewareData }
31
+ }
32
+ }
33
+ const request = { headers: input.headers, data: mergedParams, middlewareData }
34
+ return await instance[instanceMethod](mergedParams, request)
35
+ }
36
+ )
37
+ }
38
+ httpServer.listen(port)
39
+ }
40
+
41
+ private registryControllers() {
42
+ const registryControllers = Registry.resolve<any[]>('controllers');
43
+ const controllers: Controller[] = []
44
+ for (const controller of registryControllers) {
45
+ const basePath = Reflect.getMetadata('basePath', controller);
46
+ const injections = Reflect.getMetadata('injections', controller) || [];
47
+ const args = injections.map((token: string) => Registry.resolve(token))
48
+ const instance = new controller(...args)
49
+ const methodNames = Object.getOwnPropertyNames(controller.prototype).filter(method => method !== 'constructor')
50
+ for (const methodName of methodNames) {
51
+ const validation = Reflect.getMetadata('validation', controller.prototype, methodName);
52
+ const routeConfig = Reflect.getMetadata('route', controller.prototype, methodName);
53
+ const middlewares = Reflect.getMetadata('middlewares', controller.prototype, methodName);
54
+ controllers.push({
55
+ method: routeConfig.method,
56
+ route: basePath + routeConfig.path,
57
+ params: routeConfig.params,
58
+ query: routeConfig.query,
59
+ statusCode: routeConfig.statusCode,
60
+ instance,
61
+ instanceMethod: methodName,
62
+ middlewares,
63
+ validation
64
+ });
65
+ }
66
+ }
67
+ return controllers
68
+ }
69
+
70
+ private filter(params: any, filterParams?: string[]): any {
71
+ const filter: any = {}
72
+ for (const paramName of filterParams || []) {
73
+ const [paramNameFiltered, type] = paramName.split('|')
74
+ let value = params[paramName] || params[paramNameFiltered]
75
+ if (!value) return
76
+ if (type === 'boolean') value = value === 'true'
77
+ if (type === 'integer') {
78
+ value = value.replace(/[^0-9]/g, '')
79
+ value = value ? parseInt(value) : 0
80
+ }
81
+ if (type === 'string') value = value.toString()
82
+ filter[paramNameFiltered] = value
83
+ }
84
+ return filter
85
+ }
86
+ }
package/dist/di.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function Inject(token: string): void;
@@ -0,0 +1,24 @@
1
+ import { Auth, Controller, Delete, Get, Post, Put, Validator } from '@/decorators';
2
+ import { ControllerHandler, UseCaseHandler } from '@/handlers';
3
+ import { HttpMiddleware, UseCase, Validation } from '@/protocols';
4
+ import { HttpServer, ServerError } from '@/http';
5
+ import { Registry } from './di/registry';
6
+
7
+
8
+ export {
9
+ Registry,
10
+ Auth,
11
+ Controller,
12
+ Delete,
13
+ Get,
14
+ Post,
15
+ Put,
16
+ Validator,
17
+ HttpMiddleware,
18
+ UseCase,
19
+ Validation,
20
+ HttpServer,
21
+ ServerError,
22
+ UseCaseHandler,
23
+ ControllerHandler
24
+ }
@@ -0,0 +1,4 @@
1
+ declare const dependency: unknown;
2
+ declare const dependency: unknown;
3
+ declare const paramtypes: (...args: any[]) => unknown;
4
+ export declare const Registry: unknown;
@@ -0,0 +1 @@
1
+ export declare function Auth(propertyName: string): void;
@@ -0,0 +1,23 @@
1
+ import type { UseCase } from '@/protocols';
2
+
3
+ declare type RequestData = {
4
+ headers: any,
5
+ data?: any,
6
+ middlewareData?: any
7
+ }
8
+
9
+
10
+ export class UseCaseHandler {
11
+ static load<T extends UseCase<any, any>>(
12
+ useCaseClass: new (...args: any[]) => T,
13
+ request?: RequestData
14
+ ): T {
15
+ const instance = Registry.classLoader(useCaseClass);
16
+ const auth = Reflect.getMetadata("auth", useCaseClass);
17
+ const context = request
18
+ if (auth && context?.middlewareData) {
19
+ (instance as any)[auth] = context.middlewareData[auth]
20
+ }
21
+ return instance
22
+ }
23
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "framework-do-dede",
3
+ "version": "0.0.1",
4
+ "main": "./dist/index.cjs",
5
+ "module": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "description": "",
8
+ "exports": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.cjs"
12
+ },
13
+ "scripts": {
14
+ "build": "bun run build.ts",
15
+ "prepare": "bun run build"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "keywords": [
21
+ "bun"
22
+ ],
23
+ "license": "MIT",
24
+ "homepage": "https://github.com/marcossaore/framework-do-dede#readme",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/marcossaore/framework-do-dede.git"
28
+ },
29
+ "bugs": "https://github.com/marcossaore/framework-do-dede/issues",
30
+ "author": "Marcos Soares",
31
+ "devDependencies": {
32
+ "@types/reflect-metadata": "^0.1.0",
33
+ "bun-plugin-dtsx": "^0.21.9"
34
+ },
35
+ "peerDependencies": {
36
+ "typescript": "^5.8.2"
37
+ },
38
+ "dependencies": {
39
+ "@types/bun": "^1.2.5",
40
+ "reflect-metadata": "^0.2.2"
41
+ }
42
+ }