Skip to content

v2.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Oct 11:17
· 8 commits to main since this release
5d9915a

Nano Kit 2.0 🎉

What's new

  • DevTools. @nano_kit/devtools is a panel right on the page to inspect your stores: your signals, their values and a log of every change.
  • Development warnings. In development, the packages warn about common mistakes, like a missing route parameter or a missing translation.
  • Tasks on signals. SSR and tests wait only for the data they need, not for every request in flight.
  • Smarter dependency injection. Stores are shared between nested contexts unless a context overrides what they depend on. The new provideAs swaps an implementation, like a mock API in tests.
  • SignalsMap class. The reactive map now has the familiar Map API.
  • Operators. With static operands they return a plain value, and pick, text and latest are new.
  • intl. relativetime() picks the unit by itself, from "5 minutes ago" to "yesterday", and format() messages accept signals.
  • Preact 11 and SvelteKit 3 are supported.

Upgrading from 1.x

The breaking changes below list everything. The usual edits:

  • Node.js 24 or newer is required.
  • inject(TasksRunner$) with task(fn) becomes task($signal, fn), waitTasks(pool) becomes waitTasks($signal), and client(ssr()) or client(tasks(), hydratable()) becomes client(hydratable()).
  • context.set(token, value) becomes context.deps.set(token, value). To keep a store per context, provide it in that context.
  • $getMapKey(map, key), setMapKey, deleteMapKey and clearMap become map.$get(key), map.set, map.delete and map.clear of a new SignalsMap().
  • An operator with static operands returns the value, not an accessor, and concat($first, ' ', $last) becomes text`${$first} ${$last}` (the f tag in the notes below shipped as text).
  • resolved keeps a falsy value as data: express an empty state with the type, such as User | null.
  • An effect created in a deferred scope body no longer defers: use deferEffect there.
  • relativetime() takes a moment instead of a count, and its unit option is gone: set largestUnit and smallestUnit to one unit to format in it.

Where to start

  • 📚 Documentation: guides for every package
  • 🛠️ DevTools: install the panel and open it with Alt+Shift+D
  • 🤖 Agent Skills: teach your coding agent the Nano Kit API

⚠ BREAKING CHANGES

  • store,query: $getMapKey, setMapKey, deleteMapKey, clearMap, subMapEvent,
    fireMapEvent, $$insert, $$clear, $$deleted and the SignalsMapEvent and
    SignalsMapEvents types are removed from @nano_kit/store, and SignalsMap is a class to
    create with new, not a type over a plain Map. The cache of a query client context is
    a ShardedSignalsMap: its has, set and delete take a sharded key.
  • agera,kida: effect no longer defers when created inside a deferred scope body: use
    deferEffect there. subscribe, listen, observe and subscribeAny no longer accept the
    noDefer argument.
  • kida,store,react,svelte-kit: InjectionContext no longer extends Map: its values are in the public deps
    map, so context.set(token, value) becomes context.deps.set(token, value). A dependency that
    is not provided is no longer created in the context that injects it first, and a context no
    longer takes a dependency from above when it overrides what that dependency reads.
  • intl: relativetime() takes a moment, a date, a timestamp or a date string,
    instead of a count of units, and its unit option is gone, so a call that passes it no
    longer compiles. Format in one unit with largestUnit and smallestUnit set to it, and
    format a count of units with Intl.RelativeTimeFormat or a plural() message.
  • kida: resolved hands values through verbatim - a falsy source value is data, not a
    reset to undefined: emptiness is expressed by T itself (e.g. T | null), and the input type
    drops the falsy arm.
  • kida,store: an operator called with static operands returns the value, not an accessor.
    concat is removed, the f tag takes its place.
  • the packages require Node.js 24 or newer.
  • kida,store,query: the tasks pool is gone — TasksPool$, TasksRunner$, tasksRunner, addTask,
    waitCurrentTasks and taskPromise are removed, waitTasks takes a signal instead of a pool, and
    the tasks() and ssr() query settings are removed: hydratable() is the whole SSR setting.

