@hocuspocus/extension-webhook 1.0.0-alpha.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +272 -0
- package/LICENSE.md +21 -0
- package/dist/demos/backend/src/create-document.d.ts +1 -0
- package/dist/demos/backend/src/express.d.ts +1 -0
- package/dist/demos/backend/src/koa.d.ts +1 -0
- package/dist/demos/backend/src/minimal.d.ts +1 -0
- package/dist/demos/backend/src/monitor.d.ts +1 -0
- package/dist/demos/backend/src/redis.d.ts +1 -0
- package/dist/demos/backend/src/slow.d.ts +1 -0
- package/dist/demos/backend/src/webhook.d.ts +1 -0
- package/dist/hocuspocus-webhook.cjs +158 -0
- package/dist/hocuspocus-webhook.cjs.map +1 -0
- package/dist/hocuspocus-webhook.esm.js +150 -0
- package/dist/hocuspocus-webhook.esm.js.map +1 -0
- package/dist/packages/logger/src/index.d.ts +13 -0
- package/dist/packages/monitor/src/Collector.d.ts +62 -0
- package/dist/packages/monitor/src/Dashboard.d.ts +29 -0
- package/dist/packages/monitor/src/Storage.d.ts +35 -0
- package/dist/packages/monitor/src/index.d.ts +38 -0
- package/dist/packages/provider/src/EventEmitter.d.ts +9 -0
- package/dist/packages/provider/src/HocuspocusProvider.d.ts +158 -0
- package/dist/packages/provider/src/IncomingMessage.d.ts +14 -0
- package/dist/packages/provider/src/MessageReceiver.d.ts +13 -0
- package/dist/packages/provider/src/MessageSender.d.ts +10 -0
- package/dist/packages/provider/src/OutgoingMessage.d.ts +9 -0
- package/dist/packages/provider/src/OutgoingMessages/AuthenticationMessage.d.ts +7 -0
- package/dist/packages/provider/src/OutgoingMessages/AwarenessMessage.d.ts +8 -0
- package/dist/packages/provider/src/OutgoingMessages/QueryAwarenessMessage.d.ts +8 -0
- package/dist/packages/provider/src/OutgoingMessages/SyncStepOneMessage.d.ts +8 -0
- package/dist/packages/provider/src/OutgoingMessages/SyncStepTwoMessage.d.ts +8 -0
- package/dist/packages/provider/src/OutgoingMessages/UpdateMessage.d.ts +7 -0
- package/dist/packages/provider/src/index.d.ts +3 -0
- package/dist/packages/provider/src/types.d.ts +34 -0
- package/dist/packages/provider/src/utils/awarenessStatesToArray.d.ts +4 -0
- package/dist/packages/provider/src/utils/index.d.ts +1 -0
- package/dist/packages/redis/src/Redis.d.ts +16 -0
- package/dist/packages/redis/src/RedisCluster.d.ts +4 -0
- package/dist/packages/redis/src/index.d.ts +2 -0
- package/dist/packages/rocksdb/src/index.d.ts +22 -0
- package/dist/packages/server/src/CloseEvents.d.ts +4 -0
- package/dist/packages/server/src/Connection.d.ts +62 -0
- package/dist/packages/server/src/Debugger.d.ts +15 -0
- package/dist/packages/server/src/Document.d.ts +75 -0
- package/dist/packages/server/src/Hocuspocus.d.ts +86 -0
- package/dist/packages/server/src/IncomingMessage.d.ts +19 -0
- package/dist/packages/server/src/MessageReceiver.d.ts +10 -0
- package/dist/packages/server/src/OutgoingMessage.d.ts +16 -0
- package/dist/packages/server/src/index.d.ts +2 -0
- package/dist/packages/server/src/types.d.ts +133 -0
- package/dist/packages/throttle/src/index.d.ts +20 -0
- package/dist/packages/transformer/src/Prosemirror.d.ts +11 -0
- package/dist/packages/transformer/src/Tiptap.d.ts +10 -0
- package/dist/packages/transformer/src/index.d.ts +3 -0
- package/dist/packages/transformer/src/types.d.ts +5 -0
- package/dist/packages/webhook/src/index.d.ts +59 -0
- package/dist/shared/protocols/auth.d.ts +6 -0
- package/package.json +32 -0
- package/src/index.ts +197 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Decoder } from 'lib0/decoding';
|
|
2
|
+
import { Encoder } from 'lib0/encoding';
|
|
3
|
+
import { MessageType } from './types';
|
|
4
|
+
export declare class IncomingMessage {
|
|
5
|
+
/**
|
|
6
|
+
* Access to the received message.
|
|
7
|
+
*/
|
|
8
|
+
decoder: Decoder;
|
|
9
|
+
/**
|
|
10
|
+
* Access to the reply.
|
|
11
|
+
*/
|
|
12
|
+
encoder: Encoder;
|
|
13
|
+
constructor(input: any);
|
|
14
|
+
readVarUint8Array(): Uint8Array;
|
|
15
|
+
readVarUint(): number;
|
|
16
|
+
toUint8Array(): Uint8Array;
|
|
17
|
+
writeVarUint(type: MessageType): void;
|
|
18
|
+
get length(): number;
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import Connection from './Connection';
|
|
2
|
+
import { IncomingMessage } from './IncomingMessage';
|
|
3
|
+
import { MessageLogger } from './Debugger';
|
|
4
|
+
export declare class MessageReceiver {
|
|
5
|
+
message: IncomingMessage;
|
|
6
|
+
debugger: MessageLogger;
|
|
7
|
+
constructor(message: IncomingMessage);
|
|
8
|
+
apply(connection: Connection): void;
|
|
9
|
+
readSyncMessage(message: IncomingMessage, connection: Connection): 0 | 1 | 2;
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Encoder } from 'lib0/encoding';
|
|
2
|
+
import { Awareness } from 'y-protocols/awareness';
|
|
3
|
+
import Document from './Document';
|
|
4
|
+
export declare class OutgoingMessage {
|
|
5
|
+
encoder: Encoder;
|
|
6
|
+
type?: number;
|
|
7
|
+
category?: string;
|
|
8
|
+
constructor();
|
|
9
|
+
createSyncMessage(): OutgoingMessage;
|
|
10
|
+
createAwarenessUpdateMessage(awareness: Awareness, changedClients?: Array<any>): OutgoingMessage;
|
|
11
|
+
writeAuthenticated(): OutgoingMessage;
|
|
12
|
+
writePermissionDenied(reason: string): OutgoingMessage;
|
|
13
|
+
writeFirstSyncStepFor(document: Document): OutgoingMessage;
|
|
14
|
+
writeUpdate(update: Uint8Array): OutgoingMessage;
|
|
15
|
+
toUint8Array(): Uint8Array;
|
|
16
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http';
|
|
3
|
+
import { URLSearchParams } from 'url';
|
|
4
|
+
import { Socket } from 'net';
|
|
5
|
+
import Document from './Document';
|
|
6
|
+
import { Hocuspocus } from './Hocuspocus';
|
|
7
|
+
export declare enum MessageType {
|
|
8
|
+
Unknown = -1,
|
|
9
|
+
Sync = 0,
|
|
10
|
+
Awareness = 1,
|
|
11
|
+
Auth = 2
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* State of the WebSocket connection.
|
|
15
|
+
* https://developer.mozilla.org/de/docs/Web/API/WebSocket/readyState
|
|
16
|
+
*/
|
|
17
|
+
export declare enum WsReadyStates {
|
|
18
|
+
Connecting = 0,
|
|
19
|
+
Open = 1,
|
|
20
|
+
Closing = 2,
|
|
21
|
+
Closed = 3
|
|
22
|
+
}
|
|
23
|
+
export interface AwarenessUpdate {
|
|
24
|
+
added: Array<any>;
|
|
25
|
+
updated: Array<any>;
|
|
26
|
+
removed: Array<any>;
|
|
27
|
+
}
|
|
28
|
+
export interface ConnectionConfig {
|
|
29
|
+
readOnly: boolean;
|
|
30
|
+
isAuthenticated: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface Extension {
|
|
33
|
+
onAuthenticate?(data: onAuthenticatePayload): Promise<any>;
|
|
34
|
+
onChange?(data: onChangePayload): Promise<any>;
|
|
35
|
+
onConnect?(data: onConnectPayload): Promise<any>;
|
|
36
|
+
onConfigure?(data: onConfigurePayload): Promise<any>;
|
|
37
|
+
onCreateDocument?(data: onCreateDocumentPayload): Promise<any>;
|
|
38
|
+
onDestroy?(data: onDestroyPayload): Promise<any>;
|
|
39
|
+
onDisconnect?(data: onDisconnectPayload): Promise<any>;
|
|
40
|
+
onListen?(data: onListenPayload): Promise<any>;
|
|
41
|
+
onRequest?(data: onRequestPayload): Promise<any>;
|
|
42
|
+
onUpgrade?(data: onUpgradePayload): Promise<any>;
|
|
43
|
+
}
|
|
44
|
+
export interface Configuration extends Extension {
|
|
45
|
+
/**
|
|
46
|
+
* A list of hocuspocus extenions.
|
|
47
|
+
*/
|
|
48
|
+
extensions: Array<Extension>;
|
|
49
|
+
/**
|
|
50
|
+
* The port which the server listens on.
|
|
51
|
+
*/
|
|
52
|
+
port: number | null;
|
|
53
|
+
/**
|
|
54
|
+
* Defines in which interval the server sends a ping, and closes the connection when no pong is sent back.
|
|
55
|
+
*/
|
|
56
|
+
timeout: number;
|
|
57
|
+
}
|
|
58
|
+
export interface onAuthenticatePayload {
|
|
59
|
+
documentName: string;
|
|
60
|
+
instance: Hocuspocus;
|
|
61
|
+
requestHeaders: IncomingHttpHeaders;
|
|
62
|
+
requestParameters: URLSearchParams;
|
|
63
|
+
socketId: string;
|
|
64
|
+
token: string;
|
|
65
|
+
connection: ConnectionConfig;
|
|
66
|
+
}
|
|
67
|
+
export interface onConnectPayload {
|
|
68
|
+
documentName: string;
|
|
69
|
+
instance: Hocuspocus;
|
|
70
|
+
request: IncomingMessage;
|
|
71
|
+
requestHeaders: IncomingHttpHeaders;
|
|
72
|
+
requestParameters: URLSearchParams;
|
|
73
|
+
socketId: string;
|
|
74
|
+
connection: ConnectionConfig;
|
|
75
|
+
}
|
|
76
|
+
export interface onCreateDocumentPayload {
|
|
77
|
+
context: any;
|
|
78
|
+
document: Document;
|
|
79
|
+
documentName: string;
|
|
80
|
+
instance: Hocuspocus;
|
|
81
|
+
requestHeaders: IncomingHttpHeaders;
|
|
82
|
+
requestParameters: URLSearchParams;
|
|
83
|
+
socketId: string;
|
|
84
|
+
connection: ConnectionConfig;
|
|
85
|
+
}
|
|
86
|
+
export interface onChangePayload {
|
|
87
|
+
clientsCount: number;
|
|
88
|
+
context: any;
|
|
89
|
+
document: Document;
|
|
90
|
+
documentName: string;
|
|
91
|
+
instance: Hocuspocus;
|
|
92
|
+
requestHeaders: IncomingHttpHeaders;
|
|
93
|
+
requestParameters: URLSearchParams;
|
|
94
|
+
update: Uint8Array;
|
|
95
|
+
socketId: string;
|
|
96
|
+
}
|
|
97
|
+
export interface onDisconnectPayload {
|
|
98
|
+
clientsCount: number;
|
|
99
|
+
context: any;
|
|
100
|
+
document: Document;
|
|
101
|
+
documentName: string;
|
|
102
|
+
instance: Hocuspocus;
|
|
103
|
+
requestHeaders: IncomingHttpHeaders;
|
|
104
|
+
requestParameters: URLSearchParams;
|
|
105
|
+
socketId: string;
|
|
106
|
+
}
|
|
107
|
+
export interface onRequestPayload {
|
|
108
|
+
request: IncomingMessage;
|
|
109
|
+
response: ServerResponse;
|
|
110
|
+
instance: Hocuspocus;
|
|
111
|
+
}
|
|
112
|
+
export interface onUpgradePayload {
|
|
113
|
+
head: any;
|
|
114
|
+
request: IncomingMessage;
|
|
115
|
+
socket: Socket;
|
|
116
|
+
instance: Hocuspocus;
|
|
117
|
+
}
|
|
118
|
+
export interface onListenPayload {
|
|
119
|
+
port: number;
|
|
120
|
+
}
|
|
121
|
+
export interface onDestroyPayload {
|
|
122
|
+
instance: Hocuspocus;
|
|
123
|
+
}
|
|
124
|
+
export interface onConfigurePayload {
|
|
125
|
+
configuration: Configuration;
|
|
126
|
+
version: string;
|
|
127
|
+
yjsVersion: string;
|
|
128
|
+
instance: Hocuspocus;
|
|
129
|
+
}
|
|
130
|
+
export interface CloseEvent {
|
|
131
|
+
code: number;
|
|
132
|
+
reason: string;
|
|
133
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Extension, onConnectPayload } from '@hocuspocus/server';
|
|
2
|
+
export interface Configuration {
|
|
3
|
+
throttle: number | null | false;
|
|
4
|
+
banTime: number;
|
|
5
|
+
}
|
|
6
|
+
export declare class Throttle implements Extension {
|
|
7
|
+
configuration: Configuration;
|
|
8
|
+
connectionsByIp: Map<string, Array<number>>;
|
|
9
|
+
bannedIps: Map<string, number>;
|
|
10
|
+
/**
|
|
11
|
+
* Throttle requests
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
private throttle;
|
|
15
|
+
/**
|
|
16
|
+
* onConnect hook
|
|
17
|
+
* @param data
|
|
18
|
+
*/
|
|
19
|
+
onConnect(data: onConnectPayload): Promise<any>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Doc } from 'yjs';
|
|
2
|
+
import { Schema } from 'prosemirror-model';
|
|
3
|
+
import { Transformer } from './types';
|
|
4
|
+
declare class Prosemirror implements Transformer {
|
|
5
|
+
defaultSchema: Schema;
|
|
6
|
+
schema(schema: Schema): Prosemirror;
|
|
7
|
+
fromYdoc(document: Doc, fieldName?: string | Array<string>): any;
|
|
8
|
+
toYdoc(document: any, fieldName?: string | Array<string>, schema?: Schema): Doc;
|
|
9
|
+
}
|
|
10
|
+
export declare const ProsemirrorTransformer: Prosemirror;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Doc } from 'yjs';
|
|
2
|
+
import { Extensions } from '@tiptap/core/dist/packages/core/src/types';
|
|
3
|
+
import { Transformer } from './types';
|
|
4
|
+
export declare class Tiptap implements Transformer {
|
|
5
|
+
defaultExtensions: Extensions;
|
|
6
|
+
extensions(extensions: Extensions): Tiptap;
|
|
7
|
+
fromYdoc(document: Doc, fieldName?: string | Array<string>): any;
|
|
8
|
+
toYdoc(document: any, fieldName?: string | Array<string>, extensions?: Extensions): Doc;
|
|
9
|
+
}
|
|
10
|
+
export declare const TiptapTransformer: Tiptap;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Extension, onChangePayload, onConnectPayload, onCreateDocumentPayload, onDisconnectPayload } from '@hocuspocus/server';
|
|
3
|
+
import { Doc } from 'yjs';
|
|
4
|
+
import { Transformer } from '@hocuspocus/transformer';
|
|
5
|
+
import { AxiosResponse } from 'axios';
|
|
6
|
+
import Timeout = NodeJS.Timeout;
|
|
7
|
+
export declare enum Events {
|
|
8
|
+
onChange = "change",
|
|
9
|
+
onConnect = "connect",
|
|
10
|
+
onCreate = "create",
|
|
11
|
+
onDisconnect = "disconnect"
|
|
12
|
+
}
|
|
13
|
+
export interface Configuration {
|
|
14
|
+
debounce: number | false | null;
|
|
15
|
+
debounceMaxWait: number;
|
|
16
|
+
secret: string;
|
|
17
|
+
transformer: Transformer | {
|
|
18
|
+
toYdoc: (document: any) => Doc;
|
|
19
|
+
fromYdoc: (document: Doc) => any;
|
|
20
|
+
};
|
|
21
|
+
url: string;
|
|
22
|
+
events: Array<Events>;
|
|
23
|
+
}
|
|
24
|
+
export declare class Webhook implements Extension {
|
|
25
|
+
configuration: Configuration;
|
|
26
|
+
debounced: Map<string, {
|
|
27
|
+
timeout: Timeout;
|
|
28
|
+
start: number;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Constructor
|
|
32
|
+
*/
|
|
33
|
+
constructor(configuration?: Partial<Configuration>);
|
|
34
|
+
/**
|
|
35
|
+
* Create a signature for the response body
|
|
36
|
+
*/
|
|
37
|
+
createSignature(body: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* debounce the given function, using the given identifier
|
|
40
|
+
*/
|
|
41
|
+
debounce(id: string, func: Function): void;
|
|
42
|
+
/**
|
|
43
|
+
* Send a request to the given url containing the given data
|
|
44
|
+
*/
|
|
45
|
+
sendRequest(event: Events, payload: any): Promise<AxiosResponse<any>>;
|
|
46
|
+
/**
|
|
47
|
+
* onChange hook
|
|
48
|
+
*/
|
|
49
|
+
onChange(data: onChangePayload): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* onCreateDocument hook
|
|
52
|
+
*/
|
|
53
|
+
onCreateDocument(data: onCreateDocumentPayload): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* onConnect hook
|
|
56
|
+
*/
|
|
57
|
+
onConnect(data: onConnectPayload): Promise<any>;
|
|
58
|
+
onDisconnect(data: onDisconnectPayload): Promise<void>;
|
|
59
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as encoding from 'lib0/encoding';
|
|
2
|
+
import * as decoding from 'lib0/decoding';
|
|
3
|
+
export declare const writeAuthentication: (encoder: encoding.Encoder, auth: string) => void;
|
|
4
|
+
export declare const writePermissionDenied: (encoder: encoding.Encoder, reason: string) => void;
|
|
5
|
+
export declare const writeAuthenticated: (encoder: encoding.Encoder) => void;
|
|
6
|
+
export declare const readAuthMessage: (decoder: decoding.Decoder, permissionDeniedHandler: (reason: string) => void, authenticatedHandler: () => void) => void;
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hocuspocus/extension-webhook",
|
|
3
|
+
"version": "1.0.0-alpha.34",
|
|
4
|
+
"description": "hocuspocus webhook extension",
|
|
5
|
+
"homepage": "https://hocuspocus.dev",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"hocuspocus",
|
|
8
|
+
"webhook",
|
|
9
|
+
"api",
|
|
10
|
+
"rest",
|
|
11
|
+
"yjs"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "dist/hocuspocus-webhook.esm.js",
|
|
16
|
+
"module": "dist/hocuspocus-webhook.esm.js",
|
|
17
|
+
"types": "dist/packages/webhook/src/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
"import": "./dist/hocuspocus-webhook.esm.js",
|
|
20
|
+
"require": "./dist/hocuspocus-webhook.cjs"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"src",
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@hocuspocus/server": "^1.0.0-alpha.69",
|
|
28
|
+
"@hocuspocus/transformer": "^1.0.0-alpha.14",
|
|
29
|
+
"axios": "^0.21.1"
|
|
30
|
+
},
|
|
31
|
+
"gitHead": "d84b5516f65dfe096fd6c633f96309a6f65a9811"
|
|
32
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { createHmac } from 'crypto'
|
|
2
|
+
import {
|
|
3
|
+
Extension,
|
|
4
|
+
onChangePayload,
|
|
5
|
+
onConnectPayload,
|
|
6
|
+
onCreateDocumentPayload,
|
|
7
|
+
onDisconnectPayload,
|
|
8
|
+
} from '@hocuspocus/server'
|
|
9
|
+
import { Doc } from 'yjs'
|
|
10
|
+
import { TiptapTransformer, Transformer } from '@hocuspocus/transformer'
|
|
11
|
+
import axios, { AxiosResponse } from 'axios'
|
|
12
|
+
import Timeout = NodeJS.Timeout
|
|
13
|
+
|
|
14
|
+
export enum Events {
|
|
15
|
+
onChange = 'change',
|
|
16
|
+
onConnect = 'connect',
|
|
17
|
+
onCreate = 'create',
|
|
18
|
+
onDisconnect = 'disconnect',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface Configuration {
|
|
22
|
+
debounce: number | false | null,
|
|
23
|
+
debounceMaxWait: number,
|
|
24
|
+
secret: string,
|
|
25
|
+
transformer: Transformer | {
|
|
26
|
+
toYdoc: (document: any) => Doc,
|
|
27
|
+
fromYdoc: (document: Doc) => any,
|
|
28
|
+
},
|
|
29
|
+
url: string,
|
|
30
|
+
events: Array<Events>,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class Webhook implements Extension {
|
|
34
|
+
|
|
35
|
+
configuration: Configuration = {
|
|
36
|
+
debounce: 2000,
|
|
37
|
+
debounceMaxWait: 10000,
|
|
38
|
+
secret: '',
|
|
39
|
+
transformer: TiptapTransformer,
|
|
40
|
+
url: '',
|
|
41
|
+
events: [
|
|
42
|
+
Events.onChange,
|
|
43
|
+
],
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
debounced: Map<string, { timeout: Timeout, start: number }> = new Map()
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Constructor
|
|
50
|
+
*/
|
|
51
|
+
constructor(configuration?: Partial<Configuration>) {
|
|
52
|
+
this.configuration = {
|
|
53
|
+
...this.configuration,
|
|
54
|
+
...configuration,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!this.configuration.url) {
|
|
58
|
+
throw new Error('url is required!')
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a signature for the response body
|
|
64
|
+
*/
|
|
65
|
+
createSignature(body: string): string {
|
|
66
|
+
const hmac = createHmac('sha256', this.configuration.secret)
|
|
67
|
+
|
|
68
|
+
return `sha256=${hmac.update(body).digest('hex')}`
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* debounce the given function, using the given identifier
|
|
73
|
+
*/
|
|
74
|
+
debounce(id: string, func: Function) {
|
|
75
|
+
const old = this.debounced.get(id)
|
|
76
|
+
const start = old?.start || Date.now()
|
|
77
|
+
|
|
78
|
+
const run = () => {
|
|
79
|
+
this.debounced.delete(id)
|
|
80
|
+
func()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (old?.timeout) clearTimeout(old.timeout)
|
|
84
|
+
if (Date.now() - start >= this.configuration.debounceMaxWait) return run()
|
|
85
|
+
|
|
86
|
+
this.debounced.set(id, {
|
|
87
|
+
start,
|
|
88
|
+
timeout: setTimeout(run, <number> this.configuration.debounce),
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Send a request to the given url containing the given data
|
|
94
|
+
*/
|
|
95
|
+
async sendRequest(event: Events, payload: any) {
|
|
96
|
+
const json = JSON.stringify({ event, payload })
|
|
97
|
+
|
|
98
|
+
return axios.post(
|
|
99
|
+
this.configuration.url,
|
|
100
|
+
json,
|
|
101
|
+
{ headers: { 'X-Hocuspocus-Signature-256': this.createSignature(json) } },
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* onChange hook
|
|
107
|
+
*/
|
|
108
|
+
async onChange(data: onChangePayload) {
|
|
109
|
+
if (!this.configuration.events.includes(Events.onChange)) {
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const save = () => {
|
|
114
|
+
this.sendRequest(Events.onChange, {
|
|
115
|
+
document: this.configuration.transformer.fromYdoc(data.document),
|
|
116
|
+
documentName: data.documentName,
|
|
117
|
+
context: data.context,
|
|
118
|
+
requestHeaders: data.requestHeaders,
|
|
119
|
+
requestParameters: Object.fromEntries(data.requestParameters.entries()),
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!this.configuration.debounce) {
|
|
124
|
+
return save()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.debounce(data.documentName, save)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* onCreateDocument hook
|
|
132
|
+
*/
|
|
133
|
+
async onCreateDocument(data: onCreateDocumentPayload) {
|
|
134
|
+
if (!this.configuration.events.includes(Events.onCreate)) {
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const response = <AxiosResponse> await this.sendRequest(Events.onCreate, {
|
|
139
|
+
documentName: data.documentName,
|
|
140
|
+
requestHeaders: data.requestHeaders,
|
|
141
|
+
requestParameters: Object.fromEntries(data.requestParameters.entries()),
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
if (response.status !== 200 || !response.data) return
|
|
145
|
+
|
|
146
|
+
const document = typeof response.data === 'string'
|
|
147
|
+
? JSON.parse(response.data)
|
|
148
|
+
: response.data
|
|
149
|
+
|
|
150
|
+
// eslint-disable-next-line guard-for-in,no-restricted-syntax
|
|
151
|
+
for (const fieldName in document) {
|
|
152
|
+
if (data.document.isEmpty(fieldName)) {
|
|
153
|
+
data.document.merge(
|
|
154
|
+
this.configuration.transformer.toYdoc(document[fieldName], fieldName),
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* onConnect hook
|
|
162
|
+
*/
|
|
163
|
+
async onConnect(data: onConnectPayload) {
|
|
164
|
+
if (!this.configuration.events.includes(Events.onConnect)) {
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
const response = <AxiosResponse> await this.sendRequest(Events.onConnect, {
|
|
170
|
+
documentName: data.documentName,
|
|
171
|
+
requestHeaders: data.requestHeaders,
|
|
172
|
+
requestParameters: Object.fromEntries(data.requestParameters.entries()),
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
return typeof response.data === 'string'
|
|
176
|
+
? JSON.parse(response.data)
|
|
177
|
+
: response.data
|
|
178
|
+
} catch (e) {
|
|
179
|
+
// eslint-disable-next-line no-throw-literal
|
|
180
|
+
throw null
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async onDisconnect(data: onDisconnectPayload) {
|
|
185
|
+
if (!this.configuration.events.includes(Events.onConnect)) {
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
await this.sendRequest(Events.onDisconnect, {
|
|
190
|
+
documentName: data.documentName,
|
|
191
|
+
requestHeaders: data.requestHeaders,
|
|
192
|
+
requestParameters: Object.fromEntries(data.requestParameters.entries()),
|
|
193
|
+
context: data.context,
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
}
|