forked from JeremyHeleine/Photo-Sphere-Viewer
-
-
Notifications
You must be signed in to change notification settings - Fork 630
/
AbstractPlugin.ts
126 lines (109 loc) · 3.73 KB
/
AbstractPlugin.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
import { TypedEvent, TypedEventTarget } from '../lib/TypedEventTarget';
import { checkVersion, ConfigParser, logWarn } from '../utils';
import type { Viewer } from '../Viewer';
/**
* Base class for plugins
* @template TEvents union of dispatched events
*/
export abstract class AbstractPlugin<
TEvents extends TypedEvent<AbstractPlugin> = never
> extends TypedEventTarget<TEvents> {
/**
* Unique identifier of the plugin
*/
static readonly id: string;
/**
* Expected version of the core
* DO NOT USE on custom plugins
*/
static readonly VERSION: string;
constructor(protected viewer: Viewer) {
super();
}
/**
* Initializes the plugin
*/
// eslint-disable-next-line @typescript-eslint/no-empty-function
init(): void {}
/**
* Destroys the plugin
*/
// eslint-disable-next-line @typescript-eslint/no-empty-function
destroy(): void {}
}
/**
* Base class for plugins with updatable configuration
* The implementation must have a static `configParser` property which is the result of {@link utils.getConfigParser}
*
* @template TConfig type of input config
* @template TParsedConfig type of config after parsing
* @template TUpdatableConfig type of config that can be updated
* @template TEvents union of dispatched events
*/
export abstract class AbstractConfigurablePlugin<
TConfig extends Record<string, any>,
TParsedConfig extends TConfig = TConfig,
TUpdatableConfig extends TConfig = TConfig,
TEvents extends TypedEvent<AbstractPlugin> = never
> extends AbstractPlugin<TEvents> {
static configParser: ConfigParser<any, any>;
static readonlyOptions: string[] = [];
readonly config: TParsedConfig;
constructor(viewer: Viewer, config: TConfig) {
super(viewer);
this.config = (this.constructor as typeof AbstractConfigurablePlugin).configParser(config) as TParsedConfig;
}
/**
* Update options
*/
setOption<T extends keyof TUpdatableConfig>(option: T, value: TUpdatableConfig[T]) {
// @ts-ignore
this.setOptions({ [option]: value });
}
/**
* Update options
*/
setOptions(options: Partial<TUpdatableConfig>) {
const rawConfig: TConfig = {
...this.config,
...options,
};
const ctor = this.constructor as typeof AbstractConfigurablePlugin;
const parser: ConfigParser<TConfig, TParsedConfig> = ctor.configParser as any;
const readonly = ctor.readonlyOptions;
const id = ctor.id;
for (let [key, value] of Object.entries(options) as Array<[keyof TConfig, any]>) {
if (!(key in parser.defaults)) {
logWarn(`${id}: Unknown option "${key as string}"`);
continue;
}
if (readonly.includes(key as string)) {
logWarn(`${id}: Option "${key as string}" cannot be updated`);
continue;
}
if (key in parser.parsers) {
value = parser.parsers[key](value, {
rawConfig: rawConfig,
defValue: parser.defaults[key],
});
}
this.config[key] = value;
}
}
}
export type PluginConstructor = new (viewer: Viewer, config?: any) => AbstractPlugin<any>;
/**
* Returns the plugin constructor from the imported object
* @internal
*/
export function pluginInterop(plugin: any): PluginConstructor & typeof AbstractPlugin {
if (plugin) {
for (const [, p] of [['_', plugin], ...Object.entries(plugin)]) {
if (p.prototype instanceof AbstractPlugin) {
checkVersion(p.id, p.VERSION, PKG_VERSION);
return p;
}
}
}
return null;
}