@defensestation/ysync-go 0.1.0-dev.12.d04ad84

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 (38) hide show
  1. package/README.md +145 -0
  2. package/dist/client/connect-yjs-provider.d.ts +107 -0
  3. package/dist/client/connect-yjs-provider.d.ts.map +1 -0
  4. package/dist/client/connect-yjs-provider.js +333 -0
  5. package/dist/client/connect-yjs-provider.js.map +1 -0
  6. package/dist/client/id.d.ts +2 -0
  7. package/dist/client/id.d.ts.map +1 -0
  8. package/dist/client/id.js +21 -0
  9. package/dist/client/id.js.map +1 -0
  10. package/dist/client/provider-status.d.ts +8 -0
  11. package/dist/client/provider-status.d.ts.map +1 -0
  12. package/dist/client/provider-status.js +2 -0
  13. package/dist/client/provider-status.js.map +1 -0
  14. package/dist/client/websocket-yjs-provider.d.ts +51 -0
  15. package/dist/client/websocket-yjs-provider.d.ts.map +1 -0
  16. package/dist/client/websocket-yjs-provider.js +270 -0
  17. package/dist/client/websocket-yjs-provider.js.map +1 -0
  18. package/dist/compaction/cli.d.ts +3 -0
  19. package/dist/compaction/cli.d.ts.map +1 -0
  20. package/dist/compaction/cli.js +124 -0
  21. package/dist/compaction/cli.js.map +1 -0
  22. package/dist/compaction/compaction.d.ts +67 -0
  23. package/dist/compaction/compaction.d.ts.map +1 -0
  24. package/dist/compaction/compaction.js +153 -0
  25. package/dist/compaction/compaction.js.map +1 -0
  26. package/dist/compaction/index.d.ts +3 -0
  27. package/dist/compaction/index.d.ts.map +1 -0
  28. package/dist/compaction/index.js +2 -0
  29. package/dist/compaction/index.js.map +1 -0
  30. package/dist/gen/ysync/v1/sync_pb.d.ts +630 -0
  31. package/dist/gen/ysync/v1/sync_pb.d.ts.map +1 -0
  32. package/dist/gen/ysync/v1/sync_pb.js +133 -0
  33. package/dist/gen/ysync/v1/sync_pb.js.map +1 -0
  34. package/dist/index.d.ts +8 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +5 -0
  37. package/dist/index.js.map +1 -0
  38. package/package.json +70 -0
