From 5e8d4075e3d69e4cd020dc1cd962ea4ca2e8771d Mon Sep 17 00:00:00 2001 From: AmauryD Date: Wed, 23 Nov 2022 21:01:49 +0100 Subject: [PATCH 1/7] continue splitting --- .jscpd.json | 2 +- .../src/errors/unknown-special-context.ts | 3 ++ packages/http/src/interfaces/resolver.ts | 4 ++ packages/http/src/routing/builder.ts | 27 ++++++++-- .../src/routing/controller-action-resolver.ts | 19 +++++++ .../http/src/routing/controller-action.ts | 54 +++++++------------ .../routing/executable-controller-action.ts | 18 +++++++ packages/http/src/routing/guard-resolver.ts | 10 +++- packages/http/src/routing/param-resolver.ts | 6 ++- .../src/routing/response-handler-resolver.ts | 21 ++++++-- .../http/src/storages/metadata/use-param.ts | 4 +- .../tests/unit/routing/action-builder.test.ts | 28 ++++++++-- .../tests/unit/routing/guard-resolver.test.ts | 12 +++-- .../routing/response-handler-resolver.test.ts | 34 ++++++++---- 14 files changed, 174 insertions(+), 68 deletions(-) create mode 100644 packages/http/src/errors/unknown-special-context.ts create mode 100644 packages/http/src/interfaces/resolver.ts create mode 100644 packages/http/src/routing/controller-action-resolver.ts create mode 100644 packages/http/src/routing/executable-controller-action.ts diff --git a/.jscpd.json b/.jscpd.json index 14b412db..feb9d976 100644 --- a/.jscpd.json +++ b/.jscpd.json @@ -7,5 +7,5 @@ "ignorePattern": [ "import .* from '.*';" ], - "pattern": ["packages/*/src/**/*.ts"] + "pattern": ["packages/*/{src,tests}/**/*.ts"] } \ No newline at end of file diff --git a/packages/http/src/errors/unknown-special-context.ts b/packages/http/src/errors/unknown-special-context.ts new file mode 100644 index 00000000..6404d8f1 --- /dev/null +++ b/packages/http/src/errors/unknown-special-context.ts @@ -0,0 +1,3 @@ +export class UnknownSpecialContextError extends Error { + public message = 'Unknown special context'; +} diff --git a/packages/http/src/interfaces/resolver.ts b/packages/http/src/interfaces/resolver.ts new file mode 100644 index 00000000..bbcfa940 --- /dev/null +++ b/packages/http/src/interfaces/resolver.ts @@ -0,0 +1,4 @@ + +export interface ResolverInterface { + resolve(...args: unknown[]): unknown, +} diff --git a/packages/http/src/routing/builder.ts b/packages/http/src/routing/builder.ts index 871f7b46..994e9744 100644 --- a/packages/http/src/routing/builder.ts +++ b/packages/http/src/routing/builder.ts @@ -8,6 +8,10 @@ import { allowedMethods } from '../utils/allowed-methods.js'; import { middlewaresInstancesForTarget } from '../utils/middlewares.js'; import type { RouterBuilderInterface } from '../interfaces/router-builder.js'; import type { RouteMetadataArgs } from '../storages/metadata/route.js'; +import { ControllerActionResolver } from './controller-action-resolver.js'; +import { GuardResolver } from './guard-resolver.js'; +import { ResponseHandlerResolver } from './response-handler-resolver.js'; +import type { ControllerContext } from '../types/controller-context.js'; @injectable() export class HttpBuilder implements RouterBuilderInterface { @@ -41,12 +45,29 @@ export class HttpBuilder implements RouterBuilderInterface { protected setupEndpoint (router:Router, endPointMeta: HttpEndpointMetadataArgs) { const endpointMiddlewares = middlewaresInstancesForTarget(this.context.meta.target.prototype, endPointMeta.propertyName); - const controllerActionBuilder = new ControllerActionBuilder({ + const controllerContext = this.createControllerContext(endPointMeta); + const controllerActionBuilder = this.createActionBuilder(controllerContext); + + router[endPointMeta.method](endPointMeta.args.routeName, ...endpointMiddlewares, controllerActionBuilder.build()); + } + + private createControllerContext (endPointMeta: HttpEndpointMetadataArgs): ControllerContext { + return { controllerInstance: this.context.instance, controllerAction: endPointMeta.propertyName - }, this.metadataStorage); + }; + } - router[endPointMeta.method](endPointMeta.args.routeName, ...endpointMiddlewares, controllerActionBuilder.build()); + private createActionBuilder (controllerContext: ControllerContext) { + const actionResolver = new ControllerActionResolver(this.metadataStorage, controllerContext); + const guardResolver = new GuardResolver(this.metadataStorage, controllerContext); + const responseHandlerResolver = new ResponseHandlerResolver(this.metadataStorage, controllerContext); + + return new ControllerActionBuilder( + guardResolver, + responseHandlerResolver, + actionResolver + ); } private setupEndpoints (endpointsMeta: HttpEndpointMetadataArgs[], controllerRouter: Router) { diff --git a/packages/http/src/routing/controller-action-resolver.ts b/packages/http/src/routing/controller-action-resolver.ts new file mode 100644 index 00000000..ab531fed --- /dev/null +++ b/packages/http/src/routing/controller-action-resolver.ts @@ -0,0 +1,19 @@ +import 'reflect-metadata'; +import type { MetadataStorageInterface } from '../interfaces/metadata-storage.js'; +import type { ResolverInterface } from '../interfaces/resolver.js'; +import type { ControllerContext } from '../types/controller-context.js'; +import { resolveParams } from '../utils/resolve-params.js'; +import { ExecutableControllerAction } from './executable-controller-action.js'; + +export class ControllerActionResolver implements ResolverInterface { + public constructor ( + public metadataStorage: MetadataStorageInterface, + public controllerContext: ControllerContext + ) {} + + public resolve (): ExecutableControllerAction { + const paramsForRouteMetadata = this.metadataStorage.sortedParametersForEndpoint(this.controllerContext.controllerInstance.constructor, this.controllerContext.controllerAction); + const handles = resolveParams(paramsForRouteMetadata, this.controllerContext); + return new ExecutableControllerAction(this.controllerContext, handles); + } +} diff --git a/packages/http/src/routing/controller-action.ts b/packages/http/src/routing/controller-action.ts index 6ea8b4ed..affcf53b 100644 --- a/packages/http/src/routing/controller-action.ts +++ b/packages/http/src/routing/controller-action.ts @@ -1,14 +1,11 @@ import type { RouterContext } from '@koa/router'; import type { Next } from 'koa'; -import type { MetadataStorage } from '../storages/metadata-storage.js'; -import type { UseParamsMetadataArgs } from '../storages/metadata/use-param.js'; -import type { ControllerContext } from '../types/controller-context.js'; -import { executeParams } from '../utils/execute-params.js'; -import { resolveParams } from '../utils/resolve-params.js'; +import type { ControllerActionResolver } from './controller-action-resolver.js'; +import type { ExecutableControllerAction } from './executable-controller-action.js'; import type { ExecutableGuard } from './executable-guard.js'; import type { ExecutableResponseHandler } from './executable-response-handler.js'; -import { GuardResolver } from './guard-resolver.js'; -import { ResponseHandlerResolver } from './response-handler-resolver.js'; +import type { GuardResolver } from './guard-resolver.js'; +import type { ResponseHandlerResolver } from './response-handler-resolver.js'; async function executeGuards (guardsInstance: ExecutableGuard[], ctx: RouterContext) { for (const guard of guardsInstance) { @@ -17,39 +14,30 @@ async function executeGuards (guardsInstance: ExecutableGuard[], ctx: RouterCont } export class ControllerActionBuilder { - private guardResolver: GuardResolver; - private responseHandlerResolver: ResponseHandlerResolver; - public constructor ( - public context: ControllerContext, - public metadataStorage: MetadataStorage - ) { - this.guardResolver = new GuardResolver(this.metadataStorage, this.context); - this.responseHandlerResolver = new ResponseHandlerResolver(this.metadataStorage, this.context); - } + public guardResolver: GuardResolver, + public responseHandlerResolver: ResponseHandlerResolver, + public controllerActionResolver: ControllerActionResolver + ) {} public build () { - const paramsForRouteMetadata: UseParamsMetadataArgs[] = this.metadataStorage.sortedParametersForEndpoint(this.context.controllerInstance.constructor, this.context.controllerAction); - const responsehandlerForRouteMetadata = this.metadataStorage.getClosestResponseHandlerForEndpoint(this.context.controllerInstance.constructor, this.context.controllerAction); - const guardsForRouteMetadata = this.metadataStorage.getGuardsForEndpoint(this.context.controllerInstance.constructor, this.context.controllerAction); - return this.controllerActionMiddleware( - guardsForRouteMetadata.map((meta) => this.guardResolver.resolve(meta)), - responsehandlerForRouteMetadata - ? this.responseHandlerResolver.resolve(responsehandlerForRouteMetadata) - : responsehandlerForRouteMetadata, - paramsForRouteMetadata + this.controllerActionResolver.resolve(), + this.guardResolver.resolve(), + this.responseHandlerResolver.resolve() ); } - private controllerActionMiddleware (executableGuards: ExecutableGuard[], - executableResponseHandler: ExecutableResponseHandler | undefined, paramsForRouteMetadata:UseParamsMetadataArgs[]) { - const controllerMethod = (this.context.controllerInstance as any)[this.context.controllerAction] as Function; - + // eslint-disable-next-line class-methods-use-this + private controllerActionMiddleware ( + executableControllerAction: ExecutableControllerAction, + executableGuards: ExecutableGuard[], + executableResponseHandler: ExecutableResponseHandler | undefined + ) { return async (ctx: RouterContext, _next: Next) => { await executeGuards(executableGuards, ctx); - const controllerActionResult = await this.executeControllerAction(ctx, paramsForRouteMetadata, controllerMethod); + const controllerActionResult = await executableControllerAction.execute(ctx); if (executableResponseHandler) { return executableResponseHandler.execute(controllerActionResult, ctx); @@ -58,10 +46,4 @@ export class ControllerActionBuilder { ctx.response.body = controllerActionResult; }; } - - private async executeControllerAction (ctx: RouterContext, paramsForRouteMetadata: UseParamsMetadataArgs[], controllerMethod: Function) { - const resolvedParams = await executeParams(resolveParams(paramsForRouteMetadata, this.context), ctx); - - return controllerMethod.call(this.context.controllerInstance, ...resolvedParams); - } } diff --git a/packages/http/src/routing/executable-controller-action.ts b/packages/http/src/routing/executable-controller-action.ts new file mode 100644 index 00000000..7b6f5dff --- /dev/null +++ b/packages/http/src/routing/executable-controller-action.ts @@ -0,0 +1,18 @@ +import type { RouterContext } from '@koa/router'; +import type { ControllerContext } from '../types/controller-context.js'; +import { executeParams } from '../utils/execute-params.js'; +import type { ExecutableParam } from './executable-param.js'; + +export class ExecutableControllerAction { + public constructor ( + public controllerContext: ControllerContext, + public params: ExecutableParam[] + ) {} + + public async execute (ctx: RouterContext) { + const controllerMethod = (this.controllerContext.controllerInstance as any)[this.controllerContext.controllerAction] as Function; + const params = await executeParams(this.params, ctx); + + return controllerMethod.call(this.controllerContext.controllerInstance, ...params); + } +} diff --git a/packages/http/src/routing/guard-resolver.ts b/packages/http/src/routing/guard-resolver.ts index 10d02c29..cd09dea8 100644 --- a/packages/http/src/routing/guard-resolver.ts +++ b/packages/http/src/routing/guard-resolver.ts @@ -1,6 +1,7 @@ import { container } from '@triptyk/nfw-core'; import 'reflect-metadata'; import type { MetadataStorageInterface } from '../interfaces/metadata-storage.js'; +import type { ResolverInterface } from '../interfaces/resolver.js'; import type { UseGuardMetadataArgs } from '../storages/metadata/use-guard.js'; import type { ParamsHandleFunction } from '../storages/metadata/use-param.js'; import type { ControllerContext } from '../types/controller-context.js'; @@ -9,13 +10,18 @@ import { ExecutableGuard } from './executable-guard.js'; export type ResolvedParam = ControllerContext | unknown[] | ParamsHandleFunction; -export class GuardResolver { +export class GuardResolver implements ResolverInterface { public constructor ( public metadataStorage: MetadataStorageInterface, public controllerContext: ControllerContext ) {} - public resolve (guardUsageMeta: UseGuardMetadataArgs): ExecutableGuard { + public resolve (): ExecutableGuard[] { + const guardUsageMetas = this.metadataStorage.getGuardsForEndpoint(this.controllerContext.controllerInstance.constructor, this.controllerContext.controllerAction); + return guardUsageMetas.map((guardUsageMeta) => this.resolveOneGuard(guardUsageMeta)); + } + + private resolveOneGuard (guardUsageMeta: UseGuardMetadataArgs) { const paramsForGuardMetadata = this.metadataStorage.sortedParametersForTarget(guardUsageMeta.guard); const handles = resolveParams(paramsForGuardMetadata, this.controllerContext); const guardInstance = container.resolve(guardUsageMeta.guard); diff --git a/packages/http/src/routing/param-resolver.ts b/packages/http/src/routing/param-resolver.ts index 4b11a513..71d91172 100644 --- a/packages/http/src/routing/param-resolver.ts +++ b/packages/http/src/routing/param-resolver.ts @@ -1,8 +1,10 @@ import type { ControllerContext } from '../types/controller-context.js'; import type { ParamsHandleFunction, UseParamsMetadataArgs } from '../storages/metadata/use-param.js'; import { ExecutableParam } from './executable-param.js'; +import type { ResolverInterface } from '../interfaces/resolver.js'; +import { UnknownSpecialContextError } from '../errors/unknown-special-context.js'; -export class ParamResolver { +export class ParamResolver implements ResolverInterface { public constructor ( public handle: UseParamsMetadataArgs['handle'], public controllerContext: ControllerContext @@ -26,6 +28,6 @@ export class ParamResolver { if (this.handle === 'controller-context') { return this.controllerContext; } - throw new Error(); + throw new UnknownSpecialContextError(`${this.handle} is an unknown special context`); } } diff --git a/packages/http/src/routing/response-handler-resolver.ts b/packages/http/src/routing/response-handler-resolver.ts index 4f992dfe..d00f5985 100644 --- a/packages/http/src/routing/response-handler-resolver.ts +++ b/packages/http/src/routing/response-handler-resolver.ts @@ -1,20 +1,31 @@ import { container } from '@triptyk/nfw-core'; import type { MetadataStorageInterface } from '../interfaces/metadata-storage.js'; +import type { ResolverInterface } from '../interfaces/resolver.js'; import type { UseResponseHandlerMetadataArgs } from '../storages/metadata/use-response-handler.js'; import type { ControllerContext } from '../types/controller-context.js'; import { resolveParams } from '../utils/resolve-params.js'; import { ExecutableResponseHandler } from './executable-response-handler.js'; -export class ResponseHandlerResolver { +export class ResponseHandlerResolver implements ResolverInterface { public constructor ( public metadataStorage: MetadataStorageInterface, public controllerContext: ControllerContext ) {} - public resolve (responseHandlerUseMeta: UseResponseHandlerMetadataArgs): ExecutableResponseHandler { - const paramsMetadata = this.metadataStorage.sortedParametersForTarget(responseHandlerUseMeta.responseHandler); - const handles = resolveParams(paramsMetadata, this.controllerContext); - const responseHandlerInstance = container.resolve(responseHandlerUseMeta.responseHandler); + public resolve (): ExecutableResponseHandler | undefined { + const responsehandlerForRouteMetadata = this.metadataStorage.getClosestResponseHandlerForEndpoint(this.controllerContext.controllerInstance.constructor, this.controllerContext.controllerAction); + + if (!responsehandlerForRouteMetadata) { + return; + } + + const handles = this.resolveParams(responsehandlerForRouteMetadata); + const responseHandlerInstance = container.resolve(responsehandlerForRouteMetadata.responseHandler); return new ExecutableResponseHandler(responseHandlerInstance, this.controllerContext, handles); } + + private resolveParams (responsehandlerForRouteMetadata: UseResponseHandlerMetadataArgs) { + const paramsMetadata = this.metadataStorage.sortedParametersForTarget(responsehandlerForRouteMetadata.responseHandler); + return resolveParams(paramsMetadata, this.controllerContext); + } } diff --git a/packages/http/src/storages/metadata/use-param.ts b/packages/http/src/storages/metadata/use-param.ts index b0616770..5b9c36dc 100644 --- a/packages/http/src/storages/metadata/use-param.ts +++ b/packages/http/src/storages/metadata/use-param.ts @@ -6,6 +6,8 @@ export interface ControllerParamsContext extends ControllerContext { ctx: RouterContext, } +export type SpecialContextStrings = 'args' | 'controller-context'; + export type ParamsHandleFunction = ((ctx: ControllerParamsContext) => Promise | unknown); export interface UseParamsMetadataArgs { @@ -13,6 +15,6 @@ export interface UseParamsMetadataArgs { target: any, propertyName: string, index: number, - handle: ParamsHandleFunction | 'args' | 'controller-context', + handle: ParamsHandleFunction | SpecialContextStrings, args: unknown[], } diff --git a/packages/http/tests/unit/routing/action-builder.test.ts b/packages/http/tests/unit/routing/action-builder.test.ts index 2e8119bc..12f6747e 100644 --- a/packages/http/tests/unit/routing/action-builder.test.ts +++ b/packages/http/tests/unit/routing/action-builder.test.ts @@ -8,6 +8,10 @@ import { MetadataStorage } from '../../../src/storages/metadata-storage.js'; import { createKoaContext } from '../../mocks/koa-context.js'; import type { GuardInterface, ResponseHandlerInterface } from '../../../src/index.js'; import { ForbiddenError } from '../../../src/errors/forbidden.js'; +import { ControllerActionResolver } from '../../../src/routing/controller-action-resolver.js'; +import { GuardResolver } from '../../../src/routing/guard-resolver.js'; +import { ResponseHandlerResolver } from '../../../src/routing/response-handler-resolver.js'; +import type { ControllerContext } from '../../../src/types/controller-context.js'; describe('Action builder', () => { let instance: Controller; @@ -19,13 +23,29 @@ describe('Action builder', () => { public list = listFn; } + function createControllerContext () { + return { + controllerAction: 'list', + controllerInstance: instance + }; + } + + function createActionBuilder (controllerContext: ControllerContext) { + const actionResolver = new ControllerActionResolver(storage, controllerContext); + const guardResolver = new GuardResolver(storage, controllerContext); + const responseHandlerResolver = new ResponseHandlerResolver(storage, controllerContext); + + return new ControllerActionBuilder( + guardResolver, + responseHandlerResolver, + actionResolver + ); + } + beforeEach(() => { instance = new Controller(); storage = new MetadataStorage(); - actionBuilder = new ControllerActionBuilder({ - controllerAction: 'list', - controllerInstance: instance - }, storage); + actionBuilder = createActionBuilder(createControllerContext()); }); it('Builds a middleware that executes controller action', async () => { diff --git a/packages/http/tests/unit/routing/guard-resolver.test.ts b/packages/http/tests/unit/routing/guard-resolver.test.ts index a0036c31..c0f0f424 100644 --- a/packages/http/tests/unit/routing/guard-resolver.test.ts +++ b/packages/http/tests/unit/routing/guard-resolver.test.ts @@ -30,17 +30,21 @@ describe('Guard builder', () => { test('It returns an executableGuard instance', () => { const storage = new MetadataStorage(); - const meta = setupGuardMetaInStorage(Controller, Guard, storage); + setupGuardMetaInStorage(Controller, Guard, storage); const guardBuilder = new GuardResolver( storage, { controllerAction: 'nona', - controllerInstance: new class {}() + controllerInstance: new Controller() } ); - const resolved = guardBuilder.resolve(meta); + const resolved = guardBuilder.resolve(); - expect(resolved).toBeInstanceOf(ExecutableGuard); + expect(resolved).toBeInstanceOf(Array); + expect(resolved.length).toStrictEqual(1); + for (const guard of resolved) { + expect(guard).toBeInstanceOf(ExecutableGuard); + } }); }); diff --git a/packages/http/tests/unit/routing/response-handler-resolver.test.ts b/packages/http/tests/unit/routing/response-handler-resolver.test.ts index a833b0ad..b8dfd268 100644 --- a/packages/http/tests/unit/routing/response-handler-resolver.test.ts +++ b/packages/http/tests/unit/routing/response-handler-resolver.test.ts @@ -3,42 +3,56 @@ import 'reflect-metadata'; import type { Class } from 'type-fest'; -import type { ResponseHandlerInterface } from '../../../src/index.js'; +import type { MetadataStorageInterface, ResponseHandlerInterface } from '../../../src/index.js'; import { ExecutableResponseHandler } from '../../../src/routing/executable-response-handler.js'; import { ResponseHandlerResolver } from '../../../src/routing/response-handler-resolver.js'; import { MetadataStorage } from '../../../src/storages/metadata-storage.js'; describe('Response handler resolver', () => { + let storage: MetadataStorageInterface; + class Controller {} class ResponseHandler implements ResponseHandlerInterface { // eslint-disable-next-line class-methods-use-this public handle () {} } - function setupGuardMetaInStorage (Controller: Class, responseHandler: Class, storage: MetadataStorage) { + function setupResponseHandlerMetaInStorage (Controller: Class, responseHandler: Class, storage: MetadataStorageInterface) { const meta = { target: Controller, responseHandler, args: ['blah'] }; - storage.useResponseHandlers.push(meta); + storage.addResponseHandlerUsage(meta); return meta; } - test('It returns an executableGuard instance', () => { - const storage = new MetadataStorage(); - const meta = setupGuardMetaInStorage(Controller, ResponseHandler, storage); - - const guardBuilder = new ResponseHandlerResolver( + function createResolver () { + return new ResponseHandlerResolver( storage, { controllerAction: 'nona', - controllerInstance: new class {}() + controllerInstance: new Controller() } ); - const resolved = guardBuilder.resolve(meta); + } + + beforeEach(() => { + storage = new MetadataStorage(); + }); + + test('It returns an executableResponseHandler instance when response-handler is in the storage', () => { + setupResponseHandlerMetaInStorage(Controller, ResponseHandler, storage); + const responseHandlerResolver = createResolver(); + const resolved = responseHandlerResolver.resolve(); expect(resolved).toBeInstanceOf(ExecutableResponseHandler); }); + + test('It returns undefined when nothing is in storage', () => { + const responseHandlerResolver = createResolver(); + const resolved = responseHandlerResolver.resolve(); + expect(resolved).toBeUndefined(); + }); }); From f882e4356e7a8f3471e28160793406fd94b1a733 Mon Sep 17 00:00:00 2001 From: AmauryD Date: Wed, 23 Nov 2022 21:14:31 +0100 Subject: [PATCH 2/7] move files --- .../http/src/decorators/use-middleware.ts | 4 ++-- .../executable-controller-action.ts | 4 ++-- .../executable-guard.ts | 4 ++-- .../executable-param.ts | 8 +++---- .../executable-response-handler.ts | 4 ++-- .../{application.ts => create-application.ts} | 2 +- packages/http/src/index.ts | 22 ++++++++++++++----- .../controller-action-resolver.ts | 6 ++--- .../{routing => resolvers}/guard-resolver.ts | 9 +++----- .../{routing => resolvers}/param-resolver.ts | 7 +++--- .../response-handler-resolver.ts | 6 ++--- packages/http/src/routing/builder.ts | 13 ++++++----- .../http/src/routing/controller-action.ts | 12 +++++----- .../router-builder.ts} | 0 .../src/storages/metadata/use-middleware.ts | 4 ++-- .../http/src/storages/metadata/use-param.ts | 4 ++-- packages/http/src/types/any-middleware.ts | 2 +- packages/http/src/types/controller-context.ts | 2 +- packages/http/src/types/resolved-param.ts | 4 ++++ packages/http/src/utils/execute-params.ts | 2 +- packages/http/src/utils/middlewares.ts | 4 ++-- packages/http/src/utils/resolve-params.ts | 7 +++--- .../tests/unit/create-application.test.ts | 2 +- .../tests/unit/routing/action-builder.test.ts | 10 ++++----- .../unit/routing/executable-guard.test.ts | 3 +-- .../unit/routing/executable-param.test.ts | 10 ++++----- .../executable-response-handler.test.ts | 6 ++--- .../tests/unit/routing/guard-resolver.test.ts | 5 +++-- .../tests/unit/routing/param-resolver.test.ts | 3 +-- .../routing/response-handler-resolver.test.ts | 4 ++-- 30 files changed, 93 insertions(+), 80 deletions(-) rename packages/http/src/{routing => executables}/executable-controller-action.ts (82%) rename packages/http/src/{routing => executables}/executable-guard.ts (83%) rename packages/http/src/{routing => executables}/executable-param.ts (57%) rename packages/http/src/{routing => executables}/executable-response-handler.ts (82%) rename packages/http/src/factories/{application.ts => create-application.ts} (89%) rename packages/http/src/{routing => resolvers}/controller-action-resolver.ts (78%) rename packages/http/src/{routing => resolvers}/guard-resolver.ts (77%) rename packages/http/src/{routing => resolvers}/param-resolver.ts (84%) rename packages/http/src/{routing => resolvers}/response-handler-resolver.ts (86%) rename packages/http/src/{factories/controller.ts => routing/router-builder.ts} (100%) create mode 100644 packages/http/src/types/resolved-param.ts diff --git a/packages/http/src/decorators/use-middleware.ts b/packages/http/src/decorators/use-middleware.ts index ab4e9c7d..b9423411 100644 --- a/packages/http/src/decorators/use-middleware.ts +++ b/packages/http/src/decorators/use-middleware.ts @@ -2,9 +2,9 @@ import { container } from '@triptyk/nfw-core'; import type { Class } from 'type-fest'; import { MetadataStorage } from '../storages/metadata-storage.js'; -import type { AnyMiddleware } from '../types/any-middleware.js'; +import type { AnyMiddlewareType } from '../types/any-middleware.js'; -export function UseMiddleware (middleware: AnyMiddleware) { +export function UseMiddleware (middleware: AnyMiddlewareType) { return function (target: Class | unknown, propertyName?: string) { container.resolve(MetadataStorage).addMiddlewareUsage({ target, diff --git a/packages/http/src/routing/executable-controller-action.ts b/packages/http/src/executables/executable-controller-action.ts similarity index 82% rename from packages/http/src/routing/executable-controller-action.ts rename to packages/http/src/executables/executable-controller-action.ts index 7b6f5dff..81653197 100644 --- a/packages/http/src/routing/executable-controller-action.ts +++ b/packages/http/src/executables/executable-controller-action.ts @@ -1,11 +1,11 @@ import type { RouterContext } from '@koa/router'; -import type { ControllerContext } from '../types/controller-context.js'; +import type { ControllerContextType } from '../types/controller-context.js'; import { executeParams } from '../utils/execute-params.js'; import type { ExecutableParam } from './executable-param.js'; export class ExecutableControllerAction { public constructor ( - public controllerContext: ControllerContext, + public controllerContext: ControllerContextType, public params: ExecutableParam[] ) {} diff --git a/packages/http/src/routing/executable-guard.ts b/packages/http/src/executables/executable-guard.ts similarity index 83% rename from packages/http/src/routing/executable-guard.ts rename to packages/http/src/executables/executable-guard.ts index 599d5359..18bb1fff 100644 --- a/packages/http/src/routing/executable-guard.ts +++ b/packages/http/src/executables/executable-guard.ts @@ -1,14 +1,14 @@ import type { RouterContext } from '@koa/router'; import { ForbiddenError } from '../errors/forbidden.js'; import type { GuardInterface } from '../interfaces/guard.js'; -import type { ControllerContext } from '../types/controller-context.js'; +import type { ControllerContextType } from '../types/controller-context.js'; import { executeParams } from '../utils/execute-params.js'; import type { ExecutableParam } from './executable-param.js'; export class ExecutableGuard { public constructor ( public instance: GuardInterface, - public controllerContext: ControllerContext, + public controllerContext: ControllerContextType, public params: ExecutableParam[] ) {} diff --git a/packages/http/src/routing/executable-param.ts b/packages/http/src/executables/executable-param.ts similarity index 57% rename from packages/http/src/routing/executable-param.ts rename to packages/http/src/executables/executable-param.ts index 077c0e60..9ec8b368 100644 --- a/packages/http/src/routing/executable-param.ts +++ b/packages/http/src/executables/executable-param.ts @@ -1,11 +1,11 @@ import type { RouterContext } from '@koa/router'; -import type { ControllerContext } from '../types/controller-context.js'; -import type { ResolvedParam } from './guard-resolver.js'; +import type { ControllerContextType } from '../types/controller-context.js'; +import type { ResolvedParamType } from '../types/resolved-param.js'; export class ExecutableParam { public constructor ( - public controllerContext: ControllerContext, - private param: ResolvedParam + public controllerContext: ControllerContextType, + private param: ResolvedParamType ) {} public execute (ctx: RouterContext) { diff --git a/packages/http/src/routing/executable-response-handler.ts b/packages/http/src/executables/executable-response-handler.ts similarity index 82% rename from packages/http/src/routing/executable-response-handler.ts rename to packages/http/src/executables/executable-response-handler.ts index 50b8d51b..44ba3fed 100644 --- a/packages/http/src/routing/executable-response-handler.ts +++ b/packages/http/src/executables/executable-response-handler.ts @@ -1,13 +1,13 @@ import type { RouterContext } from '@koa/router'; import type { ResponseHandlerInterface } from '../interfaces/response-handler.js'; -import type { ControllerContext } from '../types/controller-context.js'; +import type { ControllerContextType } from '../types/controller-context.js'; import { executeParams } from '../utils/execute-params.js'; import type { ExecutableParam } from './executable-param.js'; export class ExecutableResponseHandler { public constructor ( public instance: ResponseHandlerInterface, - public controllerContext: ControllerContext, + public controllerContext: ControllerContextType, public params: ExecutableParam[] ) {} diff --git a/packages/http/src/factories/application.ts b/packages/http/src/factories/create-application.ts similarity index 89% rename from packages/http/src/factories/application.ts rename to packages/http/src/factories/create-application.ts index b1e2a815..4df5e3a5 100644 --- a/packages/http/src/factories/application.ts +++ b/packages/http/src/factories/create-application.ts @@ -1,5 +1,5 @@ import type Koa from 'koa'; -import { RouterBuilderFactory } from './controller.js'; +import { RouterBuilderFactory } from '../routing/router-builder.js'; import type { Class } from 'type-fest'; import { container } from '@triptyk/nfw-core'; import { MetadataStorage } from '../storages/metadata-storage.js'; diff --git a/packages/http/src/index.ts b/packages/http/src/index.ts index b76a1cb4..ff63f26e 100644 --- a/packages/http/src/index.ts +++ b/packages/http/src/index.ts @@ -9,14 +9,18 @@ export * from './decorators/use-middleware.js'; export * from './storages/metadata/endpoint.js'; +export * from './types/any-middleware.js'; +export * from './types/controller-context.js'; +export * from './types/resolved-param.js'; + export * from './interfaces/middleware.js'; export * from './interfaces/response-handler.js'; export * from './interfaces/guard.js'; export * from './interfaces/router-builder.js'; export * from './interfaces/metadata-storage.js'; -export * from './factories/application.js'; -export * from './factories/controller.js'; +export * from './factories/create-application.js'; +export * from './routing/router-builder.js'; export * from './utils/custom-decorator.js'; export * from './utils/execute-params.js'; @@ -41,10 +45,16 @@ export * from './errors/forbidden.js'; export * from './errors/router-metadata-not-found.js'; export * from './routing/controller-action.js'; -export * from './routing/param-resolver.js'; -export * from './routing/executable-guard.js'; -export * from './routing/executable-param.js'; -export * from './routing/executable-response-handler.js'; + +export * from './resolvers/controller-action-resolver.js'; +export * from './resolvers/guard-resolver.js'; +export * from './resolvers/param-resolver.js'; +export * from './resolvers/response-handler-resolver.js'; + +export * from './executables/executable-controller-action.js'; +export * from './executables/executable-guard.js'; +export * from './executables/executable-param.js'; +export * from './executables/executable-response-handler.js'; export * from './enums/http-method.js'; diff --git a/packages/http/src/routing/controller-action-resolver.ts b/packages/http/src/resolvers/controller-action-resolver.ts similarity index 78% rename from packages/http/src/routing/controller-action-resolver.ts rename to packages/http/src/resolvers/controller-action-resolver.ts index ab531fed..5895c60c 100644 --- a/packages/http/src/routing/controller-action-resolver.ts +++ b/packages/http/src/resolvers/controller-action-resolver.ts @@ -1,14 +1,14 @@ import 'reflect-metadata'; import type { MetadataStorageInterface } from '../interfaces/metadata-storage.js'; import type { ResolverInterface } from '../interfaces/resolver.js'; -import type { ControllerContext } from '../types/controller-context.js'; +import type { ControllerContextType } from '../types/controller-context.js'; import { resolveParams } from '../utils/resolve-params.js'; -import { ExecutableControllerAction } from './executable-controller-action.js'; +import { ExecutableControllerAction } from '../executables/executable-controller-action.js'; export class ControllerActionResolver implements ResolverInterface { public constructor ( public metadataStorage: MetadataStorageInterface, - public controllerContext: ControllerContext + public controllerContext: ControllerContextType ) {} public resolve (): ExecutableControllerAction { diff --git a/packages/http/src/routing/guard-resolver.ts b/packages/http/src/resolvers/guard-resolver.ts similarity index 77% rename from packages/http/src/routing/guard-resolver.ts rename to packages/http/src/resolvers/guard-resolver.ts index cd09dea8..f19ece73 100644 --- a/packages/http/src/routing/guard-resolver.ts +++ b/packages/http/src/resolvers/guard-resolver.ts @@ -1,19 +1,16 @@ import { container } from '@triptyk/nfw-core'; import 'reflect-metadata'; +import { ExecutableGuard } from '../executables/executable-guard.js'; import type { MetadataStorageInterface } from '../interfaces/metadata-storage.js'; import type { ResolverInterface } from '../interfaces/resolver.js'; import type { UseGuardMetadataArgs } from '../storages/metadata/use-guard.js'; -import type { ParamsHandleFunction } from '../storages/metadata/use-param.js'; -import type { ControllerContext } from '../types/controller-context.js'; +import type { ControllerContextType } from '../types/controller-context.js'; import { resolveParams } from '../utils/resolve-params.js'; -import { ExecutableGuard } from './executable-guard.js'; - -export type ResolvedParam = ControllerContext | unknown[] | ParamsHandleFunction; export class GuardResolver implements ResolverInterface { public constructor ( public metadataStorage: MetadataStorageInterface, - public controllerContext: ControllerContext + public controllerContext: ControllerContextType ) {} public resolve (): ExecutableGuard[] { diff --git a/packages/http/src/routing/param-resolver.ts b/packages/http/src/resolvers/param-resolver.ts similarity index 84% rename from packages/http/src/routing/param-resolver.ts rename to packages/http/src/resolvers/param-resolver.ts index 71d91172..2f4d1d58 100644 --- a/packages/http/src/routing/param-resolver.ts +++ b/packages/http/src/resolvers/param-resolver.ts @@ -1,13 +1,14 @@ -import type { ControllerContext } from '../types/controller-context.js'; +import type { ControllerContextType } from '../types/controller-context.js'; import type { ParamsHandleFunction, UseParamsMetadataArgs } from '../storages/metadata/use-param.js'; -import { ExecutableParam } from './executable-param.js'; + import type { ResolverInterface } from '../interfaces/resolver.js'; import { UnknownSpecialContextError } from '../errors/unknown-special-context.js'; +import { ExecutableParam } from '../executables/executable-param.js'; export class ParamResolver implements ResolverInterface { public constructor ( public handle: UseParamsMetadataArgs['handle'], - public controllerContext: ControllerContext + public controllerContext: ControllerContextType ) {} public resolve (contextArgs: unknown[]) : ExecutableParam { diff --git a/packages/http/src/routing/response-handler-resolver.ts b/packages/http/src/resolvers/response-handler-resolver.ts similarity index 86% rename from packages/http/src/routing/response-handler-resolver.ts rename to packages/http/src/resolvers/response-handler-resolver.ts index d00f5985..c6b59f4c 100644 --- a/packages/http/src/routing/response-handler-resolver.ts +++ b/packages/http/src/resolvers/response-handler-resolver.ts @@ -1,15 +1,15 @@ import { container } from '@triptyk/nfw-core'; +import { ExecutableResponseHandler } from '../executables/executable-response-handler.js'; import type { MetadataStorageInterface } from '../interfaces/metadata-storage.js'; import type { ResolverInterface } from '../interfaces/resolver.js'; import type { UseResponseHandlerMetadataArgs } from '../storages/metadata/use-response-handler.js'; -import type { ControllerContext } from '../types/controller-context.js'; +import type { ControllerContextType } from '../types/controller-context.js'; import { resolveParams } from '../utils/resolve-params.js'; -import { ExecutableResponseHandler } from './executable-response-handler.js'; export class ResponseHandlerResolver implements ResolverInterface { public constructor ( public metadataStorage: MetadataStorageInterface, - public controllerContext: ControllerContext + public controllerContext: ControllerContextType ) {} public resolve (): ExecutableResponseHandler | undefined { diff --git a/packages/http/src/routing/builder.ts b/packages/http/src/routing/builder.ts index 994e9744..f3cd96a2 100644 --- a/packages/http/src/routing/builder.ts +++ b/packages/http/src/routing/builder.ts @@ -8,10 +8,11 @@ import { allowedMethods } from '../utils/allowed-methods.js'; import { middlewaresInstancesForTarget } from '../utils/middlewares.js'; import type { RouterBuilderInterface } from '../interfaces/router-builder.js'; import type { RouteMetadataArgs } from '../storages/metadata/route.js'; -import { ControllerActionResolver } from './controller-action-resolver.js'; -import { GuardResolver } from './guard-resolver.js'; -import { ResponseHandlerResolver } from './response-handler-resolver.js'; -import type { ControllerContext } from '../types/controller-context.js'; +import { ControllerActionResolver } from '../resolvers/controller-action-resolver.js'; + +import type { ControllerContextType } from '../types/controller-context.js'; +import { GuardResolver } from '../resolvers/guard-resolver.js'; +import { ResponseHandlerResolver } from '../resolvers/response-handler-resolver.js'; @injectable() export class HttpBuilder implements RouterBuilderInterface { @@ -51,14 +52,14 @@ export class HttpBuilder implements RouterBuilderInterface { router[endPointMeta.method](endPointMeta.args.routeName, ...endpointMiddlewares, controllerActionBuilder.build()); } - private createControllerContext (endPointMeta: HttpEndpointMetadataArgs): ControllerContext { + private createControllerContext (endPointMeta: HttpEndpointMetadataArgs): ControllerContextType { return { controllerInstance: this.context.instance, controllerAction: endPointMeta.propertyName }; } - private createActionBuilder (controllerContext: ControllerContext) { + private createActionBuilder (controllerContext: ControllerContextType) { const actionResolver = new ControllerActionResolver(this.metadataStorage, controllerContext); const guardResolver = new GuardResolver(this.metadataStorage, controllerContext); const responseHandlerResolver = new ResponseHandlerResolver(this.metadataStorage, controllerContext); diff --git a/packages/http/src/routing/controller-action.ts b/packages/http/src/routing/controller-action.ts index affcf53b..4f6ce194 100644 --- a/packages/http/src/routing/controller-action.ts +++ b/packages/http/src/routing/controller-action.ts @@ -1,11 +1,11 @@ import type { RouterContext } from '@koa/router'; import type { Next } from 'koa'; -import type { ControllerActionResolver } from './controller-action-resolver.js'; -import type { ExecutableControllerAction } from './executable-controller-action.js'; -import type { ExecutableGuard } from './executable-guard.js'; -import type { ExecutableResponseHandler } from './executable-response-handler.js'; -import type { GuardResolver } from './guard-resolver.js'; -import type { ResponseHandlerResolver } from './response-handler-resolver.js'; +import type { ControllerActionResolver } from '../resolvers/controller-action-resolver.js'; +import type { ExecutableControllerAction } from '../executables/executable-controller-action.js'; +import type { ExecutableGuard } from '../executables/executable-guard.js'; +import type { ExecutableResponseHandler } from '../executables/executable-response-handler.js'; +import type { GuardResolver } from '../resolvers/guard-resolver.js'; +import type { ResponseHandlerResolver } from '../resolvers/response-handler-resolver.js'; async function executeGuards (guardsInstance: ExecutableGuard[], ctx: RouterContext) { for (const guard of guardsInstance) { diff --git a/packages/http/src/factories/controller.ts b/packages/http/src/routing/router-builder.ts similarity index 100% rename from packages/http/src/factories/controller.ts rename to packages/http/src/routing/router-builder.ts diff --git a/packages/http/src/storages/metadata/use-middleware.ts b/packages/http/src/storages/metadata/use-middleware.ts index 092f6318..6d6df049 100644 --- a/packages/http/src/storages/metadata/use-middleware.ts +++ b/packages/http/src/storages/metadata/use-middleware.ts @@ -1,9 +1,9 @@ import type { Class } from 'type-fest'; -import type { AnyMiddleware } from '../../types/any-middleware.js'; +import type { AnyMiddlewareType } from '../../types/any-middleware.js'; export interface UseMiddlewareMetadataArgs { target: Class | any, propertyName?: string, - middleware: AnyMiddleware, + middleware: AnyMiddlewareType, } diff --git a/packages/http/src/storages/metadata/use-param.ts b/packages/http/src/storages/metadata/use-param.ts index 5b9c36dc..551983f6 100644 --- a/packages/http/src/storages/metadata/use-param.ts +++ b/packages/http/src/storages/metadata/use-param.ts @@ -1,7 +1,7 @@ import type { RouterContext } from '@koa/router'; -import type { ControllerContext } from '../../types/controller-context.js'; +import type { ControllerContextType } from '../../types/controller-context.js'; -export interface ControllerParamsContext extends ControllerContext { +export interface ControllerParamsContext extends ControllerContextType { args?: unknown[], ctx: RouterContext, } diff --git a/packages/http/src/types/any-middleware.ts b/packages/http/src/types/any-middleware.ts index 97fc5a31..62de0466 100644 --- a/packages/http/src/types/any-middleware.ts +++ b/packages/http/src/types/any-middleware.ts @@ -2,4 +2,4 @@ import type { Middleware } from '@koa/router'; import type { Class } from 'type-fest'; import type { MiddlewareInterface } from '../interfaces/middleware.js'; -export type AnyMiddleware = Class | Middleware; +export type AnyMiddlewareType = Class | Middleware; diff --git a/packages/http/src/types/controller-context.ts b/packages/http/src/types/controller-context.ts index ca357946..35afa2ad 100644 --- a/packages/http/src/types/controller-context.ts +++ b/packages/http/src/types/controller-context.ts @@ -1,6 +1,6 @@ import type { StringKeyOf } from 'type-fest'; -export interface ControllerContext = InstanceType> { +export interface ControllerContextType = InstanceType> { controllerInstance: T, controllerAction: StringKeyOf, } diff --git a/packages/http/src/types/resolved-param.ts b/packages/http/src/types/resolved-param.ts new file mode 100644 index 00000000..7378d249 --- /dev/null +++ b/packages/http/src/types/resolved-param.ts @@ -0,0 +1,4 @@ +import type { ParamsHandleFunction } from '../storages/metadata/use-param.js'; +import type { ControllerContextType } from './controller-context.js'; + +export type ResolvedParamType = ControllerContextType | unknown[] | ParamsHandleFunction; diff --git a/packages/http/src/utils/execute-params.ts b/packages/http/src/utils/execute-params.ts index 7b16ce8f..e03ae5b8 100644 --- a/packages/http/src/utils/execute-params.ts +++ b/packages/http/src/utils/execute-params.ts @@ -1,5 +1,5 @@ import type { RouterContext } from '@koa/router'; -import type { ExecutableParam } from '../routing/executable-param.js'; +import type { ExecutableParam } from '../executables/executable-param.js'; export function executeParams (params: ExecutableParam[], ctx: RouterContext) { return Promise.all(params.map((p) => p.execute(ctx))); diff --git a/packages/http/src/utils/middlewares.ts b/packages/http/src/utils/middlewares.ts index 792b1a7f..4bc8b250 100644 --- a/packages/http/src/utils/middlewares.ts +++ b/packages/http/src/utils/middlewares.ts @@ -3,9 +3,9 @@ import isClass from 'is-class'; import type { Class } from 'type-fest'; import { MetadataStorage } from '../storages/metadata-storage.js'; import { container } from '@triptyk/nfw-core'; -import type { AnyMiddleware } from '../types/any-middleware.js'; +import type { AnyMiddlewareType } from '../types/any-middleware.js'; -export function resolveMiddlewareInstance (middleware: AnyMiddleware) { +export function resolveMiddlewareInstance (middleware: AnyMiddlewareType) { if (!isClass(middleware)) { return middleware; } diff --git a/packages/http/src/utils/resolve-params.ts b/packages/http/src/utils/resolve-params.ts index b884b584..4f243b50 100644 --- a/packages/http/src/utils/resolve-params.ts +++ b/packages/http/src/utils/resolve-params.ts @@ -1,7 +1,8 @@ -import { ParamResolver } from '../routing/param-resolver.js'; + +import { ParamResolver } from '../resolvers/param-resolver.js'; import type { UseParamsMetadataArgs } from '../storages/metadata/use-param.js'; -import type { ControllerContext } from '../types/controller-context.js'; +import type { ControllerContextType } from '../types/controller-context.js'; -export function resolveParams (params: UseParamsMetadataArgs[], controllerContext: ControllerContext) { +export function resolveParams (params: UseParamsMetadataArgs[], controllerContext: ControllerContextType) { return params.map(({ handle, args }) => new ParamResolver(handle, controllerContext).resolve(args)); } diff --git a/packages/http/tests/unit/create-application.test.ts b/packages/http/tests/unit/create-application.test.ts index c595b784..43e5999b 100644 --- a/packages/http/tests/unit/create-application.test.ts +++ b/packages/http/tests/unit/create-application.test.ts @@ -6,7 +6,7 @@ import 'reflect-metadata'; import { singleton } from '@triptyk/nfw-core'; import Application from 'koa'; import { createRequest, createResponse } from 'node-mocks-http'; -import { createApplication } from '../../src/factories/application.js'; +import { createApplication } from '../../src/factories/create-application.js'; import { Controller, GET } from '../../src/index.js'; import { jest } from '@jest/globals'; import { setTimeout } from 'node:timers/promises'; diff --git a/packages/http/tests/unit/routing/action-builder.test.ts b/packages/http/tests/unit/routing/action-builder.test.ts index 12f6747e..81cf25b6 100644 --- a/packages/http/tests/unit/routing/action-builder.test.ts +++ b/packages/http/tests/unit/routing/action-builder.test.ts @@ -7,11 +7,11 @@ import { ControllerActionBuilder } from '../../../src/routing/controller-action. import { MetadataStorage } from '../../../src/storages/metadata-storage.js'; import { createKoaContext } from '../../mocks/koa-context.js'; import type { GuardInterface, ResponseHandlerInterface } from '../../../src/index.js'; +import { GuardResolver, ResponseHandlerResolver } from '../../../src/index.js'; import { ForbiddenError } from '../../../src/errors/forbidden.js'; -import { ControllerActionResolver } from '../../../src/routing/controller-action-resolver.js'; -import { GuardResolver } from '../../../src/routing/guard-resolver.js'; -import { ResponseHandlerResolver } from '../../../src/routing/response-handler-resolver.js'; -import type { ControllerContext } from '../../../src/types/controller-context.js'; +import { ControllerActionResolver } from '../../../src/resolvers/controller-action-resolver.js'; + +import type { ControllerContextType } from '../../../src/types/controller-context.js'; describe('Action builder', () => { let instance: Controller; @@ -30,7 +30,7 @@ describe('Action builder', () => { }; } - function createActionBuilder (controllerContext: ControllerContext) { + function createActionBuilder (controllerContext: ControllerContextType) { const actionResolver = new ControllerActionResolver(storage, controllerContext); const guardResolver = new GuardResolver(storage, controllerContext); const responseHandlerResolver = new ResponseHandlerResolver(storage, controllerContext); diff --git a/packages/http/tests/unit/routing/executable-guard.test.ts b/packages/http/tests/unit/routing/executable-guard.test.ts index 4cb5fad8..2db03ea5 100644 --- a/packages/http/tests/unit/routing/executable-guard.test.ts +++ b/packages/http/tests/unit/routing/executable-guard.test.ts @@ -4,9 +4,8 @@ import 'reflect-metadata'; import type { GuardInterface } from '../../../src/interfaces/guard.js'; import { describe, expect, it, beforeEach, jest } from '@jest/globals'; import { ForbiddenError } from '../../../src/errors/forbidden.js'; -import { ExecutableGuard } from '../../../src/routing/executable-guard.js'; import type { RouterContext } from '@koa/router'; -import { ExecutableParam } from '../../../src/routing/executable-param.js'; +import { ExecutableGuard, ExecutableParam } from '../../../src/index.js'; describe('Executable Guard', () => { let guardInstance : GuardInterface; diff --git a/packages/http/tests/unit/routing/executable-param.test.ts b/packages/http/tests/unit/routing/executable-param.test.ts index 7408f6a4..f9bdfe5d 100644 --- a/packages/http/tests/unit/routing/executable-param.test.ts +++ b/packages/http/tests/unit/routing/executable-param.test.ts @@ -1,18 +1,18 @@ /* eslint-disable max-statements */ import type { RouterContext } from '@koa/router'; -import { ExecutableParam } from '../../../src/routing/executable-param.js'; -import type { ControllerContext } from '../../../src/types/controller-context.js'; +import type { ControllerContextType } from '../../../src/types/controller-context.js'; import { jest } from '@jest/globals'; import type { ControllerParamsContext } from '../../../src/index.js'; -import type { ResolvedParam } from '../../../src/routing/guard-resolver.js'; +import { ExecutableParam } from '../../../src/index.js'; +import type { ResolvedParamType } from '../../../src/types/resolved-param.js'; describe('Executable param', () => { - const context: ControllerContext = { + const context: ControllerContextType = { controllerInstance: new class {}(), controllerAction: 'list' }; - function executeParamAndCheckResult (context: ControllerContext, param: ResolvedParam, expectedResult: unknown) { + function executeParamAndCheckResult (context: ControllerContextType, param: ResolvedParamType, expectedResult: unknown) { const executableParam = new ExecutableParam(context, param); expect(executableParam.execute({} as RouterContext)).toStrictEqual(expectedResult); } diff --git a/packages/http/tests/unit/routing/executable-response-handler.test.ts b/packages/http/tests/unit/routing/executable-response-handler.test.ts index dd46920c..c37c6407 100644 --- a/packages/http/tests/unit/routing/executable-response-handler.test.ts +++ b/packages/http/tests/unit/routing/executable-response-handler.test.ts @@ -2,9 +2,9 @@ /* eslint-disable max-classes-per-file */ import type { RouterContext } from '@koa/router'; import { jest } from '@jest/globals'; -import type { ResponseHandlerInterface } from '../../../src/index.js'; -import { ExecutableParam } from '../../../src/routing/executable-param.js'; -import { ExecutableResponseHandler } from '../../../src/routing/executable-response-handler.js'; +import type { ResponseHandlerInterface } from '../../../src/interfaces/response-handler.js'; +import { ExecutableParam } from '../../../src/executables/executable-param.js'; +import { ExecutableResponseHandler } from '../../../src/executables/executable-response-handler.js'; describe('Executable response handler', () => { class RH implements ResponseHandlerInterface { diff --git a/packages/http/tests/unit/routing/guard-resolver.test.ts b/packages/http/tests/unit/routing/guard-resolver.test.ts index c0f0f424..43cd51e3 100644 --- a/packages/http/tests/unit/routing/guard-resolver.test.ts +++ b/packages/http/tests/unit/routing/guard-resolver.test.ts @@ -3,9 +3,10 @@ import 'reflect-metadata'; import type { Class } from 'type-fest'; +import { ExecutableGuard } from '../../../src/executables/executable-guard.js'; import type { GuardInterface } from '../../../src/interfaces/guard.js'; -import { ExecutableGuard } from '../../../src/routing/executable-guard.js'; -import { GuardResolver } from '../../../src/routing/guard-resolver.js'; +import { GuardResolver } from '../../../src/resolvers/guard-resolver.js'; + import { MetadataStorage } from '../../../src/storages/metadata-storage.js'; describe('Guard builder', () => { diff --git a/packages/http/tests/unit/routing/param-resolver.test.ts b/packages/http/tests/unit/routing/param-resolver.test.ts index 641b0cde..6aa8a378 100644 --- a/packages/http/tests/unit/routing/param-resolver.test.ts +++ b/packages/http/tests/unit/routing/param-resolver.test.ts @@ -3,9 +3,8 @@ import 'reflect-metadata'; import type { UseParamsMetadataArgs } from '../../../src/index.js'; +import { ExecutableParam, ParamResolver } from '../../../src/index.js'; import { jest, describe, expect, it } from '@jest/globals'; -import { ParamResolver } from '../../../src/routing/param-resolver.js'; -import { ExecutableParam } from '../../../src/routing/executable-param.js'; describe('ResolveParam', () => { class Controller {} diff --git a/packages/http/tests/unit/routing/response-handler-resolver.test.ts b/packages/http/tests/unit/routing/response-handler-resolver.test.ts index b8dfd268..fb6cf4ac 100644 --- a/packages/http/tests/unit/routing/response-handler-resolver.test.ts +++ b/packages/http/tests/unit/routing/response-handler-resolver.test.ts @@ -3,9 +3,9 @@ import 'reflect-metadata'; import type { Class } from 'type-fest'; +import { ExecutableResponseHandler } from '../../../src/executables/executable-response-handler.js'; import type { MetadataStorageInterface, ResponseHandlerInterface } from '../../../src/index.js'; -import { ExecutableResponseHandler } from '../../../src/routing/executable-response-handler.js'; -import { ResponseHandlerResolver } from '../../../src/routing/response-handler-resolver.js'; +import { ResponseHandlerResolver } from '../../../src/resolvers/response-handler-resolver.js'; import { MetadataStorage } from '../../../src/storages/metadata-storage.js'; describe('Response handler resolver', () => { From d22e32b6afb284a5ba44b2cbe334560f292150ea Mon Sep 17 00:00:00 2001 From: AmauryD Date: Sat, 26 Nov 2022 13:57:28 +0100 Subject: [PATCH 3/7] interfaces --- .../http/src/executables/executable-controller-action.ts | 3 ++- packages/http/src/executables/executable-guard.ts | 3 ++- packages/http/src/executables/executable-param.ts | 3 ++- packages/http/src/executables/executable-response-handler.ts | 3 ++- packages/http/src/factories/create-application.ts | 5 +++-- packages/http/src/interfaces/executable.ts | 3 +++ packages/http/src/interfaces/resolver.ts | 3 ++- packages/http/src/routing/router-builder.ts | 4 ++-- 8 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 packages/http/src/interfaces/executable.ts diff --git a/packages/http/src/executables/executable-controller-action.ts b/packages/http/src/executables/executable-controller-action.ts index 81653197..7c1d0dd1 100644 --- a/packages/http/src/executables/executable-controller-action.ts +++ b/packages/http/src/executables/executable-controller-action.ts @@ -1,9 +1,10 @@ import type { RouterContext } from '@koa/router'; +import type { ExecutableInterface } from '../interfaces/executable.js'; import type { ControllerContextType } from '../types/controller-context.js'; import { executeParams } from '../utils/execute-params.js'; import type { ExecutableParam } from './executable-param.js'; -export class ExecutableControllerAction { +export class ExecutableControllerAction implements ExecutableInterface { public constructor ( public controllerContext: ControllerContextType, public params: ExecutableParam[] diff --git a/packages/http/src/executables/executable-guard.ts b/packages/http/src/executables/executable-guard.ts index 18bb1fff..a3368285 100644 --- a/packages/http/src/executables/executable-guard.ts +++ b/packages/http/src/executables/executable-guard.ts @@ -1,11 +1,12 @@ import type { RouterContext } from '@koa/router'; import { ForbiddenError } from '../errors/forbidden.js'; +import type { ExecutableInterface } from '../interfaces/executable.js'; import type { GuardInterface } from '../interfaces/guard.js'; import type { ControllerContextType } from '../types/controller-context.js'; import { executeParams } from '../utils/execute-params.js'; import type { ExecutableParam } from './executable-param.js'; -export class ExecutableGuard { +export class ExecutableGuard implements ExecutableInterface { public constructor ( public instance: GuardInterface, public controllerContext: ControllerContextType, diff --git a/packages/http/src/executables/executable-param.ts b/packages/http/src/executables/executable-param.ts index 9ec8b368..161b6c2b 100644 --- a/packages/http/src/executables/executable-param.ts +++ b/packages/http/src/executables/executable-param.ts @@ -1,8 +1,9 @@ import type { RouterContext } from '@koa/router'; +import type { ExecutableInterface } from '../interfaces/executable.js'; import type { ControllerContextType } from '../types/controller-context.js'; import type { ResolvedParamType } from '../types/resolved-param.js'; -export class ExecutableParam { +export class ExecutableParam implements ExecutableInterface { public constructor ( public controllerContext: ControllerContextType, private param: ResolvedParamType diff --git a/packages/http/src/executables/executable-response-handler.ts b/packages/http/src/executables/executable-response-handler.ts index 44ba3fed..4693c482 100644 --- a/packages/http/src/executables/executable-response-handler.ts +++ b/packages/http/src/executables/executable-response-handler.ts @@ -1,10 +1,11 @@ import type { RouterContext } from '@koa/router'; +import type { ExecutableInterface } from '../interfaces/executable.js'; import type { ResponseHandlerInterface } from '../interfaces/response-handler.js'; import type { ControllerContextType } from '../types/controller-context.js'; import { executeParams } from '../utils/execute-params.js'; import type { ExecutableParam } from './executable-param.js'; -export class ExecutableResponseHandler { +export class ExecutableResponseHandler implements ExecutableInterface { public constructor ( public instance: ResponseHandlerInterface, public controllerContext: ControllerContextType, diff --git a/packages/http/src/factories/create-application.ts b/packages/http/src/factories/create-application.ts index 4df5e3a5..7ccc8576 100644 --- a/packages/http/src/factories/create-application.ts +++ b/packages/http/src/factories/create-application.ts @@ -1,5 +1,5 @@ import type Koa from 'koa'; -import { RouterBuilderFactory } from '../routing/router-builder.js'; +import { RouterBuilder } from '../routing/router-builder.js'; import type { Class } from 'type-fest'; import { container } from '@triptyk/nfw-core'; import { MetadataStorage } from '../storages/metadata-storage.js'; @@ -11,9 +11,10 @@ export interface CreateApplicationOptions { export async function createApplication (options: CreateApplicationOptions) { const app = options.server; + const metadataStorage = container.resolve(MetadataStorage); for (const controller of options.controllers) { - const routerBuilder = new RouterBuilderFactory(container.resolve(MetadataStorage), app, controller); + const routerBuilder = new RouterBuilder(metadataStorage, app, controller); await routerBuilder.createRoute(); } } diff --git a/packages/http/src/interfaces/executable.ts b/packages/http/src/interfaces/executable.ts new file mode 100644 index 00000000..551f1993 --- /dev/null +++ b/packages/http/src/interfaces/executable.ts @@ -0,0 +1,3 @@ +export interface ExecutableInterface { + execute(...args: unknown[]): unknown, +} diff --git a/packages/http/src/interfaces/resolver.ts b/packages/http/src/interfaces/resolver.ts index bbcfa940..d3e925d3 100644 --- a/packages/http/src/interfaces/resolver.ts +++ b/packages/http/src/interfaces/resolver.ts @@ -1,4 +1,5 @@ +import type { ExecutableInterface } from './executable.js'; export interface ResolverInterface { - resolve(...args: unknown[]): unknown, + resolve(...args: unknown[]): ExecutableInterface | ExecutableInterface[] | undefined, } diff --git a/packages/http/src/routing/router-builder.ts b/packages/http/src/routing/router-builder.ts index 5a4e6177..fe9dda0a 100644 --- a/packages/http/src/routing/router-builder.ts +++ b/packages/http/src/routing/router-builder.ts @@ -6,7 +6,7 @@ import type { MetadataStorageInterface } from '../interfaces/metadata-storage.js import type { RouterBuilderInterface } from '../interfaces/router-builder.js'; import type { RouteMetadataArgs } from '../storages/metadata/route.js'; -export class RouterBuilderFactory { +export class RouterBuilder { public constructor ( public metadataStorage: MetadataStorageInterface, private parentRoute: Router | Application, @@ -35,6 +35,6 @@ export class RouterBuilderFactory { } private async createNestedRouters (controllerMetadata: RouteMetadataArgs, futureParentRouter: Router) { - await Promise.all((controllerMetadata.controllers ?? []).map(async (c) => new RouterBuilderFactory(this.metadataStorage, futureParentRouter, c).createRoute())); + await Promise.all((controllerMetadata.controllers ?? []).map(async (c) => new RouterBuilder(this.metadataStorage, futureParentRouter, c).createRoute())); } } From 5fba17a760abf9fd4f3998f0e27fe4b2b0dbdebe Mon Sep 17 00:00:00 2001 From: AmauryD Date: Sat, 26 Nov 2022 14:57:09 +0100 Subject: [PATCH 4/7] ts-jest is working --- jest.config.js | 42 ++- package.json | 21 +- packages/core/tsconfig.json | 7 +- packages/http/jest.config.js | 5 + packages/http/tsconfig.json | 7 +- .../tests/acceptance/resource-service.test.ts | 1 + .../tests/acceptance/serializer.test.ts | 1 + packages/jsonapi/tsconfig.json | 7 +- packages/mikro-orm/tsconfig.json | 7 +- pnpm-lock.yaml | 353 +++++++++++------- tsconfig.build.json | 38 +- tsconfig.json | 4 +- 12 files changed, 280 insertions(+), 213 deletions(-) create mode 100644 packages/http/jest.config.js diff --git a/jest.config.js b/jest.config.js index 1eafbf1c..57913b2a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,22 +1,32 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ + +function createProject(name) { + return { + displayName: name, + testMatch: [`/packages/${name}/tests/**/*.test.ts`], + tsConfig: `/packages/${name}/tsconfig.json`, + preset: "ts-jest/presets/default-esm", // or other ESM presets + moduleNameMapper: { + "^(\\.{1,2}/.*)\\.js$": "$1", + }, + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + useESM: true, + }, + ], + }, + }; +} + export default { testEnvironment: "node", collectCoverage: Boolean(process.env.CI), projects: [ - { - displayName: "nfw-mikro-orm", - testMatch: ["/packages/mikro-orm/dist/tests/**/*.test.js"], - }, - { - displayName: "nfw-core", - testMatch: ["/packages/core/dist/tests/**/*.test.js"], - }, - { - displayName: "nfw-http", - testMatch: ["/packages/http/dist/tests/**/*.test.js"], - }, - { - displayName: "nfw-jsonapi", - testMatch: ["/packages/jsonapi/dist/tests/**/*.test.js"], - }, + createProject("mikro-orm"), + createProject("core"), + createProject("http"), + createProject("jsonapi"), ], }; diff --git a/package.json b/package.json index fcf1d9cb..0f5829ee 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,10 @@ "lint": "eslint 'packages/*/{src,tests}/**/*.ts'", "lint:fix": "eslint 'packages/*/{src,tests}/**/*.ts' --fix", "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand", - "test:jsonapi": "node --experimental-vm-modules node_modules/jest/bin/jest.js --selectProjects nfw-jsonapi", - "test:http": "node --experimental-vm-modules node_modules/jest/bin/jest.js --selectProjects nfw-http", - "test:core": "node --experimental-vm-modules node_modules/jest/bin/jest.js --selectProjects nfw-core", - "test:mikro-orm": "node --experimental-vm-modules node_modules/jest/bin/jest.js --selectProjects nfw-mikro-orm", + "test:jsonapi": "node --experimental-vm-modules node_modules/jest/bin/jest.js --selectProjects jsonapi", + "test:http": "node --experimental-vm-modules node_modules/jest/bin/jest.js --selectProjects http", + "test:core": "node --experimental-vm-modules node_modules/jest/bin/jest.js --selectProjects core", + "test:mikro-orm": "node --experimental-vm-modules node_modules/jest/bin/jest.js --selectProjects mikro-orm", "jscpd": "jscpd --exitCode 1", "build": "pnpm recursive run build", "build:clean": "pnpm recursive run build:clean", @@ -24,26 +24,27 @@ "@jest/globals": "^29.3.1", "@jscpd/finder": "^3.5.1", "@types/jest": "^29.2.3", - "@typescript-eslint/eslint-plugin": "^5.43.0", - "@typescript-eslint/parser": "^5.43.0", - "eslint": "^8.27.0", + "@typescript-eslint/eslint-plugin": "^5.44.0", + "@typescript-eslint/parser": "^5.44.0", + "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-config-standard": "17.0.0", "eslint-plugin-custom-elements": "^0.0.6", "eslint-plugin-es": "^4", "eslint-plugin-filenames": "^1", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "^27.1.5", + "eslint-plugin-jest": "^27.1.6", "eslint-plugin-n": "^15.5.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^4", "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-unicorn": "^44.0.2", + "eslint-plugin-unicorn": "^45.0.0", "eslint-plugin-unused-imports": "^2.0.0", "jest": "^29.3.1", "jscpd": "~3.5.1", "npm-run-all": "^4.1.5", - "prettier": "^2", + "prettier": "^2.8.0", + "ts-jest": "^29.0.3", "typescript": "~4.9.3" }, "keywords": [], diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 26b18be6..4082f16a 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -1,6 +1,3 @@ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "esModuleInterop": true - } -} \ No newline at end of file + "extends": "../../tsconfig.json" +} diff --git a/packages/http/jest.config.js b/packages/http/jest.config.js new file mode 100644 index 00000000..62143430 --- /dev/null +++ b/packages/http/jest.config.js @@ -0,0 +1,5 @@ +import baseConfig from "../../jest.config.js"; + +export default { + ...baseConfig, +}; diff --git a/packages/http/tsconfig.json b/packages/http/tsconfig.json index 26b18be6..4082f16a 100644 --- a/packages/http/tsconfig.json +++ b/packages/http/tsconfig.json @@ -1,6 +1,3 @@ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "esModuleInterop": true - } -} \ No newline at end of file + "extends": "../../tsconfig.json" +} diff --git a/packages/jsonapi/tests/acceptance/resource-service.test.ts b/packages/jsonapi/tests/acceptance/resource-service.test.ts index b07d490f..9aab6b1d 100644 --- a/packages/jsonapi/tests/acceptance/resource-service.test.ts +++ b/packages/jsonapi/tests/acceptance/resource-service.test.ts @@ -1,4 +1,5 @@ /* eslint-disable max-statements */ +import 'reflect-metadata'; import { MikroORM } from '@mikro-orm/core'; import { container } from '@triptyk/nfw-core'; import type { ResourceService } from '../../src/index.js'; diff --git a/packages/jsonapi/tests/acceptance/serializer.test.ts b/packages/jsonapi/tests/acceptance/serializer.test.ts index 1e9a3252..00d6bb08 100644 --- a/packages/jsonapi/tests/acceptance/serializer.test.ts +++ b/packages/jsonapi/tests/acceptance/serializer.test.ts @@ -2,6 +2,7 @@ /* eslint-disable unicorn/no-null */ /* eslint-disable max-statements */ /* eslint-disable no-console */ +import 'reflect-metadata'; import type { RouterContext } from '@koa/router'; import { MikroORM } from '@mikro-orm/core'; import { container } from '@triptyk/nfw-core'; diff --git a/packages/jsonapi/tsconfig.json b/packages/jsonapi/tsconfig.json index ca3a9d12..4082f16a 100644 --- a/packages/jsonapi/tsconfig.json +++ b/packages/jsonapi/tsconfig.json @@ -1,6 +1,3 @@ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "esModuleInterop": true - }, -} \ No newline at end of file + "extends": "../../tsconfig.json" +} diff --git a/packages/mikro-orm/tsconfig.json b/packages/mikro-orm/tsconfig.json index 26b18be6..4082f16a 100644 --- a/packages/mikro-orm/tsconfig.json +++ b/packages/mikro-orm/tsconfig.json @@ -1,6 +1,3 @@ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "esModuleInterop": true - } -} \ No newline at end of file + "extends": "../../tsconfig.json" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 085e65a2..ce1cd6da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,52 +8,54 @@ importers: '@jest/globals': ^29.3.1 '@jscpd/finder': ^3.5.1 '@types/jest': ^29.2.3 - '@typescript-eslint/eslint-plugin': ^5.43.0 - '@typescript-eslint/parser': ^5.43.0 - eslint: ^8.27.0 + '@typescript-eslint/eslint-plugin': ^5.44.0 + '@typescript-eslint/parser': ^5.44.0 + eslint: ^8.28.0 eslint-config-prettier: ^8.5.0 eslint-config-standard: 17.0.0 eslint-plugin-custom-elements: ^0.0.6 eslint-plugin-es: ^4 eslint-plugin-filenames: ^1 eslint-plugin-import: ^2.26.0 - eslint-plugin-jest: ^27.1.5 + eslint-plugin-jest: ^27.1.6 eslint-plugin-n: ^15.5.1 eslint-plugin-node: ^11.1.0 eslint-plugin-prettier: ^4 eslint-plugin-promise: ^6.1.1 - eslint-plugin-unicorn: ^44.0.2 + eslint-plugin-unicorn: ^45.0.0 eslint-plugin-unused-imports: ^2.0.0 jest: ^29.3.1 jscpd: ~3.5.1 npm-run-all: ^4.1.5 - prettier: ^2 + prettier: ^2.8.0 + ts-jest: ^29.0.3 typescript: ~4.9.3 devDependencies: - '@foxglove/eslint-plugin': 0.20.0_o7npt4uvnqzlzapxpknrignlcu + '@foxglove/eslint-plugin': 0.20.0_dcebqvpznc5dv3crofmjiwtn4u '@jest/globals': 29.3.1 '@jscpd/finder': 3.5.1 '@types/jest': 29.2.3 - '@typescript-eslint/eslint-plugin': 5.43.0_wze2rj5tow7zwqpgbdx2buoy3m - '@typescript-eslint/parser': 5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y - eslint: 8.27.0 - eslint-config-prettier: 8.5.0_eslint@8.27.0 - eslint-config-standard: 17.0.0_qmmcbu32ybj7ict4ieqqyvwr3m - eslint-plugin-custom-elements: 0.0.6_eslint@8.27.0 - eslint-plugin-es: 4.1.0_eslint@8.27.0 - eslint-plugin-filenames: 1.3.2_eslint@8.27.0 - eslint-plugin-import: 2.26.0_wbsj7pk5g7hogwvhsif6xntns4 - eslint-plugin-jest: 27.1.5_fqtdfzmoyuw7rs7dg6fkh5euye - eslint-plugin-n: 15.5.1_eslint@8.27.0 - eslint-plugin-node: 11.1.0_eslint@8.27.0 - eslint-plugin-prettier: 4.2.1_v7o5sx5x3wbs57ifz6wc4f76we - eslint-plugin-promise: 6.1.1_eslint@8.27.0 - eslint-plugin-unicorn: 44.0.2_eslint@8.27.0 - eslint-plugin-unused-imports: 2.0.0_mb5ommioozas4vcfu4l3k44vny + '@typescript-eslint/eslint-plugin': 5.44.0_fnsv2sbzcckq65bwfk7a5xwslu + '@typescript-eslint/parser': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + eslint: 8.28.0 + eslint-config-prettier: 8.5.0_eslint@8.28.0 + eslint-config-standard: 17.0.0_5dakk4wnrkkieagghiqvu5yn4y + eslint-plugin-custom-elements: 0.0.6_eslint@8.28.0 + eslint-plugin-es: 4.1.0_eslint@8.28.0 + eslint-plugin-filenames: 1.3.2_eslint@8.28.0 + eslint-plugin-import: 2.26.0_vfrilbydaxalswvos6uuh4sxs4 + eslint-plugin-jest: 27.1.6_bifecjdquhom2xjmkl7gfpj6ma + eslint-plugin-n: 15.5.1_eslint@8.28.0 + eslint-plugin-node: 11.1.0_eslint@8.28.0 + eslint-plugin-prettier: 4.2.1_cwlo2dingkvfydnaculr42urve + eslint-plugin-promise: 6.1.1_eslint@8.28.0 + eslint-plugin-unicorn: 45.0.0_eslint@8.28.0 + eslint-plugin-unused-imports: 2.0.0_aucl44mjeutxyzmt4nvo2cczya jest: 29.3.1 jscpd: 3.5.1 npm-run-all: 4.1.5 - prettier: 2.7.1 + prettier: 2.8.0 + ts-jest: 29.0.3_4f6uxrzmuwipl5rr3bcogf6k74 typescript: 4.9.3 packages/core: @@ -577,7 +579,7 @@ packages: - supports-color dev: true - /@foxglove/eslint-plugin/0.20.0_o7npt4uvnqzlzapxpknrignlcu: + /@foxglove/eslint-plugin/0.20.0_dcebqvpznc5dv3crofmjiwtn4u: resolution: {integrity: sha512-/rSWnqworu9kGd1bnfijF/aRof+hc4XmVyVLi46GKBYbeNAloh1IhZ0w8cXsio7uqIc2fxaEJvSXIrtV3cBMRA==} peerDependencies: eslint: ^7 || ^8 @@ -588,14 +590,14 @@ packages: eslint-plugin-prettier: ^3 || ^4 prettier: ^2 dependencies: - '@typescript-eslint/utils': 5.32.0_e3uo4sehh4zr4i6m57mkkxxv7y - eslint: 8.27.0 - eslint-config-prettier: 8.5.0_eslint@8.27.0 - eslint-plugin-es: 4.1.0_eslint@8.27.0 - eslint-plugin-filenames: 1.3.2_eslint@8.27.0 - eslint-plugin-import: 2.26.0_wbsj7pk5g7hogwvhsif6xntns4 - eslint-plugin-prettier: 4.2.1_v7o5sx5x3wbs57ifz6wc4f76we - prettier: 2.7.1 + '@typescript-eslint/utils': 5.32.0_hsf322ms6xhhd4b5ne6lb74y4a + eslint: 8.28.0 + eslint-config-prettier: 8.5.0_eslint@8.28.0 + eslint-plugin-es: 4.1.0_eslint@8.28.0 + eslint-plugin-filenames: 1.3.2_eslint@8.28.0 + eslint-plugin-import: 2.26.0_vfrilbydaxalswvos6uuh4sxs4 + eslint-plugin-prettier: 4.2.1_cwlo2dingkvfydnaculr42urve + prettier: 2.8.0 tsutils: 3.21.0_typescript@4.9.3 typescript: 4.9.3 transitivePeerDependencies: @@ -1400,8 +1402,8 @@ packages: '@types/yargs-parser': 21.0.0 dev: true - /@typescript-eslint/eslint-plugin/5.43.0_wze2rj5tow7zwqpgbdx2buoy3m: - resolution: {integrity: sha512-wNPzG+eDR6+hhW4yobEmpR36jrqqQv1vxBq5LJO3fBAktjkvekfr4BRl+3Fn1CM/A+s8/EiGUbOMDoYqWdbtXA==} + /@typescript-eslint/eslint-plugin/5.44.0_fnsv2sbzcckq65bwfk7a5xwslu: + resolution: {integrity: sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -1411,12 +1413,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y - '@typescript-eslint/scope-manager': 5.43.0 - '@typescript-eslint/type-utils': 5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y - '@typescript-eslint/utils': 5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y + '@typescript-eslint/parser': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + '@typescript-eslint/scope-manager': 5.44.0 + '@typescript-eslint/type-utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + '@typescript-eslint/utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a debug: 4.3.4 - eslint: 8.27.0 + eslint: 8.28.0 ignore: 5.2.0 natural-compare-lite: 1.4.0 regexpp: 3.2.0 @@ -1427,8 +1429,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser/5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y: - resolution: {integrity: sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==} + /@typescript-eslint/parser/5.44.0_hsf322ms6xhhd4b5ne6lb74y4a: + resolution: {integrity: sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1437,11 +1439,11 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.43.0 - '@typescript-eslint/types': 5.43.0 - '@typescript-eslint/typescript-estree': 5.43.0_typescript@4.9.3 + '@typescript-eslint/scope-manager': 5.44.0 + '@typescript-eslint/types': 5.44.0 + '@typescript-eslint/typescript-estree': 5.44.0_typescript@4.9.3 debug: 4.3.4 - eslint: 8.27.0 + eslint: 8.28.0 typescript: 4.9.3 transitivePeerDependencies: - supports-color @@ -1455,16 +1457,16 @@ packages: '@typescript-eslint/visitor-keys': 5.32.0 dev: true - /@typescript-eslint/scope-manager/5.43.0: - resolution: {integrity: sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==} + /@typescript-eslint/scope-manager/5.44.0: + resolution: {integrity: sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.43.0 - '@typescript-eslint/visitor-keys': 5.43.0 + '@typescript-eslint/types': 5.44.0 + '@typescript-eslint/visitor-keys': 5.44.0 dev: true - /@typescript-eslint/type-utils/5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y: - resolution: {integrity: sha512-K21f+KY2/VvYggLf5Pk4tgBOPs2otTaIHy2zjclo7UZGLyFH86VfUOm5iq+OtDtxq/Zwu2I3ujDBykVW4Xtmtg==} + /@typescript-eslint/type-utils/5.44.0_hsf322ms6xhhd4b5ne6lb74y4a: + resolution: {integrity: sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -1473,10 +1475,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.43.0_typescript@4.9.3 - '@typescript-eslint/utils': 5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y + '@typescript-eslint/typescript-estree': 5.44.0_typescript@4.9.3 + '@typescript-eslint/utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a debug: 4.3.4 - eslint: 8.27.0 + eslint: 8.28.0 tsutils: 3.21.0_typescript@4.9.3 typescript: 4.9.3 transitivePeerDependencies: @@ -1488,8 +1490,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/types/5.43.0: - resolution: {integrity: sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==} + /@typescript-eslint/types/5.44.0: + resolution: {integrity: sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true @@ -1514,8 +1516,8 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree/5.43.0_typescript@4.9.3: - resolution: {integrity: sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==} + /@typescript-eslint/typescript-estree/5.44.0_typescript@4.9.3: + resolution: {integrity: sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -1523,8 +1525,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.43.0 - '@typescript-eslint/visitor-keys': 5.43.0 + '@typescript-eslint/types': 5.44.0 + '@typescript-eslint/visitor-keys': 5.44.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1535,7 +1537,7 @@ packages: - supports-color dev: true - /@typescript-eslint/utils/5.32.0_e3uo4sehh4zr4i6m57mkkxxv7y: + /@typescript-eslint/utils/5.32.0_hsf322ms6xhhd4b5ne6lb74y4a: resolution: {integrity: sha512-W7lYIAI5Zlc5K082dGR27Fczjb3Q57ECcXefKU/f0ajM5ToM0P+N9NmJWip8GmGu/g6QISNT+K6KYB+iSHjXCQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1545,28 +1547,28 @@ packages: '@typescript-eslint/scope-manager': 5.32.0 '@typescript-eslint/types': 5.32.0 '@typescript-eslint/typescript-estree': 5.32.0_typescript@4.9.3 - eslint: 8.27.0 + eslint: 8.28.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.27.0 + eslint-utils: 3.0.0_eslint@8.28.0 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/utils/5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y: - resolution: {integrity: sha512-8nVpA6yX0sCjf7v/NDfeaOlyaIIqL7OaIGOWSPFqUKK59Gnumd3Wa+2l8oAaYO2lk0sO+SbWFWRSvhu8gLGv4A==} + /@typescript-eslint/utils/5.44.0_hsf322ms6xhhd4b5ne6lb74y4a: + resolution: {integrity: sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: '@types/json-schema': 7.0.11 '@types/semver': 7.3.13 - '@typescript-eslint/scope-manager': 5.43.0 - '@typescript-eslint/types': 5.43.0 - '@typescript-eslint/typescript-estree': 5.43.0_typescript@4.9.3 - eslint: 8.27.0 + '@typescript-eslint/scope-manager': 5.44.0 + '@typescript-eslint/types': 5.44.0 + '@typescript-eslint/typescript-estree': 5.44.0_typescript@4.9.3 + eslint: 8.28.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.27.0 + eslint-utils: 3.0.0_eslint@8.28.0 semver: 7.3.8 transitivePeerDependencies: - supports-color @@ -1581,11 +1583,11 @@ packages: eslint-visitor-keys: 3.3.0 dev: true - /@typescript-eslint/visitor-keys/5.43.0: - resolution: {integrity: sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==} + /@typescript-eslint/visitor-keys/5.44.0: + resolution: {integrity: sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.43.0 + '@typescript-eslint/types': 5.44.0 eslint-visitor-keys: 3.3.0 dev: true @@ -1922,6 +1924,13 @@ packages: update-browserslist-db: 1.0.10_browserslist@4.21.4 dev: true + /bs-logger/0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + dependencies: + fast-json-stable-stringify: 2.1.0 + dev: true + /bser/2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} dependencies: @@ -2041,15 +2050,16 @@ packages: engines: {node: '>=10'} dev: true - /ci-info/3.5.0: - resolution: {integrity: sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==} - dev: true - /ci-info/3.6.1: resolution: {integrity: sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==} engines: {node: '>=8'} dev: true + /ci-info/3.7.0: + resolution: {integrity: sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==} + engines: {node: '>=8'} + dev: true + /cjs-module-lexer/1.2.2: resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==} dev: true @@ -2450,16 +2460,16 @@ packages: engines: {node: '>=10'} dev: true - /eslint-config-prettier/8.5.0_eslint@8.27.0: + /eslint-config-prettier/8.5.0_eslint@8.28.0: resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.27.0 + eslint: 8.28.0 dev: true - /eslint-config-standard/17.0.0_qmmcbu32ybj7ict4ieqqyvwr3m: + /eslint-config-standard/17.0.0_5dakk4wnrkkieagghiqvu5yn4y: resolution: {integrity: sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==} peerDependencies: eslint: ^8.0.1 @@ -2467,10 +2477,10 @@ packages: eslint-plugin-n: ^15.0.0 eslint-plugin-promise: ^6.0.0 dependencies: - eslint: 8.27.0 - eslint-plugin-import: 2.26.0_wbsj7pk5g7hogwvhsif6xntns4 - eslint-plugin-n: 15.5.1_eslint@8.27.0 - eslint-plugin-promise: 6.1.1_eslint@8.27.0 + eslint: 8.28.0 + eslint-plugin-import: 2.26.0_vfrilbydaxalswvos6uuh4sxs4 + eslint-plugin-n: 15.5.1_eslint@8.28.0 + eslint-plugin-promise: 6.1.1_eslint@8.28.0 dev: true /eslint-import-resolver-node/0.3.6: @@ -2482,7 +2492,7 @@ packages: - supports-color dev: true - /eslint-module-utils/2.7.3_fmuy6wfytpxcy4lufnxcokvnry: + /eslint-module-utils/2.7.3_c5u3z3b56p5yrxfuaql7gkhl3q: resolution: {integrity: sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==} engines: {node: '>=4'} peerDependencies: @@ -2500,7 +2510,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y + '@typescript-eslint/parser': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a debug: 3.2.7 eslint-import-resolver-node: 0.3.6 find-up: 2.1.0 @@ -2508,49 +2518,49 @@ packages: - supports-color dev: true - /eslint-plugin-custom-elements/0.0.6_eslint@8.27.0: + /eslint-plugin-custom-elements/0.0.6_eslint@8.28.0: resolution: {integrity: sha512-JwPHRSOUe7y8dpC5hg90ySHejsfnQ3yqprv0902VMZ3j8FRZDudj+yzxqqkRDhZTNFUxP3r+0TWuveZhLgJONg==} peerDependencies: eslint: '>=4.19.0' dependencies: - eslint: 8.27.0 + eslint: 8.28.0 dev: true - /eslint-plugin-es/3.0.1_eslint@8.27.0: + /eslint-plugin-es/3.0.1_eslint@8.28.0: resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=4.19.1' dependencies: - eslint: 8.27.0 + eslint: 8.28.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true - /eslint-plugin-es/4.1.0_eslint@8.27.0: + /eslint-plugin-es/4.1.0_eslint@8.28.0: resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=4.19.1' dependencies: - eslint: 8.27.0 + eslint: 8.28.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true - /eslint-plugin-filenames/1.3.2_eslint@8.27.0: + /eslint-plugin-filenames/1.3.2_eslint@8.28.0: resolution: {integrity: sha512-tqxJTiEM5a0JmRCUYQmxw23vtTxrb2+a3Q2mMOPhFxvt7ZQQJmdiuMby9B/vUAuVMghyP7oET+nIf6EO6CBd/w==} peerDependencies: eslint: '*' dependencies: - eslint: 8.27.0 + eslint: 8.28.0 lodash.camelcase: 4.3.0 lodash.kebabcase: 4.1.1 lodash.snakecase: 4.1.1 lodash.upperfirst: 4.3.1 dev: true - /eslint-plugin-import/2.26.0_wbsj7pk5g7hogwvhsif6xntns4: + /eslint-plugin-import/2.26.0_vfrilbydaxalswvos6uuh4sxs4: resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} engines: {node: '>=4'} peerDependencies: @@ -2560,14 +2570,14 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y + '@typescript-eslint/parser': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a array-includes: 3.1.5 array.prototype.flat: 1.3.0 debug: 2.6.9 doctrine: 2.1.0 - eslint: 8.27.0 + eslint: 8.28.0 eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.7.3_fmuy6wfytpxcy4lufnxcokvnry + eslint-module-utils: 2.7.3_c5u3z3b56p5yrxfuaql7gkhl3q has: 1.0.3 is-core-module: 2.9.0 is-glob: 4.0.3 @@ -2581,8 +2591,8 @@ packages: - supports-color dev: true - /eslint-plugin-jest/27.1.5_fqtdfzmoyuw7rs7dg6fkh5euye: - resolution: {integrity: sha512-CK2dekZ5VBdzsOSOH5Fc1rwC+cWXjkcyrmf1RV714nDUDKu+o73TTJiDxpbILG8PtPPpAAl3ywzh5QA7Ft0mjA==} + /eslint-plugin-jest/27.1.6_bifecjdquhom2xjmkl7gfpj6ma: + resolution: {integrity: sha512-XA7RFLSrlQF9IGtAmhddkUkBuICCTuryfOTfCSWcZHiHb69OilIH05oozH2XA6CEOtztnOd0vgXyvxZodkxGjg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': ^5.0.0 @@ -2594,25 +2604,25 @@ packages: jest: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 5.43.0_wze2rj5tow7zwqpgbdx2buoy3m - '@typescript-eslint/utils': 5.43.0_e3uo4sehh4zr4i6m57mkkxxv7y - eslint: 8.27.0 + '@typescript-eslint/eslint-plugin': 5.44.0_fnsv2sbzcckq65bwfk7a5xwslu + '@typescript-eslint/utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + eslint: 8.28.0 jest: 29.3.1 transitivePeerDependencies: - supports-color - typescript dev: true - /eslint-plugin-n/15.5.1_eslint@8.27.0: + /eslint-plugin-n/15.5.1_eslint@8.28.0: resolution: {integrity: sha512-kAd+xhZm7brHoFLzKLB7/FGRFJNg/srmv67mqb7tto22rpr4wv/LV6RuXzAfv3jbab7+k1wi42PsIhGviywaaw==} engines: {node: '>=12.22.0'} peerDependencies: eslint: '>=7.0.0' dependencies: builtins: 5.0.1 - eslint: 8.27.0 - eslint-plugin-es: 4.1.0_eslint@8.27.0 - eslint-utils: 3.0.0_eslint@8.27.0 + eslint: 8.28.0 + eslint-plugin-es: 4.1.0_eslint@8.28.0 + eslint-utils: 3.0.0_eslint@8.28.0 ignore: 5.2.0 is-core-module: 2.11.0 minimatch: 3.1.2 @@ -2620,14 +2630,14 @@ packages: semver: 7.3.8 dev: true - /eslint-plugin-node/11.1.0_eslint@8.27.0: + /eslint-plugin-node/11.1.0_eslint@8.28.0: resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=5.16.0' dependencies: - eslint: 8.27.0 - eslint-plugin-es: 3.0.1_eslint@8.27.0 + eslint: 8.28.0 + eslint-plugin-es: 3.0.1_eslint@8.28.0 eslint-utils: 2.1.0 ignore: 5.2.0 minimatch: 3.1.2 @@ -2635,7 +2645,7 @@ packages: semver: 6.3.0 dev: true - /eslint-plugin-prettier/4.2.1_v7o5sx5x3wbs57ifz6wc4f76we: + /eslint-plugin-prettier/4.2.1_cwlo2dingkvfydnaculr42urve: resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2646,45 +2656,47 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.27.0 - eslint-config-prettier: 8.5.0_eslint@8.27.0 - prettier: 2.7.1 + eslint: 8.28.0 + eslint-config-prettier: 8.5.0_eslint@8.28.0 + prettier: 2.8.0 prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-promise/6.1.1_eslint@8.27.0: + /eslint-plugin-promise/6.1.1_eslint@8.28.0: resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - eslint: 8.27.0 + eslint: 8.28.0 dev: true - /eslint-plugin-unicorn/44.0.2_eslint@8.27.0: - resolution: {integrity: sha512-GLIDX1wmeEqpGaKcnMcqRvMVsoabeF0Ton0EX4Th5u6Kmf7RM9WBl705AXFEsns56ESkEs0uyelLuUTvz9Tr0w==} + /eslint-plugin-unicorn/45.0.0_eslint@8.28.0: + resolution: {integrity: sha512-iP8cMRxXKHonKioOhnCoCcqVhoqhAp6rB+nsoLjXFDxTHz3btWMAp8xwzjHA0B1K6YV/U/Yvqn1bUXZt8sJPuQ==} engines: {node: '>=14.18'} peerDependencies: - eslint: '>=8.23.1' + eslint: '>=8.28.0' dependencies: '@babel/helper-validator-identifier': 7.19.1 - ci-info: 3.5.0 + ci-info: 3.7.0 clean-regexp: 1.0.0 - eslint: 8.27.0 - eslint-utils: 3.0.0_eslint@8.27.0 + eslint: 8.28.0 + eslint-utils: 3.0.0_eslint@8.28.0 esquery: 1.4.0 indent-string: 4.0.0 is-builtin-module: 3.2.0 + jsesc: 3.0.2 lodash: 4.17.21 pluralize: 8.0.0 read-pkg-up: 7.0.1 regexp-tree: 0.1.24 + regjsparser: 0.9.1 safe-regex: 2.1.1 - semver: 7.3.7 + semver: 7.3.8 strip-indent: 3.0.0 dev: true - /eslint-plugin-unused-imports/2.0.0_mb5ommioozas4vcfu4l3k44vny: + /eslint-plugin-unused-imports/2.0.0_aucl44mjeutxyzmt4nvo2cczya: resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -2694,8 +2706,8 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: - '@typescript-eslint/eslint-plugin': 5.43.0_wze2rj5tow7zwqpgbdx2buoy3m - eslint: 8.27.0 + '@typescript-eslint/eslint-plugin': 5.44.0_fnsv2sbzcckq65bwfk7a5xwslu + eslint: 8.28.0 eslint-rule-composer: 0.3.0 dev: true @@ -2727,13 +2739,13 @@ packages: eslint-visitor-keys: 1.3.0 dev: true - /eslint-utils/3.0.0_eslint@8.27.0: + /eslint-utils/3.0.0_eslint@8.28.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.27.0 + eslint: 8.28.0 eslint-visitor-keys: 2.1.0 dev: true @@ -2752,8 +2764,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint/8.27.0: - resolution: {integrity: sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==} + /eslint/8.28.0: + resolution: {integrity: sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: @@ -2768,7 +2780,7 @@ packages: doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.27.0 + eslint-utils: 3.0.0_eslint@8.28.0 eslint-visitor-keys: 3.3.0 espree: 9.4.1 esquery: 1.4.0 @@ -2784,7 +2796,7 @@ packages: imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 - js-sdsl: 4.1.5 + js-sdsl: 4.2.0 js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 @@ -4090,8 +4102,8 @@ packages: - ts-node dev: true - /js-sdsl/4.1.5: - resolution: {integrity: sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==} + /js-sdsl/4.2.0: + resolution: {integrity: sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==} dev: true /js-stringify/1.0.2: @@ -4131,12 +4143,23 @@ packages: gitignore-to-glob: 0.3.0 dev: true + /jsesc/0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + /jsesc/2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true dev: true + /jsesc/3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: true + /json-parse-better-errors/1.0.2: resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} dev: true @@ -4397,6 +4420,10 @@ packages: resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} dev: true + /lodash.memoize/4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + dev: true + /lodash.merge/4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true @@ -4427,6 +4454,10 @@ packages: semver: 6.3.0 dev: true + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + /make-fetch-happen/9.1.0: resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} engines: {node: '>= 10'} @@ -5032,8 +5063,8 @@ packages: fast-diff: 1.2.0 dev: true - /prettier/2.7.1: - resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} + /prettier/2.8.0: + resolution: {integrity: sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==} engines: {node: '>=10.13.0'} hasBin: true dev: true @@ -5269,6 +5300,13 @@ packages: engines: {node: '>=8'} dev: true + /regjsparser/0.9.1: + resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + /repeat-string/1.6.1: resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} engines: {node: '>=0.10'} @@ -5367,14 +5405,6 @@ packages: hasBin: true dev: true - /semver/7.3.7: - resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - /semver/7.3.8: resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} engines: {node: '>=10'} @@ -5736,6 +5766,39 @@ packages: engines: {node: '>=14'} dev: false + /ts-jest/29.0.3_4f6uxrzmuwipl5rr3bcogf6k74: + resolution: {integrity: sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + dependencies: + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + jest: 29.3.1 + jest-util: 29.3.1 + json5: 2.2.1 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.3.8 + typescript: 4.9.3 + yargs-parser: 21.1.1 + dev: true + /tsconfig-paths/3.14.1: resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} dependencies: diff --git a/tsconfig.build.json b/tsconfig.build.json index 1c1b048c..4bd3e654 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,21 +1,19 @@ { - "compilerOptions": { - "lib": ["ES2022"], - "target": "ES2022", - "strict": true, - "moduleResolution": "node", - "module": "ES2022", - "noEmitOnError": true, - "allowSyntheticDefaultImports": true, - "emitDecoratorMetadata": true, - "esModuleInterop": true, - "experimentalDecorators": true, - "skipLibCheck": true, - "declaration": true, - "incremental": true, - "composite": true, - "forceConsistentCasingInFileNames": true, - "noEmit": false - }, - "exclude": [ "node_modules", "dist"], - } \ No newline at end of file + "compilerOptions": { + "lib": ["ES2022"], + "target": "ES2022", + "strict": true, + "moduleResolution": "node", + "module": "ES2022", + "noEmitOnError": true, + "allowSyntheticDefaultImports": true, + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "skipLibCheck": true, + "declaration": true, + "incremental": true, + "forceConsistentCasingInFileNames": true + }, + "exclude": ["node_modules", "dist"] +} diff --git a/tsconfig.json b/tsconfig.json index e99e7e4e..2728f7ea 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,13 +1,13 @@ { "extends": "./tsconfig.build.json", - "exclude": ["./examples/*","./dist"], + "exclude": ["./examples/*", "./dist"], "compilerOptions": { "paths": { "@triptyk/nfw-core/*": ["./packages/core/src"], "@triptyk/nfw-http/*": ["./packages/http/src"], "@triptyk/nfw-jsonapi/*": ["./packages/jsonapi/tests/src"], "@triptyk/nfw-mikro-orm/*": ["./packages/mikro-orm/src"], - "*" : ["./node_modules/*"] + "*": ["./node_modules/*"] }, "noEmit": true } From 964478ca137bd23f82d8ac0e654ed384183261c4 Mon Sep 17 00:00:00 2001 From: AmauryD Date: Sat, 26 Nov 2022 15:22:13 +0100 Subject: [PATCH 5/7] ts-jest-vscode setup --- .vscode/settings.json | 24 ++++++++++-------------- jest.config.js | 30 +++++++++++++++++------------- package.json | 4 ++-- pnpm-lock.yaml | 26 +++++++++++++------------- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 896a7608..f0b91a09 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,16 +1,12 @@ { - "editor.formatOnSave": true, - "gitscrum.company": "triptyk", - "gitscrum.project-slug": "krs-logistics", - "editor.defaultFormatter": "dbaeumer.vscode-eslint", - "[typescript]": { - "editor.defaultFormatter": "dbaeumer.vscode-eslint" - }, - "eslint.validate": [ - "javascript", - "typescript" - ], - "eslint.format.enable": true, - "typescript.preferences.importModuleSpecifierEnding": "js", - "typescript.preferences.importModuleSpecifier": "project-relative" + "editor.formatOnSave": true, + "editor.defaultFormatter": "dbaeumer.vscode-eslint", + "[typescript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "eslint.validate": ["javascript", "typescript"], + "eslint.format.enable": true, + "typescript.preferences.importModuleSpecifierEnding": "js", + "typescript.preferences.importModuleSpecifier": "project-relative", + "jest.jestCommandLine": "pnpm test --" } diff --git a/jest.config.js b/jest.config.js index 57913b2a..e3791f3d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,28 +1,32 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ +const ESMPreset = { + preset: "ts-jest/presets/default-esm", // or other ESM presets + moduleNameMapper: { + "^(\\.{1,2}/.*)\\.js$": "$1", + }, + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + useESM: true, + }, + ], + }, +}; + function createProject(name) { return { displayName: name, testMatch: [`/packages/${name}/tests/**/*.test.ts`], - tsConfig: `/packages/${name}/tsconfig.json`, - preset: "ts-jest/presets/default-esm", // or other ESM presets - moduleNameMapper: { - "^(\\.{1,2}/.*)\\.js$": "$1", - }, - transform: { - "^.+\\.tsx?$": [ - "ts-jest", - { - useESM: true, - }, - ], - }, + ...ESMPreset, }; } export default { testEnvironment: "node", collectCoverage: Boolean(process.env.CI), + ...ESMPreset, projects: [ createProject("mikro-orm"), createProject("core"), diff --git a/package.json b/package.json index 0f5829ee..dd49b7dc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nfw-core", "version": "1.0.0", - "private": "true", + "private": true, "description": "", "main": "index.js", "scripts": { @@ -40,7 +40,7 @@ "eslint-plugin-promise": "^6.1.1", "eslint-plugin-unicorn": "^45.0.0", "eslint-plugin-unused-imports": "^2.0.0", - "jest": "^29.3.1", + "jest": "^29.0.2", "jscpd": "~3.5.1", "npm-run-all": "^4.1.5", "prettier": "^2.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce1cd6da..250869c6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,7 +24,7 @@ importers: eslint-plugin-promise: ^6.1.1 eslint-plugin-unicorn: ^45.0.0 eslint-plugin-unused-imports: ^2.0.0 - jest: ^29.3.1 + jest: ^29.0.2 jscpd: ~3.5.1 npm-run-all: ^4.1.5 prettier: ^2.8.0 @@ -44,18 +44,18 @@ importers: eslint-plugin-es: 4.1.0_eslint@8.28.0 eslint-plugin-filenames: 1.3.2_eslint@8.28.0 eslint-plugin-import: 2.26.0_vfrilbydaxalswvos6uuh4sxs4 - eslint-plugin-jest: 27.1.6_bifecjdquhom2xjmkl7gfpj6ma + eslint-plugin-jest: 27.1.6_ae2mh4xwjahfpse3cfxikresmq eslint-plugin-n: 15.5.1_eslint@8.28.0 eslint-plugin-node: 11.1.0_eslint@8.28.0 eslint-plugin-prettier: 4.2.1_cwlo2dingkvfydnaculr42urve eslint-plugin-promise: 6.1.1_eslint@8.28.0 eslint-plugin-unicorn: 45.0.0_eslint@8.28.0 eslint-plugin-unused-imports: 2.0.0_aucl44mjeutxyzmt4nvo2cczya - jest: 29.3.1 + jest: 29.0.2 jscpd: 3.5.1 npm-run-all: 4.1.5 prettier: 2.8.0 - ts-jest: 29.0.3_4f6uxrzmuwipl5rr3bcogf6k74 + ts-jest: 29.0.3_njtzcxnpzlmaf7be6e2mvjnsou typescript: 4.9.3 packages/core: @@ -674,7 +674,7 @@ packages: '@types/node': 18.11.9 ansi-escapes: 4.3.2 chalk: 4.1.2 - ci-info: 3.6.1 + ci-info: 3.7.0 exit: 0.1.2 graceful-fs: 4.2.10 jest-changed-files: 29.2.0 @@ -2591,7 +2591,7 @@ packages: - supports-color dev: true - /eslint-plugin-jest/27.1.6_bifecjdquhom2xjmkl7gfpj6ma: + /eslint-plugin-jest/27.1.6_ae2mh4xwjahfpse3cfxikresmq: resolution: {integrity: sha512-XA7RFLSrlQF9IGtAmhddkUkBuICCTuryfOTfCSWcZHiHb69OilIH05oozH2XA6CEOtztnOd0vgXyvxZodkxGjg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -2607,7 +2607,7 @@ packages: '@typescript-eslint/eslint-plugin': 5.44.0_fnsv2sbzcckq65bwfk7a5xwslu '@typescript-eslint/utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a eslint: 8.28.0 - jest: 29.3.1 + jest: 29.0.2 transitivePeerDependencies: - supports-color - typescript @@ -3735,7 +3735,7 @@ packages: '@jest/types': 29.3.1 babel-jest: 29.3.1_@babel+core@7.20.2 chalk: 4.1.2 - ci-info: 3.6.1 + ci-info: 3.7.0 deepmerge: 4.2.2 glob: 7.2.3 graceful-fs: 4.2.10 @@ -3774,7 +3774,7 @@ packages: '@types/node': 18.11.9 babel-jest: 29.3.1_@babel+core@7.20.2 chalk: 4.1.2 - ci-info: 3.6.1 + ci-info: 3.7.0 deepmerge: 4.2.2 glob: 7.2.3 graceful-fs: 4.2.10 @@ -4082,8 +4082,8 @@ packages: supports-color: 8.1.1 dev: true - /jest/29.3.1: - resolution: {integrity: sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==} + /jest/29.0.2: + resolution: {integrity: sha512-enziNbNUmXTcTaTP/Uq5rV91r0Yqy2UKzLUIabxMpGm9YHz8qpbJhiRnNVNvm6vzWfzt/0o97NEHH8/3udoClA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true peerDependencies: @@ -5766,7 +5766,7 @@ packages: engines: {node: '>=14'} dev: false - /ts-jest/29.0.3_4f6uxrzmuwipl5rr3bcogf6k74: + /ts-jest/29.0.3_njtzcxnpzlmaf7be6e2mvjnsou: resolution: {integrity: sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -5789,7 +5789,7 @@ packages: dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.3.1 + jest: 29.0.2 jest-util: 29.3.1 json5: 2.2.1 lodash.memoize: 4.1.2 From 6851a86af7aa4e9a1f1dd509ac592db0b58d9c2d Mon Sep 17 00:00:00 2001 From: AmauryD Date: Mon, 28 Nov 2022 16:51:21 +0100 Subject: [PATCH 6/7] progress --- .eslintrc.json | 1 + jest.config.js | 7 +- packages/jsonapi-new/.npmignore | 5 + packages/jsonapi-new/package.json | 56 ++++++++++ packages/jsonapi-new/src/index.ts | 0 .../jsonapi-new/src/interfaces/registry.ts | 7 ++ .../src/interfaces/relationship-serializer.ts | 5 + .../src/interfaces/relationship.ts | 6 ++ .../src/interfaces/resource-serializer.ts | 6 ++ .../jsonapi-new/src/interfaces/resource.ts | 8 ++ .../src/interfaces/top-level-serializer.ts | 5 + packages/jsonapi-new/src/registry.ts | 19 ++++ .../src/serializers/relationship.ts | 42 ++++++++ .../jsonapi-new/src/serializers/resource.ts | 36 +++++++ .../jsonapi-new/src/serializers/top-level.ts | 46 ++++++++ .../src/types/serialized-relationship.ts | 5 + .../src/types/serialized-resource.ts | 6 ++ packages/jsonapi-new/tests/fake/resources.ts | 57 ++++++++++ .../tests/fake/serializable-resources.ts | 0 .../jsonapi-new/tests/nfw-registry.test.ts | 11 ++ .../tests/relationship-serializer.test.ts | 74 +++++++++++++ packages/jsonapi-new/tests/serializer.test.ts | 68 ++++++++++++ .../tests/top-level-serializer.test.ts | 102 ++++++++++++++++++ packages/jsonapi-new/tsconfig.build.json | 11 ++ packages/jsonapi-new/tsconfig.json | 3 + pnpm-lock.yaml | 49 +++++++++ tsconfig.json | 1 + 27 files changed, 633 insertions(+), 3 deletions(-) create mode 100644 packages/jsonapi-new/.npmignore create mode 100644 packages/jsonapi-new/package.json create mode 100644 packages/jsonapi-new/src/index.ts create mode 100644 packages/jsonapi-new/src/interfaces/registry.ts create mode 100644 packages/jsonapi-new/src/interfaces/relationship-serializer.ts create mode 100644 packages/jsonapi-new/src/interfaces/relationship.ts create mode 100644 packages/jsonapi-new/src/interfaces/resource-serializer.ts create mode 100644 packages/jsonapi-new/src/interfaces/resource.ts create mode 100644 packages/jsonapi-new/src/interfaces/top-level-serializer.ts create mode 100644 packages/jsonapi-new/src/registry.ts create mode 100644 packages/jsonapi-new/src/serializers/relationship.ts create mode 100644 packages/jsonapi-new/src/serializers/resource.ts create mode 100644 packages/jsonapi-new/src/serializers/top-level.ts create mode 100644 packages/jsonapi-new/src/types/serialized-relationship.ts create mode 100644 packages/jsonapi-new/src/types/serialized-resource.ts create mode 100644 packages/jsonapi-new/tests/fake/resources.ts create mode 100644 packages/jsonapi-new/tests/fake/serializable-resources.ts create mode 100644 packages/jsonapi-new/tests/nfw-registry.test.ts create mode 100644 packages/jsonapi-new/tests/relationship-serializer.test.ts create mode 100644 packages/jsonapi-new/tests/serializer.test.ts create mode 100644 packages/jsonapi-new/tests/top-level-serializer.test.ts create mode 100644 packages/jsonapi-new/tsconfig.build.json create mode 100644 packages/jsonapi-new/tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json index c7447f4c..c78f518d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,6 +7,7 @@ "root": true, "extends": ["standard"], "parser": "@typescript-eslint/parser", + "ignorePatterns": ["*.js"], "parserOptions": { "ecmaVersion": 12, "sourceType": "module", diff --git a/jest.config.js b/jest.config.js index e3791f3d..394507e3 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,3 @@ -/** @type {import('ts-jest').JestConfigWithTsJest} */ - const ESMPreset = { preset: "ts-jest/presets/default-esm", // or other ESM presets moduleNameMapper: { @@ -18,19 +16,22 @@ const ESMPreset = { function createProject(name) { return { displayName: name, + coveragePathIgnorePatterns: [`/packages/${name}/tests/.*`], + collectCoverageFrom: [`packages/${name}/src/**/*.ts`], testMatch: [`/packages/${name}/tests/**/*.test.ts`], ...ESMPreset, }; } +/** @type {import('ts-jest').JestConfigWithTsJest} */ export default { testEnvironment: "node", collectCoverage: Boolean(process.env.CI), - ...ESMPreset, projects: [ createProject("mikro-orm"), createProject("core"), createProject("http"), createProject("jsonapi"), + createProject("jsonapi-new"), ], }; diff --git a/packages/jsonapi-new/.npmignore b/packages/jsonapi-new/.npmignore new file mode 100644 index 00000000..f06ebedb --- /dev/null +++ b/packages/jsonapi-new/.npmignore @@ -0,0 +1,5 @@ +src/ +tests/ +dist/tests/ +dist/coverage/ +tsconfig.build.tsbuildinfo \ No newline at end of file diff --git a/packages/jsonapi-new/package.json b/packages/jsonapi-new/package.json new file mode 100644 index 00000000..d36e0a38 --- /dev/null +++ b/packages/jsonapi-new/package.json @@ -0,0 +1,56 @@ +{ + "name": "@triptyk/nfw-jsonapi-new", + "version": "4.0.0-alpha.27", + "description": "JSON:API module for NFW-CORE", + "main": "dist/src/index.js", + "types": "dist/src/index.d.ts", + "scripts": { + "prepublishOnly": "pnpm run build", + "build": "tsc -p tsconfig.build.json", + "build:clean": "rm -f tsconfig.tsbuildinfo && rm -rf dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/TRIPTYK/nfw-core.git" + }, + "type": "module", + "author": "TRIPTYK", + "engines": { + "node": ">=16.3.1" + }, + "contributors": [ + "Amaury Deflorenne (https://github.com/AmauryD)", + "Gilles Bertrand (https://github.com/gilles-bertrand)", + "Romain Verliefden (https://github.com/DramixDW)" + ], + "license": "MIT", + "devDependencies": { + "@mikro-orm/core": "~5.5.3", + "@mikro-orm/knex": "~5.5.3", + "@mikro-orm/sqlite": "~5.5.3", + "@nestjs/class-validator": "^0.13.4", + "@triptyk/nfw-core": "workspace:*", + "@types/koa": "^2.13.5", + "@types/koa-qs": "^2.0.0", + "@types/koa__router": "^12.0.0", + "@types/node": "^18.11.9", + "@types/pluralize": "^0.0.29", + "node-mocks-http": "^1.11.0", + "reflect-metadata": "^0.1.13", + "tsyringe": "4.7.0", + "type-fest": "^3.2.0", + "typescript": "~4.9.3" + }, + "dependencies": { + "@casl/ability": "~6.3.2", + "@koa/router": "~12.0.0", + "fastest-validator": "~1.15.0", + "fastest-validator-decorators": "~2.0.0", + "koa-qs": "~3.0.0", + "pluralize": "~8.0.0", + "ts-deepmerge": "~5.0.0" + }, + "peerDependencies": { + "@triptyk/nfw-core": "workspace:*" + } +} \ No newline at end of file diff --git a/packages/jsonapi-new/src/index.ts b/packages/jsonapi-new/src/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/jsonapi-new/src/interfaces/registry.ts b/packages/jsonapi-new/src/interfaces/registry.ts new file mode 100644 index 00000000..60e804b7 --- /dev/null +++ b/packages/jsonapi-new/src/interfaces/registry.ts @@ -0,0 +1,7 @@ +import type { Class } from 'type-fest'; +import type { ResourceSerializerInterface } from './resource-serializer.js'; + +export interface RegistryInterface { + registerSerializerFor(resourceName: string, serializer: Class): void, + serializerFor(resourceName: string): ResourceSerializerInterface | undefined, +} diff --git a/packages/jsonapi-new/src/interfaces/relationship-serializer.ts b/packages/jsonapi-new/src/interfaces/relationship-serializer.ts new file mode 100644 index 00000000..6f2f3cd2 --- /dev/null +++ b/packages/jsonapi-new/src/interfaces/relationship-serializer.ts @@ -0,0 +1,5 @@ +import type { RelationshipInterface } from './relationship.js'; + +export interface RelationshipSerializerInterface { + serialize(relationship: RelationshipInterface): unknown, +} diff --git a/packages/jsonapi-new/src/interfaces/relationship.ts b/packages/jsonapi-new/src/interfaces/relationship.ts new file mode 100644 index 00000000..3dcdd4f0 --- /dev/null +++ b/packages/jsonapi-new/src/interfaces/relationship.ts @@ -0,0 +1,6 @@ +import type { ResourceInterface } from './resource.js'; + +export interface RelationshipInterface { + name: string, + value: ResourceInterface | ResourceInterface[] | null | undefined, +} diff --git a/packages/jsonapi-new/src/interfaces/resource-serializer.ts b/packages/jsonapi-new/src/interfaces/resource-serializer.ts new file mode 100644 index 00000000..0b6ae361 --- /dev/null +++ b/packages/jsonapi-new/src/interfaces/resource-serializer.ts @@ -0,0 +1,6 @@ +import type { SerializedResourceType } from '../types/serialized-resource.js'; +import type { ResourceInterface } from './resource.js'; + +export interface ResourceSerializerInterface { + serialize(resource: ResourceInterface): SerializedResourceType, +} diff --git a/packages/jsonapi-new/src/interfaces/resource.ts b/packages/jsonapi-new/src/interfaces/resource.ts new file mode 100644 index 00000000..eb36349d --- /dev/null +++ b/packages/jsonapi-new/src/interfaces/resource.ts @@ -0,0 +1,8 @@ +import type { RelationshipInterface } from './relationship.js'; + +export interface ResourceInterface { + getName(): string, + getId(): string, + attributes(): Record, + relationships(): RelationshipInterface[], +} diff --git a/packages/jsonapi-new/src/interfaces/top-level-serializer.ts b/packages/jsonapi-new/src/interfaces/top-level-serializer.ts new file mode 100644 index 00000000..96ccd151 --- /dev/null +++ b/packages/jsonapi-new/src/interfaces/top-level-serializer.ts @@ -0,0 +1,5 @@ +import type { ResourceInterface } from './resource.js'; + +export interface TopLevelSerializerInterface { + serialize(resource: ResourceInterface | ResourceInterface[] | null): unknown, +} diff --git a/packages/jsonapi-new/src/registry.ts b/packages/jsonapi-new/src/registry.ts new file mode 100644 index 00000000..a1bcdfc3 --- /dev/null +++ b/packages/jsonapi-new/src/registry.ts @@ -0,0 +1,19 @@ +/* eslint-disable class-methods-use-this */ +import type { RegistryInterface } from './interfaces/registry.js'; +import type { ResourceSerializerInterface } from './interfaces/resource-serializer.js'; +import { container } from '@triptyk/nfw-core'; +import type { Class } from 'type-fest'; + +export class NFWRegistry implements RegistryInterface { + public registerSerializerFor (resourceName: string, serializer: Class): void { + container.registerInstance(this.serializerTokenName(resourceName), container.resolve(serializer)); + } + + public serializerFor (resourceName: string): ResourceSerializerInterface { + return container.resolve(this.serializerTokenName(resourceName)); + } + + private serializerTokenName (resourceName: string) { + return `serializer:${resourceName}`; + } +} diff --git a/packages/jsonapi-new/src/serializers/relationship.ts b/packages/jsonapi-new/src/serializers/relationship.ts new file mode 100644 index 00000000..e13d5af5 --- /dev/null +++ b/packages/jsonapi-new/src/serializers/relationship.ts @@ -0,0 +1,42 @@ +import type { RelationshipSerializerInterface } from '../interfaces/relationship-serializer.js'; +import type { RelationshipInterface } from '../interfaces/relationship.js'; +import type { ResourceInterface } from '../interfaces/resource.js'; +import type { SerializedRelationshipType } from '../types/serialized-relationship.js'; + +export class RelationshipSerializer implements RelationshipSerializerInterface { + public constructor ( + private parentResource: ResourceInterface + ) {} + + public serialize (resource: RelationshipInterface): unknown { + const relationship: SerializedRelationshipType = { + links: this.makeLinks(resource.name) + }; + if (resource.value !== undefined) { + relationship.data = this.makeData(resource.value); + } + return relationship; + } + + private makeLinks (relationName: string) { + return { + self: `/${this.parentResource.getName()}/${this.parentResource.getId()}/relationships/${relationName}`, + related: `/${this.parentResource.getName()}/${this.parentResource.getId()}/${relationName}` + }; + } + + private makeData (resource: ResourceInterface | ResourceInterface[] | null) { + if (resource === null) { + // eslint-disable-next-line unicorn/no-null + return null; + } + if (Array.isArray(resource)) { + return resource.map((r) => this.makeSingleData(r)); + } + return this.makeSingleData(resource); + } + + private makeSingleData (value: ResourceInterface) { + return { type: value!.getName(), id: value.getId() }; + } +} diff --git a/packages/jsonapi-new/src/serializers/resource.ts b/packages/jsonapi-new/src/serializers/resource.ts new file mode 100644 index 00000000..450cf33a --- /dev/null +++ b/packages/jsonapi-new/src/serializers/resource.ts @@ -0,0 +1,36 @@ +import type { RelationshipInterface } from '../interfaces/relationship.js'; +import type { ResourceSerializerInterface } from '../interfaces/resource-serializer.js'; +import type { ResourceInterface } from '../interfaces/resource.js'; +import type { SerializedResourceType } from '../types/serialized-resource.js'; +import { RelationshipSerializer } from './relationship.js'; + +export class ResourceSerializer implements ResourceSerializerInterface { + public serialize (resource: ResourceInterface) { + const relationships = this.serializeRelationships(resource); + + const serialized: SerializedResourceType = { + type: resource.getName(), + id: resource.getId(), + attributes: resource.attributes() + }; + + if (Object.keys(relationships).length > 0) { + serialized.relationships = relationships; + } + + return serialized; + } + + private serializeRelationships (resource: ResourceInterface) { + const relationships: Record = {}; + for (const relation of resource.relationships()) { + relationships[relation.name] = this.serializeRelation(resource, relation); + } + return relationships; + } + + private serializeRelation (resource: ResourceInterface, relation : RelationshipInterface) { + const relationshipData = new RelationshipSerializer(resource); + return relationshipData.serialize(relation); + } +} diff --git a/packages/jsonapi-new/src/serializers/top-level.ts b/packages/jsonapi-new/src/serializers/top-level.ts new file mode 100644 index 00000000..b9faf516 --- /dev/null +++ b/packages/jsonapi-new/src/serializers/top-level.ts @@ -0,0 +1,46 @@ +// eslint-disable-next-line max-classes-per-file +import type { RegistryInterface } from '../interfaces/registry.js'; +import type { ResourceInterface } from '../interfaces/resource.js'; +import type { TopLevelSerializerInterface } from '../interfaces/top-level-serializer.js'; +import type { SerializedResourceType } from '../types/serialized-resource.js'; + +export class TopLevelSerializer implements TopLevelSerializerInterface { + public constructor ( + public registry : RegistryInterface + ) {} + + public serialize (resource: ResourceInterface | ResourceInterface[] | null) { + const included = new Map(); + return { + data: this.makeData(resource, included), + included: Array.from(included.values()) + }; + } + + private makeData (resource: ResourceInterface | ResourceInterface[] | null, included: Map) { + if (resource === null) { + // eslint-disable-next-line unicorn/no-null + return null; + } + if (Array.isArray(resource)) { + return resource.map((r) => this.serializeOneResource(r, included)); + } + return this.serializeOneResource(resource, included); + } + + // eslint-disable-next-line max-statements + private serializeOneResource (resource: ResourceInterface, included: Map) { + const serialized = this.serializeResource(resource); + for (const relationship of resource.relationships()) { + if (relationship.value !== undefined) { + this.makeData(relationship.value, included); + } + } + return serialized; + } + + private serializeResource (resource: ResourceInterface) { + const serializer = this.registry.serializerFor(resource.getName()); + return serializer!.serialize(resource); + } +} diff --git a/packages/jsonapi-new/src/types/serialized-relationship.ts b/packages/jsonapi-new/src/types/serialized-relationship.ts new file mode 100644 index 00000000..e73e02ee --- /dev/null +++ b/packages/jsonapi-new/src/types/serialized-relationship.ts @@ -0,0 +1,5 @@ + +export interface SerializedRelationshipType { + links: Record, + data?: unknown, +} diff --git a/packages/jsonapi-new/src/types/serialized-resource.ts b/packages/jsonapi-new/src/types/serialized-resource.ts new file mode 100644 index 00000000..99186da2 --- /dev/null +++ b/packages/jsonapi-new/src/types/serialized-resource.ts @@ -0,0 +1,6 @@ +export interface SerializedResourceType { + type: string, + id: string, + attributes: Record, + relationships?: Record, + } diff --git a/packages/jsonapi-new/tests/fake/resources.ts b/packages/jsonapi-new/tests/fake/resources.ts new file mode 100644 index 00000000..d6730774 --- /dev/null +++ b/packages/jsonapi-new/tests/fake/resources.ts @@ -0,0 +1,57 @@ +/* eslint-disable class-methods-use-this */ +/* eslint-disable max-classes-per-file */ +import type { ResourceInterface } from '../../src/interfaces/resource.js'; + +export class ArticleResource implements ResourceInterface { + public constructor ( + public id: string + ) {} + + public relationships () { + return []; + } + + public getName (): string { + return 'articles'; + } + + public getId (): string { + return this.id; + } + + public attributes () { + return {}; + } +} + +export class UserResource implements ResourceInterface { + public articles: ArticleResource[] = []; + + public constructor ( + public name: string, + public id: string, + public article?: ArticleResource + ) {} + + public relationships () { + return [ + { value: this.article, name: 'article' }, + { value: this.articles, name: 'articles' } + ]; + } + + public attributes () { + return { + name: this.name + }; + } + + // eslint-disable-next-line class-methods-use-this + public getName (): string { + return 'users'; + } + + public getId (): string { + return this.id; + } +} diff --git a/packages/jsonapi-new/tests/fake/serializable-resources.ts b/packages/jsonapi-new/tests/fake/serializable-resources.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/jsonapi-new/tests/nfw-registry.test.ts b/packages/jsonapi-new/tests/nfw-registry.test.ts new file mode 100644 index 00000000..3d914a1b --- /dev/null +++ b/packages/jsonapi-new/tests/nfw-registry.test.ts @@ -0,0 +1,11 @@ +import 'reflect-metadata'; +import { NFWRegistry } from '../src/registry.js'; +import { ResourceSerializer } from '../src/serializers/resource.js'; + +class UsersSerializer extends ResourceSerializer {} + +test('Register serializer in registry for resource', () => { + const registry = new NFWRegistry(); + registry.registerSerializerFor('articles', UsersSerializer); + expect(registry.serializerFor('articles')).toBeInstanceOf(UsersSerializer); +}); diff --git a/packages/jsonapi-new/tests/relationship-serializer.test.ts b/packages/jsonapi-new/tests/relationship-serializer.test.ts new file mode 100644 index 00000000..fbb699a7 --- /dev/null +++ b/packages/jsonapi-new/tests/relationship-serializer.test.ts @@ -0,0 +1,74 @@ +import { RelationshipSerializer } from '../src/serializers/relationship.js'; +import { ArticleResource, UserResource } from './fake/resources.js'; + +it('Serializes an empty relationship', () => { + const user = new UserResource('amaury', '1'); + user.article = undefined; + const serializer = new RelationshipSerializer( + user + ); + expect(serializer.serialize({ + value: user.article!, + name: 'article' + })).toStrictEqual({ + links: { + self: '/users/1/relationships/article', + related: '/users/1/article' + } + }); +}); + +it('Serializes a single relationship', () => { + const user = new UserResource('amaury', '1'); + user.article = new ArticleResource('2'); + const serializer = new RelationshipSerializer( + user + ); + expect(serializer.serialize({ + name: 'article', + value: user.article + })).toStrictEqual({ + links: { + self: '/users/1/relationships/article', + related: '/users/1/article' + }, + data: { type: 'articles', id: '2' } + }); +}); + +it('Serializes a null relationship', () => { + const user = new UserResource('amaury', '1'); + const serializer = new RelationshipSerializer( + user + ); + expect(serializer.serialize({ + name: 'article', + // eslint-disable-next-line unicorn/no-null + value: null + })).toStrictEqual({ + links: { + self: '/users/1/relationships/article', + related: '/users/1/article' + }, + // eslint-disable-next-line unicorn/no-null + data: null + }); +}); + +it('Serializes a many-relationship', () => { + const user = new UserResource('amaury', '1'); + user.articles = [new ArticleResource('2')]; + const serializer = new RelationshipSerializer( + user + ); + expect(serializer.serialize({ + name: 'articles', + value: user.articles + })).toStrictEqual({ + links: { + self: '/users/1/relationships/articles', + related: '/users/1/articles' + }, + data: [{ type: 'articles', id: '2' }] + }); +}); diff --git a/packages/jsonapi-new/tests/serializer.test.ts b/packages/jsonapi-new/tests/serializer.test.ts new file mode 100644 index 00000000..51a4d489 --- /dev/null +++ b/packages/jsonapi-new/tests/serializer.test.ts @@ -0,0 +1,68 @@ +/* eslint-disable class-methods-use-this */ +/* eslint-disable max-classes-per-file */ +import type { ResourceSerializerInterface } from '../src/interfaces/resource-serializer.js'; +import { ResourceSerializer } from '../src/serializers/resource.js'; +import { UserResource, ArticleResource } from './fake/resources.js'; + +let serializer: ResourceSerializerInterface; + +beforeEach(() => { + serializer = new ResourceSerializer(); +}); + +test('It serializes a resource with no relationships', () => { + const resource = new UserResource('amaury', '1'); + resource.article = undefined; + + expect(serializer.serialize(resource)).toStrictEqual({ + type: 'users', + id: '1', + attributes: { + name: 'amaury' + }, + relationships: { + article: { + links: { + self: '/users/1/relationships/article', + related: '/users/1/article' + } + }, + articles: { + links: { + self: '/users/1/relationships/articles', + related: '/users/1/articles' + }, + data: [] + } + } + }); +}); + +test('It serializes a resource with relationships', () => { + const articleResource = new ArticleResource('2'); + const resource = new UserResource('amaury', '1', articleResource); + + expect(serializer.serialize(resource)).toStrictEqual({ + type: 'users', + id: '1', + attributes: { + name: 'amaury' + }, + relationships: { + article: { + links: { + self: '/users/1/relationships/article', + related: '/users/1/article' + }, + data: { type: 'articles', id: '2' } + }, + articles: { + links: { + self: '/users/1/relationships/articles', + related: '/users/1/articles' + }, + data: [] + } + } + }); +}); diff --git a/packages/jsonapi-new/tests/top-level-serializer.test.ts b/packages/jsonapi-new/tests/top-level-serializer.test.ts new file mode 100644 index 00000000..4e9094b1 --- /dev/null +++ b/packages/jsonapi-new/tests/top-level-serializer.test.ts @@ -0,0 +1,102 @@ +/* eslint-disable class-methods-use-this */ +import type { RegistryInterface } from '../src/interfaces/registry.js'; +import type { ResourceSerializerInterface } from '../src/interfaces/resource-serializer.js'; +import type { TopLevelSerializerInterface } from '../src/interfaces/top-level-serializer.js'; +import { ResourceSerializer } from '../src/serializers/resource.js'; +import { TopLevelSerializer } from '../src/serializers/top-level.js'; +import { ArticleResource, UserResource } from './fake/resources.js'; + +const articlesSerializer: ResourceSerializerInterface = new ResourceSerializer(); +const usersSerializer: ResourceSerializerInterface = new ResourceSerializer(); + +class CustomRegistry implements RegistryInterface { + public registerSerializerFor (): void {} + + public serializerFor (resourceName: string): ResourceSerializerInterface | undefined { + if (resourceName === 'articles') { + return articlesSerializer; + } + if (resourceName === 'users') { + return usersSerializer; + } + } +} + +let userResource: UserResource; +let registry: RegistryInterface; +let serializer: TopLevelSerializerInterface; + +beforeEach(() => { + userResource = new UserResource('amaury', '3'); + registry = new CustomRegistry(); + serializer = new TopLevelSerializer( + registry + ); +}); + +it('It serializes a resource to a top level document', () => { + expect(serializer.serialize(userResource)).toStrictEqual({ + data: { + type: 'users', + id: '3', + attributes: { + name: 'amaury' + }, + relationships: { + articles: { + links: { + self: '/users/3/relationships/articles', + related: '/users/3/articles' + }, + data: [] + }, + article: { + links: { + self: '/users/3/relationships/article', + related: '/users/3/article' + } + } + } + } + }); +}); + +it('It serializes a resource with its relationships', () => { + userResource.article = new ArticleResource('3'); + + expect(serializer.serialize(userResource)).toStrictEqual({ + data: { + type: 'users', + id: '3', + attributes: { + name: 'amaury' + }, + relationships: { + articles: { + links: { + self: '/users/3/relationships/articles', + related: '/users/3/articles' + }, + data: [] + }, + article: { + links: { + self: '/users/3/relationships/article', + related: '/users/3/article' + }, + data: { + type: 'articles', + data: '1' + } + } + } + }, + included: [ + { + type: 'articles', + id: '1', + attributes: {} + } + ] + }); +}); diff --git a/packages/jsonapi-new/tsconfig.build.json b/packages/jsonapi-new/tsconfig.build.json new file mode 100644 index 00000000..7a607182 --- /dev/null +++ b/packages/jsonapi-new/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "./dist", + "esModuleInterop": true + }, + "include": [ + "src/**/*", + "tests/**/*" + ] +} diff --git a/packages/jsonapi-new/tsconfig.json b/packages/jsonapi-new/tsconfig.json new file mode 100644 index 00000000..4082f16a --- /dev/null +++ b/packages/jsonapi-new/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tsconfig.json" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 250869c6..39a0b951 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,6 +159,55 @@ importers: type-fest: 3.2.0 typescript: 4.9.3 + packages/jsonapi-new: + specifiers: + '@casl/ability': ~6.3.2 + '@koa/router': ~12.0.0 + '@mikro-orm/core': ~5.5.3 + '@mikro-orm/knex': ~5.5.3 + '@mikro-orm/sqlite': ~5.5.3 + '@nestjs/class-validator': ^0.13.4 + '@triptyk/nfw-core': workspace:* + '@types/koa': ^2.13.5 + '@types/koa-qs': ^2.0.0 + '@types/koa__router': ^12.0.0 + '@types/node': ^18.11.9 + '@types/pluralize': ^0.0.29 + fastest-validator: ~1.15.0 + fastest-validator-decorators: ~2.0.0 + koa-qs: ~3.0.0 + node-mocks-http: ^1.11.0 + pluralize: ~8.0.0 + reflect-metadata: ^0.1.13 + ts-deepmerge: ~5.0.0 + tsyringe: 4.7.0 + type-fest: ^3.2.0 + typescript: ~4.9.3 + dependencies: + '@casl/ability': 6.3.2 + '@koa/router': 12.0.0 + fastest-validator: 1.15.0 + fastest-validator-decorators: 2.0.0_fastest-validator@1.15.0 + koa-qs: 3.0.0 + pluralize: 8.0.0 + ts-deepmerge: 5.0.0 + devDependencies: + '@mikro-orm/core': 5.5.3_@mikro-orm+sqlite@5.5.3 + '@mikro-orm/knex': 5.5.3_@mikro-orm+core@5.5.3 + '@mikro-orm/sqlite': 5.5.3_@mikro-orm+core@5.5.3 + '@nestjs/class-validator': 0.13.4 + '@triptyk/nfw-core': link:../core + '@types/koa': 2.13.5 + '@types/koa-qs': 2.0.0 + '@types/koa__router': 12.0.0 + '@types/node': 18.11.9 + '@types/pluralize': 0.0.29 + node-mocks-http: 1.12.1 + reflect-metadata: 0.1.13 + tsyringe: 4.7.0 + type-fest: 3.2.0 + typescript: 4.9.3 + packages/mikro-orm: specifiers: '@mikro-orm/core': ~5.5.3 diff --git a/tsconfig.json b/tsconfig.json index 2728f7ea..3442955a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "@triptyk/nfw-core/*": ["./packages/core/src"], "@triptyk/nfw-http/*": ["./packages/http/src"], "@triptyk/nfw-jsonapi/*": ["./packages/jsonapi/tests/src"], + "@triptyk/nfw-jsonapi-new/*": ["./packages/jsonapi-new/tests/src"], "@triptyk/nfw-mikro-orm/*": ["./packages/mikro-orm/src"], "*": ["./node_modules/*"] }, From 900210a63627d5abd84d1791cf9742c35d005fc9 Mon Sep 17 00:00:00 2001 From: AmauryD Date: Mon, 28 Nov 2022 16:55:04 +0100 Subject: [PATCH 7/7] cahnge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c15b856f..99284c10 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,6 @@ A NodeJS Typescript framework using Koa ! +Nothing has changed + ## [See the wiki !](https://triptyk.github.io/nfw-core/) \ No newline at end of file