Features

  • add development diagnostics with separate development and production builds (#236) (39be996)
  • agera,kida,store: add uninspected to keep the nodes of a listener out of inspect, and the old value to UpdateEvent (#262) (83384ce)
  • agera,kida: add deferEffect for effects owned by a deferred scope (#257) (12cb14b)
  • agera: add inspect to report graph events in the development build (#237) (07e4290)
  • agera: call the inspect listener with one event object (#264) (f49ec73)
  • agera: enclose the lifecycle listeners of a node between FireEvent and FireEndEvent (#267) (ef084b7)
  • agera: report the end of a run with RunEndEvent, and leave oldValue out of a first evaluation (#265) (61186e0)
  • devtools,store: add the DevTools panel (#263) (bc1e51a)
  • intl: accept a signal, an accessor or null as the value of a format() message (#286) (4010477)
  • intl: make relativetime() take a moment and pick the unit by the distance (#287) (cdf1238)
  • intl: use a plain string translation for every plural form and match case (#246) (82d45cf)
  • kida,store,query: attach tasks to the signals they fill (#222) (841acd1)
  • kida,store,react,svelte-kit: create a dependency in the deepest context that provides what it reads, and add provideAs (#279) (5052174)
  • kida,store: move latest from kida to @nano_kit/store (#296) (f503e28)
  • kida,store: return a plain result from the operators when every operand is static (#260) (3a8b32f)
  • kida: add latest for the value of the source that changed last (#231) (84efaed)
  • kida: attach the resolved promise as a task and hand values through verbatim (#223) (8fabbeb)
  • kida: export child to build custom child signals (#250) (8794697)
  • kida: rename the template tag f to text (505d947)
  • preact,preact-router,preact-ssr: support Preact 11 (#302) (b05c190)
  • require Node.js 24 (#268) (c6ed062)
  • store,query: replace the signals map functions with the SignalsMap and IndexedSignalsMap classes (#261) (c062f06)
  • svelte-kit: support SvelteKit 3 (#299) (b2c54bb)

Bug Fixes

  • agera: drop the development warning about a signal written inside a computed (#266) (21e269b)
  • agera: mount a mountable first read on a re-run of a computed that another computed reads (#294) (df898de)
  • agera: queue batch and trigger writes onto a running flush instead of draining it (#256) (d6afbdd)
  • deps: update dependency @astrojs/starlight to ^0.42.0 (#228) (bb5a65c)
  • deps: update dependency jotai to v3 (#243) (a6c972f)
  • deps: update dependency mobx to v7 (#184) (5c3ff53)
  • deps: update dependency starlight-llms-txt to ^0.12.0 (#258) (d52874c)
  • deps: update dependency starlight-sidebar-topics to ^0.9.0 (#232) (65da70d)
  • intl: do not warn that a format() message is missing from the translations (#285) (3c12504)
  • intl: require explicit options next to a fallback in the Intl formatters (#245) (6b3d44e)
  • kida: keep onMount subscribed when a signal remounts within the unmount delay (#229) (b911d4c)
  • kida: type record() and deepRecord() of a Signalish source as readable (#295) (ffe5453)
  • next-router: let a nested NextNavigationProvider pick up search params below a prerenderable layout (#242) (13a2eb3)
  • platform-web,svelte-kit: round-trip any value through the cookie storage on the server and in the browser (#289) (8ed53a3)
  • platform-web: accept null in parseLocales for a missing Accept-Language header (#244) (1e29516)
  • platform-web: broadcast broadcasted writes and resets while the signal is not observed (#247) (2696386)
  • platform-web: expire a cookie immediately with maxAge: 0 (#248) (bae248e)
  • preact: reuse the parent context by default in HydrationProvider, as React does (#249) (cb2d9e2)
  • query: drop the development warning about a cache key shard registered twice (#275) (6a0749b)
  • query: refetch a query revalidated while its request is in flight (#284) (2c0ed97)
  • router,ssr: render the httpEquiv meta prop as the http-equiv attribute (#253) (568df71)
  • router: stop back() and forward() of browserNavigation from throwing Illegal invocation (#290) (f747eaf)
  • ssr,react-ssr,preact-ssr,svelte-ssr: escape head values and the dehydrated snapshot in the rendered html (#239) (60eefe2)
  • ssr: link the stylesheets of a chunk after those of the chunks it imports (#282) (07b0c48)
  • svelte-router: re-render App when the matched page component changes (#241) (0d44ed1)
  • svelte-router: resolve getLocation, getNavigation, getPaths and getCanGoBack through the Svelte context (#240) (2e465d3)