/
pluginConfig.ts
129 lines (117 loc) · 4.86 KB
/
pluginConfig.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
119
120
121
122
123
124
125
126
127
128
129
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable no-prototype-builtins */
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable no-case-declarations */
// tslint:disable: no-shadowed-variable
import { Serializable } from 'puppeteer';
import { logError, yellow } from '../utils/log';
import { PluginFunction, PluginTypes } from './Plugin.interfaces';
import { accessPluginDirectly, configData, plugins, pluginTypes, routeProcessPriority } from './pluginRepository';
export const backupData = configData + 'BackupData__';
export const routeConfigData = configData + 'Route_Config_Data__';
export const resetConfig = configData + 'resetData__';
interface SetPluginConfig {
<T>(name: string | symbol, configData: T): void;
<T>(name: string | symbol, type: PluginTypes, configData: T): void;
(name: string | symbol, configData: Serializable): void;
(name: string | symbol, type: PluginTypes, configData: Serializable): void;
}
export const setPluginConfig: SetPluginConfig = <T>(
name: string,
typeOrConfig: PluginTypes | Serializable | T,
config?: Serializable | T
): void => {
let type: PluginTypes;
// tslint:disable-next-line: no-angle-bracket-type-assertion
if ((typeof typeOrConfig === 'string' || typeof typeOrConfig === 'symbol') && pluginTypes.includes(<any>typeOrConfig)) {
type = (typeOrConfig as unknown) as PluginTypes;
} else {
config = (typeOrConfig as unknown) as Serializable;
}
const plugin = findPlugin(name, type);
setConfig<T>(plugin, config);
};
export const getPluginConfig = <T>(name: string | symbol, type?: PluginTypes): T => {
const plugin = findPlugin(name, type);
return getConfig(plugin) as T;
};
export function fetchPlugins(name: string | symbol, type?: PluginTypes): Function[] {
/** fix for people still caliing utility functions with render type */
type = type === 'render' ? 'postProcessByHtml' : type;
const result = Object.entries(plugins)
/** filter out deprecated render name */
.filter(([type]) => type !== 'render')
/** only catch the type that is given, or all */
.filter(([ofType]) => (!type ? true : ofType === type))
.map(([_, typedPlugins]) => typedPlugins[name])
.filter(Boolean);
return result;
}
export function findPlugin(name: string | symbol, type?: PluginTypes, errorOnNotfound = true): PluginFunction {
const found = fetchPlugins(name, type);
const displayName = typeof name === 'string' ? name : name.description;
switch (found.length) {
case 0:
if (errorOnNotfound) {
logError(`Plugin "${yellow(displayName)}" of type "${yellow(type)}" is not found, can not store config`);
process.exit(15);
}
return undefined;
break;
case 1:
return found[0] as PluginFunction;
default:
if (errorOnNotfound) {
logError(`Plugin "${yellow(displayName)}" has multiple types, please specify type to be able to store config`);
process.exit(15);
}
return undefined;
}
}
export function hasPlugin(name: string | symbol, type?: PluginTypes): boolean {
return fetchPlugins(name, type).length === 1;
}
export const getConfig = <T>(plugin: any): T => {
const target = plugin.hasOwnProperty(accessPluginDirectly) ? plugin[accessPluginDirectly] : plugin;
return target[configData] || ({} as T);
};
export const setConfig = <T>(plugin: any, config: Serializable | T): void => {
const target = plugin.hasOwnProperty(accessPluginDirectly) ? plugin[accessPluginDirectly] : plugin;
target[configData] = Object.assign({}, target[configData] || {}, config);
target[backupData] = { ...target[configData] };
};
/**
* @param type
* @param name
* @param config
*/
export const routePluginConfig = (
route: string,
name: string,
typeOrConfig: PluginTypes | Serializable,
config?: Serializable
): void => {
let type: PluginTypes;
// tslint:disable-next-line: no-angle-bracket-type-assertion
if ((typeof typeOrConfig === 'string' || typeof typeOrConfig === 'symbol') && pluginTypes.includes(<any>typeOrConfig)) {
type = (typeOrConfig as unknown) as PluginTypes;
} else {
config = (typeOrConfig as unknown) as Serializable;
}
const plugin = findPlugin(name, type);
plugin[routeConfigData] = plugin[routeConfigData] || {};
plugin[routeConfigData][route] = Object.assign({}, plugin[configData] || {}, config);
plugin[resetConfig] = () => {
plugin[configData] = plugin[backupData];
};
};
export const setPluginPriority = (name: string | symbol, priority: number) => {
const plugin = findPlugin(name, 'routeProcess', false);
if (plugin === undefined) {
const displayName = typeof name === 'string' ? name : name.description;
logError(`Plugin "${yellow(displayName)}" of type "routeProcess" is not found, its priority cannot be changed`);
process.exit(15);
}
plugin[routeProcessPriority] = priority;
};