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: export EggAppConfig type let plugin can override it #286

Merged
merged 3 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
5 changes: 3 additions & 2 deletions src/egg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type { Fun } from './utils/index.js';
import { Lifecycle } from './lifecycle.js';
import { EggLoader } from './loader/egg_loader.js';
import utils from './utils/index.js';
import { EggAppConfig } from './types.js';

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

Expand Down Expand Up @@ -247,8 +248,8 @@ export class EggCore extends KoaApplication {
* @member {Config}
* @since 1.0.0
*/
get config() {
return this.loader ? this.loader.config : {};
get config(): EggAppConfig {
return this.loader ? this.loader.config : {} as EggAppConfig;
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './loader/file_loader.js';
export * from './loader/context_loader.js';
export * from './utils/sequencify.js';
export * from './utils/timing.js';
export type * from './types.js';
76 changes: 22 additions & 54 deletions src/loader/egg_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { extend } from 'extend2';
import { Request, Response, Application, Context as KoaContext } from '@eggjs/koa';
import { pathMatching, type PathMatchingOptions } from 'egg-path-matching';
import { now, diff } from 'performance-ms';
import { FULLPATH, FileLoader, FileLoaderOptions } from './file_loader.js';
import { CaseStyle, FULLPATH, FileLoader, FileLoaderOptions } from './file_loader.js';
import { ContextLoader, ContextLoaderOptions } from './context_loader.js';
import utils, { Fun } from '../utils/index.js';
import sequencify from '../utils/sequencify.js';
Expand All @@ -19,6 +19,7 @@ import type {
Context, EggCore, MiddlewareFunc,
} from '../egg.js';
import type { BaseContextClass } from '../base_context_class.js';
import type { EggAppConfig, EggAppInfo, EggPluginInfo } from '../types.js';

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

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

export interface EggAppInfo {
/** package.json */
pkg: Record<string, any>;
/** the application name from package.json */
name: string;
/** current directory of application */
baseDir: string;
/** equals to serverEnv */
env: string;
/** equals to serverScope */
scope: string;
/** home directory of the OS */
HOME: string;
/** baseDir when local and unittest, HOME when other environment */
root: string;
}

export interface EggPluginInfo {
/** the plugin name, it can be used in `dep` */
name: string;
/** the package name of plugin */
package?: string;
version?: string;
/** whether enabled */
enable: boolean;
implicitEnable?: boolean;
/** the directory of the plugin package */
path?: string;
/** the dependent plugins, you can use the plugin name */
dependencies: string[];
/** the optional dependent plugins. */
optionalDependencies: string[];
dependents?: string[];
/** specify the serverEnv that only enable the plugin in it */
env: string[];
/** the file plugin config in. */
from: string;
}

export interface EggLoaderOptions {
/** server env */
Expand Down Expand Up @@ -845,7 +808,7 @@ export class EggLoader {

/** start Config loader */
configMeta: Record<string, any>;
config: Record<string, any>;
config: EggAppConfig;

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

const target: Record<string, any> = {};
const target: EggAppConfig = {
appMiddleware: [],
coreMiddleware: [],
};

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

// You can manipulate the order of app.config.coreMiddleware and app.config.appMiddleware in app.js
target.coreMiddleware = target.coreMiddlewares = target.coreMiddleware || [];
target.appMiddleware = target.appMiddlewares = target.middleware || [];
target.coreMiddlewares = target.coreMiddleware;
target.appMiddlewares = target.middleware;

this.config = target;
debug('[loadConfig] all config: %o', this.config);
Expand Down Expand Up @@ -1208,7 +1174,7 @@ export class EggLoader {
const servicePaths = this.getLoadUnits().map(unit => path.join(unit.path, 'app/service'));
options = {
call: true,
caseStyle: 'lower',
caseStyle: CaseStyle.lower,
fieldClass: 'serviceClasses',
directory: servicePaths,
...options,
Expand Down Expand Up @@ -1248,7 +1214,7 @@ export class EggLoader {
opt = {
call: false,
override: true,
caseStyle: 'lower',
caseStyle: CaseStyle.lower,
directory: middlewarePaths,
...opt,
};
Expand Down Expand Up @@ -1323,7 +1289,7 @@ export class EggLoader {
this.timing.start('Load Controller');
const controllerBase = path.join(this.options.baseDir, 'app/controller');
opt = {
caseStyle: 'lower',
caseStyle: CaseStyle.lower,
directory: controllerBase,
initializer: (obj, opt) => {
// return class if it exports a function
Expand Down Expand Up @@ -1403,7 +1369,7 @@ export class EggLoader {
case 'ctx': {
assert(!(property in this.app.context), `customLoader should not override ctx.${property}`);
const options = {
caseStyle: 'lower',
caseStyle: CaseStyle.lower,
fieldClass: `${property}Classes`,
...loaderConfig,
directory,
Expand All @@ -1414,7 +1380,7 @@ export class EggLoader {
case 'app': {
assert(!(property in this.app), `customLoader should not override app.${property}`);
const options = {
caseStyle: 'lower',
caseStyle: CaseStyle.lower,
initializer: (Clazz: unknown) => {
return isClass(Clazz) ? new Clazz(this.app) : Clazz;
},
Expand Down Expand Up @@ -1533,10 +1499,11 @@ export class EggLoader {
* @param {Object} options - see {@link FileLoader}
* @since 1.0.0
*/
async loadToApp(directory: string | string[], property: string | symbol, options?: FileLoaderOptions) {
async loadToApp(directory: string | string[], property: string | symbol,
options?: Omit<FileLoaderOptions, 'inject' | 'target'>) {
const target = {};
Reflect.set(this.app, property, target);
options = {
const loadOptions: FileLoaderOptions = {
...options,
directory: options?.directory ?? directory,
target,
Expand All @@ -1545,7 +1512,7 @@ export class EggLoader {

const timingKey = `Load "${String(property)}" to Application`;
this.timing.start(timingKey);
await new FileLoader(options).load();
await new FileLoader(loadOptions).load();
this.timing.end(timingKey);
}

Expand All @@ -1556,8 +1523,9 @@ export class EggLoader {
* @param {Object} options - see {@link ContextLoader}
* @since 1.0.0
*/
async loadToContext(directory: string | string[], property: string | symbol, options?: ContextLoaderOptions) {
options = {
async loadToContext(directory: string | string[], property: string | symbol,
options?: Omit<ContextLoaderOptions, 'inject' | 'property'>) {
const loadOptions: ContextLoaderOptions = {
...options,
directory: options?.directory || directory,
property,
Expand All @@ -1566,7 +1534,7 @@ export class EggLoader {

const timingKey = `Load "${String(property)}" to Context`;
this.timing.start(timingKey);
await new ContextLoader(options).load();
await new ContextLoader(loadOptions).load();
this.timing.end(timingKey);
}

Expand Down
11 changes: 8 additions & 3 deletions src/loader/file_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ const debug = debuglog('@eggjs/core/file_loader');
export const FULLPATH = Symbol('EGG_LOADER_ITEM_FULLPATH');
export const EXPORTS = Symbol('EGG_LOADER_ITEM_EXPORTS');

export type CaseStyle = 'camel' | 'lower' | 'upper';
export enum CaseStyle {
camel = 'camel',
lower = 'lower',
upper = 'upper',
}

export type CaseStyleFunction = (filepath: string) => string[];
export type FileLoaderInitializer = (exports: unknown, options: { path: string; pathName: string }) => unknown;
export type FileLoaderFilter = (exports: unknown) => boolean;
Expand Down Expand Up @@ -79,7 +84,7 @@ export class FileLoader {
assert(options.directory, 'options.directory is required');
assert(options.target, 'options.target is required');
this.options = {
caseStyle: 'camel',
caseStyle: CaseStyle.camel,
call: true,
override: false,
...options,
Expand All @@ -88,7 +93,7 @@ export class FileLoader {
// compatible old options _lowercaseFirst_
if (this.options.lowercaseFirst === true) {
utils.deprecated('lowercaseFirst is deprecated, use caseStyle instead');
this.options.caseStyle = 'lower';
this.options.caseStyle = CaseStyle.lower;
}
}

Expand Down
56 changes: 56 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
export interface EggAppInfo {
/** package.json */
pkg: Record<string, any>;
/** the application name from package.json */
name: string;
/** current directory of application */
baseDir: string;
/** equals to serverEnv */
env: string;
/** equals to serverScope */
scope: string;
/** home directory of the OS */
HOME: string;
/** baseDir when local and unittest, HOME when other environment */
root: string;
}

export interface EggPluginInfo {
/** the plugin name, it can be used in `dep` */
name: string;
/** the package name of plugin */
package?: string;
version?: string;
/** whether enabled */
enable: boolean;
implicitEnable?: boolean;
/** the directory of the plugin package */
path?: string;
/** the dependent plugins, you can use the plugin name */
dependencies: string[];
/** the optional dependent plugins. */
optionalDependencies: string[];
dependents?: string[];
/** specify the serverEnv that only enable the plugin in it */
env: string[];
/** the file plugin config in. */
from: string;
}

export interface CustomLoaderConfigItem {
/** the directory of the custom loader */
directory: string;
/** the inject object, it can be app or ctx */
inject: string;
/** whether load unit files */
loadunit?: boolean;
}

export interface EggAppConfig extends Record<string, any> {
coreMiddleware: string[];
appMiddleware: string[];
customLoader?: Record<string, CustomLoaderConfigItem>;
controller?: {
supportParams?: boolean;
};
}
11 changes: 11 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { strict as assert } from 'node:assert';
import * as EggCore from '../src/index.js';
import type { EggAppConfig } from '../src/index.js';

describe('test/index.test.ts', () => {
it('should expose properties', () => {
Expand All @@ -10,6 +11,7 @@ describe('test/index.test.ts', () => {
console.log(Object.keys(EggCore));
assert.deepEqual(Object.keys(EggCore), [
'BaseContextClass',
'CaseStyle',
'ClassLoader',
'Context',
'ContextLoader',
Expand All @@ -31,4 +33,13 @@ describe('test/index.test.ts', () => {
'utils',
]);
});

it('should expose types', () => {
const config = {
coreMiddleware: [],
appMiddleware: [],
} as EggAppConfig;
assert(config.appMiddleware);
assert(config.coreMiddleware);
});
});
2 changes: 1 addition & 1 deletion test/loader/mixin/load_controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ describe('test/loader/mixin/load_controller.test.ts', () => {
});

it('should support parameter', async () => {
assert.equal(app.config.controller.supportParams, true);
assert.equal(app.config.controller!.supportParams, true);
const ctx = { app };
const args = [ 1, 2, 3 ];
let r = await app.controller.generatorFunction.call(ctx, ...args);
Expand Down
2 changes: 2 additions & 0 deletions test/loader/mixin/load_custom_loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ describe('test/loader/mixin/load_custom_loader.test.ts', () => {
const app = createApp('custom-loader');
try {
app.loader.config = {
coreMiddleware: [],
appMiddleware: [],
customLoader: {
config: {
directory: 'app/config',
Expand Down
Loading