flags
Version:
Flags SDK by Vercel - The feature flags toolkit for Next.js and SvelteKit
238 lines (233 loc) • 8.64 kB
TypeScript
import { IncomingHttpHeaders } from 'http';
import { RequestCookies, ResponseCookies } from '@edge-runtime/cookies';
type ReadonlyHeaders = Headers & {
/** @deprecated Method unavailable on `ReadonlyHeaders`. Read more: https://nextjs.org/docs/app/api-reference/functions/headers */
append(...args: any[]): void;
/** @deprecated Method unavailable on `ReadonlyHeaders`. Read more: https://nextjs.org/docs/app/api-reference/functions/headers */
set(...args: any[]): void;
/** @deprecated Method unavailable on `ReadonlyHeaders`. Read more: https://nextjs.org/docs/app/api-reference/functions/headers */
delete(...args: any[]): void;
};
declare class HeadersAdapter extends Headers {
private readonly headers;
constructor(headers: IncomingHttpHeaders);
/**
* Seals a Headers instance to prevent modification by throwing an error when
* any mutating method is called.
*/
static seal(headers: Headers): ReadonlyHeaders;
/**
* Merges a header value into a string. This stores multiple values as an
* array, so we need to merge them into a string.
*
* @param value a header value
* @returns a merged header value (a string)
*/
private merge;
/**
* Creates a Headers instance from a plain object or a Headers instance.
*
* @param headers a plain object or a Headers instance
* @returns a headers instance
*/
static from(headers: IncomingHttpHeaders | Headers): Headers;
append(name: string, value: string): void;
delete(name: string): void;
get(name: string): string | null;
has(name: string): boolean;
set(name: string, value: string): void;
forEach(callbackfn: (value: string, name: string, parent: Headers) => void, thisArg?: any): void;
entries(): HeadersIterator<[string, string]>;
keys(): HeadersIterator<string>;
values(): HeadersIterator<string>;
[Symbol.iterator](): HeadersIterator<[string, string]>;
}
type ReadonlyRequestCookies = Omit<RequestCookies, 'set' | 'clear' | 'delete'> & Pick<ResponseCookies, 'set' | 'delete'>;
declare class RequestCookiesAdapter {
static seal(cookies: RequestCookies): ReadonlyRequestCookies;
}
type FlagParamsType = {
headers: ReadonlyHeaders;
cookies: ReadonlyRequestCookies;
};
/**
* Data flag providers can return to integrate with the toolbar.
*/
type ProviderData = {
definitions: FlagDefinitionsType;
hints: {
key: string;
text: string;
}[];
};
/**
* Describes the provider of a feature flag
*/
type Origin = {
provider: 'vercel';
projectId: string;
} | {
provider: 'edge-config';
edgeConfigId: string;
edgeConfigItemKey?: string;
teamSlug: string;
} | Record<string, unknown>;
/**
* Data returned by the .well-known/vercel/flags API Route which the toolbar understands.
*/
type ApiData = {
/**
* Metadata about your application's feature flags
*/
definitions?: FlagDefinitionsType;
/**
* Hints show up in the toolbar. They are meant to be used in case loading
* data from your flag provider fails. For example when the provider fails to
* responed or the configuration is invalid due to a missing environment variable.
*/
hints?: ProviderData['hints'];
/**
* Sets the encryption mode for the vercel-flag-overrides cookie
* - when set to "encrypted" the toolbar will store encrypted overrides
* - when set to "plaintext" the toolbar will store plaintext overrides
*/
overrideEncryptionMode?: 'encrypted' | 'plaintext';
};
/**
* Represents a JSON stringifiable value.
*
* This is essentially just `any` to make it easy to work with, but we use a dedicated type to signal the intent.
*/
type JsonValue = any;
interface FlagOptionType {
value: JsonValue;
label?: string;
}
interface FlagDefinitionType {
options?: FlagOptionType[];
/**
* The URL where the feature flag can be managed.
*/
origin?: string | Origin;
description?: string;
/**
* When a feature flag is declared through `flag` or `declareFlag` instead
* of being loaded from an external source like a feature flag provider's SDK
* then this will be `true`.
*/
declaredInCode?: boolean;
/**
* The defaultValue defined in code which will be used when the flag
* can not be loaded from the provider or throws an error.
*/
defaultValue?: JsonValue;
/**
* The timestamp in milliseconds of when the flag was updated.
*/
updatedAt?: number;
/**
* The timestamp in milliseconds of when the flag was created.
*/
createdAt?: number;
}
/**
* Definitions of a feature flags.
*
* Definitions are data like the description, available options, or its origin.
*/
type FlagDefinitionsType = Record<string, FlagDefinitionType>;
/**
* Values of feature flags.
*
* This record consists of key-value pairs of flag keys and the value they resolved to.
*/
type FlagValuesType = Record<string, JsonValue>;
/**
* Overrides of feature flags.
*
* This record consists of key-value pairs of flag keys and the override to be used for them.
*/
type FlagOverridesType = Record<string, JsonValue>;
type FlagOption<T> = {
value: T;
label?: string;
};
type GenerousOption<T> = boolean extends T ? boolean | FlagOption<T> : T extends string | number ? T | FlagOption<T> : FlagOption<T>;
type Decide<ValueType, EntitiesType> = (params: FlagParamsType & {
entities?: EntitiesType;
}) => Promise<ValueType> | ValueType;
type Identify<EntitiesType> = (params: FlagParamsType) => Promise<EntitiesType | undefined> | EntitiesType | undefined;
/** An adapter interface to use the Flags SDK with any flag provider */
interface Adapter<ValueType, EntitiesType> {
initialize?: () => Promise<void>;
identify?: Identify<EntitiesType>;
origin?: Origin | string | ((key: string) => Origin | string | undefined);
config?: {
reportValue?: boolean;
};
decide: (params: {
key: string;
entities?: EntitiesType;
headers: ReadonlyHeaders;
cookies: ReadonlyRequestCookies;
defaultValue?: ValueType;
}) => Promise<ValueType> | ValueType;
}
/**
* Definition when declaring a feature flag, as provided to `flag(declaration)`
*/
type FlagDeclaration<ValueType, EntitiesType> = {
/**
* The key of the feature flag
*/
key: string;
/**
* An optional defaultValue which will be used when the flag's `decide` function returns undefined or throws an error. Catches async errors too.
*/
defaultValue?: ValueType;
/**
* A URL where this feature flag can be managed. Will show up in Vercel Toolbar.
*/
origin?: string | Origin;
/**
* A description of this feature flag. Will show up in Vercel Toolbar.
*/
description?: string;
/**
* An array containing available options.
*
* The returend value does not need to be declared in `options`, but it's recommended as all declared options show up in Vercel Toolbar.
*
* Value is required, but the label is optional.
* @example `[{ label: "Off", value: false }, { label: "On", value: true }]`
*
* Non-objects like strings can be passed using shorthands which will be used as values without labels.
* @example `["EUR", "USD"]`
*/
options?: GenerousOption<ValueType>[];
/**
* Configuration options that can be passed to the flag.
*/
config?: {
reportValue?: boolean;
};
/**
* Adapters can implement default behavior for flags.
*
* Explicitly provided values always override adapters.
*/
/**
* This function is called when the feature flag is used (and no override is present) to return a value.
*/
/**
* This function can establish entities which the `decide` function will be called with.
*/
identify?: Identify<EntitiesType>;
} & ({
adapter: Adapter<ValueType, EntitiesType>;
decide?: Decide<ValueType, EntitiesType>;
} | {
adapter?: Adapter<ValueType, EntitiesType>;
decide: Decide<ValueType, EntitiesType>;
});
export { type Adapter as A, type Decide as D, type FlagOverridesType as F, type GenerousOption as G, HeadersAdapter as H, type Identify as I, type JsonValue as J, type Origin as O, type ProviderData as P, type ReadonlyHeaders as R, type FlagValuesType as a, type FlagDefinitionsType as b, type ApiData as c, type FlagOptionType as d, type FlagDefinitionType as e, type FlagDeclaration as f, type ReadonlyRequestCookies as g, RequestCookiesAdapter as h, type FlagOption as i };