@pantheon-systems/css-client 0.4.0

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 (89) hide show
  1. package/dist/auth.d.ts +54 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +72 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/broker.d.ts +41 -0
  6. package/dist/broker.d.ts.map +1 -0
  7. package/dist/broker.js +187 -0
  8. package/dist/broker.js.map +1 -0
  9. package/dist/client.d.ts +138 -0
  10. package/dist/client.d.ts.map +1 -0
  11. package/dist/client.js +130 -0
  12. package/dist/client.js.map +1 -0
  13. package/dist/content.d.ts +45 -0
  14. package/dist/content.d.ts.map +1 -0
  15. package/dist/content.js +65 -0
  16. package/dist/content.js.map +1 -0
  17. package/dist/endpoints/agent-edit.d.ts +79 -0
  18. package/dist/endpoints/agent-edit.d.ts.map +1 -0
  19. package/dist/endpoints/agent-edit.js +125 -0
  20. package/dist/endpoints/agent-edit.js.map +1 -0
  21. package/dist/endpoints/agent-registry.d.ts +59 -0
  22. package/dist/endpoints/agent-registry.d.ts.map +1 -0
  23. package/dist/endpoints/agent-registry.js +96 -0
  24. package/dist/endpoints/agent-registry.js.map +1 -0
  25. package/dist/endpoints/base.d.ts +49 -0
  26. package/dist/endpoints/base.d.ts.map +1 -0
  27. package/dist/endpoints/base.js +150 -0
  28. package/dist/endpoints/base.js.map +1 -0
  29. package/dist/endpoints/branches.d.ts +32 -0
  30. package/dist/endpoints/branches.d.ts.map +1 -0
  31. package/dist/endpoints/branches.js +69 -0
  32. package/dist/endpoints/branches.js.map +1 -0
  33. package/dist/endpoints/checkpoints.d.ts +36 -0
  34. package/dist/endpoints/checkpoints.d.ts.map +1 -0
  35. package/dist/endpoints/checkpoints.js +76 -0
  36. package/dist/endpoints/checkpoints.js.map +1 -0
  37. package/dist/endpoints/documents.d.ts +46 -0
  38. package/dist/endpoints/documents.d.ts.map +1 -0
  39. package/dist/endpoints/documents.js +101 -0
  40. package/dist/endpoints/documents.js.map +1 -0
  41. package/dist/endpoints/index.d.ts +15 -0
  42. package/dist/endpoints/index.d.ts.map +1 -0
  43. package/dist/endpoints/index.js +16 -0
  44. package/dist/endpoints/index.js.map +1 -0
  45. package/dist/endpoints/merge.d.ts +51 -0
  46. package/dist/endpoints/merge.d.ts.map +1 -0
  47. package/dist/endpoints/merge.js +104 -0
  48. package/dist/endpoints/merge.js.map +1 -0
  49. package/dist/endpoints/presence.d.ts +55 -0
  50. package/dist/endpoints/presence.d.ts.map +1 -0
  51. package/dist/endpoints/presence.js +72 -0
  52. package/dist/endpoints/presence.js.map +1 -0
  53. package/dist/endpoints/sites.d.ts +20 -0
  54. package/dist/endpoints/sites.d.ts.map +1 -0
  55. package/dist/endpoints/sites.js +38 -0
  56. package/dist/endpoints/sites.js.map +1 -0
  57. package/dist/endpoints/versions.d.ts +37 -0
  58. package/dist/endpoints/versions.d.ts.map +1 -0
  59. package/dist/endpoints/versions.js +64 -0
  60. package/dist/endpoints/versions.js.map +1 -0
  61. package/dist/errors.d.ts +61 -0
  62. package/dist/errors.d.ts.map +1 -0
  63. package/dist/errors.js +87 -0
  64. package/dist/errors.js.map +1 -0
  65. package/dist/index.d.ts +20 -0
  66. package/dist/index.d.ts.map +1 -0
  67. package/dist/index.js +20 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/jwt-utils.d.ts +13 -0
  70. package/dist/jwt-utils.d.ts.map +1 -0
  71. package/dist/jwt-utils.js +45 -0
  72. package/dist/jwt-utils.js.map +1 -0
  73. package/dist/oauth.d.ts +64 -0
  74. package/dist/oauth.d.ts.map +1 -0
  75. package/dist/oauth.js +62 -0
  76. package/dist/oauth.js.map +1 -0
  77. package/dist/realtime.d.ts +314 -0
  78. package/dist/realtime.d.ts.map +1 -0
  79. package/dist/realtime.js +615 -0
  80. package/dist/realtime.js.map +1 -0
  81. package/dist/types.d.ts +703 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +7 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/utils.d.ts +3 -0
  86. package/dist/utils.d.ts.map +1 -0
  87. package/dist/utils.js +17 -0
  88. package/dist/utils.js.map +1 -0
  89. package/package.json +56 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-utils.d.ts","sourceRoot":"","sources":["../src/jwt-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAU7E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAK/D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CASnE"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * JWT Utility Functions
