@leaven-graphql/ws 0.1.0 → 0.2.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/LICENSE CHANGED
@@ -175,7 +175,7 @@
175
175
 
176
176
  END OF TERMS AND CONDITIONS
177
177
 
178
- Copyright 2026 Pegasus Heavy Industries LLC
178
+ Copyright 2026 Joseph Quinn
179
179
 
180
180
  Licensed under the Apache License, Version 2.0 (the "License");
181
181
  you may not use this file except in compliance with the License.
package/README.md CHANGED
@@ -10,33 +10,60 @@ bun add @leaven-graphql/ws @leaven-graphql/core graphql
10
10
 
11
11
  ## Quick Start
12
12
 
13
+ `createWebSocketHandler` implements the whole `graphql-ws` server: connection
14
+ init and acknowledgement, keep-alive pings, subscription lifecycle, and the
15
+ protocol close codes. Hand it to `Bun.serve` via `getWebSocketConfig()`.
16
+
13
17
  ```typescript
14
- import { createPubSub } from '@leaven-graphql/ws';
15
- import { LeavenExecutor } from '@leaven-graphql/core';
18
+ import { createWebSocketHandler, type WebSocketContext } from '@leaven-graphql/ws';
16
19
 
17
- const pubsub = createPubSub();
18
- const executor = new LeavenExecutor({ schema });
20
+ const handler = createWebSocketHandler({
21
+ schema,
22
+ // Optional: build the GraphQL context for every operation
23
+ context: (socket) => ({ user: socket.data.connectionParams?.user }),
24
+ });
19
25
 
20
26
  Bun.serve({
21
27
  port: 4000,
22
28
  fetch(request, server) {
23
- if (request.headers.get('upgrade') === 'websocket') {
24
- server.upgrade(request);
29
+ // Bun's types require the `data` option, but the handler's `open` replaces
30
+ // socket.data with a fresh WebSocketContext, so nothing needs stashing.
31
+ if (server.upgrade(request, { data: undefined as unknown as WebSocketContext })) {
25
32
  return;
26
33
  }
27
34
  return new Response('Not Found', { status: 404 });
28
35
  },
29
- websocket: {
30
- message(ws, message) {
31
- handleMessage(ws, message, executor, pubsub);
32
- },
33
- close(ws) {
34
- cleanupConnection(ws);
35
- },
36
- },
36
+ websocket: handler.getWebSocketConfig(),
37
37
  });
38
38
  ```
39
39
 
40
+ Queries and mutations are supported on the same transport: per the `graphql-ws`
41
+ protocol, a `subscribe` frame carrying a query or mutation is answered with a
42
+ single `next` followed by `complete`. Failures before execution (validation,
43
+ variable coercion) come back as an `error` frame instead; resolver errors ride
44
+ inside the `next` payload.
45
+
46
+ Serving HTTP and WebSocket from one server is a matter of passing the handler
47
+ to `@leaven-graphql/http`. Subscriptions do **not** inherit the HTTP
48
+ executor's options, so state them for both transports — otherwise the
49
+ longest-lived transport quietly runs on executor defaults:
50
+
51
+ ```typescript
52
+ import { createServer } from '@leaven-graphql/http';
53
+ import { createWebSocketHandler } from '@leaven-graphql/ws';
54
+
55
+ const executor = { introspection: false, maxDepth: 10 };
56
+
57
+ createServer({
58
+ schema,
59
+ executor,
60
+ websocket: createWebSocketHandler({
61
+ schema,
62
+ subscriptionManager: { executor },
63
+ }),
64
+ }).start();
65
+ ```
66
+
40
67
  ## Features
41
68
 
42
69
  ### PubSub
