aboutsummaryrefslogtreecommitdiffstats
path: root/packages/shared/plugins.ts
blob: 2aa7df4a2bfbc22b6559b76cedf1855b753d20e3 (plain) (blame)
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
// Implementation inspired from Outline

import type { QueueClient } from "./queueing";
import logger from "./logger";
import { SearchIndexClient } from "./search";

export enum PluginType {
  Search = "search",
  Queue = "queue",
}

interface PluginTypeMap {
  [PluginType.Search]: SearchIndexClient;
  [PluginType.Queue]: QueueClient;
}

export interface TPlugin<T extends PluginType> {
  type: T;
  name: string;
  provider: PluginProvider<PluginTypeMap[T]>;
}

export interface PluginProvider<T> {
  getClient(): Promise<T | null>;
}

// Preserve the key-dependent value type: for K, store TPlugin<K>[]
type ProviderMap = { [K in PluginType]: TPlugin<K>[] };

export class PluginManager {
  private static providers: ProviderMap = {
    [PluginType.Search]: [],
    [PluginType.Queue]: [],
  };

  static register<T extends PluginType>(plugin: TPlugin<T>): void {
    PluginManager.providers[plugin.type].push(plugin);
  }

  static async getClient<T extends PluginType>(
    type: T,
  ): Promise<PluginTypeMap[T] | null> {
    const providers: TPlugin<T>[] = PluginManager.providers[type];
    if (providers.length === 0) {
      return null;
    }
    return await providers[providers.length - 1]!.provider.getClient();
  }

  static isRegistered<T extends PluginType>(type: T): boolean {
    return PluginManager.providers[type].length > 0;
  }

  static logAllPlugins() {
    logger.info("Plugins (Last one wins):");
    for (const type of Object.values(PluginType)) {
      logger.info(`  ${type}:`);
      const plugins = PluginManager.providers[type];
      if (!plugins) {
        logger.info("    - None");
        continue;
      }
      for (const plugin of plugins) {
        logger.info(`    - ${plugin.name}`);
      }
    }
  }
}