Releases: whisqjs/whisq
Release list
create-whisq@0.1.0-alpha.10
create-whisq@0.1.0-alpha.10
@whisq/vite-plugin@0.1.0-alpha.10
@whisq/vite-plugin@0.1.0-alpha.10
@whisq/testing@0.1.0-alpha.10
@whisq/ssr@0.1.0-alpha.10
@whisq/sandbox@0.1.0-alpha.10
@whisq/sandbox@0.1.0-alpha.10
@whisq/router@0.1.0-alpha.10
@whisq/mcp-server@0.1.0-alpha.10
Minor Changes
-
fe295e0: Spike: first slice of the enriched
public-api.jsonfrom #103 — ships a drift-validated per-symbol metadata manifest, populates it for thesignalstopic, and wires the MCP server'ssignalsdocs to consume it.@whisq/core- New artefact:
dist/public-api-annotated.json. Schema spec atpackages/core/docs/api-metadata-schema.md. Current shape —{ version, schemaVersion: 1, symbols: SymbolEntry[] }— is frozen behindschemaVersionso consumers can guard against breaking changes. - New exports-map entry:
"@whisq/core/public-api-annotated.json"— the public path consumers import from. - Hand-curated source of truth at
packages/core/metadata/api-enrichment.json. The build step runsscripts/generate-api-metadata.mjsaftergenerate-public-api.mjsand fails with a non-zero exit if:- a
symbols[*].nameis not inpublic-api.jsonexports (drift), - a
seeAlso[*]reference is not inpublic-api.jsonexports (drift), - any required field on a
SymbolEntryis missing or wrong type, - a duplicate symbol entry appears.
- a
- Populated for one topic this release:
signals(signal,computed,effect,batch). The names-onlypublic-api.jsonis unchanged — this is a sibling file, not a replacement. See #103 for the path to unification.
@whisq/mcp-server- New
@whisq/coreworkspace dependency (was previously untyped docs; now consumes the annotated manifest). api-docs.tssignalstopic is generated from the enriched manifest at build time — no more hand-written drift. The other topics (elements,components,routing, …) remain hand-written until the schema stabilises; migrating them is a follow-up tracked against #103.- Load-bearing phrases consumers grep for (
signal(,computed(,.value,peek(),batch(() =>) are locked in by a new regression test block.
Out of scope (follow-ups)
- CI drift check between
public-api.jsonandpublic-api-annotated.json(all existing exports must have enrichment) — follow-up once the other topics migrate. - Migrating the remaining MCP topics — mechanical once this spike's shape is validated across a release cycle.
- Unifying the two manifests into one — option A in #103; gated on 1–2 releases of stable schema.
Closes #138.
- New artefact:
Patch Changes
@whisq/devtools@0.1.0-alpha.10
@whisq/core@0.1.0-alpha.10
Minor Changes
-
987fde7: New
compose(bindResult, extras)helper for order-independent composition ofbind()/bindField()/bindPath()results with user-supplied event handlers.The dev warning added in alpha.9 caught direction 1 (user handler after the bind spread) but direction 2 (user handler before the spread) was undetectable from final props alone — the user's handler was gone without a trace by the time the element builder ran.
compose()sidesteps the order dependency entirely: shared handler keys chain both handlers (bind first, user second), and non-handler props follow normal object-spread semantics (extras win).import { bind, compose, input } from "@whisq/core"; input({ ...compose(bind(draft), { oninput: (e) => track(e), // fires after bind writes draft onfocus: () => analytics.focus(), // bind has no onfocus — attaches cleanly }), });
The compose result re-tags its bind-sentinel with the composed handler as the "declared" one, so the alpha.9 duplicate-handler warning does not fire on a well-formed
compose()spread, but still fires if someone overwrites the compose result afterward.Closes WHISQ-132.
-
fe295e0: Spike: first slice of the enriched
public-api.jsonfrom #103 — ships a drift-validated per-symbol metadata manifest, populates it for thesignalstopic, and wires the MCP server'ssignalsdocs to consume it.@whisq/core- New artefact:
dist/public-api-annotated.json. Schema spec atpackages/core/docs/api-metadata-schema.md. Current shape —{ version, schemaVersion: 1, symbols: SymbolEntry[] }— is frozen behindschemaVersionso consumers can guard against breaking changes. - New exports-map entry:
"@whisq/core/public-api-annotated.json"— the public path consumers import from. - Hand-curated source of truth at
packages/core/metadata/api-enrichment.json. The build step runsscripts/generate-api-metadata.mjsaftergenerate-public-api.mjsand fails with a non-zero exit if:- a
symbols[*].nameis not inpublic-api.jsonexports (drift), - a
seeAlso[*]reference is not inpublic-api.jsonexports (drift), - any required field on a
SymbolEntryis missing or wrong type, - a duplicate symbol entry appears.
- a
- Populated for one topic this release:
signals(signal,computed,effect,batch). The names-onlypublic-api.jsonis unchanged — this is a sibling file, not a replacement. See #103 for the path to unification.
@whisq/mcp-server- New
@whisq/coreworkspace dependency (was previously untyped docs; now consumes the annotated manifest). api-docs.tssignalstopic is generated from the enriched manifest at build time — no more hand-written drift. The other topics (elements,components,routing, …) remain hand-written until the schema stabilises; migrating them is a follow-up tracked against #103.- Load-bearing phrases consumers grep for (
signal(,computed(,.value,peek(),batch(() =>) are locked in by a new regression test block.
Out of scope (follow-ups)
- CI drift check between
public-api.jsonandpublic-api-annotated.json(all existing exports must have enrichment) — follow-up once the other topics migrate. - Migrating the remaining MCP topics — mechanical once this spike's shape is validated across a release cycle.
- Unifying the two manifests into one — option A in #103; gated on 1–2 releases of stable schema.
Closes #138.
- New artefact:
-
94caac8: Two small additive helpers to close the alpha.9 feedback loop — both opt-in on existing sub-path imports, no breaking changes.
-
createStorageNamespace(prefix)on@whisq/core/persistence— returns a{ persistedSignal }view whose storage keys are transparently rewritten to${prefix}:${key}. Use when several Whisq apps share an origin (marketing site + dashboard + demo playground on the same host) and must not collide. A thin compositional wrapper — everythingpersistedSignalalready supports (storage kind, schema, onSchemaFailure, …) passes straight through. Empty or whitespace prefixes are rejected so a forgotten interpolation fails loudly instead of silently using":key".import { createStorageNamespace } from "@whisq/core/persistence"; const app = createStorageNamespace("whisq-todo-app"); export const todos = app.persistedSignal<Todo[]>("todos", []); // ↑ actual key: "whisq-todo-app:todos"
-
randomId(options?)on@whisq/core/ids— now accepts{ prefix, rng }. Zero-arg call is unchanged.prefixconcatenates directly (no separator — pass"todo_"if that's what you want).rngreplacesMath.randomin the fallback synthesis and also bypassescrypto.randomUUID, so a seeded PRNG produces the same id on every platform. The primary use-case is deterministic ids for snapshot tests — no more globally stubbingcrypto.randomUUID.import { randomId } from "@whisq/core/ids"; randomId(); // default: crypto.randomUUID randomId({ prefix: "todo_" }); // "todo_01K1…" randomId({ rng: seedrandom(42) }); // deterministic across environments
Closes WHISQ-134. Source:
dev/feedback/latest/FRAMEWORK_FEEDBACK_CLAUDE_v0.1.0-alpha.9.md(N5, N7). -
-
310dd97: Friendly runtime errors for sub-path exports imported from the main
@whisq/corepath.Apps of any size reach into multiple sub-path imports:
@whisq/core/persistence,/ids,/collections,/forms. This is the right shape for tree-shaking — unused sub-paths add zero bytes — but an AI or human writingimport { partition } from "@whisq/core"used to hit the generic bundler "not exported" error with no hint about where the symbol actually lives.The main entry now re-exports these sub-path names as runtime stubs. Importing one compiles cleanly; calling it throws with a message that names the correct sub-path and links to the docs page:
import { partition } from "@whisq/core"; // compiles const [a, b] = partition(() => xs.value, p); // → Error("partition" is not exported from "@whisq/core". Import it from "@whisq/core/collections" instead. See https://whisq.dev/api/partition/)
Each stub carries
@deprecatedJSDoc so editor hover surfaces the correct sub-path without running the code.Symbols covered:
partition,signalMap,signalSet→@whisq/core/collectionsrandomId→@whisq/core/idspersistedSignal→@whisq/core/persistencebindPath→@whisq/core/forms
Stubs are plain
export functions in a side-effect-free module; bundlers with standard unused-export elimination (esbuild, Rollup, Vite) drop them to zero bytes in apps that don't import them. Verified by building a minimalimport { signal }app: the produced bundle contains no stub names, no error strings, and no sub-path-stubs module reference.Closes WHISQ-133.
v0.1.0-alpha.9
Alpha.8 reviewer follow-up + mid-cycle discoveries. Six feature PRs; top-level @whisq/core bundle at 5.67 KB gzipped (under the 6.0 KB budget bumped for the WHISQ-121 function-child lift).
Diagnostics — three new dev-mode warnings
- #123 (WHISQ-120) — Dev warning when spreading
bind()/bindField()/bindPath()then overwriting one of its event handlers. Alpha.8 reviewer's top-ranked concern ("the only one that will produce a bug someone ships to production"). Sentinel-symbol survives JS object spread. Direction 2 (user handler first, spread last) documented as a known limitation with the safer convention steered in the warning. - #126 (WHISQ-122) — Dev warning on duplicate
theme()calls. Completes the alpha.7theme()saga (#99 → #105 → #126). DOM-based detection;{ silent: true }opt-out for intentional theme-switching. - #129 (WHISQ-128) — Typed
aria-*attributes on every element. Also fixes an ARIA-spec bug the new typing exposed: boolean aria values now serialise to"true"/"false"(not empty string, which is invalid per the ARIA spec).
API
- #125 (WHISQ-121) —
component()accepts a function-child setup return. Alpha.8 reviewer's #2 ranked concern: no more sacrificial wrapperdivto host amatch()return. Same fragment + start/end marker patternerrorBoundary/ keyedeach()already use internally.
Isolation
- #119 (WHISQ-118) —
mountSandboxed()in@whisq/sandbox. Iframe + CSP +<iframe srcdoc>+__whisq-tagged postMessage bridge — standards-only, zero new deps. Scaffolded API shape for futureisolation: "worker" | "wasm". Motivated by the ArrowJS positioning analysis indev/feedback/comparison.md.
Templates + Examples
- #127 (WHISQ-124) — First runnable public example at
examples/template-todo/. Unblocks whisqjs/whisq.dev#158's "Open in StackBlitz" button. URL:
https://stackblitz.com/github/whisqjs/whisq/tree/main/examples/template-todo
Demonstrates the full alpha.9 canonical API:persistedSignal+onSchemaFailure,randomId, named-action mutations,bind(spread last per WHISQ-120),match()as component root (WHISQ-121), keyedeachwithItemAccessor,bindField,class:array form,errorBoundary,sheet()nested selectors +theme().
Infrastructure
@whisq/corebundle budget: 5.5 → 6.0 KB (WHISQ-121 fragment helper).scripts/sync-template-versions.mjs+scripts/check-versions.mjsextended to walkexamples/*/package.jsonalongside the CLI templatepackage.json.tmplfiles..gitignore: narrowed from blanketexamples/toexamples/*+!examples/template-todo/.
Coverage of alpha.8 reviewer feedback
Both P1 items closed (#120, #121). P3 theme() dup warning closed (#122). Docs-side concerns (inline factory vs component(), .value hoisting trap, persistence matrix, state-management named-actions) tracked on whisq.dev.
Next cycle
whisq.dev has open docs issues consuming these APIs (#108 cookbook, #109 persistence matrix, #110 golden patterns, #158 StackBlitz button which this release enables, plus #162–#165 from the alpha.8 analyze-feedback round). Natural next focus.
Remaining open (framework-repo, not release blockers)
#84(P2) — alpha.6 docs papercuts; framework-repo side done, remaining ACs are whisq.dev-only.#90(P3) — dev warn for snapshotted accessors; parked (prefer static analysis; no user reports).#103(P3) — enrichpublic-api.json; parked (no concrete consumer yet).