@iadev93/zuno 0.0.5 → 0.0.6

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.
Files changed (72) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +7 -11
  3. package/dist/index-IbvF6TBr.d.cts +151 -0
  4. package/dist/index-IbvF6TBr.d.ts +151 -0
  5. package/dist/index.cjs +2 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/{shared/readable.d.ts → index.d.cts} +7 -4
  8. package/dist/index.d.ts +24 -10
  9. package/dist/index.js +2 -6
  10. package/dist/index.js.map +1 -0
  11. package/dist/server/index.cjs +17 -0
  12. package/dist/server/index.cjs.map +1 -0
  13. package/dist/server/index.d.cts +57 -0
  14. package/dist/server/index.d.ts +57 -4
  15. package/dist/server/index.js +17 -3
  16. package/dist/server/index.js.map +1 -0
  17. package/package.json +9 -5
  18. package/dist/core/createZuno.d.ts +0 -77
  19. package/dist/core/createZuno.d.ts.map +0 -1
  20. package/dist/core/createZuno.js +0 -250
  21. package/dist/core/store.d.ts +0 -10
  22. package/dist/core/store.d.ts.map +0 -1
  23. package/dist/core/store.js +0 -27
  24. package/dist/core/types.d.ts +0 -107
  25. package/dist/core/types.d.ts.map +0 -1
  26. package/dist/core/types.js +0 -1
  27. package/dist/core/universe.d.ts +0 -12
  28. package/dist/core/universe.d.ts.map +0 -1
  29. package/dist/core/universe.js +0 -53
  30. package/dist/index.d.ts.map +0 -1
  31. package/dist/server/apply-state-event.d.ts +0 -26
  32. package/dist/server/apply-state-event.d.ts.map +0 -1
  33. package/dist/server/apply-state-event.js +0 -29
  34. package/dist/server/index.d.ts.map +0 -1
  35. package/dist/server/server-transport.d.ts +0 -8
  36. package/dist/server/server-transport.d.ts.map +0 -1
  37. package/dist/server/server-transport.js +0 -25
  38. package/dist/server/snapshot-handler.d.ts +0 -9
  39. package/dist/server/snapshot-handler.d.ts.map +0 -1
  40. package/dist/server/snapshot-handler.js +0 -18
  41. package/dist/server/sse-handler.d.ts +0 -24
  42. package/dist/server/sse-handler.d.ts.map +0 -1
  43. package/dist/server/sse-handler.js +0 -127
  44. package/dist/server/state.bus.d.ts +0 -18
  45. package/dist/server/state.bus.d.ts.map +0 -1
  46. package/dist/server/state.bus.js +0 -26
  47. package/dist/server/state.log.d.ts +0 -22
  48. package/dist/server/state.log.d.ts.map +0 -1
  49. package/dist/server/state.log.js +0 -37
  50. package/dist/server/types.d.ts +0 -8
  51. package/dist/server/types.d.ts.map +0 -1
  52. package/dist/server/types.js +0 -1
  53. package/dist/server/universe-store.d.ts +0 -29
  54. package/dist/server/universe-store.d.ts.map +0 -1
  55. package/dist/server/universe-store.js +0 -26
  56. package/dist/shared/readable.d.ts.map +0 -1
  57. package/dist/shared/readable.js +0 -7
  58. package/dist/sync/apply-incoming-event.d.ts +0 -10
  59. package/dist/sync/apply-incoming-event.d.ts.map +0 -1
  60. package/dist/sync/apply-incoming-event.js +0 -28
  61. package/dist/sync/broadcast-channel.d.ts +0 -12
  62. package/dist/sync/broadcast-channel.d.ts.map +0 -1
  63. package/dist/sync/broadcast-channel.js +0 -73
  64. package/dist/sync/sse-client.d.ts +0 -21
  65. package/dist/sync/sse-client.d.ts.map +0 -1
  66. package/dist/sync/sse-client.js +0 -162
  67. package/dist/sync/sync-types.d.ts +0 -164
  68. package/dist/sync/sync-types.d.ts.map +0 -1
  69. package/dist/sync/sync-types.js +0 -1
  70. package/dist/sync/transport.d.ts +0 -10
  71. package/dist/sync/transport.d.ts.map +0 -1
  72. package/dist/sync/transport.js +0 -26