@@ -0,0 +1,153 @@
1
+ // Compaction adapter for ysync-go servers.
2
+ //
3
+ // The server's update log grows until the host folds it (see the repository
4
+ // README's Compaction section). This module implements the recommended
5
+ // policy — once a document exceeds `threshold` log records, fold everything
6
+ // except the newest `keep` records into one snapshot — using **real Yjs** to
7
+ // build the snapshot. That matters: Go-side merges corrupt documents with
8
+ // nested XML content (BlockNote, ProseMirror, Tiptap); see
9
+ // adapters/yjs/ygo/README.md and its xmlrepro/ cross-implementation check.
10
+ //
11
+ // The functions are runtime-agnostic on purpose: call `compactDocuments`
12
+ // from an AWS Lambda handler, a Cloud Run job, a Kubernetes CronJob (the
13
+ // bundled `ysync-compact` CLI), or any Node 18+ process with `fetch`.
14
+ //
15
+ // Security: `CompactDocument` rewrites stored history, so gate it with
16
+ // `Authz.CanCompact` on the server and give **only** this job's identity
17
+ // that permission. Pass the credential via `headers`.
18
+ import * as Y from "yjs";
19
+ const DEFAULT_THRESHOLD = 200;
20
+ const DEFAULT_KEEP = 50;
21
+ /**
22
+ * Compacts one document if its update log exceeds the policy threshold:
23
+ * lists the stored log, replays all but the newest `keep` records into a
24
+ * fresh Y.Doc, encodes the state with `Y.encodeStateAsUpdate`, and calls
25
+ * `CompactDocument` for the covered sequence. Idempotent — re-running
26
+ * converges to the same folded log, and updates pushed concurrently are
27
+ * unaffected (they sort after `compactThroughSequence`).
28
+ */
29
+ export async function compactDocument(options, docId) {
30
+ if (!docId) {
31
+ throw new Error("docId is required");
32
+ }
33
+ const threshold = options.threshold ?? DEFAULT_THRESHOLD;
34
+ const keep = options.keep ?? DEFAULT_KEEP;
35
+ if (threshold < 1 || keep < 0) {
36
+ throw new Error(`invalid policy: threshold ${threshold}, keep ${keep}`);
37
+ }
38
+ const listed = (await rpc(options, "ListDocumentUpdates", { docId }));
39
+ const updates = listed.updates ?? [];
40
+ const skip = {
41
+ docId,
42
+ compacted: false,
43
+ records: updates.length,
44
+ };
45
+ if (updates.length <= threshold) {
46
+ return skip;
47
+ }
48
+ // Records arrive in sequence order; the first may already be a snapshot
49
+ // from a prior run. Folding only that snapshot again would be a no-op.
50
+ const cutoff = updates.length - keep;
51
+ if (cutoff < 1 || (cutoff === 1 && updates[0]?.isSnapshot)) {
52
+ return skip;
53
+ }
54
+ const target = updates[cutoff - 1];
55
+ if (target?.sequence === undefined) {
56
+ throw new Error(`${docId}: log record ${cutoff - 1} has no sequence`);
57
+ }
58
+ const doc = new Y.Doc();
59
+ for (const record of updates.slice(0, cutoff)) {
60
+ if (record.yjsUpdate) {
61
+ Y.applyUpdate(doc, fromBase64(record.yjsUpdate));
62
+ }
63
+ }
64
+ const snapshot = Y.encodeStateAsUpdate(doc);
65
+ doc.destroy();
66
+ await rpc(options, "CompactDocument", {
67
+ docId,
68
+ compactUpdate: toBase64(snapshot),
69
+ compactThroughSequence: target.sequence,
70
+ });
71
+ return {
72
+ docId,
73
+ compacted: true,
74
+ records: updates.length,
75
+ foldedRecords: cutoff,
76
+ foldedThroughSequence: String(target.sequence),
77
+ snapshotBytes: snapshot.byteLength,
78
+ };
79
+ }
80
+ /**
81
+ * Compacts many documents sequentially (compaction is background work;
82
+ * predictable server load beats speed here). Per-document failures are
83
+ * collected in `errors` instead of aborting the run.
84
+ */
85
+ export async function compactDocuments(options, docIds) {
86
+ const run = {
87
+ results: [],
88
+ errors: [],
89
+ compacted: 0,
90
+ skipped: 0,
91
+ };
92
+ for (const docId of docIds) {
93
+ try {
94
+ const result = await compactDocument(options, docId);
95
+ run.results.push(result);
96
+ if (result.compacted) {
97
+ run.compacted++;
98
+ }
99
+ else {
100
+ run.skipped++;
101
+ }
102
+ }
103
+ catch (error) {
104
+ run.errors.push({ docId, error });
105
+ }
106
+ }
107
+ return run;
108
+ }
109
+ /** Plain Connect JSON: POST /<service>/<method> with a JSON body. */
110
+ async function rpc(options, method, body) {
111
+ const headers = typeof options.headers === "function"
112
+ ? await options.headers()
113
+ : (options.headers ?? {});
114
+ const doFetch = options.fetch ?? globalThis.fetch;
115
+ const base = options.baseUrl.replace(/\/+$/, "");
116
+ const response = await doFetch(`${base}/ysync.v1.YjsSyncService/${method}`, {
117
+ method: "POST",
118
+ headers: { "content-type": "application/json", ...headers },
119
+ body: JSON.stringify(body),
120
+ });
121
+ if (!response.ok) {
122
+ const detail = await response.text().catch(() => "");
123
+ throw new Error(`${method}: HTTP ${response.status}${detail ? `: ${detail}` : ""}`);
124
+ }
125
+ return response.json();
126
+ }
127
+ function nodeBuffer() {
128
+ return globalThis.Buffer;
129
+ }
130
+ function toBase64(bytes) {
131
+ const buffer = nodeBuffer();
132
+ if (buffer) {
133
+ return buffer.from(bytes).toString("base64");
134
+ }
135
+ let binary = "";
136
+ for (const byte of bytes) {
137
+ binary += String.fromCharCode(byte);
138
+ }
139
+ return btoa(binary);
140
+ }
141
+ function fromBase64(encoded) {
142
+ const buffer = nodeBuffer();
143
+ if (buffer) {
144
+ return Uint8Array.from(buffer.from(encoded, "base64"));
145
+ }
146
+ const binary = atob(encoded);
147
+ const out = new Uint8Array(binary.length);
148
+ for (let i = 0; i < binary.length; i++) {
149
+ out[i] = binary.charCodeAt(i);
150
+ }
151
+ return out;
152
+ }
153
+ //# sourceMappingURL=compaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../src/compaction/compaction.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,4EAA4E;AAC5E,6EAA6E;AAC7E,0EAA0E;AAC1E,2DAA2D;AAC3D,2EAA2E;AAC3E,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,sEAAsE;AACtE,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,sDAAsD;AACtD,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAgEzB,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA+B,EAC/B,KAAa;IAEb,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,iBAAiB,CAAC;IACzD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,YAAY,CAAC;IAC1C,IAAI,SAAS,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,6BAA6B,SAAS,UAAU,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,OAAO,EAAE,qBAAqB,EAAE,EAAE,KAAK,EAAE,CAAC,CAEnE,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IACrC,MAAM,IAAI,GAA0B;QAClC,KAAK;QACL,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,OAAO,CAAC,MAAM;KACxB,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,wEAAwE;IACxE,uEAAuE;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IACrC,IAAI,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnC,IAAI,MAAM,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,gBAAgB,MAAM,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;IACxB,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;QAC9C,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC5C,GAAG,CAAC,OAAO,EAAE,CAAC;IAEd,MAAM,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE;QACpC,KAAK;QACL,aAAa,EAAE,QAAQ,CAAC,QAAQ,CAAC;QACjC,sBAAsB,EAAE,MAAM,CAAC,QAAQ;KACxC,CAAC,CAAC;IACH,OAAO;QACL,KAAK;QACL,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,OAAO,CAAC,MAAM;QACvB,aAAa,EAAE,MAAM;QACrB,qBAAqB,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC9C,aAAa,EAAE,QAAQ,CAAC,UAAU;KACnC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAA+B,EAC/B,MAAwB;IAExB,MAAM,GAAG,GAAwB;QAC/B,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;KACX,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACrD,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzB,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACrB,GAAG,CAAC,SAAS,EAAE,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,OAAO,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qEAAqE;AACrE,KAAK,UAAU,GAAG,CAChB,OAAgC,EAChC,MAAc,EACd,IAAa;IAEb,MAAM,OAAO,GACX,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU;QACnC,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE;QACzB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,IAAI,4BAA4B,MAAM,EAAE,EAAE;QAC1E,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,EAAE;QAC3D,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,UAAU,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAUD,SAAS,UAAU;IACjB,OAAQ,UAAsC,CAAC,MAAM,CAAC;AACxD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAiB;IACjC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,UAAU,CAAC,OAAe;IACjC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { compactDocument, compactDocuments } from "./compaction.js";
2
+ export type { CompactionClientOptions, CompactionPolicy, CompactDocumentOptions, CompactDocumentResult, CompactionRunResult, } from "./compaction.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compaction/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACpE,YAAY,EACV,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { compactDocument, compactDocuments } from "./compaction.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/compaction/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}