Skip to content

Commit

Permalink
feat: use app.loader.getTypeFiles to generate module config file names (
Browse files Browse the repository at this point in the history
#213)

<!--
Thank you for your pull request. Please review below requirements.
Bug fixes and new features should include tests and possibly benchmarks.
Contributors guide:
https://github.com/eggjs/egg/blob/master/CONTRIBUTING.md

感谢您贡献代码。请确认下列 checklist 的完成情况。
Bug 修复和新功能必须包含测试,必要时请附上性能测试。
Contributors guide:
https://github.com/eggjs/egg/blob/master/CONTRIBUTING.md
-->

##### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to
[x]. -->

- [ ] `npm test` passes
- [ ] tests and/or benchmarks are included
- [ ] documentation is changed or added
- [ ] commit message follows commit guidelines

##### Affected core subsystem(s)
<!-- Provide affected core subsystem(s). -->


##### Description of change
<!-- Provide a description of the change below this comment. -->

<!--
- any feature?
- close https://github.com/eggjs/egg/ISSUE_URL
-->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
	- Introduced default configuration loading for specific module files.

- **Refactor**
- Enhanced module configuration management with new methods and
asynchronous loading capabilities.
- Updated import syntax and added comprehensive tests for configuration
loading.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: killa <[email protected]>
  • Loading branch information
gxkl and killagu authored Apr 19, 2024
1 parent 8411e07 commit e0656a4
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 51 deletions.
109 changes: 67 additions & 42 deletions core/common-util/src/ModuleConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,10 @@ const DEFAULT_READ_MODULE_REF_OPTS = {
};

export class ModuleConfigUtil {
public static moduleYamlPath(modulePath: string, env?: string): string {
if (env) {
return path.join(modulePath, `module.${env}.yml`);
}
return path.join(modulePath, 'module.yml');
}
static configNames: string[] | undefined;

public static moduleJsonPath(modulePath: string, env?: string): string {
if (env) {
return path.join(modulePath, `module.${env}.json`);
}
return path.join(modulePath, 'module.json');
public static setConfigNames(configNames: string[] | undefined) {
ModuleConfigUtil.configNames = configNames;
}

public static readModuleReference(baseDir: string, options?: ReadModuleReferenceOptions): readonly ModuleReference[] {
Expand Down Expand Up @@ -205,25 +197,42 @@ export class ModuleConfigUtil {
return ModuleConfigUtil.getModuleName(pkg);
}

public static async loadModuleConfig(moduleDir: string, baseDir?: string, env?: string): Promise<ModuleConfig | undefined> {
moduleDir = ModuleConfigUtil.resolveModuleDir(moduleDir, baseDir);
let defaultConfig = await ModuleConfigUtil.loadModuleYaml(moduleDir);
if (!defaultConfig) {
defaultConfig = await ModuleConfigUtil.loadModuleJson(moduleDir);
}
let envConfig: ModuleConfig | undefined;
public static async loadModuleConfig(moduleDir: string, baseDir?: string, env?: string): Promise<ModuleConfig> {
const modulePath = ModuleConfigUtil.resolveModuleDir(moduleDir, baseDir);
let configNames: string[];
if (env) {
envConfig = await ModuleConfigUtil.loadModuleYaml(moduleDir, env);
if (!envConfig) {
envConfig = await ModuleConfigUtil.loadModuleJson(moduleDir, env);
configNames = [ 'module', `module.${env}` ];
} else {
// assert(ModuleConfigUtil.configNames, 'should setConfigNames before load module config');
configNames = ModuleConfigUtil.configNames || [ 'module' ];
}

const target: ModuleConfig = {};
for (const configName of configNames) {
let config = await ModuleConfigUtil.#loadOne(modulePath, configName);
// both module.yml and module.default.yml are ok for default config
if (configName === 'module.default' && !config) {
config = await ModuleConfigUtil.#loadOne(modulePath, 'module');
}
if (config) {
extend(true, target, config);
}
}
extend(true, defaultConfig, envConfig);
return defaultConfig;

return target;
}

private static async loadModuleJson(moduleDir: string, env?: string): Promise<ModuleConfig | undefined> {
const moduleJsonPath = ModuleConfigUtil.moduleJsonPath(moduleDir, env);
static async #loadOne(moduleDir: string, configName: string): Promise<ModuleConfig | undefined> {
const yamlConfigPath = path.join(moduleDir, `${configName}.yml`);
let config = await ModuleConfigUtil.#loadYaml(yamlConfigPath);
if (!config) {
const jsonConfigPath = path.join(moduleDir, `${configName}.json`);
config = await ModuleConfigUtil.#loadJson(jsonConfigPath);
}
return config;
}

static async #loadJson(moduleJsonPath: string): Promise<ModuleConfig | undefined> {
const moduleJsonPathExists = await FSUtil.fileExists(moduleJsonPath);
if (!moduleJsonPathExists) {
return;
Expand All @@ -233,8 +242,7 @@ export class ModuleConfigUtil {
return moduleJson.config;
}

private static async loadModuleYaml(moduleDir: string, env?: string): Promise<ModuleConfig | undefined> {
const moduleYamlPath = ModuleConfigUtil.moduleYamlPath(moduleDir, env);
static async #loadYaml(moduleYamlPath: string): Promise<ModuleConfig | undefined> {
const moduleYamlPathExists = await FSUtil.fileExists(moduleYamlPath);
if (!moduleYamlPathExists) {
return;
Expand All @@ -243,24 +251,42 @@ export class ModuleConfigUtil {
return yaml.safeLoad(moduleYamlContent) as ModuleConfigUtil;
}

public static loadModuleConfigSync(moduleDir: string, baseDir?: string, env?: string): ModuleConfig | undefined {
moduleDir = ModuleConfigUtil.resolveModuleDir(moduleDir, baseDir);
let defaultConfig = ModuleConfigUtil.loadModuleYamlSync(moduleDir);
if (!defaultConfig) {
defaultConfig = ModuleConfigUtil.loadModuleJsonSync(moduleDir);
}
let envConfig: ModuleConfig | undefined;
public static loadModuleConfigSync(moduleDir: string, baseDir?: string, env?: string): ModuleConfig {
const modulePath = ModuleConfigUtil.resolveModuleDir(moduleDir, baseDir);
let configNames: string[];
if (env) {
envConfig = ModuleConfigUtil.loadModuleYamlSync(moduleDir, env);
if (!envConfig) {
envConfig = ModuleConfigUtil.loadModuleJsonSync(moduleDir, env);
configNames = [ 'module', `module.${env}` ];
} else {
// assert(ModuleConfigUtil.configNames, 'should setConfigNames before load module config');
configNames = ModuleConfigUtil.configNames || [ 'module' ];
}

const target: ModuleConfig = {};
for (const configName of configNames) {
let config = ModuleConfigUtil.#loadOneSync(modulePath, configName);
// both module.yml and module.default.yml are ok for default config
if (configName === 'module.default' && !config) {
config = ModuleConfigUtil.#loadOneSync(modulePath, 'module');
}
if (config) {
extend(true, target, config);
}
}

return target;
}

static #loadOneSync(moduleDir: string, configName: string): ModuleConfig | undefined {
const yamlConfigPath = path.join(moduleDir, `${configName}.yml`);
let config = ModuleConfigUtil.#loadYamlSync(yamlConfigPath);
if (!config) {
const jsonConfigPath = path.join(moduleDir, `${configName}.json`);
config = ModuleConfigUtil.#loadJsonSync(jsonConfigPath);
}
return extend(true, defaultConfig, envConfig);
return config;
}

private static loadModuleJsonSync(moduleDir: string, env?: string): ModuleConfig | undefined {
const moduleJsonPath = ModuleConfigUtil.moduleJsonPath(moduleDir, env);
static #loadJsonSync(moduleJsonPath: string): ModuleConfig | undefined {
const moduleJsonPathExists = fs.existsSync(moduleJsonPath);
if (!moduleJsonPathExists) {
return;
Expand All @@ -270,8 +296,7 @@ export class ModuleConfigUtil {
return moduleJson.config;
}

private static loadModuleYamlSync(moduleDir: string, env?: string): ModuleConfig | undefined {
const moduleYamlPath = ModuleConfigUtil.moduleYamlPath(moduleDir, env);
static #loadYamlSync(moduleYamlPath: string): ModuleConfig | undefined {
const moduleYamlPathExists = fs.existsSync(moduleYamlPath);
if (!moduleYamlPathExists) {
return;
Expand Down
24 changes: 23 additions & 1 deletion core/common-util/test/ModuleConfig.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import assert from 'node:assert';
import { strict as assert } from 'node:assert';
import path from 'node:path';
import { ModuleConfigUtil } from '../src/ModuleConfig';

describe('test/ModuleConfig.test.ts', () => {
describe('load yaml config', () => {
afterEach(() => {
ModuleConfigUtil.setConfigNames(undefined);
});

it('should work', () => {
const config = ModuleConfigUtil.loadModuleConfigSync(path.join(__dirname, './fixtures/modules/foo-yaml'));
assert.deepStrictEqual(config, { mysql: { host: '127.0.0.1' } });
Expand All @@ -13,6 +17,24 @@ describe('test/ModuleConfig.test.ts', () => {
const config = ModuleConfigUtil.loadModuleConfigSync(path.join(__dirname, './fixtures/modules/dev-module-config'), undefined, 'dev');
assert.deepStrictEqual(config, { mysql: { host: '127.0.0.1', port: 11306 } });
});

it('should load with configNames', async () => {
ModuleConfigUtil.setConfigNames([ 'module.default', 'module.dev' ]);
const config = await ModuleConfigUtil.loadModuleConfig(path.join(__dirname, './fixtures/modules/dev-module-config'));
const configSync = ModuleConfigUtil.loadModuleConfigSync(path.join(__dirname, './fixtures/modules/dev-module-config'));
assert.deepStrictEqual(config, { mysql: { host: '127.0.0.1', port: 11306 } });
assert.deepStrictEqual(configSync, { mysql: { host: '127.0.0.1', port: 11306 } });
});

// it('should throw error without initialization', async () => {
// await assert.rejects(async () => {
// await ModuleConfigUtil.loadModuleConfig(path.join(__dirname, './fixtures/modules/dev-module-config'));
// }, /should setConfigNames before load module config/);
//
// assert.throws(() => {
// ModuleConfigUtil.loadModuleConfigSync(path.join(__dirname, './fixtures/modules/dev-module-config'));
// }, /should setConfigNames before load module config/);
// });
});

describe('load module reference', () => {
Expand Down
16 changes: 12 additions & 4 deletions plugin/config/app.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Application } from 'egg';
import { ModuleConfigUtil, ModuleReference } from '@eggjs/tegg-common-util';
import type { Application, IBoot } from 'egg';
import { ModuleConfigUtil } from '@eggjs/tegg-common-util';
import type { ModuleReference } from '@eggjs/tegg-common-util';
import { ModuleScanner } from './lib/ModuleScanner';

export default class App {
export default class App implements IBoot {
private readonly app: Application;

constructor(app: Application) {
this.app = app;
const configNames = this.app.loader.getTypeFiles('module');
ModuleConfigUtil.setConfigNames(configNames);
}

configWillLoad() {
Expand All @@ -15,6 +18,7 @@ export default class App {
this.app.moduleReferences = moduleScanner.loadModuleReferences();

this.app.moduleConfigs = {};

for (const reference of this.app.moduleReferences) {
const absoluteRef: ModuleReference = {
path: ModuleConfigUtil.resolveModuleDir(reference.path, this.app.baseDir),
Expand All @@ -26,8 +30,12 @@ export default class App {
this.app.moduleConfigs[moduleName] = {
name: moduleName,
reference: absoluteRef,
config: ModuleConfigUtil.loadModuleConfigSync(absoluteRef.path, undefined, this.app.config.env) || {},
config: ModuleConfigUtil.loadModuleConfigSync(absoluteRef.path),
};
}
}

async beforeClose() {
ModuleConfigUtil.setConfigNames(undefined);
}
}
18 changes: 14 additions & 4 deletions standalone/standalone/src/Runner.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { ModuleConfigUtil, ModuleReference, ReadModuleReferenceOptions, RuntimeConfig } from '@eggjs/tegg-common-util';
import {
EggPrototype, EggPrototypeLifecycleUtil,
EggPrototype,
EggPrototypeLifecycleUtil,
LoadUnit,
LoadUnitFactory,
LoadUnitLifecycleUtil, LoadUnitMultiInstanceProtoHook,
LoadUnitLifecycleUtil,
LoadUnitMultiInstanceProtoHook,
} from '@eggjs/tegg-metadata';
import {
ContextHandler,
EggContainerFactory, EggContext, EggObjectLifecycleUtil,
EggContainerFactory,
EggContext,
EggObjectLifecycleUtil,
LoadUnitInstance,
LoadUnitInstanceFactory,
ModuleLoadUnitInstance,
Expand Down Expand Up @@ -104,6 +108,10 @@ export class Runner {
obj: runtimeConfig,
}];

// load module.yml and module.env.yml by default
if (!ModuleConfigUtil.configNames) {
ModuleConfigUtil.configNames = [ 'module.default', `module.${this.env}` ];
}
for (const reference of this.moduleReferences) {
const absoluteRef = {
path: ModuleConfigUtil.resolveModuleDir(reference.path, this.cwd),
Expand All @@ -114,7 +122,7 @@ export class Runner {
this.moduleConfigs[moduleName] = {
name: moduleName,
reference: absoluteRef,
config: ModuleConfigUtil.loadModuleConfigSync(absoluteRef.path, undefined, this.env) || {},
config: ModuleConfigUtil.loadModuleConfigSync(absoluteRef.path),
};
}
for (const moduleConfig of Object.values(this.moduleConfigs)) {
Expand Down Expand Up @@ -267,5 +275,7 @@ export class Runner {
MysqlDataSourceManager.instance.clear();
SqlMapManager.instance.clear();
TableModelManager.instance.clear();
// clear configNames
ModuleConfigUtil.setConfigNames(undefined);
}
}

0 comments on commit e0656a4

Please sign in to comment.