diff --git a/packages/contracts/src/database/config.ts b/packages/contracts/src/database/config.ts index b9359882..891e8d46 100644 --- a/packages/contracts/src/database/config.ts +++ b/packages/contracts/src/database/config.ts @@ -12,7 +12,7 @@ export interface DatabaseConfig { /** * The default database connection name. */ - connection: string + connection: keyof this['connections'] /** * The settings of configured database connections. diff --git a/packages/contracts/src/http/request.ts b/packages/contracts/src/http/request.ts index 71a21cab..805fb259 100644 --- a/packages/contracts/src/http/request.ts +++ b/packages/contracts/src/http/request.ts @@ -5,6 +5,7 @@ import { HttpMethods } from './methods.js' import { HttpContext } from './context.js' import { CookieBag } from './cookie-bag.js' import { IncomingMessage } from 'node:http' +import type { Encrypter } from '../index.js' import { IncomingHttpHeaders } from 'node:http2' import { CookieConfig } from './cookie-config.js' import { MacroableCtor } from '@supercharge/macroable' @@ -17,7 +18,7 @@ export interface HttpRequestCtor extends MacroableCtor { /** * Create a new HTTP request instance. */ - new (context: HttpContext, cookieConfig: CookieConfig): HttpRequest + new (context: HttpContext, cookieConfig: CookieConfig, encryption: Encrypter): HttpRequest } export type Protocol = 'http' | 'https' | string diff --git a/packages/contracts/src/http/response.ts b/packages/contracts/src/http/response.ts index 5419a2fa..cbd48236 100644 --- a/packages/contracts/src/http/response.ts +++ b/packages/contracts/src/http/response.ts @@ -3,6 +3,7 @@ import { InputBag } from './input-bag.js' import { HttpContext } from './context.js' import { CookieBag } from './cookie-bag.js' import { HttpRedirect } from './redirect.js' +import type { Encrypter } from '../index.js' import { OutgoingHttpHeaders } from 'node:http2' import { CookieConfig } from './cookie-config.js' import { MacroableCtor } from '@supercharge/macroable' @@ -13,7 +14,7 @@ export interface HttpResponseCtor extends MacroableCtor { /** * Create a new HTTP response instance. */ - new (context: HttpContext, cookieConfig: CookieConfig): HttpResponse + new (context: HttpContext, cookieConfig: CookieConfig, encryption: Encrypter): HttpResponse } export interface HttpResponse extends InteractsWithState { diff --git a/packages/contracts/src/logging/config.ts b/packages/contracts/src/logging/config.ts index 2ae92cd2..0cdf13f7 100644 --- a/packages/contracts/src/logging/config.ts +++ b/packages/contracts/src/logging/config.ts @@ -3,7 +3,7 @@ export interface LoggingConfig { /** * The logging driver name. */ - driver: string + driver: keyof this['channels'] /** * The logging channels config. @@ -13,12 +13,12 @@ export interface LoggingConfig { export interface LoggingChannels { /** - * The file channel. + * Stores the configuration for the file channel. */ file?: FileChannelConfig /** - * The console channel. + * Stores the configuration for the console channel. */ console?: ConsoleChannelConfig } diff --git a/packages/core/package.json b/packages/core/package.json index 985c015b..2814b0c4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -33,6 +33,7 @@ }, "devDependencies": { "@supercharge/view": "^4.0.0-alpha.2", + "@supercharge/encryption": "^4.0.0-alpha.2", "c8": "~8.0.1", "expect": "~29.7.0", "mocked-env": "~1.3.5", diff --git a/packages/core/src/bootstrappers/handle-shutdown.ts b/packages/core/src/bootstrappers/handle-shutdown.ts index 803aec6a..f69aecdc 100644 --- a/packages/core/src/bootstrappers/handle-shutdown.ts +++ b/packages/core/src/bootstrappers/handle-shutdown.ts @@ -19,9 +19,8 @@ export class HandleShutdown implements Bootstrapper { */ async bootstrap (): Promise { this.shutdownSignalListener - .onShutdown(async () => { - await this.app.shutdown() - }) + .onShutdown(async () => await this.app.shutdown()) + .onShutdown(() => this.shutdownSignalListener.cleanup()) .listen() } } diff --git a/packages/core/src/shutdown-signal-listener.ts b/packages/core/src/shutdown-signal-listener.ts index 8f1f612f..6994d9b7 100644 --- a/packages/core/src/shutdown-signal-listener.ts +++ b/packages/core/src/shutdown-signal-listener.ts @@ -3,7 +3,7 @@ import Os from 'node:os' import Set from '@supercharge/set' import { Application } from '@supercharge/contracts' -export type OnShutdownCallback = () => Promise | void +export type OnShutdownCallback = () => Promise | unknown export class ShutdownSignalListener { /** diff --git a/packages/core/test/error-handler.js b/packages/core/test/error-handler.js index fcc61aae..393b1830 100644 --- a/packages/core/test/error-handler.js +++ b/packages/core/test/error-handler.js @@ -8,6 +8,7 @@ import { fileURLToPath } from 'node:url' import { Server } from '@supercharge/http' import { ViewServiceProvider } from '@supercharge/view' import { Application, ErrorHandler } from '../dist/index.js' +import { EncryptionServiceProvider } from '@supercharge/encryption' const viewMock = { boot () { }, @@ -29,6 +30,7 @@ function createApp () { app .bind('view', () => viewMock) + .register(new EncryptionServiceProvider(app)) app.config() .set('app.key', 1234) diff --git a/packages/http/src/http-service-provider.ts b/packages/http/src/http-service-provider.ts index 03ee58f8..6a535817 100644 --- a/packages/http/src/http-service-provider.ts +++ b/packages/http/src/http-service-provider.ts @@ -4,7 +4,7 @@ import { Router } from './routing/index.js' import { Request } from './server/request.js' import { Response } from './server/response.js' import { ServiceProvider } from '@supercharge/support' -import { ApplicationConfig, HttpConfig } from '@supercharge/contracts' +import { ApplicationConfig, HttpConfig, type Encrypter } from '@supercharge/contracts' /** * Add container bindings for services from this provider. @@ -39,7 +39,12 @@ export class HttpServiceProvider extends ServiceProvider { .singleton('server', () => { const appConfig = this.config().get('app') - return new Server(this.app(), appConfig, this.httpConfig()) + return new Server( + this.app(), + appConfig, + this.httpConfig(), + this.encrypter(), + ) }) .alias('server', 'http.server') .alias('server', Server) @@ -50,8 +55,21 @@ export class HttpServiceProvider extends ServiceProvider { */ private bindRouter (): void { this.app() - .singleton('route', () => new Router(this.app(), this.httpConfig())) - .alias('route', 'router') + .singleton('router', () => { + return new Router( + this.app(), + this.httpConfig(), + this.encrypter(), + ) + }) + .alias('router', 'route') + } + + /** + * Returns the encrypter instance. + */ + private encrypter (): Encrypter { + return this.app().make('encryption') } /** diff --git a/packages/http/src/routing/router.ts b/packages/http/src/routing/router.ts index fd4315e7..e89eef47 100644 --- a/packages/http/src/routing/router.ts +++ b/packages/http/src/routing/router.ts @@ -13,7 +13,7 @@ import { HandleErrorMiddleware } from '../middleware/handle-error.js' import { HttpContext, HttpRedirect, Response } from '../server/index.js' import KoaRouter, { RouterContext, Middleware as KoaMiddleware } from '@koa/router' import { Class, isConstructor, isFunction, isNotConstructor } from '@supercharge/classes' -import { HttpRouter, RouteHandler, RouteAttributes, HttpMethods, MiddlewareCtor, NextHandler, Middleware, Application, HttpConfig } from '@supercharge/contracts' +import { HttpRouter, RouteHandler, RouteAttributes, HttpMethods, MiddlewareCtor, NextHandler, Middleware, Application, HttpConfig, type Encrypter } from '@supercharge/contracts' export class Router implements HttpRouter { private readonly meta: { @@ -22,6 +22,11 @@ export class Router implements HttpRouter { */ app: Application + /** + * Stores the encrypter instance. + */ + encryption: Encrypter + /** * Stores the HTTP configuration object. */ @@ -51,9 +56,10 @@ export class Router implements HttpRouter { /** * Create a new router instance. */ - constructor (app: Application, httpConfig: HttpConfig) { + constructor (app: Application, httpConfig: HttpConfig, encryption: Encrypter) { this.meta = { app, + encryption, httpConfig, groupStack: [], middleware: new Map(), @@ -69,6 +75,13 @@ export class Router implements HttpRouter { return this.meta.app } + /** + * Returns the encryption instance. + */ + encryption (): Encrypter { + return this.meta.encryption + } + /** * Returns the Koa router instance. */ @@ -251,7 +264,7 @@ export class Router implements HttpRouter { * Wrap the given Koa `ctx` into a Supercharge ctx. */ private createContext (ctx: any): HttpContext { - return HttpContext.wrap(ctx, this.app(), this.meta.httpConfig.cookie) + return HttpContext.wrap(ctx, this.app(), this.meta.httpConfig.cookie, this.encryption()) } /** diff --git a/packages/http/src/server/http-context.ts b/packages/http/src/server/http-context.ts index 267d6a55..4e1837c2 100644 --- a/packages/http/src/server/http-context.ts +++ b/packages/http/src/server/http-context.ts @@ -1,34 +1,40 @@ import { RouterContext } from '@koa/router' import { InteractsWithState } from './interacts-with-state.js' -import { Application, HttpContext as HttpContextContract, HttpRequest, HttpResponse, HttpResponseCtor, HttpRequestCtor, HttpConfig } from '@supercharge/contracts' +import { Application, HttpContext as HttpContextContract, HttpRequest, HttpResponse, HttpResponseCtor, HttpRequestCtor, HttpConfig, type Encrypter } from '@supercharge/contracts' export class HttpContext extends InteractsWithState implements HttpContextContract { /** - * The application instance. + * Stores the application instance. */ private readonly app: Application /** - * The cookie config object. + * Stores the encrypter instance. + */ + private readonly encryption: Encrypter + + /** + * Stores the cookie config object. */ private readonly cookieConfig: HttpConfig['cookie'] /** * Create a new HTTP context instance. */ - constructor (ctx: RouterContext, app: Application, cookieConfig: HttpConfig['cookie']) { + constructor (ctx: RouterContext, app: Application, cookieConfig: HttpConfig['cookie'], encryption: Encrypter) { super(ctx) this.app = app + this.encryption = encryption this.cookieConfig = cookieConfig } /** * Returns a wrapped HTTP context for the raw Koa HTTP `ctx`. */ - static wrap (ctx: RouterContext, app: Application, cookieConfig: HttpConfig['cookie']): HttpContext { - return new this(ctx, app, cookieConfig) + static wrap (ctx: RouterContext, app: Application, cookieConfig: HttpConfig['cookie'], encryption: Encrypter): HttpContext { + return new this(ctx, app, cookieConfig, encryption) } /** @@ -49,7 +55,7 @@ export class HttpContext extends InteractsWithState implements HttpContextContra */ const Request = this.app.make('request') - return new Request(this, this.cookieConfig) + return new Request(this, this.cookieConfig, this.encryption) } /** @@ -63,6 +69,6 @@ export class HttpContext extends InteractsWithState implements HttpContextContra */ const Response = this.app.make('response') - return new Response(this, this.cookieConfig) + return new Response(this, this.cookieConfig, this.encryption) } } diff --git a/packages/http/src/server/server.ts b/packages/http/src/server/server.ts index c7374c15..c90d757b 100644 --- a/packages/http/src/server/server.ts +++ b/packages/http/src/server/server.ts @@ -7,7 +7,7 @@ import { Server as NodeHttpServer } from 'node:http' import { BodyparserMiddleware } from '../middleware/index.js' import { className, isConstructor } from '@supercharge/classes' import { HandleErrorMiddleware } from '../middleware/handle-error.js' -import { Application, HttpServer as HttpServerContract, Middleware as MiddlewareContract, MiddlewareCtor, HttpRouter, HttpServerHandler, InlineMiddlewareHandler, ApplicationConfig, HttpConfig } from '@supercharge/contracts' +import { Application, HttpServer as HttpServerContract, Middleware as MiddlewareContract, MiddlewareCtor, HttpRouter, HttpServerHandler, InlineMiddlewareHandler, ApplicationConfig, HttpConfig, type Encrypter } from '@supercharge/contracts' type Callback = (server: Server) => unknown | Promise @@ -26,6 +26,11 @@ export class Server implements HttpServerContract { */ httpConfig: HttpConfig + /** + * The encrypter instance. + */ + encryption: Encrypter + /** * The Koa server instance. */ @@ -55,10 +60,11 @@ export class Server implements HttpServerContract { /** * Create a new HTTP context instance. */ - constructor (app: Application, appConfig: ApplicationConfig, httpConfig: HttpConfig) { + constructor (app: Application, appConfig: ApplicationConfig, httpConfig: HttpConfig, encryption: Encrypter) { this.meta = { app, httpConfig, + encryption, bootedCallbacks: [], isBootstrapped: false, koa: this.createKoaInstance(appConfig) @@ -162,6 +168,13 @@ export class Server implements HttpServerContract { return this.meta.app } + /** + * Returns the encrypter instance. + */ + encryption (): Encrypter { + return this.meta.encryption + } + /** * Determine whether the HTTP server is already boostrapped. */ @@ -292,7 +305,7 @@ export class Server implements HttpServerContract { * Wrap the given Koa `ctx` into a Supercharge context. */ private createContext (ctx: any): HttpContext { - return HttpContext.wrap(ctx, this.app(), this.cookieConfig()) + return HttpContext.wrap(ctx, this.app(), this.cookieConfig(), this.encryption()) } /** diff --git a/packages/logging/src/console-logger.ts b/packages/logging/src/console-logger.ts index c1012b12..cf53923e 100644 --- a/packages/logging/src/console-logger.ts +++ b/packages/logging/src/console-logger.ts @@ -64,7 +64,7 @@ export class ConsoleLogger extends Logger implements Loggi * error => bold red */ getColorForLevel (label: string): ChalkInstance { - return this.logColors()[label] || Chalk.white + return this.logColors()[label] ?? Chalk.white } /**