@hocuspocus/provider 1.0.0-alpha.26 → 1.0.0-alpha.30

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.
Files changed (91) hide show
  1. package/dist/hocuspocus-provider.cjs +132 -330
  2. package/dist/hocuspocus-provider.cjs.map +1 -1
  3. package/dist/hocuspocus-provider.esm.js +130 -329
  4. package/dist/hocuspocus-provider.esm.js.map +1 -1
  5. package/dist/packages/common/src/CloseEvents.d.ts +23 -0
  6. package/dist/packages/common/src/index.d.ts +1 -0
  7. package/dist/packages/extension-database/src/Database.d.ts +32 -0
  8. package/dist/packages/extension-database/src/index.d.ts +1 -0
  9. package/dist/packages/extension-logger/src/Logger.d.ts +7 -8
  10. package/dist/packages/extension-sqlite/src/SQLite.d.ts +26 -0
  11. package/dist/packages/extension-sqlite/src/index.d.ts +1 -0
  12. package/dist/packages/extension-webhook/src/index.d.ts +2 -3
  13. package/dist/packages/provider/src/EventEmitter.d.ts +1 -1
  14. package/dist/packages/provider/src/HocuspocusCloudProvider.d.ts +11 -0
  15. package/dist/packages/provider/src/HocuspocusProvider.d.ts +17 -9
  16. package/dist/packages/provider/src/index.d.ts +1 -0
  17. package/dist/packages/provider/src/types.d.ts +10 -0
  18. package/dist/packages/server/src/Connection.d.ts +5 -5
  19. package/dist/packages/server/src/Debugger.d.ts +1 -2
  20. package/dist/packages/server/src/Document.d.ts +8 -5
  21. package/dist/packages/server/src/Hocuspocus.d.ts +37 -16
  22. package/dist/packages/server/src/MessageReceiver.d.ts +8 -5
  23. package/dist/packages/server/src/OutgoingMessage.d.ts +1 -0
  24. package/dist/packages/server/src/index.d.ts +7 -0
  25. package/dist/packages/server/src/types.d.ts +89 -18
  26. package/dist/{demos/backend/src/express.d.ts → playground/backend/src/default.d.ts} +0 -0
  27. package/dist/{demos/backend/src/koa.d.ts → playground/backend/src/express.d.ts} +0 -0
  28. package/dist/{demos/backend/src/load-document.d.ts → playground/backend/src/koa.d.ts} +0 -0
  29. package/dist/{demos/backend/src/minimal.d.ts → playground/backend/src/load-document.d.ts} +0 -0
  30. package/dist/{demos → playground}/backend/src/monitor.d.ts +0 -0
  31. package/dist/{demos → playground}/backend/src/redis.d.ts +0 -0
  32. package/dist/{demos → playground}/backend/src/slow.d.ts +0 -0
  33. package/dist/{demos → playground}/backend/src/webhook.d.ts +0 -0
  34. package/dist/tests/extension-logger/onListen.d.ts +1 -0
  35. package/dist/tests/extension-redis/onLoadDocument.d.ts +1 -0
  36. package/dist/tests/extension-redis/onSynced.d.ts +1 -0
  37. package/dist/tests/extension-redis-rewrite/closeConnections.d.ts +1 -0
  38. package/dist/tests/extension-redis-rewrite/getConnectionCount.d.ts +1 -0
  39. package/dist/tests/extension-redis-rewrite/getDocumentsCount.d.ts +1 -0
  40. package/dist/tests/extension-redis-rewrite/onAwarenessChange.d.ts +1 -0
  41. package/dist/tests/extension-redis-rewrite/onChange.d.ts +1 -0
  42. package/dist/tests/extension-redis-rewrite/onStoreDocument.d.ts +1 -0
  43. package/dist/tests/extension-rocksdb/onLoadDocument.d.ts +1 -0
  44. package/dist/tests/provider/configuration.d.ts +1 -0
  45. package/dist/tests/provider/onAuthenticated.d.ts +1 -0
  46. package/dist/tests/provider/onAuthenticationFailed.d.ts +1 -0
  47. package/dist/tests/provider/onAwarenessChange.d.ts +1 -0
  48. package/dist/tests/provider/onAwarenessUpdate.d.ts +1 -0
  49. package/dist/tests/provider/onClose.d.ts +1 -0
  50. package/dist/tests/provider/onConnect.d.ts +1 -0
  51. package/dist/tests/provider/onDisconnect.d.ts +1 -0
  52. package/dist/tests/provider/onMessage.d.ts +1 -0
  53. package/dist/tests/provider/onOpen.d.ts +1 -0
  54. package/dist/tests/provider/onSynced.d.ts +1 -0
  55. package/dist/tests/server/address.d.ts +1 -0
  56. package/dist/tests/server/afterStoreDocument.d.ts +1 -0
  57. package/dist/tests/server/closeConnections.d.ts +1 -0
  58. package/dist/tests/server/getConnectionsCount.d.ts +1 -0
  59. package/dist/tests/server/getDocumentName.d.ts +1 -0
  60. package/dist/tests/server/getDocumentsCount.d.ts +1 -0
  61. package/dist/tests/server/getMessageLogs.d.ts +1 -0
  62. package/dist/tests/server/listen.d.ts +1 -0
  63. package/dist/tests/server/onAuthenticate.d.ts +1 -0
  64. package/dist/tests/server/onAwarenessUpdate.d.ts +1 -0
  65. package/dist/tests/server/onChange.d.ts +1 -0
  66. package/dist/tests/server/onConfigure.d.ts +1 -0
  67. package/dist/tests/server/onConnect.d.ts +1 -0
  68. package/dist/tests/server/onDestroy.d.ts +1 -0
  69. package/dist/tests/server/onDisconnect.d.ts +1 -0
  70. package/dist/tests/server/onListen.d.ts +1 -0
  71. package/dist/tests/server/onLoadDocument.d.ts +1 -0
  72. package/dist/tests/server/onRequest.d.ts +1 -0
  73. package/dist/tests/server/onStoreDocument.d.ts +1 -0
  74. package/dist/tests/server/onUpgrade.d.ts +1 -0
  75. package/dist/tests/server/requiresAuthentication.d.ts +1 -0
  76. package/dist/tests/transformer/TiptapTransformer.d.ts +1 -0
  77. package/dist/tests/utils/createDirectory.d.ts +1 -0
  78. package/dist/tests/utils/flushRedis.d.ts +1 -0
  79. package/dist/tests/utils/index.d.ts +7 -0
  80. package/dist/tests/utils/newHocuspocus.d.ts +2 -0
  81. package/dist/tests/utils/newHocuspocusProvider.d.ts +3 -0
  82. package/dist/tests/utils/redisConnectionSettings.d.ts +4 -0
  83. package/dist/tests/utils/removeDirectory.d.ts +1 -0
  84. package/dist/tests/utils/sleep.d.ts +1 -0
  85. package/package.json +6 -5
  86. package/src/EventEmitter.ts +1 -1
  87. package/src/HocuspocusCloudProvider.ts +34 -0
  88. package/src/HocuspocusProvider.ts +101 -68
  89. package/src/index.ts +1 -0
  90. package/src/types.ts +10 -0
  91. package/dist/packages/server/src/CloseEvents.d.ts +0 -4
