feat: add @tanstack/marko-store - a Marko v6 adapter for TanStack Store#340
feat: add @tanstack/marko-store - a Marko v6 adapter for TanStack Store#340defunkt-dev wants to merge 26 commits into
Conversation
|
Important Review skippedToo many files! This PR contains 184 files, which is 34 over the limit of 150. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (184)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Summary
This PR adds
@tanstack/marko-store, a Marko v6 adapter for@tanstack/store, alongside the existing react / solid / svelte / vue / angular / preact / lit adapters in the monorepo. It exposes the store API as idiomatic Marko tags, re-exports the framework-agnostic@tanstack/storecore, and supports Marko's full rendering model: client rendering, SSR with resume, per-request isolation, and progressive (out-of-order) streaming.What's added
Package:
packages/marko-storeFive tags plus a small internal helper:
<store-provider>— provides a per-request bundle of stores to descendants by a context key.<store-context>— reads the provided bundle (for dispatching actions, etc.).<store-selector>— subscribes to a store or atom and projects a slice, infrommode orcontextmode.<store-atom>— two-way binding to a single writable atom fromcreateAtom().<stream-store-provider>— a provider for progressive streaming that builds a per-request bundle from data awaited inside a late<await>and keeps it live across the server-to-client boundary.store-bus.ts— an internal publish bus (publishStore/subscribeStorePublish) used to reattach selectors when a provider parks its bundle during resume/streaming.The package re-exports the full
@tanstack/storecore (createStore,createAtom,Store,Derived,shallow, and so on) so Marko users have a single import.Distribution mirrors the Marko-library convention: the tags ship as raw
.markosource (filesincludessrc/tags), so the consumer's Marko tooling reads their types directly. Each tag also ships a hand-written.d.markodeclaration for robust type resolution in consumer projects undernoUnusedLocalsand referenced-file checking; onlydist/index.d.tsistsc-emitted (for the core re-export).Examples:
examples/marko/*Five client-only parity examples mirroring the sibling adapters:
simple,atoms,stores,store-actions, andstore-context.Three Marko-specific SSR examples demonstrating server behavior:
ssr-resume(store stays live after resume),ssr-per-request-multi(per-request store isolation), andstreaming(progressive streaming with a live store). These run on the standalone@marko/vitedev server; each README notes that a production deployment uses@marko/run(see Known limitations).Docs:
docs/framework/marko/*A hand-written
quick-start.mdand a hand-authored tag reference (reference/index.mdplus one page per tag underreference/tags/). The reference is hand-authored because the public API is.markotags, which TypeDoc does not read; see the matchingdocs/config.jsonnav entries (Getting Started, Examples, API Reference, Store API Reference).Design notes
<await>, the store is created from the awaited value inside the await body; the value crosses to the client through the await subtree's resume scope. Marko'sserializedGlobalsis unsuitable here because it is written once at the first flush (the shell), before late awaits resolve, so globals set inside a late await read back as null on the client.$global+ publish-bus model for context. Context delivery (the bundle) plus a live store reference is modeled on themarko-queryadapter's$global+ bus pattern, not a tree-scoped context primitive. The bus lets a context-mode<store-selector>reattach the moment its provider parks the bundle during streaming or resume.<store-provider>and<stream-store-provider>share an owner marker on the context key and throw on a duplicate, rather than silently clobbering the same box.@marko/run. A standalone@marko/viteproduction build does not coordinate resume for the adapter;@marko/rundoes. This was verified by building a minimal@marko/runapp and confirming store liveness and BWD streaming in a production build under real Chromium.Testing
streaming-livenessandstreaming-out-of-order(behavioral), andstreaming-fill-renderandstreaming-fill-onmount(characterization).All suites pass under the monorepo's
test:cipipeline (package build,marko-type-check, knip, eslint, jsdom tests, real-Chromium e2e).Commands to use to test locally:
Known limitations
@marko/vitedev server; a production Marko v6 app uses@marko/run, and the example READMEs say so. (@marko/runis currently beta at 0.10.0.)$global+ bus model in the interim. This tracks Marko core discussion (issue #3155);let-globalis the community interim pattern. The adapter solves the constrained case (a serializable bundle plus a live store reference), not general tree-scoped context.<try>+<@placeholder>. Marko v6 removed theclient-reorderattribute on<await>, so out-of-order streaming is expressed with<try>and a placeholder.Checklist
pnpm test:cigreen in the monorepo@tanstack/marko-store)docs/config.jsonNote
packages/marko-store,examples/markoanddocs/framework/marko.package.json,pnpm-lock.yaml,pnpm-workspace.yaml, docs/config.json ,.gitignore,.changeset/,.prettierrcandknip.json`