mirror of
https://github.com/directus/directus.git
synced 2026-02-10 21:45:02 -05:00
Delete required hooks only once (#10955)
* Add dedicated options object to ExtensionManager * Delete required hooks only once
This commit is contained in:
committed by
GitHub
parent
0d9de79abf
commit
c2eefc524f
@@ -51,20 +51,31 @@ export function getExtensionManager(): ExtensionManager {
|
||||
return extensionManager;
|
||||
}
|
||||
|
||||
type EventHandler =
|
||||
| { type: 'filter'; name: string; handler: FilterHandler }
|
||||
| { type: 'action'; name: string; handler: ActionHandler }
|
||||
| { type: 'init'; name: string; handler: InitHandler }
|
||||
| { type: 'schedule'; task: ScheduledTask };
|
||||
|
||||
type AppExtensions = Partial<Record<AppExtensionType, string>>;
|
||||
type ApiExtensions = {
|
||||
hooks: (
|
||||
| { type: 'filter'; path: string; event: string; handler: FilterHandler }
|
||||
| { type: 'action'; path: string; event: string; handler: ActionHandler }
|
||||
| { type: 'init'; path: string; event: string; handler: InitHandler }
|
||||
| { type: 'schedule'; path: string; task: ScheduledTask }
|
||||
)[];
|
||||
hooks: { path: string; events: EventHandler[] }[];
|
||||
endpoints: { path: string }[];
|
||||
};
|
||||
|
||||
type Options = {
|
||||
schedule: boolean;
|
||||
watch: boolean;
|
||||
};
|
||||
|
||||
const defaultOptions: Options = {
|
||||
schedule: true,
|
||||
watch: env.EXTENSIONS_AUTO_RELOAD && env.NODE_ENV !== 'development',
|
||||
};
|
||||
|
||||
class ExtensionManager {
|
||||
private isLoaded = false;
|
||||
private isScheduleHookEnabled = true;
|
||||
private options: Options;
|
||||
|
||||
private extensions: Extension[] = [];
|
||||
|
||||
@@ -77,16 +88,19 @@ class ExtensionManager {
|
||||
private watcher: FSWatcher | null = null;
|
||||
|
||||
constructor() {
|
||||
this.options = defaultOptions;
|
||||
|
||||
this.apiEmitter = new Emitter();
|
||||
this.endpointRouter = Router();
|
||||
}
|
||||
|
||||
public async initialize({ schedule, watch } = { schedule: true, watch: true }): Promise<void> {
|
||||
this.isScheduleHookEnabled = schedule;
|
||||
public async initialize(options: Partial<Options> = {}): Promise<void> {
|
||||
this.options = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (watch) {
|
||||
this.initializeWatcher();
|
||||
}
|
||||
this.initializeWatcher();
|
||||
|
||||
if (!this.isLoaded) {
|
||||
await this.load();
|
||||
@@ -181,7 +195,7 @@ class ExtensionManager {
|
||||
}
|
||||
|
||||
private initializeWatcher(): void {
|
||||
if (env.EXTENSIONS_AUTO_RELOAD && env.NODE_ENV !== 'development' && !this.watcher) {
|
||||
if (this.options.watch && !this.watcher) {
|
||||
logger.info('Watching extensions for changes...');
|
||||
|
||||
const localExtensionPaths = (env.SERVE_APP ? EXTENSION_TYPES : API_EXTENSION_TYPES).map((type) =>
|
||||
@@ -311,41 +325,43 @@ class ExtensionManager {
|
||||
|
||||
const register = getModuleDefault(hookInstance);
|
||||
|
||||
const hookHandler: { path: string; events: EventHandler[] } = {
|
||||
path: hookPath,
|
||||
events: [],
|
||||
};
|
||||
|
||||
const registerFunctions = {
|
||||
filter: (event: string, handler: FilterHandler) => {
|
||||
emitter.onFilter(event, handler);
|
||||
|
||||
this.apiExtensions.hooks.push({
|
||||
hookHandler.events.push({
|
||||
type: 'filter',
|
||||
path: hookPath,
|
||||
event,
|
||||
name: event,
|
||||
handler,
|
||||
});
|
||||
},
|
||||
action: (event: string, handler: ActionHandler) => {
|
||||
emitter.onAction(event, handler);
|
||||
|
||||
this.apiExtensions.hooks.push({
|
||||
hookHandler.events.push({
|
||||
type: 'action',
|
||||
path: hookPath,
|
||||
event,
|
||||
name: event,
|
||||
handler,
|
||||
});
|
||||
},
|
||||
init: (event: string, handler: InitHandler) => {
|
||||
emitter.onInit(event, handler);
|
||||
|
||||
this.apiExtensions.hooks.push({
|
||||
hookHandler.events.push({
|
||||
type: 'init',
|
||||
path: hookPath,
|
||||
event,
|
||||
name: event,
|
||||
handler,
|
||||
});
|
||||
},
|
||||
schedule: (cron: string, handler: ScheduleHandler) => {
|
||||
if (validate(cron)) {
|
||||
const task = schedule(cron, async () => {
|
||||
if (this.isScheduleHookEnabled) {
|
||||
if (this.options.schedule) {
|
||||
try {
|
||||
await handler();
|
||||
} catch (error: any) {
|
||||
@@ -354,9 +370,8 @@ class ExtensionManager {
|
||||
}
|
||||
});
|
||||
|
||||
this.apiExtensions.hooks.push({
|
||||
hookHandler.events.push({
|
||||
type: 'schedule',
|
||||
path: hookPath,
|
||||
task,
|
||||
});
|
||||
} else {
|
||||
@@ -374,6 +389,8 @@ class ExtensionManager {
|
||||
logger,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
this.apiExtensions.hooks.push(hookHandler);
|
||||
}
|
||||
|
||||
private registerEndpoint(endpoint: Extension, router: Router) {
|
||||
@@ -405,19 +422,21 @@ class ExtensionManager {
|
||||
|
||||
private unregisterHooks(): void {
|
||||
for (const hook of this.apiExtensions.hooks) {
|
||||
switch (hook.type) {
|
||||
case 'filter':
|
||||
emitter.offFilter(hook.event, hook.handler);
|
||||
break;
|
||||
case 'action':
|
||||
emitter.offAction(hook.event, hook.handler);
|
||||
break;
|
||||
case 'init':
|
||||
emitter.offInit(hook.event, hook.handler);
|
||||
break;
|
||||
case 'schedule':
|
||||
hook.task.stop();
|
||||
break;
|
||||
for (const event of hook.events) {
|
||||
switch (event.type) {
|
||||
case 'filter':
|
||||
emitter.offFilter(event.name, event.handler);
|
||||
break;
|
||||
case 'action':
|
||||
emitter.offAction(event.name, event.handler);
|
||||
break;
|
||||
case 'init':
|
||||
emitter.offInit(event.name, event.handler);
|
||||
break;
|
||||
case 'schedule':
|
||||
event.task.stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete require.cache[require.resolve(hook.path)];
|
||||
|
||||
Reference in New Issue
Block a user