@@ -4,8 +4,9 @@ import * as time from 'lib0/time'
4
4
  import { Awareness, removeAwarenessStates } from 'y-protocols/awareness'
5
5
  import * as mutex from 'lib0/mutex'
6
6
  import * as url from 'lib0/url'
7
- import { Event, CloseEvent, MessageEvent } from 'ws'
7
+ import type { Event, CloseEvent, MessageEvent } from 'ws'
8
8
  import { retry } from '@lifeomic/attempt'
9
+ import { Forbidden, Unauthorized } from '@hocuspocus/common'
9
10
  import EventEmitter from './EventEmitter'
10
11
  import { IncomingMessage } from './IncomingMessage'
11
12
  import { MessageReceiver } from './MessageReceiver'
@@ -18,7 +19,8 @@ import { AwarenessMessage } from './OutgoingMessages/AwarenessMessage'
18
19
  import { UpdateMessage } from './OutgoingMessages/UpdateMessage'
19
20
  import { OutgoingMessage } from './OutgoingMessage'
20
21
  import awarenessStatesToArray from './utils/awarenessStatesToArray'
21
- import { ConstructableOutgoingMessage } from './types'
22
+ import { ConstructableOutgoingMessage, StatesArray } from './types'
23
+ import { onAwarenessChangeParameters, onAwarenessUpdateParameters } from '.'
22
24
 
