Skip to content

Commit

Permalink
fix: missing import component will be throw error (#1694)
Browse files Browse the repository at this point in the history
  • Loading branch information
czy88840616 committed Feb 13, 2022
1 parent 89a0300 commit c17f049
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 11 deletions.
6 changes: 3 additions & 3 deletions packages/core/src/context/container.ts
Expand Up @@ -213,8 +213,6 @@ class ContainerConfiguration {
}
}

class ObjectCreateEventTarget extends EventEmitter {}

export class MidwayContainer implements IMidwayContainer, IModuleStore {
private _resolverFactory: ManagedResolverFactory = null;
private _registry: IObjectDefinitionRegistry = null;
Expand Down Expand Up @@ -242,7 +240,7 @@ export class MidwayContainer implements IMidwayContainer, IModuleStore {

get objectCreateEventTarget() {
if (!this._objectCreateEventTarget) {
this._objectCreateEventTarget = new ObjectCreateEventTarget();
this._objectCreateEventTarget = new EventEmitter();
}
return this._objectCreateEventTarget;
}
Expand Down Expand Up @@ -363,6 +361,8 @@ export class MidwayContainer implements IMidwayContainer, IModuleStore {
const refManaged = new ManagedReference();
refManaged.args = propertyMeta.args;
refManaged.name = propertyMeta.value as any;
refManaged.injectMode = propertyMeta['injectMode'];

definition.properties.set(propertyMeta['targetKey'], refManaged);
}

Expand Down
24 changes: 23 additions & 1 deletion packages/core/src/context/managedResolverFactory.ts
@@ -1,7 +1,11 @@
/**
* 管理对象解析构建
*/
import { IManagedInstance, ObjectIdentifier } from '@midwayjs/decorator';
import {
IManagedInstance,
InjectModeEnum,
ObjectIdentifier,
} from '@midwayjs/decorator';
import { KEYS } from '../common/constants';
import {
IManagedResolver,
Expand All @@ -18,6 +22,7 @@ import * as EventEmitter from 'events';
import {
MidwayCommonError,
MidwayDefinitionNotFoundError,
MidwayMissingImportComponentError,
MidwayResolverMissingError,
MidwaySingletonInjectRequestError,
} from '../error';
Expand All @@ -28,6 +33,7 @@ const debugLog = util.debuglog('midway:debug');
export class ManagedReference implements IManagedInstance {
type = KEYS.REF_ELEMENT;
name: string;
injectMode: InjectModeEnum;
args?: any;
}

Expand All @@ -42,6 +48,14 @@ class RefResolver {

resolve(managed: IManagedInstance, originName: string): any {
const mr = managed as ManagedReference;
if (
mr.injectMode === InjectModeEnum.Class &&
!(this.factory.context.parent ?? this.factory.context).hasDefinition(
mr.name
)
) {
throw new MidwayMissingImportComponentError(originName);
}
return this.factory.context.get(mr.name, mr.args, {
originName,
});
Expand All @@ -52,6 +66,14 @@ class RefResolver {
originName: string
): Promise<any> {
const mr = managed as ManagedReference;
if (
mr.injectMode === InjectModeEnum.Class &&
!(this.factory.context.parent ?? this.factory.context).hasDefinition(
mr.name
)
) {
throw new MidwayMissingImportComponentError(originName);
}
return this.factory.context.getAsync(mr.name, mr.args, {
originName,
});
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/error/framework.ts
Expand Up @@ -13,6 +13,7 @@ export const FrameworkErrorEnum = registerErrorCode('midway', {
DUPLICATE_ROUTER: 10008,
USE_WRONG_METHOD: 10009,
SINGLETON_INJECT_REQUEST: 10010,
MISSING_IMPORTS: 10011,
} as const);

export class MidwayCommonError extends MidwayError {
Expand Down Expand Up @@ -115,3 +116,10 @@ export class MidwaySingletonInjectRequestError extends MidwayError {
super(text, FrameworkErrorEnum.SINGLETON_INJECT_REQUEST);
}
}

export class MidwayMissingImportComponentError extends MidwayError {
constructor(originName: string) {
const text = `"${originName}" can't inject and maybe forgot add "{imports: [***]}" in @Configuration.`;
super(text, FrameworkErrorEnum.MISSING_IMPORTS);
}
}
4 changes: 2 additions & 2 deletions packages/core/src/setup.ts
Expand Up @@ -62,14 +62,14 @@ export async function initializeGlobalApplicationContext(
// bind inner service
applicationContext.bindClass(MidwayEnvironmentService);
applicationContext.bindClass(MidwayInformationService);
applicationContext.bindClass(MidwayAspectService);
applicationContext.bindClass(MidwayDecoratorService);
applicationContext.bindClass(MidwayConfigService);
applicationContext.bindClass(MidwayAspectService);
applicationContext.bindClass(MidwayLoggerService);
applicationContext.bindClass(MidwayApplicationManager);
applicationContext.bindClass(MidwayFrameworkService);
applicationContext.bindClass(MidwayMiddlewareService);
applicationContext.bindClass(MidwayLifeCycleService);
applicationContext.bindClass(MidwayApplicationManager);

// bind preload module
if (globalOptions.preloadModules && globalOptions.preloadModules.length) {
Expand Down
21 changes: 21 additions & 0 deletions packages/core/test/feature.test.ts
@@ -0,0 +1,21 @@
import { createLightFramework } from './util';
import { join } from 'path';
import { MidwayMissingImportComponentError } from '../src';

describe('/test/feature.test.ts', () => {
it('should throw error when inject', async () => {
let err;
try {
await createLightFramework(join(
__dirname,
'./fixtures/base-app-not-import-throw-error/src'
));
} catch (error) {
err = error;
}
expect(err).toBeDefined();
expect(() => {
throw err;
}).toThrowError(MidwayMissingImportComponentError);
});
});
@@ -0,0 +1,3 @@
{
"name": "ali-demo"
}
@@ -0,0 +1,16 @@
import { Configuration, Inject } from '@midwayjs/decorator';
// import * as book from 'midway-test-component';
import { BookService } from 'midway-test-component';

@Configuration({
imports: [],
})
export class ContainerLifeCycle {

@Inject()
bookService: BookService;

async onReady() {
console.log('[ Midway ] onReady', this.bookService);
}
}
6 changes: 4 additions & 2 deletions packages/core/test/util.ts
Expand Up @@ -85,7 +85,9 @@ export async function createLightFramework(baseDir: string = '', globalConfig: a
}
}

@Configuration()
@Configuration({
namespace: 'empty'
})
class EmptyConfiguration {

@Inject()
Expand All @@ -97,8 +99,8 @@ export async function createLightFramework(baseDir: string = '', globalConfig: a
}

const imports = [{
EmptyFramework,
Configuration: EmptyConfiguration,
EmptyFramework
}];
if (baseDir) {
imports.push(safeRequire(join(baseDir, 'configuration')));
Expand Down
11 changes: 8 additions & 3 deletions packages/decorator/src/decoratorManager.ts
@@ -1,11 +1,12 @@
import 'reflect-metadata';
import {
GroupModeType,
IModuleStore,
InjectModeEnum,
ObjectDefinitionOptions,
ObjectIdentifier,
TagClsMetadata,
TagPropsMetadata,
IModuleStore,
GroupModeType,
} from './interface';
import {
INJECT_CUSTOM_METHOD,
Expand All @@ -16,7 +17,7 @@ import {
TAGGED_CLS,
} from './constant';

import { isNullOrUndefined, isClass, generateRandomId, merge } from './util';
import { generateRandomId, isClass, isNullOrUndefined, merge } from './util';
import { camelCase } from './util/camelCase';

const debug = require('util').debuglog('midway:decorator');
Expand Down Expand Up @@ -753,6 +754,7 @@ export function savePropertyInject(opts: {
}) {
// 1、use identifier by user
let identifier = opts.identifier;
let injectMode = InjectModeEnum.Identifier;
// 2、use identifier by class uuid
if (!identifier) {
const type = getPropertyType(opts.target, opts.targetKey);
Expand All @@ -762,10 +764,12 @@ export function savePropertyInject(opts: {
isProvide(type.originDesign)
) {
identifier = getProviderUUId(type.originDesign);
injectMode = InjectModeEnum.Class;
}
if (!identifier) {
// 3、use identifier by property name
identifier = opts.targetKey;
injectMode = InjectModeEnum.PropertyName;
}
}
attachClassMetadata(
Expand All @@ -774,6 +778,7 @@ export function savePropertyInject(opts: {
targetKey: opts.targetKey, // 注入的属性名
value: identifier, // 注入的 id
args: opts.args, // 注入的其他参数
injectMode,
},
opts.target,
opts.targetKey
Expand Down
6 changes: 6 additions & 0 deletions packages/decorator/src/interface.ts
Expand Up @@ -8,6 +8,12 @@ export enum ScopeEnum {
Prototype = 'Prototype',
}

export enum InjectModeEnum {
Identifier = 'Identifier',
Class = 'Class',
PropertyName = 'PropertyName',
}

/**
* 内部管理的属性、json、ref等解析实例存储
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/decorator/test/annotation/inject.test.ts
Expand Up @@ -23,12 +23,14 @@ describe('/test/annotation/inject.test.ts', () => {
it('inject decorator should be ok', () => {
let meta = getPropertyInject(Test);
expect(meta['aa']).toEqual({
injectMode: 'PropertyName',
value: 'aa',
targetKey: 'aa'
});
expect(meta['ee']['targetKey']).toEqual('ee');
expect(meta['ee']['value'].length).toEqual(32);
expect(meta['ff']).toEqual({
injectMode: 'PropertyName',
value: 'ff',
targetKey: 'ff'
});
Expand Down
2 changes: 2 additions & 0 deletions packages/decorator/test/common/utils.test.ts
Expand Up @@ -34,6 +34,7 @@ describe('/test/common/util.test.ts', () => {
let p = getPropertyInject(Test);
expect(p['hello']).toEqual({
args: undefined,
injectMode: 'Identifier',
targetKey: 'hello',
value: '@testpackage',
});
Expand All @@ -51,6 +52,7 @@ describe('/test/common/util.test.ts', () => {
p = getPropertyInject(Test, false);
expect(p['hello']).toEqual({
args: undefined,
injectMode: 'Identifier',
targetKey: 'hello',
value: '@testpackage2',
});
Expand Down

0 comments on commit c17f049

Please sign in to comment.