diff options
Diffstat (limited to 'client/src/app/core/plugins/plugin.service.ts')
-rw-r--r-- | client/src/app/core/plugins/plugin.service.ts | 60 |
1 files changed, 32 insertions, 28 deletions
diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts index af330c2eb..14310f093 100644 --- a/client/src/app/core/plugins/plugin.service.ts +++ b/client/src/app/core/plugins/plugin.service.ts | |||
@@ -3,11 +3,13 @@ import { Router } from '@angular/router' | |||
3 | import { ServerConfigPlugin } from '@shared/models' | 3 | import { ServerConfigPlugin } from '@shared/models' |
4 | import { ServerService } from '@app/core/server/server.service' | 4 | import { ServerService } from '@app/core/server/server.service' |
5 | import { ClientScript } from '@shared/models/plugins/plugin-package-json.model' | 5 | import { ClientScript } from '@shared/models/plugins/plugin-package-json.model' |
6 | import { PluginScope } from '@shared/models/plugins/plugin-scope.type' | ||
7 | import { environment } from '../../../environments/environment' | 6 | import { environment } from '../../../environments/environment' |
8 | import { RegisterHookOptions } from '@shared/models/plugins/register-hook.model' | 7 | import { RegisterHookOptions } from '@shared/models/plugins/register-hook.model' |
9 | import { ReplaySubject } from 'rxjs' | 8 | import { ReplaySubject } from 'rxjs' |
10 | import { first, shareReplay } from 'rxjs/operators' | 9 | import { first, shareReplay } from 'rxjs/operators' |
10 | import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks' | ||
11 | import { ClientHook, ClientHookName } from '@shared/models/plugins/client-hook.model' | ||
12 | import { PluginClientScope } from '@shared/models/plugins/plugin-client-scope.type' | ||
11 | 13 | ||
12 | interface HookStructValue extends RegisterHookOptions { | 14 | interface HookStructValue extends RegisterHookOptions { |
13 | plugin: ServerConfigPlugin | 15 | plugin: ServerConfigPlugin |
@@ -21,14 +23,18 @@ type PluginInfo = { | |||
21 | } | 23 | } |
22 | 24 | ||
23 | @Injectable() | 25 | @Injectable() |
24 | export class PluginService { | 26 | export class PluginService implements ClientHook { |
25 | pluginsLoaded = new ReplaySubject<boolean>(1) | 27 | pluginsBuilt = new ReplaySubject<boolean>(1) |
28 | |||
29 | pluginsLoaded: { [ scope in PluginClientScope ]: ReplaySubject<boolean> } = { | ||
30 | common: new ReplaySubject<boolean>(1), | ||
31 | 'video-watch': new ReplaySubject<boolean>(1) | ||
32 | } | ||
26 | 33 | ||
27 | private plugins: ServerConfigPlugin[] = [] | 34 | private plugins: ServerConfigPlugin[] = [] |
28 | private scopes: { [ scopeName: string ]: PluginInfo[] } = {} | 35 | private scopes: { [ scopeName: string ]: PluginInfo[] } = {} |
29 | private loadedPlugins: { [ name: string ]: boolean } = {} | ||
30 | private loadedScripts: { [ script: string ]: boolean } = {} | 36 | private loadedScripts: { [ script: string ]: boolean } = {} |
31 | private loadedScopes: PluginScope[] = [] | 37 | private loadedScopes: PluginClientScope[] = [] |
32 | 38 | ||
33 | private hooks: { [ name: string ]: HookStructValue[] } = {} | 39 | private hooks: { [ name: string ]: HookStructValue[] } = {} |
34 | 40 | ||
@@ -45,12 +51,18 @@ export class PluginService { | |||
45 | 51 | ||
46 | this.buildScopeStruct() | 52 | this.buildScopeStruct() |
47 | 53 | ||
48 | this.pluginsLoaded.next(true) | 54 | this.pluginsBuilt.next(true) |
49 | }) | 55 | }) |
50 | } | 56 | } |
51 | 57 | ||
52 | ensurePluginsAreLoaded () { | 58 | ensurePluginsAreBuilt () { |
53 | return this.pluginsLoaded.asObservable() | 59 | return this.pluginsBuilt.asObservable() |
60 | .pipe(first(), shareReplay()) | ||
61 | .toPromise() | ||
62 | } | ||
63 | |||
64 | ensurePluginsAreLoaded (scope: PluginClientScope) { | ||
65 | return this.pluginsLoaded[scope].asObservable() | ||
54 | .pipe(first(), shareReplay()) | 66 | .pipe(first(), shareReplay()) |
55 | .toPromise() | 67 | .toPromise() |
56 | } | 68 | } |
@@ -90,9 +102,9 @@ export class PluginService { | |||
90 | } | 102 | } |
91 | } | 103 | } |
92 | 104 | ||
93 | async loadPluginsByScope (scope: PluginScope, isReload = false) { | 105 | async loadPluginsByScope (scope: PluginClientScope, isReload = false) { |
94 | try { | 106 | try { |
95 | await this.ensurePluginsAreLoaded() | 107 | await this.ensurePluginsAreBuilt() |
96 | 108 | ||
97 | if (!isReload) this.loadedScopes.push(scope) | 109 | if (!isReload) this.loadedScopes.push(scope) |
98 | 110 | ||
@@ -111,32 +123,24 @@ export class PluginService { | |||
111 | } | 123 | } |
112 | 124 | ||
113 | await Promise.all(promises) | 125 | await Promise.all(promises) |
126 | |||
127 | this.pluginsLoaded[scope].next(true) | ||
114 | } catch (err) { | 128 | } catch (err) { |
115 | console.error('Cannot load plugins by scope %s.', scope, err) | 129 | console.error('Cannot load plugins by scope %s.', scope, err) |
116 | } | 130 | } |
117 | } | 131 | } |
118 | 132 | ||
119 | async runHook (hookName: string, param?: any) { | 133 | async runHook <T> (hookName: ClientHookName, result?: T, params?: any): Promise<T> { |
120 | let result = param | 134 | if (!this.hooks[hookName]) return Promise.resolve(result) |
121 | |||
122 | if (!this.hooks[hookName]) return result | ||
123 | 135 | ||
124 | const wait = hookName.startsWith('static:') | 136 | const hookType = getHookType(hookName) |
125 | 137 | ||
126 | for (const hook of this.hooks[hookName]) { | 138 | for (const hook of this.hooks[hookName]) { |
127 | try { | 139 | console.log('Running hook %s of plugin %s.', hookName, hook.plugin.name) |
128 | const p = hook.handler(param) | 140 | |
129 | 141 | result = await internalRunHook(hook.handler, hookType, result, params, err => { | |
130 | if (wait) { | 142 | console.error('Cannot run hook %s of script %s of plugin %s.', hookName, hook.clientScript.script, hook.plugin.name, err) |
131 | result = await p | 143 | }) |
132 | } else if (p.catch) { | ||
133 | p.catch((err: Error) => { | ||
134 | console.error('Cannot run hook %s of script %s of plugin %s.', hookName, hook.plugin, hook.clientScript, err) | ||
135 | }) | ||
136 | } | ||
137 | } catch (err) { | ||
138 | console.error('Cannot run hook %s of script %s of plugin %s.', hookName, hook.plugin, hook.clientScript, err) | ||
139 | } | ||
140 | } | 144 | } |
141 | 145 | ||
142 | return result | 146 | return result |