@sylphx/lens-server 1.0.2

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.
@@ -0,0 +1,226 @@
1
+ /**
2
+ * @sylphx/lens-server - Lens Server
3
+ *
4
+ * Core server implementation:
5
+ * - Free Operations (query/mutation definitions)
6
+ * - GraphStateManager (per-client state tracking, minimal diffs)
7
+ * - Field-level subscriptions
8
+ * - Entity Resolvers with DataLoader batching
9
+ */
10
+ import { type ContextValue, type EntityDef, type EntityDefinition, type EntityResolvers, type EntityResolversDefinition, type MutationDef, type QueryDef, type RelationDef, type RelationTypeWithForeignKey, type RouterDef } from "@sylphx/lens-core";
11
+ /** Selection object type for nested field selection */
12
+ export interface SelectionObject {
13
+ [key: string]: boolean | SelectionObject | {
14
+ select: SelectionObject;
15
+ };
16
+ }
17
+ import { GraphStateManager } from "../state/graph-state-manager";
18
+ /** Entity map type */
19
+ export type EntitiesMap = Record<string, EntityDef<string, any>>;
20
+ /** Queries map type */
21
+ export type QueriesMap = Record<string, QueryDef<unknown, unknown>>;
22
+ /** Mutations map type */
23
+ export type MutationsMap = Record<string, MutationDef<unknown, unknown>>;
24
+ /** Relations array type */
25
+ export type RelationsArray = RelationDef<EntityDef<string, EntityDefinition>, Record<string, RelationTypeWithForeignKey>>[];
26
+ /** Operation metadata for handshake */
27
+ export interface OperationMeta {
28
+ type: "query" | "mutation";
29
+ optimistic?: unknown;
30
+ }
31
+ /** Nested operations structure for handshake */
32
+ export type OperationsMap = {
33
+ [key: string]: OperationMeta | OperationsMap;
34
+ };
35
+ /** Server configuration */
36
+ export interface LensServerConfig<TContext extends ContextValue = ContextValue> {
37
+ /** Entity definitions */
38
+ entities?: EntitiesMap;
39
+ /** Relation definitions */
40
+ relations?: RelationsArray;
41
+ /** Router definition (namespaced operations) */
42
+ router?: RouterDef;
43
+ /** Query definitions (flat, legacy) */
44
+ queries?: QueriesMap;
45
+ /** Mutation definitions (flat, legacy) */
46
+ mutations?: MutationsMap;
47
+ /** Entity resolvers */
48
+ resolvers?: EntityResolvers<EntityResolversDefinition>;
49
+ /** Context factory */
50
+ context?: (req?: unknown) => TContext | Promise<TContext>;
51
+ /** Server version */
52
+ version?: string;
53
+ }
54
+ /** Server metadata for transport handshake */
55
+ export interface ServerMetadata {
56
+ /** Server version */
57
+ version: string;
58
+ /** Operations metadata map */
59
+ operations: OperationsMap;
60
+ }
61
+ /** Operation for in-process transport */
62
+ export interface LensOperation {
63
+ /** Operation path (e.g., 'user.get', 'session.create') */
64
+ path: string;
65
+ /** Operation input */
66
+ input?: unknown;
67
+ }
68
+ /** Result from operation execution */
69
+ export interface LensResult<T = unknown> {
70
+ /** Success data */
71
+ data?: T;
72
+ /** Error if operation failed */
73
+ error?: Error;
74
+ }
75
+ /** Lens server interface */
76
+ export interface LensServer {
77
+ /** Get server metadata for transport handshake */
78
+ getMetadata(): ServerMetadata;
79
+ /** Execute operation - auto-detects query vs mutation from registered operations */
80
+ execute(op: LensOperation): Promise<LensResult>;
81
+ /** Execute a query (one-time) */
82
+ executeQuery<TInput, TOutput>(name: string, input?: TInput): Promise<TOutput>;
83
+ /** Execute a mutation */
84
+ executeMutation<TInput, TOutput>(name: string, input: TInput): Promise<TOutput>;
85
+ /** Handle WebSocket connection */
86
+ handleWebSocket(ws: WebSocketLike): void;
87
+ /** Handle HTTP request */
88
+ handleRequest(req: Request): Promise<Response>;
89
+ /** Get GraphStateManager for external access */
90
+ getStateManager(): GraphStateManager;
91
+ /** Start server */
92
+ listen(port: number): Promise<void>;
93
+ /** Close server */
94
+ close(): Promise<void>;
95
+ }
96
+ /** WebSocket interface */
97
+ export interface WebSocketLike {
98
+ send(data: string): void;
99
+ close(): void;
100
+ onmessage?: ((event: {
101
+ data: string;
102
+ }) => void) | null;
103
+ onclose?: (() => void) | null;
104
+ onerror?: ((error: unknown) => void) | null;
105
+ }
106
+ declare class LensServerImpl<Q extends QueriesMap = QueriesMap, M extends MutationsMap = MutationsMap, TContext extends ContextValue = ContextValue> implements LensServer {
107
+ private queries;
108
+ private mutations;
109
+ private entities;
110
+ private resolvers?;
111
+ private contextFactory;
112
+ private version;
113
+ private ctx;
114
+ /** GraphStateManager for per-client state tracking */
115
+ private stateManager;
116
+ /** DataLoaders for N+1 batching (per-request) */
117
+ private loaders;
118
+ /** Client connections */
119
+ private connections;
120
+ private connectionCounter;
121
+ /** Server instance */
122
+ private server;
123
+ constructor(config: LensServerConfig<TContext> & {
124
+ queries?: Q;
125
+ mutations?: M;
126
+ });
127
+ getStateManager(): GraphStateManager;
128
+ /**
129
+ * Get server metadata for transport handshake.
130
+ * Used by inProcess transport for direct access.
131
+ */
132
+ getMetadata(): ServerMetadata;
133
+ /**
134
+ * Execute operation - auto-detects query vs mutation from registered operations.
135
+ * Used by inProcess transport for direct server calls.
136
+ */
137
+ execute(op: LensOperation): Promise<LensResult>;
138
+ /**
139
+ * Build nested operations map for handshake response
140
+ * Converts flat "user.get", "user.create" into nested { user: { get: {...}, create: {...} } }
141
+ */
142
+ private buildOperationsMap;
143
+ handleWebSocket(ws: WebSocketLike): void;
144
+ private handleMessage;
145
+ private handleHandshake;
146
+ private handleSubscribe;
147
+ private executeSubscription;
148
+ private handleUpdateFields;
149
+ private handleUnsubscribe;
150
+ private handleQuery;
151
+ private handleMutation;
152
+ private handleDisconnect;
153
+ executeQuery<TInput, TOutput>(name: string, input?: TInput): Promise<TOutput>;
154
+ executeMutation<TInput, TOutput>(name: string, input: TInput): Promise<TOutput>;
155
+ handleRequest(req: Request): Promise<Response>;
156
+ listen(port: number): Promise<void>;
157
+ close(): Promise<void>;
158
+ private findConnectionByWs;
159
+ private getEntityNameFromOutput;
160
+ private getEntityNameFromMutation;
161
+ private extractEntities;
162
+ private applySelection;
163
+ private applySelectionToObject;
164
+ /**
165
+ * Execute entity resolvers for nested data.
166
+ * Processes the selection object and resolves relation fields.
167
+ */
168
+ private executeEntityResolvers;
169
+ /**
170
+ * Get target entity name for a relation field.
171
+ */
172
+ private getRelationTargetEntity;
173
+ /**
174
+ * Serialize entity data for transport.
175
+ * Auto-calls serialize() on field types (Date → ISO string, etc.)
176
+ */
177
+ private serializeEntity;
178
+ /**
179
+ * Process query result: execute entity resolvers, apply selection, serialize
180
+ */
181
+ private processQueryResult;
182
+ private computeUpdates;
183
+ private deepEqual;
184
+ private clearLoaders;
185
+ }
186
+ /**
187
+ * Infer input type from a query/mutation definition
188
+ */
189
+ export type InferInput<T> = T extends QueryDef<infer I, unknown> ? I extends void ? void : I : T extends MutationDef<infer I, unknown> ? I : never;
190
+ /**
191
+ * Infer output type from a query/mutation definition
192
+ */
193
+ export type InferOutput<T> = T extends QueryDef<unknown, infer O> ? O : T extends MutationDef<unknown, infer O> ? O : never;
194
+ /**
195
+ * API type for client inference
196
+ * Export this type for client-side type safety
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * // Server
201
+ * const server = createLensServer({ queries, mutations });
202
+ * export type Api = InferApi<typeof server>;
203
+ *
204
+ * // Client (only imports TYPE)
205
+ * import type { Api } from './server';
206
+ * const client = createClient<Api>({ links: [...] });
207
+ * ```
208
+ */
209
+ export type InferApi<T extends LensServer> = T extends LensServerImpl<infer Q, infer M> ? {
210
+ queries: Q;
211
+ mutations: M;
212
+ } : never;
213
+ /**
214
+ * Create Lens server with Operations API + Optimization Layer
215
+ */
216
+ export declare function createServer<TContext extends ContextValue = ContextValue, Q extends QueriesMap = QueriesMap, M extends MutationsMap = MutationsMap>(config: LensServerConfig<TContext> & {
217
+ queries?: Q;
218
+ mutations?: M;
219
+ }): LensServer & {
220
+ _types: {
221
+ queries: Q;
222
+ mutations: M;
223
+ };
224
+ };
225
+ export {};
226
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @sylphx/lens-server - SSE Transport Adapter
3
+ *
4
+ * Thin transport adapter for Server-Sent Events.
5
+ * Connects SSE streams to GraphStateManager.
6
+ */
7
+ import type { GraphStateManager } from "../state/graph-state-manager";
8
+ /** SSE handler configuration */
9
+ export interface SSEHandlerConfig {
10
+ /** GraphStateManager instance (required) */
11
+ stateManager: GraphStateManager;
12
+ /** Heartbeat interval in ms (default: 30000) */
13
+ heartbeatInterval?: number;
14
+ }
15
+ /** SSE client info */
16
+ export interface SSEClientInfo {
17
+ id: string;
18
+ connectedAt: number;
19
+ }
20
+ /**
21
+ * SSE transport adapter for GraphStateManager.
22
+ *
23
+ * This is a thin adapter that:
24
+ * - Creates SSE connections
25
+ * - Registers clients with GraphStateManager
26
+ * - Forwards updates to SSE streams
27
+ *
28
+ * All state/subscription logic is handled by GraphStateManager.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const stateManager = new GraphStateManager();
33
+ * const sse = new SSEHandler({ stateManager });
34
+ *
35
+ * // Handle SSE connection
36
+ * app.get('/events', (req) => sse.handleConnection(req));
37
+ *
38
+ * // Subscribe via separate endpoint or message
39
+ * stateManager.subscribe(clientId, "Post", "123", "*");
40
+ * ```
41
+ */
42
+ export declare class SSEHandler {
43
+ private stateManager;
44
+ private heartbeatInterval;
45
+ private clients;
46
+ private clientCounter;
47
+ constructor(config: SSEHandlerConfig);
48
+ /**
49
+ * Handle new SSE connection
50
+ * Returns a Response with SSE stream
51
+ */
52
+ handleConnection(req?: Request): Response;
53
+ /**
54
+ * Remove client and cleanup
55
+ */
56
+ private removeClient;
57
+ /**
58
+ * Close specific client connection
59
+ */
60
+ closeClient(clientId: string): void;
61
+ /**
62
+ * Get connected client count
63
+ */
64
+ getClientCount(): number;
65
+ /**
66
+ * Get connected client IDs
67
+ */
68
+ getClientIds(): string[];
69
+ /**
70
+ * Close all connections
71
+ */
72
+ closeAll(): void;
73
+ }
74
+ /**
75
+ * Create SSE handler (transport adapter)
76
+ */
77
+ export declare function createSSEHandler(config: SSEHandlerConfig): SSEHandler;
78
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/sse/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAe,MAAM,8BAA8B,CAAC;AAMnF,gCAAgC;AAChC,MAAM,WAAW,gBAAgB;IAChC,4CAA4C;IAC5C,YAAY,EAAE,iBAAiB,CAAC;IAChC,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,sBAAsB;AACtB,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,UAAU;IACtB,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,OAAO,CAGX;IACJ,OAAO,CAAC,aAAa,CAAK;gBAEd,MAAM,EAAE,gBAAgB;IAKpC;;;OAGG;IACH,gBAAgB,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,QAAQ;IAqDzC;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYnC;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,YAAY,IAAI,MAAM,EAAE;IAIxB;;OAEG;IACH,QAAQ,IAAI,IAAI;CAKhB;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAErE"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * @sylphx/lens-server - Graph State Manager
3
+ *
4
+ * Core orchestration layer that:
5
+ * - Maintains canonical state per entity (server truth)
6
+ * - Tracks per-client last known state
7
+ * - Computes minimal diffs when state changes
8
+ * - Auto-selects transfer strategy (value/delta/patch)
9
+ * - Pushes updates to subscribed clients
10
+ */
11
+ import { type EntityKey, type Update } from "@sylphx/lens-core";
12
+ export type { EntityKey };
13
+ /** Client connection interface */
14
+ export interface StateClient {
15
+ id: string;
16
+ send: (message: StateUpdateMessage) => void;
17
+ }
18
+ /** Update message sent to clients */
19
+ export interface StateUpdateMessage {
20
+ type: "update";
21
+ entity: string;
22
+ id: string;
23
+ /** Field-level updates with strategy */
24
+ updates: Record<string, Update>;
25
+ }
26
+ /** Full entity update message */
27
+ export interface StateFullMessage {
28
+ type: "data";
29
+ entity: string;
30
+ id: string;
31
+ data: Record<string, unknown>;
32
+ }
33
+ /** Subscription info */
34
+ export interface Subscription {
35
+ clientId: string;
36
+ fields: Set<string> | "*";
37
+ }
38
+ /** Configuration */
39
+ export interface GraphStateManagerConfig {
40
+ /** Called when an entity has no more subscribers */
41
+ onEntityUnsubscribed?: (entity: string, id: string) => void;
42
+ }
43
+ /**
44
+ * Manages server-side canonical state and syncs to clients.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const manager = new GraphStateManager();
49
+ *
50
+ * // Add client
51
+ * manager.addClient({
52
+ * id: "client-1",
53
+ * send: (msg) => ws.send(JSON.stringify(msg)),
54
+ * });
55
+ *
56
+ * // Subscribe client to entity
57
+ * manager.subscribe("client-1", "Post", "123", ["title", "content"]);
58
+ *
59
+ * // Emit updates (from resolvers)
60
+ * manager.emit("Post", "123", { content: "Updated content" });
61
+ * // → Automatically computes diff and sends to subscribed clients
62
+ * ```
63
+ */
64
+ export declare class GraphStateManager {
65
+ /** Connected clients */
66
+ private clients;
67
+ /** Canonical state per entity (server truth) */
68
+ private canonical;
69
+ /** Per-client state tracking */
70
+ private clientStates;
71
+ /** Entity → subscribed client IDs */
72
+ private entitySubscribers;
73
+ /** Configuration */
74
+ private config;
75
+ constructor(config?: GraphStateManagerConfig);
76
+ /**
77
+ * Add a client connection
78
+ */
79
+ addClient(client: StateClient): void;
80
+ /**
81
+ * Remove a client and cleanup all subscriptions
82
+ */
83
+ removeClient(clientId: string): void;
84
+ /**
85
+ * Subscribe a client to an entity
86
+ */
87
+ subscribe(clientId: string, entity: string, id: string, fields?: string[] | "*"): void;
88
+ /**
89
+ * Unsubscribe a client from an entity
90
+ */
91
+ unsubscribe(clientId: string, entity: string, id: string): void;
92
+ /**
93
+ * Update subscription fields for a client
94
+ */
95
+ updateSubscription(clientId: string, entity: string, id: string, fields: string[] | "*"): void;
96
+ /**
97
+ * Emit data for an entity.
98
+ * This is the core method called by resolvers.
99
+ *
100
+ * @param entity - Entity name
101
+ * @param id - Entity ID
102
+ * @param data - Full or partial entity data
103
+ * @param options - Emit options
104
+ */
105
+ emit(entity: string, id: string, data: Record<string, unknown>, options?: {
106
+ replace?: boolean;
107
+ }): void;
108
+ /**
109
+ * Get current canonical state for an entity
110
+ */
111
+ getState(entity: string, id: string): Record<string, unknown> | undefined;
112
+ /**
113
+ * Check if entity has any subscribers
114
+ */
115
+ hasSubscribers(entity: string, id: string): boolean;
116
+ /**
117
+ * Push update to a specific client
118
+ */
119
+ private pushToClient;
120
+ /**
121
+ * Send initial data to a newly subscribed client
122
+ */
123
+ private sendInitialData;
124
+ /**
125
+ * Cleanup entity when no subscribers remain
126
+ */
127
+ private cleanupEntity;
128
+ private makeKey;
129
+ /**
130
+ * Get statistics
131
+ */
132
+ getStats(): {
133
+ clients: number;
134
+ entities: number;
135
+ totalSubscriptions: number;
136
+ };
137
+ /**
138
+ * Clear all state (for testing)
139
+ */
140
+ clear(): void;
141
+ }
142
+ /**
143
+ * Create a GraphStateManager instance
144
+ */
145
+ export declare function createGraphStateManager(config?: GraphStateManagerConfig): GraphStateManager;
146
+ //# sourceMappingURL=graph-state-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-state-manager.d.ts","sourceRoot":"","sources":["../../src/state/graph-state-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @sylphx/lens-server - State Management
3
+ *
4
+ * Server-side state management for reactive data sync.
5
+ */
6
+ export { GraphStateManager, createGraphStateManager, type EntityKey, type StateClient, type StateUpdateMessage, type StateFullMessage, type Subscription, type GraphStateManagerConfig, } from "./graph-state-manager";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,uBAAuB,GAC5B,MAAM,uBAAuB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@sylphx/lens-server",
3
+ "version": "1.0.2",
4
+ "description": "Server runtime for Lens API framework",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "bun build ./src/index.ts --outdir ./dist --target node && bun run build:types",
16
+ "build:types": "tsc --emitDeclarationOnly --outDir ./dist",
17
+ "typecheck": "tsc --noEmit",
18
+ "test": "bun test"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "src"
23
+ ],
24
+ "keywords": [
25
+ "lens",
26
+ "server",
27
+ "resolvers",
28
+ "graphql"
29
+ ],
30
+ "author": "SylphxAI",
31
+ "license": "MIT",
32
+ "dependencies": {
33
+ "@sylphx/lens-core": "workspace:*"
34
+ },
35
+ "devDependencies": {
36
+ "typescript": "^5.9.3",
37
+ "zod": "^4.1.13"
38
+ }
39
+ }