Commit Graph

30 Commits

Author SHA1 Message Date
Dominik Ferber e7360242b0 feat(flags): share the evaluation pipeline and bring SvelteKit to parity
Lifts the per-request evaluation pipeline into src/shared/ and points both
frameworks at it, so behavior is defined once. The Next-specific
isInternalNextError check becomes an injected `isFrameworkError` hook on
applyResult (Next passes it; SvelteKit defaults to none).

- shared/evaluation.ts: evaluationCache (+ getUsedFlags accessor), getEntities
  + identify-args dedupe, and applyResult (cache -> override -> produce ->
  defaultValue/error -> report).
- shared/flag-meta.ts: resolveAdapter, getDecide (with adapter validation),
  getIdentify, getOrigin.

SvelteKit's flag() now runs through this pipeline. This is a behavior change
that brings it to parity with Next — SvelteKit now:
- falls back to defaultValue when decide throws or returns undefined
- honors config.reportValue / adapter.config.reportValue
- resolves adapter.origin (value or (key) => origin)
- dedupes evaluation via the shared headers-keyed cache (replacing the
  per-store usedFlags/identifiers maps); createHandle's transformPageChunk
  reads used flags via getUsedFlags()
- getProviderData emits defaultValue + declaredInCode

Adds `defaultValue?` to the SvelteKit Flag type (additive) and 9 parity tests.
Next's public .d.ts is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 16:15:18 +03:00
Dominik Ferber e1d377c453 refactor(flags): extract framework-agnostic shared/ module
Both flags/next and flags/sveltekit implemented the same flag pipeline
twice and had drifted. This lifts the parts that are framework-agnostic
(or trivially so) into src/shared/, with each framework keeping thin
wrappers for its differences. Zero public API change — the generated
.d.ts for flags, flags/next and flags/sveltekit are byte-identical.

- shared/seal.ts: sealHeaders/sealCookies/transformToHeaders
  (was duplicated in next/evaluate.ts and sveltekit/index.ts)
- shared/overrides.ts: readOverrides + memoized decrypt; SvelteKit now
  gets the override memoization Next already had. Removes next/overrides.ts.
- shared/precompute.ts: combine/serialize/deserialize/generatePermutations
  + getPrecomputed core. Frameworks keep wrappers for secret defaulting
  and the getPrecomputed(flag) vs getPrecomputed(key) signatures.
- shared/discovery.ts: shared authorize -> 401-or-data -> version-header
  control flow behind createFlagsDiscoveryEndpoint.