3
+ *
4
+ * Shared helpers for parsing JWT payloads and checking expiry.
5
+ * These decode JWTs for display/routing only — no cryptographic verification.
6
+ */
7
+ export const TOKEN_REFRESH_BUFFER_SECONDS = 300;
8
+ export function parseJwtPayload(token) {
9
+ try {
10
+ const parts = token.split('.');
11
+ const payload = parts[1];
12
+ if (!payload)
13
+ return null;
14
+ const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));
15
+ return JSON.parse(decoded);
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ export function getTokenExpiry(token) {
22
+ const payload = parseJwtPayload(token);
23
+ if (!payload || typeof payload.exp !== 'number')
24
+ return null;
25
+ return payload.exp;
26
+ }
27
+ export function isTokenExpiredOrExpiring(token) {
28
+ const exp = getTokenExpiry(token);
29
+ if (exp === null)
30
+ return false;
31
+ const nowSeconds = Math.floor(Date.now() / 1000);
32
+ return nowSeconds >= exp - TOKEN_REFRESH_BUFFER_SECONDS;
33
+ }
34
+ export function extractUserInfo(token) {
35
+ const payload = parseJwtPayload(token);
36
+ if (!payload || typeof payload.sub !== 'string')
37
+ return null;
38
+ return {
39
+ id: payload.sub,
40
+ email: payload.email,
41
+ name: payload.name,
42
+ picture: payload.picture,
43
+ };
44
+ }
45
+ //# sourceMappingURL=jwt-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-utils.js","sourceRoot":"","sources":["../src/jwt-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7D,OAAO,OAAO,CAAC,GAAG,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,KAAa;IACpD,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IACjD,OAAO,UAAU,IAAI,GAAG,GAAG,4BAA4B,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7D,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,GAAG;QACf,KAAK,EAAE,OAAO,CAAC,KAA2B;QAC1C,IAAI,EAAE,OAAO,CAAC,IAA0B;QACxC,OAAO,EAAE,OAAO,CAAC,OAA6B;KAC/C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,64 @@
1
+ import type { AuthProvider } from './auth.js';
2
+ /** User info returned from OAuth providers */
3
+ export interface OAuthUserInfo {
4
+ id: string;
5
+ email?: string;
6
+ name?: string;
7
+ picture?: string;
8
+ }
9
+ export interface OAuthSession {
10
+ provider: 'broker';
11
+ login(): Promise<void>;
12
+ logout(): Promise<void>;
13
+ isAuthenticated(): boolean;
14
+ getUserInfo(): OAuthUserInfo | null;
15
+ getToken(): Promise<string | null>;
16
+ }
17
+ /**
18
+ * Create an AuthProvider from an OAuthSession.
19
+ * The returned AuthProvider is compatible with P1Client's authProvider config option.
20
+ *
21
+ * @param session - The OAuth session to derive the auth provider from
22
+ * @returns AuthProvider function that returns `Bearer <token>`
23
+ */
24
+ export declare function createOAuthAuthProvider(session: OAuthSession): AuthProvider;
25
+ export interface AuthMeResponse {
26
+ id: string;
27
+ type: string;
28
+ email?: string;
29
+ name?: string;
30
+ avatarUrl?: string;
31
+ authProvider?: string;
32
+ tokenExpiry?: string;
33
+ providerSubjectId?: string;
34
+ }
35
+ /**
36
+ * Validate a token against the P1 backend's /api/auth/me endpoint.
37
+ * Framework-agnostic — works in any JS environment with fetch().
38
+ *
39
+ * @param baseUrl - P1 backend base URL (e.g., "http://localhost:8787")
40
+ * @param token - Bearer token to validate
41
+ * @returns The authenticated user info, or null if the token is invalid
42
+ */
43
+ export declare function validateToken(baseUrl: string, token: string): Promise<AuthMeResponse | null>;
44
+ /**
45
+ * Login as a mock/demo user via POST /api/auth/token.
46
+ * Framework-agnostic — works in any JS environment with fetch().
47
+ *
48
+ * @internal This is a local-development helper. The backend only enables
49
+ * `/api/auth/token` when `ENVIRONMENT === 'local'`; mock tokens are rejected
50
+ * by all other environments. Do not use in production deployments.
51
+ *
52
+ * @param baseUrl - P1 backend base URL
53
+ * @param userId - The mock user ID to log in as
54
+ * @returns Token and user info
55
+ */
56
+ export declare function loginMockUser(baseUrl: string, userId: string): Promise<{
57
+ token: string;
58
+ user: {
59
+ id: string;
60
+ name: string;
61
+ email: string;
62
+ };
63
+ }>;
64
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,eAAe,IAAI,OAAO,CAAC;IAC3B,WAAW,IAAI,aAAa,GAAG,IAAI,CAAC;IACpC,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACpC;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,YAAY,CAQ3E;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAUhC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAgB/E"}
package/dist/oauth.js ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Create an AuthProvider from an OAuthSession.
3
+ * The returned AuthProvider is compatible with P1Client's authProvider config option.
4
+ *
5
+ * @param session - The OAuth session to derive the auth provider from
6
+ * @returns AuthProvider function that returns `Bearer <token>`
7
+ */
8
+ export function createOAuthAuthProvider(session) {
9
+ return async () => {
10
+ const token = await session.getToken();
11
+ if (!token) {
12
+ throw new Error('No OAuth token available. Please log in first.');
13
+ }
14
+ return `Bearer ${token}`;
15
+ };
16
+ }
17
+ /**
18
+ * Validate a token against the P1 backend's /api/auth/me endpoint.
19
+ * Framework-agnostic — works in any JS environment with fetch().
20
+ *
21
+ * @param baseUrl - P1 backend base URL (e.g., "http://localhost:8787")
22
+ * @param token - Bearer token to validate
23
+ * @returns The authenticated user info, or null if the token is invalid
24
+ */
25
+ export async function validateToken(baseUrl, token) {
26
+ try {
27
+ const response = await fetch(`${baseUrl}/api/auth/me`, {
28
+ headers: { Authorization: `Bearer ${token}` },
29
+ });
30
+ if (!response.ok)
31
+ return null;
32
+ return (await response.json());
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ /**
39
+ * Login as a mock/demo user via POST /api/auth/token.
40
+ * Framework-agnostic — works in any JS environment with fetch().
41
+ *
42
+ * @internal This is a local-development helper. The backend only enables
43
+ * `/api/auth/token` when `ENVIRONMENT === 'local'`; mock tokens are rejected
44
+ * by all other environments. Do not use in production deployments.
45
+ *
46
+ * @param baseUrl - P1 backend base URL
47
+ * @param userId - The mock user ID to log in as
48
+ * @returns Token and user info
49
+ */
50
+ export async function loginMockUser(baseUrl, userId) {
51
+ const response = await fetch(`${baseUrl}/api/auth/token`, {
52
+ method: 'POST',
53
+ headers: { 'Content-Type': 'application/json' },
54
+ body: JSON.stringify({ userId }),
55
+ });
56
+ if (!response.ok) {
57
+ const error = await response.json().catch(() => ({ error: 'Login failed' }));
58
+ throw new Error(error.error ?? 'Login failed');
59
+ }
60
+ return response.json();
61
+ }
62
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAoBA;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAqB;IAC3D,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,UAAU,KAAK,EAAE,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC;AAaD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,cAAc,EAAE;YACrD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;SAC9C,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAC9B,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmB,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,MAAc;IAEd,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,iBAAiB,EAAE;QACxD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACjC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAE,KAA4B,CAAC,KAAK,IAAI,cAAc,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAGlB,CAAC;AACL,CAAC"}
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Phase 2.1: RealtimeClient
3
+ *
4
+ * WebSocket-based real-time collaboration client using Yjs CRDT.
5
+ * Provides bidirectional sync between client and DocumentSession Durable Object.
6
+ * Uses ReconnectingWebSocket from partysocket for automatic reconnection with exponential backoff.
7
+ */
8
+ import * as Y from 'yjs';
9
+ import type { ActorPresence, ActorState, PublishResult } from './types';
10
+ /**
11
+ * Configuration for reconnection behavior
12
+ */
13
+ export interface ReconnectionConfig {
14
+ /**
15
+ * Maximum number of reconnection attempts.
16
+ * Set to Infinity for unlimited retries.
17
+ * @default Infinity
18
+ */
19
+ maxRetries?: number;
20
+ /**
21
+ * Minimum delay between reconnection attempts in milliseconds.
22
+ * @default 1000
23
+ */
24
+ minReconnectionDelay?: number;
25
+ /**
26
+ * Maximum delay between reconnection attempts in milliseconds.
27
+ * @default 30000
28
+ */
29
+ maxReconnectionDelay?: number;
30
+ /**
31
+ * Factor by which to multiply the delay for each retry (exponential backoff).
32
+ * @default 1.5
33
+ */
34
+ reconnectionDelayGrowFactor?: number;
35
+ }
36
+ /**
37
+ * Configuration for the RealtimeClient
38
+ */
39
+ export interface RealtimeClientConfig {
40
+ /**
41
+ * Base URL for WebSocket connections.
42
+ * Can be ws:// or wss:// protocol.
43
+ * Example: "wss://api.example.com" or "ws://localhost:8787"
44
+ */
45
+ baseUrl: string;
46
+ /**
47
+ * API key for authentication.
48
+ * Will be passed as a query parameter since browsers can't send
49
+ * custom headers with WebSocket upgrade requests.
50
+ */
51
+ apiKey?: string;
52
+ /**
53
+ * Callback when document state is updated (from remote changes)
54
+ */
55
+ onUpdate?: (snapshot: Record<string, unknown>) => void;
56
+ /**
57
+ * Callback when WebSocket connection is established
58
+ */
59
+ onConnect?: () => void;
60
+ /**
61
+ * Callback when WebSocket connection is closed
62
+ */
63
+ onDisconnect?: () => void;
64
+ /**
65
+ * Callback when an error occurs
66
+ */
67
+ onError?: (error: Error) => void;
68
+ /**
69
+ * Callback when attempting to reconnect after a connection loss.
70
+ * Called with the current retry attempt number.
71
+ */
72
+ onReconnecting?: (attempt: number) => void;
73
+ /**
74
+ * Callback when authorization fails (WebSocket close code 4401 or 4403).
75
+ * This indicates the session is invalid or the agent lacks permission.
76
+ * When this is called, the client will NOT attempt to reconnect.
77
+ */
78
+ onAuthorizationError?: (error: Error) => void;
79
+ /**
80
+ * Callback when presence update is received from server.
81
+ * Called with the full list of actors in the document.
82
+ */
83
+ onPresenceUpdate?: (actors: ActorPresence[]) => void;
84
+ /**
85
+ * Callback when another actor updates their focus regions.
86
+ * Called with the actor ID and their new focus regions.
87
+ */
88
+ onFocusRegionBroadcast?: (actorId: string, focusRegions: string[]) => void;
89
+ /**
90
+ * Configuration for automatic reconnection behavior.
91
+ */
92
+ reconnection?: ReconnectionConfig;
93
+ /**
94
+ * Callback when the server sends a RATE_LIMITED error.
95
+ * The client remains connected; this is informational.
96
+ */
97
+ onRateLimited?: () => void;
98
+ /**
99
+ * Optional token refresher for dynamic WebSocket authentication.
100
+ * Called when the WebSocket connection closes unexpectedly (non-intentionally).
101
+ * Should return a fresh token string, or null if the session cannot be refreshed.
102
+ * The fresh token is used in subsequent reconnection URLs.
103
+ */
104
+ tokenRefresher?: () => Promise<string | null>;
105
+ }
106
+ /**
107
+ * Parameters for connecting to a document session
108
+ */
109
+ export interface ConnectionParams {
110
+ /** Site ID */
111
+ siteId: string;
112
+ /** Branch ID */
113
+ branchId: string;
114
+ /** Document path (e.g., "pages/home") */
115
+ documentPath: string;
116
+ /** Actor ID (user or agent ID) */
117
+ actorId: string;
118
+ /** Actor type */
119
+ actorType: 'user' | 'agent';
120
+ /**
121
+ * Session ID for agent authorization.
122
+ * Required for agents, obtained from startEdit() response.
123
+ * Enables server-side enforcement of the Agent Politeness Protocol.
124
+ */
125
+ sessionId?: string;
126
+ }
127
+ /**
128
+ * Real-time collaboration client using Yjs CRDT over WebSocket.
129
+ * Uses PartySocket for automatic reconnection with exponential backoff.
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const client = new RealtimeClient({
134
+ * baseUrl: 'wss://api.example.com',
135
+ * onUpdate: (snapshot) => {
136
+ * console.log('Document updated:', snapshot);
137
+ * },
138
+ * onReconnecting: (attempt) => {
139
+ * console.log(`Reconnecting... attempt ${attempt}`);
140
+ * },
141
+ * reconnection: {
142
+ * maxRetries: 10,
143
+ * minReconnectionDelay: 1000,
144
+ * maxReconnectionDelay: 30000,
145
+ * },
146
+ * });
147
+ *
148
+ * client.connect({
149
+ * siteId: 'site-123',
150
+ * branchId: 'branch-456',
151
+ * documentPath: 'pages/home',
152
+ * actorId: 'user-789',
153
+ * actorType: 'user',
154
+ * });
155
+ *
156
+ * // When done
157
+ * client.disconnect();
158
+ * ```
159
+ */
160
+ export declare class RealtimeClient {
161
+ private readonly config;
162
+ private readonly ydoc;
163
+ private ws;
164
+ private connected;
165
+ private intentionalDisconnect;
166
+ private currentApiKey;
167
+ private tokenRefreshInFlight;
168
+ private hasConnectedOnce;
169
+ private lastReportedRetryCount;
170
+ private reconnectCheckInterval;
171
+ private visibilityHandler;
172
+ private sendTimestamps;
173
+ private pendingUpdates;
174
+ private flushTimer;
175
+ private static readonly RATE_THRESHOLD;
176
+ private static readonly RATE_WINDOW_MS;
177
+ private lastSentSnapshot;
178
+ private pendingDeliveryAcks;
179
+ private static readonly DELIVERY_ACK_TIMEOUT_MS;
180
+ private pendingPublishRequests;
181
+ private static readonly PUBLISH_TIMEOUT_MS;
182
+ private pendingActionMetadata;
183
+ constructor(config: RealtimeClientConfig);
184
+ /**
185
+ * Connect to a document session via WebSocket.
186
+ * Uses PartySocket for automatic reconnection on connection loss.
187
+ *
188
+ * @param params - Connection parameters including site, branch, document, and actor info
189
+ */
190
+ connect(params: ConnectionParams): void;
191
+ /**
192
+ * Start monitoring for reconnection attempts by polling retryCount.
193
+ * This is needed because PartySocket doesn't expose a reconnection callback.
194
+ */
195
+ private startReconnectMonitoring;
196
+ /**
197
+ * Stop the reconnection monitoring interval.
198
+ */
199
+ private stopReconnectMonitoring;
200
+ /**
201
+ * Start monitoring for page visibility changes.
202
+ * When the page becomes visible after being hidden, check connection health
203
+ * and force a reconnection sync if needed.
204
+ */
205
+ private startVisibilityMonitoring;
206
+ /**
207
+ * Stop visibility change monitoring.
208
+ */
209
+ private stopVisibilityMonitoring;
210
+ /**
211
+ * Disconnect from the current session.
212
+ * This permanently closes the connection and stops any reconnection attempts.
213
+ */
214
+ disconnect(): void;
215
+ /**
216
+ * Apply a local Yjs update.
217
+ * This is typically called from Puck-Yjs binding when local edits occur.
218
+ * Uses rate-aware sending to avoid exceeding the server's rate limit.
219
+ *
220
+ * @param update - Raw Yjs update bytes
221
+ */
222
+ applyLocalUpdate(update: Uint8Array): void;
223
+ /**
224
+ * Set pending action metadata to be sent after the next CRDT update.
225
+ * The metadata is best-effort — if the WebSocket is not open or the
226
+ * send fails, the CRDT update still goes through without metadata.
227
+ *
228
+ * @param meta - Action type and metadata from Puck's onAction callback
229
+ */
230
+ setActionMetadata(meta: {
231
+ actionType: string;
232
+ actionMetadata: Record<string, unknown>;
233
+ } | null): void;
234
+ /**
235
+ * Send any pending action metadata as a text message and clear it.
236
+ * Called after a CRDT update is sent to associate the metadata with
237
+ * the most recent edit.
238
+ */
239
+ sendPendingActionMetadata(): void;
240
+ /**
241
+ * Send a Yjs update with rate awareness.
242
+ * Sends immediately when under the threshold (40 msgs/sec).
243
+ * Buffers and coalesces updates when approaching the server's 50 msg/sec limit.
244
+ */
245
+ private rateLimitedSend;
246
+ /**
247
+ * Schedule a flush of buffered updates after the rate window resets.
248
+ */
249
+ private scheduleFlush;
250
+ /**
251
+ * Flush all buffered updates as a single coalesced message.
252
+ */
253
+ private flushPendingUpdates;
254
+ /**
255
+ * Get the current document snapshot as JSON.
256
+ */
257
+ getSnapshot(): Record<string, unknown>;
258
+ /**
259
+ * Get the underlying Y.Doc for direct manipulation.
260
+ * Use with caution - prefer using the Puck-Yjs binding utilities.
261
+ */
262
+ getYDoc(): Y.Doc;
263
+ /**
264
+ * Check if currently connected.
265
+ */
266
+ isConnected(): boolean;
267
+ /**
268
+ * Check if presence updates are available via WebSocket.
269
+ * Returns true when connected and able to send/receive presence messages.
270
+ */
271
+ get presenceViaWebSocket(): boolean;
272
+ /**
273
+ * Send focus regions update to the server.
274
+ * @param focusRegions - JSON paths the actor is focused on
275
+ * @returns true if message was sent, false if not connected
276
+ */
277
+ sendFocusRegions(focusRegions: string[]): boolean;
278
+ /**
279
+ * Send a presence heartbeat to keep the connection alive.
280
+ * @param state - Optional state update (active, idle, editing)
281
+ */
282
+ sendHeartbeat(state?: ActorState): void;
283
+ /**
284
+ * Wait for the server to acknowledge that all preceding WebSocket messages
285
+ * have been processed. This uses TCP ordering guarantees: a text frame sent
286
+ * after binary CRDT updates is guaranteed to arrive after those updates.
287
+ * The server echoes back a delivery_ack with the matching requestId.
288
+ *
289
+ * Used before publish to ensure the Durable Object has received and applied
290
+ * the latest edits before the HTTP publish request arrives.
291
+ *
292
+ * @returns Promise that resolves when the server confirms delivery
293
+ * @throws Error if not connected or if timeout expires (5 seconds)
294
+ */
295
+ waitForDelivery(): Promise<void>;
296
+ /**
297
+ * Request the server to publish the current document via WebSocket.
298
+ * TCP ordering guarantees all preceding binary CRDT updates have been
299
+ * processed before this message is handled, eliminating stale-version races.
300
+ *
301
+ * The Durable Object handles the entire flow: flush to Postgres, then
302
+ * call /internal/publish to create the checkpoint.
303
+ *
304
+ * @returns Promise that resolves with the publish result
305
+ * @throws Error if not connected or if timeout expires (30 seconds)
306
+ */
307
+ requestPublish(): Promise<PublishResult>;
308
+ /**
309
+ * Handle incoming text (JSON) messages for presence protocol.
310
+ * @param data - Raw JSON string from WebSocket
311
+ */
312
+ private handleTextMessage;
313
+ }
314
+ //# sourceMappingURL=realtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"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"}