Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
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
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"get-ready": "catalog:",
"globby": "catalog:",
"is-type-of": "catalog:",
"multimatch": "catalog:",
"node-homedir": "catalog:",
"performance-ms": "catalog:",
"ready-callback": "catalog:",
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/egg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { ReadyFunctionArg } from 'get-ready';
import { BaseContextClass } from './base_context_class.ts';
import { Lifecycle } from './lifecycle.ts';
import { EggLoader } from './loader/egg_loader.ts';
import type { LoaderFS } from './loader/loader_fs.ts';
import { Singleton, type SingletonCreateMethod, type SingletonOptions } from './singleton.ts';
import type { EggAppConfig } from './types.ts';
import utils, { type Fun } from './utils/index.ts';
Expand All @@ -33,6 +34,8 @@ export interface EggCoreOptions {
env?: string;
/** Skip lifecycle hooks, only trigger loadMetadata for manifest generation */
metadataOnly?: boolean;
/** Loader-facing filesystem abstraction */
loaderFS?: LoaderFS;
/**
* When true, lifecycle stops after the `configWillLoad` phase.
* `configDidLoad`, `didLoad`, `willReady`, `didReady`, and `serverDidReady`
Expand Down Expand Up @@ -230,6 +233,7 @@ export class EggCore extends KoaApplication {
env: options.env ?? '',
EggCoreClass: EggCore,
metadataOnly: options.metadataOnly,
loaderFS: options.loaderFS,
});
}

Expand Down
32 changes: 26 additions & 6 deletions packages/core/src/loader/egg_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { isAsyncFunction, isClass, isGeneratorFunction, isObject, isPromise } fr
import { homedir } from 'node-homedir';
import { now, diff } from 'performance-ms';
import { register as tsconfigPathsRegister } from 'tsconfig-paths';
import { getParamNames, readJSONSync, readJSON, exists } from 'utility';
import { getParamNames, readJSONSync } from 'utility';

import type { BaseContextClass } from '../base_context_class.ts';
import type { Context, EggCore, MiddlewareFunc } from '../egg.ts';
Expand All @@ -24,7 +24,7 @@ import { sequencify } from '../utils/sequencify.ts';
import { Timing } from '../utils/timing.ts';
import { type ContextLoaderOptions, ContextLoader } from './context_loader.ts';
import { type FileLoaderOptions, CaseStyle, FULLPATH, FileLoader } from './file_loader.ts';
import { RealLoaderFS, type LoaderFS } from './loader_fs.ts';
import { ManifestLoaderFS, RealLoaderFS, type LoaderFS } from './loader_fs.ts';
import { ManifestStore, type StartupManifest } from './manifest.ts';

const debug = debuglog('egg/core/loader/egg_loader');
Expand Down Expand Up @@ -95,7 +95,10 @@ export class EggLoader {
*/
constructor(options: EggLoaderOptions) {
this.options = options;
this.loaderFS = this.options.loaderFS ?? new RealLoaderFS();
const bundleStore = ManifestStore.getBundleStore();
this.loaderFS =
this.options.loaderFS ??
(bundleStore?.baseDir === this.options.baseDir ? new ManifestLoaderFS(bundleStore) : new RealLoaderFS());
assert(fs.existsSync(this.options.baseDir), `${this.options.baseDir} not exists`);
assert(this.options.app, 'options.app is required');
assert(this.options.logger, 'options.logger is required');
Expand Down Expand Up @@ -176,6 +179,9 @@ export class EggLoader {
this.manifest =
ManifestStore.load(this.options.baseDir, this.serverEnv, this.serverScope) ??
ManifestStore.createCollector(this.options.baseDir);
if (!this.options.loaderFS && !(this.loaderFS instanceof ManifestLoaderFS)) {
this.loaderFS = new ManifestLoaderFS(this.manifest, this.loaderFS);
}
}

get app(): EggCore {
Expand Down Expand Up @@ -644,8 +650,8 @@ export class EggLoader {
let pkg: any;
let eggPluginConfig: any;
const pluginPackage = path.join(plugin.path as string, 'package.json');
if (await utils.existsPath(pluginPackage)) {
pkg = await readJSON(pluginPackage);
if (this.loaderFS.exists(pluginPackage)) {
pkg = this.loaderFS.readJSON(pluginPackage);
eggPluginConfig = pkg.eggPlugin;
if (pkg.version) {
plugin.version = pkg.version;
Expand Down Expand Up @@ -848,7 +854,7 @@ export class EggLoader {
} else if (exports.require) {
realPluginPath = path.join(pluginPath, exports.require);
}
if (exports.typescript && isSupportTypeScript() && !(await exists(realPluginPath))) {
if (exports.typescript && isSupportTypeScript() && !this.loaderFS.exists(realPluginPath)) {
// if require/import path not exists, use typescript path for development stage
realPluginPath = path.join(pluginPath, exports.typescript);
debug('[formatPluginPathFromPackageJSON] use typescript path %o', realPluginPath);
Expand Down Expand Up @@ -1796,6 +1802,7 @@ export class EggLoader {
*/
#collectConventionalDynamicFiles(manifest: StartupManifest): void {
for (const unit of this.getLoadUnits()) {
this.#collectConventionFile(manifest, path.join(unit.path, 'package.json'));
for (const load of CONVENTIONAL_MANIFEST_LOADS) {
const target = path.join(unit.path, ...load.path);
if (load.type === 'resolve') {
Expand Down Expand Up @@ -1838,6 +1845,19 @@ export class EggLoader {
return manifest.fileDiscovery[dirKey];
}

#collectConventionFile(manifest: StartupManifest, filepath: string): void {
const fileKey = this.#toManifestRel(filepath);
if (Object.values(manifest.resolveCache).includes(fileKey)) return;
Comment thread
killagu marked this conversation as resolved.
Outdated
if (!fs.existsSync(filepath) || !fs.statSync(filepath).isFile()) return;

const dirKey = this.#toManifestRel(path.dirname(filepath));
const basename = path.basename(filepath);
const files = manifest.fileDiscovery[dirKey] ?? [];
if (!files.includes(basename)) {
manifest.fileDiscovery[dirKey] = [...files, basename].sort();
}
}

#toManifestRel(filepath: string): string {
const rel = path.isAbsolute(filepath) ? path.relative(this.options.baseDir, filepath) : filepath;
return rel.replaceAll(path.sep, '/');
Expand Down
Loading
Loading