Named "shared" rather than "core" to avoid confusion with the separate
@vercel/flags-core package.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 15:22:35 +03:00
Dominik Ferber 2cb0b49698 Allow passing an adapter factory directly to flag() (#402)
* Allow passing an adapter factory directly to flag()

flag() now accepts the adapter factory by reference (`adapter: vercelAdapter`)
as a shorthand for calling it (`adapter: vercelAdapter()`). The factory is
resolved once per declaration; passing an instance keeps working. Applies to
both the Next.js and SvelteKit entrypoints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [@flags-sdk/vercel] reuse adapter instance

* reword changeset

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 16:14:25 +03:00
Josh Story b23b7b407b Recognize hanging promise rejection as internal (#397) 2026-06-15 14:31:10 +03:00
Dominik Ferber 201f9d5988 Add bulk evaluation (#385)
* [flags] avoid re-imports

Avoid re-importing next/headers since it adds unnecessary microtask queue overhead

* [flags] avoid iife microtask queue overhead

* [flags] skip awaits where possible

* [flags] allow bulk eval

* wip

* add bulk mode to playground

* first try of bulk eval

* add bulk evaluation to adapters

* reuse

* simplify

* versions

* rm outdated changeset

* rm outdated changeset

* revert playground

* revert playground flags

* rm logs

* reuse cache of resolved flags for bulk

* simplify

* changesets

* support bulk([]) and bulk({})

* flagKey → key

* allow any type in expectPermutations

* avoid unnecessary mapping

* fix changeset

* validate package.json fields

* update package.json fields

* keep covariant

* adjust adapter types

* Merge bulk into evaluate (#392)

* merge bulk into evaluate

* add pages router compatibility

* better types

* add array test

* add test

* changesets

* use type import

* fix import

* extract readOverrides

* fix import of reportValue

* tracing

* skip bulkDecide for overwritten flags

* update changesets

* [changesets] onlyUpdatePeerDependentsWhenOutOfRange

* add type guard

* adjust changeset
2026-06-05 08:14:29 +00:00
Dominik Ferber c08f3e5614 [flags/next] perf improvements (#356)
* [flags] avoid re-imports

Avoid re-importing next/headers since it adds unnecessary microtask queue overhead

* [flags] avoid iife microtask queue overhead

* [flags] skip awaits where possible

* add undefined to headersModulePromise type
2026-04-03 11:24:31 +00:00
nadav dd1396e461 Guard missing Vercel Flags runtime helpers (#326)
* Guard request-context flag reporting

* Preserve request-context hook binding

* Guard core request-context reporting

* Guard missing bundled flag definitions

---------

Co-authored-by: Dominik Ferber <dominik.ferber@gmail.com>
2026-03-12 16:38:18 +02:00
Dominik Ferber 77727aaade use __no_flags__ to handle precompute with empty flags (#300)
* use __no_flags__ to handle precompute with empty flags

* handle __no_flags__ in serialize

* add __no_flags__ handling to sveltekit

* avoid returning undefined when defaultValue is set

This could only happen on precomputed flags in case of bad usage.

* add error messages

* test console logs

* update changeset
2026-03-09 15:10:47 +00:00
Dominik Ferber 795dfd46a1 throw on declaration if flag is missing decide function (#259) 2026-02-09 13:28:41 +02:00
Dominik Ferber ec0d13f66f Rename Edge Middleware to Routing Middleware / Proxy (#229)
* adjust proxy export

* rename Edge Middleware to Proxy

* mv folder

* rename featureFlagsInProxy

* proxy

* Routing Functions → Routing Middleware
2025-12-05 11:51:42 +02:00
Dominik Ferber 11472542d8 rename (#228) 2025-12-05 10:14:26 +02:00
Dominik Ferber f2eba9c624 upgrade pnpm (#198)
* extract @flags-sdk/utils

* init

* split package

* rename createFlagsClient to createClient

* add TODO

* wip

* add openfeature adapter

* reuse InlineDataSource

* fix type in test

* expose OpenFeature adapter

* implement OpenFeature adapter

* wip

* wip

* convert shirt-shop

* move store into flags-core

* split up data-source

* add READMEs

* upgrade to pnpm v10

* update comment

* undo example changes

* rm flags/utils

* fix biome issues

* rm status test

* tests
2025-10-25 00:13:34 +03:00
Dominik Ferber ba4eec7b23 replace eslint and prettier with biome (#187)
* remove @pyra/eslint-config

* wip

* wip

* convert shirt-shop-api

* convert shirt-shop

* convert snippets

* convert next-13

* convert next-14

* convert next-15

* eslint configs

* upgrade prettier

* use eslint v9

* run prettier

* resolve type-check

* adjust eslint

* drop Next.js v13

* fix next-14

Avoid accidentally using implicitly installed eslint v8

* update lockfile

* rm @eslint/eslintrc

* add @next/eslint-plugin-next

* biome

* biome fixes

* wip

* apply formatting

* tabs

* rm prettier

* spaces

* fix svelte

* update lockfile

* single quotes

* format all

* rm eslint-disable comments

* upgrade playwright

* upgrade publint

* upgrade playwright ci workflow

* try chromium headless

* try adding executablePath
2025-10-15 23:38:17 +03:00
Dominik Ferber d4108c8127 allow clearing the dedupe cache (#138)
* allow clearing the dedupe cache

* add changeset

* expose clearCacheForCurrentRequest

* reword changeset

* avoid adding prop to deduped fn
2025-05-23 11:07:58 +03:00
Dominik Ferber bc7944ed89 split crypto functions into dedicated functions (#126) 2025-05-02 17:45:00 +03:00
Simon H 701f3c2bf2 Sveltekit flags enhancements (#75)
* use `$env/dynamic/private` from SvelteKit for convenience: people don't have to pass FLAGS_SECRET manually anymore then

* allow flag to be called outside of the lifecycle of the handle hook, with a request object being the key for deduplication etc

* add support for identifiers

* fix types

* new function for managing precomputed flags

* align with next.js API instead

* update example app

* lockfile

* test

* fix example

* restructure examples app

* make it two flags to show power of precompute + code

* add manual approach

* lets see if preview deployment is picked up

* change crypto usage to be usable in middleware

* make sveltekit flags pkg usable within edge middleware

* use ISR

* changeset

* enhance error message

* use static env instead of dynamic env

* bump kit

* use vercel adapter

* make sure Vite tooling is used for sveltekit entry point

---------

Co-authored-by: Dominik Ferber <dominik.ferber@gmail.com>
2025-03-21 14:43:28 +02:00
Andy b79a84a861 [flags] Add defaultValue to decide call (#107)
* [flags] Add `defaultValue` to `decide` call

* Update .changeset/popular-eels-heal.md

---------

Co-authored-by: Dominik Ferber <dominik.ferber@gmail.com>
2025-03-19 17:30:13 +02:00
Andy 2fcc446ea8 Create LaunchDarkly adapter (#2)
* Create LaunchDarkly adapter

* Update example to include a LaunchDarkly flag

* Add missing env to turbo

* Rename to defaultLaunchDarklyAdapter

* Add winter sale example for providers

* Update winter-sale

* Document usage in readme

* Allow to set the default value through the adapter

* Fix readme

* Add default value for adapter

* Make argument optional

* Add @ts-expect-error

* Add a LaunchDarkly adapter (#10)

* add ld example

* reword

* remove winter-sale example

* remove defaultValue

* use @flags-sdk/launchdarkly

* add install steps

* add changeset

* move @vercel/edge-config to peer deps

* add more secrets

* spell out name

* remove unused env var

* rename properties

* Capitalize

* Change import

* Fix more imports

* expose ldClient

* move peerDeps to real deps

* clarify Edge Config requirement in README

* remove adapter-launchdarkly snippet

* upgrade next@canary

* polish @flags-sdk/launchdarkly README

---------

Co-authored-by: Dominik Ferber <dominik.ferber@gmail.com>
2025-03-08 09:29:26 +02:00
Dominik Ferber 422435c0eb rename (#68)
* @vercel-flags » flags

* update lockfile

* fix name
2025-02-20 19:54:09 +02:00
Dominik Ferber a96464e7b9 Revert "fix use node: protocol for async_hooks import (#52)"
This reverts commit 6784f10def.
2025-02-07 06:55:43 +02:00
Dominik Ferber 475dd26e4d remove empty line 2025-02-06 15:34:33 +02:00
jlca 6784f10def fix use node: protocol for async_hooks import (#52)
* fix use node: protocol for async_hooks import
2025-02-06 15:33:49 +02:00
Dominik Ferber 6955b68448 avoid printing full error during development (#59)
* avoid printing error in development

* add description

* add changeset

* change message

* add more tests
2025-02-05 17:55:25 +02:00
Dominik Ferber 2713ea7aff throw on undefined unless defaultValue is defined (#46)
* throw when decide returns undefined

* throw on undefined unless defaultValue is defined

* wip

* bring back JsonValue

* do not enforce on typescript level for now

* add changeset

* mention exported types

* add precise types

* fix summer-sale example
2025-01-24 14:22:12 +02:00
Dominik Ferber 76feb1667f add mergeProviderData (#47) 2025-01-23 19:57:31 +02:00
Dominik Ferber 13269ff404 add tests for inferred options (#42) 2025-01-20 21:35:21 +02:00
Dominik Ferber 708d5e21b9 infer options of boolean flags (#40)
* infer options of boolean flags

* fix typo
2025-01-20 17:34:04 +02:00
Dominik Ferber 30f26947d6 allow usage without FLAGS_SECRET (#25) 2025-01-14 17:53:48 +02:00
Dominik Ferber 1fcd4fc177 Add Pages Router examples (#12)
* upgrade next

* ensure pages router support in turbopack

* add pages router examples

* fix cards

* re-add node prefix

* remove node prefix

* fix tests

* fix pages router pages
2025-01-10 15:06:24 +02:00
Dominik Ferber db89f0dfb1 Init 2024-12-12 13:01:06 +02:00