@iadev93/zuno-express 0.0.7 → 0.0.9

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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @iadev93/zuno-express
2
2
 
3
- Express adapter for **Zuno**.
3
+ <p><b>Express adapter for Zuno.</b></p>
4
4
 
5
- Provides serverside synchronization endpoints using ServerSent Events (SSE).
5
+ Provides server-side synchronization endpoints using Server-Sent Events (SSE) for Express applications.
6
6
 
7
7
  ---
8
8
 
@@ -13,7 +13,6 @@ npm install @iadev93/zuno-express
13
13
  ```
14
14
 
15
15
  Peer dependency:
16
-
17
16
  * `express >= 4`
18
17
 
19
18
  ---
@@ -23,23 +22,36 @@ Peer dependency:
23
22
  ```ts
24
23
  import express from "express";
25
24
  import { createZunoExpress } from "@iadev93/zuno-express";
26
- import { createZuno } from "@iadev93/zuno";
27
25
 
28
26
  const app = express();
29
- const zuno = createZuno();
27
+ app.use(express.json());
28
+
29
+ const zuno = createZunoExpress();
30
30
 
31
- createZunoExpress(app, { zuno });
31
+ // Unified handlers
32
+ app.get("/zuno/sse", zuno.sse);
33
+ app.post("/zuno/sync", zuno.sync);
34
+ app.get("/zuno/snapshot", zuno.snapshot);
32
35
 
33
36
  app.listen(3000);
