Skip to content

Commit

Permalink
feat: support inject in lifecycle (#145)
Browse files Browse the repository at this point in the history
* feat: support inject in lifecycle

* remove unused WithXXX api

* chore: update framework test

* make lifecycle props lazy inject
  • Loading branch information
hyj1991 authored Aug 1, 2022
1 parent 6945a13 commit 6f79b40
Show file tree
Hide file tree
Showing 22 changed files with 54 additions and 140 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"typescript": "^4.7.2"
},
"dependencies": {
"@artus/injection": "^0.4.0",
"@artus/injection": "^0.4.1",
"@artus/pipeline": "^0.2.2",
"deepmerge": "^4.2.2",
"minimatch": "^5.0.1"
Expand Down
10 changes: 3 additions & 7 deletions src/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ export enum ARTUS_DEFAULT_CONFIG_ENV {
}

export const HOOK_NAME_META_PREFIX = 'hookName:';
export const CONSTRUCTOR_PARAMS = 'constructor:params';
export const CONSTRUCTOR_PARAMS_APP = 'constructor:params:app';
export const CONSTRUCTOR_PARAMS_CONTAINER = 'constructor:params:container';
export const CONSTRUCTOR_PARAMS_CONTEXT = 'constructor:params:context';
export const HOOK_FILE_LOADER = 'appHook:fileLoader';
export const HOOK_CONFIG_HANDLE = 'appHook:configHandle::';

Expand All @@ -54,12 +50,12 @@ export const EXCEPTION_FILENAME = 'exception.json';
export const DEFAULT_LOADER_LIST_WITH_ORDER = [
'exception',
'plugin-config',
'lifecycle-hook-unit',
'config',
'plugin-meta',
'module',
'framework-config',
'package-json',
'module',
'lifecycle-hook-unit',
'config',
];

export const DEFAULT_CONFIG_DIR = 'src/config';
Expand Down
31 changes: 2 additions & 29 deletions src/decorator.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { Injectable } from '@artus/injection';
import {
CONSTRUCTOR_PARAMS,
CONSTRUCTOR_PARAMS_APP,
CONSTRUCTOR_PARAMS_CONTAINER,
HOOK_NAME_META_PREFIX,
CONSTRUCTOR_PARAMS_CONTEXT,
HOOK_FILE_LOADER,
} from './constant';

export function LifecycleHookUnit(): ClassDecorator {
return (target: any) => {
// Ready to remove?
Reflect.defineMetadata(HOOK_FILE_LOADER, { loader: 'lifecycle-hook-unit' }, target);
Injectable({ lazy: true })(target);
};
}

Expand All @@ -23,29 +20,5 @@ export function LifecycleHook(hookName?: string): PropertyDecorator {
};
}

const WithConstructorParams = (tag: string): ParameterDecorator => {
return (target: any, _propertyKey: string | symbol, parameterIndex: number) => {
const paramsMd = Reflect.getOwnMetadata(CONSTRUCTOR_PARAMS, target) ?? [];
paramsMd[parameterIndex] = tag;
if (_propertyKey) {
Reflect.defineMetadata(CONSTRUCTOR_PARAMS, paramsMd, target[_propertyKey]); // for proto
} else {
Reflect.defineMetadata(CONSTRUCTOR_PARAMS, paramsMd, target); // for constructor
}
};
};

export function WithApplication(): ParameterDecorator {
return WithConstructorParams(CONSTRUCTOR_PARAMS_APP);
}

export function WithContainer(): ParameterDecorator {
return WithConstructorParams(CONSTRUCTOR_PARAMS_CONTAINER);
}

export function WithContext(): ParameterDecorator {
return WithConstructorParams(CONSTRUCTOR_PARAMS_CONTEXT);
}

export * from './loader/decorator';
export * from './trigger/decorator';
7 changes: 1 addition & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@


export {
Inject,
Injectable,
} from '@artus/injection';
export * from '@artus/injection';

