effect-atom-svelte 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # effect-atom-svelte
2
2
 
3
- Svelte 5 bindings for Effect Atom (`effect/reactivity`), following the API of `@effect/atom-react`: hooks with a reactive `current`, async atoms you can `await` in markup, and server rendering with hydration.
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`, as 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 or later, with `experimental.async` turned on for the async hooks and server rendering.
13
- - SvelteKit is optional. The error hooks in `effect-atom-svelte/sveltekit` are made for SvelteKit 3 and work with less detail on SvelteKit 2.
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. See [Installation](https://atom.jarrednorris.dev/installation) for the options and for apps without SvelteKit.
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; destructuring it reads the value once and loses reactivity. Coming from React? See [Migrating from React](https://atom.jarrednorris.dev/migrating-from-react).
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)
@@ -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: dropping it there
180
- // too made a getter switched in onMount compute the server's atom again (JND-24).
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) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-atom-svelte",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
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.0",
56
+ "effect": "4.0.1",
57
57
  "playwright": "^1.57.0",
58
- "svelte": "^5.57.1",
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.0"
67
+ "svelte": "^5.57.2"
68
68
  },
69
69
  "peerDependenciesMeta": {
70
70
  "@sveltejs/kit": {