@electric-sql/react 0.1.0 → 0.1.1
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/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/react-hooks.tsx"],"sourcesContent":["export * from './react-hooks'\n","import {\n
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/react-hooks.tsx"],"sourcesContent":["export * from './react-hooks'\n","import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/next'\nimport React, { createContext, useCallback, useContext, useRef } from 'react'\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'\n\ninterface ShapeContextType {\n getShape: (shapeStream: ShapeStream) => Shape\n getShapeStream: (options: ShapeStreamOptions) => ShapeStream\n}\n\n// Create a Context\nconst ShapesContext = createContext<ShapeContextType | null>(null)\n\nconst streamCache = new Map<string, ShapeStream>()\nconst shapeCache = new Map<ShapeStream, Shape>()\n\nexport async function preloadShape(\n options: ShapeStreamOptions\n): Promise<Shape> {\n const shapeStream = getShapeStream(options)\n const shape = getShape(shapeStream)\n await shape.value\n return shape\n}\n\nexport function sortedOptionsHash(options: ShapeStreamOptions): string {\n return JSON.stringify(options, Object.keys(options).sort())\n}\n\nexport function getShapeStream(options: ShapeStreamOptions): ShapeStream {\n const shapeHash = sortedOptionsHash(options)\n\n // If the stream is already cached, return\n if (streamCache.has(shapeHash)) {\n // Return the ShapeStream\n return streamCache.get(shapeHash)!\n } else {\n const newShapeStream = new ShapeStream(options)\n\n streamCache.set(shapeHash, newShapeStream)\n\n // Return the created shape\n return newShapeStream\n }\n}\n\nexport function getShape(shapeStream: ShapeStream): Shape {\n // If the stream is already cached, return\n if (shapeCache.has(shapeStream)) {\n // Return the ShapeStream\n return shapeCache.get(shapeStream)!\n } else {\n const newShape = new Shape(shapeStream)\n\n shapeCache.set(shapeStream, newShape)\n\n // Return the created shape\n return newShape\n }\n}\n\ninterface ShapeProviderProps {\n children: React.ReactNode\n}\n\n// Shapes Provider Component\nexport function ShapesProvider({ children }: ShapeProviderProps): JSX.Element {\n // Provide the context value\n return (\n <ShapesContext.Provider value={{ getShape, getShapeStream }}>\n {children}\n </ShapesContext.Provider>\n )\n}\n\nexport function useShapeContext() {\n const context = useContext(ShapesContext)\n if (!context) {\n throw new Error(`useShapeContext must be used within a ShapeProvider`)\n }\n return context\n}\n\ninterface UseShapeResult {\n /**\n * The array of rows that make up the Shape.\n * @type {{ [key: string]: Value }[]}\n */\n data: { [key: string]: Value }[]\n /**\n * The Shape instance used by this useShape\n * @type(Shape)\n */\n shape: Shape\n error: Shape[`error`]\n isError: boolean\n /**\n * Has the ShapeStream caught up with the replication log from Postgres.\n */\n isUpToDate: boolean\n}\n\nfunction shapeSubscribe(shape: Shape, callback: () => void) {\n const unsubscribe = shape.subscribe(callback)\n return () => {\n unsubscribe()\n }\n}\n\nfunction parseShapeData(shape: Shape): UseShapeResult {\n return {\n data: [...shape.valueSync.values()],\n isUpToDate: shape.isUpToDate,\n isError: shape.error !== false,\n shape,\n error: shape.error,\n }\n}\n\nconst identity = (arg: unknown) => arg\n\ninterface UseShapeOptions<Selection> extends ShapeStreamOptions {\n selector?: (value: UseShapeResult) => Selection\n}\n\nexport function useShape<Selection = UseShapeResult>({\n selector = identity as never,\n ...options\n}: UseShapeOptions<Selection>): Selection {\n const { getShape, getShapeStream } = useShapeContext()\n const shapeStream = getShapeStream(options as ShapeStreamOptions)\n const shape = getShape(shapeStream)\n\n const latestShapeData = useRef(parseShapeData(shape))\n const getSnapshot = React.useCallback(() => latestShapeData.current, [])\n const shapeData = useSyncExternalStoreWithSelector(\n useCallback(\n (onStoreChange) =>\n shapeSubscribe(shape, () => {\n latestShapeData.current = parseShapeData(shape)\n onStoreChange()\n }),\n [shape]\n ),\n getSnapshot,\n getSnapshot,\n selector\n )\n\n return shapeData\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAKO;AACP,mBAAsE;AACtE,2BAAiD;AAQjD,IAAM,oBAAgB,4BAAuC,IAAI;AAEjE,IAAM,cAAc,oBAAI,IAAyB;AACjD,IAAM,aAAa,oBAAI,IAAwB;AAE/C,SAAsB,aACpB,SACgB;AAAA;AAChB,UAAM,cAAc,eAAe,OAAO;AAC1C,UAAM,QAAQ,SAAS,WAAW;AAClC,UAAM,MAAM;AACZ,WAAO;AAAA,EACT;AAAA;AAEO,SAAS,kBAAkB,SAAqC;AACrE,SAAO,KAAK,UAAU,SAAS,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC;AAC5D;AAEO,SAAS,eAAe,SAA0C;AACvE,QAAM,YAAY,kBAAkB,OAAO;AAG3C,MAAI,YAAY,IAAI,SAAS,GAAG;AAE9B,WAAO,YAAY,IAAI,SAAS;AAAA,EAClC,OAAO;AACL,UAAM,iBAAiB,IAAI,wBAAY,OAAO;AAE9C,gBAAY,IAAI,WAAW,cAAc;AAGzC,WAAO;AAAA,EACT;AACF;AAEO,SAAS,SAAS,aAAiC;AAExD,MAAI,WAAW,IAAI,WAAW,GAAG;AAE/B,WAAO,WAAW,IAAI,WAAW;AAAA,EACnC,OAAO;AACL,UAAM,WAAW,IAAI,kBAAM,WAAW;AAEtC,eAAW,IAAI,aAAa,QAAQ;AAGpC,WAAO;AAAA,EACT;AACF;AAOO,SAAS,eAAe,EAAE,SAAS,GAAoC;AAE5E,SACE,6BAAAA,QAAA,cAAC,cAAc,UAAd,EAAuB,OAAO,EAAE,UAAU,eAAe,KACvD,QACH;AAEJ;AAEO,SAAS,kBAAkB;AAChC,QAAM,cAAU,yBAAW,aAAa;AACxC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,SAAO;AACT;AAqBA,SAAS,eAAe,OAAc,UAAsB;AAC1D,QAAM,cAAc,MAAM,UAAU,QAAQ;AAC5C,SAAO,MAAM;AACX,gBAAY;AAAA,EACd;AACF;AAEA,SAAS,eAAe,OAA8B;AACpD,SAAO;AAAA,IACL,MAAM,CAAC,GAAG,MAAM,UAAU,OAAO,CAAC;AAAA,IAClC,YAAY,MAAM;AAAA,IAClB,SAAS,MAAM,UAAU;AAAA,IACzB;AAAA,IACA,OAAO,MAAM;AAAA,EACf;AACF;AAEA,IAAM,WAAW,CAAC,QAAiB;AAM5B,SAAS,SAAqC,IAGX;AAHW,eACnD;AAAA,eAAW;AAAA,EAlIb,IAiIqD,IAEhD,oBAFgD,IAEhD;AAAA,IADH;AAAA;AAGA,QAAM,EAAE,UAAAC,WAAU,gBAAAC,gBAAe,IAAI,gBAAgB;AACrD,QAAM,cAAcA,gBAAe,OAA6B;AAChE,QAAM,QAAQD,UAAS,WAAW;AAElC,QAAM,sBAAkB,qBAAO,eAAe,KAAK,CAAC;AACpD,QAAM,cAAc,aAAAD,QAAM,YAAY,MAAM,gBAAgB,SAAS,CAAC,CAAC;AACvE,QAAM,gBAAY;AAAA,QAChB;AAAA,MACE,CAAC,kBACC,eAAe,OAAO,MAAM;AAC1B,wBAAgB,UAAU,eAAe,KAAK;AAC9C,sBAAc;AAAA,MAChB,CAAC;AAAA,MACH,CAAC,KAAK;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;","names":["React","getShape","getShapeStream"]}
|
package/dist/index.browser.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var u=Object.getOwnPropertySymbols;var C=Object.prototype.hasOwnProperty,O=Object.prototype.propertyIsEnumerable;var l=(e,t)=>{var a={};for(var r in e)C.call(e,r)&&t.indexOf(r)<0&&(a[r]=e[r]);if(e!=null&&u)for(var r of u(e))t.indexOf(r)<0&&O.call(e,r)&&(a[r]=e[r]);return a};var m=(e,t,a)=>new Promise((r,p)=>{var S=n=>{try{o(a.next(n))}catch(s){p(s)}},h=n=>{try{o(a.throw(n))}catch(s){p(s)}},o=n=>n.done?r(n.value):Promise.resolve(n.value).then(S,h);o((a=a.apply(e,t)).next())});import{Shape as w,ShapeStream as y}from"@electric-sql/next";import x,{createContext as P,useCallback as U,useContext as D,useRef as R}from"react";import{useSyncExternalStoreWithSelector as k}from"use-sync-external-store/with-selector.js";var d=P(null),i=new Map,c=new Map;function
|
|
1
|
+
var u=Object.getOwnPropertySymbols;var C=Object.prototype.hasOwnProperty,O=Object.prototype.propertyIsEnumerable;var l=(e,t)=>{var a={};for(var r in e)C.call(e,r)&&t.indexOf(r)<0&&(a[r]=e[r]);if(e!=null&&u)for(var r of u(e))t.indexOf(r)<0&&O.call(e,r)&&(a[r]=e[r]);return a};var m=(e,t,a)=>new Promise((r,p)=>{var S=n=>{try{o(a.next(n))}catch(s){p(s)}},h=n=>{try{o(a.throw(n))}catch(s){p(s)}},o=n=>n.done?r(n.value):Promise.resolve(n.value).then(S,h);o((a=a.apply(e,t)).next())});import{Shape as w,ShapeStream as y}from"@electric-sql/next";import x,{createContext as P,useCallback as U,useContext as D,useRef as R}from"react";import{useSyncExternalStoreWithSelector as k}from"use-sync-external-store/with-selector.js";var d=P(null),i=new Map,c=new Map;function z(e){return m(this,null,function*(){let t=g(e),a=v(t);return yield a.value,a})}function E(e){return JSON.stringify(e,Object.keys(e).sort())}function g(e){let t=E(e);if(i.has(t))return i.get(t);{let a=new y(e);return i.set(t,a),a}}function v(e){if(c.has(e))return c.get(e);{let t=new w(e);return c.set(e,t),t}}function A({children:e}){return x.createElement(d.Provider,{value:{getShape:v,getShapeStream:g}},e)}function T(){let e=D(d);if(!e)throw new Error("useShapeContext must be used within a ShapeProvider");return e}function H(e,t){let a=e.subscribe(t);return()=>{a()}}function f(e){return{data:[...e.valueSync.values()],isUpToDate:e.isUpToDate,isError:e.error!==!1,shape:e,error:e.error}}var J=e=>e;function B(a){var r=a,{selector:e=J}=r,t=l(r,["selector"]);let{getShape:p,getShapeStream:S}=T(),h=S(t),o=p(h),n=R(f(o)),s=x.useCallback(()=>n.current,[]);return k(U(b=>H(o,()=>{n.current=f(o),b()}),[o]),s,s,e)}export{A as ShapesProvider,v as getShape,g as getShapeStream,z as preloadShape,E as sortedOptionsHash,B as useShape,T as useShapeContext};
|
|
2
2
|
//# sourceMappingURL=index.browser.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n
|
|
1
|
+
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/next'\nimport React, { createContext, useCallback, useContext, useRef } from 'react'\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'\n\ninterface ShapeContextType {\n getShape: (shapeStream: ShapeStream) => Shape\n getShapeStream: (options: ShapeStreamOptions) => ShapeStream\n}\n\n// Create a Context\nconst ShapesContext = createContext<ShapeContextType | null>(null)\n\nconst streamCache = new Map<string, ShapeStream>()\nconst shapeCache = new Map<ShapeStream, Shape>()\n\nexport async function preloadShape(\n options: ShapeStreamOptions\n): Promise<Shape> {\n const shapeStream = getShapeStream(options)\n const shape = getShape(shapeStream)\n await shape.value\n return shape\n}\n\nexport function sortedOptionsHash(options: ShapeStreamOptions): string {\n return JSON.stringify(options, Object.keys(options).sort())\n}\n\nexport function getShapeStream(options: ShapeStreamOptions): ShapeStream {\n const shapeHash = sortedOptionsHash(options)\n\n // If the stream is already cached, return\n if (streamCache.has(shapeHash)) {\n // Return the ShapeStream\n return streamCache.get(shapeHash)!\n } else {\n const newShapeStream = new ShapeStream(options)\n\n streamCache.set(shapeHash, newShapeStream)\n\n // Return the created shape\n return newShapeStream\n }\n}\n\nexport function getShape(shapeStream: ShapeStream): Shape {\n // If the stream is already cached, return\n if (shapeCache.has(shapeStream)) {\n // Return the ShapeStream\n return shapeCache.get(shapeStream)!\n } else {\n const newShape = new Shape(shapeStream)\n\n shapeCache.set(shapeStream, newShape)\n\n // Return the created shape\n return newShape\n }\n}\n\ninterface ShapeProviderProps {\n children: React.ReactNode\n}\n\n// Shapes Provider Component\nexport function ShapesProvider({ children }: ShapeProviderProps): JSX.Element {\n // Provide the context value\n return (\n <ShapesContext.Provider value={{ getShape, getShapeStream }}>\n {children}\n </ShapesContext.Provider>\n )\n}\n\nexport function useShapeContext() {\n const context = useContext(ShapesContext)\n if (!context) {\n throw new Error(`useShapeContext must be used within a ShapeProvider`)\n }\n return context\n}\n\ninterface UseShapeResult {\n /**\n * The array of rows that make up the Shape.\n * @type {{ [key: string]: Value }[]}\n */\n data: { [key: string]: Value }[]\n /**\n * The Shape instance used by this useShape\n * @type(Shape)\n */\n shape: Shape\n error: Shape[`error`]\n isError: boolean\n /**\n * Has the ShapeStream caught up with the replication log from Postgres.\n */\n isUpToDate: boolean\n}\n\nfunction shapeSubscribe(shape: Shape, callback: () => void) {\n const unsubscribe = shape.subscribe(callback)\n return () => {\n unsubscribe()\n }\n}\n\nfunction parseShapeData(shape: Shape): UseShapeResult {\n return {\n data: [...shape.valueSync.values()],\n isUpToDate: shape.isUpToDate,\n isError: shape.error !== false,\n shape,\n error: shape.error,\n }\n}\n\nconst identity = (arg: unknown) => arg\n\ninterface UseShapeOptions<Selection> extends ShapeStreamOptions {\n selector?: (value: UseShapeResult) => Selection\n}\n\nexport function useShape<Selection = UseShapeResult>({\n selector = identity as never,\n ...options\n}: UseShapeOptions<Selection>): Selection {\n const { getShape, getShapeStream } = useShapeContext()\n const shapeStream = getShapeStream(options as ShapeStreamOptions)\n const shape = getShape(shapeStream)\n\n const latestShapeData = useRef(parseShapeData(shape))\n const getSnapshot = React.useCallback(() => latestShapeData.current, [])\n const shapeData = useSyncExternalStoreWithSelector(\n useCallback(\n (onStoreChange) =>\n shapeSubscribe(shape, () => {\n latestShapeData.current = parseShapeData(shape)\n onStoreChange()\n }),\n [shape]\n ),\n getSnapshot,\n getSnapshot,\n selector\n )\n\n return shapeData\n}\n"],"mappings":"geAAA,OAEE,SAAAA,EACA,eAAAC,MAEK,qBACP,OAAOC,GAAS,iBAAAC,EAAe,eAAAC,EAAa,cAAAC,EAAY,UAAAC,MAAc,QACtE,OAAS,oCAAAC,MAAwC,2CAQjD,IAAMC,EAAgBC,EAAuC,IAAI,EAE3DC,EAAc,IAAI,IAClBC,EAAa,IAAI,IAEvB,SAAsBC,EACpBC,EACgB,QAAAC,EAAA,sBAChB,IAAMC,EAAcC,EAAeH,CAAO,EACpCI,EAAQC,EAASH,CAAW,EAClC,aAAME,EAAM,MACLA,CACT,GAEO,SAASE,EAAkBN,EAAqC,CACrE,OAAO,KAAK,UAAUA,EAAS,OAAO,KAAKA,CAAO,EAAE,KAAK,CAAC,CAC5D,CAEO,SAASG,EAAeH,EAA0C,CACvE,IAAMO,EAAYD,EAAkBN,CAAO,EAG3C,GAAIH,EAAY,IAAIU,CAAS,EAE3B,OAAOV,EAAY,IAAIU,CAAS,EAC3B,CACL,IAAMC,EAAiB,IAAIC,EAAYT,CAAO,EAE9C,OAAAH,EAAY,IAAIU,EAAWC,CAAc,EAGlCA,CACT,CACF,CAEO,SAASH,EAASH,EAAiC,CAExD,GAAIJ,EAAW,IAAII,CAAW,EAE5B,OAAOJ,EAAW,IAAII,CAAW,EAC5B,CACL,IAAMQ,EAAW,IAAIC,EAAMT,CAAW,EAEtC,OAAAJ,EAAW,IAAII,EAAaQ,CAAQ,EAG7BA,CACT,CACF,CAOO,SAASE,EAAe,CAAE,SAAAC,CAAS,EAAoC,CAE5E,OACEC,EAAA,cAACnB,EAAc,SAAd,CAAuB,MAAO,CAAE,SAAAU,EAAU,eAAAF,CAAe,GACvDU,CACH,CAEJ,CAEO,SAASE,GAAkB,CAChC,IAAMC,EAAUC,EAAWtB,CAAa,EACxC,GAAI,CAACqB,EACH,MAAM,IAAI,MAAM,qDAAqD,EAEvE,OAAOA,CACT,CAqBA,SAASE,EAAed,EAAce,EAAsB,CAC1D,IAAMC,EAAchB,EAAM,UAAUe,CAAQ,EAC5C,MAAO,IAAM,CACXC,EAAY,CACd,CACF,CAEA,SAASC,EAAejB,EAA8B,CACpD,MAAO,CACL,KAAM,CAAC,GAAGA,EAAM,UAAU,OAAO,CAAC,EAClC,WAAYA,EAAM,WAClB,QAASA,EAAM,QAAU,GACzB,MAAAA,EACA,MAAOA,EAAM,KACf,CACF,CAEA,IAAMkB,EAAYC,GAAiBA,EAM5B,SAASC,EAAqCC,EAGX,CAHW,IAAAC,EAAAD,EACnD,UAAAE,EAAWL,CAlIb,EAiIqDI,EAEhD1B,EAAA4B,EAFgDF,EAEhD,CADH,aAGA,GAAM,CAAE,SAAArB,EAAU,eAAAF,CAAe,EAAIY,EAAgB,EAC/Cb,EAAcC,EAAeH,CAA6B,EAC1DI,EAAQC,EAASH,CAAW,EAE5B2B,EAAkBC,EAAOT,EAAejB,CAAK,CAAC,EAC9C2B,EAAcjB,EAAM,YAAY,IAAMe,EAAgB,QAAS,CAAC,CAAC,EAevE,OAdkBG,EAChBC,EACGC,GACChB,EAAed,EAAO,IAAM,CAC1ByB,EAAgB,QAAUR,EAAejB,CAAK,EAC9C8B,EAAc,CAChB,CAAC,EACH,CAAC9B,CAAK,CACR,EACA2B,EACAA,EACAJ,CACF,CAGF","names":["Shape","ShapeStream","React","createContext","useCallback","useContext","useRef","useSyncExternalStoreWithSelector","ShapesContext","createContext","streamCache","shapeCache","preloadShape","options","__async","shapeStream","getShapeStream","shape","getShape","sortedOptionsHash","shapeHash","newShapeStream","ShapeStream","newShape","Shape","ShapesProvider","children","React","useShapeContext","context","useContext","shapeSubscribe","callback","unsubscribe","parseShapeData","identity","arg","useShape","_a","_b","selector","__objRest","latestShapeData","useRef","getSnapshot","useSyncExternalStoreWithSelector","useCallback","onStoreChange"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ShapeStreamOptions, Shape, ShapeStream,
|
|
1
|
+
import { ShapeStreamOptions, Shape, ShapeStream, Value } from '@electric-sql/next';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
4
|
interface ShapeContextType {
|
|
@@ -17,10 +17,10 @@ declare function useShapeContext(): ShapeContextType;
|
|
|
17
17
|
interface UseShapeResult {
|
|
18
18
|
/**
|
|
19
19
|
* The array of rows that make up the Shape.
|
|
20
|
-
* @type {{ [key: string]:
|
|
20
|
+
* @type {{ [key: string]: Value }[]}
|
|
21
21
|
*/
|
|
22
22
|
data: {
|
|
23
|
-
[key: string]:
|
|
23
|
+
[key: string]: Value;
|
|
24
24
|
}[];
|
|
25
25
|
/**
|
|
26
26
|
* The Shape instance used by this useShape
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n
|
|
1
|
+
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/next'\nimport React, { createContext, useCallback, useContext, useRef } from 'react'\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'\n\ninterface ShapeContextType {\n getShape: (shapeStream: ShapeStream) => Shape\n getShapeStream: (options: ShapeStreamOptions) => ShapeStream\n}\n\n// Create a Context\nconst ShapesContext = createContext<ShapeContextType | null>(null)\n\nconst streamCache = new Map<string, ShapeStream>()\nconst shapeCache = new Map<ShapeStream, Shape>()\n\nexport async function preloadShape(\n options: ShapeStreamOptions\n): Promise<Shape> {\n const shapeStream = getShapeStream(options)\n const shape = getShape(shapeStream)\n await shape.value\n return shape\n}\n\nexport function sortedOptionsHash(options: ShapeStreamOptions): string {\n return JSON.stringify(options, Object.keys(options).sort())\n}\n\nexport function getShapeStream(options: ShapeStreamOptions): ShapeStream {\n const shapeHash = sortedOptionsHash(options)\n\n // If the stream is already cached, return\n if (streamCache.has(shapeHash)) {\n // Return the ShapeStream\n return streamCache.get(shapeHash)!\n } else {\n const newShapeStream = new ShapeStream(options)\n\n streamCache.set(shapeHash, newShapeStream)\n\n // Return the created shape\n return newShapeStream\n }\n}\n\nexport function getShape(shapeStream: ShapeStream): Shape {\n // If the stream is already cached, return\n if (shapeCache.has(shapeStream)) {\n // Return the ShapeStream\n return shapeCache.get(shapeStream)!\n } else {\n const newShape = new Shape(shapeStream)\n\n shapeCache.set(shapeStream, newShape)\n\n // Return the created shape\n return newShape\n }\n}\n\ninterface ShapeProviderProps {\n children: React.ReactNode\n}\n\n// Shapes Provider Component\nexport function ShapesProvider({ children }: ShapeProviderProps): JSX.Element {\n // Provide the context value\n return (\n <ShapesContext.Provider value={{ getShape, getShapeStream }}>\n {children}\n </ShapesContext.Provider>\n )\n}\n\nexport function useShapeContext() {\n const context = useContext(ShapesContext)\n if (!context) {\n throw new Error(`useShapeContext must be used within a ShapeProvider`)\n }\n return context\n}\n\ninterface UseShapeResult {\n /**\n * The array of rows that make up the Shape.\n * @type {{ [key: string]: Value }[]}\n */\n data: { [key: string]: Value }[]\n /**\n * The Shape instance used by this useShape\n * @type(Shape)\n */\n shape: Shape\n error: Shape[`error`]\n isError: boolean\n /**\n * Has the ShapeStream caught up with the replication log from Postgres.\n */\n isUpToDate: boolean\n}\n\nfunction shapeSubscribe(shape: Shape, callback: () => void) {\n const unsubscribe = shape.subscribe(callback)\n return () => {\n unsubscribe()\n }\n}\n\nfunction parseShapeData(shape: Shape): UseShapeResult {\n return {\n data: [...shape.valueSync.values()],\n isUpToDate: shape.isUpToDate,\n isError: shape.error !== false,\n shape,\n error: shape.error,\n }\n}\n\nconst identity = (arg: unknown) => arg\n\ninterface UseShapeOptions<Selection> extends ShapeStreamOptions {\n selector?: (value: UseShapeResult) => Selection\n}\n\nexport function useShape<Selection = UseShapeResult>({\n selector = identity as never,\n ...options\n}: UseShapeOptions<Selection>): Selection {\n const { getShape, getShapeStream } = useShapeContext()\n const shapeStream = getShapeStream(options as ShapeStreamOptions)\n const shape = getShape(shapeStream)\n\n const latestShapeData = useRef(parseShapeData(shape))\n const getSnapshot = React.useCallback(() => latestShapeData.current, [])\n const shapeData = useSyncExternalStoreWithSelector(\n useCallback(\n (onStoreChange) =>\n shapeSubscribe(shape, () => {\n latestShapeData.current = parseShapeData(shape)\n onStoreChange()\n }),\n [shape]\n ),\n getSnapshot,\n getSnapshot,\n selector\n )\n\n return shapeData\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AAAA,EAEE;AAAA,EACA;AAAA,OAEK;AACP,OAAO,SAAS,eAAe,aAAa,YAAY,cAAc;AACtE,SAAS,wCAAwC;AAQjD,IAAM,gBAAgB,cAAuC,IAAI;AAEjE,IAAM,cAAc,oBAAI,IAAyB;AACjD,IAAM,aAAa,oBAAI,IAAwB;AAE/C,eAAsB,aACpB,SACgB;AAChB,QAAM,cAAc,eAAe,OAAO;AAC1C,QAAM,QAAQ,SAAS,WAAW;AAClC,QAAM,MAAM;AACZ,SAAO;AACT;AAEO,SAAS,kBAAkB,SAAqC;AACrE,SAAO,KAAK,UAAU,SAAS,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC;AAC5D;AAEO,SAAS,eAAe,SAA0C;AACvE,QAAM,YAAY,kBAAkB,OAAO;AAG3C,MAAI,YAAY,IAAI,SAAS,GAAG;AAE9B,WAAO,YAAY,IAAI,SAAS;AAAA,EAClC,OAAO;AACL,UAAM,iBAAiB,IAAI,YAAY,OAAO;AAE9C,gBAAY,IAAI,WAAW,cAAc;AAGzC,WAAO;AAAA,EACT;AACF;AAEO,SAAS,SAAS,aAAiC;AAExD,MAAI,WAAW,IAAI,WAAW,GAAG;AAE/B,WAAO,WAAW,IAAI,WAAW;AAAA,EACnC,OAAO;AACL,UAAM,WAAW,IAAI,MAAM,WAAW;AAEtC,eAAW,IAAI,aAAa,QAAQ;AAGpC,WAAO;AAAA,EACT;AACF;AAOO,SAAS,eAAe,EAAE,SAAS,GAAoC;AAE5E,SACE,oCAAC,cAAc,UAAd,EAAuB,OAAO,EAAE,UAAU,eAAe,KACvD,QACH;AAEJ;AAEO,SAAS,kBAAkB;AAChC,QAAM,UAAU,WAAW,aAAa;AACxC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,SAAO;AACT;AAqBA,SAAS,eAAe,OAAc,UAAsB;AAC1D,QAAM,cAAc,MAAM,UAAU,QAAQ;AAC5C,SAAO,MAAM;AACX,gBAAY;AAAA,EACd;AACF;AAEA,SAAS,eAAe,OAA8B;AACpD,SAAO;AAAA,IACL,MAAM,CAAC,GAAG,MAAM,UAAU,OAAO,CAAC;AAAA,IAClC,YAAY,MAAM;AAAA,IAClB,SAAS,MAAM,UAAU;AAAA,IACzB;AAAA,IACA,OAAO,MAAM;AAAA,EACf;AACF;AAEA,IAAM,WAAW,CAAC,QAAiB;AAM5B,SAAS,SAAqC,IAGX;AAHW,eACnD;AAAA,eAAW;AAAA,EAlIb,IAiIqD,IAEhD,oBAFgD,IAEhD;AAAA,IADH;AAAA;AAGA,QAAM,EAAE,UAAAA,WAAU,gBAAAC,gBAAe,IAAI,gBAAgB;AACrD,QAAM,cAAcA,gBAAe,OAA6B;AAChE,QAAM,QAAQD,UAAS,WAAW;AAElC,QAAM,kBAAkB,OAAO,eAAe,KAAK,CAAC;AACpD,QAAM,cAAc,MAAM,YAAY,MAAM,gBAAgB,SAAS,CAAC,CAAC;AACvE,QAAM,YAAY;AAAA,IAChB;AAAA,MACE,CAAC,kBACC,eAAe,OAAO,MAAM;AAC1B,wBAAgB,UAAU,eAAe,KAAK;AAC9C,sBAAc;AAAA,MAChB,CAAC;AAAA,MACH,CAAC,KAAK;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;","names":["getShape","getShapeStream"]}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n
|
|
1
|
+
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/next'\nimport React, { createContext, useCallback, useContext, useRef } from 'react'\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'\n\ninterface ShapeContextType {\n getShape: (shapeStream: ShapeStream) => Shape\n getShapeStream: (options: ShapeStreamOptions) => ShapeStream\n}\n\n// Create a Context\nconst ShapesContext = createContext<ShapeContextType | null>(null)\n\nconst streamCache = new Map<string, ShapeStream>()\nconst shapeCache = new Map<ShapeStream, Shape>()\n\nexport async function preloadShape(\n options: ShapeStreamOptions\n): Promise<Shape> {\n const shapeStream = getShapeStream(options)\n const shape = getShape(shapeStream)\n await shape.value\n return shape\n}\n\nexport function sortedOptionsHash(options: ShapeStreamOptions): string {\n return JSON.stringify(options, Object.keys(options).sort())\n}\n\nexport function getShapeStream(options: ShapeStreamOptions): ShapeStream {\n const shapeHash = sortedOptionsHash(options)\n\n // If the stream is already cached, return\n if (streamCache.has(shapeHash)) {\n // Return the ShapeStream\n return streamCache.get(shapeHash)!\n } else {\n const newShapeStream = new ShapeStream(options)\n\n streamCache.set(shapeHash, newShapeStream)\n\n // Return the created shape\n return newShapeStream\n }\n}\n\nexport function getShape(shapeStream: ShapeStream): Shape {\n // If the stream is already cached, return\n if (shapeCache.has(shapeStream)) {\n // Return the ShapeStream\n return shapeCache.get(shapeStream)!\n } else {\n const newShape = new Shape(shapeStream)\n\n shapeCache.set(shapeStream, newShape)\n\n // Return the created shape\n return newShape\n }\n}\n\ninterface ShapeProviderProps {\n children: React.ReactNode\n}\n\n// Shapes Provider Component\nexport function ShapesProvider({ children }: ShapeProviderProps): JSX.Element {\n // Provide the context value\n return (\n <ShapesContext.Provider value={{ getShape, getShapeStream }}>\n {children}\n </ShapesContext.Provider>\n )\n}\n\nexport function useShapeContext() {\n const context = useContext(ShapesContext)\n if (!context) {\n throw new Error(`useShapeContext must be used within a ShapeProvider`)\n }\n return context\n}\n\ninterface UseShapeResult {\n /**\n * The array of rows that make up the Shape.\n * @type {{ [key: string]: Value }[]}\n */\n data: { [key: string]: Value }[]\n /**\n * The Shape instance used by this useShape\n * @type(Shape)\n */\n shape: Shape\n error: Shape[`error`]\n isError: boolean\n /**\n * Has the ShapeStream caught up with the replication log from Postgres.\n */\n isUpToDate: boolean\n}\n\nfunction shapeSubscribe(shape: Shape, callback: () => void) {\n const unsubscribe = shape.subscribe(callback)\n return () => {\n unsubscribe()\n }\n}\n\nfunction parseShapeData(shape: Shape): UseShapeResult {\n return {\n data: [...shape.valueSync.values()],\n isUpToDate: shape.isUpToDate,\n isError: shape.error !== false,\n shape,\n error: shape.error,\n }\n}\n\nconst identity = (arg: unknown) => arg\n\ninterface UseShapeOptions<Selection> extends ShapeStreamOptions {\n selector?: (value: UseShapeResult) => Selection\n}\n\nexport function useShape<Selection = UseShapeResult>({\n selector = identity as never,\n ...options\n}: UseShapeOptions<Selection>): Selection {\n const { getShape, getShapeStream } = useShapeContext()\n const shapeStream = getShapeStream(options as ShapeStreamOptions)\n const shape = getShape(shapeStream)\n\n const latestShapeData = useRef(parseShapeData(shape))\n const getSnapshot = React.useCallback(() => latestShapeData.current, [])\n const shapeData = useSyncExternalStoreWithSelector(\n useCallback(\n (onStoreChange) =>\n shapeSubscribe(shape, () => {\n latestShapeData.current = parseShapeData(shape)\n onStoreChange()\n }),\n [shape]\n ),\n getSnapshot,\n getSnapshot,\n selector\n )\n\n return shapeData\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EAEE;AAAA,EACA;AAAA,OAEK;AACP,OAAO,SAAS,eAAe,aAAa,YAAY,cAAc;AACtE,SAAS,wCAAwC;AAQjD,IAAM,gBAAgB,cAAuC,IAAI;AAEjE,IAAM,cAAc,oBAAI,IAAyB;AACjD,IAAM,aAAa,oBAAI,IAAwB;AAE/C,SAAsB,aACpB,SACgB;AAAA;AAChB,UAAM,cAAc,eAAe,OAAO;AAC1C,UAAM,QAAQ,SAAS,WAAW;AAClC,UAAM,MAAM;AACZ,WAAO;AAAA,EACT;AAAA;AAEO,SAAS,kBAAkB,SAAqC;AACrE,SAAO,KAAK,UAAU,SAAS,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC;AAC5D;AAEO,SAAS,eAAe,SAA0C;AACvE,QAAM,YAAY,kBAAkB,OAAO;AAG3C,MAAI,YAAY,IAAI,SAAS,GAAG;AAE9B,WAAO,YAAY,IAAI,SAAS;AAAA,EAClC,OAAO;AACL,UAAM,iBAAiB,IAAI,YAAY,OAAO;AAE9C,gBAAY,IAAI,WAAW,cAAc;AAGzC,WAAO;AAAA,EACT;AACF;AAEO,SAAS,SAAS,aAAiC;AAExD,MAAI,WAAW,IAAI,WAAW,GAAG;AAE/B,WAAO,WAAW,IAAI,WAAW;AAAA,EACnC,OAAO;AACL,UAAM,WAAW,IAAI,MAAM,WAAW;AAEtC,eAAW,IAAI,aAAa,QAAQ;AAGpC,WAAO;AAAA,EACT;AACF;AAOO,SAAS,eAAe,EAAE,SAAS,GAAoC;AAE5E,SACE,oCAAC,cAAc,UAAd,EAAuB,OAAO,EAAE,UAAU,eAAe,KACvD,QACH;AAEJ;AAEO,SAAS,kBAAkB;AAChC,QAAM,UAAU,WAAW,aAAa;AACxC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,SAAO;AACT;AAqBA,SAAS,eAAe,OAAc,UAAsB;AAC1D,QAAM,cAAc,MAAM,UAAU,QAAQ;AAC5C,SAAO,MAAM;AACX,gBAAY;AAAA,EACd;AACF;AAEA,SAAS,eAAe,OAA8B;AACpD,SAAO;AAAA,IACL,MAAM,CAAC,GAAG,MAAM,UAAU,OAAO,CAAC;AAAA,IAClC,YAAY,MAAM;AAAA,IAClB,SAAS,MAAM,UAAU;AAAA,IACzB;AAAA,IACA,OAAO,MAAM;AAAA,EACf;AACF;AAEA,IAAM,WAAW,CAAC,QAAiB;AAM5B,SAAS,SAAqC,IAGX;AAHW,eACnD;AAAA,eAAW;AAAA,EAlIb,IAiIqD,IAEhD,oBAFgD,IAEhD;AAAA,IADH;AAAA;AAGA,QAAM,EAAE,UAAAA,WAAU,gBAAAC,gBAAe,IAAI,gBAAgB;AACrD,QAAM,cAAcA,gBAAe,OAA6B;AAChE,QAAM,QAAQD,UAAS,WAAW;AAElC,QAAM,kBAAkB,OAAO,eAAe,KAAK,CAAC;AACpD,QAAM,cAAc,MAAM,YAAY,MAAM,gBAAgB,SAAS,CAAC,CAAC;AACvE,QAAM,YAAY;AAAA,IAChB;AAAA,MACE,CAAC,kBACC,eAAe,OAAO,MAAM;AAC1B,wBAAgB,UAAU,eAAe,KAAK;AAC9C,sBAAc;AAAA,MAChB,CAAC;AAAA,MACH,CAAC,KAAK;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;","names":["getShape","getShapeStream"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electric-sql/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "React hooks for ElectricSQL",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cjs/index.cjs",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"homepage": "https://next.electric-sql.com",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"use-sync-external-store": "^1.2.2",
|
|
34
|
-
"@electric-sql/next": "0.2.
|
|
34
|
+
"@electric-sql/next": "0.2.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@testing-library/react": "^16.0.0",
|
package/src/react-hooks.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
Value,
|
|
3
3
|
Shape,
|
|
4
4
|
ShapeStream,
|
|
5
5
|
ShapeStreamOptions,
|
|
@@ -88,9 +88,9 @@ export function useShapeContext() {
|
|
|
88
88
|
interface UseShapeResult {
|
|
89
89
|
/**
|
|
90
90
|
* The array of rows that make up the Shape.
|
|
91
|
-
* @type {{ [key: string]:
|
|
91
|
+
* @type {{ [key: string]: Value }[]}
|
|
92
92
|
*/
|
|
93
|
-
data: { [key: string]:
|
|
93
|
+
data: { [key: string]: Value }[]
|
|
94
94
|
/**
|
|
95
95
|
* The Shape instance used by this useShape
|
|
96
96
|
* @type(Shape)
|