export * from './loader';
export * from './logger';
Expand Down
14 changes: 3 additions & 11 deletions src/lifecycle/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { Constructable, Container } from '@artus/injection';
import { Application } from '../types';
import {
CONSTRUCTOR_PARAMS,
CONSTRUCTOR_PARAMS_APP,
CONSTRUCTOR_PARAMS_CONTAINER,
HOOK_NAME_META_PREFIX,
} from '../constant';

export type HookFunction = <T = unknown>(hookProps : {
export type HookFunction = <T = unknown>(hookProps: {
app: Application,
lifecycleManager: LifecycleManager,
payload?: T
}) => void|Promise<void>;
}) => void | Promise<void>;

export class LifecycleManager {
hookList: string[] = [
Expand Down Expand Up @@ -52,12 +49,7 @@ export class LifecycleManager {

registerHookUnit(extClazz: Constructable<any>) {
const fnMetaKeys = Reflect.getMetadataKeys(extClazz);
const constructorParams = Reflect.getMetadata(CONSTRUCTOR_PARAMS, extClazz) ?? [];
const paramsMap = {
[CONSTRUCTOR_PARAMS_APP]: this.app,
[CONSTRUCTOR_PARAMS_CONTAINER]: this.container,
};
const extClazzInstance = new extClazz(...constructorParams.map(param => paramsMap[param]));
const extClazzInstance = this.container.get(extClazz);
for (const fnMetaKey of fnMetaKeys) {
if (typeof fnMetaKey !== 'string' || !fnMetaKey.startsWith(HOOK_NAME_META_PREFIX)) {
continue;
Expand Down
1 change: 1 addition & 0 deletions src/loader/impl/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class LifecycleLoader implements Loader {
async load(item: ManifestItem) {
const extClazz: Constructable<ApplicationLifecycle> = await compatibleRequire(item.path);
const lifecycleManager: LifecycleManager = this.container.get(ArtusInjectEnum.LifecycleManager);
this.container.set({ type: extClazz });
lifecycleManager.registerHookUnit(extClazz);
return extClazz;
}
Expand Down
13 changes: 5 additions & 8 deletions test/fixtures/app_koa_with_ts/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { DefaultContext } from 'koa';
import { Server } from 'http';
import { Container } from '@artus/injection';
import { Container, Inject } from '@artus/injection';
import { Context, Input } from '@artus/pipeline';

import { ArtusApplication } from '../../../../src';
import { LifecycleHookUnit, LifecycleHook, WithApplication, WithContainer } from '../../../../src/decorator';
import { ArtusApplication, ArtusInjectEnum } from '../../../../src';
import { LifecycleHookUnit, LifecycleHook } from '../../../../src/decorator';
import { ApplicationLifecycle } from '../../../../src/types';

import KoaApplication from './koa_app';
Expand All @@ -14,14 +14,11 @@ export let server: Server;

@LifecycleHookUnit()
export default class MyLifecycle implements ApplicationLifecycle {
@Inject(ArtusInjectEnum.Application)
app: ArtusApplication;
@Inject()
container: Container;

constructor(@WithApplication() app: ArtusApplication, @WithContainer() container: Container) {
this.app = app;
this.container = container;
}

get koaApp(): KoaApplication {
return this.container.get(KoaApplication);
}
Expand Down
3 changes: 1 addition & 2 deletions test/fixtures/artus_application/src/controller/conifg.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Context } from '@artus/pipeline';
import { HttpController, HttpMethod, HTTPMethodEnum } from '../../../frameworks/bar/src';
import { WithContext } from '../../../../../src/decorator';

@HttpController()
export default class Hello {
@HttpMethod({
method: HTTPMethodEnum.GET,
path: '/config',
})
async index(@WithContext() ctx: Context) {
async index(ctx: Context) {
const { params: { config } } = ctx.input;
return {
message: `get conifg succeed`,
Expand Down
7 changes: 3 additions & 4 deletions test/fixtures/artus_application/src/controller/hello.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Context } from '@artus/pipeline';
import { HttpController, HttpMethod, HTTPMethodEnum } from '../../../frameworks/bar/src';
import { WithContext } from '../../../../../src/decorator';

@HttpController()
export default class Hello {
@HttpMethod({
method: HTTPMethodEnum.GET,
path: '/home',
})
async index(@WithContext() ctx: Context) {
async index(ctx: Context) {
const { params: { config } } = ctx.input;
return { title: `Hello Artus ${config.name}` };
}
Expand All @@ -17,7 +16,7 @@ export default class Hello {
method: HTTPMethodEnum.GET,
path: '/get_name2',
})
async name2(@WithContext() ctx: Context) {
async name2(ctx: Context) {
const { params: { config } } = ctx.input;
return { title: `Hello Artus ${config.name2}` };
}
Expand All @@ -26,7 +25,7 @@ export default class Hello {
method: HTTPMethodEnum.GET,
path: '/get_name3',
})
async name3(@WithContext() ctx: Context) {
async name3(ctx: Context) {
const { params: { config } } = ctx.input;
return { title: `Hello Artus ${config.name3}` };
}
Expand Down
3 changes: 1 addition & 2 deletions test/fixtures/artus_application/src/controller/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { HttpController, HttpMethod, HTTPMethodEnum } from '../../../frameworks/bar/src';
import { Inject } from '@artus/injection';
import { WithContext } from '../../../../../src/decorator';
import { ArtusApplication } from '../../../../../src';
import { Context } from '@artus/pipeline';

Expand All @@ -23,7 +22,7 @@ export default class Hello {
method: HTTPMethodEnum.GET,
path: '/plugin-redis',
})
async getRedisClient(@WithContext() ctx: Context) {
async getRedisClient(ctx: Context) {
const app: ArtusApplication = ctx.input.params.app;
let client;
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { Server } from 'http';
import { LifecycleHookUnit, LifecycleHook, WithApplication } from '../../../../../../../src/decorator';
import { LifecycleHookUnit, LifecycleHook } from '../../../../../../../src/decorator';
import { ApplicationLifecycle } from '../../../../../../../src/types';
import { ArtusApplication } from '../../../../../../../src';
import { ArtusApplication, Inject, ArtusInjectEnum } from '../../../../../../../src';
import Client, { MysqlConfig } from './client';

export let server: Server;

@LifecycleHookUnit()
export default class MyLifecycle implements ApplicationLifecycle {
@Inject(ArtusInjectEnum.Application)
app: ArtusApplication;

constructor(@WithApplication() app: ArtusApplication) {
this.app = app;
}

@LifecycleHook()
async willReady() {
const mysql = this.app.container.get('ARTUS_MYSQL') as Client;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { Server } from 'http';
import { LifecycleHookUnit, LifecycleHook, WithApplication } from '../../../../../../../src/decorator';
import { LifecycleHookUnit, LifecycleHook } from '../../../../../../../src/decorator';
import { ApplicationLifecycle } from '../../../../../../../src/types';
import { ArtusApplication } from '../../../../../../../src';
import { ArtusApplication, Inject, ArtusInjectEnum } from '../../../../../../../src';
import Client, { MysqlConfig } from './client';

export let server: Server;

@LifecycleHookUnit()
export default class MyLifecycle implements ApplicationLifecycle {
@Inject(ArtusInjectEnum.Application)
app: ArtusApplication;

constructor(@WithApplication() app: ArtusApplication) {
this.app = app;
}

@LifecycleHook()
async willReady() {
const mysql = this.app.container.get('ARTUS_MYSQL') as Client;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { Server } from 'http';
import { LifecycleHookUnit, LifecycleHook, WithApplication } from '../../../../../../../src/decorator';
import { LifecycleHookUnit, LifecycleHook } from '../../../../../../../src/decorator';
import { ApplicationLifecycle } from '../../../../../../../src/types';
import { ArtusApplication } from '../../../../../../../src';
import { ArtusApplication, Inject, ArtusInjectEnum } from '../../../../../../../src';
import Client, { RedisConfig } from './client';

export let server: Server;

@LifecycleHookUnit()
export default class MyLifecycle implements ApplicationLifecycle {
@Inject(ArtusInjectEnum.Application)
app: ArtusApplication;

constructor(@WithApplication() app: ArtusApplication) {
this.app = app;
}

@LifecycleHook()
async willReady() {
const redis = this.app.container.get('ARTUS_REDIS') as Client;
Expand Down
12 changes: 4 additions & 8 deletions test/fixtures/custom_instance/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import {
ArtusApplication,
ApplicationLifecycle, LifecycleHookUnit, LifecycleHook,
WithApplication, WithContainer,
ApplicationLifecycle, LifecycleHookUnit, LifecycleHook, ArtusInjectEnum,
} from '../../../src/index';

import { Container } from '@artus/injection';
import { Container, Inject } from '@artus/injection';
import Custom from './custom';

@LifecycleHookUnit()
export default class MyLifecycle implements ApplicationLifecycle {
@Inject(ArtusInjectEnum.Application)
app: ArtusApplication;
@Inject()
container: Container;

constructor(@WithApplication() app: ArtusApplication, @WithContainer() container) {
this.app = app;
this.container = container;
}

@LifecycleHook()
configDidLoad() {
this.container.set({ id: Custom, value: new Custom('foo') });
Expand Down
9 changes: 2 additions & 7 deletions test/fixtures/frameworks/bar/src/http.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'reflect-metadata';
import { Context, Next } from '@artus/pipeline';
import { Constructable , Injectable, ScopeEnum } from '@artus/injection';
import { CONSTRUCTOR_PARAMS, CONSTRUCTOR_PARAMS_CONTEXT } from '../../../../../src/constant';
import { Constructable, Injectable, ScopeEnum } from '@artus/injection';
import { HttpTrigger } from '../../abstract/foo';

export const enum HTTPMethodEnum {
Expand Down Expand Up @@ -72,11 +71,7 @@ export function registerController(trigger: HttpTrigger) {
if (req.url === `${prefix}${path}` && req.method === method) {
const instance: any = ctx.container.get(clazz);
const target = instance[key];
const params: any = Reflect.getMetadata(CONSTRUCTOR_PARAMS, target) ?? [];
const paramsMap = {
[CONSTRUCTOR_PARAMS_CONTEXT]: ctx,
};
ctx.output.data.content = await target.call(instance, ...params.map(param => paramsMap[param]));
ctx.output.data.content = await target.call(instance, ctx);
}
await next();
});
Expand Down
9 changes: 3 additions & 6 deletions test/fixtures/frameworks/bar/src/lifecycle.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { Server } from 'http';
import { LifecycleHookUnit, LifecycleHook, WithApplication } from '../../../../../src/decorator';
import { LifecycleHookUnit, LifecycleHook } from '../../../../../src/decorator';
import { ApplicationLifecycle } from '../../../../../src/types';
import { ArtusApplication } from '../../../../../src';
import { ArtusInjectEnum, ArtusApplication, Inject } from '../../../../../src';
import { registerController } from './/http';
import { HttpTrigger } from '../../abstract/foo';

export let server: Server;

@LifecycleHookUnit()
export default class MyLifecycle implements ApplicationLifecycle {
@Inject(ArtusInjectEnum.Application)
app: ArtusApplication;

constructor(@WithApplication() app: ArtusApplication) {
this.app = app;
}

@LifecycleHook()
async didLoad() {
// register controller
Expand Down
9 changes: 3 additions & 6 deletions test/fixtures/frameworks/layer/foo/foo1/src/lifecycle.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import http, { Server } from 'http';
import { LifecycleHookUnit, LifecycleHook, WithApplication } from '../../../../../../../src/decorator';
import { LifecycleHookUnit, LifecycleHook } from '../../../../../../../src/decorator';
import { ApplicationLifecycle } from '../../../../../../../src/types';
import { Input } from '@artus/pipeline';
import { ArtusApplication } from '../../../../../../../src';
import { ArtusApplication, Inject, ArtusInjectEnum } from '../../../../../../../src';

export let server: Server;

@LifecycleHookUnit()
export default class MyLifecycle implements ApplicationLifecycle {
@Inject(ArtusInjectEnum.Application)
app: ArtusApplication;

constructor(@WithApplication() app: ArtusApplication) {
this.app = app;
}

@LifecycleHook()
willReady() {
const config = this.app.config ?? {};
Expand Down
Loading

0 comments on commit 6f79b40

Please sign in to comment.