Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions packages/app/tests/service-container.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,6 @@ test('exported module', () => {
});

test('scoped InjectorContext access', () => {
class RpcInjectorContext extends InjectorContext {
}

class MyService {
constructor(public injectorContext: InjectorContext) {
}
Expand All @@ -286,7 +283,7 @@ test('scoped InjectorContext access', () => {
const myModule = new AppModule({}, {
providers: [
{ provide: MyService },
{ provide: RpcInjectorContext, scope: 'rpc', useValue: undefined },
{ provide: InjectorContext, scope: 'rpc', useValue: undefined },
]
});

Expand All @@ -299,7 +296,7 @@ test('scoped InjectorContext access', () => {

{
const injector = serviceContainer.getInjectorContext().createChildScope('rpc');
injector.set(RpcInjectorContext, injector);
injector.set(InjectorContext, injector);

const myService = injector.get(MyService);
expect(myService.injectorContext).toBeInstanceOf(InjectorContext);
Expand Down
6 changes: 3 additions & 3 deletions packages/framework/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { Zone } from './zone.js';
import { DebugBrokerBus } from './debug/broker.js';
import { ApiConsoleModule } from '@deepkit/api-console-module';
import { AppModule, ControllerConfig, createModuleClass, DeepPartial, onAppShutdown } from '@deepkit/app';
import { RpcControllers, RpcInjectorContext, RpcKernelWithStopwatch } from './rpc.js';
import { RpcControllers, RpcKernelWithStopwatch } from './rpc.js';
import { normalizeDirectory } from './utils.js';
import { FilesystemRegistry, PublicFilesystem } from './filesystem.js';
import { Filesystem } from '@deepkit/filesystem';
Expand Down Expand Up @@ -92,7 +92,7 @@ export class FrameworkModule extends createModuleClass({

//all of these will be set on scope creation
{ provide: HttpRequest, scope: 'rpc', useValue: undefined },
{ provide: RpcInjectorContext, scope: 'rpc', useValue: undefined },
{ provide: InjectorContext, scope: 'rpc', useValue: undefined },
{ provide: SessionState, scope: 'rpc', useValue: undefined },
{ provide: RpcKernelBaseConnection, scope: 'rpc', useValue: undefined },
{ provide: RpcKernelConnection, scope: 'rpc', useValue: undefined },
Expand Down Expand Up @@ -125,7 +125,7 @@ export class FrameworkModule extends createModuleClass({
DatabaseRegistry,

HttpRequest,
RpcInjectorContext,
InjectorContext,
SessionState,
RpcKernelConnection,
RpcKernelBaseConnection,
Expand Down
3 changes: 0 additions & 3 deletions packages/framework/src/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ export class RpcControllers {
public readonly controllers = new Map<string, { controller: ClassType, module: AppModule<any> }>();
}

export class RpcInjectorContext extends InjectorContext {
}

export class RpcServerActionWithStopwatch extends RpcServerAction {
stopwatch?: Stopwatch;

Expand Down
5 changes: 5 additions & 0 deletions packages/framework/src/testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export class TestingFacade<A extends App<any>> {
await this.app.get(ApplicationServer).close(graceful);
}

/**
* ```typescript
* const response = await testing.request(HttpRequest.GET('/test').header('x-test', '123'));
* ```
*/
public async request(requestBuilder: RequestBuilder): Promise<MemoryHttpResponse> {
const request = requestBuilder.build();
const response = new MemoryHttpResponse(request);
Expand Down
5 changes: 2 additions & 3 deletions packages/framework/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import selfsigned from 'selfsigned';

import { HttpConfig, HttpKernel, HttpRequest, HttpResponse } from '@deepkit/http';
import { InjectorContext } from '@deepkit/injector';
import { RpcControllers, RpcInjectorContext } from './rpc.js';
import { RpcControllers } from './rpc.js';
import { SecureContextOptions, TlsOptions } from 'tls';

// @ts-ignore
Expand Down Expand Up @@ -174,8 +174,7 @@ export class WebMemoryWorkerFactory extends WebWorkerFactory {
export function createRpcConnection(rootScopedContext: InjectorContext, rpcKernel: RpcKernel, transport: TransportConnection, request?: HttpRequest) {
const injector = rootScopedContext.createChildScope('rpc');
injector.set(HttpRequest, request);
injector.set(RpcInjectorContext, injector);

injector.set(InjectorContext, injector);
const connection = rpcKernel.createConnection(transport, injector);
injector.set(SessionState, connection.sessionState);
injector.set(RpcKernelConnection, connection);
Expand Down
53 changes: 50 additions & 3 deletions packages/framework/tests/rpc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { expect, test } from '@jest/globals';
import { ControllerSymbol, rpc, RpcKernelConnection, RpcKernelSecurity, Session, SessionState } from '@deepkit/rpc';
import { createTestingApp } from '../src/testing.js';
import { AppModule } from '@deepkit/app';
import { InjectorContext } from '@deepkit/injector';
import { http, HttpQuery, HttpRequest } from '@deepkit/http';

test('di', async () => {
class MyService {
Expand Down Expand Up @@ -100,8 +102,8 @@ test('module provides RpcKernelSecurity', async () => {
name: 'module',
controllers: [Controller],
providers: [{
provide: RpcKernelSecurity, useClass: MyRpcKernelSecurity, scope: 'rpc'
}]
provide: RpcKernelSecurity, useClass: MyRpcKernelSecurity, scope: 'rpc',
}],
}).forRoot();
const testing = createTestingApp({ imports: [module] });
await testing.startServer();
Expand Down Expand Up @@ -143,7 +145,7 @@ test('rpc controller access unscoped provider', async () => {

const testing = createTestingApp({
controllers: [Controller],
providers: [ModelRegistryService]
providers: [ModelRegistryService],
});

const client = testing.createRpcClient();
Expand All @@ -153,3 +155,48 @@ test('rpc controller access unscoped provider', async () => {
const registry = testing.app.get(ModelRegistryService);
expect(registry.models).toEqual(['a']);
});

test('InjectorContext', async () => {
@rpc.controller('main')
class RpcController {
constructor(private injectorContext: InjectorContext) {
}

@rpc.action()
test() {
expect(this.injectorContext.scope?.name).toBe('rpc');
expect(this.injectorContext.getOrUndefined(HttpRequest)?.url).toBe(undefined);
}
}

class HttpController {
constructor(private injectorContext: InjectorContext) {
}

@http.GET('/test')
test(q: HttpQuery<string>) {
expect(this.injectorContext.scope?.name).toBe('http');
expect(this.injectorContext.get(HttpRequest)?.url).toBe('/test?q=' + q);
}
}

const testing = createTestingApp({
controllers: [RpcController, HttpController],
});

await testing.startServer();

const request1 = await testing.request(HttpRequest.GET('/test?q=1'));
expect(request1.statusCode).toBe(200);
const request2 = await testing.request(HttpRequest.GET('/test?q=2'));
expect(request2.statusCode).toBe(200);

const client = testing.createRpcClient();
const controller = client.controller<RpcController>('main');
await controller.test();

const request3 = await testing.request(HttpRequest.GET('/test?q=3'));
expect(request3.statusCode).toBe(200);

await testing.stopServer();
});
2 changes: 1 addition & 1 deletion packages/http/src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ export class HttpListener {
protected injector: Injector,
protected stopwatch: Stopwatch,
) {
this.setRouteConfig = injector.createSetter(RouteConfig, {name: 'http'});
this.setRouteConfig = injector.createSetter(RouteConfig, 'http');
}

@eventDispatcher.listen(httpWorkflow.onRequest, 100)
Expand Down
6 changes: 4 additions & 2 deletions packages/http/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ export class HttpModule extends createModuleClass({
HttpResultFormatter,
HttpRouterRegistry,
HttpRouterFilterResolver,
{ provide: HttpResponse, scope: 'http' },
{ provide: HttpRequest, scope: 'http' },
{ provide: InjectorContext, useValue: undefined, scope: 'http' },
{ provide: HttpResponse, useValue: undefined, scope: 'http' },
{ provide: HttpRequest, useValue: undefined, scope: 'http' },
{ provide: RouteConfig, useValue: undefined, scope: 'http' },
{ provide: Logger, useValue: new Logger([new ConsoleTransport()]) },
],
Expand All @@ -49,6 +50,7 @@ export class HttpModule extends createModuleClass({
HttpKernel,
HttpResultFormatter,
HttpRouterFilterResolver,
InjectorContext,
HttpResponse,
HttpRequest,
HttpControllers,
Expand Down
74 changes: 20 additions & 54 deletions packages/injector/src/injector.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,7 @@
import {
isClassProvider,
isExistingProvider,
isFactoryProvider,
isValueProvider,
NormalizedProvider,
ProviderWithScope,
Tag,
TagProvider,
TagRegistry,
Token,
} from './provider.js';
import {
AbstractClassType,
ClassType,
CompilerContext,
CustomError,
getClassName,
getPathValue,
isArray,
isClass,
isFunction,
isPrototypeOfBase,
} from '@deepkit/core';
import { isClassProvider, isExistingProvider, isFactoryProvider, isValueProvider, NormalizedProvider, ProviderWithScope, Tag, TagProvider, TagRegistry, Token } from './provider.js';
import { AbstractClassType, ClassType, CompilerContext, CustomError, getClassName, getPathValue, isArray, isClass, isFunction, isPrototypeOfBase } from '@deepkit/core';
import { ConfigurationProviderRegistry, ConfigureProviderEntry, findModuleForConfig, getScope, InjectorModule, PreparedProvider } from './module.js';
import {
isOptional,
isWithAnnotations,
Packed,
ReceiveType,
reflect,
ReflectionClass,
ReflectionFunction,
ReflectionKind,
resolveReceiveType,
stringifyType,
Type,
typeAnnotation,
} from '@deepkit/type';
import { isOptional, isWithAnnotations, Packed, ReceiveType, reflect, ReflectionClass, ReflectionFunction, ReflectionKind, resolveReceiveType, stringifyType, Type, typeAnnotation } from '@deepkit/type';

export class InjectorError extends CustomError {

Expand Down Expand Up @@ -316,7 +281,7 @@ interface BuiltInjector {

resolver(token: Token, scope?: Scope, optional?: boolean): Resolver<unknown>;

setter(token: Token, scope?: Scope): Setter<unknown>;
setter(token: Token, scopeName?: string): Setter<unknown>;

collectStack(stack: StackEntry[]): void;
}
Expand Down Expand Up @@ -368,11 +333,11 @@ export class Injector {
return this.built.instantiationCount(token, scope);
}

getSetter<T>(token: ReceiveType<T> | Token<T>): Setter<T> {
getSetter<T>(token: ReceiveType<T> | Token<T>, scopeName?: string): Setter<T> {
let setter = this.setterMap.get(token);
if (!setter) {
setter = this.createSetter(token as ReceiveType<T> | Token);
this.setterMap.set(token, setter);
setter = this.createSetter(token as ReceiveType<T> | Token, scopeName);
if (!scopeName) this.setterMap.set(token, setter);
}
return setter;
}
Expand Down Expand Up @@ -645,9 +610,8 @@ export class Injector {
}
}

function setter_${routerName}(scope) {
const name = scope?.name || '';
switch (name) {
function setter_${routerName}(scopeName) {
switch (scopeName) {
${setterNames.map(v => `case ${JSON.stringify(v.scope)}: return ${v.function};`).join('\n')}
default: return ${routerName}_setter; // no scope given, so return route for value itself
}
Expand Down Expand Up @@ -773,17 +737,17 @@ export class Injector {
throw serviceNotFoundError(tokenLabel(token));
}

// setter(token: Token, scope?: Scope): Setter<unknown>;
function setter(token, scope) {
// setter(token: Token, scopeName?: string): Setter<unknown>;
function setter(token, scopeName) {
const containerToken = getContainerToken(token);
const fn = containerToken[symbolSetter] || lookupSetter[containerToken];
if (fn) return fn(scope);
if (fn) return fn(scopeName);
throw serviceNotFoundError(tokenLabel(token));
}

// set(token: Token, value: any, scope?: Scope): void;
function set(token, value, scope) {
setter(token)(value, scope);
setter(token, scope?.name)(value, scope);
}

// get(token: Token, scope?: Scope, optional?: boolean): unknown;
Expand Down Expand Up @@ -1194,7 +1158,7 @@ export class Injector {
return foundPreparedProvider;
}

createSetter<T>(token: ReceiveType<T> | Token<T>, scope?: Scope, label?: string): Setter<T> {
createSetter<T>(token: ReceiveType<T> | Token<T>, scopeName?: string, label?: string): Setter<T> {
if (token instanceof TagProvider) token = token.provider.provide;

// todo remove isClass since it's slow
Expand All @@ -1215,7 +1179,7 @@ export class Injector {

const containerToken = getContainerToken(foundPreparedProvider.token);
const resolveFromModule = foundPreparedProvider.resolveFrom || foundPreparedProvider.modules[0];
return resolveFromModule.injector!.built!.setter(containerToken, scope);
return resolveFromModule.injector!.built!.setter(containerToken, scopeName);
}

createResolver<T>(token: ReceiveType<T> | Token<T>, scope?: Scope, label?: string): Resolver<T> {
Expand Down Expand Up @@ -1391,11 +1355,13 @@ export class InjectorContext {
* be executed to resolve the token. This increases performance in hot paths.
*/
resolve<T>(module?: InjectorModule, type?: ReceiveType<T> | Token<T>): Resolver<T> {
return this.getInjector(module || this.rootModule).getResolver(type) as Resolver<T>;
const injector = this.getInjector(module || this.rootModule);
return injector.getResolver(type) as Resolver<T>;
}

setter<T>(module?: InjectorModule, type?: ReceiveType<T> | Token<T>): Setter<T> {
return this.getInjector(module || this.rootModule).getSetter(type) as Setter<T>;
setter<T>(module?: InjectorModule, type?: ReceiveType<T> | Token<T>, scopeName?: string): Setter<T> {
const injector = this.getInjector(module || this.rootModule);
return injector.getSetter(type, scopeName || this.scope?.name) as Setter<T>;
}

/**
Expand Down
Loading