@sylphx/lens-server 1.11.3 → 2.1.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.
- package/dist/index.d.ts +1262 -262
- package/dist/index.js +1714 -1154
- package/package.json +2 -2
- package/src/context/index.test.ts +425 -0
- package/src/context/index.ts +90 -0
- package/src/e2e/server.test.ts +215 -433
- package/src/handlers/framework.ts +294 -0
- package/src/handlers/http.test.ts +215 -0
- package/src/handlers/http.ts +189 -0
- package/src/handlers/index.ts +55 -0
- package/src/handlers/unified.ts +114 -0
- package/src/handlers/ws-types.ts +126 -0
- package/src/handlers/ws.ts +669 -0
- package/src/index.ts +127 -24
- package/src/plugin/index.ts +41 -0
- package/src/plugin/op-log.ts +286 -0
- package/src/plugin/optimistic.ts +375 -0
- package/src/plugin/types.ts +551 -0
- package/src/reconnect/index.ts +9 -0
- package/src/reconnect/operation-log.test.ts +480 -0
- package/src/reconnect/operation-log.ts +450 -0
- package/src/server/create.test.ts +256 -2193
- package/src/server/create.ts +285 -1481
- package/src/server/dataloader.ts +60 -0
- package/src/server/selection.ts +123 -0
- package/src/server/types.ts +306 -0
- package/src/sse/handler.ts +123 -56
- package/src/state/index.ts +9 -11
- package/src/storage/index.ts +26 -0
- package/src/storage/memory.ts +279 -0
- package/src/storage/types.ts +205 -0
- package/src/state/graph-state-manager.test.ts +0 -1105
- package/src/state/graph-state-manager.ts +0 -890
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sylphx/lens-server - Storage Types
|
|
3
|
+
*
|
|
4
|
+
* Storage adapter interface for opLog plugin.
|
|
5
|
+
* Enables serverless support by abstracting state/version/patch storage.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { PatchOperation } from "@sylphx/lens-core";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Entity state stored in the operation log.
|
|
12
|
+
*/
|
|
13
|
+
export interface StoredEntityState {
|
|
14
|
+
/** Canonical state data */
|
|
15
|
+
data: Record<string, unknown>;
|
|
16
|
+
/** Current version */
|
|
17
|
+
version: number;
|
|
18
|
+
/** Timestamp of last update */
|
|
19
|
+
updatedAt: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Operation log entry stored in storage.
|
|
24
|
+
*/
|
|
25
|
+
export interface StoredPatchEntry {
|
|
26
|
+
/** Version this patch creates */
|
|
27
|
+
version: number;
|
|
28
|
+
/** Patch operations */
|
|
29
|
+
patch: PatchOperation[];
|
|
30
|
+
/** Timestamp when patch was created */
|
|
31
|
+
timestamp: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Result from emit operation.
|
|
36
|
+
*/
|
|
37
|
+
export interface EmitResult {
|
|
38
|
+
/** New version after emit */
|
|
39
|
+
version: number;
|
|
40
|
+
/** Computed patch (null if first emit) */
|
|
41
|
+
patch: PatchOperation[] | null;
|
|
42
|
+
/** Whether state actually changed */
|
|
43
|
+
changed: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Storage adapter interface for opLog.
|
|
48
|
+
*
|
|
49
|
+
* Implementations:
|
|
50
|
+
* - `memoryStorage()` - In-memory (default, for long-running servers)
|
|
51
|
+
* - `redisStorage()` - Redis/Upstash (for serverless)
|
|
52
|
+
* - `kvStorage()` - Cloudflare KV, Vercel KV
|
|
53
|
+
*
|
|
54
|
+
* All methods are async to support external storage.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* // Default (in-memory)
|
|
59
|
+
* const app = createApp({
|
|
60
|
+
* router,
|
|
61
|
+
* plugins: [opLog()],
|
|
62
|
+
* });
|
|
63
|
+
*
|
|
64
|
+
* // With Redis for serverless
|
|
65
|
+
* const app = createApp({
|
|
66
|
+
* router,
|
|
67
|
+
* plugins: [opLog({
|
|
68
|
+
* storage: redisStorage({ url: process.env.REDIS_URL }),
|
|
69
|
+
* })],
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export interface OpLogStorage {
|
|
74
|
+
/**
|
|
75
|
+
* Emit new state for an entity.
|
|
76
|
+
* This is an atomic operation that:
|
|
77
|
+
* 1. Computes patch from previous state (if exists)
|
|
78
|
+
* 2. Stores new state with incremented version
|
|
79
|
+
* 3. Appends patch to operation log
|
|
80
|
+
*
|
|
81
|
+
* @param entity - Entity type name
|
|
82
|
+
* @param entityId - Entity ID
|
|
83
|
+
* @param data - New state data
|
|
84
|
+
* @returns Emit result with version, patch, and changed flag
|
|
85
|
+
*/
|
|
86
|
+
emit(entity: string, entityId: string, data: Record<string, unknown>): Promise<EmitResult>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get current canonical state for an entity.
|
|
90
|
+
*
|
|
91
|
+
* @param entity - Entity type name
|
|
92
|
+
* @param entityId - Entity ID
|
|
93
|
+
* @returns State data or null if not found
|
|
94
|
+
*/
|
|
95
|
+
getState(entity: string, entityId: string): Promise<Record<string, unknown> | null>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Get current version for an entity.
|
|
99
|
+
* Returns 0 if entity doesn't exist.
|
|
100
|
+
*
|
|
101
|
+
* @param entity - Entity type name
|
|
102
|
+
* @param entityId - Entity ID
|
|
103
|
+
* @returns Current version (0 if not found)
|
|
104
|
+
*/
|
|
105
|
+
getVersion(entity: string, entityId: string): Promise<number>;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get the latest patch for an entity.
|
|
109
|
+
* Returns null if no patches available.
|
|
110
|
+
*
|
|
111
|
+
* @param entity - Entity type name
|
|
112
|
+
* @param entityId - Entity ID
|
|
113
|
+
* @returns Latest patch or null
|
|
114
|
+
*/
|
|
115
|
+
getLatestPatch(entity: string, entityId: string): Promise<PatchOperation[] | null>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Get all patches since a given version.
|
|
119
|
+
* Used for reconnection to bring client up to date.
|
|
120
|
+
*
|
|
121
|
+
* @param entity - Entity type name
|
|
122
|
+
* @param entityId - Entity ID
|
|
123
|
+
* @param sinceVersion - Client's current version
|
|
124
|
+
* @returns Array of patches (one per version), or null if too old
|
|
125
|
+
*/
|
|
126
|
+
getPatchesSince(
|
|
127
|
+
entity: string,
|
|
128
|
+
entityId: string,
|
|
129
|
+
sinceVersion: number,
|
|
130
|
+
): Promise<PatchOperation[][] | null>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check if entity exists in storage.
|
|
134
|
+
*
|
|
135
|
+
* @param entity - Entity type name
|
|
136
|
+
* @param entityId - Entity ID
|
|
137
|
+
* @returns True if entity exists
|
|
138
|
+
*/
|
|
139
|
+
has(entity: string, entityId: string): Promise<boolean>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Delete an entity from storage.
|
|
143
|
+
* Removes state, version, and all patches.
|
|
144
|
+
*
|
|
145
|
+
* @param entity - Entity type name
|
|
146
|
+
* @param entityId - Entity ID
|
|
147
|
+
*/
|
|
148
|
+
delete(entity: string, entityId: string): Promise<void>;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Clear all data from storage.
|
|
152
|
+
* Used for testing.
|
|
153
|
+
*/
|
|
154
|
+
clear(): Promise<void>;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Dispose storage resources.
|
|
158
|
+
* Called when shutting down.
|
|
159
|
+
*/
|
|
160
|
+
dispose?(): Promise<void>;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Configuration for operation log storage.
|
|
165
|
+
*/
|
|
166
|
+
export interface OpLogStorageConfig {
|
|
167
|
+
/**
|
|
168
|
+
* Maximum number of patches to keep per entity.
|
|
169
|
+
* Older patches are evicted when limit is reached.
|
|
170
|
+
* @default 1000
|
|
171
|
+
*/
|
|
172
|
+
maxPatchesPerEntity?: number;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Maximum age of patches in milliseconds.
|
|
176
|
+
* Patches older than this are evicted.
|
|
177
|
+
* @default 300000 (5 minutes)
|
|
178
|
+
*/
|
|
179
|
+
maxPatchAge?: number;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Cleanup interval in milliseconds.
|
|
183
|
+
* Set to 0 to disable automatic cleanup.
|
|
184
|
+
* @default 60000 (1 minute)
|
|
185
|
+
*/
|
|
186
|
+
cleanupInterval?: number;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Maximum retries for emit operations on version conflict.
|
|
190
|
+
* Only applies to external storage (Redis, Upstash, Vercel KV).
|
|
191
|
+
* Set to 0 to disable retries (fail immediately on conflict).
|
|
192
|
+
* @default 3
|
|
193
|
+
*/
|
|
194
|
+
maxRetries?: number;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Default storage configuration.
|
|
199
|
+
*/
|
|
200
|
+
export const DEFAULT_STORAGE_CONFIG: Required<OpLogStorageConfig> = {
|
|
201
|
+
maxPatchesPerEntity: 1000,
|
|
202
|
+
maxPatchAge: 5 * 60 * 1000, // 5 minutes
|
|
203
|
+
cleanupInterval: 60 * 1000, // 1 minute
|
|
204
|
+
maxRetries: 3,
|
|
205
|
+
};
|