Release 0.22.0: localStorage engine, Tauri bridge, npm package rewrite - #6
Merged
Merged
Conversation
…that end themselves The localstorage engine opens a store in a page on wasm32-unknown-unknown: one JSON value per key under amethystate:<store>:, a write in the call, a full quota answered by set, and another tab's write arriving as Source::AnotherPage. StoreLayout::PageStorage says where it lives. save_async, close_async, shutdown_async and GlobalStoreGuard::close_async resolve with how the write ended without blocking the thread that awaits them, so a page, which cannot block, can still wait for its data. Store::subscribe returns a StoreSubscription that unsubscribes on drop. SubscriptionId is drawn from one count per process, so an id from one store names nothing in another, and StoreBackend::unsubscribe says whether it held it. The memory engine runs migration steps when it is asked for by name, and reads in parallel as redb does. The whole tests/ tree builds for wasm and runs in headless Chrome through cargo xtask browser, which hands each run a Chrome profile of its own and removes it afterwards: wasm-bindgen-test-runner kills chromedriver before the session ends, and every run used to leave about 30 MB under the temporary directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Frontend listeners go through the Tauri 2 event plugin; before, they never heard anything. Event channel names come from one function, amethystate_core::event_channel, checked against a fixture the TypeScript side reads too. The plugin keeps a path watched while anyone still watches it rather than ending it at the first unsubscribe, clears a watched map when a prefix deletion covers it, and names a map entry by its own key with the handle that wrote it, so a frontend skips its own echo. delete_prefix and scan_keys join the commands and amethystate:default. An async map write applies and notifies before it reaches the backend and is undone when the backend refuses it, with the old value taken from the cache: an entry no longer shows as removed while its write is in flight. The arena's Tauri path is rewritten and inserts a new entry rather than updating an absent one, so a new entry no longer vanishes right after it is added. amethystate-codegen writes strict TypeScript classes over the npm package, with value types imported from the files ts-rs writes beside them; volatile fields are skipped. The Rust wasm bindings are generated from StorePath. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amethystate 0.4.0: Field, ReactiveMap, load() into a slice, and a Transport with tauri() as the default. get() is synchronous and subscribe returns the function that stops it, which is the contract of React's useSyncExternalStore and of Svelte stores. Writes apply at once and roll back when the store refuses them; a map skips its own echo by the handle that wrote it. Tested with vitest over @tauri-apps/api/mocks; path spellings and channel names are checked against the fixture the Rust side reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
yew: a local path over a store in the same process - AmeStateProvider, use_field, use_read_only_field, use_map, use_map_entry and use_amethystate - beside the Tauri path, which sits behind tauri-backend, on by default. Effects on the Tauri path depend on the field, map or entry they watch. gpui 0.3.0 builds on gpui-pre 0.3.6 and needs Rust 1.95. AmeView<T> and AmeEntity<T> lose the store parameter nothing used; new_amethystate panics with the error when the slice will not open, and try_new_amethystate returns it. dioxus builds against dioxus with default features off; its Tauri writes are spawned. leptos and dioxus build again on the Tauri path. amethystate-reactor is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every example is the same todo app with lists, a page per list and settings, so each adapter's lifecycle gets exercised as pages mount and unmount. New: web-dioxus and web-yew beside web-leptos. tauri-typescript replaces tauri-settings and runs on the rewritten npm package; tauri-leptos and tauri-yew are ported to the same app. The windows-reactor example goes with its adapter. Trunk output and the Tauri examples' lockfiles are ignored. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The introduction opens with why amethystate was written. The installation page gets a browser section for localstorage, the TypeScript page is rewritten for the new package, and the Tauri page hands the store to init and lists the two new permissions. The gpui page follows the adapter; the leptos and yew pages name the adapters' own versions and no feature that does not exist. The windows-reactor pages go. The README names localStorage and says plainly that the adapters and about half of the engines are a proof of concept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both ci.ps1 and the workflow type-check and test js/. ci.ps1 also lints the tests for wasm32 and runs them in headless Chrome. amethystate-gpui leaves the workspace runs, because gpui-pre needs Rust 1.95 against the workspace's 1.90; ci.ps1 lints it on its own with cargo +1.95.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The workspace drops amethystate-reactor and gains the two page test crates. Breaking below 1.0: MemoryStore::open takes the migration steps, Store::subscribe returns a guard, SubscriptionId is a type of its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ang on Windows notify 8.2 stops a Windows watch with CancelIo and CloseHandle, and a read that had already completed with an event re-arms ReadDirectoryChangesW on the closed handle. When the handle value has been handed to a synchronous open in the meantime, the watcher thread and whoever opened the file both block on it for good. A text store closing while its directory changed - a test removing its temporary directory, an application removing or rewriting the file - could hang like that. In CI it hung a RON conformance test for an hour; locally one run in ten of the RON conformance tests hung, and none in a hundred after the move. notify 9.0.0-rc.5 marks the watch as stopping before it cancels, so the late completion does not re-arm. 8.x has no release with the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
0.22.0
Breaking
Store::subscribereturns aStoreSubscriptionthat unsubscribes when dropped, in place of a bare id.SubscriptionIdis a type of its own, drawn from one count per process: an id from one store names nothing in another.StoreBackend::unsubscribereturns whether this store held it.MemoryStore::open(&config, migrations)takes the steps and returns(store, report): a store opened on the memory engine by name runs its steps like any other.SourcegainsAnotherPage, andStoreEvent::is_external_editis true for it.AmeView<T>andAmeEntity<T>lose the store parameter;new_amethystatepanics when the slice will not open,try_new_amethystatereturns the error. Built ongpui-pre0.3.6, Rust 1.95.amethystate0.4.0 is rewritten:Field,ReactiveMap,load()into a slice, aTransportwithtauri()as the default.get()is synchronous andsubscribereturns its unsubscribe, theuseSyncExternalStoreand Svelte store contract.amethystate-codegenwrites strict TypeScript classes over that package; value types come fromts-rs, derived only where the frontend sees them.amethystate-reactoris removed.New
Backend::LocalStorage(featurelocalstorage), for a page onwasm32-unknown-unknown: one JSON value per key, a write in the call, a full quota answered byset, another tab's write arriving asSource::AnotherPage.StoreLayout::PageStorage { under }says where it lives.StoreBackend::save_asyncandclose_async,shutdown_async,GlobalStoreGuard::close_async.delete_prefixandscan_keys, both inamethystate:default.AmeStateProvider,use_field,use_read_only_field,use_map,use_map_entry,use_amethystateover a local store.cargo xtask browserruns the whole test suite in headless Chrome.Fixes
cargo xtask browserremoves the Chrome profile each run leaves, about 30 MB apiece.Also here
web-dioxusandweb-yew, andtauri-typescriptin place oftauri-settings.Warning
The framework adapters and about half of the engines are not used in any real application. They run in CI and were smoke-tested, and they were built as a proof of concept for the architecture of the store.
🤖 Generated with Claude Code