23
25
  export enum WebSocketStatus {
24
26
  Connecting = 'connecting',
@@ -26,15 +28,19 @@ export enum WebSocketStatus {
26
28
  Disconnected = 'disconnected',
27
29
  }
28
30
 
29
- export interface HocuspocusProviderOptions {
31
+ export type HocuspocusProviderConfiguration =
32
+ Required<Pick<CompleteHocuspocusProviderConfiguration, 'url' | 'name'>>
33
+ & Partial<CompleteHocuspocusProviderConfiguration>
34
+
35
+ export interface CompleteHocuspocusProviderConfiguration {
30
36
  /**
31
37
  * URL of your @hocuspocus/server instance
32
38
  */
33
- url: string,
34
- /**
35
- * The identifier/name of your document
36
- */
37
- name: string,
39
+ url: string,
40
+ /**
41
+ * The identifier/name of your document
42
+ */
43
+ name: string,
38
44
  /**
39
45
  * The actual Y.js document
40
46
  */
@@ -110,23 +116,27 @@ export interface HocuspocusProviderOptions {
110
116
  onMessage: (event: MessageEvent) => void,
111
117
  onOutgoingMessage: (message: OutgoingMessage) => void,
112
118
  onStatus: (status: any) => void,
113
- onSynced: () => void,
119
+ onSynced: ({ state }: { state: boolean }) => void,
114
120
  onDisconnect: (event: CloseEvent) => void,
115
121
  onClose: (event: CloseEvent) => void,
116
122
  onDestroy: () => void,
117
- onAwarenessUpdate: (states: any) => void,
118
- onAwarenessChange: (states: any) => void,
123
+ onAwarenessUpdate: ({ states }: onAwarenessUpdateParameters) => void,
124
+ onAwarenessChange: ({ states }: onAwarenessChangeParameters) => void,
125
+ /**
126
+ * Don’t output any warnings.
127
+ */
128
+ quiet: boolean,
119
129
  }
120
130
 
121
131
  export class HocuspocusProvider extends EventEmitter {
122
- public options: HocuspocusProviderOptions = {
132
+ public configuration: CompleteHocuspocusProviderConfiguration = {
133
+ name: '',
134
+ url: '',
123
135
  // @ts-ignore
124
136
  document: undefined,
125
137
  // @ts-ignore
126
138
  awareness: undefined,
127
139
  WebSocketPolyfill: undefined,
128
- url: '',
129
- name: '',
130
140
  token: null,
131
141
  parameters: {},
132
142
  connect: true,
@@ -163,6 +173,7 @@ export class HocuspocusProvider extends EventEmitter {
163
173
  onDestroy: () => null,
164
174
  onAwarenessUpdate: () => null,
165
175
  onAwarenessChange: () => null,
176
+ quiet: false,
166
177
  }
167
178
 
168
179
  subscribedToBroadcastChannel = false
@@ -191,26 +202,27 @@ export class HocuspocusProvider extends EventEmitter {
191
202
  reject: (reason?: any) => void
192
203
  } | null = null
193
204
 
194
- constructor(options: Partial<HocuspocusProviderOptions> = {}) {
205
+ constructor(configuration: HocuspocusProviderConfiguration) {
195
206
  super()
196
- this.setOptions(options)
197
-
198
- this.options.awareness = options.awareness ? options.awareness : new Awareness(this.document)
199
- this.options.WebSocketPolyfill = options.WebSocketPolyfill ? options.WebSocketPolyfill : WebSocket
200
-
201
- this.on('open', this.options.onOpen)
202
- this.on('authenticated', this.options.onAuthenticated)
203
- this.on('authenticationFailed', this.options.onAuthenticationFailed)
204
- this.on('connect', this.options.onConnect)
205
- this.on('message', this.options.onMessage)
206
- this.on('outgoingMessage', this.options.onOutgoingMessage)
207
- this.on('synced', this.options.onSynced)
208
- this.on('status', this.options.onStatus)
209
- this.on('disconnect', this.options.onDisconnect)
210
- this.on('close', this.options.onClose)
211
- this.on('destroy', this.options.onDestroy)
212
- this.on('awarenessUpdate', this.options.onAwarenessUpdate)
213
- this.on('awarenessChange', this.options.onAwarenessChange)
207
+ this.setConfiguration(configuration)
208
+
209
+ this.configuration.document = configuration.document ? configuration.document : new Y.Doc()
210
+ this.configuration.awareness = configuration.awareness ? configuration.awareness : new Awareness(this.document)
211
+ this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill ? configuration.WebSocketPolyfill : WebSocket
212
+
213
+ this.on('open', this.configuration.onOpen)
214
+ this.on('authenticated', this.configuration.onAuthenticated)
215
+ this.on('authenticationFailed', this.configuration.onAuthenticationFailed)
216
+ this.on('connect', this.configuration.onConnect)
217
+ this.on('message', this.configuration.onMessage)
218
+ this.on('outgoingMessage', this.configuration.onOutgoingMessage)
219
+ this.on('synced', this.configuration.onSynced)
220
+ this.on('status', this.configuration.onStatus)
221
+ this.on('disconnect', this.configuration.onDisconnect)
222
+ this.on('close', this.configuration.onClose)
223
+ this.on('destroy', this.configuration.onDestroy)
224
+ this.on('awarenessUpdate', this.configuration.onAwarenessUpdate)
225
+ this.on('awarenessChange', this.configuration.onAwarenessChange)
214
226
 
215
227
  this.awareness.on('update', () => {
216
228
  this.emit('awarenessUpdate', { states: awarenessStatesToArray(this.awareness.getStates()) })
@@ -222,22 +234,22 @@ export class HocuspocusProvider extends EventEmitter {
222
234
 
223
235
  this.document.on('update', this.documentUpdateHandler.bind(this))
224
236
  this.awareness.on('update', this.awarenessUpdateHandler.bind(this))
225
- this.registerBeforeUnloadEventListener()
237
+ this.registerEventListeners()
226
238
 
227
239
  this.intervals.connectionChecker = setInterval(
228
240
  this.checkConnection.bind(this),
229
- this.options.messageReconnectTimeout / 10,
241
+ this.configuration.messageReconnectTimeout / 10,
230
242
  )
231
243
 
232
- if (this.options.forceSyncInterval) {
244
+ if (this.configuration.forceSyncInterval) {
233
245
  this.intervals.forceSync = setInterval(
234
246
  this.forceSync.bind(this),
235
- this.options.forceSyncInterval,
247
+ this.configuration.forceSyncInterval,
236
248
  )
237
249
  }
238
250
 
239
- if (typeof options.connect !== 'undefined') {
240
- this.shouldConnect = options.connect
251
+ if (typeof configuration.connect !== 'undefined') {
252
+ this.shouldConnect = configuration.connect
241
253
  }
242
254
 
243
255
  if (!this.shouldConnect) {
@@ -247,8 +259,8 @@ export class HocuspocusProvider extends EventEmitter {
247
259
  this.connect()
248
260
  }
249
261
 
250
- public setOptions(options: Partial<HocuspocusProviderOptions> = {}): void {
251
- this.options = { ...this.options, ...options }
262
+ public setConfiguration(configuration: Partial<HocuspocusProviderConfiguration> = {}): void {
263
+ this.configuration = { ...this.configuration, ...configuration }
252
264
  }
253
265
 
254
266
  async connect() {
@@ -261,14 +273,14 @@ export class HocuspocusProvider extends EventEmitter {
261
273
 
262
274
  try {
263
275
  await retry(this.createWebSocketConnection.bind(this), {
264
- delay: this.options.delay,
265
- initialDelay: this.options.initialDelay,
266
- factor: this.options.factor,
267
- maxAttempts: this.options.maxAttempts,
268
- minDelay: this.options.minDelay,
269
- maxDelay: this.options.maxDelay,
270
- jitter: this.options.jitter,
271
- timeout: this.options.timeout,
276
+ delay: this.configuration.delay,
277
+ initialDelay: this.configuration.initialDelay,
278
+ factor: this.configuration.factor,
279
+ maxAttempts: this.configuration.maxAttempts,
280
+ minDelay: this.configuration.minDelay,
281
+ maxDelay: this.configuration.maxDelay,
282
+ jitter: this.configuration.jitter,
283
+ timeout: this.configuration.timeout,
272
284
  beforeAttempt: context => {
273
285
  if (!this.shouldConnect) {
274
286
  context.abort()
@@ -287,7 +299,7 @@ export class HocuspocusProvider extends EventEmitter {
287
299
  createWebSocketConnection() {
288
300
  return new Promise((resolve, reject) => {
289
301
  // Init the WebSocket connection
290
- const ws = new this.options.WebSocketPolyfill(this.url)
302
+ const ws = new this.configuration.WebSocketPolyfill(this.url)
291
303
  ws.binaryType = 'arraybuffer'
292
304
  ws.onmessage = this.onMessage.bind(this)
293
305
  ws.onclose = this.onClose.bind(this)
@@ -321,11 +333,11 @@ export class HocuspocusProvider extends EventEmitter {
321
333
  }
322
334
 
323
335
  get document() {
324
- return this.options.document
336
+ return this.configuration.document
325
337
  }
326
338
 
327
339
  get awareness() {
328
- return this.options.awareness
340
+ return this.configuration.awareness
329
341
  }
330
342
 
331
343
  checkConnection() {
@@ -340,7 +352,7 @@ export class HocuspocusProvider extends EventEmitter {
340
352
  }
341
353
 
342
354
  // Don’t close the connection when a message was received recently
343
- if (this.options.messageReconnectTimeout >= time.getUnixTime() - this.lastMessageReceived) {
355
+ if (this.configuration.messageReconnectTimeout >= time.getUnixTime() - this.lastMessageReceived) {
344
356
  return
345
357
  }
346
358
 
@@ -357,11 +369,12 @@ export class HocuspocusProvider extends EventEmitter {
357
369
  this.send(SyncStepOneMessage, { document: this.document })
358
370
  }
359
371
 
360
- registerBeforeUnloadEventListener() {
372
+ registerEventListeners() {
361
373
  if (typeof window === 'undefined') {
362
374
  return
363
375
  }
364
376
 
377
+ window.addEventListener('online', this.connect.bind(this))
365
378
  window.addEventListener('beforeunload', () => {
366
379
  removeAwarenessStates(this.awareness, [this.document.clientID], 'window unload')
367
380
  })
@@ -399,17 +412,17 @@ export class HocuspocusProvider extends EventEmitter {
399
412
 
400
413
  // Ensure that the URL always ends with /
401
414
  get serverUrl() {
402
- while (this.options.url[this.options.url.length - 1] === '/') {
403
- return this.options.url.slice(0, this.options.url.length - 1)
415
+ while (this.configuration.url[this.configuration.url.length - 1] === '/') {
416
+ return this.configuration.url.slice(0, this.configuration.url.length - 1)
404
417
  }
405
418
 
406
- return this.options.url
419
+ return this.configuration.url
407
420
  }
408
421
 
409
422
  get url() {
410
- const encodedParams = url.encodeQueryParams(this.options.parameters)
423
+ const encodedParams = url.encodeQueryParams(this.configuration.parameters)
411
424
 
412
- return `${this.serverUrl}/${this.options.name}${encodedParams.length === 0 ? '' : `?${encodedParams}`}`
425
+ return `${this.serverUrl}/${this.configuration.name}${encodedParams.length === 0 ? '' : `?${encodedParams}`}`
413
426
  }
414
427
 
415
428
  get synced(): boolean {
@@ -427,7 +440,7 @@ export class HocuspocusProvider extends EventEmitter {
427
440
  }
428
441
 
429
442
  get isAuthenticationRequired(): boolean {
430
- return !!this.options.token && !this.isAuthenticated
443
+ return !!this.configuration.token && !this.isAuthenticated
431
444
  }
432
445
 
433
446
  disconnect() {
@@ -454,12 +467,12 @@ export class HocuspocusProvider extends EventEmitter {
454
467
  }
455
468
 
456
469
  async getToken() {
457
- if (typeof this.options.token === 'function') {
458
- const token = await this.options.token()
470
+ if (typeof this.configuration.token === 'function') {
471
+ const token = await this.configuration.token()
459
472
  return token
460
473
  }
461
474
 
462
- return this.options.token
475
+ return this.configuration.token
463
476
  }
464
477
 
465
478
  async webSocketConnectionEstablished() {
@@ -533,15 +546,29 @@ export class HocuspocusProvider extends EventEmitter {
533
546
  this.emit('disconnect', { event })
534
547
  }
535
548
 
549
+ if (event.code === Unauthorized.code) {
550
+ if (!this.configuration.quiet) {
551
+ console.warn('[HocuspocusProvider] An authentication token is required, but you didn’t send one. Try adding a `token` to your HocuspocusProvider configuration. Won’t try again.')
552
+ }
553
+
554
+ this.shouldConnect = false
555
+ }
556
+
557
+ if (event.code === Forbidden.code) {
558
+ if (!this.configuration.quiet) {
559
+ console.warn('[HocuspocusProvider] The provided authentication token isn’t allowed to connect to this server. Will try again.')
560
+ }
561
+ }
562
+
536
563
  if (this.connectionAttempt) {
537
- // Okay, that connection attempt failed
564
+ // That connection attempt failed.
538
565
  this.rejectConnectionAttempt()
539
566
  } else if (this.shouldConnect) {
540
- // The connection was closed by the server, so let’s just try again.
567
+ // The connection was closed by the server. Let’s just try again.
541
568
  this.connect()
542
569
  }
543
570
 
544
- // If we’ll reconnect anyway, we’re done for now.
571
+ // If we’ll reconnect, we’re done for now.
545
572
  if (this.shouldConnect) {
546
573
  return
547
574
  }
@@ -579,10 +606,16 @@ export class HocuspocusProvider extends EventEmitter {
579
606
  this.document.off('update', this.documentUpdateHandler)
580
607
 
581
608
  this.removeAllListeners()
609
+
610
+ if (typeof window === 'undefined') {
611
+ return
612
+ }
613
+
614
+ window.removeEventListener('online', this.connect.bind(this))
582
615
  }
583
616
 
584
617
  get broadcastChannel() {
585
- return `${this.serverUrl}/${this.options.name}`
618
+ return `${this.serverUrl}/${this.configuration.name}`
586
619
  }
587
620
 
588
621
  broadcastChannelSubscriber(data: ArrayBuffer) {
@@ -623,7 +656,7 @@ export class HocuspocusProvider extends EventEmitter {
623
656
  }
624
657
 
625
658
  broadcast(Message: ConstructableOutgoingMessage, args?: any) {
626
- if (!this.options.broadcast) {
659
+ if (!this.configuration.broadcast) {
627
660
  return
628
661
  }
629
662
 
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './HocuspocusProvider'
2
+ export * from './HocuspocusCloudProvider'
2
3
  export * from './types'
3
4
  export * from './utils'
package/src/types.ts CHANGED
@@ -41,3 +41,13 @@ export type ConstructableOutgoingMessage =
41
41
  Constructable<SyncStepOneMessage> |
42
42
  Constructable<SyncStepTwoMessage> |
43
43
  Constructable<UpdateMessage>
44
+
45
+ export type onAwarenessUpdateParameters = {
46
+ states: StatesArray
47
+ }
48
+
49
+ export type onAwarenessChangeParameters = {
50
+ states: StatesArray
51
+ }
52
+
53
+ export type StatesArray = { clientId: number, [key: string | number]: any }[]
@@ -1,4 +0,0 @@
1
- import { CloseEvent } from './types';
2
- export declare const Forbidden: CloseEvent;
3
- export declare const ResetConnection: CloseEvent;
4
- export declare const CloseEvents: CloseEvent[];