effect-atom-svelte 0.1.0 → 0.1.2
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/README.md +11 -9
- package/dist/Hooks.svelte.js +22 -6
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# effect-atom-svelte
|
|
2
2
|
|
|
3
|
-
Svelte 5 bindings for Effect Atom (`effect/reactivity`)
|
|
3
|
+
Svelte 5 bindings for Effect Atom (`effect/reactivity`): hooks with a reactive `current`, async atoms you can `await` in markup, and server rendering with hydration. The API follows `@effect/atom-react`.
|
|
4
4
|
|
|
5
|
-
This is a community project by Jarred Norris. It is not part of Effect, and the Effect team neither makes nor endorses it. Most of its code and docs were written with the help of AI (Claude); its behavior is covered by tests in Chromium, Firefox and WebKit.
|
|
5
|
+
This is a community project by Jarred Norris. It is not part of Effect, and the Effect team neither makes nor endorses it. Most of its code and docs were written with the help of AI (Claude Opus 5.5); its behavior is covered by tests in Chromium, Firefox and WebKit.
|
|
6
6
|
|
|
7
|
-
**Documentation: [atom.jarrednorris.dev](https://atom.jarrednorris.dev)**
|
|
7
|
+
**Documentation: [atom.jarrednorris.dev](https://atom.jarrednorris.dev)** · [API reference](https://atom.jarrednorris.dev/reference) · [GitHub](https://github.com/jarrednorrisdev/effect-atom-svelte)
|
|
8
8
|
|
|
9
9
|
## Requirements
|
|
10
10
|
|
|
11
|
-
- `effect` 4.0.x. The peer range is `~4.0.0`, not `^4.0.0
|
|
12
|
-
- Svelte 5.57 or later
|
|
13
|
-
- SvelteKit is optional. The error hooks in `effect-atom-svelte/sveltekit`
|
|
11
|
+
- `effect` 4.0.x. The peer range is `~4.0.0`, not `^4.0.0`: the bindings use parts of the atom registry that aren't public API, which a minor release of `effect` can change.
|
|
12
|
+
- Svelte 5.57.2 or later. `experimental.async` is needed for `useAtomSuspense`, `useAtomResult` and server rendering.
|
|
13
|
+
- SvelteKit is optional. The docs site and its tests run on SvelteKit 3. On SvelteKit 2, the error hooks in `effect-atom-svelte/sveltekit` work with less detail.
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
@@ -21,6 +21,7 @@ npm install effect-atom-svelte "effect@~4.0.0"
|
|
|
21
21
|
Turn on Svelte's async mode. In SvelteKit 3, pass it to `sveltekit()` in `vite.config.ts`:
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
|
+
// vite.config.ts
|
|
24
25
|
sveltekit({
|
|
25
26
|
compilerOptions: { experimental: { async: true } },
|
|
26
27
|
});
|
|
@@ -39,7 +40,7 @@ Then put a registry around your app, in the root layout:
|
|
|
39
40
|
<RegistryProvider>{@render children()}</RegistryProvider>
|
|
40
41
|
```
|
|
41
42
|
|
|
42
|
-
On the server, the provider creates a registry for each request, so visitors never see each other's state.
|
|
43
|
+
On the server, the provider creates a registry for each request, so visitors never see each other's state. Without one, the server throws `No AtomRegistry in context`. [Installation](https://atom.jarrednorris.dev/installation) covers the registry options and apps without SvelteKit.
|
|
43
44
|
|
|
44
45
|
## Example
|
|
45
46
|
|
|
@@ -72,7 +73,7 @@ On the server, the provider creates a registry for each request, so visitors nev
|
|
|
72
73
|
</svelte:boundary>
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
Hooks return an object whose `current` you read, assign or `bind:` to
|
|
76
|
+
Hooks return an object whose `current` you read, assign or `bind:` to. Don't destructure `current`: `const { current } = useAtomValue(atom)` reads once and never updates. Coming from `@effect/atom-react`? See [Migrating from atom-react](https://atom.jarrednorris.dev/migrating-from-react).
|
|
76
77
|
|
|
77
78
|
## Learn more
|
|
78
79
|
|
|
@@ -80,6 +81,7 @@ Hooks return an object whose `current` you read, assign or `bind:` to; destructu
|
|
|
80
81
|
- [Server rendering](https://atom.jarrednorris.dev/server-rendering) and [Hydration](https://atom.jarrednorris.dev/hydration)
|
|
81
82
|
- [Effect RPC](https://atom.jarrednorris.dev/rpc) and [HttpApi](https://atom.jarrednorris.dev/http)
|
|
82
83
|
- [API reference](https://atom.jarrednorris.dev/reference) and [Troubleshooting](https://atom.jarrednorris.dev/troubleshooting)
|
|
84
|
+
- [Every export at a glance, and more recipes](https://github.com/jarrednorrisdev/effect-atom-svelte#api-at-a-glance), in the repository's README
|
|
83
85
|
|
|
84
86
|
## Versioning
|
|
85
87
|
|
|
@@ -87,4 +89,4 @@ The package is at 0.x, so a minor release can change the API. Every change is li
|
|
|
87
89
|
|
|
88
90
|
## License
|
|
89
91
|
|
|
90
|
-
MIT
|
|
92
|
+
[MIT](https://github.com/jarrednorrisdev/effect-atom-svelte/blob/main/LICENSE)
|
package/dist/Hooks.svelte.js
CHANGED
|
@@ -176,8 +176,9 @@ const subscribedReader = (registry, getAtom) => {
|
|
|
176
176
|
// render, which already has the value, so it is dropped. Delivered on a microtask it started a
|
|
177
177
|
// Svelte batch that, when the first render ran after an await in markup (a HydrationBoundary
|
|
178
178
|
// awaiting its state), committed before hydration's own and made Svelte's dev build throw "Batch
|
|
179
|
-
// has scheduled effects" (JND-95). After mount it is still delivered, as before
|
|
180
|
-
//
|
|
179
|
+
// has scheduled effects" (JND-95). After mount it is still delivered, as before. Nothing depends
|
|
180
|
+
// on the update it starts: a getter switched in onMount once did, by accident, as that update
|
|
181
|
+
// rendered before the registry swept the old atom (JND-98, fixed in the effect below).
|
|
181
182
|
let reading;
|
|
182
183
|
const listen = (current, update) => registry.subscribe(current, () => {
|
|
183
184
|
if (mounted || reading !== current) {
|
|
@@ -202,11 +203,20 @@ const subscribedReader = (registry, getAtom) => {
|
|
|
202
203
|
// the subscription may follow an atom the commit did not pick. It moves to the committed atom,
|
|
203
204
|
// or that atom's later changes, a refresh's result or failure included, would not reach the
|
|
204
205
|
// page (JND-93).
|
|
206
|
+
// The atom it leaves is kept, not released: this effect can run before the switch it reads has
|
|
207
|
+
// committed. A getter switched in onMount is read here in the same flush, while Svelte's batch
|
|
208
|
+
// for the switch is still pending, and the renders with that batch rolled back read the old
|
|
209
|
+
// atom. Released here, the registry could sweep it before they do, and they would compute it
|
|
210
|
+
// again (JND-98). A later run that commits another atom releases it.
|
|
205
211
|
if (atom !== undefined && atom !== committed) {
|
|
212
|
+
const previous = atom;
|
|
206
213
|
const previousCancel = cancel;
|
|
207
214
|
atom = committed;
|
|
208
215
|
cancel = follow(committed);
|
|
209
|
-
previousCancel
|
|
216
|
+
if (previousCancel) {
|
|
217
|
+
releaseKept();
|
|
218
|
+
kept = { atom: previous, cancel: previousCancel };
|
|
219
|
+
}
|
|
210
220
|
}
|
|
211
221
|
});
|
|
212
222
|
const subscribe = createSubscriber((update) => {
|
|
@@ -324,11 +334,17 @@ export function useAtomSet(input, options) {
|
|
|
324
334
|
throw new TypeError(`useAtomSet's ${mode} mode cannot wait for Atom.Reset; reset with a value mode setter`);
|
|
325
335
|
}
|
|
326
336
|
const atom = getAtom();
|
|
327
|
-
// An already aborted signal
|
|
328
|
-
|
|
337
|
+
// An already aborted signal settles as interrupted without writing, as fetch does (JND-25). It
|
|
338
|
+
// skips the wait too: Effect checks the signal only after a first run, which would return a
|
|
339
|
+
// result the atom already holds from an earlier call.
|
|
340
|
+
let exit;
|
|
341
|
+
if (writeOptions?.signal?.aborted) {
|
|
342
|
+
exit = Exit.interrupt();
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
329
345
|
registry.set(atom, value);
|
|
346
|
+
exit = await awaitResult(registry, atom, { suspendOnWaiting: true }, writeOptions?.signal);
|
|
330
347
|
}
|
|
331
|
-
const exit = await awaitResult(registry, atom, { suspendOnWaiting: true }, writeOptions?.signal);
|
|
332
348
|
return mode === "promiseExit" ? exit : valueOrThrow(exit);
|
|
333
349
|
};
|
|
334
350
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-atom-svelte",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Community-built Svelte 5 bindings for Effect Atom (not affiliated with the Effect team)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"@sveltejs/vite-plugin-svelte": "^7.2.0",
|
|
54
54
|
"@vitest/browser": "^5.0.3",
|
|
55
55
|
"@vitest/browser-playwright": "^5.0.3",
|
|
56
|
-
"effect": "4.0.
|
|
56
|
+
"effect": "4.0.1",
|
|
57
57
|
"playwright": "^1.57.0",
|
|
58
|
-
"svelte": "^5.57.
|
|
58
|
+
"svelte": "^5.57.2",
|
|
59
59
|
"svelte-check": "^4.6.0",
|
|
60
60
|
"vite": "^8.3.0",
|
|
61
61
|
"vitest": "^5.0.3",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@sveltejs/kit": "^2.0.0 || ^3.0.0",
|
|
66
66
|
"effect": "~4.0.0",
|
|
67
|
-
"svelte": "^5.57.
|
|
67
|
+
"svelte": "^5.57.2"
|
|
68
68
|
},
|
|
69
69
|
"peerDependenciesMeta": {
|
|
70
70
|
"@sveltejs/kit": {
|