Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: configuration inject plugin and more in production environment #680

Merged
merged 35 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f12cd10
refactor: egg load and midway bootstrap
czy88840616 Oct 20, 2020
92c4cb6
feat: add container cache
czy88840616 Oct 21, 2020
692c32c
fix: web refactor case error
czy88840616 Oct 21, 2020
789cfa3
chore: clean code
czy88840616 Oct 21, 2020
1fb3ee5
chore: clean code
czy88840616 Oct 21, 2020
c344f42
fix: app.generateController
czy88840616 Oct 21, 2020
15754f8
test: complete case and enable old suit
czy88840616 Oct 21, 2020
7ca58aa
chore: add @deprecated jsdoc
czy88840616 Oct 22, 2020
1dd84bf
v2.3.17-beta.1
czy88840616 Oct 22, 2020
561ad17
Merge branch '2.x' into fix_egg_loader
czy88840616 Oct 22, 2020
297d419
refactor: use new method to resolve registry
czy88840616 Oct 23, 2020
600e1e5
chore: revert cache
czy88840616 Oct 23, 2020
626d825
v2.3.18-beta.1
czy88840616 Oct 23, 2020
f9daf1e
chore: try add definition meteadata
czy88840616 Oct 23, 2020
2754389
refactor: add cache for definition
czy88840616 Oct 24, 2020
f412a7b
chore: lint
czy88840616 Oct 24, 2020
b9e40e7
chore: update
czy88840616 Oct 24, 2020
35bf565
fix: move cache to midwayContainer
czy88840616 Oct 24, 2020
d5f8030
v2.3.18-beta.2
czy88840616 Oct 24, 2020
44896a5
fix: configuration emit twice in app
czy88840616 Oct 24, 2020
10d06b4
refactor: merge container and midwayContainer
czy88840616 Oct 25, 2020
a17f2c2
fix: lint
czy88840616 Oct 25, 2020
4814910
fix: lint
czy88840616 Oct 25, 2020
6f46753
fix: lint
czy88840616 Oct 25, 2020
bfe1926
refactor: merge loader and base framework
czy88840616 Oct 26, 2020
f7ad592
test: fix case
czy88840616 Oct 26, 2020
e2335ff
test: change lifecycle and pass case
czy88840616 Oct 26, 2020
1afb6db
fix: lifecycle trigger
czy88840616 Oct 26, 2020
595f272
v2.3.18-beta.3
czy88840616 Oct 26, 2020
df60453
fix: configuration trigger
czy88840616 Oct 26, 2020
a0948a7
v2.3.18-beta.4
czy88840616 Oct 26, 2020
92713d8
chore: update tsc
czy88840616 Oct 27, 2020
a603d23
v2.3.18-beta.5
czy88840616 Oct 27, 2020
d9de275
chore: update
czy88840616 Oct 27, 2020
8356e59
v2.3.18-beta.6
czy88840616 Oct 27, 2020
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
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
}
},
"npmClient": "npm",
"version": "2.3.17"
"version": "2.3.18-beta.6"
}
6 changes: 3 additions & 3 deletions packages/bootstrap/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@midwayjs/bootstrap",
"version": "2.3.17",
"version": "2.3.18-beta.6",
"description": "midwayjs bootstrap",
"main": "dist/index",
"typings": "dist/index.d.ts",
Expand All @@ -22,12 +22,12 @@
"license": "MIT",
"devDependencies": {
"@midwayjs/cli": "^1.0.0",
"@midwayjs/core": "^2.3.17"
"@midwayjs/core": "^2.3.18-beta.6"
},
"author": "Harry Chen <[email protected]>",
"repository": {
"type": "git",
"url": "http://github.com/midwayjs/midway.git"
},
"gitHead": "44c0803552baf265debed8a11a860988b7e07a85"
"gitHead": "a603d2348d6141f8f723901498f03a162a037708"
}
6 changes: 3 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@midwayjs/core",
"version": "2.3.17",
"version": "2.3.18-beta.6",
"description": "midway core",
"main": "dist/index",
"typings": "dist/index.d.ts",
Expand All @@ -27,7 +27,7 @@
"sinon": "^7.2.2"
},
"dependencies": {
"@midwayjs/decorator": "^2.3.17",
"@midwayjs/decorator": "^2.3.18-beta.6",
"@midwayjs/glob": "^1.0.2",
"class-transformer": "^0.3.1",
"extend2": "^1.0.0",
Expand All @@ -48,5 +48,5 @@
"engines": {
"node": ">= 10.0.0"
},
"gitHead": "44c0803552baf265debed8a11a860988b7e07a85"
"gitHead": "a603d2348d6141f8f723901498f03a162a037708"
}
249 changes: 208 additions & 41 deletions packages/core/src/baseFramework.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
import {
IConfigurationOptions,
ILifeCycle,
IMidwayApplication,
IMidwayBootstrapOptions,
IMidwayContainer,
IMidwayFramework,
MidwayFrameworkType,
MidwayProcessTypeEnum,
} from './interface';
import { ContainerLoader } from './';
import { APPLICATION_KEY } from '@midwayjs/decorator';
import { MidwayContainer } from './context/midwayContainer';
import {
APPLICATION_KEY,
ASPECT_KEY,
CONFIGURATION_KEY,
getClassMetadata,
getProviderId,
IMethodAspect,
listModule,
listPreloadModule,
} from '@midwayjs/decorator';
import { isAbsolute, join } from 'path';