@@ -0,0 +1,57 @@
1
+ import { f as ZunoStateEvent } from '../index-IbvF6TBr.cjs';
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+
4
+ type UniverseRecord = {
5
+ state: any;
6
+ version: number;
7
+ };
8
+ type ZunoStateListener = (event: ZunoStateEvent) => void;
9
+ declare const getUniverseRecord: (storeKey: string) => UniverseRecord | undefined;
10
+ declare const updateUniverseState: (event: ZunoStateEvent) => void;
11
+ declare const getUniverseState: () => {
12
+ [k: string]: UniverseRecord;
13
+ };
14
+ declare const appendEvent: (event: ZunoStateEvent) => ZunoStateEvent;
15
+ declare const getEventsAfter: (lastEventId: number) => ZunoStateEvent[];
16
+ declare const getLastEventId: () => number;
17
+ declare const subscribeToStateEvents: (listener: ZunoStateListener) => () => void;
18
+ declare const publishToStateEvent: (event: ZunoStateEvent) => void;
19
+
20
+ type ApplyResult = {
21
+ ok: true;
22
+ event: ZunoStateEvent;
23
+ } | {
24
+ ok: false;
25
+ reason: "VERSION_CONFLICT";
26
+ current: {
27
+ state: any;
28
+ version: number;
29
+ };
30
+ } | {
31
+ ok: false;
32
+ reason: string;
33
+ current?: never;
34
+ };
35
+ /**
36
+ * Validates and applies a state event to the server universe.
37
+ */
38
+ declare function applyStateEvent(incoming: ZunoStateEvent): ApplyResult;
39
+
40
+ type IncomingHeaders = IncomingMessage["headers"];
41
+ /**
42
+ * Creates a Server-Sent Events (SSE) connection for Zuno state updates.
43
+ */
44
+ declare const createSSEConnection: (req: IncomingMessage, res: ServerResponse, headers: IncomingHeaders) => void;
45
+ /**
46
+ * Synchronizes the Zuno universe state by applying an incoming event.
47
+ */
48
+ declare const syncUniverseState: (req: IncomingMessage, res: ServerResponse) => void;
49
+ declare const setUniverseState: (req: IncomingMessage, res: ServerResponse) => void;
50
+
51
+ /**
52
+ * Sends a snapshot of the current universe state to the response.
53
+ * Compatible with both Express and raw Node.js http.
54
+ */
55
+ declare function sendSnapshot(_req: IncomingMessage, res: ServerResponse): void;
56
+
57
+ export { type ApplyResult, type UniverseRecord, type ZunoStateListener, appendEvent, applyStateEvent, createSSEConnection, getEventsAfter, getLastEventId, getUniverseRecord, getUniverseState, publishToStateEvent, sendSnapshot, setUniverseState, subscribeToStateEvents, syncUniverseState, updateUniverseState };
@@ -1,4 +1,57 @@
1
- export * from "./snapshot-handler";
2
- export { createSSEConnection, setUniverseState } from "./sse-handler";
3
- export * from "./apply-state-event";
4
- //# sourceMappingURL=index.d.ts.map
1
+ import { f as ZunoStateEvent } from '../index-IbvF6TBr.js';
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+
4
+ type UniverseRecord = {
5
+ state: any;
6
+ version: number;
7
+ };
8
+ type ZunoStateListener = (event: ZunoStateEvent) => void;
9
+ declare const getUniverseRecord: (storeKey: string) => UniverseRecord | undefined;
10
+ declare const updateUniverseState: (event: ZunoStateEvent) => void;
11
+ declare const getUniverseState: () => {
12
+ [k: string]: UniverseRecord;
13
+ };
14
+ declare const appendEvent: (event: ZunoStateEvent) => ZunoStateEvent;
15
+ declare const getEventsAfter: (lastEventId: number) => ZunoStateEvent[];
16
+ declare const getLastEventId: () => number;
17
+ declare const subscribeToStateEvents: (listener: ZunoStateListener) => () => void;
18
+ declare const publishToStateEvent: (event: ZunoStateEvent) => void;
19
+
20
+ type ApplyResult = {
21
+ ok: true;
22
+ event: ZunoStateEvent;
23
+ } | {
24
+ ok: false;
25
+ reason: "VERSION_CONFLICT";
26
+ current: {
27
+ state: any;
28
+ version: number;
29
+ };
30
+ } | {
31
+ ok: false;
32
+ reason: string;
33
+ current?: never;
34
+ };
35
+ /**
36
+ * Validates and applies a state event to the server universe.
37
+ */
38
+ declare function applyStateEvent(incoming: ZunoStateEvent): ApplyResult;
39
+
40
+ type IncomingHeaders = IncomingMessage["headers"];
41
+ /**
42
+ * Creates a Server-Sent Events (SSE) connection for Zuno state updates.
43
+ */
44
+ declare const createSSEConnection: (req: IncomingMessage, res: ServerResponse, headers: IncomingHeaders) => void;
45
+ /**
46
+ * Synchronizes the Zuno universe state by applying an incoming event.
47
+ */
48
+ declare const syncUniverseState: (req: IncomingMessage, res: ServerResponse) => void;
49
+ declare const setUniverseState: (req: IncomingMessage, res: ServerResponse) => void;
50
+
51
+ /**
52
+ * Sends a snapshot of the current universe state to the response.
53
+ * Compatible with both Express and raw Node.js http.
54
+ */
55
+ declare function sendSnapshot(_req: IncomingMessage, res: ServerResponse): void;
56
+
57
+ export { type ApplyResult, type UniverseRecord, type ZunoStateListener, appendEvent, applyStateEvent, createSSEConnection, getEventsAfter, getLastEventId, getUniverseRecord, getUniverseState, publishToStateEvent, sendSnapshot, setUniverseState, subscribeToStateEvents, syncUniverseState, updateUniverseState };
@@ -1,3 +1,17 @@
1
- export * from "./snapshot-handler";
2
- export { createSSEConnection, setUniverseState } from "./sse-handler";
3
- export * from "./apply-state-event";
1
+ var p=new Map,f=t=>p.get(t),d=t=>{let e=p.get(t.storeKey)??{version:0},o=typeof t.version=="number"?t.version:e.version+1;p.set(t.storeKey,{state:t.state,version:o});},c=()=>Object.fromEntries(p),h=1e3,x=1,a=[],S=t=>(t.eventId=x++,a.push(t),a.length>h&&a.shift(),t),y=t=>a.filter(e=>(e?.eventId??0)>t),g=()=>a[a.length-1]?.eventId??0,v=new Set,l=t=>(v.add(t),()=>{v.delete(t);}),m=t=>{v.forEach(e=>e(t));};function E(t){let e=f(t.storeKey)??{state:void 0,version:0};if(typeof t.baseVersion=="number"&&t.baseVersion!==e.version)return {ok:false,reason:"VERSION_CONFLICT",current:e};let o=e.version+1,n={...t,version:o};return d(n),S(n),m(n),{ok:true,event:n}}var A=(t,e,o)=>{e.writeHead(200,{"Cache-Control":"no-cache, no-transform","Content-Type":"text/event-stream; charset=utf-8",Connection:"keep-alive","X-Accel-Buffering":"no",...o}),e.flushHeaders?.();let n=t.headers["last-event-id"]||new URL(t.url||"","http://localhost").searchParams.get("lastEventId"),r=Number.parseInt(Array.isArray(n)?n[0]:n??"0",10)||0;if(r>0){let i=y(r);for(let u of i)e.write(`id: ${u.eventId}
2
+ `),e.write(`event: state
3
+ `),e.write(`data: ${JSON.stringify(u)}
4
+
5
+ `);}else e.write(`event: snapshot
6
+ `),e.write(`data: ${JSON.stringify(c())}
7
+
8
+ `);let s=l(i=>{e.write(`id: ${i.eventId}
9
+ `),e.write(`event: state
10
+ `),e.write(`data: ${JSON.stringify(i)}
11
+
12
+ `);}),I=setInterval(()=>{e.write(`: ping ${Date.now()}
13
+
14
+ `);},15e3);e.write(`: connected
15
+
16
+ `),t.on("close",()=>{clearInterval(I),s(),e.end();});},O=(t,e)=>{let n="";t.on("data",r=>{n+=r.toString("utf8"),n.length>524288&&(e.writeHead(413,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:false,reason:"PAYLOAD_TOO_LARGE"})),t.destroy());}),t.on("end",()=>{try{let r=JSON.parse(n||"{}"),s=E(r);if(!s.ok){s.reason==="VERSION_CONFLICT"&&(e.writeHead(409,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:!1,reason:"VERSION_CONFLICT",current:s.current})));return}e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:!0,event:s.event}));}catch{e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:false,reason:"INVALID_JSON"}));}});},L=(t,e)=>O(t,e);function k(t,e){let o={state:c(),lastEventId:g()};"json"in e&&typeof e.json=="function"?e.json(o):(e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(o)));}export{S as appendEvent,E as applyStateEvent,A as createSSEConnection,y as getEventsAfter,g as getLastEventId,f as getUniverseRecord,c as getUniverseState,m as publishToStateEvent,k as sendSnapshot,L as setUniverseState,l as subscribeToStateEvents,O as syncUniverseState,d as updateUniverseState};//# sourceMappingURL=index.js.map
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server/core.ts","../../src/server/apply-state-event.ts","../../src/server/sse-handler.ts","../../src/server/snapshot-handler.ts"],"names":["universeState","getUniverseRecord","storeKey","updateUniverseState","event","current","nextVersion","getUniverseState","MAX_EVENTS","nextEventId","eventLog","appendEvent","getEventsAfter","lastEventId","getLastEventId","listeners","subscribeToStateEvents","listener","publishToStateEvent","applyStateEvent","incoming","createSSEConnection","req","res","headers","raw","missed","unsubscribe","heartbeat","syncUniverseState","body","chunk","result","setUniverseState","sendSnapshot","_req","snapshot"],"mappings":"AAaA,IAAMA,CAAAA,CAAgB,IAAI,GAAA,CAEbC,CAAAA,CAAqBC,CAAAA,EACzBF,CAAAA,CAAc,GAAA,CAAIE,CAAQ,CAAA,CAGtBC,CAAAA,CAAuBC,CAAAA,EAA0B,CAC5D,IAAMC,CAAAA,CAAUL,CAAAA,CAAc,GAAA,CAAII,CAAAA,CAAM,QAAQ,CAAA,EAAK,CAAoB,OAAA,CAAS,CAAE,CAAA,CAC9EE,CAAAA,CAAc,OAAOF,CAAAA,CAAM,SAAY,QAAA,CAAWA,CAAAA,CAAM,OAAA,CAAUC,CAAAA,CAAQ,OAAA,CAAU,CAAA,CAC1FL,CAAAA,CAAc,GAAA,CAAII,CAAAA,CAAM,QAAA,CAAU,CAAE,KAAA,CAAOA,CAAAA,CAAM,KAAA,CAAO,OAAA,CAASE,CAAY,CAAC,EAChF,CAAA,CAEaC,CAAAA,CAAmB,IACvB,MAAA,CAAO,WAAA,CAAYP,CAAa,CAAA,CAKnCQ,CAAAA,CAAa,GAAA,CACfC,CAAAA,CAAc,CAAA,CACZC,CAAAA,CAA6B,EAAC,CAEvBC,EAAeP,CAAAA,GAC1BA,CAAAA,CAAM,OAAA,CAAUK,CAAAA,EAAAA,CAChBC,CAAAA,CAAS,IAAA,CAAKN,CAAK,CAAA,CACfM,CAAAA,CAAS,MAAA,CAASF,CAAAA,EACpBE,CAAAA,CAAS,KAAA,EAAM,CAEVN,CAAAA,CAAAA,CAGIQ,CAAAA,CAAkBC,CAAAA,EACtBH,CAAAA,CAAS,MAAA,CAAQN,CAAAA,EAAAA,CAAWA,CAAAA,EAAO,OAAA,EAAW,CAAA,EAAKS,CAAW,CAAA,CAG1DC,CAAAA,CAAiB,IACrBJ,CAAAA,CAASA,CAAAA,CAAS,MAAA,CAAS,CAAC,CAAA,EAAG,SAAW,CAAA,CAK7CK,CAAAA,CAAY,IAAI,GAAA,CAETC,CAAAA,CAA0BC,CAAAA,GACrCF,CAAAA,CAAU,GAAA,CAAIE,CAAQ,CAAA,CACf,IAAM,CACXF,CAAAA,CAAU,MAAA,CAAOE,CAAQ,EAC3B,CAAA,CAAA,CAGWC,CAAAA,CAAuBd,CAAAA,EAA0B,CAC5DW,CAAAA,CAAU,OAAA,CAASE,CAAAA,EAAaA,CAAAA,CAASb,CAAK,CAAC,EACjD,ECtDO,SAASe,CAAAA,CAAgBC,CAAAA,CAAuC,CACrE,IAAMf,CAAAA,CAAUJ,CAAAA,CAAkBmB,CAAAA,CAAS,QAAQ,CAAA,EAAK,CAAE,KAAA,CAAO,MAAA,CAAW,OAAA,CAAS,CAAE,CAAA,CAGvF,GAAI,OAAOA,CAAAA,CAAS,WAAA,EAAgB,QAAA,EAAYA,CAAAA,CAAS,WAAA,GAAgBf,CAAAA,CAAQ,OAAA,CAC/E,OAAO,CAAE,EAAA,CAAI,KAAA,CAAO,MAAA,CAAQ,kBAAA,CAAoB,OAAA,CAAAA,CAAQ,CAAA,CAI1D,IAAMC,CAAAA,CAAcD,CAAAA,CAAQ,QAAU,CAAA,CAChCD,CAAAA,CAAQ,CAAE,GAAGgB,CAAAA,CAAU,OAAA,CAASd,CAAY,CAAA,CAGlD,OAAAH,CAAAA,CAAoBC,CAAK,CAAA,CACzBO,CAAAA,CAAYP,CAAK,CAAA,CAGjBc,CAAAA,CAAoBd,CAAK,CAAA,CAElB,CAAE,EAAA,CAAI,IAAA,CAAM,KAAA,CAAAA,CAAM,CAC3B,CCnBO,IAAMiB,CAAAA,CAAsB,CAACC,CAAAA,CAAsBC,CAAAA,CAAqBC,CAAAA,GAA6B,CAC1GD,EAAI,SAAA,CAAU,GAAA,CAAK,CACjB,eAAA,CAAiB,wBAAA,CACjB,cAAA,CAAgB,kCAAA,CAChB,UAAA,CAAY,YAAA,CACZ,mBAAA,CAAqB,IAAA,CACrB,GAAGC,CACL,CAAC,CAAA,CAEDD,CAAAA,CAAI,YAAA,IAAe,CAEnB,IAAME,CAAAA,CAAMH,CAAAA,CAAI,OAAA,CAAQ,eAAe,CAAA,EAAK,IAAI,GAAA,CAAIA,CAAAA,CAAI,GAAA,EAAO,EAAA,CAAI,kBAAkB,CAAA,CAAE,YAAA,CAAa,IAAI,aAAa,CAAA,CAC/GT,CAAAA,CAAc,MAAA,CAAO,QAAA,CAAS,KAAA,CAAM,OAAA,CAAQY,CAAG,CAAA,CAAIA,CAAAA,CAAI,CAAC,CAAA,CAAKA,CAAAA,EAAO,GAAA,CAAM,EAAE,CAAA,EAAK,CAAA,CAEvF,GAAIZ,CAAAA,CAAc,CAAA,CAAG,CACnB,IAAMa,CAAAA,CAASd,CAAAA,CAAeC,CAAW,CAAA,CACzC,IAAA,IAAWT,CAAAA,IAASsB,CAAAA,CAClBH,CAAAA,CAAI,KAAA,CAAM,CAAA,IAAA,EAAOnB,EAAM,OAAO;AAAA,CAAI,CAAA,CAClCmB,EAAI,KAAA,CAAM,CAAA;AAAA,CAAgB,EAC1BA,CAAAA,CAAI,KAAA,CAAM,SAAS,IAAA,CAAK,SAAA,CAAUnB,CAAK,CAAC;;AAAA,CAAM,EAElD,CAAA,KACEmB,CAAAA,CAAI,KAAA,CAAM,CAAA;AAAA,CAAmB,CAAA,CAC7BA,EAAI,KAAA,CAAM,CAAA,MAAA,EAAS,KAAK,SAAA,CAAUhB,CAAAA,EAAkB,CAAC;;AAAA,CAAM,CAAA,CAG7D,IAAMoB,CAAAA,CAAcX,CAAAA,CAAwBZ,CAAAA,EAA0B,CACpEmB,CAAAA,CAAI,KAAA,CAAM,CAAA,IAAA,EAAOnB,CAAAA,CAAM,OAAO;AAAA,CAAI,CAAA,CAClCmB,EAAI,KAAA,CAAM,CAAA;AAAA,CAAgB,EAC1BA,CAAAA,CAAI,KAAA,CAAM,SAAS,IAAA,CAAK,SAAA,CAAUnB,CAAK,CAAC;;AAAA,CAAM,EAChD,CAAC,CAAA,CAEKwB,CAAAA,CAAY,WAAA,CAAY,IAAM,CAClCL,CAAAA,CAAI,KAAA,CAAM,CAAA,OAAA,EAAU,IAAA,CAAK,GAAA,EAAK;;AAAA,CAAM,EACtC,CAAA,CAAG,IAAK,CAAA,CAERA,EAAI,KAAA,CAAM,CAAA;;AAAA,CAAkB,CAAA,CAE5BD,EAAI,EAAA,CAAG,OAAA,CAAS,IAAM,CACpB,aAAA,CAAcM,CAAS,CAAA,CACvBD,CAAAA,EAAY,CACZJ,EAAI,GAAA,GACN,CAAC,EACH,CAAA,CAKaM,EAAoB,CAACP,CAAAA,CAAsBC,CAAAA,GAAwB,CAE9E,IAAIO,CAAAA,CAAO,GAEXR,CAAAA,CAAI,EAAA,CAAG,OAASS,CAAAA,EAAkB,CAChCD,GAAQC,CAAAA,CAAM,QAAA,CAAS,MAAM,CAAA,CACzBD,CAAAA,CAAK,MAAA,CAAS,SAChBP,CAAAA,CAAI,SAAA,CAAU,GAAA,CAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,CAAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,CAAE,GAAI,KAAA,CAAO,MAAA,CAAQ,mBAAoB,CAAC,CAAC,EAClED,CAAAA,CAAI,OAAA,EAAQ,EAEhB,CAAC,CAAA,CAEDA,CAAAA,CAAI,GAAG,KAAA,CAAO,IAAM,CAClB,GAAI,CACF,IAAMF,CAAAA,CAA2B,IAAA,CAAK,KAAA,CAAMU,CAAAA,EAAQ,IAAI,CAAA,CAClDE,EAASb,CAAAA,CAAgBC,CAAQ,EAEvC,GAAI,CAACY,EAAO,EAAA,CAAI,CACVA,CAAAA,CAAO,MAAA,GAAW,kBAAA,GACpBT,CAAAA,CAAI,UAAU,GAAA,CAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,EAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,CAAE,EAAA,CAAI,CAAA,CAAA,CAAO,OAAQ,kBAAA,CAAoB,OAAA,CAASS,EAAO,OAAQ,CAAC,CAAC,CAAA,CAAA,CAE5F,MACF,CAEAT,CAAAA,CAAI,SAAA,CAAU,GAAA,CAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,CAAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,CAAE,EAAA,CAAI,CAAA,CAAA,CAAM,KAAA,CAAOS,EAAO,KAAM,CAAC,CAAC,EAC3D,CAAA,KAAQ,CACNT,CAAAA,CAAI,SAAA,CAAU,GAAA,CAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,CAAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,CAAE,GAAI,KAAA,CAAO,MAAA,CAAQ,cAAe,CAAC,CAAC,EAC/D,CACF,CAAC,EACH,EAEaU,CAAAA,CAAmB,CAACX,EAAsBC,CAAAA,GAC9CM,CAAAA,CAAkBP,CAAAA,CAAKC,CAAG,ECzF5B,SAASW,EAAaC,CAAAA,CAAuBZ,CAAAA,CAAqB,CACvE,IAAMa,CAAAA,CAAW,CACf,KAAA,CAAO7B,CAAAA,EAAiB,CACxB,WAAA,CAAaO,CAAAA,EACf,EAGI,MAAA,GAAUS,CAAAA,EAAO,OAAQA,CAAAA,CAAY,IAAA,EAAS,WAC/CA,CAAAA,CAAY,IAAA,CAAKa,CAAQ,CAAA,EAE1Bb,CAAAA,CAAI,SAAA,CAAU,IAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,CAAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAUa,CAAQ,CAAC,CAAA,EAEpC","file":"index.js","sourcesContent":["import type { ZunoStateEvent } from \"../sync\";\n\n// --- Types ---\n\nexport type UniverseRecord = {\n state: any;\n version: number;\n};\n\nexport type ZunoStateListener = (event: ZunoStateEvent) => void;\n\n// --- State Store ---\n\nconst universeState = new Map<string, UniverseRecord>();\n\nexport const getUniverseRecord = (storeKey: string): UniverseRecord | undefined => {\n return universeState.get(storeKey);\n};\n\nexport const updateUniverseState = (event: ZunoStateEvent) => {\n const current = universeState.get(event.storeKey) ?? { state: undefined, version: 0 };\n const nextVersion = typeof event.version === \"number\" ? event.version : current.version + 1;\n universeState.set(event.storeKey, { state: event.state, version: nextVersion });\n};\n\nexport const getUniverseState = () => {\n return Object.fromEntries(universeState);\n};\n\n// --- Event Log ---\n\nconst MAX_EVENTS = 1000;\nlet nextEventId = 1;\nconst eventLog: ZunoStateEvent[] = [];\n\nexport const appendEvent = (event: ZunoStateEvent) => {\n event.eventId = nextEventId++;\n eventLog.push(event);\n if (eventLog.length > MAX_EVENTS) {\n eventLog.shift();\n }\n return event;\n};\n\nexport const getEventsAfter = (lastEventId: number) => {\n return eventLog.filter((event) => (event?.eventId ?? 0) > lastEventId);\n};\n\nexport const getLastEventId = () => {\n return eventLog[eventLog.length - 1]?.eventId ?? 0;\n};\n\n// --- State Bus (Events) ---\n\nconst listeners = new Set<ZunoStateListener>();\n\nexport const subscribeToStateEvents = (listener: ZunoStateListener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\nexport const publishToStateEvent = (event: ZunoStateEvent) => {\n listeners.forEach((listener) => listener(event));\n};\n","import { getUniverseRecord, updateUniverseState, publishToStateEvent, appendEvent } from \"./core\";\nimport type { ZunoStateEvent } from \"../sync\";\n\nexport type ApplyResult = \n | { ok: true; event: ZunoStateEvent }\n | { ok: false; reason: \"VERSION_CONFLICT\"; current: { state: any; version: number } }\n | { ok: false; reason: string; current?: never };\n\n/**\n * Validates and applies a state event to the server universe.\n */\nexport function applyStateEvent(incoming: ZunoStateEvent): ApplyResult {\n const current = getUniverseRecord(incoming.storeKey) ?? { state: undefined, version: 0 };\n\n // Strict version check\n if (typeof incoming.baseVersion === \"number\" && incoming.baseVersion !== current.version) {\n return { ok: false, reason: \"VERSION_CONFLICT\", current };\n }\n\n // Increment version\n const nextVersion = current.version + 1;\n const event = { ...incoming, version: nextVersion };\n\n // Persistence\n updateUniverseState(event);\n appendEvent(event);\n\n // Notify SSE subscribers\n publishToStateEvent(event);\n\n return { ok: true, event };\n}\n","import { subscribeToStateEvents } from \"./core\";\nimport { getUniverseState } from \"./core\";\nimport { getEventsAfter } from \"./core\";\nimport type { ZunoStateEvent } from \"../sync\";\nimport type { IncomingMessage, ServerResponse } from \"http\";\nimport { applyStateEvent } from \"./apply-state-event\";\n\ntype IncomingHeaders = IncomingMessage[\"headers\"];\n\n/**\n * Creates a Server-Sent Events (SSE) connection for Zuno state updates.\n */\nexport const createSSEConnection = (req: IncomingMessage, res: ServerResponse, headers: IncomingHeaders) => {\n res.writeHead(200, {\n \"Cache-Control\": \"no-cache, no-transform\",\n \"Content-Type\": \"text/event-stream; charset=utf-8\",\n Connection: \"keep-alive\",\n \"X-Accel-Buffering\": \"no\",\n ...headers\n });\n\n res.flushHeaders?.();\n\n const raw = req.headers[\"last-event-id\"] || new URL(req.url || \"\", \"http://localhost\").searchParams.get(\"lastEventId\");\n const lastEventId = Number.parseInt(Array.isArray(raw) ? raw[0] : (raw ?? \"0\"), 10) || 0;\n\n if (lastEventId > 0) {\n const missed = getEventsAfter(lastEventId);\n for (const event of missed) {\n res.write(`id: ${event.eventId}\\n`);\n res.write(`event: state\\n`);\n res.write(`data: ${JSON.stringify(event)}\\n\\n`);\n }\n } else {\n res.write(`event: snapshot\\n`);\n res.write(`data: ${JSON.stringify(getUniverseState())}\\n\\n`);\n }\n\n const unsubscribe = subscribeToStateEvents((event: ZunoStateEvent) => {\n res.write(`id: ${event.eventId}\\n`);\n res.write(`event: state\\n`);\n res.write(`data: ${JSON.stringify(event)}\\n\\n`);\n });\n\n const heartbeat = setInterval(() => {\n res.write(`: ping ${Date.now()}\\n\\n`);\n }, 15000);\n\n res.write(\": connected \\n\\n\");\n\n req.on(\"close\", () => {\n clearInterval(heartbeat);\n unsubscribe();\n res.end();\n });\n};\n\n/**\n * Synchronizes the Zuno universe state by applying an incoming event.\n */\nexport const syncUniverseState = (req: IncomingMessage, res: ServerResponse) => {\n const MAX_BODY_BYTES = 512 * 1024; // 512KB safety\n let body = \"\";\n\n req.on(\"data\", (chunk: Buffer) => {\n body += chunk.toString(\"utf8\");\n if (body.length > MAX_BODY_BYTES) {\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, reason: \"PAYLOAD_TOO_LARGE\" }));\n req.destroy();\n }\n });\n\n req.on(\"end\", () => {\n try {\n const incoming: ZunoStateEvent = JSON.parse(body || \"{}\") as any;\n const result = applyStateEvent(incoming);\n\n if (!result.ok) {\n if (result.reason === \"VERSION_CONFLICT\") {\n res.writeHead(409, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, reason: \"VERSION_CONFLICT\", current: result.current }));\n }\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, event: result.event }));\n } catch {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, reason: \"INVALID_JSON\" }));\n }\n });\n};\n\nexport const setUniverseState = (req: IncomingMessage, res: ServerResponse) => {\n return syncUniverseState(req, res);\n};\n","import type { IncomingMessage, ServerResponse } from \"http\";\nimport { getUniverseState, getLastEventId } from \"./core\";\n\n/**\n * Sends a snapshot of the current universe state to the response.\n * Compatible with both Express and raw Node.js http.\n */\nexport function sendSnapshot(_req: IncomingMessage, res: ServerResponse) {\n const snapshot = {\n state: getUniverseState(),\n lastEventId: getLastEventId(),\n };\n\n // Check for Express-like .json() method\n if (\"json\" in res && typeof (res as any).json === \"function\") {\n (res as any).json(snapshot);\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(snapshot));\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iadev93/zuno",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "author": "Ibrahim Aftab",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,9 +21,6 @@
21
21
  "default": "./dist/server/index.js"
