@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,51 @@
1
+ import { Awareness } from "y-protocols/awareness";
2
+ import * as Y from "yjs";
3
+ import type { YjsProviderIdentity, YjsProviderIdentityListener, YjsProviderStatus, YjsProviderStatusListener } from "./provider-status.js";
4
+ export interface WebSocketYjsProviderOptions {
5
+ ydoc: Y.Doc;
6
+ docId: string;
7
+ url?: string;
8
+ baseUrl?: string;
9
+ clientId?: string;
10
+ user: {
11
+ name: string;
12
+ color?: string;
13
+ };
14
+ reconnectInitialDelayMs?: number;
15
+ reconnectMaxDelayMs?: number;
16
+ awarenessThrottleMs?: number;
17
+ }
18
+ export declare class WebSocketYjsProvider {
19
+ readonly awareness: Awareness;
20
+ readonly clientId: string;
21
+ private readonly options;
22
+ private socket?;
23
+ private pending;
24
+ private reconnectTimer?;
25
+ private awarenessSendTimer?;
26
+ private awarenessDirty;
27
+ private reconnectDelayMs;
28
+ private destroyed;
29
+ private currentStatus;
30
+ private readonly statusListeners;
31
+ private currentIdentity?;
32
+ private readonly identityListeners;
33
+ private readonly yjsUpdateHandler;
34
+ private readonly awarenessUpdateHandler;
35
+ constructor(options: WebSocketYjsProviderOptions);
36
+ get status(): YjsProviderStatus;
37
+ get identity(): YjsProviderIdentity | undefined;
38
+ onIdentity(listener: YjsProviderIdentityListener): () => void;
39
+ private applyIdentity;
40
+ onStatus(listener: YjsProviderStatusListener): () => void;
41
+ private setStatus;
42
+ destroy(): void;
43
+ private connect;
44
+ private scheduleReconnect;
45
+ private send;
46
+ private sendNow;
47
+ private scheduleAwarenessSend;
48
+ private sendLocalAwarenessNow;
49
+ private applyMessage;
50
+ }
51
+ //# sourceMappingURL=websocket-yjs-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-yjs-provider.d.ts","sourceRoot":"","sources":["../../src/client/websocket-yjs-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA+C,MAAM,uBAAuB,CAAC;AAC/F,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAsB3I,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,oBAAoB;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAMM;IAC9B,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,cAAc,CAAC,CAAgC;IACvD,OAAO,CAAC,kBAAkB,CAAC,CAAgC;IAC3D,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAwC;IACxE,OAAO,CAAC,eAAe,CAAC,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0C;IAE5E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAU/B;IAKF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAUrC;gBAEU,OAAO,EAAE,2BAA2B;IA0BhD,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAID,IAAI,QAAQ,IAAI,mBAAmB,GAAG,SAAS,CAE9C;IAGD,UAAU,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM,IAAI;IAK7D,OAAO,CAAC,aAAa;IAYrB,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,GAAG,MAAM,IAAI;IAKzD,OAAO,CAAC,SAAS;IAMjB,OAAO;IA2BP,OAAO,CAAC,OAAO;IAyCf,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,YAAY;CAqBrB"}
@@ -0,0 +1,270 @@
1
+ import { Awareness, applyAwarenessUpdate, encodeAwarenessUpdate } from "y-protocols/awareness";
2
+ import * as Y from "yjs";
3
+ import { makeClientId } from "./id.js";
4
+ const REMOTE_ORIGIN = "websocket-remote";
5
+ const DEFAULT_RECONNECT_INITIAL_DELAY_MS = 500;
6
+ const DEFAULT_RECONNECT_MAX_DELAY_MS = 5000;
7
+ const DEFAULT_AWARENESS_THROTTLE_MS = 150;
8
+ export class WebSocketYjsProvider {
9
+ awareness;
10
+ clientId;
11
+ options;
12
+ socket;
13
+ pending = [];
14
+ reconnectTimer;
15
+ awarenessSendTimer;
16
+ awarenessDirty = false;
17
+ reconnectDelayMs;
18
+ destroyed = false;
19
+ currentStatus = "connecting";
20
+ statusListeners = new Set();
21
+ currentIdentity;
22
+ identityListeners = new Set();
23
+ yjsUpdateHandler = (update, origin) => {
24
+ if (origin === REMOTE_ORIGIN) {
25
+ return;
26
+ }
27
+ this.send({
28
+ type: "yjs_update",
29
+ docId: this.options.docId,
30
+ clientId: this.clientId,
31
+ update: bytesToBase64(update),
32
+ });
33
+ };
34
+ // Only push changes to the LOCAL awareness state. Remote states arrive from
35
+ // the server already fanned out; re-broadcasting them would multiply every
36
+ // cursor move by the number of connected clients.
37
+ awarenessUpdateHandler = ({ added, updated, removed }) => {
38
+ const local = this.awareness.clientID;
39
+ if (!added.includes(local) && !updated.includes(local) && !removed.includes(local)) {
40
+ return;
41
+ }
42
+ this.scheduleAwarenessSend();
43
+ };
44
+ constructor(options) {
45
+ this.options = {
46
+ ...options,
47
+ reconnectInitialDelayMs: options.reconnectInitialDelayMs ?? DEFAULT_RECONNECT_INITIAL_DELAY_MS,
48
+ reconnectMaxDelayMs: options.reconnectMaxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS,
49
+ awarenessThrottleMs: options.awarenessThrottleMs ?? DEFAULT_AWARENESS_THROTTLE_MS,
50
+ };
51
+ this.clientId = options.clientId ?? makeClientId();
52
+ this.reconnectDelayMs = this.options.reconnectInitialDelayMs;
53
+ this.awareness = new Awareness(options.ydoc);
54
+ this.awareness.setLocalStateField("user", {
55
+ name: options.user.name,
56
+ color: options.user.color,
57
+ });
58
+ this.options.ydoc.on("update", this.yjsUpdateHandler);
59
+ // No extra heartbeat timer: y-protocols renews the local awareness state
60
+ // (bumping its clock) roughly every 15s while idle, which fires this
61
+ // handler. A fixed-interval resend of the same clock would be ignored by
62
+ // receivers anyway.
63
+ this.awareness.on("update", this.awarenessUpdateHandler);
64
+ this.connect();
65
+ }
66
+ get status() {
67
+ return this.currentStatus;
68
+ }
69
+ // Server-assigned presence identity; undefined until the join is
70
+ // acknowledged.
71
+ get identity() {
72
+ return this.currentIdentity;
73
+ }
74
+ // Returns an unsubscribe function.
75
+ onIdentity(listener) {
76
+ this.identityListeners.add(listener);
77
+ return () => this.identityListeners.delete(listener);
78
+ }
79
+ applyIdentity(name, color) {
80
+ if (!name && !color)
81
+ return;
82
+ const identity = {
83
+ name: name || this.options.user.name,
84
+ color: color ?? this.options.user.color,
85
+ };
86
+ this.currentIdentity = identity;
87
+ this.awareness.setLocalStateField("user", { name: identity.name, color: identity.color });
88
+ for (const listener of this.identityListeners)
89
+ listener(identity);
90
+ }
91
+ // Returns an unsubscribe function.
92
+ onStatus(listener) {
93
+ this.statusListeners.add(listener);
94
+ return () => this.statusListeners.delete(listener);
95
+ }
96
+ setStatus(status) {
97
+ if (this.currentStatus === status)
98
+ return;
99
+ this.currentStatus = status;
100
+ for (const listener of this.statusListeners)
101
+ listener(status);
102
+ }
103
+ destroy() {
104
+ if (this.destroyed)
105
+ return;
106
+ this.options.ydoc.off("update", this.yjsUpdateHandler);
107
+ this.awareness.off("update", this.awarenessUpdateHandler);
108
+ // Announce departure while the socket is still usable so peers drop the
109
+ // cursor immediately instead of after the 30s awareness timeout.
110
+ this.awareness.setLocalState(null);
111
+ if (this.socket?.readyState === WebSocket.OPEN) {
112
+ this.sendNow({
113
+ type: "awareness_update",
114
+ docId: this.options.docId,
115
+ clientId: this.clientId,
116
+ update: bytesToBase64(encodeAwarenessUpdate(this.awareness, [this.awareness.clientID])),
117
+ });
118
+ this.sendNow({ type: "leave", docId: this.options.docId, clientId: this.clientId });
119
+ }
120
+ this.destroyed = true;
121
+ this.setStatus("disconnected");
122
+ if (this.reconnectTimer) {
123
+ clearTimeout(this.reconnectTimer);
124
+ }
125
+ if (this.awarenessSendTimer) {
126
+ clearTimeout(this.awarenessSendTimer);
127
+ }
128
+ this.socket?.close();
129
+ }
130
+ connect() {
131
+ if (this.destroyed) {
132
+ return;
133
+ }
134
+ this.setStatus("connecting");
135
+ const socket = new WebSocket(this.options.url ?? websocketURL(this.options.baseUrl));
136
+ this.socket = socket;
137
+ socket.addEventListener("open", () => {
138
+ this.setStatus("connected");
139
+ this.reconnectDelayMs = this.options.reconnectInitialDelayMs;
140
+ this.sendNow({
141
+ type: "join",
142
+ docId: this.options.docId,
143
+ clientId: this.clientId,
144
+ stateVector: bytesToBase64(Y.encodeStateVector(this.options.ydoc)),
145
+ userName: this.options.user.name,
146
+ userColor: this.options.user.color,
147
+ });
148
+ this.sendLocalAwarenessNow();
149
+ for (const message of this.pending.splice(0)) {
150
+ this.sendNow(message);
151
+ }
152
+ });
153
+ socket.addEventListener("message", (event) => {
154
+ if (typeof event.data !== "string") {
155
+ return;
156
+ }
157
+ this.applyMessage(JSON.parse(event.data));
158
+ });
159
+ socket.addEventListener("close", () => {
160
+ if (this.socket === socket) {
161
+ this.socket = undefined;
162
+ }
163
+ this.setStatus("disconnected");
164
+ this.scheduleReconnect();
165
+ });
166
+ socket.addEventListener("error", () => {
167
+ socket.close();
168
+ });
169
+ }
170
+ scheduleReconnect() {
171
+ if (this.destroyed || this.reconnectTimer) {
172
+ return;
173
+ }
174
+ const delay = this.reconnectDelayMs;
175
+ this.reconnectDelayMs = Math.min(this.reconnectDelayMs * 2, this.options.reconnectMaxDelayMs);
176
+ this.reconnectTimer = setTimeout(() => {
177
+ this.reconnectTimer = undefined;
178
+ this.connect();
179
+ }, delay);
180
+ }
181
+ send(message) {
182
+ if (this.socket?.readyState === WebSocket.OPEN) {
183
+ this.sendNow(message);
184
+ return;
185
+ }
186
+ this.pending.push(message);
187
+ }
188
+ sendNow(message) {
189
+ this.socket?.send(JSON.stringify(message));
190
+ }
191
+ // Leading + trailing throttle: the first change sends immediately, changes
192
+ // arriving inside the window (e.g. cursor movement while typing or
193
+ // selecting) collapse into one trailing send.
194
+ scheduleAwarenessSend() {
195
+ if (this.destroyed) {
196
+ return;
197
+ }
198
+ if (this.awarenessSendTimer) {
199
+ this.awarenessDirty = true;
200
+ return;
201
+ }
202
+ this.sendLocalAwarenessNow();
203
+ this.awarenessSendTimer = setTimeout(() => {
204
+ this.awarenessSendTimer = undefined;
205
+ if (this.awarenessDirty) {
206
+ this.awarenessDirty = false;
207
+ this.scheduleAwarenessSend();
208
+ }
209
+ }, this.options.awarenessThrottleMs);
210
+ }
211
+ sendLocalAwarenessNow() {
212
+ if (this.destroyed) {
213
+ return;
214
+ }
215
+ this.send({
216
+ type: "awareness_update",
217
+ docId: this.options.docId,
218
+ clientId: this.clientId,
219
+ update: bytesToBase64(encodeAwarenessUpdate(this.awareness, [this.awareness.clientID])),
220
+ });
221
+ }
222
+ applyMessage(message) {
223
+ switch (message.type) {
224
+ case "joined":
225
+ this.applyIdentity(message.userName, message.userColor);
226
+ break;
227
+ case "sync_update":
228
+ case "yjs_update":
229
+ if (message.update) {
230
+ Y.applyUpdate(this.options.ydoc, base64ToBytes(message.update), REMOTE_ORIGIN);
231
+ }
232
+ break;
233
+ case "awareness_update":
234
+ if (message.update) {
235
+ applyAwarenessUpdate(this.awareness, base64ToBytes(message.update), REMOTE_ORIGIN);
236
+ }
237
+ break;
238
+ case "error":
239
+ console.error("Yjs WebSocket server error", message.errorCode, message.errorMessage);
240
+ break;
241
+ }
242
+ }
243
+ }
244
+ function websocketURL(baseUrl) {
245
+ const fallback = typeof window !== "undefined" && window.location?.origin
246
+ ? window.location.origin
247
+ : "http://localhost:8080";
248
+ const url = new URL(baseUrl ?? fallback);
249
+ url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
250
+ url.pathname = "/ysync/ws";
251
+ url.search = "";
252
+ url.hash = "";
253
+ return url.toString();
254
+ }
255
+ function bytesToBase64(bytes) {
256
+ let binary = "";
257
+ for (let i = 0; i < bytes.length; i += 0x8000) {
258
+ binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
259
+ }
260
+ return btoa(binary);
261
+ }
262
+ function base64ToBytes(base64) {
263
+ const binary = atob(base64);
264
+ const bytes = new Uint8Array(binary.length);
265
+ for (let i = 0; i < binary.length; i++) {
266
+ bytes[i] = binary.charCodeAt(i);
267
+ }
268
+ return bytes;
269
+ }
270
+ //# sourceMappingURL=websocket-yjs-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-yjs-provider.js","sourceRoot":"","sources":["../../src/client/websocket-yjs-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/compaction/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+ // ysync-compact: compaction CLI over the programmatic adapter in
3
+ // compaction.ts, for cron-style schedulers (Kubernetes CronJob, systemd
4
+ // timers). Lambda/Cloud Run users should import `compactDocuments` directly.
5
+ //
6
+ // Usage:
7
+ // ysync-compact --base-url http://localhost:8080 --docs doc-1,doc-2
8
+ // ysync-compact --base-url ... --docs - # doc IDs from stdin, one per line
9
+ // ysync-compact --base-url ... --docs ... \
10
+ // [--threshold 200] [--keep 50] \
11
+ // [--header 'authorization: Bearer ...']... [--user-id compact-sidecar]
12
+ //
13
+ // Exits 0 when every document succeeded, 1 when any document failed, 2 on
14
+ // usage errors. Gate the server's Authz.CanCompact to this job's identity.
15
+ import { compactDocuments } from "./compaction.js";
16
+ async function main() {
17
+ let args;
18
+ try {
19
+ args = parseArgs(process.argv.slice(2));
20
+ }
21
+ catch (error) {
22
+ console.error(String(error instanceof Error ? error.message : error));
23
+ return 2;
24
+ }
25
+ if (!args.baseUrl || !args.docs) {
26
+ console.error("usage: ysync-compact --base-url URL --docs id1,id2|- [--threshold N] " +
27
+ "[--keep N] [--header 'name: value']... [--user-id ID]");
28
+ return 2;
29
+ }
30
+ const docIds = args.docs === "-"
31
+ ? (await readStdin()).split("\n").map((line) => line.trim())
32
+ : args.docs.split(",").map((docId) => docId.trim());
33
+ const filtered = docIds.filter((docId) => docId.length > 0);
34
+ if (filtered.length === 0) {
35
+ console.error("no document IDs given");
36
+ return 2;
37
+ }
38
+ const headers = { ...args.headers };
39
+ if (args.userId) {
40
+ // Demo identity hint; real deployments attach identity via auth
41
+ // middleware and pass the credential with --header instead.
42
+ headers["x-user-id"] = args.userId;
43
+ }
44
+ const run = await compactDocuments({
45
+ baseUrl: args.baseUrl,
46
+ headers,
47
+ threshold: args.threshold === undefined ? undefined : parseCount("--threshold", args.threshold),
48
+ keep: args.keep === undefined ? undefined : parseCount("--keep", args.keep),
49
+ }, filtered);
50
+ for (const result of run.results) {
51
+ if (result.compacted) {
52
+ console.log(`${result.docId}: folded ${result.foldedRecords}/${result.records} records ` +
53
+ `through sequence ${result.foldedThroughSequence} into a ` +
54
+ `${result.snapshotBytes}-byte snapshot`);
55
+ }
56
+ else {
57
+ console.log(`${result.docId}: ${result.records} records, nothing to do`);
58
+ }
59
+ }
60
+ for (const failure of run.errors) {
61
+ console.error(`${failure.docId}: ${String(failure.error)}`);
62
+ }
63
+ return run.errors.length > 0 ? 1 : 0;
64
+ }
65
+ function parseArgs(argv) {
66
+ const args = { headers: {} };
67
+ for (let i = 0; i < argv.length; i++) {
68
+ const flag = argv[i];
69
+ const value = argv[i + 1];
70
+ if (!flag.startsWith("--") || value === undefined) {
71
+ throw new Error(`unexpected argument: ${flag}`);
72
+ }
73
+ i++;
74
+ switch (flag) {
75
+ case "--base-url":
76
+ args.baseUrl = value;
77
+ break;
78
+ case "--docs":
79
+ args.docs = value;
80
+ break;
81
+ case "--threshold":
82
+ args.threshold = value;
83
+ break;
84
+ case "--keep":
85
+ args.keep = value;
86
+ break;
87
+ case "--user-id":
88
+ args.userId = value;
89
+ break;
90
+ case "--header": {
91
+ const colon = value.indexOf(":");
92
+ if (colon < 1) {
93
+ throw new Error(`--header expects 'name: value', got ${JSON.stringify(value)}`);
94
+ }
95
+ args.headers[value.slice(0, colon).trim()] = value.slice(colon + 1).trim();
96
+ break;
97
+ }
98
+ default:
99
+ throw new Error(`unknown flag: ${flag}`);
100
+ }
101
+ }
102
+ return args;
103
+ }
104
+ function parseCount(flag, value) {
105
+ const parsed = Number(value);
106
+ if (!Number.isInteger(parsed) || parsed < 0) {
107
+ throw new Error(`${flag} expects a non-negative integer, got ${JSON.stringify(value)}`);
108
+ }
109
+ return parsed;
110
+ }
111
+ function readStdin() {
112
+ return new Promise((resolve, reject) => {
113
+ let data = "";
114
+ process.stdin.setEncoding("utf8");
115
+ process.stdin.on("data", (chunk) => (data += chunk));
116
+ process.stdin.on("end", () => resolve(data));
117
+ process.stdin.on("error", reject);
118
+ });
119
+ }
120
+ main().then((code) => process.exit(code), (error) => {
121
+ console.error(String(error));
122
+ process.exit(1);
123
+ });
124
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/compaction/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /** How to reach the ysync server and authenticate against it. */
2
+ export interface CompactionClientOptions {
3
+ /** Server base URL, e.g. "http://localhost:8080". */
4
+ baseUrl: string;
5
+ /**
6
+ * Extra request headers (an authenticated identity that passes
7
+ * `Authz.CanCompact`). A function is awaited per request, so short-lived
8
+ * tokens can be refreshed.
9
+ */
10
+ headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
11
+ /** Override the fetch implementation (tests, custom agents). */
12
+ fetch?: typeof globalThis.fetch;
13
+ }
14
+ /** When and how much to fold. Zero-config defaults match examples/compact-docs. */
15
+ export interface CompactionPolicy {
16
+ /**
17
+ * Compact only when the document has more than this many log records
18
+ * (snapshot record included). Default 200.
19
+ */
20
+ threshold?: number;
21
+ /**
22
+ * Newest records to keep individually attributed for change history.
23
+ * Default 50.
24
+ */
25
+ keep?: number;
26
+ }
27
+ export interface CompactDocumentOptions extends CompactionClientOptions, CompactionPolicy {
28
+ }
29
+ export interface CompactDocumentResult {
30
+ docId: string;
31
+ /** False when the log was at or below the threshold (nothing folded). */
32
+ compacted: boolean;
33
+ /** Log records before compaction. */
34
+ records: number;
35
+ /** Records folded into the snapshot (set when compacted). */
36
+ foldedRecords?: number;
37
+ /** Sequence the log was folded through (set when compacted). */
38
+ foldedThroughSequence?: string;
39
+ /** Encoded snapshot size in bytes (set when compacted). */
40
+ snapshotBytes?: number;
41
+ }
42
+ export interface CompactionRunResult {
43
+ results: CompactDocumentResult[];
44
+ /** Per-document failures; one bad document never aborts the run. */
45
+ errors: {
46
+ docId: string;
47
+ error: unknown;
48
+ }[];
49
+ compacted: number;
50
+ skipped: number;
51
+ }
52
+ /**
53
+ * Compacts one document if its update log exceeds the policy threshold:
54
+ * lists the stored log, replays all but the newest `keep` records into a
55
+ * fresh Y.Doc, encodes the state with `Y.encodeStateAsUpdate`, and calls
56
+ * `CompactDocument` for the covered sequence. Idempotent — re-running
57
+ * converges to the same folded log, and updates pushed concurrently are
58
+ * unaffected (they sort after `compactThroughSequence`).
59
+ */
60
+ export declare function compactDocument(options: CompactDocumentOptions, docId: string): Promise<CompactDocumentResult>;
61
+ /**
62
+ * Compacts many documents sequentially (compaction is background work;
63
+ * predictable server load beats speed here). Per-document failures are
64
+ * collected in `errors` instead of aborting the run.
65
+ */
66
+ export declare function compactDocuments(options: CompactDocumentOptions, docIds: Iterable<string>): Promise<CompactionRunResult>;
67
+ //# sourceMappingURL=compaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/compaction/compaction.ts"],"names":[],"mappings":"AAmBA,iEAAiE;AACjE,MAAM,WAAW,uBAAuB;IACtC,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACrE,gEAAgE;IAChE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,mFAAmF;AACnF,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBACf,SAAQ,uBAAuB,EAC7B,gBAAgB;CAAG;AAEvB,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,oEAAoE;IACpE,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAWD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,EAC/B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,qBAAqB,CAAC,CAuDhC;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GACvB,OAAO,CAAC,mBAAmB,CAAC,CAqB9B"}