function buildLoadDir(baseDir, dir) {
if (!isAbsolute(dir)) {
return join(baseDir, dir);
}
return dir;
}

export abstract class BaseFramework<
APP extends IMidwayApplication,
Expand All @@ -17,7 +35,7 @@ export abstract class BaseFramework<
protected isTsMode = true;
protected baseDir: string;
protected appDir: string;
protected containerLoader: ContainerLoader;
protected applicationContext: IMidwayContainer;
public configurationOptions: T;
public app: APP;

Expand All @@ -26,54 +44,113 @@ export abstract class BaseFramework<
return this;
}

public async initialize(
options: Partial<IMidwayBootstrapOptions>
): Promise<void> {
public async initialize(options: IMidwayBootstrapOptions): Promise<void> {
this.baseDir = options.baseDir;
this.appDir = options.appDir;

this.containerLoader = new ContainerLoader({
baseDir: this.baseDir,
isTsMode: this.isTsMode,
preloadModules: options.preloadModules || [],
});
/**
* before create MidwayContainer instance,can change init parameters
*/
await this.beforeContainerInitialize(options);

/**
* initialize containerLoader and initialize ioc container instance
* initialize MidwayContainer instance
*/
await this.beforeInitialize(options);
this.containerLoader.initialize();
await this.containerInitialize(options);

/**
* before container load directory and bind
*/
await this.afterContainerInitialize(options);

/**
* run container loadDirectoryLoad method to create object definition
*/
await this.containerDirectoryLoad(options);

/**
* after container load directory and bind
*/
await this.afterContainerDirectoryLoad(options);

/**
* Third party application initialization
*/
await this.applicationInitialize(options);

/**
* start to load configuration and lifeCycle
*/
await this.containerReady(options);

/**
* after container refresh
*/
await this.afterContainerReady(options);
}

protected async containerInitialize(options: IMidwayBootstrapOptions) {
this.applicationContext = new MidwayContainer(this.baseDir, undefined);
this.applicationContext.disableConflictCheck =
options.disableConflictCheck || true;
this.applicationContext.registerObject('baseDir', this.baseDir);
this.applicationContext.registerObject('appDir', this.appDir);
this.applicationContext.registerObject('isTsMode', this.isTsMode);
}

protected async containerDirectoryLoad(options: IMidwayBootstrapOptions) {
/**
* load directory and bind files to ioc container
*/
await this.beforeDirectoryLoad(options);
const applicationContext = this.containerLoader.getApplicationContext();
applicationContext.registerObject('baseDir', this.baseDir);
applicationContext.registerObject('appDir', this.appDir);
// 如果没有关闭autoLoad 则进行load
this.containerLoader.loadDirectory(options);

// register app
this.containerLoader.registerHook(APPLICATION_KEY, () => {
return this.getApplication();
if (!this.isTsMode && options.disableAutoLoad === undefined) {
// disable auto load in js mode by default
options.disableAutoLoad = true;
}

if (options.disableAutoLoad) return;

// use baseDir in parameter first
const baseDir = options.baseDir || this.baseDir;
const defaultLoadDir = this.isTsMode ? [baseDir] : [];
this.applicationContext.load({
loadDir: (options.loadDir || defaultLoadDir).map(dir => {
return buildLoadDir(baseDir, dir);
}),
pattern: options.pattern,
ignore: options.ignore,
});

await this.afterDirectoryLoad(options);
if (options.preloadModules && options.preloadModules.length) {
for (const preloadModule of options.preloadModules) {
this.applicationContext.bindClass(preloadModule);
}
}

this.applicationContext.registerDataHandler(APPLICATION_KEY, () => {
return this.getApplication();
});
}

protected async containerReady(options: IMidwayBootstrapOptions) {
if (!this.app.getApplicationContext) {
this.app = this.defineApplicationProperties(this.app);
this.defineApplicationProperties();
}

/**
* start to load configuration and lifeCycle
*/
await this.containerLoader.refresh();
await this.afterInitialize(options);
await this.applicationContext.ready();
// lifecycle 支持
await this.loadLifeCycles();
// 预加载模块支持
await this.loadPreloadModule();
// 切面支持
await this.loadAspect();
}

protected async containerStop() {
await this.applicationContext.stop();
}

public getApplicationContext(): IMidwayContainer {
return this.containerLoader.getApplicationContext();
return this.applicationContext;
}

public getConfiguration(key?: string): any {
Expand All @@ -88,6 +165,8 @@ export abstract class BaseFramework<
.getCurrentEnvironment();
}

public abstract async applicationInitialize(options: IMidwayBootstrapOptions);

public abstract getFrameworkType(): MidwayFrameworkType;

public abstract getApplication(): APP;
Expand All @@ -96,11 +175,11 @@ export abstract class BaseFramework<

public async stop(): Promise<void> {
await this.beforeStop();
await this.containerLoader.stop();
await this.containerStop();
}

protected defineApplicationProperties(app: APP): APP {
return Object.assign(app, {
protected defineApplicationProperties(applicationProperties: object = {}) {
const defaultApplicationProperties = {
getBaseDir: () => {
return this.baseDir;
},
Expand All @@ -115,6 +194,10 @@ export abstract class BaseFramework<
.getCurrentEnvironment();
},

getApplicationContext: () => {
return this.getApplicationContext();
},

getConfig: (key?: string) => {
return this.getApplicationContext()
.getConfigService()
Expand All @@ -128,24 +211,108 @@ export abstract class BaseFramework<
getProcessType: () => {
return MidwayProcessTypeEnum.APPLICATION;
},
});
};
Object.assign(
this.app,
defaultApplicationProperties,
applicationProperties
);
}

protected async beforeStop(): Promise<void> {}

protected async beforeInitialize(
protected async beforeContainerInitialize(
options: Partial<IMidwayBootstrapOptions>
): Promise<void> {}

protected async beforeDirectoryLoad(
protected async afterContainerInitialize(
options: Partial<IMidwayBootstrapOptions>
): Promise<void> {}

protected async afterDirectoryLoad(
protected async afterContainerDirectoryLoad(
options: Partial<IMidwayBootstrapOptions>
): Promise<void> {}

protected abstract async afterInitialize(
protected async afterContainerReady(
options: Partial<IMidwayBootstrapOptions>
): Promise<void>;
): Promise<void> {}

public async loadLifeCycles() {
// agent 不加载生命周期
if (this.app.getProcessType() === MidwayProcessTypeEnum.AGENT) return;
const cycles: Array<{ target: any; namespace: string }> = listModule(
CONFIGURATION_KEY
);
for (const cycle of cycles) {
const providerId = getProviderId(cycle.target);
const inst = await this.getApplicationContext().getAsync<ILifeCycle>(
providerId
);
if (typeof inst.onReady === 'function') {
/**
* 让组件能正确获取到 bind 之后 registerObject 的对象有三个方法
* 1、在 load 之后修改 bind,不太可行
* 2、每次 getAsync 的时候,去掉 namespace,同时还要查找当前全局的变量,性能差
* 3、一般只会在 onReady 的地方执行 registerObject(否则没有全局的意义),这个取巧的办法就是 onReady 传入一个代理,其中绑定当前的 namespace
*/
await inst.onReady(
new Proxy(this.getApplicationContext(), {
get: function (target, prop, receiver) {
if (prop === 'getCurrentNamespace' && cycle.namespace) {
return () => {
return cycle.namespace;
};
}
return Reflect.get(target, prop, receiver);
},
})
);
}
}
}

/**
* load preload module for container
* @private
*/
private async loadPreloadModule() {
// some common decorator implementation
const modules = listPreloadModule();
for (const module of modules) {
// preload init context
await this.getApplicationContext().getAsync(module);
}
}

/**
* load aspect method for container
* @private
*/
private async loadAspect() {
// for aop implementation
const aspectModules = listModule(ASPECT_KEY);
// sort for aspect target
let aspectDataList = [];
for (const module of aspectModules) {
const data = getClassMetadata(ASPECT_KEY, module);
aspectDataList = aspectDataList.concat(
data.map(el => {
el.aspectModule = module;
return el;
})
);
}

// sort priority
aspectDataList.sort((pre, next) => {
return (next.priority || 0) - (pre.priority || 0);
});

for (const aspectData of aspectDataList) {
const aspectIns = await this.getApplicationContext().getAsync<
IMethodAspect
>(aspectData.aspectModule);
await this.getApplicationContext().addAspect(aspectIns, aspectData);
}
}
}
Loading