22
22
  }
23
23
  },
24
- "scripts": {
25
- "build": "tsc -p tsconfig.json"
26
- },
27
24
  "keywords": [
28
25
  "state",
29
26
  "state-management",
@@ -40,5 +37,12 @@
40
37
  "repository": {
41
38
  "type": "git",
42
39
  "url": "git+https://github.com/IADev-Channel/zuno.git"
40
+ },
41
+ "devDependencies": {
42
+ "tsup": "^8.5.1"
43
+ },
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "dev": "tsup --watch"
43
47
  }
44
- }
48
+ }
@@ -1,77 +0,0 @@
1
- import type { ZunoStateEvent } from "../sync/sync-types";
2
- import type { Universe, ZunoSnapshot } from "./types";
3
- /** Store */
4
- type ZunoStore<T> = {
5
- get(): T;
6
- set(next: T): void;
7
- subscribe(cb: (state: T) => void): () => void;
8
- };
9
- export type CreateZunoOptions = {
10
- /** Universe */
11
- universe?: Universe;
12
- /** Optional transports */
13
- channelName?: string;
14
- /** SSE */
15
- sseUrl?: string;
16
- /** Sync */
17
- syncUrl?: string;
18
- /** Behavior */
19
- optimistic?: boolean;
20
- /** Client ID */
21
- clientId?: string;
22
- };
23
- /**
24
- * Creates a Zuno instance, which provides a state management system with optional synchronization
25
- * capabilities via Server-Sent Events (SSE) and BroadcastChannel.
26
- *
27
- * @param opts - Configuration options for the Zuno instance.
28
- * @param opts.universe - An optional pre-existing ZunoUniverse instance. If not provided, a new one will be created.
29
- * @param opts.channelName - An optional name for the BroadcastChannel to enable local tab synchronization.
30
- * @param opts.sseUrl - The URL for the Server-Sent Events endpoint to receive state updates from a server.
31
- * @param opts.syncUrl - The URL for the synchronization endpoint to send state updates to a server. Required if `sseUrl` is provided.
32
- * @param opts.optimistic - A boolean indicating whether state updates should be applied optimistically before server confirmation. Defaults to `true`.
33
- * @param opts.clientId - A unique identifier for the client. If not provided, a random UUID will be generated.
34
- * @returns An object containing methods to interact with the Zuno instance, including `getStore`, `destroy`, and `broadcast`.
35
- */
36
- export declare const createZuno: (opts?: CreateZunoOptions) => {
37
- /** Universe */
38
- universe: Universe;
39
- /** Client ID */
40
- clientId: string;
41
- /** Get store */
42
- getStore: <T>(storeKey: string, init: () => T) => import("./types").Store<T>;
43
- /** Create store */
44
- store: <T>(storeKey: string, init: () => T) => {
45
- key: string;
46
- get: () => T;
47
- set: (next: T | ((prev: T) => T)) => Promise<any>;
48
- subscribe: (cb: (state: T) => void) => () => void;
49
- raw: () => ZunoStore<T>;
50
- };
51
- /** Get state */
52
- get: <T>(storeKey: string, init?: () => T) => T;
53
- /** Set state */
54
- set: <T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T) => Promise<{
55
- ok: boolean;
56
- status: number;
57
- json: any;
58
- }>;
59
- /** Subscribe to store */
60
- subscribe: <T>(storeKey: string, init: () => T, cb: (state: T) => void) => () => boolean;
61
- /** Dispatch event */
62
- dispatch: (event: ZunoStateEvent) => Promise<{
63
- ok: boolean;
64
- status: number;
65
- json: any;
66
- }>;
67
- /** Stop */
68
- stop: () => void;
69
- /** Hydrate snapshot */
70
- hydrateSnapshot: (snapshot: ZunoSnapshot) => void;
71
- /** Get last event ID */
72
- getLastEventId: () => number;
73
- /** Set last event ID */
74
- setLastEventId: (id: number) => void;
75
- };
76
- export {};
77
- //# sourceMappingURL=createZuno.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createZuno.d.ts","sourceRoot":"","sources":["../../src/core/createZuno.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEtD,YAAY;AACZ,KAAK,SAAS,CAAC,CAAC,IAAI;IAClB,GAAG,IAAI,CAAC,CAAC;IACT,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,UAAU;IACV,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,WAAW;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,eAAe;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,GAAI,OAAM,iBAAsB;IAmRnD,eAAe;;IAEf,gBAAgB;;IAIhB,gBAAgB;eAlIA,CAAC,YAAa,MAAM,QAAQ,MAAM,CAAC;IAoInD,mBAAmB;YArBN,CAAC,YAAa,MAAM,QAAQ,MAAM,CAAC;aAb3C,MAAM;;6CAE0B,OAAO,CAAC,GAAG,CAAC;sCACnB,IAAI,KAAK,MAAM,IAAI;;;IAiCjD,gBAAgB;UA7HL,CAAC,YAAa,MAAM,SAAS,MAAM,CAAC,KAAG,CAAC;IA+HnD,gBAAgB;UAhFC,CAAC,YACR,MAAM,QACV,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,SACnB,MAAM,CAAC;;;;;IA+Ed,yBAAyB;gBA1DR,CAAC,YACR,MAAM,QACV,MAAM,CAAC,MACT,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI;IA2DtB,qBAAqB;sBA7HQ,cAAc;;;;;IA+H3C,WAAW;;IAGX,uBAAuB;gCAhRU,YAAY;IAkR7C,wBAAwB;;IAExB,wBAAwB;yBA3PE,MAAM;CA8PnC,CAAC"}
@@ -1,250 +0,0 @@
1
- import { createUniverse } from "./universe";
2
- import { startSSE } from "../sync/sse-client";
3
- import { startBroadcastChannel } from "../sync/broadcast-channel";
4
- import { applyIncomingEvent } from "../sync/apply-incoming-event";
5
- /**
6
- * Creates a Zuno instance, which provides a state management system with optional synchronization
7
- * capabilities via Server-Sent Events (SSE) and BroadcastChannel.
8
- *
9
- * @param opts - Configuration options for the Zuno instance.
10
- * @param opts.universe - An optional pre-existing ZunoUniverse instance. If not provided, a new one will be created.
11
- * @param opts.channelName - An optional name for the BroadcastChannel to enable local tab synchronization.
12
- * @param opts.sseUrl - The URL for the Server-Sent Events endpoint to receive state updates from a server.
13
- * @param opts.syncUrl - The URL for the synchronization endpoint to send state updates to a server. Required if `sseUrl` is provided.
14
- * @param opts.optimistic - A boolean indicating whether state updates should be applied optimistically before server confirmation. Defaults to `true`.
15
- * @param opts.clientId - A unique identifier for the client. If not provided, a random UUID will be generated.
16
- * @returns An object containing methods to interact with the Zuno instance, including `getStore`, `destroy`, and `broadcast`.
17
- */
18
- export const createZuno = (opts = {}) => {
19
- /** Local state */
20
- const localState = new Map();
21
- /** Local per-store versions (for BC / local ordering) */
22
- const versions = new Map();
23
- /** Universe */
24
- const universe = (opts.universe ?? (createUniverse()));
25
- /** Unique client ID */
26
- const clientId = opts.clientId ?? (globalThis.crypto?.randomUUID?.() ?? String(Math.random()));
27
- /** SSE ready */
28
- let sseReady = false;
29
- /** Last event ID */
30
- let lastEventId = 0;
31
- /**
32
- * Hydrate snapshot
33
- * @param snapshot - The snapshot to hydrate.
34
- */
35
- function hydrateSnapshot(snapshot) {
36
- const plain = {};
37
- for (const [k, rec] of Object.entries(snapshot.state)) {
38
- plain[k] = rec.state;
39
- versions.set(k, rec.version);
40
- }
41
- universe.restore(plain);
42
- lastEventId = snapshot.lastEventId;
43
- }
44
- /**
45
- * Get store base version
46
- * @param storeKey - The key of the store to get the base version for.
47
- */
48
- function getStoreBaseVersion(storeKey) { return versions.get(storeKey) ?? 0; }
49
- /**
50
- * Get last event ID
51
- */
52
- function getLastEventId() { return lastEventId; }
53
- /**
54
- * Set last event ID
55
- * @param id - The new last event ID.
56
- */
57
- function setLastEventId(id) { lastEventId = id; }
58
- /** SSE Prefer server sync if provided */
59
- const sse = opts.sseUrl && opts.syncUrl
60
- ? startSSE({
61
- universe,
62
- url: opts.sseUrl,
63
- syncUrl: opts.syncUrl,
64
- optimistic: opts.optimistic ?? true,
65
- clientId,
66
- versions,
67
- getLastEventId: () => lastEventId,
68
- onOpen: () => {
69
- sseReady = true;
70
- },
71
- onClose: () => {
72
- sseReady = false;
73
- },
74
- })
75
- : null;
76
- /** Apply event to target */
77
- const apply = (event) => {
78
- /** Update last event ID */
79
- if (typeof event.eventId === "number")
80
- lastEventId = Math.max(lastEventId, event.eventId);
81
- applyIncomingEvent(universe, event, { clientId, localState, versions });
82
- };
83
- /** Broadcast Channel for local tab sync */
84
- const bc = opts.channelName
85
- ? startBroadcastChannel({
86
- /** Channel name for BroadcastChannel */
87
- channelName: opts.channelName,
88
- /** Unique client ID */
89
- clientId,
90
- /** Apply event to target */
91
- onEvent: (ev) => {
92
- apply(ev);
93
- },
94
- /** Get snapshot of local state */
95
- getSnapshot: () => {
96
- /** Snapshot */
97
- const snap = universe.snapshot();
98
- /** Snapshot */
99
- const out = {};
100
- /** Iterate local state */
101
- for (const [storeKey, state] of Object.entries(snap)) {
102
- /** Add to snapshot */
103
- out[storeKey] = {
104
- state,
105
- version: versions.get(storeKey) ?? 0,
106
- };
107
- }
108
- return out;
109
- },
110
- /** Apply snapshot to target */
111
- onSnapshot: (snap) => {
112
- /** Iterate snapshot with store key and record */
113
- for (const [storeKey, rec] of Object.entries(snap)) {
114
- /** Record */
115
- const record = rec;
116
- /** Get the universe store state or the store state */
117
- const state = record?.state ?? record;
118
- /** Get the universe store version or the store version */
119
- const version = typeof record?.version === "number" ? record.version : 0;
120
- /** Set the latest version */
121
- // versions.set(storeKey, Math.max(versions.get(storeKey) ?? 0, version));
122
- /** Apply the event */
123
- apply({ storeKey, state, version });
124
- }
125
- },
126
- })
127
- : null;
128
- /** Immediately ask other tabs for snapshot (BC-first) */
129
- setTimeout(() => bc?.hello(), 0);
130
- /** Store factory
131
- * @param storeKey - The key of the store to get.
132
- * @param init - The initialization function for the store.
133
- * @returns The store.
134
- */
135
- const getStore = (storeKey, init) => {
136
- return universe.getStore(storeKey, init);
137
- };
138
- /** Get store by store key
139
- * @param storeKey - The key of the store to get.
140
- * @param init - The initialization function for the store.
141
- * @returns The state of the store.
142
- */
143
- const get = (storeKey, init) => {
144
- return universe.getStore(storeKey, init ?? (() => undefined)).get();
145
- };
146
- /** Dispatch event to universe
147
- * @param event - The event to dispatch.
148
- * @returns A promise that resolves to the result of the dispatch.
149
- */
150
- const dispatch = async (event) => {
151
- /** Check if SSE is enabled */
152
- if (sse && sseReady) {
153
- /** Payload with origin */
154
- const payload = { ...event, origin: clientId, baseVersion: getStoreBaseVersion(event.storeKey) };
155
- /** Dispatch to SSE */
156
- return await sse.dispatch(payload);
157
- }
158
- /** Current version */
159
- const current = versions.get(event.storeKey) ?? 0;
160
- /** Next version */
161
- const nextVersion = current + 1;
162
- /** Apply event with next version */
163
- apply({ ...event, version: nextVersion });
164
- /** Set version */
165
- versions.set(event.storeKey, nextVersion);
166
- /** Check if BroadcastChannel is enabled */
167
- if (bc) {
168
- /** Publish event */
169
- bc.publish({ ...event, version: nextVersion, origin: clientId });
170
- }
171
- /** Return success */
172
- return { ok: true, status: 200, json: null };
173
- };
174
- /** Set store state
175
- * @param storeKey - The key of the store to set.
176
- * @param next - The new state to set.
177
- * @param init - The initialization function for the store.
178
- * @returns A promise that resolves to the result of the dispatch.
179
- */
180
- const set = async (storeKey, next, init) => {
181
- /** Get store */
182
- const store = universe.getStore(storeKey, init ?? (() => undefined));
183
- /** Get previous state */
184
- const prev = store.get();
185
- /** Get next state */
186
- const state = typeof next === "function" ? next(prev) : next;
187
- /** Dispatch event */
188
- return dispatch({ storeKey, state });
189
- };
190
- /** Subscribe to store
191
- * @param storeKey - The key of the store to subscribe to.
192
- * @param init - The initialization function for the store.
193
- * @param cb - The callback function to be called when the store state changes.
194
- * @returns A function to unsubscribe from the store.
195
- */
196
- const subscribe = (storeKey, init, cb) => {
197
- /** Get store */
198
- const store = universe.getStore(storeKey, init);
199
- return store.subscribe(cb);
200
- };
201
- /** Stop cleanup */
202
- const stop = () => {
203
- sse?.unsubscribe?.();
204
- bc?.stop?.();
205
- };
206
- /**
207
- * Creates a bound store for a specific key.
208
- * @param storeKey The key of the store to create.
209
- * @param init The initialization function for the store.
210
- * @returns A BoundStore object representing the store.
211
- */
212
- const store = (storeKey, init) => {
213
- const rawStore = getStore(storeKey, init);
214
- return {
215
- key: storeKey,
216
- raw: () => rawStore,
217
- get: () => rawStore.get(),
218
- subscribe: (cb) => rawStore.subscribe(cb),
219
- set: (next) => set(storeKey, next, init),
220
- };
221
- };
222
- return {
223
- /** Universe */
224
- universe,
225
- /** Client ID */
226
- clientId,
227
- // ------------ DX ------------ \\
228
- /** Get store */
229
- getStore,
230
- /** Create store */
231
- store,
232
- /** Get state */
233
- get,
234
- /** Set state */
235
- set,
236
- /** Subscribe to store */
237
- subscribe,
238
- // ------------ Advanced ------------ \\
239
- /** Dispatch event */
240
- dispatch,
241
- /** Stop */
242
- stop,
243
- /** Hydrate snapshot */
244
- hydrateSnapshot,
245
- /** Get last event ID */
246
- getLastEventId,
247
- /** Set last event ID */
248
- setLastEventId,
249
- };
250
- };
@@ -1,10 +0,0 @@
1
- import type { Store } from "./types";
2
- /**
3
- * Creates a ZUNO state management store.
4
- *
5
- * @template T The type of the state managed by the store.
6
- * @param {T} initial The initial state value.
7
- * @returns {Store<T>} An object containing methods to interact with the store.
8
- */
9
- export declare const createStore: <T>(initial: T) => Store<T>;
10
- //# sourceMappingURL=store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,SAAS,CAAC,KAAG,KAAK,CAAC,CAAC,CAsBlD,CAAC"}
@@ -1,27 +0,0 @@
1
- /**
2
- * Creates a ZUNO state management store.
3
- *
4
- * @template T The type of the state managed by the store.
5
- * @param {T} initial The initial state value.
6
- * @returns {Store<T>} An object containing methods to interact with the store.
7
- */
8
- export const createStore = (initial) => {
9
- let state = initial;
10
- const listeners = new Set();
11
- return {
12
- get: () => state,
13
- set: (next) => {
14
- const value = typeof next === "function"
15
- ? next(state)
16
- : next;
17
- if (Object.is(value, state))
18
- return;
19
- state = value;
20
- listeners.forEach((l) => l(state));
21
- },
22
- subscribe: (listener) => {
23
- listeners.add(listener);
24
- return () => listeners.delete(listener);
25
- }
26
- };
27
- };