Skip to content

Commit

Permalink
Merge pull request #52 from micalevisk/refactor-with-minor-perf-improv
Browse files Browse the repository at this point in the history
refactor: minor perf improvements and typing changes
  • Loading branch information
jmcdo29 authored Oct 12, 2023
2 parents b8cf461 + a059a4e commit edbc834
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 50 deletions.
5 changes: 5 additions & 0 deletions .changeset/witty-turkeys-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'nestjs-spelunker': minor
---

refactor: minor perf improvements and typing changes
8 changes: 6 additions & 2 deletions nest-cli.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "test"
}
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"preversion": "yarn format && yarn lint && yarn build",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
"commit": "git-cz",
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"lint": "eslint '{src,test}/**/*.ts' --fix",
Expand Down Expand Up @@ -51,7 +50,6 @@
"lint-staged": "^12.3.7",
"prettier": "^2.6.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.5.5",
"ts-node": "^10.9.1",
"typescript": "^4.6.2",
Expand Down
3 changes: 0 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/debug.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ export class DebugModule {
}
const selfDeps =
(Reflect.getMetadata(SELF_DECLARED_DEPS_METADATA, classObj) as [
// eslint-disable-next-line @typescript-eslint/ban-types
{ index: number; param: string | { forwardRef: () => Function } },
]) || [];
for (const selfDep of selfDeps) {
Expand Down
73 changes: 41 additions & 32 deletions src/exploration.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export class ExplorationModule {
);
};

// NOTE: Using 'forEach' here instead of filter+map for performance reasons.
// NOTE: Using for..of here instead of filter+map for performance reasons.
const dependencyMap: SpelunkedTree[] = [];
modulesArray.forEach((nestjsModule) => {
for (const nestjsModule of modulesArray) {
if (shouldIncludeModule(nestjsModule)) {
dependencyMap.push({
name: nestjsModule.metatype.name,
Expand All @@ -50,36 +50,41 @@ export class ExplorationModule {
exports: this.getExports(nestjsModule),
});
}
});
}
return dependencyMap;
}

private static getImports(module: NestModule): string[] {
return Array.from(module.imports)
.filter((module) => module.metatype.name !== InternalCoreModule.name)
.map((module) => module.metatype.name);
// NOTE: Using for..of here instead of filter+map for performance reasons.
const importsNames: string[] = [];
for (const importedModule of module.imports.values()) {
if (importedModule.metatype.name !== InternalCoreModule.name) {
importsNames.push(importedModule.metatype.name);
}
}
return importsNames;
}

private static getProviders(module: NestModule): any {
const providerList: Record<
string,
{ method: string; injections?: string[] }
> = {};
const providerNames = Array.from(module.providers.keys()).filter(
(provider) =>
provider !== module.metatype &&
provider !== ModuleRef &&
provider !== ApplicationConfig,
);
providerNames.map((prov) => {
const providerToken = this.getInjectionToken(prov);
const provider = module.providers.get(prov);
if (provider === undefined) {
private static getProviders(module: NestModule): SpelunkedTree['providers'] {
const providerList: SpelunkedTree['providers'] = {};
// NOTE: Using for..of here instead of filter+forEach for performance reasons.
for (const provider of module.providers.keys()) {
if (
provider === module.metatype ||
provider === ModuleRef ||
provider === ApplicationConfig
) {
continue;
}

const providerToken = this.getInjectionToken(provider);
const providerInstanceWrapper = module.providers.get(provider);
if (providerInstanceWrapper === undefined) {
throw new Error(UndefinedProvider(providerToken));
}
const metatype = provider.metatype;
const metatype = providerInstanceWrapper.metatype;
const name = (metatype && metatype.name) || 'useValue';
let provided: { method: string; injections?: string[] };
let provided: SpelunkedTree['providers'][number];
switch (name) {
case 'useValue':
provided = {
Expand All @@ -94,7 +99,7 @@ export class ExplorationModule {
case 'useFactory':
provided = {
method: 'factory',
injections: provider.inject?.map((injection) =>
injections: providerInstanceWrapper.inject?.map((injection) =>
this.getInjectionToken(injection),
),
};
Expand All @@ -105,20 +110,24 @@ export class ExplorationModule {
};
}
providerList[providerToken] = provided;
});
}
return providerList;
}

private static getControllers(module: NestModule): string[] {
return Array.from(module.controllers.values()).map(
(controller) => controller.metatype.name,
);
const controllersNames: string[] = [];
for (const controller of module.controllers.values()) {
controllersNames.push(controller.metatype.name);
}
return controllersNames;
}

private static getExports(module: NestModule): string[] {
return Array.from(module.exports).map((exportValue) =>
this.getInjectionToken(exportValue),
);
const exportsNames: string[] = [];
for (const exportValue of module.exports.values()) {
exportsNames.push(this.getInjectionToken(exportValue));
}
return exportsNames;
}

private static getInjectionToken(
Expand All @@ -134,6 +143,6 @@ export class ExplorationModule {
private static tokenIsOptionalToken(
token: InjectionToken | OptionalFactoryDependency,
): token is OptionalFactoryDependency {
return Object.keys(token).includes('token');
return !!(token as any)['token'];
}
}
22 changes: 14 additions & 8 deletions src/graphing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ export class GraphingModule {
new Map<string, SpelunkedNode>(),
);

nodeMap.forEach((node) => this.findDependencies(node, nodeMap));
for (const [, node] of nodeMap) {
this.findDependencies(node, nodeMap);
}

return this.findRoot(nodeMap);
}
Expand Down Expand Up @@ -58,16 +60,20 @@ export class GraphingModule {
root: SpelunkedNode,
visitedNodes: Set<SpelunkedNode> = new Set(),
): Set<SpelunkedEdge> {
const set = new Set<SpelunkedEdge>();

// short-circuit cycles
if (visitedNodes.has(root)) return new Set();
if (visitedNodes.has(root)) return set;

visitedNodes.add(root);

return [...root.dependencies.values()].reduce((set, n) => {
set.add({ from: root, to: n });
this.getEdgesRecursively(n, visitedNodes).forEach((e) => set.add(e));

return set;
}, new Set<SpelunkedEdge>());
for (const node of root.dependencies) {
set.add({ from: root, to: node });
const edges = this.getEdgesRecursively(node, visitedNodes);
for (const edge of edges) {
set.add(edge);
}
}
return set;
}
}
5 changes: 2 additions & 3 deletions test/large-app/app.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ import {
} from '../fixtures/output';
import { AppModule } from './app.module';

export const SpelunkerSuite = suite<{ app: INestApplication }>(
'SpelunkerSuite',
);
export const SpelunkerSuite =
suite<{ app: INestApplication }>('SpelunkerSuite');

SpelunkerSuite.before(async (context) => {
context.app = await NestFactory.create(AppModule, { logger: false });
Expand Down

0 comments on commit edbc834

Please sign in to comment.