Skip to content

Commit 5a80a53

Browse files
committed
fix: export EggAppConfig type let plugin can override it
1 parent 31f2580 commit 5a80a53

8 files changed

+104
-60
lines changed

src/egg.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type { Fun } from './utils/index.js';
1818
import { Lifecycle } from './lifecycle.js';
1919
import { EggLoader } from './loader/egg_loader.js';
2020
import utils from './utils/index.js';
21+
import { EggAppConfig } from './types.js';
2122

2223
const debug = debuglog('@eggjs/core/egg');
2324

@@ -247,8 +248,8 @@ export class EggCore extends KoaApplication {
247248
* @member {Config}
248249
* @since 1.0.0
249250
*/
250-
get config() {
251-
return this.loader ? this.loader.config : {};
251+
get config(): EggAppConfig {
252+
return this.loader ? this.loader.config : {} as EggAppConfig;
252253
}
253254

254255
/**

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export * from './loader/file_loader.js';
1010
export * from './loader/context_loader.js';
1111
export * from './utils/sequencify.js';
1212
export * from './utils/timing.js';
13+
export type * from './types.js';

src/loader/egg_loader.ts

+22-54
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { extend } from 'extend2';
1010
import { Request, Response, Application, Context as KoaContext } from '@eggjs/koa';
1111
import { pathMatching, type PathMatchingOptions } from 'egg-path-matching';
1212
import { now, diff } from 'performance-ms';
13-
import { FULLPATH, FileLoader, FileLoaderOptions } from './file_loader.js';
13+
import { CaseStyle, FULLPATH, FileLoader, FileLoaderOptions } from './file_loader.js';
1414
import { ContextLoader, ContextLoaderOptions } from './context_loader.js';
1515
import utils, { Fun } from '../utils/index.js';
1616
import sequencify from '../utils/sequencify.js';
@@ -19,6 +19,7 @@ import type {
1919
Context, EggCore, MiddlewareFunc,
2020
} from '../egg.js';
2121
import type { BaseContextClass } from '../base_context_class.js';
22+
import type { EggAppConfig, EggAppInfo, EggPluginInfo } from '../types.js';
2223

2324
const debug = debuglog('@eggjs/core/loader/egg_loader');
2425

@@ -29,44 +30,6 @@ const originalPrototypes: Record<string, any> = {
2930
application: Application.prototype,
3031
};
3132

32-
export interface EggAppInfo {
33-
/** package.json */
34-
pkg: Record<string, any>;
35-
/** the application name from package.json */
36-
name: string;
37-
/** current directory of application */
38-
baseDir: string;
39-
/** equals to serverEnv */
40-
env: string;
41-
/** equals to serverScope */
42-
scope: string;
43-
/** home directory of the OS */
44-
HOME: string;
45-
/** baseDir when local and unittest, HOME when other environment */
46-
root: string;
47-
}
48-
49-
export interface EggPluginInfo {
50-
/** the plugin name, it can be used in `dep` */
51-
name: string;
52-
/** the package name of plugin */
53-
package?: string;
54-
version?: string;
55-
/** whether enabled */
56-
enable: boolean;
57-
implicitEnable?: boolean;
58-
/** the directory of the plugin package */
59-
path?: string;
60-
/** the dependent plugins, you can use the plugin name */
61-
dependencies: string[];
62-
/** the optional dependent plugins. */
63-
optionalDependencies: string[];
64-
dependents?: string[];
65-
/** specify the serverEnv that only enable the plugin in it */
66-
env: string[];
67-
/** the file plugin config in. */
68-
from: string;
69-
}
7033

7134
export interface EggLoaderOptions {
7235
/** server env */
@@ -845,7 +808,7 @@ export class EggLoader {
845808

846809
/** start Config loader */
847810
configMeta: Record<string, any>;
848-
config: Record<string, any>;
811+
config: EggAppConfig;
849812

850813
/**
851814
* Load config/config.js
@@ -859,7 +822,10 @@ export class EggLoader {
859822
this.timing.start('Load Config');
860823
this.configMeta = {};
861824

862-
const target: Record<string, any> = {};
825+
const target: EggAppConfig = {
826+
appMiddleware: [],
827+
coreMiddleware: [],
828+
};
863829

864830
// Load Application config first
865831
const appConfig = await this.#preloadAppConfig();
@@ -889,8 +855,8 @@ export class EggLoader {
889855
extend(true, target, envConfig);
890856

891857
// You can manipulate the order of app.config.coreMiddleware and app.config.appMiddleware in app.js
892-
target.coreMiddleware = target.coreMiddlewares = target.coreMiddleware || [];
893-
target.appMiddleware = target.appMiddlewares = target.middleware || [];
858+
target.coreMiddlewares = target.coreMiddleware;
859+
target.appMiddlewares = target.middleware;
894860

895861
this.config = target;
896862
debug('[loadConfig] all config: %o', this.config);
@@ -1208,7 +1174,7 @@ export class EggLoader {
12081174
const servicePaths = this.getLoadUnits().map(unit => path.join(unit.path, 'app/service'));
12091175
options = {
12101176
call: true,
1211-
caseStyle: 'lower',
1177+
caseStyle: CaseStyle.lower,
12121178
fieldClass: 'serviceClasses',
12131179
directory: servicePaths,
12141180
...options,
@@ -1248,7 +1214,7 @@ export class EggLoader {
12481214
opt = {
12491215
call: false,
12501216
override: true,
1251-
caseStyle: 'lower',
1217+
caseStyle: CaseStyle.lower,
12521218
directory: middlewarePaths,
12531219
...opt,
12541220
};
@@ -1323,7 +1289,7 @@ export class EggLoader {
13231289
this.timing.start('Load Controller');
13241290
const controllerBase = path.join(this.options.baseDir, 'app/controller');
13251291
opt = {
1326-
caseStyle: 'lower',
1292+
caseStyle: CaseStyle.lower,
13271293
directory: controllerBase,
13281294
initializer: (obj, opt) => {
13291295
// return class if it exports a function
@@ -1403,7 +1369,7 @@ export class EggLoader {
14031369
case 'ctx': {
14041370
assert(!(property in this.app.context), `customLoader should not override ctx.${property}`);
14051371
const options = {
1406-
caseStyle: 'lower',
1372+
caseStyle: CaseStyle.lower,
14071373
fieldClass: `${property}Classes`,
14081374
...loaderConfig,
14091375
directory,
@@ -1414,7 +1380,7 @@ export class EggLoader {
14141380
case 'app': {
14151381
assert(!(property in this.app), `customLoader should not override app.${property}`);
14161382
const options = {
1417-
caseStyle: 'lower',
1383+
caseStyle: CaseStyle.lower,
14181384
initializer: (Clazz: unknown) => {
14191385
return isClass(Clazz) ? new Clazz(this.app) : Clazz;
14201386
},
@@ -1533,10 +1499,11 @@ export class EggLoader {
15331499
* @param {Object} options - see {@link FileLoader}
15341500
* @since 1.0.0
15351501
*/
1536-
async loadToApp(directory: string | string[], property: string | symbol, options?: FileLoaderOptions) {
1502+
async loadToApp(directory: string | string[], property: string | symbol,
1503+
options?: Omit<FileLoaderOptions, 'inject' | 'target'>) {
15371504
const target = {};
15381505
Reflect.set(this.app, property, target);
1539-
options = {
1506+
const loadOptions: FileLoaderOptions = {
15401507
...options,
15411508
directory: options?.directory ?? directory,
15421509
target,
@@ -1545,7 +1512,7 @@ export class EggLoader {
15451512

15461513
const timingKey = `Load "${String(property)}" to Application`;
15471514
this.timing.start(timingKey);
1548-
await new FileLoader(options).load();
1515+
await new FileLoader(loadOptions).load();
15491516
this.timing.end(timingKey);
15501517
}
15511518

@@ -1556,8 +1523,9 @@ export class EggLoader {
15561523
* @param {Object} options - see {@link ContextLoader}
15571524
* @since 1.0.0
15581525
*/
1559-
async loadToContext(directory: string | string[], property: string | symbol, options?: ContextLoaderOptions) {
1560-
options = {
1526+
async loadToContext(directory: string | string[], property: string | symbol,
1527+
options?: Omit<ContextLoaderOptions, 'inject' | 'property'>) {
1528+
const loadOptions: ContextLoaderOptions = {
15611529
...options,
15621530
directory: options?.directory || directory,
15631531
property,
@@ -1566,7 +1534,7 @@ export class EggLoader {
15661534

15671535
const timingKey = `Load "${String(property)}" to Context`;
15681536
this.timing.start(timingKey);
1569-
await new ContextLoader(options).load();
1537+
await new ContextLoader(loadOptions).load();
15701538
this.timing.end(timingKey);
15711539
}
15721540

src/loader/file_loader.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ const debug = debuglog('@eggjs/core/file_loader');
1111
export const FULLPATH = Symbol('EGG_LOADER_ITEM_FULLPATH');
1212
export const EXPORTS = Symbol('EGG_LOADER_ITEM_EXPORTS');
1313

14-
export type CaseStyle = 'camel' | 'lower' | 'upper';
14+
export enum CaseStyle {
15+
camel = 'camel',
16+
lower = 'lower',
17+
upper = 'upper',
18+
}
19+
1520
export type CaseStyleFunction = (filepath: string) => string[];
1621
export type FileLoaderInitializer = (exports: unknown, options: { path: string; pathName: string }) => unknown;
1722
export type FileLoaderFilter = (exports: unknown) => boolean;
@@ -79,7 +84,7 @@ export class FileLoader {
7984
assert(options.directory, 'options.directory is required');
8085
assert(options.target, 'options.target is required');
8186
this.options = {
82-
caseStyle: 'camel',
87+
caseStyle: CaseStyle.camel,
8388
call: true,
8489
override: false,
8590
...options,
@@ -88,7 +93,7 @@ export class FileLoader {
8893
// compatible old options _lowercaseFirst_
8994
if (this.options.lowercaseFirst === true) {
9095
utils.deprecated('lowercaseFirst is deprecated, use caseStyle instead');
91-
this.options.caseStyle = 'lower';
96+
this.options.caseStyle = CaseStyle.lower;
9297
}
9398
}
9499

src/types.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
export interface EggAppInfo {
2+
/** package.json */
3+
pkg: Record<string, any>;
4+
/** the application name from package.json */
5+
name: string;
6+
/** current directory of application */
7+
baseDir: string;
8+
/** equals to serverEnv */
9+
env: string;
10+
/** equals to serverScope */
11+
scope: string;
12+
/** home directory of the OS */
13+
HOME: string;
14+
/** baseDir when local and unittest, HOME when other environment */
15+
root: string;
16+
}
17+
18+
export interface EggPluginInfo {
19+
/** the plugin name, it can be used in `dep` */
20+
name: string;
21+
/** the package name of plugin */
22+
package?: string;
23+
version?: string;
24+
/** whether enabled */
25+
enable: boolean;
26+
implicitEnable?: boolean;
27+
/** the directory of the plugin package */
28+
path?: string;
29+
/** the dependent plugins, you can use the plugin name */
30+
dependencies: string[];
31+
/** the optional dependent plugins. */
32+
optionalDependencies: string[];
33+
dependents?: string[];
34+
/** specify the serverEnv that only enable the plugin in it */
35+
env: string[];
36+
/** the file plugin config in. */
37+
from: string;
38+
}
39+
40+
export interface CustomLoaderConfigItem {
41+
/** the directory of the custom loader */
42+
directory: string;
43+
/** the inject object, it can be app or ctx */
44+
inject: string;
45+
/** whether load unit files */
46+
loadunit?: boolean;
47+
}
48+
49+
export interface EggAppConfig extends Record<string, any> {
50+
coreMiddleware: string[];
51+
appMiddleware: string[];
52+
customLoader?: Record<string, CustomLoaderConfigItem>;
53+
controller?: {
54+
supportParams?: boolean;
55+
};
56+
}

test/index.test.ts

+11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { strict as assert } from 'node:assert';
22
import * as EggCore from '../src/index.js';
3+
import type { EggAppConfig } from '../src/index.js';
34

45
describe('test/index.test.ts', () => {
56
it('should expose properties', () => {
@@ -10,6 +11,7 @@ describe('test/index.test.ts', () => {
1011
console.log(Object.keys(EggCore));
1112
assert.deepEqual(Object.keys(EggCore), [
1213
'BaseContextClass',
14+
'CaseStyle',
1315
'ClassLoader',
1416
'Context',
1517
'ContextLoader',
@@ -31,4 +33,13 @@ describe('test/index.test.ts', () => {
3133
'utils',
3234
]);
3335
});
36+
37+
it('should expose types', () => {
38+
const config = {
39+
coreMiddleware: [],
40+
appMiddleware: [],
41+
} as EggAppConfig;
42+
assert(config.appMiddleware);
43+
assert(config.coreMiddleware);
44+
});
3445
});

test/loader/mixin/load_controller.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ describe('test/loader/mixin/load_controller.test.ts', () => {
379379
});
380380

381381
it('should support parameter', async () => {
382-
assert.equal(app.config.controller.supportParams, true);
382+
assert.equal(app.config.controller!.supportParams, true);
383383
const ctx = { app };
384384
const args = [ 1, 2, 3 ];
385385
let r = await app.controller.generatorFunction.call(ctx, ...args);

test/loader/mixin/load_custom_loader.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ describe('test/loader/mixin/load_custom_loader.test.ts', () => {
102102
const app = createApp('custom-loader');
103103
try {
104104
app.loader.config = {
105+
coreMiddleware: [],
106+
appMiddleware: [],
105107
customLoader: {
106108
config: {
107109
directory: 'app/config',

0 commit comments

Comments
 (0)