Skip to content

Commit

Permalink
feat(core): add support for partial graphs
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmysliwiec committed Mar 15, 2023
1 parent a61bcd3 commit a064e6d
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 11 deletions.
3 changes: 2 additions & 1 deletion integration/inspector/e2e/fixtures/post-init-graph.json
Original file line number Diff line number Diff line change
Expand Up @@ -3166,5 +3166,6 @@
"nodeId": "-2007711503"
}
]
}
},
"status": "complete"
}
3 changes: 2 additions & 1 deletion integration/inspector/e2e/fixtures/pre-init-graph.json
Original file line number Diff line number Diff line change
Expand Up @@ -2624,5 +2624,6 @@
"nodeId": "-2007711503"
}
]
}
},
"status": "complete"
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { InjectorDependencyContext } from '../../injector/injector';
import { Module } from '../../injector/module';
import { UNKNOWN_DEPENDENCIES_MESSAGE } from '../messages';
import { RuntimeException } from './runtime.exception';
import { Module } from '../../injector/module';

export class UnknownDependenciesException extends RuntimeException {
constructor(
type: string | symbol,
unknownDependencyContext: InjectorDependencyContext,
module?: Module,
public readonly type: string | symbol,
public readonly context: InjectorDependencyContext,
public readonly moduleRef?: Module,
public readonly metadata?: { id: string },
) {
super(UNKNOWN_DEPENDENCIES_MESSAGE(type, unknownDependencyContext, module));
super(UNKNOWN_DEPENDENCIES_MESSAGE(type, context, moduleRef));
}
}
2 changes: 2 additions & 0 deletions packages/core/injector/injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ export class Injector {
wrapper.name,
dependencyContext,
moduleRef,
{ id: wrapper.id },
);
}
if (providers.has(name)) {
Expand Down Expand Up @@ -547,6 +548,7 @@ export class Injector {
wrapper.name,
dependencyContext,
moduleRef,
{ id: wrapper.id },
);
}
return instanceWrapper;
Expand Down
9 changes: 7 additions & 2 deletions packages/core/injector/instance-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ export class InstanceLoader<TInjector extends Injector = Injector> {
) {
this.createPrototypes(modules);

await this.createInstances(modules);

try {
await this.createInstances(modules);
} catch (err) {
this.graphInspector.inspectModules(modules);
this.graphInspector.registerPartial(err);
throw err;
}
this.graphInspector.inspectModules(modules);
}

Expand Down
25 changes: 25 additions & 0 deletions packages/core/inspector/graph-inspector.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { UnknownDependenciesException } from '../errors/exceptions/unknown-dependencies.exception';
import { NestContainer } from '../injector/container';
import { InstanceWrapper } from '../injector/instance-wrapper';
import { Module } from '../injector/module';
Expand All @@ -6,6 +7,7 @@ import { EnhancerMetadataCacheEntry } from './interfaces/enhancer-metadata-cache
import { Entrypoint } from './interfaces/entrypoint.interface';
import { OrphanedEnhancerDefinition } from './interfaces/extras.interface';
import { ClassNode, Node } from './interfaces/node.interface';
import { PartialGraphHost } from './partial-graph.host';
import { SerializedGraph } from './serialized-graph';

export class GraphInspector {
Expand Down Expand Up @@ -33,6 +35,29 @@ export class GraphInspector {
DeterministicUuidRegistry.clear();
}

public registerPartial(error: unknown) {
this.graph.status = 'partial';

if (error instanceof UnknownDependenciesException) {
this.graph.metadata = {
cause: {
type: 'unknown-dependencies',
context: error.context,
moduleId: error.moduleRef?.id,
nodeId: error.metadata?.id,
},
};
} else {
this.graph.metadata = {
cause: {
type: 'unknown',
error,
},
};
}
PartialGraphHost.register(this.graph);
}

public inspectInstanceWrapper<T = any>(
source: InstanceWrapper<T>,
moduleRef: Module,
Expand Down
2 changes: 2 additions & 0 deletions packages/core/inspector/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './graph-inspector';
export * from './initialize-on-preview.allowlist';
export * from './partial-graph.host';
export * from './serialized-graph';
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { SerializedGraphStatus } from '../serialized-graph';
import { Edge } from './edge.interface';
import { Entrypoint } from './entrypoint.interface';
import { Extras } from './extras.interface';
import { Node } from './node.interface';
import { SerializedGraphMetadata } from './serialized-graph-metadata.interface';

export interface SerializedGraphJson {
nodes: Record<string, Node>;
edges: Record<string, Edge>;
entrypoints: Record<string, Entrypoint<unknown>[]>;
extras: Extras;
status?: SerializedGraphStatus;
metadata?: SerializedGraphMetadata;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { InjectorDependencyContext } from '../../injector/injector';

export interface SerializedGraphMetadata {
cause: {
type: 'unknown-dependencies' | 'unknown';
context?: InjectorDependencyContext;
moduleId?: string;
nodeId?: string;
error?: any;
};
}
17 changes: 17 additions & 0 deletions packages/core/inspector/partial-graph.host.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { SerializedGraph } from './serialized-graph';

export class PartialGraphHost {
private static partialGraph: SerializedGraph;

static toJSON() {
return this.partialGraph?.toJSON();
}

static toString() {
return this.partialGraph?.toString();
}

static register(partialGraph: SerializedGraph) {
this.partialGraph = partialGraph;
}
}
25 changes: 23 additions & 2 deletions packages/core/inspector/serialized-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import {
OrphanedEnhancerDefinition,
} from './interfaces/extras.interface';
import { Node } from './interfaces/node.interface';
import { SerializedGraphJson } from './interfaces/serialized-graph-json.interface';
import { SerializedGraphMetadata } from './interfaces/serialized-graph-metadata.interface';

export type SerializedGraphStatus = 'partial' | 'complete';
type WithOptionalId<T extends Record<'id', string>> = Omit<T, 'id'> &
Partial<Pick<T, 'id'>>;

Expand All @@ -28,6 +31,8 @@ export class SerializedGraph {
orphanedEnhancers: [],
attachedEnhancers: [],
};
private _status: SerializedGraphStatus = 'complete';
private _metadata?: SerializedGraphMetadata;

private static readonly INTERNAL_PROVIDERS: Array<InjectionToken> = [
ApplicationConfig,
Expand All @@ -44,6 +49,14 @@ export class SerializedGraph {
INQUIRER,
];

set status(status: SerializedGraphStatus) {
this._status = status;
}

set metadata(metadata: SerializedGraphMetadata) {
this._metadata = metadata;
}

public insertNode(nodeDefinition: Node) {
if (
nodeDefinition.metadata.type === 'provider' &&
Expand Down Expand Up @@ -109,13 +122,21 @@ export class SerializedGraph {
return this.nodes.get(id);
}

public toJSON() {
return {
public toJSON(): SerializedGraphJson {
const json: SerializedGraphJson = {
nodes: Object.fromEntries(this.nodes),
edges: Object.fromEntries(this.edges),
entrypoints: Object.fromEntries(this.entrypoints),
extras: this.extras,
};

if (this._status) {
json['status'] = this._status;
}
if (this._metadata) {
json['metadata'] = this._metadata;
}
return json;
}

public toString() {
Expand Down

0 comments on commit a064e6d

Please sign in to comment.