Skip to content

Commit

Permalink
fix(di): use async_hook directly on @tsed/di
Browse files Browse the repository at this point in the history
BREAKING CHANGE: use async_hook directly on @tsed/di. Remove @tsed/async_hook_context. Use @tsed/di to inject context.
  • Loading branch information
Romakita committed Apr 14, 2022
1 parent f66b26c commit 6ef22a6
Show file tree
Hide file tree
Showing 23 changed files with 84 additions and 453 deletions.
25 changes: 25 additions & 0 deletions packages/di/src/decorators/inject.ts
@@ -1,6 +1,7 @@
import {decoratorTypeOf, DecoratorTypes, isPromise, Metadata, Store, UnsupportedDecoratorType} from "@tsed/core";
import {DI_PARAM_OPTIONS, INJECTABLE_PROP} from "../constants/constants";
import type {InjectablePropertyOptions} from "../interfaces/InjectableProperties";
import {getContext} from "../utils/runInContext";

export function injectProperty(target: any, propertyKey: string, options: Partial<InjectablePropertyOptions>) {
Store.from(target).merge(INJECTABLE_PROP, {
Expand Down Expand Up @@ -84,3 +85,27 @@ export function Inject(symbol?: any, onGet = (bean: any) => bean): Function {
}
};
}

/**
* Inject a context like PlatformContext or any BaseContext.
*
* ```typescript
* @Injectable()
* export class MyService {
* @InjectContext()
* ctx?: Context;
* }
* ```
*
* @returns {Function}
* @decorator
*/
export function InjectContext(): PropertyDecorator {
return (target: any, propertyKey: string): any | void => {
injectProperty(target, propertyKey, {
resolver() {
return () => getContext();
}
});
};
}
1 change: 1 addition & 0 deletions packages/di/src/index.ts
Expand Up @@ -47,6 +47,7 @@ export * from "./services/DIConfiguration";
export * from "./services/DILogger";
export * from "./services/DITest";
export * from "./services/InjectorService";
export * from "./utils/runInContext";
export * from "./utils/colors";
export * from "./utils/createContainer";
export * from "./utils/getConfiguration";
Expand Down
9 changes: 9 additions & 0 deletions packages/di/src/services/DITest.ts
Expand Up @@ -6,6 +6,7 @@ import {OnInit} from "../interfaces/OnInit";
import {TokenProvider} from "../interfaces/TokenProvider";
import {setLoggerLevel} from "../utils/setLoggerLevel";
import {InjectorService} from "./InjectorService";
import {DIContext} from "../domain/DIContext";

export interface DITestInvokeOptions {
token?: TokenProvider;
Expand Down Expand Up @@ -124,6 +125,14 @@ export class DITest {
return DITest.injector.get<T>(target, options)!;
}

static createDIContext() {
return new DIContext({
id: "id",
injector: DITest.injector,
logger: DITest.injector.logger
});
}

protected static configure(settings: Partial<TsED.Configuration> = {}): Partial<TsED.Configuration> {
return {
...settings,
Expand Down
6 changes: 0 additions & 6 deletions packages/di/src/services/InjectorService.spec.ts
Expand Up @@ -49,12 +49,6 @@ describe("InjectorService", () => {
expect(new InjectorService().has(Test)).to.be.false;
});
});
describe("runInContext()", () => {
it("should return true", () => {
const injector = new InjectorService();
injector.runInContext({} as any, () => {});
});
});

describe("get()", () => {
it("should return element", () => {
Expand Down
12 changes: 0 additions & 12 deletions packages/di/src/services/InjectorService.ts
Expand Up @@ -27,13 +27,11 @@ import {ResolvedInvokeOptions} from "../interfaces/ResolvedInvokeOptions";
import {ProviderScope} from "../domain/ProviderScope";
import {DILogger} from "../interfaces/DILogger";
import {TokenProvider} from "../interfaces/TokenProvider";
import {ProviderOpts} from "../interfaces/ProviderOpts";
import {InvokeOptions} from "../interfaces/InvokeOptions";
import {InjectableProperties, InjectablePropertyOptions, InjectablePropertyValue} from "../interfaces/InjectableProperties";
import {InjectablePropertyType} from "../domain/InjectablePropertyType";
import {InterceptorContext} from "../interfaces/InterceptorContext";
import {InterceptorMethods} from "../interfaces/InterceptorMethods";
import {DIContext} from "../domain/DIContext";

/**
* This service contain all services collected by `@Service` or services declared manually with `InjectorService.factory()` or `InjectorService.service()`.
Expand Down Expand Up @@ -501,16 +499,6 @@ export class InjectorService extends Container {
};
}

/**
* Allow handler hack for AsyncHookContext plugin.
* @param ctx
* @param cb
* @protected
*/
runInContext(ctx: DIContext, cb: any) {
return cb();
}

async lazyInvoke<T = any>(token: TokenProvider) {
let instance = this.getInstance(token);

Expand Down
17 changes: 17 additions & 0 deletions packages/di/src/utils/runInContext.ts
@@ -0,0 +1,17 @@
import {AsyncLocalStorage} from "async_hooks";
import {DIContext} from "../domain/DIContext";

let store: AsyncLocalStorage<DIContext>;

export function getAsyncStore() {
store = store || new AsyncLocalStorage();
return store;
}

export function getContext() {
return store?.getStore();
}

export function runInContext(ctx: DIContext, cb: any) {
return getAsyncStore().run(ctx, cb);
}
26 changes: 26 additions & 0 deletions packages/di/test/integration/inject-context.spec.ts
@@ -0,0 +1,26 @@
import {DIContext, DITest, Injectable, InjectContext, runInContext} from "@tsed/di";
import {expect} from "chai";

@Injectable()
class MyService {
@InjectContext()
$ctx: DIContext;

get() {
return this.$ctx.id;
}
}

describe("InjectContext", () => {
beforeEach(() => DITest.create());
afterEach(() => DITest.reset());

it("should inject context", () => {
const ctx = DITest.createDIContext();
const service = DITest.get<MyService>(MyService);

const result = runInContext(ctx, () => service.get());

expect(result).to.equal("id");
});
});
4 changes: 2 additions & 2 deletions packages/platform/common/src/services/PlatformHandler.ts
@@ -1,5 +1,5 @@
import {AnyToPromiseStatus, isFunction, isStream} from "@tsed/core";
import {Inject, Injectable, InjectorService, Provider, ProviderScope} from "@tsed/di";
import {Inject, Injectable, InjectorService, Provider, ProviderScope, runInContext} from "@tsed/di";
import {$log} from "@tsed/logger";
import {ArgScope, HandlerWithScope, PlatformParams} from "@tsed/platform-params";
import {PlatformResponseFilter} from "@tsed/platform-response-filter";
Expand Down Expand Up @@ -135,7 +135,7 @@ export class PlatformHandler {

const resolver = new AnyToPromiseWithCtx({$ctx, err});

return this.injector.runInContext($ctx, async () => {
return runInContext($ctx, async () => {
try {
const {state, data, status, headers} = await resolver.call(handler);

Expand Down
1 change: 0 additions & 1 deletion packages/platform/common/src/services/PlatformTest.ts
Expand Up @@ -7,7 +7,6 @@ import {PlatformApplication} from "./PlatformApplication";
import {getConfiguration} from "../utils/getConfiguration";
import {PlatformAdapter, PlatformBuilderSettings} from "./PlatformAdapter";
import accepts from "accepts";
import {FakeAdapter} from "./FakeAdapter";

/**
* @platform
Expand Down
@@ -1,5 +1,5 @@
import {AnyPromiseResult, AnyToPromise, isSerializable} from "@tsed/core";
import {BaseContext, Inject, Injectable, InjectorService, LazyInject, ProviderScope, TokenProvider} from "@tsed/di";
import {BaseContext, Inject, Injectable, InjectorService, LazyInject, ProviderScope, runInContext, TokenProvider} from "@tsed/di";
import {serialize} from "@tsed/json-mapper";
import {DeserializerPipe, PlatformParams, ValidationPipe} from "@tsed/platform-params";
import type {PlatformExceptions} from "@tsed/platform-exceptions";
Expand Down Expand Up @@ -29,7 +29,7 @@ export class PlatformServerlessHandler {
return async ($ctx: ServerlessContext) => {
await this.injector.emit("$onRequest", $ctx);

await this.injector.runInContext($ctx, async () => {
await runInContext($ctx as any, async () => {
try {
const resolver = new AnyToPromise();
const handler = await promisedHandler;
Expand Down
5 changes: 0 additions & 5 deletions packages/third-parties/async-hook-context/.mocharc.js

This file was deleted.

4 changes: 0 additions & 4 deletions packages/third-parties/async-hook-context/.npmignore

This file was deleted.

26 changes: 0 additions & 26 deletions packages/third-parties/async-hook-context/.nycrc

This file was deleted.

46 changes: 0 additions & 46 deletions packages/third-parties/async-hook-context/package.json

This file was deleted.

0 comments on commit 6ef22a6

Please sign in to comment.