34
37
  ```
35
38
 
36
39
  ---
37
40
 
38
- ## What It Provides
41
+ ## API
42
+
43
+ ### `createZunoExpress(opts?)`
44
+
45
+ Returns an object containing the following Express handlers:
46
+
47
+ #### `sse` (GET)
48
+ Handles persistent SSE connections, heartbeats, and initial synchronization.
49
+
50
+ #### `sync` (POST)
51
+ Validates and applies incoming state events.
39
52
 
40
- * SSE endpoint for state sync
41
- * Snapshot delivery
42
- * Version‑safe event ingestion
53
+ #### `snapshot` (GET)
54
+ Returns the current full state of the universe.
43
55
 
44
56
  ---
45
57
 
@@ -0,0 +1,40 @@
1
+ import { Request, Response } from 'express';
2
+ import { IncomingHttpHeaders } from 'http';
3
+
4
+ /**
5
+ * Options for creating an Express router for Zuno.
6
+ */
7
+ type CreateZunoExpressOptions = {
8
+ /** Optional custom headers to be sent with the SSE response. */
9
+ headers?: IncomingHttpHeaders;
10
+ };
11
+ /**
12
+ * Creates a Zuno Express instance.
13
+ * @param {CreateZunoExpressOptions} [opts] - Options for creating the Express router.
14
+ * @returns {Object} An object with the following properties:
15
+ * - sse: An Express handler function that handles SSE connections.
16
+ * - sync: An Express handler function that handles sync POST requests.
17
+ * - snapshot: An Express handler function that handles snapshot GET requests.
18
+ */
19
+ declare function createZunoExpress(opts?: CreateZunoExpressOptions): {
20
+ /**
21
+ * Handles SSE connections for Express.
22
+ * @param {Request} req - Express request object.
23
+ * @param {Response} res - Express response object.
24
+ */
25
+ sse: (req: Request, res: Response) => void;
26
+ /**
27
+ * Handles sync POST requests for Express.
28
+ * @param {Request} req - Express request object.
29
+ * @param {Response} res - Express response object.
30
+ */
31
+ sync: (req: Request, res: Response) => void;
32
+ /**
33
+ * Handles snapshot GET requests for Express.
34
+ * @param {Request} req - Express request object.
35
+ * @param {Response} res - Express response object.
36
+ */
37
+ snapshot: (req: Request, res: Response) => void;
38
+ };
39
+
40
+ export { type CreateZunoExpressOptions, createZunoExpress };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import type { Request, Response } from "express";
2
- import type { IncomingHttpHeaders } from "http";
1
+ import { Request, Response } from 'express';
2
+ import { IncomingHttpHeaders } from 'http';
3
+
3
4
  /**
4
5
  * Options for creating an Express router for Zuno.
5
6
  */
6
- export type CreateZunoExpressOptions = {
7
+ type CreateZunoExpressOptions = {
7
8
  /** Optional custom headers to be sent with the SSE response. */
8
9
  headers?: IncomingHttpHeaders;
9
10
  };
@@ -15,7 +16,7 @@ export type CreateZunoExpressOptions = {
15
16
  * - sync: An Express handler function that handles sync POST requests.
16
17
  * - snapshot: An Express handler function that handles snapshot GET requests.
17
18
  */
18
- export declare function createZunoExpress(opts?: CreateZunoExpressOptions): {
19
+ declare function createZunoExpress(opts?: CreateZunoExpressOptions): {
19
20
  /**
20
21
  * Handles SSE connections for Express.
21
22
  * @param {Request} req - Express request object.
@@ -35,4 +36,5 @@ export declare function createZunoExpress(opts?: CreateZunoExpressOptions): {
35
36
  */
36
37
  snapshot: (req: Request, res: Response) => void;
37
38
  };
38
- //# sourceMappingURL=index.d.ts.map
39
+
40
+ export { type CreateZunoExpressOptions, createZunoExpress };
package/dist/index.js CHANGED
@@ -1,43 +1,2 @@
1
- import { createSSEConnection, applyStateEvent, sendSnapshot } from "@iadev93/zuno/server";
2
- /**
3
- * Creates a Zuno Express instance.
4
- * @param {CreateZunoExpressOptions} [opts] - Options for creating the Express router.
5
- * @returns {Object} An object with the following properties:
6
- * - sse: An Express handler function that handles SSE connections.
7
- * - sync: An Express handler function that handles sync POST requests.
8
- * - snapshot: An Express handler function that handles snapshot GET requests.
9
- */
10
- export function createZunoExpress(opts) {
11
- const { headers } = opts ?? {};
12
- return {
13
- /**
14
- * Handles SSE connections for Express.
15
- * @param {Request} req - Express request object.
16
- * @param {Response} res - Express response object.
17
- */
18
- sse: (req, res) => createSSEConnection(req, res, headers ?? {}),
19
- /**
20
- * Handles sync POST requests for Express.
21
- * @param {Request} req - Express request object.
22
- * @param {Response} res - Express response object.
23
- */
24
- sync: (req, res) => {
25
- const incoming = req.body;
26
- const result = applyStateEvent(incoming);
27
- if (!result.ok) {
28
- res.status(409).json({
29
- reason: result.reason,
30
- current: result.current,
31
- });
32
- return;
33
- }
34
- res.status(200).json({ ok: true, event: result.event });
35
- },
36
- /**
37
- * Handles snapshot GET requests for Express.
38
- * @param {Request} req - Express request object.
39
- * @param {Response} res - Express response object.
40
- */
41
- snapshot: (req, res) => sendSnapshot(req, res),
42
- };
43
- }
1
+ 'use strict';var server=require('@iadev93/zuno/server');function c(n){let{headers:o}=n??{};return {sse:(t,e)=>server.createSSEConnection(t,e,o??{}),sync:(t,e)=>{let r=t.body,s=server.applyStateEvent(r);if(!s.ok){e.status(409).json({reason:s.reason,current:s.current});return}e.status(200).json({ok:true,event:s.event});},snapshot:(t,e)=>server.sendSnapshot(t,e)}}exports.createZunoExpress=c;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["createZunoExpress","opts","headers","req","res","createSSEConnection","incoming","result","applyStateEvent","sendSnapshot"],"mappings":"wDAyBO,SAASA,CAAAA,CAAkBC,EAAiC,CACjE,GAAM,CAAE,OAAA,CAAAC,CAAQ,EAAID,CAAAA,EAAQ,GAE5B,OAAO,CAML,GAAA,CAAK,CAACE,EAAcC,CAAAA,GAAkBC,0BAAAA,CAAoBF,EAAKC,CAAAA,CAAKF,CAAAA,EAAW,EAAE,CAAA,CAOjF,KAAM,CAACC,CAAAA,CAAcC,IAAkB,CACrC,IAAME,EAAWH,CAAAA,CAAI,IAAA,CACfI,EAASC,sBAAAA,CAAgBF,CAAQ,CAAA,CAEvC,GAAI,CAACC,CAAAA,CAAO,EAAA,CAAI,CACdH,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CACnB,MAAA,CAAQG,CAAAA,CAAO,OACf,OAAA,CAASA,CAAAA,CAAO,OAClB,CAAC,CAAA,CACD,MACF,CAEAH,CAAAA,CAAI,MAAA,CAAO,GAAG,EAAE,IAAA,CAAK,CAAE,GAAI,IAAA,CAAM,KAAA,CAAOG,EAAO,KAAM,CAAC,EACxD,CAAA,CAOA,QAAA,CAAU,CAACJ,CAAAA,CAAcC,CAAAA,GAAkBK,oBAAaN,CAAAA,CAAKC,CAAG,CAClE,CACF","file":"index.js","sourcesContent":["import type { Request, Response } from \"express\";\nimport type { IncomingHttpHeaders } from \"http\";\nimport type { ZunoStateEvent } from \"@iadev93/zuno\";\nimport { \n createSSEConnection, \n applyStateEvent, \n sendSnapshot \n} from \"@iadev93/zuno/server\";\n\n/**\n * Options for creating an Express router for Zuno.\n */\nexport type CreateZunoExpressOptions = {\n /** Optional custom headers to be sent with the SSE response. */\n headers?: IncomingHttpHeaders;\n};\n\n/**\n * Creates a Zuno Express instance.\n * @param {CreateZunoExpressOptions} [opts] - Options for creating the Express router.\n * @returns {Object} An object with the following properties:\n * - sse: An Express handler function that handles SSE connections.\n * - sync: An Express handler function that handles sync POST requests.\n * - snapshot: An Express handler function that handles snapshot GET requests.\n */\nexport function createZunoExpress(opts?: CreateZunoExpressOptions) {\n const { headers } = opts ?? {};\n\n return {\n /**\n * Handles SSE connections for Express.\n * @param {Request} req - Express request object.\n * @param {Response} res - Express response object.\n */\n sse: (req: Request, res: Response) => createSSEConnection(req, res, headers ?? {}),\n\n /**\n * Handles sync POST requests for Express.\n * @param {Request} req - Express request object.\n * @param {Response} res - Express response object.\n */\n sync: (req: Request, res: Response) => {\n const incoming = req.body as ZunoStateEvent;\n const result = applyStateEvent(incoming);\n\n if (!result.ok) {\n res.status(409).json({\n reason: result.reason,\n current: result.current,\n });\n return;\n }\n\n res.status(200).json({ ok: true, event: result.event });\n },\n\n /**\n * Handles snapshot GET requests for Express.\n * @param {Request} req - Express request object.\n * @param {Response} res - Express response object.\n */\n snapshot: (req: Request, res: Response) => sendSnapshot(req, res),\n };\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import {sendSnapshot,createSSEConnection,applyStateEvent}from'@iadev93/zuno/server';function c(n){let{headers:o}=n??{};return {sse:(t,e)=>createSSEConnection(t,e,o??{}),sync:(t,e)=>{let r=t.body,s=applyStateEvent(r);if(!s.ok){e.status(409).json({reason:s.reason,current:s.current});return}e.status(200).json({ok:true,event:s.event});},snapshot:(t,e)=>sendSnapshot(t,e)}}export{c as createZunoExpress};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["createZunoExpress","opts","headers","req","res","createSSEConnection","incoming","result","applyStateEvent","sendSnapshot"],"mappings":"oFAyBO,SAASA,CAAAA,CAAkBC,EAAiC,CACjE,GAAM,CAAE,OAAA,CAAAC,CAAQ,EAAID,CAAAA,EAAQ,GAE5B,OAAO,CAML,GAAA,CAAK,CAACE,EAAcC,CAAAA,GAAkBC,mBAAAA,CAAoBF,EAAKC,CAAAA,CAAKF,CAAAA,EAAW,EAAE,CAAA,CAOjF,KAAM,CAACC,CAAAA,CAAcC,IAAkB,CACrC,IAAME,EAAWH,CAAAA,CAAI,IAAA,CACfI,EAASC,eAAAA,CAAgBF,CAAQ,CAAA,CAEvC,GAAI,CAACC,CAAAA,CAAO,EAAA,CAAI,CACdH,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CACnB,MAAA,CAAQG,CAAAA,CAAO,OACf,OAAA,CAASA,CAAAA,CAAO,OAClB,CAAC,CAAA,CACD,MACF,CAEAH,CAAAA,CAAI,MAAA,CAAO,GAAG,EAAE,IAAA,CAAK,CAAE,GAAI,IAAA,CAAM,KAAA,CAAOG,EAAO,KAAM,CAAC,EACxD,CAAA,CAOA,QAAA,CAAU,CAACJ,CAAAA,CAAcC,CAAAA,GAAkBK,aAAaN,CAAAA,CAAKC,CAAG,CAClE,CACF","file":"index.mjs","sourcesContent":["import type { Request, Response } from \"express\";\nimport type { IncomingHttpHeaders } from \"http\";\nimport type { ZunoStateEvent } from \"@iadev93/zuno\";\nimport { \n createSSEConnection, \n applyStateEvent, \n sendSnapshot \n} from \"@iadev93/zuno/server\";\n\n/**\n * Options for creating an Express router for Zuno.\n */\nexport type CreateZunoExpressOptions = {\n /** Optional custom headers to be sent with the SSE response. */\n headers?: IncomingHttpHeaders;\n};\n\n/**\n * Creates a Zuno Express instance.\n * @param {CreateZunoExpressOptions} [opts] - Options for creating the Express router.\n * @returns {Object} An object with the following properties:\n * - sse: An Express handler function that handles SSE connections.\n * - sync: An Express handler function that handles sync POST requests.\n * - snapshot: An Express handler function that handles snapshot GET requests.\n */\nexport function createZunoExpress(opts?: CreateZunoExpressOptions) {\n const { headers } = opts ?? {};\n\n return {\n /**\n * Handles SSE connections for Express.\n * @param {Request} req - Express request object.\n * @param {Response} res - Express response object.\n */\n sse: (req: Request, res: Response) => createSSEConnection(req, res, headers ?? {}),\n\n /**\n * Handles sync POST requests for Express.\n * @param {Request} req - Express request object.\n * @param {Response} res - Express response object.\n */\n sync: (req: Request, res: Response) => {\n const incoming = req.body as ZunoStateEvent;\n const result = applyStateEvent(incoming);\n\n if (!result.ok) {\n res.status(409).json({\n reason: result.reason,\n current: result.current,\n });\n return;\n }\n\n res.status(200).json({ ok: true, event: result.event });\n },\n\n /**\n * Handles snapshot GET requests for Express.\n * @param {Request} req - Express request object.\n * @param {Response} res - Express response object.\n */\n snapshot: (req: Request, res: Response) => sendSnapshot(req, res),\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iadev93/zuno-express",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -21,6 +21,7 @@
21
21
  "devDependencies": {
22
22
  "@types/express": "^5.0.0",
23
23
  "@types/node": "^20.0.0",
24
+ "tsup": "^8.5.1",
24
25
  "typescript": "^5.9.3",
25
26
  "@iadev93/zuno": "0.0.5"
26
27
  },
@@ -46,6 +47,7 @@
46
47
  "author": "Ibrahim Aftab",
47
48
  "license": "MIT",
48
49
  "scripts": {
49
- "build": "tsc -p tsconfig.json"
50
+ "build": "tsup",
51
+ "dev": "tsup --watch"
50
52
  }
51
53
  }
@@ -1,29 +0,0 @@
1
- import type { IncomingHttpHeaders } from "http";
2
- /**
3
- * Options for creating an Express router for Zuno.
4
- */
5
- type CreateZunoExpressOptions = {
6
- headers?: IncomingHttpHeaders;
7
- };
8
- /**
9
- * Creates an Express router for Zuno.
10
- *
11
- * @param opts - Options for creating the Express router.
12
- * @returns An object containing the SSE, sync, and snapshot handlers
13
- */
14
- export declare function createZunoExpress(opts?: CreateZunoExpressOptions): {
15
- /**
16
- * Handles SSE connections.
17
- */
18
- sse: (req: import("express").Request, res: import("express").Response) => void;
19
- /**
20
- * Handles sync connections.
21
- */
22
- sync: (req: import("express").Request, res: import("express").Response) => void;
23
- /**
24
- * Handles snapshot connections.
25
- */
26
- snapshot: (req: import("express").Request, res: import("express").Response) => void;
27
- };
28
- export {};
29
- //# sourceMappingURL=createZunoExpress.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createZunoExpress.d.ts","sourceRoot":"","sources":["../src/createZunoExpress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAA;AAK/C;;GAEG;AACH,KAAK,wBAAwB,GAAG;IAC9B,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAC9B,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,wBAAwB;IAI7D;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;EAGN"}
@@ -1,26 +0,0 @@
1
- import { createExpressSSEHandler } from "./express-sse-handler";
2
- import { createExpressSyncHandler } from "./express-sync-handler";
3
- import { createExpressSnapshotHandler } from "./express-snapshot-handler";
4
- /**
5
- * Creates an Express router for Zuno.
6
- *
7
- * @param opts - Options for creating the Express router.
8
- * @returns An object containing the SSE, sync, and snapshot handlers
9
- */
10
- export function createZunoExpress(opts) {
11
- const { headers } = opts ?? {};
12
- return {
13
- /**
14
- * Handles SSE connections.
15
- */
16
- sse: createExpressSSEHandler(headers),
17
- /**
18
- * Handles sync connections.
19
- */
20
- sync: createExpressSyncHandler(),
21
- /**
22
- * Handles snapshot connections.
23
- */
24
- snapshot: createExpressSnapshotHandler(),
25
- };
26
- }
@@ -1,7 +0,0 @@
1
- import type { Request, Response } from "express";
2
- /**
3
- * Creates an Express handler for handling Zuno state events.
4
- * @returns An Express handler function.
5
- */
6
- export declare function createExpressSnapshotHandler(): (req: Request, res: Response) => void;
7
- //# sourceMappingURL=express-snapshot-handler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"express-snapshot-handler.d.ts","sourceRoot":"","sources":["../src/express-snapshot-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGhD;;;GAGG;AACH,wBAAgB,4BAA4B,KAClC,KAAK,OAAO,EAAE,KAAK,QAAQ,UACpC"}
@@ -1,8 +0,0 @@
1
- import { sendSnapshot } from "@iadev93/zuno/server";
2
- /**
3
- * Creates an Express handler for handling Zuno state events.
4
- * @returns An Express handler function.
5
- */
6
- export function createExpressSnapshotHandler() {
7
- return (req, res) => sendSnapshot(req, res);
8
- }
@@ -1,8 +0,0 @@
1
- import type { Request, Response } from "express";
2
- import type { IncomingHttpHeaders } from "http";
3
- /**
4
- * Creates an SSE handler for express.
5
- * @returns An Express handler function.
6
- */
7
- export declare function createExpressSSEHandler(headers?: IncomingHttpHeaders): (req: Request, res: Response) => void;
8
- //# sourceMappingURL=express-sse-handler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"express-sse-handler.d.ts","sourceRoot":"","sources":["../src/express-sse-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAIhD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,mBAAmB,IAI3D,KAAK,OAAO,EAAE,KAAK,QAAQ,UACpC"}
@@ -1,11 +0,0 @@
1
- import { createSSEConnection } from "@iadev93/zuno/server";
2
- /**
3
- * Creates an SSE handler for express.
4
- * @returns An Express handler function.
5
- */
6
- export function createExpressSSEHandler(headers) {
7
- /**
8
- * Creates an SSE connection for the client.
9
- */
10
- return (req, res) => createSSEConnection(req, res, headers ?? {});
11
- }
@@ -1,7 +0,0 @@
1
- import type { Request, Response } from "express";
2
- /**
3
- * Creates an Express handler for handling Zuno state events.
4
- * @returns An Express handler function.
5
- */
6
- export declare function createExpressSyncHandler(): (req: Request, res: Response) => void;
7
- //# sourceMappingURL=express-sync-handler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"express-sync-handler.d.ts","sourceRoot":"","sources":["../src/express-sync-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKhD;;;GAGG;AACH,wBAAgB,wBAAwB,KAC9B,KAAK,OAAO,EAAE,KAAK,QAAQ,UAmBpC"}
@@ -1,23 +0,0 @@
1
- import { applyStateEvent } from "@iadev93/zuno/server";
2
- /**
3
- * Creates an Express handler for handling Zuno state events.
4
- * @returns An Express handler function.
5
- */
6
- export function createExpressSyncHandler() {
7
- return (req, res) => {
8
- /** The incoming state event to apply. */
9
- const incoming = req.body;
10
- /** Applies the incoming state event to the target Zuno universe or store. */
11
- const result = applyStateEvent(incoming);
12
- /** If the state event is not valid, returns a 409 status code with the reason and current state. */
13
- if (!result.ok) {
14
- res.status(409).json({
15
- reason: result.reason,
16
- current: result.current,
17
- });
18
- return;
19
- }
20
- /** Returns a 200 status code with the result. */
21
- res.status(200).json({ ok: true, event: result.event });
22
- };
23
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAQhD;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,gEAAgE;IAChE,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,wBAAwB;IAI7D;;;;OAIG;eACQ,OAAO,OAAO,QAAQ;IAEjC;;;;OAIG;gBACS,OAAO,OAAO,QAAQ;IAelC;;;;OAIG;oBACa,OAAO,OAAO,QAAQ;EAEzC"}