Skip to content

Commit

Permalink
feat(di): add inject() function to inject provider on prop using angu…
Browse files Browse the repository at this point in the history
…lar style
  • Loading branch information
Romakita committed Sep 7, 2024
1 parent 1eefe71 commit 9babaf6
Show file tree
Hide file tree
Showing 55 changed files with 605 additions and 784 deletions.
6 changes: 5 additions & 1 deletion packages/core/src/domain/Type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* An example of a `Type` is `MyCustomComponent` filters, which in JavaScript is be represented by
* An example of a `Type` is `MyCustomComponent` filters, which in JavaScript is represented by
* the `MyCustomComponent` constructor function.
*/
// tslint:disable-next-line: variable-name
Expand All @@ -14,3 +14,7 @@ export const Type = Function;

// @ts-ignore
global.Type = Type;

export interface AbstractType<T> extends Function {
prototype: T;
}
2 changes: 1 addition & 1 deletion packages/core/src/utils/objects/descriptorOf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @returns {PropertyDescriptor}
*/
export function descriptorOf(target: any, propertyKey: string | symbol): PropertyDescriptor {
return Object.getOwnPropertyDescriptor((target && target.prototype) || target, propertyKey)!;
return Reflect.getOwnPropertyDescriptor((target && target.prototype) || target, propertyKey)!;
}

export function isMethodDescriptor(target: any, propertyKey: string | symbol) {
Expand Down
3 changes: 2 additions & 1 deletion packages/di/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"test:ci": "vitest run --coverage.thresholds.autoUpdate=true"
},
"dependencies": {
"tslib": "2.6.2"
"tslib": "2.6.2",
"uuid": "9.0.1"
},
"devDependencies": {
"@tsed/barrels": "workspace:*",
Expand Down
6 changes: 4 additions & 2 deletions packages/di/src/common/constants/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const INJECTABLE_PROP = "DI:INJECTABLE_PROP";
export const DI_PARAMS = "DI:PARAMS";
export const DI_INVOKE_OPTIONS = Symbol("DI:INVOKE_OPTIONS");
export const DI_INJECTABLE_PROPS = Symbol("DI_INJECTABLE_PROPS");
export const DI_INJECTABLE_PROP = "DI:DI_INJECTABLE_PROP";
export const DI_PARAM_OPTIONS = "DI:PARAM:OPTIONS";
export const DI_INTERCEPTOR_OPTIONS = "DI:INTERCEPTOR:OPTIONS";
5 changes: 3 additions & 2 deletions packages/di/src/common/decorators/autoInjectable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,15 @@ describe("AutoInjectable", () => {
logger: Logger;

private value: string;
instances?: InterfaceGroup[];

constructor(initialValue: string, @Inject(TOKEN_GROUPS) instances?: InterfaceGroup[]) {
this.value = initialValue;
expect(instances).toHaveLength(3);
this.instances = instances;
}
}

new Test("test");
expect(new Test("test").instances).toHaveLength(3);
});
it("should return a class that extends the original class (with 3 arguments)", () => {
@AutoInjectable()
Expand Down
30 changes: 27 additions & 3 deletions packages/di/src/common/decorators/autoInjectable.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
import {isArray, type Type} from "@tsed/core";
import {LocalsContainer} from "../domain/LocalsContainer.js";
import type {TokenProvider} from "../interfaces/TokenProvider.js";
import {InjectorService} from "../services/InjectorService.js";
import {getConstructorDependencies} from "../utils/getConstructorDependencies.js";

function resolveAutoInjectableArgs(token: Type, args: unknown[]) {
const locals = new LocalsContainer();
const injector = InjectorService.getInstance();
const deps: TokenProvider[] = getConstructorDependencies(token);
const list: any[] = [];
const length = Math.max(deps.length, args.length);

for (let i = 0; i < length; i++) {
if (args[i] !== undefined) {
list.push(args[i]);
} else {
const value = deps[i];
const instance = isArray(value)
? injector!.getMany(value[0], locals, {parent: token})
: injector!.invoke(value, locals, {parent: token});

list.push(instance);
}
}

return list;
}

export function AutoInjectable() {
return <T extends {new (...args: any[]): NonNullable<unknown>}>(constr: T): T => {
return class AutoInjectable extends constr {
constructor(...args: any[]) {
const locals = new LocalsContainer();
super(...InjectorService.resolveAutoInjectableArgs(constr, locals, args));
InjectorService.bind(this, locals);
super(...resolveAutoInjectableArgs(constr, args));
}
} as unknown as T;
};
Expand Down
2 changes: 1 addition & 1 deletion packages/di/src/common/decorators/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function constant<Type>(expression: string, defaultValue?: Type | undefin
}

export function bindConstant(target: any, propertyKey: string | symbol, expression: string, defaultValue?: any) {
let symbol = Symbol();
const symbol = Symbol();

catchError(() => Reflect.deleteProperty(target, propertyKey));
Reflect.defineProperty(target, propertyKey, {
Expand Down
Loading

0 comments on commit 9babaf6

Please sign in to comment.