@@ -114,62 +141,35 @@ const resolvers = {
114
141
 
115
142
  ### Authentication
116
143
 
117
- ```typescript
118
- import { parseMessage } from '@leaven-graphql/ws';
119
-
120
- const connections = new Map();
121
-
122
- Bun.serve({
123
- websocket: {
124
- async message(ws, data) {
125
- const message = parseMessage(data);
126
-
127
- switch (message.type) {
128
- case 'connection_init': {
129
- const token = message.payload?.authToken;
130
-
131
- try {
132
- const user = await verifyToken(token);
133
- connections.set(ws, { user, subscriptions: new Map() });
134
- ws.send(JSON.stringify({ type: 'connection_ack' }));
135
- } catch (error) {
136
- ws.close(4401, 'Unauthorized');
137
- }
138
- break;
139
- }
140
-
141
- case 'subscribe': {
142
- const connection = connections.get(ws);
143
- if (!connection) {
144
- ws.close(4401, 'Unauthorized');
145
- return;
146
- }
147
- handleSubscribe(ws, message, connection.user);
148
- break;
149
- }
144
+ Authenticate in `onConnect`. Returning `false` closes the socket with `4403`,
145
+ and no `subscribe` frame is accepted before a connection is acknowledged
146
+ (unacknowledged operations are closed with `4401`).
150
147
 
151
- case 'complete': {
152
- const connection = connections.get(ws);
153
- connection?.subscriptions.get(message.id)?.unsubscribe();
154
- connection?.subscriptions.delete(message.id);
155
- break;
156
- }
157
- }
158
- },
159
-
160
- close(ws) {
161
- const connection = connections.get(ws);
162
- if (connection) {
163
- for (const sub of connection.subscriptions.values()) {
164
- sub.unsubscribe();
165
- }
166
- connections.delete(ws);
167
- }
168
- },
148
+ ```typescript
149
+ import { createWebSocketHandler } from '@leaven-graphql/ws';
150
+
151
+ const users = new WeakMap<object, User>();
152
+
153
+ const handler = createWebSocketHandler({
154
+ schema,
155
+ async onConnect(socket, params) {
156
+ try {
157
+ users.set(socket, await verifyToken(params?.authToken as string));
158
+ return true;
159
+ } catch {
160
+ return false;
161
+ }
162
+ },
163
+ context: (socket) => ({ user: users.get(socket) }),
164
+ onDisconnect(socket) {
165
+ users.delete(socket);
169
166
  },
170
167
  });
171
168
  ```
172
169
 
170
+ The lifecycle hooks may be async; a hook that rejects is logged and never
171
+ takes the connection (or the process) down with it.
172
+
173
173
  ### Schema Definition
174
174
 
175
175
  ```graphql
@@ -239,44 +239,289 @@ unsubscribe();
239
239
 
240
240
  ## API Reference
241
241
 
242
+ ### WebSocketHandler
243
+
244
+ The `graphql-ws` server. `getWebSocketConfig()` returns the object `Bun.serve`
245
+ expects under `websocket`.
246
+
247
+ ```typescript
248
+ class WebSocketHandler<TContext = unknown> {
249
+ constructor(config: WebSocketHandlerConfig<TContext>);
250
+
251
+ handleOpen(socket: ServerWebSocket<WebSocketContext>): void;
252
+ handleMessage(
253
+ socket: ServerWebSocket<WebSocketContext>,
254
+ message: string | Buffer
255
+ ): Promise<void>;
256
+ handleClose(socket: ServerWebSocket<WebSocketContext>): Promise<void>;
257
+
258
+ getWebSocketConfig(): {
259
+ open: (socket: ServerWebSocket<WebSocketContext>) => void;
260
+ message: (
261
+ socket: ServerWebSocket<WebSocketContext>,
262
+ message: string | Buffer
263
+ ) => void;
264
+ close: (socket: ServerWebSocket<WebSocketContext>) => void;
265
+ };
266
+ }
267
+
268
+ function createWebSocketHandler<TContext = unknown>(
269
+ config: WebSocketHandlerConfig<TContext>
270
+ ): WebSocketHandler<TContext>;
271
+
272
+ interface WebSocketHandlerConfig<TContext = unknown> {
273
+ /** GraphQL schema */
274
+ schema: GraphQLSchema;
275
+ /** Builds the GraphQL context for each operation */
276
+ context?: (
277
+ socket: ServerWebSocket<WebSocketContext>,
278
+ request: GraphQLRequest
279
+ ) => TContext | Promise<TContext>;
280
+ /** Close with 4408 if `connection_init` does not arrive in time (default 3000ms) */
281
+ connectionInitTimeout?: number;
282
+ /** Server ping interval; 0 disables keep-alive (default 12000ms) */
283
+ keepAliveInterval?: number;
284
+ /** Forwarded to the SubscriptionManager (minus `schema`) */
285
+ subscriptionManager?: Omit<SubscriptionManagerConfig, 'schema'>;
286
+ /** Return false to reject the connection with 4403 */
287
+ onConnect?: (
288
+ socket: ServerWebSocket<WebSocketContext>,
289
+ params?: Record<string, unknown>
290
+ ) => boolean | Promise<boolean>;
291
+ onDisconnect?: (socket: ServerWebSocket<WebSocketContext>) => void | Promise<void>;
292
+ onSubscribe?: (
293
+ socket: ServerWebSocket<WebSocketContext>,
294
+ id: string,
295
+ request: GraphQLRequest
296
+ ) => void | Promise<void>;
297
+ /** Called once per operation id when it reaches a terminal state */
298
+ onComplete?: (
299
+ socket: ServerWebSocket<WebSocketContext>,
300
+ id: string
301
+ ) => void | Promise<void>;
302
+ }
303
+
304
+ interface WebSocketContext {
305
+ /** Opaque UUIDv4 — do not parse it */
306
+ connectionId: string;
307
+ connectionParams?: Record<string, unknown>;
308
+ initialized: boolean;
309
+ subscriptions: Set<string>;
310
+ }
311
+ ```
312
+
313
+ Close codes follow the protocol: `4400` invalid message, `4401` unauthorized
314
+ (operation before `connection_init`), `4403` rejected by `onConnect`, `4408`
315
+ init timeout, `4409` duplicate subscription id, `4429` repeated
316
+ `connection_init`.
317
+
318
+ ### SubscriptionManager
319
+
320
+ Owns the executor and the per-connection subscription registry. The handler
321
+ creates one; you only need it directly when driving subscriptions yourself.
322
+
323
+ ```typescript
324
+ class SubscriptionManager {
325
+ constructor(config: SubscriptionManagerConfig);
326
+
327
+ subscribe<TContext = unknown>(
328
+ connectionId: string,
329
+ subscriptionId: string,
330
+ request: GraphQLRequest,
331
+ context: TContext,
332
+ onNext: (result: GraphQLResponse) => void,
333
+ onComplete: () => void,
334
+ onError: (errors: readonly { message: string }[]) => void
335
+ ): Promise<Subscription>;
336
+
337
+ /** Run a query or mutation on the same executor */
338
+ execute<TContext = unknown>(
339
+ request: GraphQLRequest,
340
+ context?: TContext
341
+ ): Promise<GraphQLResponse>;
342
+
343
+ unsubscribe(connectionId: string, subscriptionId: string): boolean;
344
+ unsubscribeConnection(connectionId: string): number;
345
+ getSubscription(connectionId: string, subscriptionId: string): Subscription | undefined;
346
+ getConnectionSubscriptions(connectionId: string): Subscription[];
347
+ clear(): void;
348
+
349
+ readonly subscriptionCount: number;
350
+ readonly connectionCount: number;
351
+ }
352
+
353
+ function createSubscriptionManager(config: SubscriptionManagerConfig): SubscriptionManager;
354
+
355
+ interface SubscriptionManagerConfig {
356
+ schema: GraphQLSchema;
357
+ /** Default 100 */
358
+ maxSubscriptionsPerConnection?: number;
359
+ /** Complete a subscription after this many ms; 0 disables (default 0) */
360
+ subscriptionTimeout?: number;
361
+ /**
362
+ * Reuse an existing executor, or configure the one this manager builds.
363
+ * Sharing an executor with the HTTP transport avoids a second schema print
364
+ * and a duplicate document cache, and is the only way subscriptions inherit
365
+ * `introspection: false`, `maxDepth` or `maxComplexity`.
366
+ */
367
+ executor?: LeavenExecutor | Omit<ExecutorConfig, 'schema'>;
368
+ }
369
+
370
+ interface Subscription {
371
+ id: string;
372
+ connectionId: string;
373
+ request: GraphQLRequest;
374
+ status: 'pending' | 'active' | 'completed' | 'error';
375
+ createdAt: number;
376
+ iterator?: AsyncIterableIterator<GraphQLResponse>;
377
+ cleanup?: () => void;
378
+ }
379
+ ```
380
+
381
+ Subscription ids are scoped to a connection: `graphql-ws` clients number their
382
+ operations per connection (starting at `"1"`), so every lookup and teardown
383
+ takes **both** the connection id and the subscription id.
384
+
242
385
  ### PubSub
243
386
 
244
387
  ```typescript
245
- class PubSub {
246
- subscribe(topic: string, callback: (payload: unknown) => void): () => void;
247
- publish(topic: string, payload: unknown): void;
248
- asyncIterator(topic: string | string[]): AsyncIterableIterator<unknown>;
388
+ class PubSub implements PubSubEngine {
389
+ constructor(config?: PubSubConfig);
390
+
391
+ subscribe<T = unknown>(topic: string, callback: (payload: T) => void): () => void;
392
+ publish<T = unknown>(topic: string, payload: T): void;
393
+ asyncIterator<T = unknown>(topic: string | string[]): AsyncIterableIterator<T>;
394
+ getSubscriberCount(topic: string): number;
395
+ getTopics(): string[];
396
+ clear(): void;
249
397
  }
250
398
 
251
399
  function createPubSub(config?: PubSubConfig): PubSub;
252
400
 
253
401
  interface PubSubConfig {
254
- maxSubscribers?: number;
402
+ /** Subscribers allowed per topic before `subscribe` throws (default 10000) */
403
+ maxSubscribersPerTopic?: number;
404
+ /** Enable `.`-segmented `*` / `#` topic patterns (default false) */
255
405
  wildcards?: boolean;
406
+ /**
407
+ * Payloads an `asyncIterator` buffers while nothing is pulling. When full,
408
+ * the OLDEST payload is dropped so a slow consumer sees the most recent
409
+ * events instead of an unbounded queue. Unlimited by default.
410
+ */
411
+ maxQueueSize?: number;
256
412
  }
