自定义扩展

官方扩展

你可以在这里查看我们已经创建的扩展。

创建你自己的扩展

Hocuspocus 是用 TypeScript 编写的。你不必一定使用 TypeScript 来编写扩展,但强烈推荐。本文档中我们只介绍 TypeScript 部分。

第一步:创建一个实现 Extension 接口的新类,并添加所需的钩子。

由于每个钩子都需要返回一个 Promise,最简单的方式是将它们标记为 async

import {
  Extension,
  onChangePayload,
  onConnectPayload,
  onAuthenticatePayload,
  onLoadDocumentPayload,
  onDisconnectPayload,
} from "@hocuspocus/server";

export class MyHocuspocusExtension implements Extension {
  async onLoadDocument(data: onLoadDocumentPayload): Promise<void> {}

  async onChange(data: onChangePayload): Promise<void> {}

  async onConnect(data: onConnectPayload): Promise<void> {}

  async onAuthenticate(data: onAuthenticatePayload): Promise<void> {}

  async onDisconnect(data: onDisconnectPayload): Promise<void> {}

  async onRequest(data: onRequestPayload): Promise<void> {}

  async onUpgrade(data: onUpgradePayload): Promise<void> {}

  async onListen(data: onListenPayload): Promise<void> {}

  async onDestroy(data: onDestroyPayload): Promise<void> {}

  async onConfigure(data: onConfigurePayload): Promise<void> {}
}

注意到了吗?这些钩子看起来和我们在之前章节中介绍的钩子非常相似。没错:它们的工作方式也是一样的。所以你应该已经知道它们的作用以及如何使用它们。如果你仍然不确定,可以查看本教程中更详细介绍这些钩子的钩子章节

现在你可以添加一个构造函数,接受你的扩展配置并合并默认配置。此时创建一个配置接口是个好习惯。

import {
  Extension,
  onChangePayload,
  onConnectPayload,
  onAuthenticatePayload,
  onLoadDocumentPayload,
  onDisconnectPayload,
} from "@hocuspocus/server";

export interface Configuration {
  myConfigurationOption: string;
  myOptionalConfigurationOption: number | undefined;
}

export class MyHocuspocusExtension implements Extension {
  configuration: Configuration = {
    myConfigurationOption: "foobar",
    myOptionalConfigurationOption: 42,
  };

  constructor(configuration?: Partial<Configuration>) {
    this.configuration = { ...this.configuration, ...configuration };
  }

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onLoadDocument(data: onLoadDocumentPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onChange(data: onChangePayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onConnect(data: onConnectPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onAuthenticate(data: onAuthenticatePayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onDisconnect(data: onDisconnectPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onRequest(data: onRequestPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onUpgrade(data: onUpgradePayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onListen(data: onListenPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onDestroy(data: onDestroyPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onConfigure(data: onConfigurePayload): Promise<void> {}
}

就是这样。现在只差你写代码了。祝你扩展开发愉快!完成后,你可以像导入其他扩展一样导入并注册你的扩展:

import { Server } from "@hocuspocus/server";
import { MyHocuspocusExtension } from "./extensions/my-hocuspocus-extension";

const server = new Server({
  extensions: [
    new MyHocuspocusExtension({
      myConfigurationOption: "baz",
      myOptionalConfigurationOption: 1337,
    }),
  ],
});

server.listen();