@iadev93/zuno-elysia 0.0.3 → 0.0.4

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.mts CHANGED
@@ -12,6 +12,7 @@ import { ZunoStateEvent } from '@iadev93/zuno';
12
12
  * @property {Object} body - Elysia request body.
13
13
  * @property {Object} set - Elysia response object.
14
14
  * - snapshot: A function that handles snapshot GET requests for Elysia.
15
+ * - snapshot: A function that handles snapshot GET requests for Elysia.
15
16
  */
16
17
  declare function createZunoElysia(): {
17
18
  /**
@@ -21,9 +22,7 @@ declare function createZunoElysia(): {
21
22
  * @param {Object} param.headers - Elysia request headers.
22
23
  * @param {Object} param.query - Elysia request query parameters.
23
24
  */
24
- sse: ({ set, headers, query }: any) => AsyncGenerator<string | {
25
- readonly data: string;
26
- }, never, unknown>;
25
+ sse: ({ set, headers, query }: any) => AsyncGenerator<any, never, unknown>;
27
26
  /**
28
27
  * Handles sync POST requests for Elysia.
29
28
  * @param {Object} param - Elysia request object.
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ import { ZunoStateEvent } from '@iadev93/zuno';
12
12
  * @property {Object} body - Elysia request body.
13
13
  * @property {Object} set - Elysia response object.
14
14
  * - snapshot: A function that handles snapshot GET requests for Elysia.
15
+ * - snapshot: A function that handles snapshot GET requests for Elysia.
15
16
  */
16
17
  declare function createZunoElysia(): {
17
18
  /**
@@ -21,9 +22,7 @@ declare function createZunoElysia(): {
21
22
  * @param {Object} param.headers - Elysia request headers.
22
23
  * @param {Object} param.query - Elysia request query parameters.
23
24
  */
24
- sse: ({ set, headers, query }: any) => AsyncGenerator<string | {
25
- readonly data: string;
26
- }, never, unknown>;
25
+ sse: ({ set, headers, query }: any) => AsyncGenerator<any, never, unknown>;
27
26
  /**
28
27
  * Handles sync POST requests for Elysia.
29
28
  * @param {Object} param - Elysia request object.
package/dist/index.js CHANGED
@@ -1,18 +1,2 @@
1
- 'use strict';var server=require('@iadev93/zuno/server'),elysia=require('elysia');function g(){return {sse:async function*({set:s,headers:i,query:l}){s.headers["Content-Type"]="text/event-stream",s.headers["Cache-Control"]="no-cache",s.headers.Connection="keep-alive",yield elysia.sse(`: connected
2
- `),yield elysia.sse(":"+" ".repeat(2048)+`
3
-
4
- `);let n=i["last-event-id"]||l?.lastEventId,v=Number.parseInt(n||"0",10)||0;if(v>0){let e=server.getEventsAfter(v);for(let u of e)yield elysia.sse(`id: ${u.eventId}
5
- event: state
6
- data: ${JSON.stringify(u)}
7
-
8
- `);}else {let e=server.getUniverseState();yield elysia.sse(`event: snapshot
9
- data: ${JSON.stringify(e)}
10
-
11
- `);}let a=[],t=null,c=server.subscribeToStateEvents(e=>{a.push(`id: ${e.eventId}
12
- event: state
13
- data: ${JSON.stringify(e)}
14
-
15
- `),t&&(t(),t=null);}),d=setInterval(()=>{a.push(`: ping ${Date.now()}
16
-
17
- `),t&&(t(),t=null);},15e3);try{for(;;)for(a.length===0&&await new Promise(e=>{t=e;});a.length>0;)yield a.shift();}finally{clearInterval(d),c();}},sync:({body:s,set:i})=>{let n=server.applyStateEvent(s);return n.ok?{ok:true,event:n.event}:(i.status=409,{ok:false,reason:n.reason,current:n.current})},snapshot:()=>({state:server.getUniverseState(),version:server.getUniverseState().version??0,lastEventId:server.getLastEventId()})}}exports.createZunoElysia=g;//# sourceMappingURL=index.js.map
1
+ 'use strict';var server=require('@iadev93/zuno/server'),elysia=require('elysia');function E(){return {sse:async function*({set:s,headers:r,query:l}){s.headers["Content-Type"]="text/event-stream",s.headers["Cache-Control"]="no-cache",s.headers.Connection="keep-alive",yield elysia.sse({data:": connected"});let n=r["last-event-id"]||l?.lastEventId,v=Number.parseInt(n||"0",10)||0;if(v>0){let e=server.getEventsAfter(v);for(let u of e)yield elysia.sse({id:String(u.eventId),event:"state",data:JSON.stringify(u)});}else {let e=server.getUniverseState();yield elysia.sse({event:"snapshot",data:JSON.stringify(e)});}let a=[],t=null,d=server.subscribeToStateEvents(e=>{a.push(elysia.sse({id:String(e.eventId),event:"state",data:JSON.stringify(e)})),t&&(t(),t=null);}),c=setInterval(()=>{a.push(elysia.sse({data:`: ping ${Date.now()}`})),t&&(t(),t=null);},15e3);try{for(;;)for(a.length===0&&await new Promise(e=>{t=e;});a.length>0;)yield a.shift();}finally{clearInterval(c),d();}},sync:({body:s,set:r})=>{let n=server.applyStateEvent(s);return n.ok?{ok:true,event:n.event}:(r.status=409,{ok:false,reason:n.reason,current:n.current})},snapshot:()=>({state:server.getUniverseState(),version:server.getUniverseState().version??0,lastEventId:server.getLastEventId()})}}exports.createZunoElysia=E;//# sourceMappingURL=index.js.map
18
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["createZunoElysia","set","headers","query","elysiaSSE","rawLastEventId","lastEventId","missed","getEventsAfter","event","snapshot","getUniverseState","queue","resolve","unsubscribe","subscribeToStateEvents","heartbeat","r","body","result","applyStateEvent","getLastEventId"],"mappings":"iFAsBO,SAASA,GAAmB,CACjC,OAAO,CAQL,GAAA,CAAK,gBAAiB,CAAE,IAAAC,CAAAA,CAAK,OAAA,CAAAC,EAAS,KAAA,CAAAC,CAAM,EAAQ,CAClDF,CAAAA,CAAI,QAAQ,cAAc,CAAA,CAAI,oBAC9BA,CAAAA,CAAI,OAAA,CAAQ,eAAe,CAAA,CAAI,UAAA,CAC/BA,EAAI,OAAA,CAAQ,UAAA,CAAgB,YAAA,CAE5B,MAAMG,UAAAA,CAAU,CAAA;AAAA,CAAe,EAC/B,MAAMA,UAAAA,CAAU,IAAM,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,CAAI;;AAAA,CAAM,CAAA,CAG/C,IAAMC,CAAAA,CAAiBH,CAAAA,CAAQ,eAAe,CAAA,EAAKC,CAAAA,EAAO,WAAA,CACpDG,CAAAA,CAAc,MAAA,CAAO,QAAA,CAASD,CAAAA,EAAkB,GAAA,CAAK,EAAE,CAAA,EAAK,CAAA,CAElE,GAAIC,CAAAA,CAAc,CAAA,CAAG,CACnB,IAAMC,CAAAA,CAASC,sBAAeF,CAAW,CAAA,CACzC,IAAA,IAAWG,CAAAA,IAASF,CAAAA,CAClB,MAAMH,UAAAA,CAAU,CAAA,IAAA,EAAOK,EAAM,OAAO;AAAA;AAAA,MAAA,EAAyB,IAAA,CAAK,SAAA,CAAUA,CAAK,CAAC;;AAAA,CAAM,EAE5F,MAAO,CACL,IAAMC,EAAWC,uBAAAA,EAAiB,CAClC,MAAMP,UAAAA,CAAU,CAAA;AAAA,MAAA,EAA0B,IAAA,CAAK,SAAA,CAAUM,CAAQ,CAAC;;AAAA,CAAM,EAC1E,CAGA,IAAME,CAAAA,CAAkB,GACpBC,CAAAA,CAA8D,IAAA,CAG5DC,CAAAA,CAAcC,6BAAAA,CAAwBN,GAA0B,CACpEG,CAAAA,CAAM,IAAA,CAAK,CAAA,IAAA,EAAOH,EAAM,OAAO;AAAA;AAAA,MAAA,EAAyB,IAAA,CAAK,SAAA,CAAUA,CAAK,CAAC;;AAAA,CAAM,EAC/EI,CAAAA,GACFA,CAAAA,EAAQ,CACRA,CAAAA,CAAU,MAEd,CAAC,CAAA,CAGKG,CAAAA,CAAY,WAAA,CAAY,IAAM,CAClCJ,CAAAA,CAAM,KAAK,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK;;AAAA,CAAM,CAAA,CACjCC,IACFA,CAAAA,EAAQ,CACRA,EAAU,IAAA,EAEd,CAAA,CAAG,IAAK,CAAA,CAER,GAAI,CACF,OAOE,IANID,EAAM,MAAA,GAAW,CAAA,EACnB,MAAM,IAAI,OAAA,CAAeK,GAAM,CAC7BJ,CAAAA,CAAUI,EACZ,CAAC,CAAA,CAGIL,EAAM,MAAA,CAAS,CAAA,EACpB,MAAMA,CAAAA,CAAM,KAAA,GAGlB,CAAA,OAAE,CACA,cAAcI,CAAS,CAAA,CACvBF,IACF,CACF,EAWA,IAAA,CAAM,CAAC,CAAE,IAAA,CAAAI,CAAAA,CAAM,GAAA,CAAAjB,CAAI,CAAA,GAAW,CAE5B,IAAMkB,CAAAA,CAASC,sBAAAA,CADEF,CACsB,CAAA,CAEvC,OAAKC,EAAO,EAAA,CASL,CAAE,GAAI,IAAA,CAAM,KAAA,CAAOA,EAAO,KAAM,CAAA,EARrClB,EAAI,MAAA,CAAS,GAAA,CACN,CACL,EAAA,CAAI,KAAA,CACJ,OAAQkB,CAAAA,CAAO,MAAA,CACf,QAASA,CAAAA,CAAO,OAClB,EAIJ,CAAA,CASA,QAAA,CAAU,KACD,CACL,KAAA,CAAOR,yBAAiB,CACxB,OAAA,CAAUA,yBAAiB,CAAU,OAAA,EAAW,EAChD,WAAA,CAAaU,qBAAAA,EACf,CAAA,CAEJ,CACF","file":"index.js","sourcesContent":["import type { ZunoStateEvent } from \"@iadev93/zuno\";\nimport {\n applyStateEvent,\n getEventsAfter,\n getLastEventId,\n getUniverseState,\n subscribeToStateEvents,\n} from \"@iadev93/zuno/server\";\nimport { sse as elysiaSSE } from \"elysia\"\n\n/**\n * Creates a Zuno Elysia instance.\n * @returns {Object} An object with the following properties:\n * - sse: An async generator function that handles SSE connections for Elysia.\n * @property {Object} set - Elysia response object.\n * @property {Object} headers - Elysia request headers.\n * @property {Object} query - Elysia request query parameters.\n * - sync: A function that handles sync POST requests for Elysia.\n * @property {Object} body - Elysia request body.\n * @property {Object} set - Elysia response object.\n * - snapshot: A function that handles snapshot GET requests for Elysia.\n */\nexport function createZunoElysia() {\n return {\n /**\n * Handles SSE connections for Elysia using an async generator.\n * @param {Object} param - Elysia request object.\n * @param {Object} param.set - Elysia response object.\n * @param {Object} param.headers - Elysia request headers.\n * @param {Object} param.query - Elysia request query parameters.\n */\n sse: async function* ({ set, headers, query }: any) {\n set.headers[\"Content-Type\"] = \"text/event-stream\";\n set.headers[\"Cache-Control\"] = \"no-cache\";\n set.headers[\"Connection\"] = \"keep-alive\";\n\n yield elysiaSSE(\": connected\\n\");\n yield elysiaSSE(\":\" + \" \".repeat(2048) + \"\\n\\n\"); // Padding to bypass browser buffering\n\n // Get last event id\n const rawLastEventId = headers[\"last-event-id\"] || query?.lastEventId;\n const lastEventId = Number.parseInt(rawLastEventId || \"0\", 10) || 0;\n\n if (lastEventId > 0) {\n const missed = getEventsAfter(lastEventId);\n for (const event of missed) {\n yield elysiaSSE(`id: ${event.eventId}\\nevent: state\\ndata: ${JSON.stringify(event)}\\n\\n`);\n }\n } else {\n const snapshot = getUniverseState();\n yield elysiaSSE(`event: snapshot\\ndata: ${JSON.stringify(snapshot)}\\n\\n`);\n }\n\n // Buffer queue for events\n const queue: string[] = [];\n let resolve: ((value: void | PromiseLike<void>) => void) | null = null;\n\n // Subscribe to events\n const unsubscribe = subscribeToStateEvents((event: ZunoStateEvent) => {\n queue.push(`id: ${event.eventId}\\nevent: state\\ndata: ${JSON.stringify(event)}\\n\\n`);\n if (resolve) {\n resolve();\n resolve = null;\n }\n });\n\n // Heartbeat interval\n const heartbeat = setInterval(() => {\n queue.push(`: ping ${Date.now()}\\n\\n`);\n if (resolve) {\n resolve();\n resolve = null;\n }\n }, 15000);\n\n try {\n while (true) {\n if (queue.length === 0) {\n await new Promise<void>((r) => {\n resolve = r;\n });\n }\n\n while (queue.length > 0) {\n yield queue.shift()!;\n }\n }\n } finally {\n clearInterval(heartbeat);\n unsubscribe();\n }\n },\n\n /**\n * Handles sync POST requests for Elysia.\n * @param {Object} param - Elysia request object.\n * @param {Object} param.body - Elysia request body.\n * @param {Object} param.set - Elysia response object.\n * @returns {Object} An object with the following properties:\n * - ok: A boolean indicating whether the sync was successful.\n * - event: The event that was applied to the universe.\n */\n sync: ({ body, set }: any) => {\n const incoming = body as ZunoStateEvent;\n const result = applyStateEvent(incoming);\n\n if (!result.ok) {\n set.status = 409;\n return {\n ok: false,\n reason: result.reason,\n current: result.current,\n };\n }\n\n return { ok: true, event: result.event };\n },\n\n /**\n * Handles snapshot GET requests for Elysia.\n * @returns {Object} An object with the following properties:\n * - state: The current state of the universe.\n * - version: The version of the universe.\n * - lastEventId: The ID of the last event in the universe.\n */\n snapshot: () => {\n return {\n state: getUniverseState(),\n version: (getUniverseState() as any).version ?? 0,\n lastEventId: getLastEventId(),\n };\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["createZunoElysia","set","headers","query","sse","rawLastEventId","lastEventId","missed","getEventsAfter","event","snapshot","getUniverseState","queue","resolve","unsubscribe","subscribeToStateEvents","heartbeat","r","body","result","applyStateEvent","getLastEventId"],"mappings":"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","file":"index.js","sourcesContent":["import type { ZunoStateEvent } from \"@iadev93/zuno\";\nimport {\n applyStateEvent,\n getEventsAfter,\n getLastEventId,\n getUniverseState,\n subscribeToStateEvents,\n} from \"@iadev93/zuno/server\";\nimport { sse } from \"elysia\";\n\n/**\n * Creates a Zuno Elysia instance.\n * @returns {Object} An object with the following properties:\n * - sse: An async generator function that handles SSE connections for Elysia.\n * @property {Object} set - Elysia response object.\n * @property {Object} headers - Elysia request headers.\n * @property {Object} query - Elysia request query parameters.\n * - sync: A function that handles sync POST requests for Elysia.\n * @property {Object} body - Elysia request body.\n * @property {Object} set - Elysia response object.\n * - snapshot: A function that handles snapshot GET requests for Elysia.\n * - snapshot: A function that handles snapshot GET requests for Elysia.\n */\nexport function createZunoElysia() {\n return {\n /**\n * Handles SSE connections for Elysia using an async generator.\n * @param {Object} param - Elysia request object.\n * @param {Object} param.set - Elysia response object.\n * @param {Object} param.headers - Elysia request headers.\n * @param {Object} param.query - Elysia request query parameters.\n */\n sse: async function* ({ set, headers, query }: any) {\n set.headers[\"Content-Type\"] = \"text/event-stream\";\n set.headers[\"Cache-Control\"] = \"no-cache\";\n set.headers[\"Connection\"] = \"keep-alive\";\n\n yield sse({ data: \": connected\" });\n\n // Get last event id\n const rawLastEventId = headers[\"last-event-id\"] || query?.lastEventId;\n const lastEventId = Number.parseInt(rawLastEventId || \"0\", 10) || 0;\n\n if (lastEventId > 0) {\n const missed = getEventsAfter(lastEventId);\n for (const event of missed) {\n yield sse({\n id: String(event.eventId),\n event: \"state\",\n data: JSON.stringify(event)\n });\n }\n } else {\n const snapshot = getUniverseState();\n yield sse({\n event: \"snapshot\",\n data: JSON.stringify(snapshot)\n });\n }\n\n // Buffer queue for events\n const queue: any[] = [];\n let resolve: ((value: void | PromiseLike<void>) => void) | null = null;\n\n // Subscribe to events\n const unsubscribe = subscribeToStateEvents((event: ZunoStateEvent) => {\n queue.push(sse({\n id: String(event.eventId),\n event: \"state\",\n data: JSON.stringify(event)\n }));\n if (resolve) {\n resolve();\n resolve = null;\n }\n });\n\n // Heartbeat interval\n const heartbeat = setInterval(() => {\n queue.push(sse({ data: `: ping ${Date.now()}` }));\n if (resolve) {\n resolve();\n resolve = null;\n }\n }, 15000);\n\n try {\n while (true) {\n if (queue.length === 0) {\n await new Promise<void>((r) => {\n resolve = r;\n });\n }\n\n while (queue.length > 0) {\n yield queue.shift()!;\n }\n }\n } finally {\n clearInterval(heartbeat);\n unsubscribe();\n }\n },\n\n /**\n * Handles sync POST requests for Elysia.\n * @param {Object} param - Elysia request object.\n * @param {Object} param.body - Elysia request body.\n * @param {Object} param.set - Elysia response object.\n * @returns {Object} An object with the following properties:\n * - ok: A boolean indicating whether the sync was successful.\n * - event: The event that was applied to the universe.\n */\n sync: ({ body, set }: any) => {\n const incoming = body as ZunoStateEvent;\n const result = applyStateEvent(incoming);\n\n if (!result.ok) {\n set.status = 409;\n return {\n ok: false,\n reason: result.reason,\n current: result.current,\n };\n }\n\n return { ok: true, event: result.event };\n },\n\n /**\n * Handles snapshot GET requests for Elysia.\n * @returns {Object} An object with the following properties:\n * - state: The current state of the universe.\n * - version: The version of the universe.\n * - lastEventId: The ID of the last event in the universe.\n */\n snapshot: () => {\n return {\n state: getUniverseState(),\n version: (getUniverseState() as any).version ?? 0,\n lastEventId: getLastEventId(),\n };\n },\n };\n}\n"]}
package/dist/index.mjs CHANGED
@@ -1,18 +1,2 @@
1
- import {getLastEventId,getUniverseState,applyStateEvent,getEventsAfter,subscribeToStateEvents}from'@iadev93/zuno/server';import {sse}from'elysia';function g(){return {sse:async function*({set:s,headers:i,query:l}){s.headers["Content-Type"]="text/event-stream",s.headers["Cache-Control"]="no-cache",s.headers.Connection="keep-alive",yield sse(`: connected
2
- `),yield sse(":"+" ".repeat(2048)+`
3
-
4
- `);let n=i["last-event-id"]||l?.lastEventId,v=Number.parseInt(n||"0",10)||0;if(v>0){let e=getEventsAfter(v);for(let u of e)yield sse(`id: ${u.eventId}
5
- event: state
6
- data: ${JSON.stringify(u)}
7
-
8
- `);}else {let e=getUniverseState();yield sse(`event: snapshot
9
- data: ${JSON.stringify(e)}
10
-
11
- `);}let a=[],t=null,c=subscribeToStateEvents(e=>{a.push(`id: ${e.eventId}
12
- event: state
13
- data: ${JSON.stringify(e)}
14
-
15
- `),t&&(t(),t=null);}),d=setInterval(()=>{a.push(`: ping ${Date.now()}
16
-
17
- `),t&&(t(),t=null);},15e3);try{for(;;)for(a.length===0&&await new Promise(e=>{t=e;});a.length>0;)yield a.shift();}finally{clearInterval(d),c();}},sync:({body:s,set:i})=>{let n=applyStateEvent(s);return n.ok?{ok:true,event:n.event}:(i.status=409,{ok:false,reason:n.reason,current:n.current})},snapshot:()=>({state:getUniverseState(),version:getUniverseState().version??0,lastEventId:getLastEventId()})}}export{g as createZunoElysia};//# sourceMappingURL=index.mjs.map
1
+ import {getLastEventId,getUniverseState,applyStateEvent,getEventsAfter,subscribeToStateEvents}from'@iadev93/zuno/server';import {sse}from'elysia';function E(){return {sse:async function*({set:s,headers:r,query:l}){s.headers["Content-Type"]="text/event-stream",s.headers["Cache-Control"]="no-cache",s.headers.Connection="keep-alive",yield sse({data:": connected"});let n=r["last-event-id"]||l?.lastEventId,v=Number.parseInt(n||"0",10)||0;if(v>0){let e=getEventsAfter(v);for(let u of e)yield sse({id:String(u.eventId),event:"state",data:JSON.stringify(u)});}else {let e=getUniverseState();yield sse({event:"snapshot",data:JSON.stringify(e)});}let a=[],t=null,d=subscribeToStateEvents(e=>{a.push(sse({id:String(e.eventId),event:"state",data:JSON.stringify(e)})),t&&(t(),t=null);}),c=setInterval(()=>{a.push(sse({data:`: ping ${Date.now()}`})),t&&(t(),t=null);},15e3);try{for(;;)for(a.length===0&&await new Promise(e=>{t=e;});a.length>0;)yield a.shift();}finally{clearInterval(c),d();}},sync:({body:s,set:r})=>{let n=applyStateEvent(s);return n.ok?{ok:true,event:n.event}:(r.status=409,{ok:false,reason:n.reason,current:n.current})},snapshot:()=>({state:getUniverseState(),version:getUniverseState().version??0,lastEventId:getLastEventId()})}}export{E as createZunoElysia};//# sourceMappingURL=index.mjs.map
18
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["createZunoElysia","set","headers","query","elysiaSSE","rawLastEventId","lastEventId","missed","getEventsAfter","event","snapshot","getUniverseState","queue","resolve","unsubscribe","subscribeToStateEvents","heartbeat","r","body","result","applyStateEvent","getLastEventId"],"mappings":"kJAsBO,SAASA,GAAmB,CACjC,OAAO,CAQL,GAAA,CAAK,gBAAiB,CAAE,IAAAC,CAAAA,CAAK,OAAA,CAAAC,EAAS,KAAA,CAAAC,CAAM,EAAQ,CAClDF,CAAAA,CAAI,QAAQ,cAAc,CAAA,CAAI,oBAC9BA,CAAAA,CAAI,OAAA,CAAQ,eAAe,CAAA,CAAI,UAAA,CAC/BA,EAAI,OAAA,CAAQ,UAAA,CAAgB,YAAA,CAE5B,MAAMG,GAAAA,CAAU,CAAA;AAAA,CAAe,EAC/B,MAAMA,GAAAA,CAAU,IAAM,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,CAAI;;AAAA,CAAM,CAAA,CAG/C,IAAMC,CAAAA,CAAiBH,CAAAA,CAAQ,eAAe,CAAA,EAAKC,CAAAA,EAAO,WAAA,CACpDG,CAAAA,CAAc,MAAA,CAAO,QAAA,CAASD,CAAAA,EAAkB,GAAA,CAAK,EAAE,CAAA,EAAK,CAAA,CAElE,GAAIC,CAAAA,CAAc,CAAA,CAAG,CACnB,IAAMC,CAAAA,CAASC,eAAeF,CAAW,CAAA,CACzC,IAAA,IAAWG,CAAAA,IAASF,CAAAA,CAClB,MAAMH,GAAAA,CAAU,CAAA,IAAA,EAAOK,EAAM,OAAO;AAAA;AAAA,MAAA,EAAyB,IAAA,CAAK,SAAA,CAAUA,CAAK,CAAC;;AAAA,CAAM,EAE5F,MAAO,CACL,IAAMC,EAAWC,gBAAAA,EAAiB,CAClC,MAAMP,GAAAA,CAAU,CAAA;AAAA,MAAA,EAA0B,IAAA,CAAK,SAAA,CAAUM,CAAQ,CAAC;;AAAA,CAAM,EAC1E,CAGA,IAAME,CAAAA,CAAkB,GACpBC,CAAAA,CAA8D,IAAA,CAG5DC,CAAAA,CAAcC,sBAAAA,CAAwBN,GAA0B,CACpEG,CAAAA,CAAM,IAAA,CAAK,CAAA,IAAA,EAAOH,EAAM,OAAO;AAAA;AAAA,MAAA,EAAyB,IAAA,CAAK,SAAA,CAAUA,CAAK,CAAC;;AAAA,CAAM,EAC/EI,CAAAA,GACFA,CAAAA,EAAQ,CACRA,CAAAA,CAAU,MAEd,CAAC,CAAA,CAGKG,CAAAA,CAAY,WAAA,CAAY,IAAM,CAClCJ,CAAAA,CAAM,KAAK,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK;;AAAA,CAAM,CAAA,CACjCC,IACFA,CAAAA,EAAQ,CACRA,EAAU,IAAA,EAEd,CAAA,CAAG,IAAK,CAAA,CAER,GAAI,CACF,OAOE,IANID,EAAM,MAAA,GAAW,CAAA,EACnB,MAAM,IAAI,OAAA,CAAeK,GAAM,CAC7BJ,CAAAA,CAAUI,EACZ,CAAC,CAAA,CAGIL,EAAM,MAAA,CAAS,CAAA,EACpB,MAAMA,CAAAA,CAAM,KAAA,GAGlB,CAAA,OAAE,CACA,cAAcI,CAAS,CAAA,CACvBF,IACF,CACF,EAWA,IAAA,CAAM,CAAC,CAAE,IAAA,CAAAI,CAAAA,CAAM,GAAA,CAAAjB,CAAI,CAAA,GAAW,CAE5B,IAAMkB,CAAAA,CAASC,eAAAA,CADEF,CACsB,CAAA,CAEvC,OAAKC,EAAO,EAAA,CASL,CAAE,GAAI,IAAA,CAAM,KAAA,CAAOA,EAAO,KAAM,CAAA,EARrClB,EAAI,MAAA,CAAS,GAAA,CACN,CACL,EAAA,CAAI,KAAA,CACJ,OAAQkB,CAAAA,CAAO,MAAA,CACf,QAASA,CAAAA,CAAO,OAClB,EAIJ,CAAA,CASA,QAAA,CAAU,KACD,CACL,KAAA,CAAOR,kBAAiB,CACxB,OAAA,CAAUA,kBAAiB,CAAU,OAAA,EAAW,EAChD,WAAA,CAAaU,cAAAA,EACf,CAAA,CAEJ,CACF","file":"index.mjs","sourcesContent":["import type { ZunoStateEvent } from \"@iadev93/zuno\";\nimport {\n applyStateEvent,\n getEventsAfter,\n getLastEventId,\n getUniverseState,\n subscribeToStateEvents,\n} from \"@iadev93/zuno/server\";\nimport { sse as elysiaSSE } from \"elysia\"\n\n/**\n * Creates a Zuno Elysia instance.\n * @returns {Object} An object with the following properties:\n * - sse: An async generator function that handles SSE connections for Elysia.\n * @property {Object} set - Elysia response object.\n * @property {Object} headers - Elysia request headers.\n * @property {Object} query - Elysia request query parameters.\n * - sync: A function that handles sync POST requests for Elysia.\n * @property {Object} body - Elysia request body.\n * @property {Object} set - Elysia response object.\n * - snapshot: A function that handles snapshot GET requests for Elysia.\n */\nexport function createZunoElysia() {\n return {\n /**\n * Handles SSE connections for Elysia using an async generator.\n * @param {Object} param - Elysia request object.\n * @param {Object} param.set - Elysia response object.\n * @param {Object} param.headers - Elysia request headers.\n * @param {Object} param.query - Elysia request query parameters.\n */\n sse: async function* ({ set, headers, query }: any) {\n set.headers[\"Content-Type\"] = \"text/event-stream\";\n set.headers[\"Cache-Control\"] = \"no-cache\";\n set.headers[\"Connection\"] = \"keep-alive\";\n\n yield elysiaSSE(\": connected\\n\");\n yield elysiaSSE(\":\" + \" \".repeat(2048) + \"\\n\\n\"); // Padding to bypass browser buffering\n\n // Get last event id\n const rawLastEventId = headers[\"last-event-id\"] || query?.lastEventId;\n const lastEventId = Number.parseInt(rawLastEventId || \"0\", 10) || 0;\n\n if (lastEventId > 0) {\n const missed = getEventsAfter(lastEventId);\n for (const event of missed) {\n yield elysiaSSE(`id: ${event.eventId}\\nevent: state\\ndata: ${JSON.stringify(event)}\\n\\n`);\n }\n } else {\n const snapshot = getUniverseState();\n yield elysiaSSE(`event: snapshot\\ndata: ${JSON.stringify(snapshot)}\\n\\n`);\n }\n\n // Buffer queue for events\n const queue: string[] = [];\n let resolve: ((value: void | PromiseLike<void>) => void) | null = null;\n\n // Subscribe to events\n const unsubscribe = subscribeToStateEvents((event: ZunoStateEvent) => {\n queue.push(`id: ${event.eventId}\\nevent: state\\ndata: ${JSON.stringify(event)}\\n\\n`);\n if (resolve) {\n resolve();\n resolve = null;\n }\n });\n\n // Heartbeat interval\n const heartbeat = setInterval(() => {\n queue.push(`: ping ${Date.now()}\\n\\n`);\n if (resolve) {\n resolve();\n resolve = null;\n }\n }, 15000);\n\n try {\n while (true) {\n if (queue.length === 0) {\n await new Promise<void>((r) => {\n resolve = r;\n });\n }\n\n while (queue.length > 0) {\n yield queue.shift()!;\n }\n }\n } finally {\n clearInterval(heartbeat);\n unsubscribe();\n }\n },\n\n /**\n * Handles sync POST requests for Elysia.\n * @param {Object} param - Elysia request object.\n * @param {Object} param.body - Elysia request body.\n * @param {Object} param.set - Elysia response object.\n * @returns {Object} An object with the following properties:\n * - ok: A boolean indicating whether the sync was successful.\n * - event: The event that was applied to the universe.\n */\n sync: ({ body, set }: any) => {\n const incoming = body as ZunoStateEvent;\n const result = applyStateEvent(incoming);\n\n if (!result.ok) {\n set.status = 409;\n return {\n ok: false,\n reason: result.reason,\n current: result.current,\n };\n }\n\n return { ok: true, event: result.event };\n },\n\n /**\n * Handles snapshot GET requests for Elysia.\n * @returns {Object} An object with the following properties:\n * - state: The current state of the universe.\n * - version: The version of the universe.\n * - lastEventId: The ID of the last event in the universe.\n */\n snapshot: () => {\n return {\n state: getUniverseState(),\n version: (getUniverseState() as any).version ?? 0,\n lastEventId: getLastEventId(),\n };\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["createZunoElysia","set","headers","query","sse","rawLastEventId","lastEventId","missed","getEventsAfter","event","snapshot","getUniverseState","queue","resolve","unsubscribe","subscribeToStateEvents","heartbeat","r","body","result","applyStateEvent","getLastEventId"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { ZunoStateEvent } from \"@iadev93/zuno\";\nimport {\n applyStateEvent,\n getEventsAfter,\n getLastEventId,\n getUniverseState,\n subscribeToStateEvents,\n} from \"@iadev93/zuno/server\";\nimport { sse } from \"elysia\";\n\n/**\n * Creates a Zuno Elysia instance.\n * @returns {Object} An object with the following properties:\n * - sse: An async generator function that handles SSE connections for Elysia.\n * @property {Object} set - Elysia response object.\n * @property {Object} headers - Elysia request headers.\n * @property {Object} query - Elysia request query parameters.\n * - sync: A function that handles sync POST requests for Elysia.\n * @property {Object} body - Elysia request body.\n * @property {Object} set - Elysia response object.\n * - snapshot: A function that handles snapshot GET requests for Elysia.\n * - snapshot: A function that handles snapshot GET requests for Elysia.\n */\nexport function createZunoElysia() {\n return {\n /**\n * Handles SSE connections for Elysia using an async generator.\n * @param {Object} param - Elysia request object.\n * @param {Object} param.set - Elysia response object.\n * @param {Object} param.headers - Elysia request headers.\n * @param {Object} param.query - Elysia request query parameters.\n */\n sse: async function* ({ set, headers, query }: any) {\n set.headers[\"Content-Type\"] = \"text/event-stream\";\n set.headers[\"Cache-Control\"] = \"no-cache\";\n set.headers[\"Connection\"] = \"keep-alive\";\n\n yield sse({ data: \": connected\" });\n\n // Get last event id\n const rawLastEventId = headers[\"last-event-id\"] || query?.lastEventId;\n const lastEventId = Number.parseInt(rawLastEventId || \"0\", 10) || 0;\n\n if (lastEventId > 0) {\n const missed = getEventsAfter(lastEventId);\n for (const event of missed) {\n yield sse({\n id: String(event.eventId),\n event: \"state\",\n data: JSON.stringify(event)\n });\n }\n } else {\n const snapshot = getUniverseState();\n yield sse({\n event: \"snapshot\",\n data: JSON.stringify(snapshot)\n });\n }\n\n // Buffer queue for events\n const queue: any[] = [];\n let resolve: ((value: void | PromiseLike<void>) => void) | null = null;\n\n // Subscribe to events\n const unsubscribe = subscribeToStateEvents((event: ZunoStateEvent) => {\n queue.push(sse({\n id: String(event.eventId),\n event: \"state\",\n data: JSON.stringify(event)\n }));\n if (resolve) {\n resolve();\n resolve = null;\n }\n });\n\n // Heartbeat interval\n const heartbeat = setInterval(() => {\n queue.push(sse({ data: `: ping ${Date.now()}` }));\n if (resolve) {\n resolve();\n resolve = null;\n }\n }, 15000);\n\n try {\n while (true) {\n if (queue.length === 0) {\n await new Promise<void>((r) => {\n resolve = r;\n });\n }\n\n while (queue.length > 0) {\n yield queue.shift()!;\n }\n }\n } finally {\n clearInterval(heartbeat);\n unsubscribe();\n }\n },\n\n /**\n * Handles sync POST requests for Elysia.\n * @param {Object} param - Elysia request object.\n * @param {Object} param.body - Elysia request body.\n * @param {Object} param.set - Elysia response object.\n * @returns {Object} An object with the following properties:\n * - ok: A boolean indicating whether the sync was successful.\n * - event: The event that was applied to the universe.\n */\n sync: ({ body, set }: any) => {\n const incoming = body as ZunoStateEvent;\n const result = applyStateEvent(incoming);\n\n if (!result.ok) {\n set.status = 409;\n return {\n ok: false,\n reason: result.reason,\n current: result.current,\n };\n }\n\n return { ok: true, event: result.event };\n },\n\n /**\n * Handles snapshot GET requests for Elysia.\n * @returns {Object} An object with the following properties:\n * - state: The current state of the universe.\n * - version: The version of the universe.\n * - lastEventId: The ID of the last event in the universe.\n */\n snapshot: () => {\n return {\n state: getUniverseState(),\n version: (getUniverseState() as any).version ?? 0,\n lastEventId: getLastEventId(),\n };\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iadev93/zuno-elysia",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -11,18 +11,19 @@
11
11
  "exports": {
12
12
  ".": {
13
13
  "types": "./dist/index.d.ts",
14
- "default": "./dist/index.js"
14
+ "import": "./dist/index.mjs",
15
+ "require": "./dist/index.js"
15
16
  }
16
17
  },
17
18
  "peerDependencies": {
18
19
  "elysia": ">=1.0.0",
19
- "@iadev93/zuno": "0.0.5"
20
+ "@iadev93/zuno": "0.0.7"
20
21
  },
21
22
  "devDependencies": {
22
23
  "elysia": "^1.2.10",
23
24
  "tsup": "^8.5.1",
24
25
  "typescript": "^5.9.3",
25
- "@iadev93/zuno": "0.0.5"
26
+ "@iadev93/zuno": "0.0.7"
26
27
  },
27
28
  "author": "Ibrahim Aftab",
28
29
  "license": "MIT",