257
413
  ```
258
414
 
259
415
  ### Message Handling
260
416
 
417
+ `parseMessage` returns a parsed message object; `formatMessage` takes a message
418
+ object and returns the string to send. The `create*` helpers build message
419
+ objects, so they are composed with `formatMessage` rather than sent directly.
420
+
261
421
  ```typescript
262
- function parseMessage(data: string | Buffer): GraphQLWSMessage;
263
- function formatMessage(type: string, payload?: unknown): string;
264
- function createNextMessage(id: string, payload: unknown): string;
265
- function createErrorMessage(id: string, errors: GraphQLError[]): string;
266
- function createCompleteMessage(id: string): string;
422
+ function parseMessage(data: string | Buffer, options?: ParseMessageOptions): Message;
423
+ function formatMessage(message: Message): string;
424
+
425
+ function createConnectionAck(payload?: Record<string, unknown>): ConnectionAckMessage;
426
+ function createNextMessage(
427
+ id: string,
428
+ data: Record<string, unknown> | null | undefined,
429
+ errors?: readonly { message: string }[]
430
+ ): NextMessage;
431
+ function createErrorMessage(
432
+ id: string,
433
+ errors: readonly { message: string }[]
434
+ ): ErrorMessage;
435
+ function createCompleteMessage(id: string): CompleteMessage;
436
+ function createPongMessage(payload?: Record<string, unknown>): PongMessage;
437
+
438
+ interface ParseMessageOptions {
439
+ /**
440
+ * Require a string `id` on the types that carry one (`subscribe`, `next`,
441
+ * `error`, `complete`). Defaults to `true`, which is correct for a server
442
+ * reading client frames: an operation frame with no id cannot be routed.
443
+ * Pass `false` on the client, where a lenient peer may omit the id and a
444
+ * throw would tear down the whole connection.
445
+ */
446
+ requireId?: boolean;
447
+ }
267
448
  ```
268
449
 
450
+ ```typescript
451
+ import {
452
+ createCompleteMessage,
453
+ createNextMessage,
454
+ formatMessage,
455
+ parseMessage,
456
+ } from '@leaven-graphql/ws';
457
+
458
+ socket.send(formatMessage(createNextMessage('1', { hello: 'world' })));
459
+ socket.send(formatMessage(createCompleteMessage('1')));
460
+
461
+ const message = parseMessage(data, { requireId: false });
462
+ ```
463
+
464
+ `parseMessage` throws on invalid JSON, on JSON that is not an object, on a
465
+ missing or unknown `type`, and — unless `requireId` is `false` — on a missing
466
+ `id`.
467
+
269
468
  ### Message Types
270
469
 
271
470
  ```typescript
