@shapeshift-labs/frontier-react 0.1.0
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/LICENSE +21 -0
- package/README.md +219 -0
- package/benchmarks/package-bench.mjs +124 -0
- package/dist/adapters.d.ts +6 -0
- package/dist/adapters.d.ts.map +1 -0
- package/dist/adapters.js +35 -0
- package/dist/adapters.js.map +1 -0
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +26 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/store.d.ts +6 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +96 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +97 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shapeshift Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Frontier React
|
|
2
|
+
|
|
3
|
+
React external-store hooks and adapters for Frontier state, cache, and CRDT surfaces.
|
|
4
|
+
|
|
5
|
+
This package sits above the Frontier runtime packages. It gives React apps a small `useSyncExternalStore` bridge without making core Frontier packages depend on React.
|
|
6
|
+
|
|
7
|
+
- npm: [`@shapeshift-labs/frontier-react`](https://www.npmjs.com/package/@shapeshift-labs/frontier-react)
|
|
8
|
+
- source: [`siliconjungle/-shapeshift-labs-frontier-react`](https://github.com/siliconjungle/-shapeshift-labs-frontier-react)
|
|
9
|
+
- license: MIT
|
|
10
|
+
|
|
11
|
+
## Related Packages
|
|
12
|
+
|
|
13
|
+
- [`@shapeshift-labs/frontier`](https://www.npmjs.com/package/@shapeshift-labs/frontier): core JSON diff/apply primitives used by the patch store.
|
|
14
|
+
- [`@shapeshift-labs/frontier-state`](https://www.npmjs.com/package/@shapeshift-labs/frontier-state): patch-routed app-state engine.
|
|
15
|
+
- [`@shapeshift-labs/frontier-state-cache`](https://www.npmjs.com/package/@shapeshift-labs/frontier-state-cache): normalized query/result cache.
|
|
16
|
+
- [`@shapeshift-labs/frontier-crdt`](https://www.npmjs.com/package/@shapeshift-labs/frontier-crdt): CRDT document layer.
|
|
17
|
+
- [`@shapeshift-labs/frontier-crdt-sync`](https://www.npmjs.com/package/@shapeshift-labs/frontier-crdt-sync): sync/repo/provider layer for CRDT documents.
|
|
18
|
+
|
|
19
|
+
Package source repositories:
|
|
20
|
+
|
|
21
|
+
- [`siliconjungle/-shapeshift-labs-frontier`](https://github.com/siliconjungle/-shapeshift-labs-frontier)
|
|
22
|
+
- [`siliconjungle/-shapeshift-labs-frontier-state`](https://github.com/siliconjungle/-shapeshift-labs-frontier-state)
|
|
23
|
+
- [`siliconjungle/-shapeshift-labs-frontier-state-cache`](https://github.com/siliconjungle/-shapeshift-labs-frontier-state-cache)
|
|
24
|
+
- [`siliconjungle/-shapeshift-labs-frontier-crdt`](https://github.com/siliconjungle/-shapeshift-labs-frontier-crdt)
|
|
25
|
+
- [`siliconjungle/-shapeshift-labs-frontier-crdt-sync`](https://github.com/siliconjungle/-shapeshift-labs-frontier-crdt-sync)
|
|
26
|
+
- [`siliconjungle/-shapeshift-labs-frontier-react`](https://github.com/siliconjungle/-shapeshift-labs-frontier-react)
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npm install react @shapeshift-labs/frontier @shapeshift-labs/frontier-react
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Install the Frontier packages you want to wrap separately, for example `@shapeshift-labs/frontier-state`, `@shapeshift-labs/frontier-state-cache`, or `@shapeshift-labs/frontier-crdt`.
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
Patch store:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { createFrontierPatchStore, useFrontierStore } from '@shapeshift-labs/frontier-react';
|
|
42
|
+
|
|
43
|
+
const store = createFrontierPatchStore({
|
|
44
|
+
todos: [{ id: 'a', text: 'Ship', done: false }]
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
function TodoCount() {
|
|
48
|
+
const count = useFrontierStore(store, (state) => state.todos.length);
|
|
49
|
+
return <span>{count}</span>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
store.update((state) => ({
|
|
53
|
+
...state,
|
|
54
|
+
todos: state.todos.concat({ id: 'b', text: 'Document', done: false })
|
|
55
|
+
}));
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
State engine:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { createStateEngine } from '@shapeshift-labs/frontier-state';
|
|
62
|
+
import { createFrontierStateStore, useFrontierSelector } from '@shapeshift-labs/frontier-react';
|
|
63
|
+
|
|
64
|
+
const engine = createStateEngine({ count: 0 });
|
|
65
|
+
const store = createFrontierStateStore(engine);
|
|
66
|
+
|
|
67
|
+
function Counter() {
|
|
68
|
+
const count = useFrontierSelector(store, (state) => state.count);
|
|
69
|
+
return <button onClick={() => engine.commit({ count: count + 1 })}>{count}</button>;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Query cache:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import { createQueryCache } from '@shapeshift-labs/frontier-state-cache';
|
|
77
|
+
import { createFrontierQueryStore, useFrontierStore } from '@shapeshift-labs/frontier-react';
|
|
78
|
+
|
|
79
|
+
const cache = createQueryCache();
|
|
80
|
+
const todos = createFrontierQueryStore(cache, ['todos']);
|
|
81
|
+
|
|
82
|
+
function Todos() {
|
|
83
|
+
const rows = useFrontierStore(todos) ?? [];
|
|
84
|
+
return rows.map((row) => <div key={row.id}>{row.text}</div>);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
CRDT state document:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { createCrdtStateEngine } from '@shapeshift-labs/frontier-crdt';
|
|
92
|
+
import { createFrontierCrdtStore, useFrontierStore } from '@shapeshift-labs/frontier-react';
|
|
93
|
+
|
|
94
|
+
const doc = createCrdtStateEngine({ actorId: 'alice' });
|
|
95
|
+
const store = createFrontierCrdtStore(doc);
|
|
96
|
+
|
|
97
|
+
function Title() {
|
|
98
|
+
const title = useFrontierStore(store, (state) => state?.title ?? '');
|
|
99
|
+
return <h1>{title}</h1>;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## API
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import {
|
|
107
|
+
createFrontierPatchStore,
|
|
108
|
+
createFrontierStoreAdapter,
|
|
109
|
+
createFrontierStateStore,
|
|
110
|
+
createFrontierQueryStore,
|
|
111
|
+
createFrontierEntityStore,
|
|
112
|
+
createFrontierCrdtStore,
|
|
113
|
+
useFrontierSnapshot,
|
|
114
|
+
useFrontierStore,
|
|
115
|
+
useFrontierSelector
|
|
116
|
+
} from '@shapeshift-labs/frontier-react';
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `useFrontierStore(store, selector?, equals?)`
|
|
120
|
+
|
|
121
|
+
Subscribes to a Frontier external store with React `useSyncExternalStore`. If a selector is supplied, the hook returns the selected value and reuses the previous selected value when `equals(previous, next)` returns true.
|
|
122
|
+
|
|
123
|
+
### `useFrontierSelector(store, selector, equals?)`
|
|
124
|
+
|
|
125
|
+
Alias for selected store reads. Use this when a component should render only from a small part of a larger Frontier snapshot.
|
|
126
|
+
|
|
127
|
+
### `useFrontierSnapshot(store)`
|
|
128
|
+
|
|
129
|
+
Returns the whole current snapshot from a Frontier external store.
|
|
130
|
+
|
|
131
|
+
### `createFrontierPatchStore(initial, options?)`
|
|
132
|
+
|
|
133
|
+
Creates a small immutable JSON store backed by Frontier `diff()` and `applyPatchImmutable()`.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
const store = createFrontierPatchStore({ count: 0 });
|
|
137
|
+
const patch = store.setSnapshot({ count: 1 });
|
|
138
|
+
store.applyPatch(patch);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `createFrontierStoreAdapter(source)`
|
|
142
|
+
|
|
143
|
+
Adapts any structural source with `getSnapshot`, `get`, `value`, or `toJSON` plus `subscribe` or `watch` into the store shape consumed by the hooks.
|
|
144
|
+
|
|
145
|
+
### `createFrontierStateStore(engine, options?)`
|
|
146
|
+
|
|
147
|
+
Wraps a Frontier state engine-like object with `get()` and `watch()`.
|
|
148
|
+
|
|
149
|
+
### `createFrontierQueryStore(cache, key)`
|
|
150
|
+
|
|
151
|
+
Wraps a Frontier state-cache query using `getQueryData()` and `watchQuery()`.
|
|
152
|
+
|
|
153
|
+
### `createFrontierEntityStore(cache, entity)`
|
|
154
|
+
|
|
155
|
+
Wraps a Frontier state-cache entity using `getEntity()` and `watchEntity()`.
|
|
156
|
+
|
|
157
|
+
### `createFrontierCrdtStore(doc, options?)`
|
|
158
|
+
|
|
159
|
+
Wraps a CRDT state document-like object with `get()` or `toJSON()` and optional `watch()`.
|
|
160
|
+
|
|
161
|
+
## Subpath Imports
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
import { createFrontierPatchStore } from '@shapeshift-labs/frontier-react/store';
|
|
165
|
+
import { useFrontierStore } from '@shapeshift-labs/frontier-react/hooks';
|
|
166
|
+
import { createFrontierQueryStore } from '@shapeshift-labs/frontier-react/adapters';
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Package Scope
|
|
170
|
+
|
|
171
|
+
This package owns:
|
|
172
|
+
|
|
173
|
+
- React `useSyncExternalStore` hooks for Frontier stores.
|
|
174
|
+
- A tiny Frontier patch store for local React state.
|
|
175
|
+
- Structural adapters for state engines, query caches, entities, and CRDT documents.
|
|
176
|
+
- React-facing tests, fuzzers, and package-local benchmarks.
|
|
177
|
+
|
|
178
|
+
It does not own:
|
|
179
|
+
|
|
180
|
+
- Frontier diff/apply semantics.
|
|
181
|
+
- State engine routing, query cache storage, CRDT documents, sync providers, WebSocket transports, rich text, or logging.
|
|
182
|
+
- React components, styling, Suspense data loading, server components, router bindings, auth, or persistence.
|
|
183
|
+
|
|
184
|
+
## TypeScript
|
|
185
|
+
|
|
186
|
+
The package ships ESM JavaScript plus `.d.ts` declarations for root, `./store`, `./hooks`, and `./adapters`. React is a peer dependency, so apps keep control of their React version.
|
|
187
|
+
|
|
188
|
+
## Validation
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
npm test
|
|
192
|
+
npm run fuzz
|
|
193
|
+
npm run bench
|
|
194
|
+
npm run pack:dry
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The package test suite covers root and subpath imports, patch-store commits, patch application, React hook rendering, state-engine adapters, query/entity cache adapters, CRDT document adapters, and randomized patch-store replay.
|
|
198
|
+
|
|
199
|
+
## Benchmarks
|
|
200
|
+
|
|
201
|
+
Run the package-local benchmark:
|
|
202
|
+
|
|
203
|
+
```sh
|
|
204
|
+
npm run bench
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Latest local package benchmark on Node v26.1.0, darwin arm64, 7 rounds:
|
|
208
|
+
|
|
209
|
+
| Fixture | Median | p95 |
|
|
210
|
+
| --- | ---: | ---: |
|
|
211
|
+
| React patch store replace, 1k rows one edit | 200.74 us | 214.39 us |
|
|
212
|
+
| External store adapter notify 10 listeners | 0.07 us | 0.09 us |
|
|
213
|
+
| State engine adapter snapshot read | 0.01 us | 0.01 us |
|
|
214
|
+
|
|
215
|
+
These are Frontier-only package measurements, not competitor comparisons.
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { performance } from 'node:perf_hooks';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import {
|
|
6
|
+
createFrontierPatchStore,
|
|
7
|
+
createFrontierStateStore,
|
|
8
|
+
createFrontierStoreAdapter
|
|
9
|
+
} from '../dist/index.js';
|
|
10
|
+
|
|
11
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const rootDir = path.resolve(__dirname, '..');
|
|
13
|
+
const args = parseArgs(process.argv.slice(2));
|
|
14
|
+
const rounds = readPositiveInt(args.rounds, 9);
|
|
15
|
+
const outPath = args.out ? path.resolve(rootDir, args.out) : null;
|
|
16
|
+
let sink = 0;
|
|
17
|
+
|
|
18
|
+
const baseRows = Array.from({ length: 1000 }, (_value, index) => ({ id: `r${index}`, value: index, done: false }));
|
|
19
|
+
const patchStore = createFrontierPatchStore({ rows: baseRows, tick: 0 });
|
|
20
|
+
const adapterSource = createAdapterSource({ count: 0 });
|
|
21
|
+
const adapter = createFrontierStoreAdapter(adapterSource);
|
|
22
|
+
const stateStore = createFrontierStateStore(createStateEngineLike({ value: 0 }));
|
|
23
|
+
|
|
24
|
+
const rows = [
|
|
25
|
+
runRow('React patch store replace, 1k rows one edit', 500, () => {
|
|
26
|
+
const current = patchStore.getSnapshot();
|
|
27
|
+
const rows = current.rows.slice();
|
|
28
|
+
rows[17] = { ...rows[17], done: !rows[17].done };
|
|
29
|
+
sink += patchStore.setSnapshot({ rows, tick: current.tick + 1 }).length;
|
|
30
|
+
}),
|
|
31
|
+
runRow('External store adapter notify 10 listeners', 50000, () => {
|
|
32
|
+
sink += adapterSource.emit();
|
|
33
|
+
}),
|
|
34
|
+
runRow('State engine adapter snapshot read', 200000, () => {
|
|
35
|
+
sink += stateStore.getSnapshot().value;
|
|
36
|
+
})
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
finish('@shapeshift-labs/frontier-react', rows);
|
|
40
|
+
|
|
41
|
+
function measure(fn, inner) {
|
|
42
|
+
for (let i = 0; i < inner; i++) fn();
|
|
43
|
+
const samples = new Array(rounds);
|
|
44
|
+
for (let roundIndex = 0; roundIndex < rounds; roundIndex++) {
|
|
45
|
+
const start = performance.now();
|
|
46
|
+
for (let i = 0; i < inner; i++) fn();
|
|
47
|
+
samples[roundIndex] = ((performance.now() - start) * 1000) / inner;
|
|
48
|
+
}
|
|
49
|
+
samples.sort((left, right) => left - right);
|
|
50
|
+
return { median: percentile(samples, 0.5), p95: percentile(samples, 0.95) };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function runRow(name, inner, fn) {
|
|
54
|
+
const timing = measure(fn, inner);
|
|
55
|
+
return { fixture: name, medianUs: round(timing.median), p95Us: round(timing.p95) };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function createAdapterSource(initial) {
|
|
59
|
+
let value = initial;
|
|
60
|
+
const listeners = new Set();
|
|
61
|
+
for (let i = 0; i < 10; i++) listeners.add(() => { sink++; });
|
|
62
|
+
return {
|
|
63
|
+
getSnapshot: () => value,
|
|
64
|
+
subscribe(listener) {
|
|
65
|
+
listeners.add(listener);
|
|
66
|
+
return () => listeners.delete(listener);
|
|
67
|
+
},
|
|
68
|
+
emit() {
|
|
69
|
+
value = { count: value.count + 1 };
|
|
70
|
+
for (const listener of listeners) listener();
|
|
71
|
+
return value.count;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function createStateEngineLike(initial) {
|
|
77
|
+
const listeners = new Set();
|
|
78
|
+
return {
|
|
79
|
+
get: () => initial,
|
|
80
|
+
watch(_path, listener) {
|
|
81
|
+
listeners.add(listener);
|
|
82
|
+
return { unsubscribe: () => listeners.delete(listener) };
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function finish(packageName, rows) {
|
|
88
|
+
const report = {
|
|
89
|
+
package: packageName,
|
|
90
|
+
version: readPackageVersion(),
|
|
91
|
+
generatedAt: new Date().toISOString(),
|
|
92
|
+
node: process.version,
|
|
93
|
+
platform: process.platform + ' ' + process.arch,
|
|
94
|
+
rounds,
|
|
95
|
+
rows
|
|
96
|
+
};
|
|
97
|
+
if (outPath) {
|
|
98
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
99
|
+
fs.writeFileSync(outPath, JSON.stringify(report, null, 2) + '\n');
|
|
100
|
+
}
|
|
101
|
+
printReport(report);
|
|
102
|
+
if (sink === 42) console.log('sink=' + sink);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function printReport(report) {
|
|
106
|
+
console.log(report.package + ' package benchmark');
|
|
107
|
+
console.log('Node ' + report.node + ' on ' + report.platform + ', rounds=' + rounds);
|
|
108
|
+
console.log('These are Frontier-only package measurements, not competitor comparisons.');
|
|
109
|
+
console.log('');
|
|
110
|
+
console.log(padRight('Fixture', 48) + padLeft('Median', 12) + padLeft('p95', 11));
|
|
111
|
+
for (const row of report.rows) {
|
|
112
|
+
console.log(padRight(row.fixture, 48) + padLeft(formatUs(row.medianUs), 12) + padLeft(formatUs(row.p95Us), 11));
|
|
113
|
+
}
|
|
114
|
+
if (outPath) console.log('\nwrote ' + path.relative(rootDir, outPath));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function percentile(sorted, fraction) { return sorted[Math.min(sorted.length - 1, Math.max(0, Math.ceil(sorted.length * fraction) - 1))]; }
|
|
118
|
+
function readPackageVersion() { return JSON.parse(fs.readFileSync(path.join(rootDir, 'package.json'), 'utf8')).version; }
|
|
119
|
+
function parseArgs(argv) { const out = {}; for (let i = 0; i < argv.length; i++) { const arg = argv[i]; if (arg === '--rounds') out.rounds = argv[++i]; else if (arg === '--out') out.out = argv[++i]; else if (arg === '--help' || arg === '-h') { console.log('Usage: npm run bench -- [--rounds 9] [--out benchmarks/results/package-bench.json]'); process.exit(0); } else throw new Error('unknown argument: ' + arg); } return out; }
|
|
120
|
+
function readPositiveInt(value, fallback) { if (value === undefined) return fallback; const number = Number(value); if (!Number.isInteger(number) || number <= 0) throw new Error('expected positive integer, got ' + value); return number; }
|
|
121
|
+
function round(value) { return Math.round(value * 100) / 100; }
|
|
122
|
+
function formatUs(value) { return value >= 1000 ? (value / 1000).toFixed(2) + ' ms' : value.toFixed(2) + ' us'; }
|
|
123
|
+
function padRight(value, width) { return String(value).padEnd(width); }
|
|
124
|
+
function padLeft(value, width) { return String(value).padStart(width); }
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FrontierCrdtDocumentLike, FrontierEntityCacheLike, FrontierExternalStore, FrontierQueryCacheLike, FrontierStateEngineLike, FrontierStateStoreOptions } from './types.js';
|
|
2
|
+
export declare function createFrontierStateStore<TSnapshot>(engine: FrontierStateEngineLike<TSnapshot>, options?: FrontierStateStoreOptions): FrontierExternalStore<TSnapshot>;
|
|
3
|
+
export declare function createFrontierQueryStore<TSnapshot, TQueryKey>(cache: FrontierQueryCacheLike<TSnapshot, TQueryKey>, key: TQueryKey): FrontierExternalStore<TSnapshot | undefined>;
|
|
4
|
+
export declare function createFrontierEntityStore<TSnapshot, TEntity>(cache: FrontierEntityCacheLike<TSnapshot, TEntity>, entity: TEntity): FrontierExternalStore<TSnapshot | undefined>;
|
|
5
|
+
export declare function createFrontierCrdtStore<TSnapshot>(doc: FrontierCrdtDocumentLike<TSnapshot>, options?: FrontierStateStoreOptions): FrontierExternalStore<TSnapshot>;
|
|
6
|
+
//# sourceMappingURL=adapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAEpB,wBAAgB,wBAAwB,CAAC,SAAS,EAChD,MAAM,EAAE,uBAAuB,CAAC,SAAS,CAAC,EAC1C,OAAO,GAAE,yBAA8B,GACtC,qBAAqB,CAAC,SAAS,CAAC,CAMlC;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,SAAS,EAC3D,KAAK,EAAE,sBAAsB,CAAC,SAAS,EAAE,SAAS,CAAC,EACnD,GAAG,EAAE,SAAS,GACb,qBAAqB,CAAC,SAAS,GAAG,SAAS,CAAC,CAK9C;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,OAAO,EAC1D,KAAK,EAAE,uBAAuB,CAAC,SAAS,EAAE,OAAO,CAAC,EAClD,MAAM,EAAE,OAAO,GACd,qBAAqB,CAAC,SAAS,GAAG,SAAS,CAAC,CAK9C;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAC/C,GAAG,EAAE,wBAAwB,CAAC,SAAS,CAAC,EACxC,OAAO,GAAE,yBAA8B,GACtC,qBAAqB,CAAC,SAAS,CAAC,CAUlC"}
|
package/dist/adapters.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createFrontierStoreAdapter, normalizeUnsubscribe } from './store.js';
|
|
2
|
+
export function createFrontierStateStore(engine, options = {}) {
|
|
3
|
+
const path = options.path ?? '';
|
|
4
|
+
return createFrontierStoreAdapter({
|
|
5
|
+
getSnapshot: () => engine.get(),
|
|
6
|
+
subscribe: (listener) => normalizeUnsubscribe(engine.watch(path, listener))
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
export function createFrontierQueryStore(cache, key) {
|
|
10
|
+
return createFrontierStoreAdapter({
|
|
11
|
+
getSnapshot: () => cache.getQueryData(key),
|
|
12
|
+
subscribe: (listener) => normalizeUnsubscribe(cache.watchQuery(key, listener))
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export function createFrontierEntityStore(cache, entity) {
|
|
16
|
+
return createFrontierStoreAdapter({
|
|
17
|
+
getSnapshot: () => cache.getEntity(entity),
|
|
18
|
+
subscribe: (listener) => normalizeUnsubscribe(cache.watchEntity(entity, listener))
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function createFrontierCrdtStore(doc, options = {}) {
|
|
22
|
+
const path = options.path ?? '';
|
|
23
|
+
return createFrontierStoreAdapter({
|
|
24
|
+
getSnapshot: () => {
|
|
25
|
+
if (typeof doc.get === 'function')
|
|
26
|
+
return doc.get();
|
|
27
|
+
if (typeof doc.toJSON === 'function')
|
|
28
|
+
return doc.toJSON();
|
|
29
|
+
throw new TypeError('Frontier CRDT store needs get() or toJSON()');
|
|
30
|
+
},
|
|
31
|
+
subscribe: (listener) => typeof doc.watch === 'function' ? normalizeUnsubscribe(doc.watch(path, listener)) : noop
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function noop() { }
|
|
35
|
+
//# sourceMappingURL=adapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAU9E,MAAM,UAAU,wBAAwB,CACtC,MAA0C,EAC1C,UAAqC,EAAE;IAEvC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,OAAO,0BAA0B,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE;QAC/B,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;KAC5E,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,KAAmD,EACnD,GAAc;IAEd,OAAO,0BAA0B,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC;QAC1C,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;KAC/E,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAAkD,EAClD,MAAe;IAEf,OAAO,0BAA0B,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC;QAC1C,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;KACnF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,GAAwC,EACxC,UAAqC,EAAE;IAEvC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,OAAO,0BAA0B,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE;YAChB,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,UAAU;gBAAE,OAAO,GAAG,CAAC,GAAG,EAAE,CAAC;YACpD,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU;gBAAE,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC;YAC1D,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;QACrE,CAAC;QACD,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;KAClH,CAAC,CAAC;AACL,CAAC;AAED,SAAS,IAAI,KAAU,CAAC"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FrontierEquality, FrontierExternalStore, FrontierSelector } from './types.js';
|
|
2
|
+
export declare function useFrontierSnapshot<TSnapshot>(store: FrontierExternalStore<TSnapshot>): TSnapshot;
|
|
3
|
+
export declare function useFrontierStore<TSnapshot>(store: FrontierExternalStore<TSnapshot>): TSnapshot;
|
|
4
|
+
export declare function useFrontierStore<TSnapshot, TSelected>(store: FrontierExternalStore<TSnapshot>, selector: FrontierSelector<TSnapshot, TSelected>, equals?: FrontierEquality<TSelected>): TSelected;
|
|
5
|
+
export declare function useFrontierSelector<TSnapshot, TSelected>(store: FrontierExternalStore<TSnapshot>, selector: FrontierSelector<TSnapshot, TSelected>, equals?: FrontierEquality<TSelected>): TSelected;
|
|
6
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAIpB,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,KAAK,EAAE,qBAAqB,CAAC,SAAS,CAAC,GAAG,SAAS,CAEjG;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EACxC,KAAK,EAAE,qBAAqB,CAAC,SAAS,CAAC,GACtC,SAAS,CAAC;AACb,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,EACnD,KAAK,EAAE,qBAAqB,CAAC,SAAS,CAAC,EACvC,QAAQ,EAAE,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,EAChD,MAAM,CAAC,EAAE,gBAAgB,CAAC,SAAS,CAAC,GACnC,SAAS,CAAC;AAiBb,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,SAAS,EACtD,KAAK,EAAE,qBAAqB,CAAC,SAAS,CAAC,EACvC,QAAQ,EAAE,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,EAChD,MAAM,CAAC,EAAE,gBAAgB,CAAC,SAAS,CAAC,GACnC,SAAS,CAEX"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useMemo, useSyncExternalStore } from 'react';
|
|
2
|
+
const identity = (value) => value;
|
|
3
|
+
export function useFrontierSnapshot(store) {
|
|
4
|
+
return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot);
|
|
5
|
+
}
|
|
6
|
+
export function useFrontierStore(store, selector = identity, equals = Object.is) {
|
|
7
|
+
const getSelectedSnapshot = useMemo(() => createSelectedSnapshotReader(store.getSnapshot, selector, equals), [store, selector, equals]);
|
|
8
|
+
const getSelectedServerSnapshot = useMemo(() => createSelectedSnapshotReader(store.getServerSnapshot, selector, equals), [store, selector, equals]);
|
|
9
|
+
return useSyncExternalStore(store.subscribe, getSelectedSnapshot, getSelectedServerSnapshot);
|
|
10
|
+
}
|
|
11
|
+
export function useFrontierSelector(store, selector, equals) {
|
|
12
|
+
return useFrontierStore(store, selector, equals);
|
|
13
|
+
}
|
|
14
|
+
function createSelectedSnapshotReader(readSnapshot, selector, equals) {
|
|
15
|
+
let hasSelection = false;
|
|
16
|
+
let previousSelection;
|
|
17
|
+
return () => {
|
|
18
|
+
const nextSelection = selector(readSnapshot());
|
|
19
|
+
if (hasSelection && equals(previousSelection, nextSelection))
|
|
20
|
+
return previousSelection;
|
|
21
|
+
hasSelection = true;
|
|
22
|
+
previousSelection = nextSelection;
|
|
23
|
+
return nextSelection;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAOtD,MAAM,QAAQ,GAAG,CAAI,KAAQ,EAAK,EAAE,CAAC,KAAK,CAAC;AAE3C,MAAM,UAAU,mBAAmB,CAAY,KAAuC;IACpF,OAAO,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3F,CAAC;AAUD,MAAM,UAAU,gBAAgB,CAC9B,KAAuC,EACvC,WAAmD,QAAkD,EACrG,SAAsC,MAAM,CAAC,EAAE;IAE/C,MAAM,mBAAmB,GAAG,OAAO,CACjC,GAAG,EAAE,CAAC,4BAA4B,CAAC,KAAK,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,EACvE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAC1B,CAAC;IACF,MAAM,yBAAyB,GAAG,OAAO,CACvC,GAAG,EAAE,CAAC,4BAA4B,CAAC,KAAK,CAAC,iBAAiB,EAAE,QAAQ,EAAE,MAAM,CAAC,EAC7E,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAC1B,CAAC;IACF,OAAO,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,mBAAmB,EAAE,yBAAyB,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAAuC,EACvC,QAAgD,EAChD,MAAoC;IAEpC,OAAO,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,4BAA4B,CACnC,YAA6B,EAC7B,QAAgD,EAChD,MAAmC;IAEnC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,iBAA4B,CAAC;IACjC,OAAO,GAAG,EAAE;QACV,MAAM,aAAa,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;QAC/C,IAAI,YAAY,IAAI,MAAM,CAAC,iBAAkB,EAAE,aAAa,CAAC;YAAE,OAAO,iBAAkB,CAAC;QACzF,YAAY,GAAG,IAAI,CAAC;QACpB,iBAAiB,GAAG,aAAa,CAAC;QAClC,OAAO,aAAa,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { useFrontierSelector, useFrontierSnapshot, useFrontierStore } from './hooks.js';
|
|
2
|
+
export { createFrontierPatchStore, createFrontierStoreAdapter, normalizeUnsubscribe } from './store.js';
|
|
3
|
+
export { createFrontierCrdtStore, createFrontierEntityStore, createFrontierQueryStore, createFrontierStateStore } from './adapters.js';
|
|
4
|
+
export type { FrontierCrdtDocumentLike, FrontierEntityCacheLike, FrontierEquality, FrontierExternalStore, FrontierJsonSnapshotUpdater, FrontierPatchStore, FrontierPatchStoreOptions, FrontierQueryCacheLike, FrontierSelector, FrontierSnapshotUpdater, FrontierStateEngineLike, FrontierStateStoreOptions, FrontierStoreAdapterSource, FrontierStoreListener, FrontierStoreUnsubscribe, FrontierSubscriptionHandle, FrontierWatchPath } from './types.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,kBAAkB,EAClB,yBAAyB,EACzB,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,0BAA0B,EAC1B,iBAAiB,EAClB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { useFrontierSelector, useFrontierSnapshot, useFrontierStore } from './hooks.js';
|
|
2
|
+
export { createFrontierPatchStore, createFrontierStoreAdapter, normalizeUnsubscribe } from './store.js';
|
|
3
|
+
export { createFrontierCrdtStore, createFrontierEntityStore, createFrontierQueryStore, createFrontierStateStore } from './adapters.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,eAAe,CAAC"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { JsonValue } from '@shapeshift-labs/frontier';
|
|
2
|
+
import type { FrontierExternalStore, FrontierPatchStore, FrontierPatchStoreOptions, FrontierStoreAdapterSource, FrontierStoreUnsubscribe } from './types.js';
|
|
3
|
+
export declare function createFrontierPatchStore<TSnapshot extends JsonValue>(initial: TSnapshot, options?: FrontierPatchStoreOptions<TSnapshot>): FrontierPatchStore<TSnapshot>;
|
|
4
|
+
export declare function createFrontierStoreAdapter<TSnapshot>(source: FrontierStoreAdapterSource<TSnapshot>): FrontierExternalStore<TSnapshot>;
|
|
5
|
+
export declare function normalizeUnsubscribe(value: unknown): FrontierStoreUnsubscribe;
|
|
6
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAS,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EACV,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,0BAA0B,EAE1B,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,wBAAwB,CAAC,SAAS,SAAS,SAAS,EAClE,OAAO,EAAE,SAAS,EAClB,OAAO,GAAE,yBAAyB,CAAC,SAAS,CAAM,GACjD,kBAAkB,CAAC,SAAS,CAAC,CAqD/B;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAClD,MAAM,EAAE,0BAA0B,CAAC,SAAS,CAAC,GAC5C,qBAAqB,CAAC,SAAS,CAAC,CAWlC;AAUD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAQ7E"}
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { applyPatchImmutable, cloneJson, diff, equalsJsonFast } from '@shapeshift-labs/frontier';
|
|
2
|
+
export function createFrontierPatchStore(initial, options = {}) {
|
|
3
|
+
const clone = options.clone ?? ((value) => cloneJson(value));
|
|
4
|
+
const equals = options.equals ?? ((left, right) => equalsJsonFast(left, right));
|
|
5
|
+
const recordPatches = options.recordPatches !== false;
|
|
6
|
+
const listeners = new Set();
|
|
7
|
+
const patchLog = [];
|
|
8
|
+
let snapshot = clone(initial);
|
|
9
|
+
function emit() {
|
|
10
|
+
const current = Array.from(listeners);
|
|
11
|
+
for (let i = 0; i < current.length; i++)
|
|
12
|
+
current[i]();
|
|
13
|
+
}
|
|
14
|
+
function commit(nextInput) {
|
|
15
|
+
const next = clone(nextInput);
|
|
16
|
+
if (equals(snapshot, next))
|
|
17
|
+
return [];
|
|
18
|
+
const patch = diff(snapshot, next);
|
|
19
|
+
snapshot = next;
|
|
20
|
+
if (recordPatches && patch.length > 0)
|
|
21
|
+
patchLog[patchLog.length] = patch;
|
|
22
|
+
emit();
|
|
23
|
+
return patch;
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
getSnapshot: () => snapshot,
|
|
27
|
+
getServerSnapshot: () => snapshot,
|
|
28
|
+
subscribe(listener) {
|
|
29
|
+
listeners.add(listener);
|
|
30
|
+
return () => {
|
|
31
|
+
listeners.delete(listener);
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
setSnapshot(next) {
|
|
35
|
+
return commit(typeof next === 'function' ? next(snapshot) : next);
|
|
36
|
+
},
|
|
37
|
+
replace(next) {
|
|
38
|
+
return commit(next);
|
|
39
|
+
},
|
|
40
|
+
update(updater) {
|
|
41
|
+
return commit(updater(snapshot));
|
|
42
|
+
},
|
|
43
|
+
applyPatch(patch) {
|
|
44
|
+
if (patch.length === 0)
|
|
45
|
+
return snapshot;
|
|
46
|
+
snapshot = applyPatchImmutable(snapshot, patch);
|
|
47
|
+
if (recordPatches)
|
|
48
|
+
patchLog[patchLog.length] = patch;
|
|
49
|
+
emit();
|
|
50
|
+
return snapshot;
|
|
51
|
+
},
|
|
52
|
+
getPatchLog: () => patchLog,
|
|
53
|
+
clearPatchLog() {
|
|
54
|
+
patchLog.length = 0;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function createFrontierStoreAdapter(source) {
|
|
59
|
+
const getSnapshot = resolveSnapshotReader(source);
|
|
60
|
+
return {
|
|
61
|
+
getSnapshot,
|
|
62
|
+
getServerSnapshot: source.getServerSnapshot ?? getSnapshot,
|
|
63
|
+
subscribe(listener) {
|
|
64
|
+
if (typeof source.subscribe === 'function')
|
|
65
|
+
return normalizeUnsubscribe(source.subscribe(listener));
|
|
66
|
+
if (typeof source.watch === 'function')
|
|
67
|
+
return normalizeUnsubscribe(source.watch('', listener));
|
|
68
|
+
return noop;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function resolveSnapshotReader(source) {
|
|
73
|
+
if (typeof source.getSnapshot === 'function')
|
|
74
|
+
return () => source.getSnapshot();
|
|
75
|
+
if (typeof source.get === 'function')
|
|
76
|
+
return () => source.get();
|
|
77
|
+
if (typeof source.value === 'function')
|
|
78
|
+
return () => source.value();
|
|
79
|
+
if (typeof source.toJSON === 'function')
|
|
80
|
+
return () => source.toJSON();
|
|
81
|
+
throw new TypeError('Frontier React store adapter source needs getSnapshot(), get(), value(), or toJSON()');
|
|
82
|
+
}
|
|
83
|
+
export function normalizeUnsubscribe(value) {
|
|
84
|
+
if (typeof value === 'function')
|
|
85
|
+
return value;
|
|
86
|
+
if (value !== null && typeof value === 'object') {
|
|
87
|
+
const subscription = value;
|
|
88
|
+
if (typeof subscription.unsubscribe === 'function')
|
|
89
|
+
return () => subscription.unsubscribe();
|
|
90
|
+
if (typeof subscription.dispose === 'function')
|
|
91
|
+
return () => subscription.dispose();
|
|
92
|
+
}
|
|
93
|
+
return noop;
|
|
94
|
+
}
|
|
95
|
+
function noop() { }
|
|
96
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { JsonValue, Patch } from '@shapeshift-labs/frontier';
|
|
2
|
+
export type FrontierStoreListener = () => void;
|
|
3
|
+
export type FrontierStoreUnsubscribe = () => void;
|
|
4
|
+
export type FrontierEquality<T> = (previous: T, next: T) => boolean;
|
|
5
|
+
export type FrontierSelector<TSnapshot, TSelected> = (snapshot: TSnapshot) => TSelected;
|
|
6
|
+
export type FrontierSnapshotUpdater<T> = T | ((previous: T) => T);
|
|
7
|
+
export type FrontierJsonSnapshotUpdater<T extends JsonValue> = T | ((previous: T) => T);
|
|
8
|
+
export type FrontierWatchPath = string | readonly (string | number)[];
|
|
9
|
+
export interface FrontierExternalStore<TSnapshot> {
|
|
10
|
+
getSnapshot(): TSnapshot;
|
|
11
|
+
getServerSnapshot(): TSnapshot;
|
|
12
|
+
subscribe(listener: FrontierStoreListener): FrontierStoreUnsubscribe;
|
|
13
|
+
}
|
|
14
|
+
export interface FrontierPatchStore<TSnapshot extends JsonValue> extends FrontierExternalStore<TSnapshot> {
|
|
15
|
+
setSnapshot(next: FrontierJsonSnapshotUpdater<TSnapshot>): Patch;
|
|
16
|
+
replace(next: TSnapshot): Patch;
|
|
17
|
+
update(updater: (previous: TSnapshot) => TSnapshot): Patch;
|
|
18
|
+
applyPatch(patch: Patch): TSnapshot;
|
|
19
|
+
getPatchLog(): readonly Patch[];
|
|
20
|
+
clearPatchLog(): void;
|
|
21
|
+
}
|
|
22
|
+
export interface FrontierPatchStoreOptions<TSnapshot extends JsonValue> {
|
|
23
|
+
clone?: (value: TSnapshot) => TSnapshot;
|
|
24
|
+
equals?: FrontierEquality<TSnapshot>;
|
|
25
|
+
recordPatches?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface FrontierStoreAdapterSource<TSnapshot> {
|
|
28
|
+
getSnapshot?: () => TSnapshot;
|
|
29
|
+
getServerSnapshot?: () => TSnapshot;
|
|
30
|
+
get?: () => TSnapshot;
|
|
31
|
+
value?: () => TSnapshot;
|
|
32
|
+
toJSON?: () => TSnapshot;
|
|
33
|
+
subscribe?: (listener: FrontierStoreListener) => FrontierStoreUnsubscribe | FrontierSubscriptionHandle | void;
|
|
34
|
+
watch?: (path: FrontierWatchPath, listener: (...args: unknown[]) => void) => FrontierSubscriptionHandle | FrontierStoreUnsubscribe | void;
|
|
35
|
+
}
|
|
36
|
+
export interface FrontierSubscriptionHandle {
|
|
37
|
+
unsubscribe?: () => void;
|
|
38
|
+
dispose?: () => void;
|
|
39
|
+
}
|
|
40
|
+
export interface FrontierStateEngineLike<TSnapshot> {
|
|
41
|
+
get(): TSnapshot;
|
|
42
|
+
watch(path: FrontierWatchPath, listener: (...args: unknown[]) => void): FrontierSubscriptionHandle | FrontierStoreUnsubscribe | void;
|
|
43
|
+
}
|
|
44
|
+
export interface FrontierStateStoreOptions {
|
|
45
|
+
path?: FrontierWatchPath;
|
|
46
|
+
}
|
|
47
|
+
export interface FrontierQueryCacheLike<TSnapshot, TQueryKey = unknown> {
|
|
48
|
+
getQueryData(key: TQueryKey): TSnapshot | undefined;
|
|
49
|
+
watchQuery(key: TQueryKey, listener: (...args: unknown[]) => void): FrontierSubscriptionHandle | FrontierStoreUnsubscribe | void;
|
|
50
|
+
}
|
|
51
|
+
export interface FrontierEntityCacheLike<TSnapshot, TEntity = unknown> {
|
|
52
|
+
getEntity(entity: TEntity): TSnapshot | undefined;
|
|
53
|
+
watchEntity(entity: TEntity, listener: (...args: unknown[]) => void): FrontierSubscriptionHandle | FrontierStoreUnsubscribe | void;
|
|
54
|
+
}
|
|
55
|
+
export interface FrontierCrdtDocumentLike<TSnapshot> {
|
|
56
|
+
get?: () => TSnapshot;
|
|
57
|
+
toJSON?: () => TSnapshot;
|
|
58
|
+
watch?: (path: FrontierWatchPath, listener: (...args: unknown[]) => void) => FrontierSubscriptionHandle | FrontierStoreUnsubscribe | void;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@shapeshift-labs/frontier-react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React external-store hooks and adapters for Frontier state, cache, and CRDT surfaces.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+ssh://git@github.com/siliconjungle/-shapeshift-labs-frontier-react.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/siliconjungle/-shapeshift-labs-frontier-react#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/siliconjungle/-shapeshift-labs-frontier-react/issues"
|
|
15
|
+
},
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js",
|
|
22
|
+
"default": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./store": {
|
|
25
|
+
"types": "./dist/store.d.ts",
|
|
26
|
+
"import": "./dist/store.js",
|
|
27
|
+
"default": "./dist/store.js"
|
|
28
|
+
},
|
|
29
|
+
"./hooks": {
|
|
30
|
+
"types": "./dist/hooks.d.ts",
|
|
31
|
+
"import": "./dist/hooks.js",
|
|
32
|
+
"default": "./dist/hooks.js"
|
|
33
|
+
},
|
|
34
|
+
"./adapters": {
|
|
35
|
+
"types": "./dist/adapters.d.ts",
|
|
36
|
+
"import": "./dist/adapters.js",
|
|
37
|
+
"default": "./dist/adapters.js"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"typesVersions": {
|
|
42
|
+
"*": {
|
|
43
|
+
"store": [
|
|
44
|
+
"./dist/store.d.ts"
|
|
45
|
+
],
|
|
46
|
+
"hooks": [
|
|
47
|
+
"./dist/hooks.d.ts"
|
|
48
|
+
],
|
|
49
|
+
"adapters": [
|
|
50
|
+
"./dist/adapters.d.ts"
|
|
51
|
+
],
|
|
52
|
+
"*": [
|
|
53
|
+
"./dist/index.d.ts"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"files": [
|
|
58
|
+
"dist",
|
|
59
|
+
"README.md",
|
|
60
|
+
"LICENSE",
|
|
61
|
+
"benchmarks/package-bench.mjs"
|
|
62
|
+
],
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=18"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"@shapeshift-labs/frontier": "^0.1.5"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"react": ">=18.0.0"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@types/node": "^24.10.1",
|
|
74
|
+
"@types/react": "^18.3.12",
|
|
75
|
+
"react": "^18.3.1",
|
|
76
|
+
"react-test-renderer": "^18.3.1",
|
|
77
|
+
"typescript": "^6.0.3"
|
|
78
|
+
},
|
|
79
|
+
"scripts": {
|
|
80
|
+
"build": "node build.mjs",
|
|
81
|
+
"test": "npm run build && npm run typecheck && node test/smoke.mjs && node test/fuzz.mjs --cases 500",
|
|
82
|
+
"prepack": "npm run test",
|
|
83
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p test/tsconfig.json --noEmit",
|
|
84
|
+
"fuzz": "npm run build && node test/fuzz.mjs",
|
|
85
|
+
"bench": "npm run build && node benchmarks/package-bench.mjs",
|
|
86
|
+
"pack:dry": "npm pack --dry-run"
|
|
87
|
+
},
|
|
88
|
+
"keywords": [
|
|
89
|
+
"frontier",
|
|
90
|
+
"react",
|
|
91
|
+
"useSyncExternalStore",
|
|
92
|
+
"external-store",
|
|
93
|
+
"crdt",
|
|
94
|
+
"state"
|
|
95
|
+
],
|
|
96
|
+
"author": "james addison"
|
|
97
|
+
}
|