@happykit/flags
Version:
Feature Flags for Next.js
228 lines (225 loc) • 6.51 kB
TypeScript
import { CookieSerializeOptions } from 'cookie';
/**
* A user to load the flags for. A user must at least have a `key`. See the
* supported user attributes [here](#supported-user-attributes).
* The user information you pass can be used for individual targeting or rules.
*/
declare type FlagUser = {
key: string;
email?: string;
name?: string;
avatar?: string;
country?: string;
};
/**
* Traits
*
* An object which you have access to in the flag's rules.
* You can target users based on traits.
*/
declare type Traits = {
[key: string]: any;
};
/**
* Generic Feature Flags
*
* Entries consist of the feature flag name as the key and the resolved variant's value as the value.
*/
declare type Flags = {
[key: string]: boolean | number | string | null;
};
/**
* The inputs to a flag evaluation.
*
* Given a flag has not changed, the same inputs will always lead to the same variants when evaluating a flag.
*/
declare type Input = {
endpoint: string;
envKey: string;
requestBody: EvaluationRequestBody;
};
declare type SuccessOutcome<F extends Flags> = {
data: GenericEvaluationResponseBody<F>;
error?: never;
};
declare type ErrorOutcome = {
data?: never;
error: ResolvingError;
};
/**
* The result of a flag evaluation
*/
declare type Outcome<F extends Flags> = SuccessOutcome<F> | ErrorOutcome;
/**
* The fetch() request failed due to a network error (fetch itself threw).
*/
declare type NetworkError = "network-error";
/**
* The response body could not be parsed into the expected JSON structure.
*/
declare type InvalidResponseBodyError = "invalid-response-body";
/**
* The HTTP Status Code was not 200-299, so the response was not ok.
*/
declare type ResponseNotOkError = "response-not-ok";
/**
* The request was aborted because it reached any of the loadingTimeouts.
*/
declare type RequestTimeoutError = "request-timed-out";
declare type ResolvingError = NetworkError | InvalidResponseBodyError | ResponseNotOkError | RequestTimeoutError;
declare type EvaluationRequestBody = {
visitorKey: string | null;
user: FlagUser | null;
traits: Traits | null;
};
/**
* The HappyKit API response to a feature flag evaluation request.
*/
declare type GenericEvaluationResponseBody<F extends Flags> = {
visitor: {
key: string;
} | null;
flags: F;
};
declare type SuccessInitialFlagState<F extends Flags> = {
input: Input;
outcome: SuccessOutcome<F>;
error?: never;
};
declare type ErrorInitialFlagState = {
input: Input;
outcome: ErrorOutcome;
};
/**
* The initial flag state.
*
* In case you preloaded your flags during server-side rendering using `getFlags()`, provide the returned state as `initialState`. The client will then skip the first request whenever possible and use the provided flags instead. This allows you to get rid of loading states and on the client.
*/
declare type InitialFlagState<F extends Flags> = SuccessInitialFlagState<F> | ErrorInitialFlagState;
declare type Revalidate = () => void;
declare type EmptyFlagBag = {
flags: null;
data: null;
error: null;
fetching: false;
settled: false;
revalidate: Revalidate;
visitorKey: null;
};
declare type EvaluatingFlagBag<F extends Flags> = {
flags: null | F;
data: null;
error: null;
fetching: true;
settled: false;
revalidate: Revalidate;
visitorKey: string;
};
declare type SucceededFlagBag<F extends Flags> = {
flags: F;
data: GenericEvaluationResponseBody<F>;
error: null;
fetching: false;
settled: boolean;
revalidate: Revalidate;
visitorKey: string;
};
declare type RevalidatingAfterSuccessFlagBag<F extends Flags> = {
flags: F;
data: GenericEvaluationResponseBody<F>;
error: null;
fetching: true;
settled: boolean;
revalidate: Revalidate;
visitorKey: string;
};
declare type FailedFlagBag<F extends Flags> = {
flags: F | null;
data: null;
error: ResolvingError;
fetching: false;
settled: boolean;
revalidate: Revalidate;
visitorKey: string;
};
declare type RevalidatingAfterErrorFlagBag<F extends Flags> = {
flags: F | null;
data: null;
error: ResolvingError;
fetching: true;
settled: false;
revalidate: Revalidate;
visitorKey: string;
};
/**
* A bag of feature flag related data.
*/
declare type FlagBag<F extends Flags = Flags> = EmptyFlagBag | EvaluatingFlagBag<F> | SucceededFlagBag<F> | RevalidatingAfterSuccessFlagBag<F> | FailedFlagBag<F> | RevalidatingAfterErrorFlagBag<F>;
declare type GetFlagsSuccessBag<F extends Flags> = {
/**
* The resolved flags
*
* In case the default flags contain flags not present in the loaded flags,
* the missing flags will get added to the returned flags.
*/
flags: F;
/**
* The actually loaded data without any defaults applied, or null when
* the flags could not be loaded.
*/
data: GenericEvaluationResponseBody<F> | null;
error: null;
initialFlagState: SuccessInitialFlagState<F>;
/**
* The cookie options you should forward using
*
* Only used for edge, not for server.
*
* ```
* response.cookie(
* flagBag.cookie.name,
* flagBag.cookie.value,
* flagBag.cookie.options
* );
* ```
*
* or using
*
* ```
* response.cookie(...flagBag.cookie.args)
* ```
*/
cookie?: {
name: string;
value: string;
options: CookieSerializeOptions;
/**
* Arguments for response.cookie()
*/
args: [string, string, CookieSerializeOptions];
} | null;
};
declare type GetFlagsErrorBag<F extends Flags> = {
/**
* The resolved flags
*
* In case the flags could not be loaded, you will see the default
* flags here (from config.defaultFlags)
*/
flags: F | null;
/**
* The actually loaded data without any defaults applied, or null when
* the flags could not be loaded.
*/
data: null;
error: ResolvingError;
/**
* The initial flag state that you can use to initialize useFlags()
*/
initialFlagState: ErrorInitialFlagState;
/**
* Only used for edge, not for server.
*/
cookie?: null;
};
export { Flags as F, GetFlagsSuccessBag as G, Input as I, Outcome as O, Traits as T, FlagUser as a, GetFlagsErrorBag as b, GenericEvaluationResponseBody as c, InitialFlagState as d, FlagBag as e };