272
- interface GraphQLWSMessage {
273
- type: 'connection_init' | 'connection_ack' | 'ping' | 'pong'
274
- | 'subscribe' | 'next' | 'error' | 'complete';
275
- id?: string;
276
- payload?: unknown;
471
+ enum MessageType {
472
+ ConnectionInit = 'connection_init',
473
+ ConnectionAck = 'connection_ack',
474
+ Ping = 'ping',
475
+ Pong = 'pong',
476
+ Subscribe = 'subscribe',
477
+ Next = 'next',
478
+ Error = 'error',
479
+ Complete = 'complete',
480
+ }
481
+
482
+ type Message =
483
+ | ConnectionInitMessage
484
+ | ConnectionAckMessage
485
+ | PingMessage
486
+ | PongMessage
487
+ | SubscribeMessage
488
+ | NextMessage
489
+ | ErrorMessage
490
+ | CompleteMessage;
491
+
492
+ interface SubscribeMessage {
493
+ id: string;
494
+ type: MessageType.Subscribe;
495
+ payload: {
496
+ operationName?: string;
497
+ query: string;
498
+ variables?: Record<string, unknown>;
499
+ extensions?: Record<string, unknown>;
500
+ };
501
+ }
502
+
503
+ interface NextMessage {
504
+ id: string;
505
+ type: MessageType.Next;
506
+ payload: {
507
+ data?: Record<string, unknown> | null;
508
+ errors?: readonly { message: string; [key: string]: unknown }[];
509
+ extensions?: Record<string, unknown>;
510
+ };
511
+ }
512
+
513
+ interface ErrorMessage {
514
+ id: string;
515
+ type: MessageType.Error;
516
+ payload: readonly { message: string; [key: string]: unknown }[];
517
+ }
518
+
519
+ interface CompleteMessage {
520
+ id: string;
521
+ type: MessageType.Complete;
277
522
  }
278
523
  ```
279
524
 
280
525
  ## License
281
526
 
282
- Apache 2.0 - Pegasus Heavy Industries LLC
527
+ Apache 2.0 - Joseph Quinn
package/dist/handler.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * @leaven-graphql/ws - WebSocket handler
3
3
  *
4
- * Copyright 2026 Pegasus Heavy Industries LLC
4
+ * Copyright 2026 Joseph Quinn
5
5
  * Licensed under the Apache License, Version 2.0
6
6
  */
7
- import type { GraphQLSchema } from 'graphql';
7
+ import { type GraphQLSchema } from 'graphql';
8
8
  import type { ServerWebSocket } from 'bun';
9
9
  import type { GraphQLRequest } from '@leaven-graphql/core';
10
10
  import { type SubscriptionManagerConfig } from './manager';
@@ -68,6 +68,16 @@ export declare class WebSocketHandler<TContext = unknown> {
68
68
  * Generate a unique connection ID
69
69
  */
70
70
  private generateConnectionId;
71
+ /**
72
+ * Invoke a user-supplied lifecycle hook without letting its failure escape.
73
+ *
74
+ * These hooks are called from places with no caller able to catch: iterator
75
+ * consumption stacks inside the subscription manager, timer callbacks, and
76
+ * Bun's `void`-returning socket callbacks. A rejected promise dropped into
77
+ * one of those slots is an unhandled rejection, which by default aborts the
78
+ * process and takes every other connection with it.
79
+ */
80
+ private invokeHook;
71
81
  /**
72
82
  * Handle WebSocket open
73
83
  */
@@ -88,6 +98,15 @@ export declare class WebSocketHandler<TContext = unknown> {
88
98
  * Handle subscribe message
89
99
  */
90
100
  private handleSubscribe;
101
+ /**
102
+ * Whether a request's selected operation is a subscription.
103
+ *
104
+ * A document graphql-js cannot resolve to a single operation (no operations
105
+ * at all, or several with no `operationName`) is reported as a subscription
106
+ * so the executor produces the precise error rather than this method
107
+ * guessing at one.
108
+ */
109
+ private isSubscriptionOperation;
91
110
  /**
92
111
  * Handle complete message (client unsubscribe)
93
112
  */
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @leaven-graphql/ws - WebSocket subscriptions for Leaven
3
3
  *
4
- * Copyright 2026 Pegasus Heavy Industries LLC
4
+ * Copyright 2026 Joseph Quinn
5
5
  * Licensed under the Apache License, Version 2.0
6
6
  */
7
7
  export { WebSocketHandler, createWebSocketHandler } from './handler';
@@ -10,5 +10,5 @@ export { SubscriptionManager, createSubscriptionManager } from './manager';
10
10
  export type { SubscriptionManagerConfig, Subscription, SubscriptionStatus } from './manager';
11
11
  export { PubSub, createPubSub } from './pubsub';
12
12
  export type { PubSubConfig, PubSubEngine, SubscribeFn, PublishFn } from './pubsub';
13
- export { MessageType, parseMessage, formatMessage, type ConnectionInitMessage, type ConnectionAckMessage, type SubscribeMessage, type NextMessage, type ErrorMessage, type CompleteMessage, type PingMessage, type PongMessage, } from './protocol';
13
+ export { MessageType, parseMessage, formatMessage, createConnectionAck, createNextMessage, createErrorMessage, createCompleteMessage, createPongMessage, type ConnectionInitMessage, type ConnectionAckMessage, type SubscribeMessage, type NextMessage, type ErrorMessage, type CompleteMessage, type PingMessage, type PongMessage, type ParseMessageOptions, } from './protocol';
14
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACrE,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE1E,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAC3E,YAAY,EAAE,yBAAyB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE7F,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEnF,OAAO,EACL,WAAW,EACX,YAAY,EACZ,aAAa,EACb,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACrE,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE1E,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAC3E,YAAY,EAAE,yBAAyB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE7F,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEnF,OAAO,EACL,WAAW,EACX,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC"}