@electric-sql/react 0.0.6 → 0.0.8
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/package.json +18 -7
- package/src/index.ts +1 -0
- package/src/react-hooks.tsx +167 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +0 -1
- package/dist/react-hooks.d.ts +0 -35
- package/dist/react-hooks.js +0 -130
- package/dist/react-hooks.js.map +0 -1
- package/dist/react-hooks.jsx +0 -111
package/package.json
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electric-sql/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "React hooks for ElectricSQL",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/cjs/index.cjs",
|
|
7
|
+
"module": "dist/index.legacy-esm.js",
|
|
6
8
|
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"./package.json": "./package.json",
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"default": "./dist/cjs/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
7
17
|
"files": [
|
|
8
|
-
"dist"
|
|
18
|
+
"dist",
|
|
19
|
+
"src"
|
|
9
20
|
],
|
|
21
|
+
"sideEffects": false,
|
|
10
22
|
"repository": {
|
|
11
23
|
"type": "git",
|
|
12
24
|
"url": "git+https://github.com/electric-sql/electric-next.git"
|
|
@@ -18,12 +30,14 @@
|
|
|
18
30
|
},
|
|
19
31
|
"homepage": "https://next.electric-sql.com",
|
|
20
32
|
"dependencies": {
|
|
21
|
-
"
|
|
33
|
+
"use-sync-external-store": "^1.2.2",
|
|
34
|
+
"@electric-sql/next": "0.0.8"
|
|
22
35
|
},
|
|
23
36
|
"devDependencies": {
|
|
24
37
|
"@testing-library/react": "^16.0.0",
|
|
25
38
|
"@types/pg": "^8.11.6",
|
|
26
39
|
"@types/react": "^18.3.3",
|
|
40
|
+
"@types/use-sync-external-store": "^0.0.6",
|
|
27
41
|
"@types/uuid": "^10.0.0",
|
|
28
42
|
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
|
29
43
|
"@typescript-eslint/parser": "^7.14.1",
|
|
@@ -50,9 +64,6 @@
|
|
|
50
64
|
"optional": true
|
|
51
65
|
}
|
|
52
66
|
},
|
|
53
|
-
"exports": {
|
|
54
|
-
".": "./dist/index.js"
|
|
55
|
-
},
|
|
56
67
|
"typesVersions": {
|
|
57
68
|
"*": {
|
|
58
69
|
"*": [
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './react-hooks'
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import {
|
|
2
|
+
JsonSerializable,
|
|
3
|
+
Shape,
|
|
4
|
+
ShapeStream,
|
|
5
|
+
ShapeStreamOptions,
|
|
6
|
+
} from '@electric-sql/next'
|
|
7
|
+
import React, { createContext, useCallback, useContext, useRef } from 'react'
|
|
8
|
+
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector'
|
|
9
|
+
|
|
10
|
+
interface ShapeContextType {
|
|
11
|
+
getShape: (shapeStream: ShapeStream) => Shape
|
|
12
|
+
getShapeStream: (options: ShapeStreamOptions) => ShapeStream
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Create a Context
|
|
16
|
+
const ShapesContext = createContext<ShapeContextType | null>(null)
|
|
17
|
+
|
|
18
|
+
const streamCache = new Map<string, ShapeStream>()
|
|
19
|
+
const shapeCache = new Map<ShapeStream, Shape>()
|
|
20
|
+
|
|
21
|
+
export async function preloadShape(
|
|
22
|
+
options: ShapeStreamOptions
|
|
23
|
+
): Promise<Shape> {
|
|
24
|
+
const shapeStream = getShapeStream(options)
|
|
25
|
+
const shape = getShape(shapeStream)
|
|
26
|
+
await shape.value
|
|
27
|
+
return shape
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function sortedOptionsHash(options: ShapeStreamOptions): string {
|
|
31
|
+
const shapeDef = JSON.stringify(
|
|
32
|
+
options.shape,
|
|
33
|
+
Object.keys(options.shape).sort()
|
|
34
|
+
)
|
|
35
|
+
// eslint-disable-next-line
|
|
36
|
+
const { shape, ...optionsWithoutShapeDef } = options
|
|
37
|
+
const allOptions = JSON.stringify(
|
|
38
|
+
optionsWithoutShapeDef,
|
|
39
|
+
Object.keys(options).sort()
|
|
40
|
+
)
|
|
41
|
+
const shapeHash = shapeDef + allOptions
|
|
42
|
+
|
|
43
|
+
return shapeHash
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function getShapeStream(options: ShapeStreamOptions): ShapeStream {
|
|
47
|
+
const shapeHash = sortedOptionsHash(options)
|
|
48
|
+
|
|
49
|
+
// If the stream is already cached, return
|
|
50
|
+
if (streamCache.has(shapeHash)) {
|
|
51
|
+
// Return the ShapeStream
|
|
52
|
+
return streamCache.get(shapeHash)!
|
|
53
|
+
} else {
|
|
54
|
+
const newShapeStream = new ShapeStream(options)
|
|
55
|
+
|
|
56
|
+
streamCache.set(shapeHash, newShapeStream)
|
|
57
|
+
|
|
58
|
+
// Return the created shape
|
|
59
|
+
return newShapeStream
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function getShape(shapeStream: ShapeStream): Shape {
|
|
64
|
+
// If the stream is already cached, return
|
|
65
|
+
if (shapeCache.has(shapeStream)) {
|
|
66
|
+
// Return the ShapeStream
|
|
67
|
+
return shapeCache.get(shapeStream)!
|
|
68
|
+
} else {
|
|
69
|
+
const newShape = new Shape(shapeStream)
|
|
70
|
+
|
|
71
|
+
shapeCache.set(shapeStream, newShape)
|
|
72
|
+
|
|
73
|
+
// Return the created shape
|
|
74
|
+
return newShape
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface ShapeProviderProps {
|
|
79
|
+
children: React.ReactNode
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Shapes Provider Component
|
|
83
|
+
export function ShapesProvider({ children }: ShapeProviderProps): JSX.Element {
|
|
84
|
+
// Provide the context value
|
|
85
|
+
return (
|
|
86
|
+
<ShapesContext.Provider value={{ getShape, getShapeStream }}>
|
|
87
|
+
{children}
|
|
88
|
+
</ShapesContext.Provider>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function useShapeContext() {
|
|
93
|
+
const context = useContext(ShapesContext)
|
|
94
|
+
if (!context) {
|
|
95
|
+
throw new Error(`useShapeContext must be used within a ShapeProvider`)
|
|
96
|
+
}
|
|
97
|
+
return context
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface UseShapeResult {
|
|
101
|
+
/**
|
|
102
|
+
* The array of rows that make up the Shape.
|
|
103
|
+
* @type {{ [key: string]: JsonSerializable }[]}
|
|
104
|
+
*/
|
|
105
|
+
data: { [key: string]: JsonSerializable }[]
|
|
106
|
+
/**
|
|
107
|
+
* The Shape instance used by this useShape
|
|
108
|
+
* @type(Shape)
|
|
109
|
+
*/
|
|
110
|
+
shape: Shape
|
|
111
|
+
error: Shape[`error`]
|
|
112
|
+
isError: boolean
|
|
113
|
+
/**
|
|
114
|
+
* Has the ShapeStream caught up with the replication log from Postgres.
|
|
115
|
+
*/
|
|
116
|
+
isUpToDate: boolean
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function shapeSubscribe(shape: Shape, callback: () => void) {
|
|
120
|
+
const unsubscribe = shape.subscribe(callback)
|
|
121
|
+
return () => {
|
|
122
|
+
unsubscribe()
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function parseShapeData(shape: Shape): UseShapeResult {
|
|
127
|
+
return {
|
|
128
|
+
data: [...shape.valueSync.values()],
|
|
129
|
+
isUpToDate: shape.isUpToDate,
|
|
130
|
+
isError: shape.error !== false,
|
|
131
|
+
shape,
|
|
132
|
+
error: shape.error,
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const identity = (arg: unknown) => arg
|
|
137
|
+
|
|
138
|
+
interface UseShapeOptions<Selection> extends ShapeStreamOptions {
|
|
139
|
+
selector?: (value: UseShapeResult) => Selection
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function useShape<Selection = UseShapeResult>({
|
|
143
|
+
selector = identity as never,
|
|
144
|
+
...options
|
|
145
|
+
}: UseShapeOptions<Selection>): Selection {
|
|
146
|
+
const { getShape, getShapeStream } = useShapeContext()
|
|
147
|
+
const shapeStream = getShapeStream(options as ShapeStreamOptions)
|
|
148
|
+
const shape = getShape(shapeStream)
|
|
149
|
+
|
|
150
|
+
const latestShapeData = useRef(parseShapeData(shape))
|
|
151
|
+
const getSnapshot = React.useCallback(() => latestShapeData.current, [])
|
|
152
|
+
const shapeData = useSyncExternalStoreWithSelector(
|
|
153
|
+
useCallback(
|
|
154
|
+
(onStoreChange) =>
|
|
155
|
+
shapeSubscribe(shape, () => {
|
|
156
|
+
latestShapeData.current = parseShapeData(shape)
|
|
157
|
+
onStoreChange()
|
|
158
|
+
}),
|
|
159
|
+
[shape]
|
|
160
|
+
),
|
|
161
|
+
getSnapshot,
|
|
162
|
+
getSnapshot,
|
|
163
|
+
selector
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
return shapeData
|
|
167
|
+
}
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './react-hooks';
|
package/dist/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './react-hooks';
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './react-hooks'\n"],"mappings":"AAAA,cAAc;","names":[]}
|
package/dist/react-hooks.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Shape, ShapeStream, ShapeStreamOptions, JsonSerializable } from '@electric-sql/next';
|
|
3
|
-
interface ShapeContextType {
|
|
4
|
-
getShape: (shapeStream: ShapeStream) => Shape;
|
|
5
|
-
getShapeStream: (options: ShapeStreamOptions) => ShapeStream;
|
|
6
|
-
}
|
|
7
|
-
export declare function preloadShape(options: ShapeStreamOptions): Promise<Shape>;
|
|
8
|
-
export declare function sortedOptionsHash(options: ShapeStreamOptions): string;
|
|
9
|
-
export declare function getShapeStream(options: ShapeStreamOptions): ShapeStream;
|
|
10
|
-
export declare function getShape(shapeStream: ShapeStream): Shape;
|
|
11
|
-
interface ShapeProviderProps {
|
|
12
|
-
children: React.ReactNode;
|
|
13
|
-
}
|
|
14
|
-
export declare function ShapesProvider({ children }: ShapeProviderProps): JSX.Element;
|
|
15
|
-
export declare function useShapeContext(): ShapeContextType;
|
|
16
|
-
interface UseShapeResult {
|
|
17
|
-
/**
|
|
18
|
-
* The array of rows that make up the Shape.
|
|
19
|
-
* @type {JsonSerializable}
|
|
20
|
-
*/
|
|
21
|
-
data: JsonSerializable[];
|
|
22
|
-
/**
|
|
23
|
-
* The Shape instance used by this useShape
|
|
24
|
-
* @type(Shape)
|
|
25
|
-
*/
|
|
26
|
-
shape: Shape;
|
|
27
|
-
error: Shape[`error`];
|
|
28
|
-
isError: boolean;
|
|
29
|
-
/**
|
|
30
|
-
* Has the ShapeStream caught up with the replication log from Postgres.
|
|
31
|
-
*/
|
|
32
|
-
isUpToDate: boolean;
|
|
33
|
-
}
|
|
34
|
-
export declare function useShape(options: ShapeStreamOptions): UseShapeResult;
|
|
35
|
-
export {};
|
package/dist/react-hooks.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
2
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
3
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
4
|
-
var __objRest = (source, exclude) => {
|
|
5
|
-
var target = {};
|
|
6
|
-
for (var prop in source)
|
|
7
|
-
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
8
|
-
target[prop] = source[prop];
|
|
9
|
-
if (source != null && __getOwnPropSymbols)
|
|
10
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
11
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
12
|
-
target[prop] = source[prop];
|
|
13
|
-
}
|
|
14
|
-
return target;
|
|
15
|
-
};
|
|
16
|
-
var __async = (__this, __arguments, generator) => {
|
|
17
|
-
return new Promise((resolve, reject) => {
|
|
18
|
-
var fulfilled = (value) => {
|
|
19
|
-
try {
|
|
20
|
-
step(generator.next(value));
|
|
21
|
-
} catch (e) {
|
|
22
|
-
reject(e);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
var rejected = (value) => {
|
|
26
|
-
try {
|
|
27
|
-
step(generator.throw(value));
|
|
28
|
-
} catch (e) {
|
|
29
|
-
reject(e);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
33
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
import React, { createContext, useEffect, useContext, useState } from "react";
|
|
37
|
-
import {
|
|
38
|
-
Shape,
|
|
39
|
-
ShapeStream
|
|
40
|
-
} from "@electric-sql/next";
|
|
41
|
-
const ShapesContext = createContext(null);
|
|
42
|
-
const streamCache = /* @__PURE__ */ new Map();
|
|
43
|
-
const shapeCache = /* @__PURE__ */ new Map();
|
|
44
|
-
function preloadShape(options) {
|
|
45
|
-
return __async(this, null, function* () {
|
|
46
|
-
const shapeStream = getShapeStream(options);
|
|
47
|
-
const shape = getShape(shapeStream);
|
|
48
|
-
yield shape.value;
|
|
49
|
-
return shape;
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
function sortedOptionsHash(options) {
|
|
53
|
-
const shapeDef = JSON.stringify(
|
|
54
|
-
options.shape,
|
|
55
|
-
Object.keys(options.shape).sort()
|
|
56
|
-
);
|
|
57
|
-
const _a = options, { shape } = _a, optionsWithoutShapeDef = __objRest(_a, ["shape"]);
|
|
58
|
-
const allOptions = JSON.stringify(
|
|
59
|
-
optionsWithoutShapeDef,
|
|
60
|
-
Object.keys(options).sort()
|
|
61
|
-
);
|
|
62
|
-
const shapeHash = shapeDef + allOptions;
|
|
63
|
-
return shapeHash;
|
|
64
|
-
}
|
|
65
|
-
function getShapeStream(options) {
|
|
66
|
-
const shapeHash = sortedOptionsHash(options);
|
|
67
|
-
if (streamCache.has(shapeHash)) {
|
|
68
|
-
return streamCache.get(shapeHash);
|
|
69
|
-
} else {
|
|
70
|
-
const newShapeStream = new ShapeStream(options);
|
|
71
|
-
streamCache.set(shapeHash, newShapeStream);
|
|
72
|
-
return newShapeStream;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function getShape(shapeStream) {
|
|
76
|
-
if (shapeCache.has(shapeStream)) {
|
|
77
|
-
return shapeCache.get(shapeStream);
|
|
78
|
-
} else {
|
|
79
|
-
const newShape = new Shape(shapeStream);
|
|
80
|
-
shapeCache.set(shapeStream, newShape);
|
|
81
|
-
return newShape;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
function ShapesProvider({ children }) {
|
|
85
|
-
return /* @__PURE__ */ React.createElement(ShapesContext.Provider, { value: { getShape, getShapeStream } }, children);
|
|
86
|
-
}
|
|
87
|
-
function useShapeContext() {
|
|
88
|
-
const context = useContext(ShapesContext);
|
|
89
|
-
if (!context) {
|
|
90
|
-
throw new Error(`useShapeContext must be used within a ShapeProvider`);
|
|
91
|
-
}
|
|
92
|
-
return context;
|
|
93
|
-
}
|
|
94
|
-
function useShape(options) {
|
|
95
|
-
const { getShape: getShape2, getShapeStream: getShapeStream2 } = useShapeContext();
|
|
96
|
-
const shapeStream = getShapeStream2(options);
|
|
97
|
-
const shape = getShape2(shapeStream);
|
|
98
|
-
const [shapeData, setShapeData] = useState({
|
|
99
|
-
data: [...shape.valueSync.values()],
|
|
100
|
-
isUpToDate: shape.isUpToDate,
|
|
101
|
-
isError: shape.error !== false,
|
|
102
|
-
shape,
|
|
103
|
-
error: shape.error
|
|
104
|
-
});
|
|
105
|
-
useEffect(() => {
|
|
106
|
-
const unsubscribe = shape.subscribe((map) => {
|
|
107
|
-
setShapeData({
|
|
108
|
-
data: [...map.values()],
|
|
109
|
-
isUpToDate: shape.isUpToDate,
|
|
110
|
-
isError: shape.error !== false,
|
|
111
|
-
shape,
|
|
112
|
-
error: shape.error
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
return () => {
|
|
116
|
-
unsubscribe();
|
|
117
|
-
};
|
|
118
|
-
}, []);
|
|
119
|
-
return shapeData;
|
|
120
|
-
}
|
|
121
|
-
export {
|
|
122
|
-
ShapesProvider,
|
|
123
|
-
getShape,
|
|
124
|
-
getShapeStream,
|
|
125
|
-
preloadShape,
|
|
126
|
-
sortedOptionsHash,
|
|
127
|
-
useShape,
|
|
128
|
-
useShapeContext
|
|
129
|
-
};
|
|
130
|
-
//# sourceMappingURL=react-hooks.js.map
|
package/dist/react-hooks.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react-hooks.tsx"],"sourcesContent":["import React, { createContext, useEffect, useContext, useState } from 'react'\nimport {\n Shape,\n ShapeStream,\n ShapeStreamOptions,\n JsonSerializable,\n} from '@electric-sql/next'\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 const shapeDef = JSON.stringify(\n options.shape,\n Object.keys(options.shape).sort()\n )\n // eslint-disable-next-line\n const { shape, ...optionsWithoutShapeDef } = options\n const allOptions = JSON.stringify(\n optionsWithoutShapeDef,\n Object.keys(options).sort()\n )\n const shapeHash = shapeDef + allOptions\n\n return shapeHash\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 {JsonSerializable}\n */\n data: JsonSerializable[]\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\nexport function useShape(options: ShapeStreamOptions): UseShapeResult {\n const { getShape, getShapeStream } = useShapeContext()\n const shapeStream = getShapeStream(options)\n const shape = getShape(shapeStream)\n const [shapeData, setShapeData] = useState<UseShapeResult>({\n data: [...shape.valueSync.values()],\n isUpToDate: shape.isUpToDate,\n isError: shape.error !== false,\n shape,\n error: shape.error,\n })\n\n useEffect(() => {\n // Subscribe to updates.\n const unsubscribe = shape.subscribe((map) => {\n setShapeData({\n data: [...map.values()],\n isUpToDate: shape.isUpToDate,\n isError: shape.error !== false,\n shape,\n error: shape.error,\n })\n })\n\n return () => {\n unsubscribe()\n }\n }, [])\n\n return shapeData\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,SAAS,eAAe,WAAW,YAAY,gBAAgB;AACtE;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAQP,MAAM,gBAAgB,cAAuC,IAAI;AAEjE,MAAM,cAAc,oBAAI,IAAyB;AACjD,MAAM,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,QAAM,WAAW,KAAK;AAAA,IACpB,QAAQ;AAAA,IACR,OAAO,KAAK,QAAQ,KAAK,EAAE,KAAK;AAAA,EAClC;AAEA,QAA6C,cAArC,QAlCV,IAkC+C,IAA3B,mCAA2B,IAA3B,CAAV;AACR,QAAM,aAAa,KAAK;AAAA,IACtB;AAAA,IACA,OAAO,KAAK,OAAO,EAAE,KAAK;AAAA,EAC5B;AACA,QAAM,YAAY,WAAW;AAE7B,SAAO;AACT;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;AAqBO,SAAS,SAAS,SAA6C;AACpE,QAAM,EAAE,UAAAA,WAAU,gBAAAC,gBAAe,IAAI,gBAAgB;AACrD,QAAM,cAAcA,gBAAe,OAAO;AAC1C,QAAM,QAAQD,UAAS,WAAW;AAClC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAyB;AAAA,IACzD,MAAM,CAAC,GAAG,MAAM,UAAU,OAAO,CAAC;AAAA,IAClC,YAAY,MAAM;AAAA,IAClB,SAAS,MAAM,UAAU;AAAA,IACzB;AAAA,IACA,OAAO,MAAM;AAAA,EACf,CAAC;AAED,YAAU,MAAM;AAEd,UAAM,cAAc,MAAM,UAAU,CAAC,QAAQ;AAC3C,mBAAa;AAAA,QACX,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC;AAAA,QACtB,YAAY,MAAM;AAAA,QAClB,SAAS,MAAM,UAAU;AAAA,QACzB;AAAA,QACA,OAAO,MAAM;AAAA,MACf,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;","names":["getShape","getShapeStream"]}
|
package/dist/react-hooks.jsx
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
|
-
var t = {};
|
|
12
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
13
|
-
t[p] = s[p];
|
|
14
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
15
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
17
|
-
t[p[i]] = s[p[i]];
|
|
18
|
-
}
|
|
19
|
-
return t;
|
|
20
|
-
};
|
|
21
|
-
import React, { createContext, useEffect, useContext, useState } from 'react';
|
|
22
|
-
import { Shape, ShapeStream, } from '@electric-sql/next';
|
|
23
|
-
// Create a Context
|
|
24
|
-
const ShapesContext = createContext(null);
|
|
25
|
-
const streamCache = new Map();
|
|
26
|
-
const shapeCache = new Map();
|
|
27
|
-
export function preloadShape(options) {
|
|
28
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
-
const shapeStream = getShapeStream(options);
|
|
30
|
-
const shape = getShape(shapeStream);
|
|
31
|
-
yield shape.value;
|
|
32
|
-
return shape;
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
export function sortedOptionsHash(options) {
|
|
36
|
-
const shapeDef = JSON.stringify(options.shape, Object.keys(options.shape).sort());
|
|
37
|
-
// eslint-disable-next-line
|
|
38
|
-
const { shape } = options, optionsWithoutShapeDef = __rest(options, ["shape"]);
|
|
39
|
-
const allOptions = JSON.stringify(optionsWithoutShapeDef, Object.keys(options).sort());
|
|
40
|
-
const shapeHash = shapeDef + allOptions;
|
|
41
|
-
return shapeHash;
|
|
42
|
-
}
|
|
43
|
-
export function getShapeStream(options) {
|
|
44
|
-
const shapeHash = sortedOptionsHash(options);
|
|
45
|
-
// If the stream is already cached, return
|
|
46
|
-
if (streamCache.has(shapeHash)) {
|
|
47
|
-
// Return the ShapeStream
|
|
48
|
-
return streamCache.get(shapeHash);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
const newShapeStream = new ShapeStream(options);
|
|
52
|
-
streamCache.set(shapeHash, newShapeStream);
|
|
53
|
-
// Return the created shape
|
|
54
|
-
return newShapeStream;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
export function getShape(shapeStream) {
|
|
58
|
-
// If the stream is already cached, return
|
|
59
|
-
if (shapeCache.has(shapeStream)) {
|
|
60
|
-
// Return the ShapeStream
|
|
61
|
-
return shapeCache.get(shapeStream);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
const newShape = new Shape(shapeStream);
|
|
65
|
-
shapeCache.set(shapeStream, newShape);
|
|
66
|
-
// Return the created shape
|
|
67
|
-
return newShape;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
// Shapes Provider Component
|
|
71
|
-
export function ShapesProvider({ children }) {
|
|
72
|
-
// Provide the context value
|
|
73
|
-
return (<ShapesContext.Provider value={{ getShape, getShapeStream }}>
|
|
74
|
-
{children}
|
|
75
|
-
</ShapesContext.Provider>);
|
|
76
|
-
}
|
|
77
|
-
export function useShapeContext() {
|
|
78
|
-
const context = useContext(ShapesContext);
|
|
79
|
-
if (!context) {
|
|
80
|
-
throw new Error(`useShapeContext must be used within a ShapeProvider`);
|
|
81
|
-
}
|
|
82
|
-
return context;
|
|
83
|
-
}
|
|
84
|
-
export function useShape(options) {
|
|
85
|
-
const { getShape, getShapeStream } = useShapeContext();
|
|
86
|
-
const shapeStream = getShapeStream(options);
|
|
87
|
-
const shape = getShape(shapeStream);
|
|
88
|
-
const [shapeData, setShapeData] = useState({
|
|
89
|
-
data: [...shape.valueSync.values()],
|
|
90
|
-
isUpToDate: shape.isUpToDate,
|
|
91
|
-
isError: shape.error !== false,
|
|
92
|
-
shape,
|
|
93
|
-
error: shape.error,
|
|
94
|
-
});
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
// Subscribe to updates.
|
|
97
|
-
const unsubscribe = shape.subscribe((map) => {
|
|
98
|
-
setShapeData({
|
|
99
|
-
data: [...map.values()],
|
|
100
|
-
isUpToDate: shape.isUpToDate,
|
|
101
|
-
isError: shape.error !== false,
|
|
102
|
-
shape,
|
|
103
|
-
error: shape.error,
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
return () => {
|
|
107
|
-
unsubscribe();
|
|
108
|
-
};
|
|
109
|
-
}, []);
|
|
110
|
-
return shapeData;
|
|
111
|
-
}
|