/
plugin-explorer.service.ts
118 lines (103 loc) · 3.58 KB
/
plugin-explorer.service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { ModulesContainer } from '@nestjs/core';
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
import { Injectable } from '@nestjs/common';
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
import { Plugin } from 'postgraphile';
import {makePluginByCombiningPlugins } from 'graphile-utils';
import {
PLUGIN_TYPE_METADATA,
PLUGIN_DETAILS_METADATA,
} from '../postgraphile.constants';
import { PluginType } from '../enums/plugin-type.enum';
import { BaseExplorerService } from './base-explorer.service';
import { ExtendSchemaOptions } from '../interfaces/extend-schema-options.interface';
import { PluginFactory } from '../factories/plugin.factory';
/**
* Explorer service handles creating plugins from all plugin metadata set in providers (Excluding
* SchemaType providers, as there is a separate explorer service that handles them)
*/
@Injectable()
export class PluginExplorerService extends BaseExplorerService {
constructor(
modulesContainer: ModulesContainer,
private readonly metadataScanner: MetadataScanner,
) {
super(modulesContainer);
}
/**
* Returns a plugin combining all the plugins found from all module's providers
*/
public getCombinedPlugin() {
const modules = this.getModules();
const plugins: Plugin[] = this.evaluateModules(modules, instance =>
this.filterAttachPlugins(instance),
);
return makePluginByCombiningPlugins(...plugins);
}
/**
* Returns a list of all the plugins created from all provider's method metadata set by the decorators
*/
protected filterAttachPlugins(wrapper: InstanceWrapper) {
const { instance } = wrapper;
if (!instance) {
return undefined;
}
const prototype = Object.getPrototypeOf(instance);
const plugins = this.metadataScanner.scanFromPrototype(
instance,
prototype,
methodName => this.extractPlugin(instance, prototype, methodName),
);
return plugins;
}
/**
* Extracts the plugin based on the metadata set on the method
*/
protected extractPlugin(instance: any, prototype: any, methodName: string) {
const callback = prototype[methodName];
const pluginType = Reflect.getMetadata(
PLUGIN_TYPE_METADATA,
callback,
) as PluginType;
if (pluginType) {
return this.createPlugin(pluginType, instance, prototype, methodName);
} else {
return undefined;
}
}
createPlugin(pluginType: PluginType, instance: any, prototype: any, methodName: string) {
const callback = prototype[methodName];
// tslint:disable-next-line: ban-types
const method = (instance[methodName] as Function).bind(instance);
switch (pluginType) {
case PluginType.ADD_INFLECTORS:
const { inflector, overwriteExisting } = Reflect.getMetadata(
PLUGIN_DETAILS_METADATA,
callback,
);
return PluginFactory.createAddInflectorsPlugin(inflector, method, overwriteExisting);
case PluginType.PROCESS_SCHEMA:
return PluginFactory.createProcessSchemaPlugin(method);
case PluginType.EXTEND_SCHEMA:
const {
additionalGraphql,
fieldName,
fieldType,
typeName,
} = Reflect.getMetadata(
PLUGIN_DETAILS_METADATA,
callback,
) as ExtendSchemaOptions;
return PluginFactory.createExtendSchemaPlugin(
typeName,
fieldName,
fieldType,
// tslint:disable-next-line:ban-types
(instance[methodName] as Function).bind(instance),
additionalGraphql,
);
default:
return undefined;
}
}
}