extensions.js

 1// src/ffi/extensions.js
 2// This file exports the TipTap extensions configuration.
 3
 4import StarterKit from "@tiptap/starter-kit";
 5import { Waypoint } from "./waypoint";
 6import { Collaboration } from "@tiptap/extension-collaboration";
 7import { IndexeddbPersistence } from "y-indexeddb";
 8import { createYjsProvider } from "@y-sweet/client";
 9
10/**
11 * Configure the editor extensions in JS and use Rescript interop
12 * @param {import('yjs').Doc} doc - The Yjs document instance from the yjs library
13 * @param {string} id - The document ID
14 * @returns {Array<import('@tiptap/core').Extension>}
15 */
16export const extensions = (doc, id) => {
17  // Skip IndexeddbPersistence and Y-sweet provider in test environment
18  // where indexedDB is not available
19  const isTestEnvironment =
20    typeof process !== "undefined" && process.env && process.env.VITEST;
21
22  const authEndpoint = (docID) => async () => {
23    const res = await fetch(`/api/ws/auth/${docID}`, {
24      credentials: "include",
25    });
26    if (!res.ok) {
27      console.debug("auth reponse failed", res);
28      if (res.status === 401 || res.status === 403) {
29        window.location.href = "/login";
30        throw new Error("Unauthorized");
31      }
32      throw new Error(`Auth failed: ${res.status}`);
33    }
34    return res.json(); // { url, baseUrl, docId }
35  };
36
37  if (!isTestEnvironment) {
38    new IndexeddbPersistence(id, doc);
39    const provider = createYjsProvider(doc, id, authEndpoint(id), { showDebuggerLink: false });
40    provider.on('connection-status', (status) => {
41      document.dispatchEvent(new CustomEvent('ysweet-connection-status', { detail: status }));
42    });
43    provider.on('local-changes', (hasChanges) => {
44      document.dispatchEvent(new CustomEvent('ysweet-local-changes', { detail: hasChanges }));
45    });
46    // createYjsProvider(
47    //   doc,
48    //   id,
49    //   () => new Promise((resolve) => resolve({url: `ws://127.0.0.1:8080/ws`, baseUrl: "http://127.0.0.1:8080", docId: id})),
50    //   {showDebuggerLink: false},
51    // );
52  }
53
54  return [
55    StarterKit.configure({
56      undoRedo: false,
57    }),
58    Collaboration.configure({
59      document: doc,
60      field: "main",
61    }),
62    Waypoint,
63  ];
64};