Skip to content

Commit

Permalink
fix: export EggAppConfig type let plugin can override it (#286)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Type Safety Improvements**
	- Enhanced type definitions for application configuration
	- Centralized type management across modules
	- Introduced more precise type checking for configuration objects

- **Code Structure**
	- Refactored type imports and exports
	- Updated case style handling with new enum
	- Simplified type management in loader components

- **Testing**
	- Added type exposure tests
	- Updated test configurations to reflect new type structures

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
fengmk2 authored Jan 3, 2025
1 parent 31f2580 commit 62b1f97
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 66 deletions.
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';
72 changes: 20 additions & 52 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 = {
middleware: [],
coreMiddleware: [],
};

// Load Application config first
const appConfig = await this.#preloadAppConfig();
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[];
middleware: 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: [],
middleware: [],
} as EggAppConfig;
assert(config.middleware);
assert(config.coreMiddleware);
});
});
10 changes: 5 additions & 5 deletions test/loader/file_loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { strict as assert } from 'node:assert';
import path from 'node:path';
import { isClass } from 'is-type-of';
import yaml from 'js-yaml';
import { FileLoader } from '../../src/loader/file_loader.js';
import { FileLoader, CaseStyle } from '../../src/loader/file_loader.js';
import { getFilepath } from '../helper.js';

const dirBase = getFilepath('load_dirs');
Expand Down Expand Up @@ -275,7 +275,7 @@ describe('test/loader/file_loader.test.ts', () => {
await new FileLoader({
directory: path.join(dirBase, 'camelize'),
target,
caseStyle: 'upper',
caseStyle: CaseStyle.upper,
}).load();

assert(target.FooBar1);
Expand All @@ -289,7 +289,7 @@ describe('test/loader/file_loader.test.ts', () => {
await new FileLoader({
directory: path.join(dirBase, 'camelize'),
target,
caseStyle: 'camel',
caseStyle: CaseStyle.camel,
}).load();

assert(target.fooBar1);
Expand All @@ -303,7 +303,7 @@ describe('test/loader/file_loader.test.ts', () => {
await new FileLoader({
directory: path.join(dirBase, 'camelize'),
target,
caseStyle: 'lower',
caseStyle: CaseStyle.lower,
}).load();

assert(target.fooBar1);
Expand Down Expand Up @@ -349,7 +349,7 @@ describe('test/loader/file_loader.test.ts', () => {
await new FileLoader({
directory: path.join(dirBase, 'camelize'),
target,
caseStyle: 'upper',
caseStyle: CaseStyle.upper,
lowercaseFirst: true,
}).load();

Expand Down
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
Loading

0 comments on commit 62b1f97

Please sign in to comment.