Skip to content

Releases: wraithyy/attunement

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 07 Aug 16:27
85a26b8

Minor Changes

  • 043f2b9: New safeUrlOrPath predicate: refinement for config values that become
    network targets — accepts same-origin paths and absolute http(s) URLs,
    rejects protocol-relative URLs (//evil, /\evil), non-http schemes and
    bare hostnames. Compose it via .refine(safeUrlOrPath, ...) with any
    Standard Schema library. Plus hardening recipes: build-id cache-busting,
    environment-dependent validation (buildSchema({ isProd }) + superRefine),
    and a localized error fallback built from ConfigError.issues.

Patch Changes

  • 5c1214c: Validation error messages drop the "you didn't say the magic word" easter egg
    in production builds — custom errorFallbacks render error.message to end
    users, and a broken deploy is not a dev-only situation. Dev builds and the
    CLI keep it. For localized error UIs, build from ConfigError.issues
    instead of error.message. Docs: OverrideRecovery usage is shown
    DEV-gated (ungated renders null in production but ships the devtools bytes).

v0.5.2

Choose a tag to compare

@github-actions github-actions released this 03 Aug 12:16
080541a

Patch Changes

  • 610b35c: Override recovery moved where the knowledge lives (field report #3):

    • fromOverrides(storageKey?) now registers a recovery handler (internal
      globalThis registry) that knows its own storage key and the config.* URL
      bootstrap. "Clear overrides and reload" therefore works with a custom
      storageKey and also strips config.* query params — a broken shared
      repro link no longer reseeds the override on reload.
    • The react entry no longer carries any override knowledge (hardcoded key,
      localStorage parsing, dead-in-production recovery UI paths) — the default
      errorFallback just renders what registered handlers report, which in
      production is nothing because fromOverrides doesn't run there.
    • New OverrideRecovery component in attunement/devtools: the same
      recovery block for custom/branded errorFallbacks; renders nothing when no
      overrides are stored.

v0.5.1

Choose a tag to compare

@github-actions github-actions released this 03 Aug 09:07
1469a64

Patch Changes

  • 7bcd7e5: Field report #2 fixes:

    • DevtoolsProps.config (and attunementDevtoolsPlugin) now accept the core
      Attuned handle instead of AttunedReact. The React handle is invariant in
      its config type (context), so the documented React.lazy devtools pattern
      failed to typecheck with a typed schema — and bindReact users had to
      export a bound handle just for the panel. The panel only ever needed
      load() and the schema; a React handle still works.
    • Default errorFallback detects active dev overrides
      (localStorage["attunement:overrides"]), lists them and offers
      "Clear overrides and reload" — a persisted invalid override otherwise turns
      Retry into a loop with the devtools panel unreachable behind the error
      boundary (the same failure mode cache: "no-store" fixed for CDNs, second
      persistence source).
    • README: the lazy devtools import now sits inside the import.meta.env.DEV
      gate — an ungated lazy(() => import(...)) still emits and deploys the
      devtools chunk in production builds.

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 02 Aug 18:42

Minor Changes

  • ee8ddab: API wave — field-report driven, panel-validated:

    • onReady(cb) on the attune handle: register render-critical wiring from
      modules the config module must not import (router basepath, i18n) — no more
      import cycles. One queue with onLoad (which is now just the first
      callback), awaited in registration order before load() resolves; callback
      errors reject the load as ConfigError. Registered after resolve: runs
      immediately with a DEV warning; after a failed load: never runs.
    • bindReact(attuned): React binding over an existing core handle, so the
      schema can live in a leaf module importable by attunement check and tests.
      attuneReact(options) is unchanged (it is now bindReact(attune(options))).
    • errorFallback(error, retry): function fallbacks get a retry argument
      (currently a full page reload); the default fallback gains a Retry button.
      The config boundary now rethrows errors that aren't ConfigError, so app
      bugs reach your own error boundary instead of masquerading as config
      failures. New onError prop on Provider for Sentry-style reporting.
    • optional(source) exported: failure → undefined → merge/chain falls
      through (was a recipe).
    • fromJson now defaults cache: "no-store" — a CDN-cached stale config
      survives reloads and turns Retry into a loop. Override with
      fromJson(url, { cache: "default" }) if you serve config with proper
      invalidation.
    • Devtools: fields?: FieldInfo[] on DevtoolsProps/docsTable bypasses
      zod introspection (escape hatch for Valibot/ArkType).
      attunementDevtoolsPlugin(config, { storageKey, fields }) — second argument
      is now an options object (was storageKey string).
    • CLI: check --strict turns secret-hygiene warnings into failures;
      check --print-fingerprint prints the same hash the running app reports via
      fingerprint().
    • React entries ship a "use client" banner.
    • @standard-schema/spec moved to dependencies (types-only) — public d.ts
      imports it; consumers without a transitive copy previously got TS2307.
    • Note for type-level consumers: Attuned gained onReady and an internal
      _schema — hand-built mocks of the handle need updating.
  • bcb1108: Config fingerprint: attune()/attuneReact() handles expose fingerprint()
    resolving to { hash, version?, generatedAt? } — a stable FNV-1a hash of the
    validated config (key-order independent) plus _version/_generatedAt read
    off the raw config when the deploy pipeline stamps them. onLoad receives the
    fingerprint as a second argument for Sentry scope / log prefix wiring.

Patch Changes

  • b205980: First batch of field-report fixes:

    • Schema introspection unwraps z.preprocess — zod 3 ZodEffects
      (_def.schema) and zod 4 pipes (_def.out) — so the documented
      all-strings recipe renders checkboxes/selects in the devtools panel
      instead of text inputs.
    • Provider without errorFallback now renders a minimal "Configuration
      failed to load." notice instead of a white page; the error message (config
      keys, source URLs) shows in dev builds only. Pass errorFallback={null}
      for the old behavior.
    • AttunementDevtools accepts position ("bottom-right" default,
      "bottom-left", "top-right", "top-left") to dodge TanStack Query devtools
      and friends.
    • attunement check --diff warns when fewer than two files matched instead
      of silently skipping the diff.
    • README: migration-from-hand-rolled-loader section, onLoad ordering
      guarantee vs .then(), lazy devtools import as the default pattern,
      injectKey in the Vite snippet, zod-only introspection caveat moved to
      the Standard Schema bullet.

v0.4.4

Choose a tag to compare

@github-actions github-actions released this 31 Jul 13:08

Patch Changes

  • b6921dc: Devtools panel rows no longer stretch to the full TanStack Devtools shell
    height. The shell applies > * > * { height: 100% } to plugin content, which
    blew each field row up to ~400px; rows, buttons and the note now pin
    height: auto inline.

v0.4.3

Choose a tag to compare

@github-actions github-actions released this 31 Jul 10:48

Patch Changes

  • 69bdbd2: Fix devtools panel for Zod 4 schemas and overflowing content:

    • Schema introspection (introspectShape, docsTable, devtools form) now reads
      both Zod 3 (_def.typeName, enum values, default thunk) and Zod 4
      (_def.type, enum entries, plain default value) internals. With Zod 4,
      booleans render as checkboxes and enums as populated selects again instead of
      falling back to plain text inputs.
    • The panel scrolls its own overflow (max-height + overflow-y: auto), so all
      fields and the Save/Clear buttons stay reachable inside the TanStack Devtools
      shell's fixed-height, overflow: hidden container — and the standalone
      floating widget caps at 70vh.

v0.4.2

Choose a tag to compare

@github-actions github-actions released this 31 Jul 09:52

Patch Changes

  • 8f0f965: attunementDevtoolsPlugin's return type now declares render: ReactElement instead of ReactNodeReactNode includes undefined, which the TanStack Devtools shell's TanStackDevtoolsReactPlugin.render (JSX.Element | (...) => JSX.Element) rejects. The panel always renders a real element, so the wider type was never earning its keep.

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 31 Jul 09:31

Patch Changes

  • 9361f18: Make DevtoolsProps/AttunementDevtoolsPanel/AttunementDevtools/attunementDevtoolsPlugin generic over the config shape, so a devtools consumer typed with a concrete schema (e.g. AttunedReact<RuntimeConfig, typeof schema>) doesn't need a cast to pass its attuneReact() instance in.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 31 Jul 08:11

Minor Changes

  • 9d74bec: attunement/devtools: dev override panel generated from the schema (enum → select, boolean → checkbox) — standalone floating widget (AttunementDevtools) or TanStack Devtools plugin (attunementDevtoolsPlugin). fromOverrides() source layers localStorage overrides + ?config.KEY=value URL bootstrap over real config via merge, validated by the schema like everything else.
  • cfaf690: attunement/vite: Vite plugin — dev server serves the config file (full reload on change), optional injectKey injects config into index.html for fromWindow (real content in dev, deploy-replaceable placeholder in builds).

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 31 Jul 07:04

Minor Changes

  • e98bf43: v0.3 — CI story: attunement CLI. check --schema <module> <files...> validates config files against the app schema (same did-you-mean errors as runtime), --diff fails on top-level key drift between environments, secret hygiene warnings (credential-like names, high-entropy values), docs renders a markdown table of keys/types/defaults from a zod schema. New attunement/cli entry + attunement bin.