@electric-sql/react 0.3.1 → 0.3.3
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 +20 -16
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.browser.mjs +1 -1
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.legacy-esm.js +21 -17
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +21 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/react-hooks.tsx +26 -21
package/dist/cjs/index.cjs
CHANGED
|
@@ -122,7 +122,9 @@ function parseShapeData(shape) {
|
|
|
122
122
|
error: shape.error
|
|
123
123
|
};
|
|
124
124
|
}
|
|
125
|
-
|
|
125
|
+
function identity(arg) {
|
|
126
|
+
return arg;
|
|
127
|
+
}
|
|
126
128
|
function useShape(_a) {
|
|
127
129
|
var _b = _a, {
|
|
128
130
|
selector = identity
|
|
@@ -131,21 +133,23 @@ function useShape(_a) {
|
|
|
131
133
|
]);
|
|
132
134
|
const shapeStream = getShapeStream(options);
|
|
133
135
|
const shape = getShape(shapeStream);
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
136
|
+
const useShapeData = import_react.default.useMemo(() => {
|
|
137
|
+
let latestShapeData = parseShapeData(shape);
|
|
138
|
+
const getSnapshot = () => latestShapeData;
|
|
139
|
+
const subscribe = (onStoreChange) => shapeSubscribe(shape, () => {
|
|
140
|
+
latestShapeData = parseShapeData(shape);
|
|
141
|
+
onStoreChange();
|
|
142
|
+
});
|
|
143
|
+
return () => {
|
|
144
|
+
return (0, import_with_selector.useSyncExternalStoreWithSelector)(
|
|
145
|
+
subscribe,
|
|
146
|
+
getSnapshot,
|
|
147
|
+
getSnapshot,
|
|
148
|
+
selector
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
}, [shape, selector]);
|
|
152
|
+
return useShapeData();
|
|
149
153
|
}
|
|
150
154
|
// Annotate the CommonJS export names for ESM import in node:
|
|
151
155
|
0 && (module.exports = {
|
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 Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/client'\nimport React
|
|
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/client'\nimport React from 'react'\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'\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\nexport interface 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\nfunction identity<T>(arg: T): T {\n return arg\n}\n\ninterface UseShapeOptions<Selection> extends ShapeStreamOptions {\n selector?: (value: UseShapeResult) => Selection\n}\n\nexport function useShape<Selection = UseShapeResult>({\n selector = identity as (arg: UseShapeResult) => Selection,\n ...options\n}: UseShapeOptions<Selection>): Selection {\n const shapeStream = getShapeStream(options as ShapeStreamOptions)\n const shape = getShape(shapeStream)\n\n const useShapeData = React.useMemo(() => {\n let latestShapeData = parseShapeData(shape)\n const getSnapshot = () => latestShapeData\n const subscribe = (onStoreChange: () => void) =>\n shapeSubscribe(shape, () => {\n latestShapeData = parseShapeData(shape)\n onStoreChange()\n })\n\n return () => {\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getSnapshot,\n selector\n )\n }\n }, [shape, selector])\n\n return useShapeData()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAKO;AACP,mBAAkB;AAClB,2BAAiD;AAEjD,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,0BAAY,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,oBAAM,WAAW;AAEtC,eAAW,IAAI,aAAa,QAAQ;AAGpC,WAAO;AAAA,EACT;AACF;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,SAAS,SAAY,KAAW;AAC9B,SAAO;AACT;AAMO,SAAS,SAAqC,IAGX;AAHW,eACnD;AAAA,eAAW;AAAA,EAtGb,IAqGqD,IAEhD,oBAFgD,IAEhD;AAAA,IADH;AAAA;AAGA,QAAM,cAAc,eAAe,OAA6B;AAChE,QAAM,QAAQ,SAAS,WAAW;AAElC,QAAM,eAAe,aAAAA,QAAM,QAAQ,MAAM;AACvC,QAAI,kBAAkB,eAAe,KAAK;AAC1C,UAAM,cAAc,MAAM;AAC1B,UAAM,YAAY,CAAC,kBACjB,eAAe,OAAO,MAAM;AAC1B,wBAAkB,eAAe,KAAK;AACtC,oBAAc;AAAA,IAChB,CAAC;AAEH,WAAO,MAAM;AACX,iBAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,SAAO,aAAa;AACtB;","names":["React"]}
|
package/dist/index.browser.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var u=Object.getOwnPropertySymbols;var
|
|
1
|
+
var u=Object.getOwnPropertySymbols;var U=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var l=(e,t)=>{var a={};for(var r in e)U.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&&x.call(e,r)&&(a[r]=e[r]);return a};var m=(e,t,a)=>new Promise((r,S)=>{var s=n=>{try{o(a.next(n))}catch(p){S(p)}},c=n=>{try{o(a.throw(n))}catch(p){S(p)}},o=n=>n.done?r(n.value):Promise.resolve(n.value).then(s,c);o((a=a.apply(e,t)).next())});import{Shape as d,ShapeStream as w}from"@electric-sql/client";import y from"react";import{useSyncExternalStoreWithSelector as D}from"use-sync-external-store/with-selector.js";var i=new Map,h=new Map;function j(e){return m(this,null,function*(){let t=b(e),a=O(t);return yield a.value,a})}function v(e){return JSON.stringify(e,Object.keys(e).sort())}function b(e){let t=v(e);if(i.has(t))return i.get(t);{let a=new w(e);return i.set(t,a),a}}function O(e){if(h.has(e))return h.get(e);{let t=new d(e);return h.set(e,t),t}}function R(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}}function T(e){return e}function J(a){var r=a,{selector:e=T}=r,t=l(r,["selector"]);let S=b(t),s=O(S);return y.useMemo(()=>{let o=f(s),n=()=>o,p=g=>R(s,()=>{o=f(s),g()});return()=>D(p,n,n,e)},[s,e])()}export{O as getShape,b as getShapeStream,j as preloadShape,v as sortedOptionsHash,J as useShape};
|
|
2
2
|
//# sourceMappingURL=index.browser.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/client'\nimport React
|
|
1
|
+
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/client'\nimport React from 'react'\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'\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\nexport interface 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\nfunction identity<T>(arg: T): T {\n return arg\n}\n\ninterface UseShapeOptions<Selection> extends ShapeStreamOptions {\n selector?: (value: UseShapeResult) => Selection\n}\n\nexport function useShape<Selection = UseShapeResult>({\n selector = identity as (arg: UseShapeResult) => Selection,\n ...options\n}: UseShapeOptions<Selection>): Selection {\n const shapeStream = getShapeStream(options as ShapeStreamOptions)\n const shape = getShape(shapeStream)\n\n const useShapeData = React.useMemo(() => {\n let latestShapeData = parseShapeData(shape)\n const getSnapshot = () => latestShapeData\n const subscribe = (onStoreChange: () => void) =>\n shapeSubscribe(shape, () => {\n latestShapeData = parseShapeData(shape)\n onStoreChange()\n })\n\n return () => {\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getSnapshot,\n selector\n )\n }\n }, [shape, selector])\n\n return useShapeData()\n}\n"],"mappings":"geAAA,OAEE,SAAAA,EACA,eAAAC,MAEK,uBACP,OAAOC,MAAW,QAClB,OAAS,oCAAAC,MAAwC,2CAEjD,IAAMC,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,CAqBA,SAASE,EAAeR,EAAcS,EAAsB,CAC1D,IAAMC,EAAcV,EAAM,UAAUS,CAAQ,EAC5C,MAAO,IAAM,CACXC,EAAY,CACd,CACF,CAEA,SAASC,EAAeX,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,SAASY,EAAYC,EAAW,CAC9B,OAAOA,CACT,CAMO,SAASC,EAAqCC,EAGX,CAHW,IAAAC,EAAAD,EACnD,UAAAE,EAAWL,CAtGb,EAqGqDI,EAEhDpB,EAAAsB,EAFgDF,EAEhD,CADH,aAGA,IAAMlB,EAAcC,EAAeH,CAA6B,EAC1DI,EAAQC,EAASH,CAAW,EAqBlC,OAnBqBqB,EAAM,QAAQ,IAAM,CACvC,IAAIC,EAAkBT,EAAeX,CAAK,EACpCqB,EAAc,IAAMD,EACpBE,EAAaC,GACjBf,EAAeR,EAAO,IAAM,CAC1BoB,EAAkBT,EAAeX,CAAK,EACtCuB,EAAc,CAChB,CAAC,EAEH,MAAO,IACEC,EACLF,EACAD,EACAA,EACAJ,CACF,CAEJ,EAAG,CAACjB,EAAOiB,CAAQ,CAAC,EAEA,CACtB","names":["Shape","ShapeStream","React","useSyncExternalStoreWithSelector","streamCache","shapeCache","preloadShape","options","__async","shapeStream","getShapeStream","shape","getShape","sortedOptionsHash","shapeHash","newShapeStream","ShapeStream","newShape","Shape","shapeSubscribe","callback","unsubscribe","parseShapeData","identity","arg","useShape","_a","_b","selector","__objRest","React","latestShapeData","getSnapshot","subscribe","onStoreChange","useSyncExternalStoreWithSelector"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -29,4 +29,4 @@ interface UseShapeOptions<Selection> extends ShapeStreamOptions {
|
|
|
29
29
|
}
|
|
30
30
|
declare function useShape<Selection = UseShapeResult>({ selector, ...options }: UseShapeOptions<Selection>): Selection;
|
|
31
31
|
|
|
32
|
-
export { getShape, getShapeStream, preloadShape, sortedOptionsHash, useShape };
|
|
32
|
+
export { type UseShapeResult, getShape, getShapeStream, preloadShape, sortedOptionsHash, useShape };
|
package/dist/index.legacy-esm.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
Shape,
|
|
20
20
|
ShapeStream
|
|
21
21
|
} from "@electric-sql/client";
|
|
22
|
-
import React
|
|
22
|
+
import React from "react";
|
|
23
23
|
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector.js";
|
|
24
24
|
var streamCache = /* @__PURE__ */ new Map();
|
|
25
25
|
var shapeCache = /* @__PURE__ */ new Map();
|
|
@@ -66,7 +66,9 @@ function parseShapeData(shape) {
|
|
|
66
66
|
error: shape.error
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
function identity(arg) {
|
|
70
|
+
return arg;
|
|
71
|
+
}
|
|
70
72
|
function useShape(_a) {
|
|
71
73
|
var _b = _a, {
|
|
72
74
|
selector = identity
|
|
@@ -75,21 +77,23 @@ function useShape(_a) {
|
|
|
75
77
|
]);
|
|
76
78
|
const shapeStream = getShapeStream(options);
|
|
77
79
|
const shape = getShape(shapeStream);
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
80
|
+
const useShapeData = React.useMemo(() => {
|
|
81
|
+
let latestShapeData = parseShapeData(shape);
|
|
82
|
+
const getSnapshot = () => latestShapeData;
|
|
83
|
+
const subscribe = (onStoreChange) => shapeSubscribe(shape, () => {
|
|
84
|
+
latestShapeData = parseShapeData(shape);
|
|
85
|
+
onStoreChange();
|
|
86
|
+
});
|
|
87
|
+
return () => {
|
|
88
|
+
return useSyncExternalStoreWithSelector(
|
|
89
|
+
subscribe,
|
|
90
|
+
getSnapshot,
|
|
91
|
+
getSnapshot,
|
|
92
|
+
selector
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
}, [shape, selector]);
|
|
96
|
+
return useShapeData();
|
|
93
97
|
}
|
|
94
98
|
export {
|
|
95
99
|
getShape,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/client'\nimport React
|
|
1
|
+
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/client'\nimport React from 'react'\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'\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\nexport interface 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\nfunction identity<T>(arg: T): T {\n return arg\n}\n\ninterface UseShapeOptions<Selection> extends ShapeStreamOptions {\n selector?: (value: UseShapeResult) => Selection\n}\n\nexport function useShape<Selection = UseShapeResult>({\n selector = identity as (arg: UseShapeResult) => Selection,\n ...options\n}: UseShapeOptions<Selection>): Selection {\n const shapeStream = getShapeStream(options as ShapeStreamOptions)\n const shape = getShape(shapeStream)\n\n const useShapeData = React.useMemo(() => {\n let latestShapeData = parseShapeData(shape)\n const getSnapshot = () => latestShapeData\n const subscribe = (onStoreChange: () => void) =>\n shapeSubscribe(shape, () => {\n latestShapeData = parseShapeData(shape)\n onStoreChange()\n })\n\n return () => {\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getSnapshot,\n selector\n )\n }\n }, [shape, selector])\n\n return useShapeData()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AAAA,EAEE;AAAA,EACA;AAAA,OAEK;AACP,OAAO,WAAW;AAClB,SAAS,wCAAwC;AAEjD,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;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,SAAS,SAAY,KAAW;AAC9B,SAAO;AACT;AAMO,SAAS,SAAqC,IAGX;AAHW,eACnD;AAAA,eAAW;AAAA,EAtGb,IAqGqD,IAEhD,oBAFgD,IAEhD;AAAA,IADH;AAAA;AAGA,QAAM,cAAc,eAAe,OAA6B;AAChE,QAAM,QAAQ,SAAS,WAAW;AAElC,QAAM,eAAe,MAAM,QAAQ,MAAM;AACvC,QAAI,kBAAkB,eAAe,KAAK;AAC1C,UAAM,cAAc,MAAM;AAC1B,UAAM,YAAY,CAAC,kBACjB,eAAe,OAAO,MAAM;AAC1B,wBAAkB,eAAe,KAAK;AACtC,oBAAc;AAAA,IAChB,CAAC;AAEH,WAAO,MAAM;AACX,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,SAAO,aAAa;AACtB;","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
Shape,
|
|
40
40
|
ShapeStream
|
|
41
41
|
} from "@electric-sql/client";
|
|
42
|
-
import React
|
|
42
|
+
import React from "react";
|
|
43
43
|
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector.js";
|
|
44
44
|
var streamCache = /* @__PURE__ */ new Map();
|
|
45
45
|
var shapeCache = /* @__PURE__ */ new Map();
|
|
@@ -88,7 +88,9 @@ function parseShapeData(shape) {
|
|
|
88
88
|
error: shape.error
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
function identity(arg) {
|
|
92
|
+
return arg;
|
|
93
|
+
}
|
|
92
94
|
function useShape(_a) {
|
|
93
95
|
var _b = _a, {
|
|
94
96
|
selector = identity
|
|
@@ -97,21 +99,23 @@ function useShape(_a) {
|
|
|
97
99
|
]);
|
|
98
100
|
const shapeStream = getShapeStream(options);
|
|
99
101
|
const shape = getShape(shapeStream);
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
102
|
+
const useShapeData = React.useMemo(() => {
|
|
103
|
+
let latestShapeData = parseShapeData(shape);
|
|
104
|
+
const getSnapshot = () => latestShapeData;
|
|
105
|
+
const subscribe = (onStoreChange) => shapeSubscribe(shape, () => {
|
|
106
|
+
latestShapeData = parseShapeData(shape);
|
|
107
|
+
onStoreChange();
|
|
108
|
+
});
|
|
109
|
+
return () => {
|
|
110
|
+
return useSyncExternalStoreWithSelector(
|
|
111
|
+
subscribe,
|
|
112
|
+
getSnapshot,
|
|
113
|
+
getSnapshot,
|
|
114
|
+
selector
|
|
115
|
+
);
|
|
116
|
+
};
|
|
117
|
+
}, [shape, selector]);
|
|
118
|
+
return useShapeData();
|
|
115
119
|
}
|
|
116
120
|
export {
|
|
117
121
|
getShape,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/client'\nimport React
|
|
1
|
+
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import {\n Value,\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n} from '@electric-sql/client'\nimport React from 'react'\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'\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\nexport interface 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\nfunction identity<T>(arg: T): T {\n return arg\n}\n\ninterface UseShapeOptions<Selection> extends ShapeStreamOptions {\n selector?: (value: UseShapeResult) => Selection\n}\n\nexport function useShape<Selection = UseShapeResult>({\n selector = identity as (arg: UseShapeResult) => Selection,\n ...options\n}: UseShapeOptions<Selection>): Selection {\n const shapeStream = getShapeStream(options as ShapeStreamOptions)\n const shape = getShape(shapeStream)\n\n const useShapeData = React.useMemo(() => {\n let latestShapeData = parseShapeData(shape)\n const getSnapshot = () => latestShapeData\n const subscribe = (onStoreChange: () => void) =>\n shapeSubscribe(shape, () => {\n latestShapeData = parseShapeData(shape)\n onStoreChange()\n })\n\n return () => {\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getSnapshot,\n selector\n )\n }\n }, [shape, selector])\n\n return useShapeData()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EAEE;AAAA,EACA;AAAA,OAEK;AACP,OAAO,WAAW;AAClB,SAAS,wCAAwC;AAEjD,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;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,SAAS,SAAY,KAAW;AAC9B,SAAO;AACT;AAMO,SAAS,SAAqC,IAGX;AAHW,eACnD;AAAA,eAAW;AAAA,EAtGb,IAqGqD,IAEhD,oBAFgD,IAEhD;AAAA,IADH;AAAA;AAGA,QAAM,cAAc,eAAe,OAA6B;AAChE,QAAM,QAAQ,SAAS,WAAW;AAElC,QAAM,eAAe,MAAM,QAAQ,MAAM;AACvC,QAAI,kBAAkB,eAAe,KAAK;AAC1C,UAAM,cAAc,MAAM;AAC1B,UAAM,YAAY,CAAC,kBACjB,eAAe,OAAO,MAAM;AAC1B,wBAAkB,eAAe,KAAK;AACtC,oBAAc;AAAA,IAChB,CAAC;AAEH,WAAO,MAAM;AACX,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,SAAO,aAAa;AACtB;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electric-sql/react",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
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/client": "0.3.
|
|
34
|
+
"@electric-sql/client": "0.3.3"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@testing-library/react": "^16.0.0",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"eslint-config-prettier": "^9.1.0",
|
|
47
47
|
"eslint-plugin-prettier": "^5.1.3",
|
|
48
48
|
"glob": "^10.3.10",
|
|
49
|
-
"
|
|
49
|
+
"jsdom": "^25.0.0",
|
|
50
50
|
"pg": "^8.12.0",
|
|
51
51
|
"prettier": "^3.3.2",
|
|
52
52
|
"react": "^18.3.1",
|
package/src/react-hooks.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ShapeStream,
|
|
5
5
|
ShapeStreamOptions,
|
|
6
6
|
} from '@electric-sql/client'
|
|
7
|
-
import React
|
|
7
|
+
import React from 'react'
|
|
8
8
|
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'
|
|
9
9
|
|
|
10
10
|
const streamCache = new Map<string, ShapeStream>()
|
|
@@ -55,7 +55,7 @@ export function getShape(shapeStream: ShapeStream): Shape {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
interface UseShapeResult {
|
|
58
|
+
export interface UseShapeResult {
|
|
59
59
|
/**
|
|
60
60
|
* The array of rows that make up the Shape.
|
|
61
61
|
* @type {{ [key: string]: Value }[]}
|
|
@@ -91,34 +91,39 @@ function parseShapeData(shape: Shape): UseShapeResult {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
function identity<T>(arg: T): T {
|
|
95
|
+
return arg
|
|
96
|
+
}
|
|
95
97
|
|
|
96
98
|
interface UseShapeOptions<Selection> extends ShapeStreamOptions {
|
|
97
99
|
selector?: (value: UseShapeResult) => Selection
|
|
98
100
|
}
|
|
99
101
|
|
|
100
102
|
export function useShape<Selection = UseShapeResult>({
|
|
101
|
-
selector = identity as
|
|
103
|
+
selector = identity as (arg: UseShapeResult) => Selection,
|
|
102
104
|
...options
|
|
103
105
|
}: UseShapeOptions<Selection>): Selection {
|
|
104
106
|
const shapeStream = getShapeStream(options as ShapeStreamOptions)
|
|
105
107
|
const shape = getShape(shapeStream)
|
|
106
108
|
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
109
|
+
const useShapeData = React.useMemo(() => {
|
|
110
|
+
let latestShapeData = parseShapeData(shape)
|
|
111
|
+
const getSnapshot = () => latestShapeData
|
|
112
|
+
const subscribe = (onStoreChange: () => void) =>
|
|
113
|
+
shapeSubscribe(shape, () => {
|
|
114
|
+
latestShapeData = parseShapeData(shape)
|
|
115
|
+
onStoreChange()
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
return () => {
|
|
119
|
+
return useSyncExternalStoreWithSelector(
|
|
120
|
+
subscribe,
|
|
121
|
+
getSnapshot,
|
|
122
|
+
getSnapshot,
|
|
123
|
+
selector
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
}, [shape, selector])
|
|
127
|
+
|
|
128
|
+
return useShapeData()
|
|
124
129
|
}
|