@hanzo/base 0.2.0 → 0.2.1
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/dist/{chunk-LBAV5X5P.js → chunk-3WOGNODW.js} +17 -17
- package/dist/{chunk-LBAV5X5P.js.map → chunk-3WOGNODW.js.map} +1 -1
- package/dist/chunk-DC6LDHAD.js +244 -0
- package/dist/chunk-DC6LDHAD.js.map +1 -0
- package/dist/{chunk-5NHFZRMO.js → chunk-FTBTJJQY.js} +3 -3
- package/dist/chunk-FTBTJJQY.js.map +1 -0
- package/dist/client-Ckpi5rr9.d.ts +368 -0
- package/dist/compat/index.d.ts +203 -1
- package/dist/compat/index.js +2 -1
- package/dist/compat/index.js.map +1 -1
- package/dist/core/index.d.ts +7 -363
- package/dist/core/index.js +2 -1
- package/dist/crdt/index.d.ts +1 -1
- package/dist/crdt/index.js +1 -1
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +5 -5
- package/dist/react/index.js.map +1 -1
- package/package.json +4 -6
- package/src/compat/index.ts +33 -10
- package/src/core/auth-stores.ts +222 -0
- package/src/core/client.ts +12 -12
- package/src/core/collection.ts +2 -2
- package/src/core/index.ts +27 -2
- package/src/core/realtime.ts +3 -3
- package/src/core/tokens.ts +139 -0
- package/src/core/types.ts +100 -0
- package/src/crdt/sync.ts +1 -1
- package/src/react/hooks.ts +3 -3
- package/dist/chunk-5NHFZRMO.js.map +0 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { BaseClient } from './chunk-3WOGNODW.js';
|
|
2
|
+
|
|
3
|
+
// src/core/auth-stores.ts
|
|
4
|
+
var LocalAuthStore = class {
|
|
5
|
+
constructor(storageKey = "base_auth") {
|
|
6
|
+
this._listeners = /* @__PURE__ */ new Set();
|
|
7
|
+
this._memToken = "";
|
|
8
|
+
this._memRecord = null;
|
|
9
|
+
this._storageKey = storageKey;
|
|
10
|
+
}
|
|
11
|
+
get _storage() {
|
|
12
|
+
try {
|
|
13
|
+
if (typeof globalThis !== "undefined" && "localStorage" in globalThis) {
|
|
14
|
+
return globalThis.localStorage ?? null;
|
|
15
|
+
}
|
|
16
|
+
} catch {
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
_read() {
|
|
21
|
+
const storage = this._storage;
|
|
22
|
+
if (!storage) return { token: this._memToken, record: this._memRecord };
|
|
23
|
+
try {
|
|
24
|
+
const raw = storage.getItem(this._storageKey);
|
|
25
|
+
if (!raw) return { token: "", record: null };
|
|
26
|
+
const parsed = JSON.parse(raw);
|
|
27
|
+
return { token: parsed.token ?? "", record: parsed.record ?? null };
|
|
28
|
+
} catch {
|
|
29
|
+
return { token: "", record: null };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
_write(value) {
|
|
33
|
+
const storage = this._storage;
|
|
34
|
+
if (!storage) {
|
|
35
|
+
this._memToken = value.token;
|
|
36
|
+
this._memRecord = value.record;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
if (!value.token) {
|
|
41
|
+
storage.removeItem(this._storageKey);
|
|
42
|
+
} else {
|
|
43
|
+
storage.setItem(this._storageKey, JSON.stringify(value));
|
|
44
|
+
}
|
|
45
|
+
} catch {
|
|
46
|
+
this._memToken = value.token;
|
|
47
|
+
this._memRecord = value.record;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
get token() {
|
|
51
|
+
return this._read().token;
|
|
52
|
+
}
|
|
53
|
+
get record() {
|
|
54
|
+
return this._read().record;
|
|
55
|
+
}
|
|
56
|
+
get isValid() {
|
|
57
|
+
const token = this.token;
|
|
58
|
+
if (!token) return false;
|
|
59
|
+
try {
|
|
60
|
+
const parts = token.split(".");
|
|
61
|
+
if (parts.length !== 3) return false;
|
|
62
|
+
const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
|
|
63
|
+
if (typeof payload.exp === "number") return payload.exp > Date.now() / 1e3;
|
|
64
|
+
return true;
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
save(token, record) {
|
|
70
|
+
this._write({ token, record });
|
|
71
|
+
this._notify(token, record);
|
|
72
|
+
}
|
|
73
|
+
clear() {
|
|
74
|
+
this._write({ token: "", record: null });
|
|
75
|
+
this._notify("", null);
|
|
76
|
+
}
|
|
77
|
+
onChange(callback) {
|
|
78
|
+
this._listeners.add(callback);
|
|
79
|
+
return () => {
|
|
80
|
+
this._listeners.delete(callback);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
_notify(token, record) {
|
|
84
|
+
for (const cb of this._listeners) {
|
|
85
|
+
try {
|
|
86
|
+
cb(token, record);
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var AsyncAuthStore = class {
|
|
93
|
+
constructor(config) {
|
|
94
|
+
this._token = "";
|
|
95
|
+
this._record = null;
|
|
96
|
+
this._listeners = /* @__PURE__ */ new Set();
|
|
97
|
+
this._save = config.save;
|
|
98
|
+
this._clear = config.clear;
|
|
99
|
+
if (config.initial) {
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(config.initial);
|
|
102
|
+
this._token = parsed.token ?? "";
|
|
103
|
+
this._record = parsed.record ?? null;
|
|
104
|
+
} catch {
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
get token() {
|
|
109
|
+
return this._token;
|
|
110
|
+
}
|
|
111
|
+
get record() {
|
|
112
|
+
return this._record;
|
|
113
|
+
}
|
|
114
|
+
get isValid() {
|
|
115
|
+
if (!this._token) return false;
|
|
116
|
+
try {
|
|
117
|
+
const parts = this._token.split(".");
|
|
118
|
+
if (parts.length !== 3) return false;
|
|
119
|
+
const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
|
|
120
|
+
if (typeof payload.exp === "number") return payload.exp > Date.now() / 1e3;
|
|
121
|
+
return true;
|
|
122
|
+
} catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
save(token, record) {
|
|
127
|
+
this._token = token;
|
|
128
|
+
this._record = record;
|
|
129
|
+
void this._save(JSON.stringify({ token, record }));
|
|
130
|
+
this._notify();
|
|
131
|
+
}
|
|
132
|
+
clear() {
|
|
133
|
+
this._token = "";
|
|
134
|
+
this._record = null;
|
|
135
|
+
if (this._clear) {
|
|
136
|
+
void this._clear();
|
|
137
|
+
} else {
|
|
138
|
+
void this._save("");
|
|
139
|
+
}
|
|
140
|
+
this._notify();
|
|
141
|
+
}
|
|
142
|
+
onChange(callback) {
|
|
143
|
+
this._listeners.add(callback);
|
|
144
|
+
return () => {
|
|
145
|
+
this._listeners.delete(callback);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
_notify() {
|
|
149
|
+
for (const cb of this._listeners) {
|
|
150
|
+
try {
|
|
151
|
+
cb(this._token, this._record);
|
|
152
|
+
} catch {
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// src/core/tokens.ts
|
|
159
|
+
function getTokenPayload(token) {
|
|
160
|
+
if (!token) return null;
|
|
161
|
+
const parts = token.split(".");
|
|
162
|
+
if (parts.length !== 3) return null;
|
|
163
|
+
try {
|
|
164
|
+
const padded = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
165
|
+
return JSON.parse(atob(padded));
|
|
166
|
+
} catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function isTokenExpired(token, expirationThreshold = 0) {
|
|
171
|
+
const payload = getTokenPayload(token);
|
|
172
|
+
if (!payload || typeof payload.exp !== "number") return true;
|
|
173
|
+
return payload.exp - expirationThreshold <= Date.now() / 1e3;
|
|
174
|
+
}
|
|
175
|
+
function cookieParse(input) {
|
|
176
|
+
const out = {};
|
|
177
|
+
if (!input) return out;
|
|
178
|
+
for (const segment of input.split(/;\s*/)) {
|
|
179
|
+
if (!segment) continue;
|
|
180
|
+
const eq = segment.indexOf("=");
|
|
181
|
+
if (eq < 0) continue;
|
|
182
|
+
const key = segment.slice(0, eq).trim();
|
|
183
|
+
let value = segment.slice(eq + 1).trim();
|
|
184
|
+
if (value.startsWith('"') && value.endsWith('"')) value = value.slice(1, -1);
|
|
185
|
+
try {
|
|
186
|
+
out[key] = decodeURIComponent(value);
|
|
187
|
+
} catch {
|
|
188
|
+
out[key] = value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
193
|
+
function cookieSerialize(name, value, options = {}) {
|
|
194
|
+
if (!/^[\w!#$%&'*+\-.^`|~]+$/.test(name)) {
|
|
195
|
+
throw new TypeError(`cookieSerialize: invalid cookie name ${JSON.stringify(name)}`);
|
|
196
|
+
}
|
|
197
|
+
const encode = options.encode ?? encodeURIComponent;
|
|
198
|
+
const encoded = encode(value);
|
|
199
|
+
if (encoded && !/^[\w!#$%&'()*+\-./:<=>?@[\]^`{|}~]*$/.test(encoded)) {
|
|
200
|
+
throw new TypeError(`cookieSerialize: invalid cookie value for ${name}`);
|
|
201
|
+
}
|
|
202
|
+
const parts = [`${name}=${encoded}`];
|
|
203
|
+
if (typeof options.maxAge === "number" && Number.isFinite(options.maxAge)) {
|
|
204
|
+
parts.push(`Max-Age=${Math.floor(options.maxAge)}`);
|
|
205
|
+
}
|
|
206
|
+
if (options.domain) parts.push(`Domain=${options.domain}`);
|
|
207
|
+
if (options.path) parts.push(`Path=${options.path}`);
|
|
208
|
+
if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
|
|
209
|
+
if (options.httpOnly) parts.push("HttpOnly");
|
|
210
|
+
if (options.secure) parts.push("Secure");
|
|
211
|
+
if (options.sameSite !== void 0 && options.sameSite !== false) {
|
|
212
|
+
const ss = options.sameSite;
|
|
213
|
+
const value2 = ss === true ? "Strict" : `${ss.charAt(0).toUpperCase()}${ss.slice(1)}`;
|
|
214
|
+
parts.push(`SameSite=${value2}`);
|
|
215
|
+
}
|
|
216
|
+
if (options.priority) {
|
|
217
|
+
parts.push(`Priority=${options.priority.charAt(0).toUpperCase() + options.priority.slice(1)}`);
|
|
218
|
+
}
|
|
219
|
+
return parts.join("; ");
|
|
220
|
+
}
|
|
221
|
+
function normalizeUnknownQueryParams(params) {
|
|
222
|
+
const out = {};
|
|
223
|
+
if (!params) return out;
|
|
224
|
+
for (const [key, raw] of Object.entries(params)) {
|
|
225
|
+
if (raw === void 0 || raw === null) continue;
|
|
226
|
+
if (Array.isArray(raw)) {
|
|
227
|
+
out[key] = raw.map((v) => typeof v === "string" ? v : JSON.stringify(v));
|
|
228
|
+
} else if (typeof raw === "string") {
|
|
229
|
+
out[key] = raw;
|
|
230
|
+
} else if (typeof raw === "number" || typeof raw === "boolean") {
|
|
231
|
+
out[key] = String(raw);
|
|
232
|
+
} else {
|
|
233
|
+
out[key] = JSON.stringify(raw);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/core/index.ts
|
|
240
|
+
var core_default = BaseClient;
|
|
241
|
+
|
|
242
|
+
export { AsyncAuthStore, LocalAuthStore, cookieParse, cookieSerialize, core_default, getTokenPayload, isTokenExpired, normalizeUnknownQueryParams };
|
|
243
|
+
//# sourceMappingURL=chunk-DC6LDHAD.js.map
|
|
244
|
+
//# sourceMappingURL=chunk-DC6LDHAD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/auth-stores.ts","../src/core/tokens.ts","../src/core/index.ts"],"names":["value"],"mappings":"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","file":"chunk-DC6LDHAD.js","sourcesContent":["/**\n * Auth-store implementations beyond the in-memory default.\n *\n * Native `LocalAuthStore` / `AsyncAuthStore` implementations so the\n * SDK has zero upstream client dependency. The shape matches the\n * legacy client's auth stores so existing apps migrating to\n * `@hanzo/base` keep working.\n */\n\nimport type { AuthStore, AuthChangeCallback } from './client.js'\nimport type { BaseRecord } from './state.js'\n\ninterface PersistedAuth {\n token: string\n record: BaseRecord | null\n}\n\n/**\n * Type alias matching the upstream interface name. New code should use\n * `AuthStore`.\n */\nexport type BaseAuthStore = AuthStore\n\n/**\n * Synchronous localStorage-backed auth store. Suitable for browser SPAs.\n * Falls back to in-memory storage when `window.localStorage` is absent\n * (SSR, sandboxed iframes, etc.).\n */\nexport class LocalAuthStore implements AuthStore {\n private _storageKey: string\n private _listeners = new Set<AuthChangeCallback>()\n private _memToken = ''\n private _memRecord: BaseRecord | null = null\n\n constructor(storageKey: string = 'base_auth') {\n this._storageKey = storageKey\n }\n\n private get _storage(): Storage | null {\n try {\n if (typeof globalThis !== 'undefined' && 'localStorage' in globalThis) {\n return (globalThis as { localStorage?: Storage }).localStorage ?? null\n }\n } catch {\n // Access can throw in some sandboxed contexts; fall through.\n }\n return null\n }\n\n private _read(): PersistedAuth {\n const storage = this._storage\n if (!storage) return { token: this._memToken, record: this._memRecord }\n try {\n const raw = storage.getItem(this._storageKey)\n if (!raw) return { token: '', record: null }\n const parsed = JSON.parse(raw) as Partial<PersistedAuth>\n return { token: parsed.token ?? '', record: parsed.record ?? null }\n } catch {\n return { token: '', record: null }\n }\n }\n\n private _write(value: PersistedAuth): void {\n const storage = this._storage\n if (!storage) {\n this._memToken = value.token\n this._memRecord = value.record\n return\n }\n try {\n if (!value.token) {\n storage.removeItem(this._storageKey)\n } else {\n storage.setItem(this._storageKey, JSON.stringify(value))\n }\n } catch {\n // Quota / serialization errors fall back to memory.\n this._memToken = value.token\n this._memRecord = value.record\n }\n }\n\n get token(): string {\n return this._read().token\n }\n\n get record(): BaseRecord | null {\n return this._read().record\n }\n\n get isValid(): boolean {\n const token = this.token\n if (!token) return false\n try {\n const parts = token.split('.')\n if (parts.length !== 3) return false\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')))\n if (typeof payload.exp === 'number') return payload.exp > Date.now() / 1000\n return true\n } catch {\n return false\n }\n }\n\n save(token: string, record: BaseRecord | null): void {\n this._write({ token, record })\n this._notify(token, record)\n }\n\n clear(): void {\n this._write({ token: '', record: null })\n this._notify('', null)\n }\n\n onChange(callback: AuthChangeCallback): () => void {\n this._listeners.add(callback)\n return () => {\n this._listeners.delete(callback)\n }\n }\n\n private _notify(token: string, record: BaseRecord | null): void {\n for (const cb of this._listeners) {\n try {\n cb(token, record)\n } catch {\n // listener errors must not break notification\n }\n }\n }\n}\n\n/**\n * Async auth store — wraps any async storage backend (cookies via\n * fetch, encrypted SecureStore on mobile, KV namespace on the edge,\n * etc.). Reads and writes are buffered through an in-memory cache so\n * the `token`/`record` accessors stay synchronous (matching upstream).\n *\n * Pass a `save` function that persists the serialized payload to your\n * backend, and an `initial` value loaded synchronously at app boot.\n */\nexport class AsyncAuthStore implements AuthStore {\n private _token = ''\n private _record: BaseRecord | null = null\n private _listeners = new Set<AuthChangeCallback>()\n private readonly _save: (serialized: string) => Promise<void> | void\n private readonly _clear?: () => Promise<void> | void\n\n constructor(config: {\n save: (serialized: string) => Promise<void> | void\n initial?: string | null\n clear?: () => Promise<void> | void\n }) {\n this._save = config.save\n this._clear = config.clear\n if (config.initial) {\n try {\n const parsed = JSON.parse(config.initial) as Partial<PersistedAuth>\n this._token = parsed.token ?? ''\n this._record = parsed.record ?? null\n } catch {\n // ignore malformed initial value\n }\n }\n }\n\n get token(): string {\n return this._token\n }\n\n get record(): BaseRecord | null {\n return this._record\n }\n\n get isValid(): boolean {\n if (!this._token) return false\n try {\n const parts = this._token.split('.')\n if (parts.length !== 3) return false\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')))\n if (typeof payload.exp === 'number') return payload.exp > Date.now() / 1000\n return true\n } catch {\n return false\n }\n }\n\n save(token: string, record: BaseRecord | null): void {\n this._token = token\n this._record = record\n void this._save(JSON.stringify({ token, record }))\n this._notify()\n }\n\n clear(): void {\n this._token = ''\n this._record = null\n if (this._clear) {\n void this._clear()\n } else {\n void this._save('')\n }\n this._notify()\n }\n\n onChange(callback: AuthChangeCallback): () => void {\n this._listeners.add(callback)\n return () => {\n this._listeners.delete(callback)\n }\n }\n\n private _notify(): void {\n for (const cb of this._listeners) {\n try {\n cb(this._token, this._record)\n } catch {\n // listener errors must not break notification\n }\n }\n }\n}\n","/**\n * JWT + cookie helpers — small utilities the compat layer used to\n * re-export from the upstream client. Implemented natively so the SDK\n * has zero upstream dependency.\n */\n\n/**\n * Decode the payload of a JWT without verifying its signature.\n * Returns `null` for malformed tokens. Safe for browser + Node use\n * (relies only on global `atob`).\n */\nexport function getTokenPayload<T = Record<string, unknown>>(token: string): T | null {\n if (!token) return null\n const parts = token.split('.')\n if (parts.length !== 3) return null\n try {\n const padded = parts[1].replace(/-/g, '+').replace(/_/g, '/')\n return JSON.parse(atob(padded)) as T\n } catch {\n return null\n }\n}\n\n/**\n * Check whether a JWT's `exp` claim has passed.\n * `expirationThreshold` (seconds) is subtracted from `exp` to expire\n * tokens early — set this when you want to refresh before the actual\n * expiration. Tokens without an `exp` claim are treated as\n * non-expiring.\n */\nexport function isTokenExpired(token: string, expirationThreshold: number = 0): boolean {\n const payload = getTokenPayload<{ exp?: number }>(token)\n if (!payload || typeof payload.exp !== 'number') return true\n return payload.exp - expirationThreshold <= Date.now() / 1000\n}\n\n/**\n * Cookie parsing — extracts a name→value map from a Set-Cookie or\n * Cookie header value. Decodes URI-encoded values. Mirrors the\n * `cookie` npm package's signature so it's drop-in for the upstream\n * client's `cookieParse`.\n */\nexport function cookieParse(input: string): Record<string, string> {\n const out: Record<string, string> = {}\n if (!input) return out\n for (const segment of input.split(/;\\s*/)) {\n if (!segment) continue\n const eq = segment.indexOf('=')\n if (eq < 0) continue\n const key = segment.slice(0, eq).trim()\n let value = segment.slice(eq + 1).trim()\n if (value.startsWith('\"') && value.endsWith('\"')) value = value.slice(1, -1)\n try {\n out[key] = decodeURIComponent(value)\n } catch {\n out[key] = value\n }\n }\n return out\n}\n\nexport interface CookieSerializeOptions {\n encode?: (value: string) => string\n maxAge?: number\n domain?: string\n path?: string\n expires?: Date\n httpOnly?: boolean\n secure?: boolean\n sameSite?: 'strict' | 'lax' | 'none' | boolean\n priority?: 'low' | 'medium' | 'high'\n}\n\n/**\n * Cookie serialization — builds a `Set-Cookie` header value.\n * `encode` defaults to `encodeURIComponent`. Throws if the name or\n * encoded value contain invalid characters.\n */\nexport function cookieSerialize(\n name: string,\n value: string,\n options: CookieSerializeOptions = {},\n): string {\n if (!/^[\\w!#$%&'*+\\-.^`|~]+$/.test(name)) {\n throw new TypeError(`cookieSerialize: invalid cookie name ${JSON.stringify(name)}`)\n }\n const encode = options.encode ?? encodeURIComponent\n const encoded = encode(value)\n if (encoded && !/^[\\w!#$%&'()*+\\-./:<=>?@[\\]^`{|}~]*$/.test(encoded)) {\n throw new TypeError(`cookieSerialize: invalid cookie value for ${name}`)\n }\n const parts = [`${name}=${encoded}`]\n if (typeof options.maxAge === 'number' && Number.isFinite(options.maxAge)) {\n parts.push(`Max-Age=${Math.floor(options.maxAge)}`)\n }\n if (options.domain) parts.push(`Domain=${options.domain}`)\n if (options.path) parts.push(`Path=${options.path}`)\n if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`)\n if (options.httpOnly) parts.push('HttpOnly')\n if (options.secure) parts.push('Secure')\n if (options.sameSite !== undefined && options.sameSite !== false) {\n const ss = options.sameSite\n const value =\n ss === true\n ? 'Strict'\n : `${ss.charAt(0).toUpperCase()}${ss.slice(1)}`\n parts.push(`SameSite=${value}`)\n }\n if (options.priority) {\n parts.push(`Priority=${options.priority.charAt(0).toUpperCase() + options.priority.slice(1)}`)\n }\n return parts.join('; ')\n}\n\n/**\n * Normalize a query-param record so values are always strings (or\n * arrays of strings). Mirrors the upstream `normalizeUnknownQueryParams`\n * helper used by the auto-encoding URL builder. Nullish entries are\n * dropped; non-primitive entries are JSON-stringified.\n */\nexport function normalizeUnknownQueryParams(\n params: Record<string, unknown> | null | undefined,\n): Record<string, string | string[]> {\n const out: Record<string, string | string[]> = {}\n if (!params) return out\n for (const [key, raw] of Object.entries(params)) {\n if (raw === undefined || raw === null) continue\n if (Array.isArray(raw)) {\n out[key] = raw.map((v) => (typeof v === 'string' ? v : JSON.stringify(v)))\n } else if (typeof raw === 'string') {\n out[key] = raw\n } else if (typeof raw === 'number' || typeof raw === 'boolean') {\n out[key] = String(raw)\n } else {\n out[key] = JSON.stringify(raw)\n }\n }\n return out\n}\n","/**\n * @hanzo/base -- Core entry point.\n *\n * Exposes the full Base client surface natively. No upstream package\n * dependency — every type and helper the SDK needs lives here.\n */\n\nimport { BaseClient } from './client.js'\n\n// Client\nexport { BaseClient, BaseClientError, MemoryAuthStore, FileService } from './client.js'\nexport type { AuthStore, AuthChangeCallback, ClientConfig, ListOptions, ListResult } from './client.js'\n\n// Collection\nexport { CollectionService, ClientResponseError } from './collection.js'\nexport type {\n RecordQueryOptions,\n RecordFullListOptions,\n FileOptions,\n AuthResponse,\n OAuth2Options,\n ClientResponseErrorData,\n} from './collection.js'\n\n// Store\nexport { QueryStore } from './store.js'\nexport type { QueryKey, StoreCallback } from './store.js'\n\n// State\nexport { VersionTracker } from './state.js'\nexport type { StateVersion, Modification, Transition, BaseRecord } from './state.js'\n\n// Realtime\nexport { RealtimeService } from './realtime.js'\nexport type {\n ConnectionState,\n RealtimeEvent,\n RealtimeCallback,\n ConnectionCallback,\n} from './realtime.js'\n\n// Schema types — admin UI consumers\nexport type { CollectionField, CollectionModel, RecordModel } from './types.js'\n\n// Auth stores — beyond the in-memory default\nexport { LocalAuthStore, AsyncAuthStore } from './auth-stores.js'\nexport type { BaseAuthStore } from './auth-stores.js'\n\n// Token + cookie helpers\nexport {\n getTokenPayload,\n isTokenExpired,\n cookieParse,\n cookieSerialize,\n normalizeUnknownQueryParams,\n} from './tokens.js'\nexport type { CookieSerializeOptions } from './tokens.js'\n\n// Default export — matches the upstream client default. Consumers can\n// `import Base from '@hanzo/base'` and continue calling `new Base(url)`\n// exactly as they did against the upstream package.\nexport default BaseClient\n"]}
|
|
@@ -35,7 +35,7 @@ var CRDTSync = class {
|
|
|
35
35
|
/**
|
|
36
36
|
* Connect to the CRDT sync endpoint and start syncing a document.
|
|
37
37
|
*
|
|
38
|
-
* @param wsUrl - WebSocket URL, e.g. "wss://myapp.hanzo.ai/
|
|
38
|
+
* @param wsUrl - WebSocket URL, e.g. "wss://myapp.hanzo.ai/v1/crdt"
|
|
39
39
|
* @param document - The CRDTDocument to sync.
|
|
40
40
|
* @param token - Optional auth token.
|
|
41
41
|
*/
|
|
@@ -1007,5 +1007,5 @@ var CRDTDocument = class {
|
|
|
1007
1007
|
};
|
|
1008
1008
|
|
|
1009
1009
|
export { CRDTCounter, CRDTDocument, CRDTRegister, CRDTSet, CRDTSync, CRDTText, HybridLogicalClock, compareHLC, makeOpId, makePositionId };
|
|
1010
|
-
//# sourceMappingURL=chunk-
|
|
1011
|
-
//# sourceMappingURL=chunk-
|
|
1010
|
+
//# sourceMappingURL=chunk-FTBTJJQY.js.map
|
|
1011
|
+
//# sourceMappingURL=chunk-FTBTJJQY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/crdt/sync.ts","../src/crdt/clock.ts","../src/crdt/operations.ts","../src/crdt/text.ts","../src/crdt/counter.ts","../src/crdt/set.ts","../src/crdt/register.ts","../src/crdt/document.ts"],"names":[],"mappings":"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","file":"chunk-FTBTJJQY.js","sourcesContent":["/**\n * CRDTSync -- WebSocket-based sync protocol handler.\n *\n * Connects to the Base server's CRDT sync endpoint and manages\n * bidirectional operation exchange. Handles:\n *\n * - Buffering and batching local operations\n * - Applying remote operations to the CRDTDocument\n * - Reconnection with exponential backoff\n * - Acknowledgment tracking\n * - Presence (peer awareness) via the same channel\n */\n\nimport type { CRDTDocument } from './document.js'\nimport type { Operation } from './operations.js'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type SyncState = 'disconnected' | 'connecting' | 'connected' | 'syncing'\n\nexport interface PeerState {\n siteId: string\n /** Arbitrary JSON-serializable state (cursor position, name, color, etc.). */\n meta: Record<string, unknown>\n /** Last seen timestamp (local clock). */\n lastSeen: number\n}\n\nexport type SyncStateCallback = (state: SyncState) => void\nexport type PeerCallback = (peers: Map<string, PeerState>) => void\nexport type RemoteChangeCallback = (ops: Operation[]) => void\n\n/** Wire message types sent over WebSocket. */\ninterface SyncMessage {\n type: 'ops' | 'ack' | 'presence' | 'state_request' | 'state_response'\n documentId: string\n siteId: string\n payload: unknown\n}\n\ninterface OpsPayload {\n ops: Operation[]\n}\n\ninterface AckPayload {\n lastOpId: string\n}\n\ninterface PresencePayload {\n meta: Record<string, unknown>\n}\n\n// ---------------------------------------------------------------------------\n// CRDTSync\n// ---------------------------------------------------------------------------\n\nexport class CRDTSync {\n private _ws: WebSocket | null = null\n private _state: SyncState = 'disconnected'\n private _document: CRDTDocument | null = null\n private _wsUrl: string | null = null\n\n /** Flush interval for batching local ops. */\n private _flushTimer: ReturnType<typeof setInterval> | null = null\n private _flushIntervalMs = 50\n\n /** Reconnection. */\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null\n private _reconnectAttempts = 0\n private _maxReconnectDelay = 30_000\n private _baseReconnectDelay = 500\n private _intentionalClose = false\n\n /** Presence. */\n private _peers = new Map<string, PeerState>()\n private _localPresence: Record<string, unknown> = {}\n private _presenceTimer: ReturnType<typeof setInterval> | null = null\n private _presenceIntervalMs = 2_000\n private _peerTimeoutMs = 10_000\n\n /** Listeners. */\n private _stateListeners = new Set<SyncStateCallback>()\n private _peerListeners = new Set<PeerCallback>()\n private _remoteChangeListeners = new Set<RemoteChangeCallback>()\n\n // ---- Public API ---------------------------------------------------------\n\n get state(): SyncState {\n return this._state\n }\n\n get peers(): ReadonlyMap<string, PeerState> {\n return this._peers\n }\n\n /**\n * Connect to the CRDT sync endpoint and start syncing a document.\n *\n * @param wsUrl - WebSocket URL, e.g. \"wss://myapp.hanzo.ai/v1/crdt\"\n * @param document - The CRDTDocument to sync.\n * @param token - Optional auth token.\n */\n connect(wsUrl: string, document: CRDTDocument, token?: string): void {\n if (this._ws) {\n this.disconnect()\n }\n\n this._wsUrl = wsUrl\n this._document = document\n this._intentionalClose = false\n this._setState('connecting')\n\n const url = new URL(wsUrl)\n url.searchParams.set('documentId', document.id)\n url.searchParams.set('siteId', document.clock.siteId)\n if (token) {\n url.searchParams.set('token', token)\n }\n\n this._ws = new WebSocket(url.toString())\n this._ws.binaryType = 'arraybuffer'\n\n this._ws.onopen = () => {\n this._reconnectAttempts = 0\n this._setState('connected')\n\n // Request full state from server if we have no unsynced ops.\n if (document.getUnsyncedOps().length === 0) {\n this._send({\n type: 'state_request',\n documentId: document.id,\n siteId: document.clock.siteId,\n payload: {},\n })\n } else {\n // Re-send unsynced ops.\n this._sendOps(Array.from(document.getUnsyncedOps()))\n }\n\n this._startFlush()\n this._startPresence()\n }\n\n this._ws.onmessage = (e: MessageEvent) => {\n this._handleMessage(e.data)\n }\n\n this._ws.onclose = () => {\n this._stopFlush()\n this._stopPresence()\n this._ws = null\n this._setState('disconnected')\n\n if (!this._intentionalClose) {\n this._scheduleReconnect()\n }\n }\n\n this._ws.onerror = () => {\n // The close event will fire next -- handle reconnection there.\n }\n }\n\n disconnect(): void {\n this._intentionalClose = true\n this._stopFlush()\n this._stopPresence()\n this._clearReconnect()\n\n if (this._ws) {\n this._ws.close()\n this._ws = null\n }\n\n this._peers.clear()\n this._setState('disconnected')\n }\n\n /** Update local presence metadata (cursor, name, etc.). */\n updatePresence(meta: Record<string, unknown>): void {\n this._localPresence = meta\n this._broadcastPresence()\n }\n\n // ---- Listeners ----------------------------------------------------------\n\n onStateChange(cb: SyncStateCallback): () => void {\n this._stateListeners.add(cb)\n return () => { this._stateListeners.delete(cb) }\n }\n\n onPeersChange(cb: PeerCallback): () => void {\n this._peerListeners.add(cb)\n return () => { this._peerListeners.delete(cb) }\n }\n\n onRemoteChange(cb: RemoteChangeCallback): () => void {\n this._remoteChangeListeners.add(cb)\n return () => { this._remoteChangeListeners.delete(cb) }\n }\n\n // ---- Message handling ---------------------------------------------------\n\n private _handleMessage(raw: string | ArrayBuffer): void {\n let text: string\n if (raw instanceof ArrayBuffer) {\n text = new TextDecoder().decode(raw)\n } else {\n text = raw as string\n }\n\n let msg: SyncMessage\n try {\n msg = JSON.parse(text)\n } catch {\n return\n }\n\n if (!this._document || msg.documentId !== this._document.id) return\n\n switch (msg.type) {\n case 'ops': {\n const payload = msg.payload as OpsPayload\n if (!payload.ops || payload.ops.length === 0) return\n\n // Skip our own operations echoed back.\n const remoteOps = payload.ops.filter(\n (op) => op.hlc.siteId !== this._document!.clock.siteId,\n )\n\n if (remoteOps.length > 0) {\n this._document.applyRemoteOps(remoteOps)\n for (const cb of this._remoteChangeListeners) {\n try {\n cb(remoteOps)\n } catch {\n // listener errors must not break processing\n }\n }\n }\n break\n }\n\n case 'ack': {\n const payload = msg.payload as AckPayload\n this._document.acknowledge(payload.lastOpId)\n if (this._state === 'syncing' && this._document.getUnsyncedOps().length === 0) {\n this._setState('connected')\n }\n break\n }\n\n case 'presence': {\n const payload = msg.payload as PresencePayload\n if (msg.siteId === this._document.clock.siteId) return\n this._peers.set(msg.siteId, {\n siteId: msg.siteId,\n meta: payload.meta,\n lastSeen: Date.now(),\n })\n this._notifyPeers()\n break\n }\n\n case 'state_response': {\n // Full state from server -- apply as remote ops.\n const payload = msg.payload as OpsPayload\n if (payload.ops && payload.ops.length > 0) {\n this._document.applyRemoteOps(payload.ops)\n }\n break\n }\n }\n }\n\n // ---- Flush (batched sending of local ops) -------------------------------\n\n private _startFlush(): void {\n this._stopFlush()\n this._flushTimer = setInterval(() => {\n this._flush()\n }, this._flushIntervalMs)\n }\n\n private _stopFlush(): void {\n if (this._flushTimer !== null) {\n clearInterval(this._flushTimer)\n this._flushTimer = null\n }\n }\n\n private _flush(): void {\n if (!this._document || !this._ws || this._ws.readyState !== WebSocket.OPEN) return\n\n const ops = this._document.collectOps()\n if (ops.length === 0) return\n\n this._sendOps(ops)\n this._setState('syncing')\n }\n\n private _sendOps(ops: Operation[]): void {\n if (!this._document || !this._ws || this._ws.readyState !== WebSocket.OPEN) return\n\n this._send({\n type: 'ops',\n documentId: this._document.id,\n siteId: this._document.clock.siteId,\n payload: { ops } satisfies OpsPayload,\n })\n }\n\n // ---- Presence -----------------------------------------------------------\n\n private _startPresence(): void {\n this._stopPresence()\n this._broadcastPresence()\n this._presenceTimer = setInterval(() => {\n this._broadcastPresence()\n this._pruneStalePresence()\n }, this._presenceIntervalMs)\n }\n\n private _stopPresence(): void {\n if (this._presenceTimer !== null) {\n clearInterval(this._presenceTimer)\n this._presenceTimer = null\n }\n }\n\n private _broadcastPresence(): void {\n if (!this._document || !this._ws || this._ws.readyState !== WebSocket.OPEN) return\n\n this._send({\n type: 'presence',\n documentId: this._document.id,\n siteId: this._document.clock.siteId,\n payload: { meta: this._localPresence } satisfies PresencePayload,\n })\n }\n\n private _pruneStalePresence(): void {\n const now = Date.now()\n let changed = false\n for (const [siteId, peer] of this._peers) {\n if (now - peer.lastSeen > this._peerTimeoutMs) {\n this._peers.delete(siteId)\n changed = true\n }\n }\n if (changed) {\n this._notifyPeers()\n }\n }\n\n // ---- Reconnection -------------------------------------------------------\n\n private _scheduleReconnect(): void {\n this._clearReconnect()\n const delay = Math.min(\n this._baseReconnectDelay * Math.pow(2, this._reconnectAttempts),\n this._maxReconnectDelay,\n )\n const jitter = delay * (0.75 + Math.random() * 0.5)\n this._reconnectAttempts++\n\n this._reconnectTimer = setTimeout(() => {\n this._reconnectTimer = null\n if (this._document && this._wsUrl) {\n this.connect(this._wsUrl, this._document)\n }\n }, jitter)\n }\n\n private _clearReconnect(): void {\n if (this._reconnectTimer !== null) {\n clearTimeout(this._reconnectTimer)\n this._reconnectTimer = null\n }\n }\n\n // ---- Internal helpers ---------------------------------------------------\n\n private _send(msg: SyncMessage): void {\n if (!this._ws || this._ws.readyState !== WebSocket.OPEN) return\n this._ws.send(JSON.stringify(msg))\n }\n\n private _setState(state: SyncState): void {\n if (this._state === state) return\n this._state = state\n for (const cb of this._stateListeners) {\n try {\n cb(state)\n } catch {\n // listener errors must not break state management\n }\n }\n }\n\n private _notifyPeers(): void {\n for (const cb of this._peerListeners) {\n try {\n cb(this._peers)\n } catch {\n // listener errors must not break peer notification\n }\n }\n }\n}\n","/**\n * Hybrid logical clock for CRDT operation ordering.\n *\n * Each operation is tagged with (timestamp, counter, siteId) to provide\n * a total order across all sites. Compatible with the Go HLC implementation.\n */\n\nexport interface HLCTimestamp {\n /** Wall-clock milliseconds since epoch. */\n ts: number\n /** Monotonic counter to break ties within the same ms. */\n counter: number\n /** Unique site identifier (usually client session id). */\n siteId: string\n}\n\nexport class HybridLogicalClock {\n private _ts: number\n private _counter: number\n readonly siteId: string\n\n constructor(siteId?: string) {\n this.siteId = siteId ?? randomSiteId()\n this._ts = Date.now()\n this._counter = 0\n }\n\n /** Generate a new timestamp, guaranteed > any previous. */\n now(): HLCTimestamp {\n const wall = Date.now()\n if (wall > this._ts) {\n this._ts = wall\n this._counter = 0\n } else {\n this._counter++\n }\n return { ts: this._ts, counter: this._counter, siteId: this.siteId }\n }\n\n /** Receive a remote timestamp and merge with local clock. */\n receive(remote: HLCTimestamp): HLCTimestamp {\n const wall = Date.now()\n if (wall > this._ts && wall > remote.ts) {\n this._ts = wall\n this._counter = 0\n } else if (remote.ts > this._ts) {\n this._ts = remote.ts\n this._counter = remote.counter + 1\n } else if (this._ts > remote.ts) {\n this._counter++\n } else {\n // Same ts -- take max counter + 1\n this._counter = Math.max(this._counter, remote.counter) + 1\n }\n return { ts: this._ts, counter: this._counter, siteId: this.siteId }\n }\n}\n\n/** Compare two HLC timestamps. Returns <0, 0, or >0. */\nexport function compareHLC(a: HLCTimestamp, b: HLCTimestamp): number {\n if (a.ts !== b.ts) return a.ts - b.ts\n if (a.counter !== b.counter) return a.counter - b.counter\n if (a.siteId < b.siteId) return -1\n if (a.siteId > b.siteId) return 1\n return 0\n}\n\nfunction randomSiteId(): string {\n const buf = new Uint8Array(8)\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n crypto.getRandomValues(buf)\n } else {\n for (let i = 0; i < buf.length; i++) {\n buf[i] = (Math.random() * 256) | 0\n }\n }\n return Array.from(buf, (b) => b.toString(16).padStart(2, '0')).join('')\n}\n","/**\n * CRDT operation types -- wire format for sync between client and server.\n *\n * All operations are serializable to JSON and designed for\n * eventual compatibility with a Go CRDT server.\n */\n\nimport type { HLCTimestamp } from './clock.js'\n\n// ---------------------------------------------------------------------------\n// Operation type tags\n// ---------------------------------------------------------------------------\n\nexport type OperationType =\n | 'text.insert'\n | 'text.delete'\n | 'counter.increment'\n | 'set.add'\n | 'set.remove'\n | 'register.set'\n\n// ---------------------------------------------------------------------------\n// Base operation\n// ---------------------------------------------------------------------------\n\nexport interface Operation {\n /** Unique operation id: `{siteId}:{ts}:{counter}` */\n id: string\n /** The CRDT document id this operation belongs to. */\n documentId: string\n /** Which field within the document. */\n field: string\n /** HLC timestamp for causal ordering. */\n hlc: HLCTimestamp\n /** Operation type tag. */\n type: OperationType\n /** Type-specific payload. */\n payload: OperationPayload\n}\n\n// ---------------------------------------------------------------------------\n// Payloads\n// ---------------------------------------------------------------------------\n\nexport interface TextInsertPayload {\n /** Position id of the character after which to insert (null = head). */\n afterId: string | null\n /** The text content to insert. Each character gets its own positional id. */\n content: string\n /** Assigned position ids for each character (same length as content). */\n positionIds: string[]\n}\n\nexport interface TextDeletePayload {\n /** Position ids of the characters to tombstone. */\n positionIds: string[]\n}\n\nexport interface CounterIncrementPayload {\n /** Delta (positive for increment, negative for decrement). */\n delta: number\n}\n\nexport interface SetAddPayload {\n /** The value to add (JSON-serializable). */\n value: unknown\n /** Unique tag for this add operation (for OR-Set semantics). */\n tag: string\n}\n\nexport interface SetRemovePayload {\n /** The value to remove. */\n value: unknown\n /** Tags being causally removed (observed tags at removal time). */\n tags: string[]\n}\n\nexport interface RegisterSetPayload {\n /** The new value. */\n value: unknown\n}\n\nexport type OperationPayload =\n | TextInsertPayload\n | TextDeletePayload\n | CounterIncrementPayload\n | SetAddPayload\n | SetRemovePayload\n | RegisterSetPayload\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nexport function makeOpId(hlc: HLCTimestamp): string {\n return `${hlc.siteId}:${hlc.ts}:${hlc.counter}`\n}\n\nexport function makePositionId(hlc: HLCTimestamp, charIndex: number): string {\n return `${hlc.siteId}:${hlc.ts}:${hlc.counter}:${charIndex}`\n}\n","/**\n * CRDTText -- collaborative text based on RGA (Replicated Growable Array).\n *\n * Each character has a unique position id. Insertions reference the position\n * id of the character they follow. Deletions tombstone position ids.\n * The structure resolves conflicts by using HLC comparison on concurrent\n * inserts at the same position.\n */\n\nimport type { HLCTimestamp } from './clock.js'\nimport { HybridLogicalClock, compareHLC } from './clock.js'\nimport type { Operation, TextInsertPayload, TextDeletePayload } from './operations.js'\nimport { makeOpId, makePositionId } from './operations.js'\n\n// ---------------------------------------------------------------------------\n// Internal node structure\n// ---------------------------------------------------------------------------\n\ninterface TextNode {\n id: string // unique position id\n char: string // single character\n hlc: HLCTimestamp // creation timestamp\n tombstone: boolean // soft-deleted\n afterId: string | null // the id this node was inserted after\n}\n\n// ---------------------------------------------------------------------------\n// CRDTText\n// ---------------------------------------------------------------------------\n\nexport type TextChangeCallback = (text: string) => void\n\nexport class CRDTText {\n private _nodes: TextNode[] = []\n private readonly _clock: HybridLogicalClock\n private readonly _documentId: string\n private readonly _field: string\n private readonly _pendingOps: Operation[] = []\n private _listeners = new Set<TextChangeCallback>()\n\n /** Index from position id to array index for O(1) lookup. */\n private _index = new Map<string, number>()\n\n constructor(documentId: string, field: string, clock: HybridLogicalClock) {\n this._documentId = documentId\n this._field = field\n this._clock = clock\n }\n\n // ---- Public API ---------------------------------------------------------\n\n /** Insert text at a visible character position (0-based). */\n insert(position: number, text: string): Operation {\n if (text.length === 0) {\n throw new Error('CRDTText.insert: empty text')\n }\n\n const afterId = this._visibleIdAtPosition(position - 1)\n const hlc = this._clock.now()\n const positionIds: string[] = []\n\n // Create nodes for each character, chaining them.\n let prevId = afterId\n for (let i = 0; i < text.length; i++) {\n const posId = makePositionId(hlc, i)\n positionIds.push(posId)\n\n const node: TextNode = {\n id: posId,\n char: text[i],\n hlc: { ...hlc, counter: hlc.counter + i },\n tombstone: false,\n afterId: prevId,\n }\n\n this._insertNode(node)\n prevId = posId\n }\n\n const op: Operation = {\n id: makeOpId(hlc),\n documentId: this._documentId,\n field: this._field,\n hlc,\n type: 'text.insert',\n payload: { afterId, content: text, positionIds } satisfies TextInsertPayload,\n }\n\n this._pendingOps.push(op)\n this._notifyChange()\n return op\n }\n\n /** Delete `length` visible characters starting at `position` (0-based). */\n delete(position: number, length: number): Operation {\n const ids = this._visibleIdsInRange(position, length)\n if (ids.length === 0) {\n throw new Error('CRDTText.delete: nothing to delete')\n }\n\n for (const id of ids) {\n const idx = this._index.get(id)\n if (idx !== undefined) {\n this._nodes[idx].tombstone = true\n }\n }\n\n const hlc = this._clock.now()\n const op: Operation = {\n id: makeOpId(hlc),\n documentId: this._documentId,\n field: this._field,\n hlc,\n type: 'text.delete',\n payload: { positionIds: ids } satisfies TextDeletePayload,\n }\n\n this._pendingOps.push(op)\n this._notifyChange()\n return op\n }\n\n /** Apply a remote operation. */\n applyRemote(op: Operation): void {\n this._clock.receive(op.hlc)\n\n if (op.type === 'text.insert') {\n const payload = op.payload as TextInsertPayload\n for (let i = 0; i < payload.content.length; i++) {\n const node: TextNode = {\n id: payload.positionIds[i],\n char: payload.content[i],\n hlc: { ...op.hlc, counter: op.hlc.counter + i },\n tombstone: false,\n afterId: i === 0 ? payload.afterId : payload.positionIds[i - 1],\n }\n this._insertNode(node)\n }\n } else if (op.type === 'text.delete') {\n const payload = op.payload as TextDeletePayload\n for (const posId of payload.positionIds) {\n const idx = this._index.get(posId)\n if (idx !== undefined) {\n this._nodes[idx].tombstone = true\n }\n }\n }\n\n this._notifyChange()\n }\n\n /** Get the current visible text. */\n toString(): string {\n let result = ''\n for (const node of this._nodes) {\n if (!node.tombstone) {\n result += node.char\n }\n }\n return result\n }\n\n /** Number of visible characters. */\n get length(): number {\n let count = 0\n for (const node of this._nodes) {\n if (!node.tombstone) count++\n }\n return count\n }\n\n /** Drain pending local operations. */\n drainOps(): Operation[] {\n return this._pendingOps.splice(0, this._pendingOps.length)\n }\n\n onChange(callback: TextChangeCallback): () => void {\n this._listeners.add(callback)\n return () => {\n this._listeners.delete(callback)\n }\n }\n\n // ---- Internal -----------------------------------------------------------\n\n /**\n * Insert a node into the correct position in the array.\n * RGA rule: among siblings sharing the same afterId, order by HLC descending\n * (newer inserts appear first, pushing older ones right).\n */\n private _insertNode(node: TextNode): void {\n // Find the position of the parent (afterId).\n let parentIdx: number\n if (node.afterId === null) {\n parentIdx = -1 // insert at beginning\n } else {\n const idx = this._index.get(node.afterId)\n if (idx === undefined) {\n // Parent not found -- append at end (out-of-order delivery).\n parentIdx = this._nodes.length - 1\n } else {\n parentIdx = idx\n }\n }\n\n // Scan right from parentIdx+1 to find insertion point.\n // Skip nodes that were also inserted after the same parent but have a\n // higher HLC (they should appear before this node).\n let insertIdx = parentIdx + 1\n while (insertIdx < this._nodes.length) {\n const existing = this._nodes[insertIdx]\n // Only compare with siblings of the same parent.\n if (existing.afterId !== node.afterId) break\n // Higher HLC goes first (left).\n if (compareHLC(existing.hlc, node.hlc) <= 0) break\n insertIdx++\n }\n\n // Insert and rebuild index for shifted elements.\n this._nodes.splice(insertIdx, 0, node)\n this._rebuildIndex(insertIdx)\n }\n\n /** Rebuild the id->index map from `startIdx` onward. */\n private _rebuildIndex(startIdx: number): void {\n for (let i = startIdx; i < this._nodes.length; i++) {\n this._index.set(this._nodes[i].id, i)\n }\n }\n\n /** Get the position id of the visible character at position `pos`, or null for before-head. */\n private _visibleIdAtPosition(pos: number): string | null {\n if (pos < 0) return null\n let visible = -1\n for (const node of this._nodes) {\n if (!node.tombstone) {\n visible++\n if (visible === pos) return node.id\n }\n }\n // pos is past end -- return last visible id.\n for (let i = this._nodes.length - 1; i >= 0; i--) {\n if (!this._nodes[i].tombstone) return this._nodes[i].id\n }\n return null\n }\n\n /** Get position ids for `length` visible characters starting at `position`. */\n private _visibleIdsInRange(position: number, length: number): string[] {\n const ids: string[] = []\n let visible = -1\n for (const node of this._nodes) {\n if (node.tombstone) continue\n visible++\n if (visible >= position && visible < position + length) {\n ids.push(node.id)\n }\n if (ids.length === length) break\n }\n return ids\n }\n\n private _notifyChange(): void {\n if (this._listeners.size === 0) return\n const text = this.toString()\n for (const cb of this._listeners) {\n try {\n cb(text)\n } catch {\n // listener errors must not break notification\n }\n }\n }\n}\n","/**\n * CRDTCounter -- PN-Counter (positive-negative counter).\n *\n * Each site tracks its own positive and negative totals.\n * The value is sum(positives) - sum(negatives) across all sites.\n * Merge is max() per-site per-direction.\n */\n\nimport { HybridLogicalClock } from './clock.js'\nimport type { Operation, CounterIncrementPayload } from './operations.js'\nimport { makeOpId } from './operations.js'\n\nexport type CounterChangeCallback = (value: number) => void\n\nexport class CRDTCounter {\n /** Per-site positive accumulator. */\n private _positive = new Map<string, number>()\n /** Per-site negative accumulator. */\n private _negative = new Map<string, number>()\n\n private readonly _clock: HybridLogicalClock\n private readonly _documentId: string\n private readonly _field: string\n private readonly _pendingOps: Operation[] = []\n private _listeners = new Set<CounterChangeCallback>()\n\n constructor(documentId: string, field: string, clock: HybridLogicalClock) {\n this._documentId = documentId\n this._field = field\n this._clock = clock\n }\n\n // ---- Public API ---------------------------------------------------------\n\n get value(): number {\n let pos = 0\n let neg = 0\n for (const v of this._positive.values()) pos += v\n for (const v of this._negative.values()) neg += v\n return pos - neg\n }\n\n increment(amount = 1): Operation {\n if (amount === 0) throw new Error('CRDTCounter: amount must be nonzero')\n\n const siteId = this._clock.siteId\n if (amount > 0) {\n this._positive.set(siteId, (this._positive.get(siteId) ?? 0) + amount)\n } else {\n this._negative.set(siteId, (this._negative.get(siteId) ?? 0) + Math.abs(amount))\n }\n\n const hlc = this._clock.now()\n const op: Operation = {\n id: makeOpId(hlc),\n documentId: this._documentId,\n field: this._field,\n hlc,\n type: 'counter.increment',\n payload: { delta: amount } satisfies CounterIncrementPayload,\n }\n\n this._pendingOps.push(op)\n this._notifyChange()\n return op\n }\n\n decrement(amount = 1): Operation {\n return this.increment(-amount)\n }\n\n /** Apply a remote increment operation. */\n applyRemote(op: Operation): void {\n if (op.type !== 'counter.increment') return\n this._clock.receive(op.hlc)\n\n const payload = op.payload as CounterIncrementPayload\n const siteId = op.hlc.siteId\n\n if (payload.delta > 0) {\n this._positive.set(siteId, (this._positive.get(siteId) ?? 0) + payload.delta)\n } else {\n this._negative.set(siteId, (this._negative.get(siteId) ?? 0) + Math.abs(payload.delta))\n }\n\n this._notifyChange()\n }\n\n /** Merge with a remote counter state (for full-state sync). */\n mergeState(positives: Record<string, number>, negatives: Record<string, number>): void {\n for (const [site, val] of Object.entries(positives)) {\n this._positive.set(site, Math.max(this._positive.get(site) ?? 0, val))\n }\n for (const [site, val] of Object.entries(negatives)) {\n this._negative.set(site, Math.max(this._negative.get(site) ?? 0, val))\n }\n this._notifyChange()\n }\n\n /** Export state for full-state sync. */\n exportState(): { positive: Record<string, number>; negative: Record<string, number> } {\n return {\n positive: Object.fromEntries(this._positive),\n negative: Object.fromEntries(this._negative),\n }\n }\n\n drainOps(): Operation[] {\n return this._pendingOps.splice(0, this._pendingOps.length)\n }\n\n onChange(callback: CounterChangeCallback): () => void {\n this._listeners.add(callback)\n return () => {\n this._listeners.delete(callback)\n }\n }\n\n private _notifyChange(): void {\n if (this._listeners.size === 0) return\n const val = this.value\n for (const cb of this._listeners) {\n try {\n cb(val)\n } catch {\n // listener errors must not break notification\n }\n }\n }\n}\n","/**\n * CRDTSet<T> -- Observed-Remove Set (OR-Set).\n *\n * Each add() generates a unique tag. A remove() records the set of tags\n * observed for that value at removal time. The value is present iff it has\n * any tag not covered by a remove.\n *\n * This gives add-wins semantics: a concurrent add and remove of the same\n * value results in the value being present (the new add's tag survives).\n */\n\nimport { HybridLogicalClock } from './clock.js'\nimport type { Operation, SetAddPayload, SetRemovePayload } from './operations.js'\nimport { makeOpId } from './operations.js'\n\nexport type SetChangeCallback<T> = (values: T[]) => void\n\ninterface TaggedEntry<T> {\n value: T\n tags: Set<string>\n}\n\nexport class CRDTSet<T = unknown> {\n /** Map from serialized value key to tagged entry. */\n private _entries = new Map<string, TaggedEntry<T>>()\n\n private readonly _clock: HybridLogicalClock\n private readonly _documentId: string\n private readonly _field: string\n private readonly _pendingOps: Operation[] = []\n private _listeners = new Set<SetChangeCallback<T>>()\n\n constructor(documentId: string, field: string, clock: HybridLogicalClock) {\n this._documentId = documentId\n this._field = field\n this._clock = clock\n }\n\n // ---- Public API ---------------------------------------------------------\n\n get values(): T[] {\n const result: T[] = []\n for (const entry of this._entries.values()) {\n if (entry.tags.size > 0) {\n result.push(entry.value)\n }\n }\n return result\n }\n\n get size(): number {\n let count = 0\n for (const entry of this._entries.values()) {\n if (entry.tags.size > 0) count++\n }\n return count\n }\n\n has(item: T): boolean {\n const key = this._keyOf(item)\n const entry = this._entries.get(key)\n return entry !== undefined && entry.tags.size > 0\n }\n\n add(item: T): Operation {\n const hlc = this._clock.now()\n const tag = makeOpId(hlc)\n const key = this._keyOf(item)\n\n let entry = this._entries.get(key)\n if (!entry) {\n entry = { value: item, tags: new Set() }\n this._entries.set(key, entry)\n }\n entry.tags.add(tag)\n\n const op: Operation = {\n id: tag,\n documentId: this._documentId,\n field: this._field,\n hlc,\n type: 'set.add',\n payload: { value: item, tag } satisfies SetAddPayload,\n }\n\n this._pendingOps.push(op)\n this._notifyChange()\n return op\n }\n\n remove(item: T): Operation {\n const key = this._keyOf(item)\n const entry = this._entries.get(key)\n const observedTags = entry ? Array.from(entry.tags) : []\n\n // Remove all observed tags.\n if (entry) {\n entry.tags.clear()\n }\n\n const hlc = this._clock.now()\n const op: Operation = {\n id: makeOpId(hlc),\n documentId: this._documentId,\n field: this._field,\n hlc,\n type: 'set.remove',\n payload: { value: item, tags: observedTags } satisfies SetRemovePayload,\n }\n\n this._pendingOps.push(op)\n this._notifyChange()\n return op\n }\n\n /** Apply a remote operation. */\n applyRemote(op: Operation): void {\n this._clock.receive(op.hlc)\n\n if (op.type === 'set.add') {\n const payload = op.payload as SetAddPayload\n const key = this._keyOf(payload.value as T)\n let entry = this._entries.get(key)\n if (!entry) {\n entry = { value: payload.value as T, tags: new Set() }\n this._entries.set(key, entry)\n }\n entry.tags.add(payload.tag)\n } else if (op.type === 'set.remove') {\n const payload = op.payload as SetRemovePayload\n const key = this._keyOf(payload.value as T)\n const entry = this._entries.get(key)\n if (entry) {\n for (const tag of payload.tags) {\n entry.tags.delete(tag)\n }\n }\n }\n\n this._notifyChange()\n }\n\n drainOps(): Operation[] {\n return this._pendingOps.splice(0, this._pendingOps.length)\n }\n\n onChange(callback: SetChangeCallback<T>): () => void {\n this._listeners.add(callback)\n return () => {\n this._listeners.delete(callback)\n }\n }\n\n // ---- Internal -----------------------------------------------------------\n\n private _keyOf(value: T): string {\n // Use JSON serialization as the key for value identity.\n return JSON.stringify(value)\n }\n\n private _notifyChange(): void {\n if (this._listeners.size === 0) return\n const vals = this.values\n for (const cb of this._listeners) {\n try {\n cb(vals)\n } catch {\n // listener errors must not break notification\n }\n }\n }\n}\n","/**\n * CRDTRegister<T> -- Last-Writer-Wins Register (LWW-Register).\n *\n * The value with the highest HLC timestamp wins.\n * Ties are broken by site id comparison.\n */\n\nimport type { HLCTimestamp } from './clock.js'\nimport { HybridLogicalClock, compareHLC } from './clock.js'\nimport type { Operation, RegisterSetPayload } from './operations.js'\nimport { makeOpId } from './operations.js'\n\nexport type RegisterChangeCallback<T> = (value: T | undefined) => void\n\nexport class CRDTRegister<T = unknown> {\n private _value: T | undefined = undefined\n private _hlc: HLCTimestamp | null = null\n\n private readonly _clock: HybridLogicalClock\n private readonly _documentId: string\n private readonly _field: string\n private readonly _pendingOps: Operation[] = []\n private _listeners = new Set<RegisterChangeCallback<T>>()\n\n constructor(documentId: string, field: string, clock: HybridLogicalClock) {\n this._documentId = documentId\n this._field = field\n this._clock = clock\n }\n\n // ---- Public API ---------------------------------------------------------\n\n get value(): T | undefined {\n return this._value\n }\n\n set(value: T): Operation {\n const hlc = this._clock.now()\n this._value = value\n this._hlc = hlc\n\n const op: Operation = {\n id: makeOpId(hlc),\n documentId: this._documentId,\n field: this._field,\n hlc,\n type: 'register.set',\n payload: { value } satisfies RegisterSetPayload,\n }\n\n this._pendingOps.push(op)\n this._notifyChange()\n return op\n }\n\n /** Apply a remote set operation. LWW: only apply if remote HLC > current. */\n applyRemote(op: Operation): void {\n if (op.type !== 'register.set') return\n this._clock.receive(op.hlc)\n\n const payload = op.payload as RegisterSetPayload\n\n if (this._hlc === null || compareHLC(op.hlc, this._hlc) > 0) {\n this._value = payload.value as T\n this._hlc = op.hlc\n this._notifyChange()\n }\n }\n\n /** Export current state for full-state sync. */\n exportState(): { value: T | undefined; hlc: HLCTimestamp | null } {\n return { value: this._value, hlc: this._hlc }\n }\n\n /** Import state from full-state sync. LWW merge. */\n importState(value: T, hlc: HLCTimestamp): void {\n if (this._hlc === null || compareHLC(hlc, this._hlc) > 0) {\n this._value = value\n this._hlc = hlc\n this._notifyChange()\n }\n }\n\n drainOps(): Operation[] {\n return this._pendingOps.splice(0, this._pendingOps.length)\n }\n\n onChange(callback: RegisterChangeCallback<T>): () => void {\n this._listeners.add(callback)\n return () => {\n this._listeners.delete(callback)\n }\n }\n\n private _notifyChange(): void {\n if (this._listeners.size === 0) return\n const val = this._value\n for (const cb of this._listeners) {\n try {\n cb(val)\n } catch {\n // listener errors must not break notification\n }\n }\n }\n}\n","/**\n * CRDTDocument -- container for collaborative fields.\n *\n * A document holds named CRDT fields (text, counter, set, register) that\n * share a single HLC clock and sync channel. Operations from all fields\n * are collected and sent to the server together.\n */\n\nimport { HybridLogicalClock } from './clock.js'\nimport { CRDTText } from './text.js'\nimport { CRDTCounter } from './counter.js'\nimport { CRDTSet } from './set.js'\nimport { CRDTRegister } from './register.js'\nimport type { Operation } from './operations.js'\n\nexport type DocumentChangeCallback = (ops: Operation[]) => void\n\nexport class CRDTDocument {\n readonly id: string\n readonly clock: HybridLogicalClock\n\n private _texts = new Map<string, CRDTText>()\n private _counters = new Map<string, CRDTCounter>()\n private _sets = new Map<string, CRDTSet>()\n private _registers = new Map<string, CRDTRegister>()\n private _listeners = new Set<DocumentChangeCallback>()\n\n /** Buffer for ops not yet synced. */\n private _unsyncedOps: Operation[] = []\n\n constructor(id: string, siteId?: string) {\n this.id = id\n this.clock = new HybridLogicalClock(siteId)\n }\n\n // ---- Field accessors ----------------------------------------------------\n\n getText(field: string): CRDTText {\n let t = this._texts.get(field)\n if (!t) {\n t = new CRDTText(this.id, field, this.clock)\n this._texts.set(field, t)\n }\n return t\n }\n\n getCounter(field: string): CRDTCounter {\n let c = this._counters.get(field)\n if (!c) {\n c = new CRDTCounter(this.id, field, this.clock)\n this._counters.set(field, c)\n }\n return c\n }\n\n getSet<T = unknown>(field: string): CRDTSet<T> {\n let s = this._sets.get(field)\n if (!s) {\n s = new CRDTSet(this.id, field, this.clock)\n this._sets.set(field, s)\n }\n return s as CRDTSet<T>\n }\n\n getRegister<T = unknown>(field: string): CRDTRegister<T> {\n let r = this._registers.get(field)\n if (!r) {\n r = new CRDTRegister(this.id, field, this.clock)\n this._registers.set(field, r)\n }\n return r as CRDTRegister<T>\n }\n\n // ---- Operation collection -----------------------------------------------\n\n /**\n * Collect all pending local operations from all fields.\n * Drains the per-field op buffers and returns them.\n */\n collectOps(): Operation[] {\n const ops: Operation[] = []\n for (const t of this._texts.values()) ops.push(...t.drainOps())\n for (const c of this._counters.values()) ops.push(...c.drainOps())\n for (const s of this._sets.values()) ops.push(...s.drainOps())\n for (const r of this._registers.values()) ops.push(...r.drainOps())\n this._unsyncedOps.push(...ops)\n return ops\n }\n\n /**\n * Acknowledge that operations up to and including `opId` have been\n * persisted by the server. Removes them from the unsynced buffer.\n */\n acknowledge(opId: string): void {\n const idx = this._unsyncedOps.findIndex((op) => op.id === opId)\n if (idx >= 0) {\n this._unsyncedOps.splice(0, idx + 1)\n }\n }\n\n /** Get operations that have not been acknowledged by the server. */\n getUnsyncedOps(): readonly Operation[] {\n return this._unsyncedOps\n }\n\n // ---- Remote operation application ---------------------------------------\n\n /**\n * Apply a batch of remote operations to the appropriate CRDT fields.\n */\n applyRemoteOps(ops: Operation[]): void {\n for (const op of ops) {\n if (op.documentId !== this.id) continue\n this._applyRemoteOp(op)\n }\n }\n\n private _applyRemoteOp(op: Operation): void {\n switch (op.type) {\n case 'text.insert':\n case 'text.delete': {\n const t = this.getText(op.field)\n t.applyRemote(op)\n break\n }\n case 'counter.increment': {\n const c = this.getCounter(op.field)\n c.applyRemote(op)\n break\n }\n case 'set.add':\n case 'set.remove': {\n const s = this.getSet(op.field)\n s.applyRemote(op)\n break\n }\n case 'register.set': {\n const r = this.getRegister(op.field)\n r.applyRemote(op)\n break\n }\n }\n }\n\n // ---- Serialization ------------------------------------------------------\n\n /**\n * Encode all pending operations as a Uint8Array (JSON wire format).\n * Used for WebSocket transmission.\n */\n encode(): Uint8Array {\n const ops = this.collectOps()\n const json = JSON.stringify({\n documentId: this.id,\n siteId: this.clock.siteId,\n ops,\n })\n return new TextEncoder().encode(json)\n }\n\n /**\n * Decode and apply a remote message (Uint8Array or string).\n */\n decode(data: Uint8Array | string): void {\n const text = typeof data === 'string' ? data : new TextDecoder().decode(data)\n const msg = JSON.parse(text) as { documentId: string; siteId: string; ops: Operation[] }\n\n if (msg.documentId !== this.id) return\n // Do not apply our own operations.\n if (msg.siteId === this.clock.siteId) return\n\n this.applyRemoteOps(msg.ops)\n this._notifyChange(msg.ops)\n }\n\n // ---- Change notifications -----------------------------------------------\n\n onChange(callback: DocumentChangeCallback): () => void {\n this._listeners.add(callback)\n return () => {\n this._listeners.delete(callback)\n }\n }\n\n private _notifyChange(ops: Operation[]): void {\n for (const cb of this._listeners) {\n try {\n cb(ops)\n } catch {\n // listener errors must not break notification\n }\n }\n }\n}\n"]}
|