Skip to content

feat(useLocale,useFeatures): enable reactive registry by default#211

Merged
johnleider merged 1 commit into
masterfrom
feat/locale-features-reactive-default
Apr 23, 2026
Merged

feat(useLocale,useFeatures): enable reactive registry by default#211
johnleider merged 1 commit into
masterfrom
feat/locale-features-reactive-default

Conversation

@johnleider
Copy link
Copy Markdown
Member

Summary

Pass reactive: true to the internal registries in useLocale and useFeatures so consumers get reactive collection reads and per-ticket mutation propagation without having to opt in.

Rationale

Same audit, same shape as #210:

  • useLocale — exposes size, keys(), values(), entries() over a plain Map. Most real-world usage is through t() and selectedId (already reactive), but a template listing registered locales would silently miss register() / unregister().
  • useFeatures — the higher-priority case. Its headline API, variation(id), reads registry.get(id) on a plain Map. Templates using v-if="features.variation('new-checkout')" don't react when sync() updates flag values from a remote adapter. Since sync() is called on every remote-flag update, this is the primary way the composable is meant to be used.

Both are product composables (users expect a Vue-reactive service from the name) with tiny collections (a handful of locales, a handful of flags), so the shallowReactive overhead is negligible.

Verification

  • pnpm typecheck — clean.
  • pnpm vitest run useLocale useFeatures — 136 tests passing.
  • pnpm lint:fix — clean.

Pass `reactive: true` to the internal registries so consumers get
reactive collection reads and per-ticket mutation propagation without
having to opt in.

- `useLocale` exposes `size`, `keys()`, `values()`, `entries()` — all
  untracked against a plain Map until now. Most usage sticks to `t()`
  and `selectedId` (already reactive), but a template listing
  registered locales would silently miss register/unregister.
- `useFeatures` is worse — its headline API `variation(id)` reads
  `registry.get(id)` on a plain Map, so templates using
  `v-if="features.variation('flag-x')"` never reacted to `sync()`
  calls updating flag values from a remote adapter.

Same rationale as #210 for `useTheme`: these are product composables,
small collections, and users expect a Vue-reactive service from the
name.
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 23, 2026

Open in StackBlitz

commit: 923c8d5

@johnleider johnleider self-assigned this Apr 23, 2026
@johnleider johnleider added this to the v0.2.x milestone Apr 23, 2026
@johnleider johnleider merged commit e61744a into master Apr 23, 2026
16 of 17 checks passed
@johnleider johnleider deleted the feat/locale-features-reactive-default branch April 23, 2026 17:14
johnleider added a commit that referenced this pull request Apr 23, 2026
- `.claude/rules/composables.md`: new section "Plugins and Reactive
  Defaults" covering the primitive/plugin tiers, when to pass
  `reactive: true` to an internal registry, the two-registry
  architecture, and how `reactive: true` and `useProxyRegistry`
  complement each other.
- `PHILOSOPHY.md §4.4`: rewrite from "the reactive: true footgun" to
  "Registry reactivity". The footgun described (values() cache dropping
  Vue dep tracking) was closed in #209 — that section was actively
  teaching the wrong mental model through #210, #211, and #212. New
  text positions `reactive: true` and `useProxyRegistry` as two valid
  complementary options.
- `PHILOSOPHY.md §6.7`: revise the closing warning that said "do not
  substitute reactive: true on the registry itself" — same reason.

Refs #208 #209 #210 #211 #212
johnleider added a commit that referenced this pull request Apr 23, 2026
#213)

- `.claude/rules/composables.md`: new section "Plugins and Reactive
  Defaults" covering the primitive/plugin tiers, when to pass
  `reactive: true` to an internal registry, the two-registry
  architecture, and how `reactive: true` and `useProxyRegistry`
  complement each other.
- `PHILOSOPHY.md §4.4`: rewrite from "the reactive: true footgun" to
  "Registry reactivity". The footgun described (values() cache dropping
  Vue dep tracking) was closed in #209 — that section was actively
  teaching the wrong mental model through #210, #211, and #212. New
  text positions `reactive: true` and `useProxyRegistry` as two valid
  complementary options.
- `PHILOSOPHY.md §6.7`: revise the closing warning that said "do not
  substitute reactive: true on the registry itself" — same reason.

Refs #208 #209 #210 #211 #212
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant