// Type definitions for launchdarkly-node-server-sdk /** * This is the API reference for the LaunchDarkly Server-Side SDK for Node.js. * * In typical usage, you will call [[init]] once at startup time to obtain an instance of * [[LDClient]], which provides access to all of the SDK's functionality. * * For more information, see the [SDK reference guide](https://docs.launchdarkly.com/sdk/server-side/node-js). */ declare module 'launchdarkly-node-server-sdk' { import { EventEmitter } from 'events'; import * as interfaces from 'launchdarkly-node-server-sdk/interfaces'; namespace errors { export const LDPollingError: ErrorConstructor; export const LDStreamingError: ErrorConstructor; export const LDClientError: ErrorConstructor; export const LDUnexpectedResponseError: ErrorConstructor; export const LDInvalidSDKKeyError: ErrorConstructor; } /** * Creates an instance of the LaunchDarkly client. * * Applications should instantiate a single instance for the lifetime of the application. * The client will begin attempting to connect to LaunchDarkly as soon as it is created. To * determine when it is ready to use, call [[LDClient.waitForInitialization]], or register an * event listener for the `"ready"` event using [[LDClient.on]]. * * **Important:** Do **not** try to instantiate `LDClient` with its constructor (`new LDClient()`); the SDK * does not currently support this. * * @param key * The SDK key. * @param options * Optional configuration settings. * @return * The new client instance. */ export function init(key: string, options?: LDOptions): LDClient; /** * The types of values a feature flag can have. * * Flags can have any JSON-serializable value. */ export type LDFlagValue = any; /** * A map of feature flags from their keys to their values. */ export interface LDFlagSet { [key: string]: LDFlagValue; } /** * An object that contains the state of all feature flags, generated by [[LDClient.allFlagsState]]. */ export interface LDFlagsState { /** * True if this object contains a valid snapshot of feature flag state, or false if the * state could not be computed (for instance, because the client was offline or there * was no user). */ valid: boolean; /** * Returns the value of an individual feature flag at the time the state was recorded. * It will be null if the flag returned the default value, or if there was no such flag. * * @param key * The flag key. */ getFlagValue(key: string): LDFlagValue; /** * Returns the evaluation reason for a feature flag at the time the state was recorded. * It will be null if reasons were not recorded, or if there was no such flag. * * @param key * The flag key. */ getFlagReason(key: string): LDEvaluationReason; /** * Returns a map of feature flag keys to values. If a flag would have evaluated to the * default value, its value will be null. * * Do not use this method if you are passing data to the front end to "bootstrap" the * JavaScript client. Instead, use [[toJSON]]. */ allValues(): LDFlagSet; /** * Returns a Javascript representation of the entire state map, in the format used by * the Javascript SDK. Use this method if you are passing data to the front end in * order to "bootstrap" the JavaScript client. * * Do not rely on the exact shape of this data, as it may change in future to support * the needs of the JavaScript client. */ toJSON(): object; } /** * Describes the reason that a flag evaluation produced a particular value. This is * part of the [[LDEvaluationDetail]] object returned by [[LDClient.variationDetail]]. */ export interface LDEvaluationReason { /** * The general category of the reason: * * - `'OFF'`: The flag was off and therefore returned its configured off value. * - `'FALLTHROUGH'`: The flag was on but the context did not match any targets or rules. * - `'TARGET_MATCH'`: The context key was specifically targeted for this flag. * - `'RULE_MATCH'`: the context matched one of the flag's rules. * - `'PREREQUISITE_FAILED'`: The flag was considered off because it had at least one * prerequisite flag that either was off or did not return the desired variation. * - `'ERROR'`: The flag could not be evaluated, e.g. because it does not exist or due * to an unexpected error. */ kind: string; /** * A further description of the error condition, if the kind was `'ERROR'`. */ errorKind?: string; /** * The index of the matched rule (0 for the first), if the kind was `'RULE_MATCH'`. */ ruleIndex?: number; /** * The unique identifier of the matched rule, if the kind was `'RULE_MATCH'`. */ ruleId?: string; /** * The key of the failed prerequisite flag, if the kind was `'PREREQUISITE_FAILED'`. */ prerequisiteKey?: string; /** * Whether the evaluation was part of an experiment. * * This is true if the evaluation resulted in an experiment rollout and served one of * the variations in the experiment. Otherwise it is false or undefined. */ inExperiment?: boolean; /** * Describes the validity of Big Segment information, if and only if the flag evaluation * required querying at least one Big Segment. * * - `'HEALTHY'`: The Big Segment query involved in the flag evaluation was successful, and * the segment state is considered up to date. * - `'STALE'`: The Big Segment query involved in the flag evaluation was successful, but * the segment state may not be up to date * - `'NOT_CONFIGURED'`: Big Segments could not be queried for the flag evaluation because * the SDK configuration did not include a Big Segment store. * - `'STORE_ERROR'`: The Big Segment query involved in the flag evaluation failed, for * instance due to a database error. */ bigSegmentsStatus?: "HEALTHY" | "STALE" | "NOT_CONFIGURED" | "STORE_ERROR"; } /** * An object that combines the result of a feature flag evaluation with information about * how it was calculated. * * This is the result of calling [[LDClient.variationDetail]]. * * For more information, see the [SDK reference guide](https://docs.launchdarkly.com/sdk/features/evaluation-reasons#nodejs-server-side). */ export interface LDEvaluationDetail { /** * The result of the flag evaluation. This will be either one of the flag's variations or * the default value that was passed to [[LDClient.variationDetail]]. */ value: LDFlagValue; /** * The index of the returned value within the flag's list of variations, e.g. 0 for the * first variation-- or `null` if the default value was returned. */ variationIndex?: number; /** * An object describing the main factor that influenced the flag evaluation value. */ reason: LDEvaluationReason; } /** * LaunchDarkly initialization options. */ export interface LDOptions { /** * The base URI for the LaunchDarkly server. * * Most users should use the default value. */ baseUri?: string; /** * The base URI for the LaunchDarkly streaming server. * * Most users should use the default value. */ streamUri?: string; /** * The base URI for the LaunchDarkly events server. * * Most users should use the default value. */ eventsUri?: string; /** * The connection timeout, in seconds. */ timeout?: number; /** * The capacity of the analytics events queue. * * The client buffers up to this many events in memory before flushing. If the capacity is * exceeded before the buffer is flushed, events will be discarded. */ capacity?: number; /** * Configures a logger for warnings and errors generated by the SDK. * * The logger can be any object that conforms to the [[LDLogger]] interface. * For a simple implementation that lets you filter by log level, see * [[basicLogger]]. You can also use an instance of `winston.Logger` from * the Winston logging package. * * If you do not set this property, the SDK uses [[basicLogger]] with a * minimum level of `info`. */ logger?: LDLogger; /** * A component that stores feature flags and related data received from LaunchDarkly. * * By default, this is an in-memory data structure. Database integrations are also * available, as described in the * [SDK features guide](https://docs.launchdarkly.com/sdk/concepts/data-stores). * * Some implementations provide the store implementation object itself, while others * provide a factory function that creates the store implementation based on the SDK * configuration; this property accepts either. */ featureStore?: LDFeatureStore | ((options: LDOptions) => LDFeatureStore); /** * Additional parameters for configuring the SDK's Big Segments behavior. * * Big Segments are a specific type of user segments. For more information, read the * LaunchDarkly documentation: https://docs.launchdarkly.com/home/users/big-segments * * By default, there is no configuration and Big Segments cannot be evaluated. In this * case, any flag evaluation that references a Big Segment will behave as if no users * are included in any Big Segments, and the {@link LDEvaluationReason} associated with any * such flag evaluation will have a `bigSegmentsStatus` of `"NOT_CONFIGURED"`. */ bigSegments?: LDBigSegmentsOptions; /** * A component that obtains feature flag data and puts it in the feature store. * * By default, this is the client's default streaming or polling component. It can be changed * for testing purposes; see [[FileDataSource]]. */ updateProcessor?: object; /** * The interval in between flushes of the analytics events queue, in seconds. */ flushInterval?: number; /** * The time between polling requests, in seconds. Ignored in streaming mode. */ pollInterval?: number; /** * Allows you to specify a host for an optional HTTP proxy. */ proxyHost?: string; /** * Allows you to specify a port for an optional HTTP proxy. * * Both the host and port must be specified to enable proxy support. */ proxyPort?: number; /** * When using an HTTP proxy, specifies whether it is accessed via `http` or `https`. */ proxyScheme?: string; /** * Allows you to specify basic authentication parameters for an optional HTTP proxy. * Usually of the form `username:password`. */ proxyAuth?: string; /** * Whether the client should be initialized in offline mode. */ offline?: boolean; /** * Whether streaming mode should be used to receive flag updates. * * This is true by default. If you set it to false, the client will use polling. * Streaming should only be disabled on the advice of LaunchDarkly support. */ stream?: boolean; /** * Sets the initial reconnect delay for the streaming connection, in seconds. * * The streaming service uses a backoff algorithm (with jitter) every time the connection needs * to be reestablished. The delay for the first reconnection will start near this value, and then * increase exponentially for any subsequent connection failures. * * The default value is 1. */ streamInitialReconnectDelay?: number; /** * Whether you are using the LaunchDarkly Relay Proxy in daemon mode. * * In this configuration, the client will not connect to LaunchDarkly to get feature flags, * but will instead get feature state from a database (Redis or another supported feature * store integration) that is populated by the Relay Proxy. By default, this is false. * To learn more, read [Using daemon mode](https://docs.launchdarkly.com/home/relay-proxy/using#using-daemon-mode). */ useLdd?: boolean; /** * Whether to send analytics events back to LaunchDarkly. By default, this is true. */ sendEvents?: boolean; /** * Whether all context attributes (except the contexy key) should be marked as private, and * not sent to LaunchDarkly. * * By default, this is false. */ allAttributesPrivate?: boolean; /** * The names of any context attributes that should be marked as private, and not sent * to LaunchDarkly. * * Any contexts sent to LaunchDarkly with this configuration active will have attributes with * these names removed. This is in addition to any attributes that were marked as private for an * individual context with {@link LDContextMeta.privateAttributes}. Setting * {@link LDOptions.allAttributesPrivate} to true overrides this. * * If and only if a parameter starts with a slash, it is interpreted as a slash-delimited path * that can denote a nested property within a JSON object. For instance, "/address/street" means * that if there is an attribute called "address" that is a JSON object, and one of the object's * properties is "street", the "street" property will be redacted from the analytics data but * other properties within "address" will still be sent. This syntax also uses the JSON Pointer * convention of escaping a literal slash character as "~1" and a tilde as "~0". */ privateAttributes?: Array; /** * The number of context keys that the event processor can remember at any one time, * so that duplicate context details will not be sent in analytics events. * * Defaults to 1000. */ contextKeysCapacity?: number; /** * The interval (in seconds) at which the event processor will reset its set of * known context keys. * * Defaults to 300. */ contextKeysFlushInterval?: number; /** * The number of user keys that the event processor can remember at any one time, * so that duplicate user details will not be sent in analytics events. * * Defaults to 1000. * * @deprecated Use contextKeysCapacity instead. */ userKeysCapacity?: number; /** * The interval (in seconds) at which the event processor will reset its set of * known user keys. * * Defaults to 300. * * @deprecated Use contextKeysFlushInterval instead. */ userKeysFlushInterval?: number; /** * Additional parameters to pass to the Node HTTPS API for secure requests. These can include any * of the TLS-related parameters supported by `https.request()`, such as `ca`, `cert`, and `key`. * * For more information, see the Node documentation for `https.request()` and `tls.connect()`. */ tlsParams?: LDTLSOptions; /** * Set to true to opt out of sending diagnostics data. * * Unless the `diagnosticOptOut` field is set to true, the client will send some diagnostics data to the * LaunchDarkly servers in order to assist in the development of future SDK improvements. These diagnostics * consist of an initial payload containing some details of SDK in use, the SDK's configuration, and the platform * the SDK is being run on, as well as payloads sent periodically with information on irregular occurrences such * as dropped events. */ diagnosticOptOut?: boolean; /** * The interval at which periodic diagnostic data is sent, in seconds. * * The default is 900 (every 15 minutes) and the minimum value is 60 (every minute). */ diagnosticRecordingInterval?: number; /** * For use by wrapper libraries to set an identifying name for the wrapper being used. * * This will be sent in User-Agent headers during requests to the LaunchDarkly servers to allow recording * metrics on the usage of these wrapper libraries. */ wrapperName?: string; /** * For use by wrapper libraries to report the version of the library in use. * * If `wrapperName` is not set, this field will be ignored. Otherwise the version string will be included in * the User-Agent headers along with the `wrapperName` during requests to the LaunchDarkly servers. */ wrapperVersion?: string; /** * Information about the application where the LaunchDarkly SDK is running. */ application?: { /** * A unique identifier representing the application where the LaunchDarkly SDK is running. * * This can be specified as any string value as long as it only uses the following characters: ASCII letters, * ASCII digits, period, hyphen, underscore. A string containing any other characters will be ignored. * * Example: `authentication-service` */ id?: string; /** * A unique identifier representing the version of the application where the LaunchDarkly SDK is running. * * This can be specified as any string value as long as it only uses the following characters: ASCII letters, * ASCII digits, period, hyphen, underscore. A string containing any other characters will be ignored. * * Example: `1.0.0` (standard version string) or `abcdef` (sha prefix) */ version?: string; } } /** * Additional parameters for configuring the SDK's Big Segments behavior. * * Big Segments are a specific type of user segments. For more information, read the LaunchDarkly * documentation: https://docs.launchdarkly.com/home/users/big-segments * * @see {@link LDOptions.bigSegments} */ export interface LDBigSegmentsOptions { /** * Specifies the storage component that provides Big Segments data. * * This property is mandatory. It must be obtained from one of the SDK's database integrations, * such as https://github.com/launchdarkly/node-server-sdk-redis. You will normally specify a * database implementation that matches how the LaunchDarkly Relay Proxy is configured, since the * Relay Proxy manages the Big Segment data. */ store: (options: LDOptions) => interfaces.BigSegmentStore; /** * The maximum number of users whose Big Segment state will be cached by the SDK at any given time. * * To reduce database traffic, the SDK maintains a least-recently-used cache by user key. When a feature * flag that references a Big Segment is evaluated for some user who is not currently in the cache, the * SDK queries the database for all Big Segment memberships of that user, and stores them together in a * single cache entry. If the cache is full, the oldest entry is dropped. * * A higher value for `userCacheSize` means that database queries for Big Segments will be done * less often for recently-referenced users, if the application has many users, at the cost of * increased memory used by the cache. * * Cache entries can also expire based on the setting of {@link userCacheTime}. * * If not specified, the default value is 1000. */ userCacheSize?: number; /** * The maximum length of time that the Big Segment state for a user will be cached by the SDK, * in seconds. * * See {@link userCacheSize} for more about this cache. A higher value for `userCacheTime` means * that database queries for the Big Segment state of any given user will be done less often, but * that changes to segment membership may not be detected as soon. * * If not specified, the default value is 5. Negative values are changed to the default. */ userCacheTime?: number; /** * The interval at which the SDK will poll the Big Segment store to make sure it is available * and to determine how long ago it was updated, in seconds. * * If not specified, the default value is 5. Zero or negative values are changed to the default. */ statusPollInterval?: number; /** * The maximum length of time between updates of the Big Segments data before the data is * considered out of date, in seconds. * * Normally, the LaunchDarkly Relay Proxy updates a timestamp in the Big Segment store at intervals to * confirm that it is still in sync with the LaunchDarkly data, even if there have been no changes to the * If the timestamp falls behind the current time by the amount specified in `staleAfter`, the SDK * assumes that something is not working correctly in this process and that the data may not be accurate. * * While in a stale state, the SDK will still continue using the last known data, but the status from * {@link interfaces.BigSegmentStoreStatusProvider.getStatus} will have `stale: true`, and any * {@link LDEvaluationReason} generated from a feature flag that references a Big Segment will have a * `bigSegmentsStatus` of `"STALE"`. * * If not specified, the default value is 120 (two minutes). Zero or negative values are changed to * the default. */ staleAfter?: number; } /** * Additional parameters to pass to the Node HTTPS API for secure requests. These can include any * of the TLS-related parameters supported by `https.request()`, such as `ca`, `cert`, and `key`. * * For more information, see the Node documentation for `https.request()` and `tls.connect()`. */ export interface LDTLSOptions { ca?: string | string[] | Buffer | Buffer[]; cert?: string | string[] | Buffer | Buffer[]; checkServerIdentity?: (servername: string, cert: any) => Error | undefined; ciphers?: string; pfx?: string | string[] | Buffer | Buffer[] | object[]; key?: string | string[] | Buffer | Buffer[] | object[]; passphrase?: string; rejectUnauthorized?: boolean; secureProtocol?: string; servername?: string; } /** * Meta attributes are used to control behavioral aspects of the Context. * They cannot be addressed in targeting rules. */ export interface LDContextMeta { /** * * Designate any number of Context attributes, or properties within them, as private: that is, * their values will not be sent to LaunchDarkly. * * Each parameter can be a simple attribute name, such as "email". Or, if the first character is * a slash, the parameter is interpreted as a slash-delimited path to a property within a JSON * object, where the first path component is a Context attribute name and each following * component is a nested property name: for example, suppose the attribute "address" had the * following JSON object value: * * ``` * {"street": {"line1": "abc", "line2": "def"}} * ``` * * Using ["/address/street/line1"] in this case would cause the "line1" property to be marked as * private. This syntax deliberately resembles JSON Pointer, but other JSON Pointer features * such as array indexing are not supported for Private. * * This action only affects analytics events that involve this particular Context. To mark some * (or all) Context attributes as private for all users, use the overall configuration for the * SDK. * See {@link LDOptions.allAttributesPrivate} and {@link LDOptions.privateAttributes}. * * The attributes "kind" and "key", and the "_meta" attributes cannot be made private. * * In this example, firstName is marked as private, but lastName is not: * * ``` * const context = { * kind: 'org', * key: 'my-key', * firstName: 'Pierre', * lastName: 'Menard', * _meta: { * privateAttributes: ['firstName'], * } * }; * ``` * * This is a metadata property, rather than an attribute that can be addressed in evaluations: * that is, a rule clause that references the attribute name "privateAttributes", will not use * this value, but would use a "privateAttributes" attribute set on the context. */ privateAttributes?: string[]; } interface LDContextCommon { /** * If true, the context will _not_ appear on the Contexts page in the LaunchDarkly dashboard. */ anonymous?: boolean; /** * A unique string identifying a context. */ key: string; /** * The context's name. * * You can search for contexts on the Contexts page by name. */ name?: string; /** * Meta attributes are used to control behavioral aspects of the Context, such as private * private attributes. See {@link LDContextMeta.privateAttributes} as an example. * * They cannot be addressed in targeting rules. */ _meta?: LDContextMeta; /** * Any additional attributes associated with the context. */ [attribute: string]: any; } /** * A context which represents a single kind. * * For a single kind context the 'kind' may not be 'multi'. * * ``` * const myOrgContext = { * kind: 'org', * key: 'my-org-key', * someAttribute: 'my-attribute-value' * }; * ``` * * The above context would be a single kind context representing an organization. It has a key * for that organization, and a single attribute 'someAttribute'. */ interface LDSingleKindContext extends LDContextCommon { /** * The kind of the context. */ kind: string; } /** * A context which represents multiple kinds. Each kind having its own key and attributes. * * A multi-context must contain `kind: 'multi'` at the root. * * ``` * const myMultiContext = { * // Multi-contexts must be of kind 'multi'. * kind: 'multi', * // The context is namespaced by its kind. This is an 'org' kind context. * org: { * // Each component context has its own key and attributes. * key: 'my-org-key', * someAttribute: 'my-attribute-value', * }, * user: { * key: 'my-user-key', * firstName: 'Bob', * lastName: 'Bobberson', * _meta: { * // Each component context has its own _meta attributes. This will only apply the this * // 'user' context. * privateAttributes: ['firstName'] * } * } * }; * ``` * * The above multi-context contains both an 'org' and a 'user'. Each with their own key, * attributes, and _meta attributes. */ interface LDMultiKindContext { /** * The kind of the context. */ kind: "multi", /** * The contexts which compose this multi-kind context. * * These should be of type LDContextCommon. "multi" is to allow * for the top level "kind" attribute. */ [kind: string]: "multi" | LDContextCommon; } /** * A LaunchDarkly context object. */ export type LDContext = LDUser | LDSingleKindContext | LDMultiKindContext; /** * A legacy LaunchDarkly user object. * * This type exists for easing migration to contexts, but code should be moved to use single/multi * contexts. * * The LDUser object is currently supported for ease of upgrade. It may be removed in a future * release. * In order to convert an LDUser into a LDSingleKindContext the following changes should * be made. * * 1.) Add a kind to the object. `kind: 'user'`. * * 2.) Move custom attributes to the top level of the object. * * 3.) Move `privateAttributeNames` to `_meta.privateAttributes`. * * ``` * const LDUser: user = { * key: '1234', * privateAttributeNames: ['myAttr'] * custom: { * myAttr: 'value' * } * } * * const LDSingleKindContext: context = { * kind: 'user', * key: '1234', * myAttr: 'value' * _meta: { * privateAttributes: ['myAttr'] * } * } * ``` */ export interface LDUser { /** * A unique string identifying a user. */ key: string; /** * The user's name. * * You can search for users on the User page by name. */ name?: string; /** * The user's first name. */ firstName?: string; /** * The user's last name. */ lastName?: string; /** * The user's email address. * * If an `avatar` URL is not provided, LaunchDarkly will use Gravatar * to try to display an avatar for the user on the Users page. */ email?: string; /** * An absolute URL to an avatar image for the user. */ avatar?: string; /** * The user's IP address. * * If you provide an IP, LaunchDarkly will use a geolocation service to * automatically infer a `country` for the user, unless you've already * specified one. */ ip?: string; /** * The country associated with the user. */ country?: string; /** * If true, the user will _not_ appear on the Users page in the LaunchDarkly dashboard. */ anonymous?: boolean; /** * Any additional attributes associated with the user. */ custom?: { [key: string]: | string | boolean | number | Array; }; /** * Specifies a list of attribute names (either built-in or custom) which should be * marked as private, and not sent to LaunchDarkly in analytics events. This is in * addition to any private attributes designated in the global configuration * with [[LDOptions.privateAttributeNames]] or [[LDOptions.allAttributesPrivate]]. */ privateAttributeNames?: Array; } /** * The LaunchDarkly client logger interface. * * The [[LDOptions.logger]] property accepts any object that conforms to this * interface. The SDK only uses four logging levels: `error`, `warn`, `info`, and * `debug`. It will call the corresponding method of the `LDLogger` either with a * single string argument, or with a format string and variable arguments in the * format used by Node's `util.format()`. * * The [Winston](https://github.com/winstonjs/winston) logging package provides a * logger that conforms to this interface, so if you have created a logger with * Winston, you can simply put it into the [[LDOptions.logger]] property. * * If you do not provide a logger object, the SDK uses the [[basicLogger]] * implementation with a minimum level of `info`. */ export interface LDLogger { /** * The error logger. * * @param args * A sequence of any JavaScript values. */ error(...args: any[]): void; /** * The warning logger. * * @param args * A sequence of any JavaScript values. */ warn(...args: any[]): void; /** * The info logger. * * @param args * A sequence of any JavaScript values. */ info(...args: any[]): void; /** * The debug logger. * * @param args * A sequence of any JavaScript values. */ debug(...args: any[]): void; } /** * Interface for a feature store component. * * The feature store is what the client uses to store feature flag data that has been received * from LaunchDarkly. By default, it uses an in-memory implementation; database integrations are * also available. Read the [SDK features guide](https://docs.launchdarkly.com/sdk/concepts/data-stores). * You will not need to use this interface unless you are writing your own implementation. * * Feature store methods can and should call their callbacks directly whenever possible, rather * than deferring them with setImmediate() or process.nextTick(). This means that if for any * reason you are updating or querying a feature store directly in your application code (which * is not part of normal use of the SDK) you should be aware that the callback may be executed * immediately. */ export interface LDFeatureStore { /** * Get an entity from the store. * * The store should treat any entity with the property `deleted: true` as "not found". * * @param kind * The type of data to be accessed. The store should not make any assumptions about the format * of the data, but just return a JSON object. The actual type of this parameter is * [[interfaces.DataKind]]. * * @param key * The unique key of the entity within the specified collection. * * @param callback * Will be called with the retrieved entity, or null if not found. The actual type of the result * value is [[interfaces.VersionedData]]. */ get(kind: object, key: string, callback: (res: object) => void): void; /** * Get all entities from a collection. * * The store should filter out any entities with the property `deleted: true`. * * @param kind * The type of data to be accessed. The store should not make any assumptions about the format * of the data, but just return an object in which each key is the `key` property of an entity * and the value is the entity. The actual type of this parameter is [[interfaces.DataKind]]. * * @param callback * Will be called with the resulting map. The actual type of the result value is * `interfaces.KeyedItems`. */ all(kind: object, callback: (res: object) => void): void; /** * Initialize the store, overwriting any existing data. * * @param allData * An object in which each key is the "namespace" of a collection (e.g. `"features"`) and * the value is an object that maps keys to entities. The actual type of this parameter is * `interfaces.FullDataSet`. * * @param callback * Will be called when the store has been initialized. */ init(allData: object, callback: () => void): void; /** * Delete an entity from the store. * * Deletion should be implemented by storing a placeholder object with the property * `deleted: true` and a `version` property equal to the provided version. In other words, * it should be exactly the same as calling `upsert` with such an object. * * @param kind * The type of data to be accessed. The actual type of this parameter is * [[interfaces.DataKind]]. * * @param key * The unique key of the entity within the specified collection. * * @param version * A number that must be greater than the `version` property of the existing entity in * order for it to be deleted. If it is less than or equal to the existing version, the * method should do nothing. * * @param callback * Will be called when the delete operation is complete. */ delete(kind: object, key: string, version: string, callback: () => void): void; /** * Add an entity or update an existing entity. * * @param kind * The type of data to be accessed. The actual type of this parameter is * [[interfaces.DataKind]]. * * @param data * The contents of the entity, as an object that can be converted to JSON. The store * should check the `version` property of this object, and should *not* overwrite any * existing data if the existing `version` is greater than or equal to that value. * The actual type of this parameter is [[interfaces.VersionedData]]. * * @param callback * Will be called after the upsert operation is complete. */ upsert(kind: object, data: object, callback: () => void): void; /** * Tests whether the store is initialized. * * "Initialized" means that the store has been populated with data, either by the client * having called `init()` within this process, or by another process (if this is a shared * database). * * @param callback * Will be called back with the boolean result. */ initialized(callback: (isInitialized: boolean) => void): void; /** * Releases any resources being used by the feature store. */ close(): void; } /** * The LaunchDarkly client stream processor * * The client uses this internally to retrieve updates from LaunchDarkly. * * @ignore */ export interface LDStreamProcessor { start: (fn?: (err?: any) => void) => void; stop: () => void; close: () => void; } /** * The LaunchDarkly client feature flag requestor * * The client uses this internally to retrieve feature flags from LaunchDarkly. * * @ignore */ export interface LDFeatureRequestor { requestObject: ( kind: any, key: string, cb: (err: any, body: any) => void ) => void; requestAllData: (cb: (err: any, body: any) => void) => void; } /** * Optional settings that can be passed to [[LDClient.allFlagsState]]. */ export interface LDFlagsStateOptions { /** * True if the state should include only flags that have been marked for use with the * client-side SDK. By default, all flags are included. */ clientSideOnly?: boolean; /** * True if evaluation reason data should be captured in the state object (see LDClient.variationDetail). * By default, it is not. */ withReasons?: boolean; /** * True if any flag metadata that is normally only used for event generation-- such as flag versions and * evaluation reasons-- should be omitted for any flag that does not have event tracking or debugging turned on. * This reduces the size of the JSON data if you are passing the flag state to the front end. */ detailsOnlyForTrackedFlags?: boolean; } /** * The LaunchDarkly SDK client object. * * Create this object with [[init]]. Applications should configure the client at startup time and continue * to use it throughout the lifetime of the application, rather than creating instances on the fly. * * Note that `LDClient` inherits from `EventEmitter`, so you can use the standard `on()`, `once()`, and * `off()` methods to receive events. The standard `EventEmitter` methods are not documented here; see the * {@link https://nodejs.org/api/events.html#events_class_eventemitter|Node API documentation}. For a * description of events you can listen for, see [[on]]. * * @see {@link https://docs.launchdarkly.com/sdk/server-side/node-js|SDK Reference Guide} */ export interface LDClient extends EventEmitter { /** * Tests whether the client has completed initialization. * * If this returns false, it means that the client has not yet successfully connected to LaunchDarkly. * It might still be in the process of starting up, or it might be attempting to reconnect after an * unsuccessful attempt, or it might have received an unrecoverable error (such as an invalid SDK key) * and given up. * * @returns * True if the client has successfully initialized. */ initialized(): boolean; /** * Returns a Promise that tracks the client's initialization state. * * The Promise will be resolved if the client successfully initializes, or rejected if client * initialization has failed unrecoverably (for instance, if it detects that the SDK key is invalid). * Keep in mind that unhandled Promise rejections can be fatal in Node, so if you call this method, * be sure to attach a rejection handler to it (or, if using `async`/`await`, a catch block). * * Note that you can also use event listeners ([[on]]) for the same purpose: the event `"ready"` * indicates success, and `"failed"` indicates failure. * * There is no built-in timeout for this method. If you want your code to stop waiting on the * Promise after some amount of time, you could use * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race|`Promise.race()`} * or one of the several NPM helper packages that provides a standard mechanism for this. Regardless * of whether you continue to wait, the SDK will still retry all connection failures indefinitely * unless it gets an unrecoverable error as described above. * * @returns * A Promise that will be resolved if the client initializes successfully, or rejected if it * fails. If successful, the result is the same client object. * * @example * This example shows use of Promise chaining methods for specifying handlers: * ```javascript * client.waitForInitialization().then(() => { * // do whatever is appropriate if initialization has succeeded * }).catch(err => { * // do whatever is appropriate if initialization has failed * }) * ``` * * @example * This example shows use of `async`/`await` syntax for specifying handlers: * ```javascript * try { * await client.waitForInitialization(); * // do whatever is appropriate if initialization has succeeded * } catch (err) { * // do whatever is appropriate if initialization has failed * } * ``` */ waitForInitialization(): Promise; /** * Determines the variation of a feature flag for a context. * * @param key * The unique key of the feature flag. * @param context * The context requesting the flag. The client will generate an analytics event to register * this context with LaunchDarkly if the context does not already exist. * @param defaultValue * The default value of the flag, to be used if the value is not available from LaunchDarkly. * @param callback * A Node-style callback to receive the result value. If omitted, you will receive a Promise instead. * @returns * If you provided a callback, then nothing. Otherwise, a Promise which will be resolved * with the result value. */ variation( key: string, context: LDContext, defaultValue: LDFlagValue, callback?: (err: any, res: LDFlagValue) => void ): Promise; /** * Determines the variation of a feature flag for a context, along with information about how it was * calculated. * * The `reason` property of the result will also be included in analytics events, if you are * capturing detailed event data for this flag. * * For more information, see the [SDK reference guide](https://docs.launchdarkly.com/sdk/features/evaluation-reasons#nodejs-server-side). * * @param key * The unique key of the feature flag. * @param context * The context requesting the flag. The client will generate an analytics event to register * this context with LaunchDarkly if the context does not already exist. * @param defaultValue * The default value of the flag, to be used if the value is not available from LaunchDarkly. * @param callback * A Node-style callback to receive the result (as an [[LDEvaluationDetail]]). If omitted, you * will receive a Promise instead. * @returns * If you provided a callback, then nothing. Otherwise, a Promise which will be resolved * with the result (as an [[LDEvaluationDetail]]). */ variationDetail( key: string, context: LDContext, defaultValue: LDFlagValue, callback?: (err: any, res: LDEvaluationDetail) => void ): Promise; /** * Builds an object that encapsulates the state of all feature flags for a given context. * This includes the flag values and also metadata that can be used on the front end. This * method does not send analytics events back to LaunchDarkly. * * The most common use case for this method is to bootstrap a set of client-side * feature flags from a back-end service. Call the `toJSON()` method of the returned object * to convert it to the data structure used by the client-side SDK. * * @param context * The context requesting the feature flags. * @param options * Optional [[LDFlagsStateOptions]] to determine how the state is computed. * @param callback * A Node-style callback to receive the result (as an [[LDFlagsState]]). If omitted, you * will receive a Promise instead. * @returns * If you provided a callback, then nothing. Otherwise, a Promise which will be resolved * with the result as an [[LDFlagsState]]. */ allFlagsState( context: LDContext, options?: LDFlagsStateOptions, callback?: (err: Error, res: LDFlagsState) => void ): Promise; /** * Computes an HMAC signature of a context signed with the client's SDK key. * * For more information, see the JavaScript SDK Reference Guide on * [Secure mode](https://github.com/launchdarkly/js-client#secure-mode). * * @param context * The context properties. * * @returns * The hash string. */ secureModeHash(context: LDContext): string; /** * Discards all network connections, background tasks, and other resources held by the client. * * Do not attempt to use the client after calling this method. */ close(): void; /** * Tests whether the client is configured in offline mode. * * @returns * True if the `offline` property is true in your [[LDOptions]]. */ isOffline(): boolean; /** * Tracks that a context performed an event. * * LaunchDarkly automatically tracks pageviews and clicks that are specified in the Metrics * section of the dashboard. This can be used to track custom metrics (goals) or other events that do * not currently have metrics. * * Note that event delivery is asynchronous, so the event may not actually be sent until later; * see [[flush]]. * * If the context is omitted or has no key, the client will log a warning and will not send an event. * * @param key * The name of the event, which may correspond to a metric in experiments. * @param context * The context to track. * @param data * Optional additional information to associate with the event. * @param metricValue * A numeric value used by the LaunchDarkly experimentation feature in numeric custom metrics. Can * be omitted if this event is used by only non-numeric metrics. This field will also be returned * as part of the custom event for Data Export. */ track(key: string, context: LDContext, data?: any, metricValue?: number): void; /** * Identifies a context to LaunchDarkly. * * This simply creates an analytics event that will transmit the given user properties to * LaunchDarkly, so that the context will be visible on your dashboard even if you have not * evaluated any flags for that user. It has no other effect. * * If the context is omitted or has no key, the client will log a warning * and will not send an event. * * @param context * The context properties. Must contain at least the `key` property. */ identify(context: LDContext): void; /** * Flushes all pending analytics events. * * Normally, batches of events are delivered in the background at intervals determined by the * `flushInterval` property of [[LDOptions]]. Calling `flush()` triggers an immediate delivery. * However, like Node I/O in general, this is still an asynchronous operation so you must still * use Promise chaining, a callback, or `async`/`await` to detect when it has finished or failed. * * @param callback * A function which will be called when the flush completes (meaning that all pending events * have been delivered to LaunchDarkly). If omitted, you will receive a Promise instead. * * @returns * If you provided a callback, then nothing. Otherwise, a Promise which resolves once * flushing is finished. Note that the Promise will be rejected if the HTTP request * fails, so be sure to attach a rejection handler to it. */ flush(callback?: (err: Error, res: boolean) => void): Promise; /** * A mechanism for tracking the status of a Big Segment store. * * This object has methods for checking whether the Big Segment store is (as far as the SDK * knows) currently operational and tracking changes in this status. See * {@link interfaces.BigSegmentStoreStatusProvider} for more about this functionality. */ readonly bigSegmentStoreStatusProvider: interfaces.BigSegmentStoreStatusProvider; /** * Registers an event listener that will be called when the client triggers some type of event. * * This is the standard `on` method inherited from Node's `EventEmitter`; see the * {@link https://nodejs.org/api/events.html#events_class_eventemitter|Node API docs} for more * details on how to manage event listeners. Here is a description of the event types defined * by `LDClient`. * * - `"ready"`: Sent only once, when the client has successfully connected to LaunchDarkly. * Alternately, you can detect this with [[waitForInitialization]]. * - `"failed"`: Sent only once, if the client has permanently failed to connect to LaunchDarkly. * Alternately, you can detect this with [[waitForInitialization]]. * - `"error"`: Contains an error object describing some abnormal condition that the client has detected * (such as a network error). * - `"update"`: The client has received a change to a feature flag. The event parameter is an object * containing a single property, `key`, the flag key. Note that this does not necessarily mean the flag's * value has changed for any particular context, only that some part of the flag configuration was changed. * - `"update:KEY"`: The client has received a change to the feature flag whose key is KEY. This is the * same as `"update"` but allows you to listen for a specific flag. * * @param event the name of the event to listen for * @param listener the function to call when the event happens */ on(event: string | symbol, listener: (...args: any[]) => void): this; // The following are symbols that LDClient inherits from EventEmitter, which we are declaring // again here only so that we can use @ignore to exclude them from the generated docs. // Unfortunately it does not seem possible to exclude these inherited methods en masse without // using a Typedoc plugin. /** @ignore */ addListener(event: string | symbol, listener: (...args: any[]) => void): this; /** @ignore */ emit(event: string | symbol, ...args: any[]): boolean; /** @ignore */ eventNames(): Array; /** @ignore */ getMaxListeners(): number; /** @ignore */ listenerCount(type: string | symbol): number; /** @ignore */ listeners(event: string | symbol): Function[]; /** @ignore */ prependListener(event: string | symbol, listener: (...args: any[]) => void): this; /** @ignore */ prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; /** @ignore */ rawListeners(event: string | symbol): Function[]; /** @ignore */ removeAllListeners(event?: string | symbol): this; /** @ignore */ removeListener(event: string | symbol, listener: (...args: any[]) => void): this; /** @ignore */ setMaxListeners(n: number): this; /** @ignore */ once(event: string | symbol, listener: (...args: any[]) => void): this; /** @ignore */ off(event: string | symbol, listener: (...args: any[]) => void): this; } /** * Provides a simple [[LDLogger]] implementation. * * This logging implementation uses a simple format that includes only the log level * and the message text. Output is written to the standard error stream (`console.error`). * You can filter by log level as described in [[BasicLoggerOptions.level]]. * * To use the logger created by this function, put it into [[LDOptions.logger]]. If * you do not set [[LDOptions.logger]] to anything, the SDK uses a default logger * that is equivalent to `ld.basicLogger({ level: 'info' })`. * * @param options Configuration for the logger. If no options are specified, the * logger uses `{ level: 'info' }`. * * @example * This example shows how to use `basicLogger` in your SDK options to enable console * logging only at `warn` and `error` levels. * ```javascript * const ldOptions = { * logger: ld.basicLogger({ level: 'warn' }), * }; * ``` * * @example * This example shows how to use `basicLogger` in your SDK options to cause log * output to go to `console.log` instead of `console.error`. * ```javascript * const ldOptions = { * logger: ld.basicLogger({ destination: console.log }), * }; * ``` */ export function basicLogger( options?: BasicLoggerOptions ): LDLogger; /** * Configuration for [[basicLogger]]. */ export interface BasicLoggerOptions { /** * The lowest level of log message to enable. * * See [[LDLogLevel]] for a list of possible levels. Setting a level here causes * all lower-importance levels to be disabled: for instance, if you specify * `'warn'`, then `'debug'` and `'info'` are disabled. * * If not specified, the default is `'info'` (meaning that `'debug'` is disabled). */ level?: LDLogLevel; /** * An optional function to use to print each log line. * * If this is specified, `basicLogger` calls it to write each line of output. The * argument is a fully formatted log line, not including a linefeed. The function * is only called for log levels that are enabled. * * If not specified, the default is `console.error`. * * Setting this property to anything other than a function will cause SDK * initialization to fail. */ destination?: (line: string) => void, } /** * Logging levels that can be used with [[basicLogger]]. * * Set [[BasicLoggerOptions.level]] to one of these values to control what levels * of log messages are enabled. Going from lowest importance (and most verbose) * to most importance, the levels are `'debug'`, `'info'`, `'warn'`, and `'error'`. * You can also specify `'none'` instead to disable all logging. */ export type LDLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none'; /** * Configuration for [[FileDataSource]]. * * @deprecated Import this type from the `launchdarkly-node-server-sdk/integrations` module instead. * It will be removed from the main SDK module in a future release. */ export interface FileDataSourceOptions { paths: Array; autoUpdate?: boolean; logger?: LDLogger | object; } /** * Creates an object that allows you to use local files as a source of feature flag state, * instead of connecting to LaunchDarkly. This would typically be used in a test environment. * * @deprecated Import this function from the `launchdarkly-node-server-sdk/integrations` module instead. * It will be removed from the main SDK module in a future release. */ export function FileDataSource( options: FileDataSourceOptions ): object; } /** * This module contains tools for connecting the LaunchDarkly client to other software, or * to test fixtures. */ declare module 'launchdarkly-node-server-sdk/integrations' { import { LDLogger } from 'launchdarkly-node-server-sdk'; /** * Configuration for [[FileDataSource]]. */ export interface FileDataSourceOptions { /** * The path(s) of the file(s) that FileDataSource will read. */ paths: Array; /** * True if FileDataSource should reload flags whenever one of the data files is modified. * This feature uses Node's `fs.watch()` API, so it is subject to * the limitations described [here](https://nodejs.org/docs/latest/api/fs.html#fs_fs_watch_filename_options_listener). */ autoUpdate?: boolean; /** * Configures a logger for warnings and errors. This can be a custom logger or an instance of * `winston.Logger`. By default, it uses the same logger as the rest of the SDK. */ logger?: LDLogger | object; } /** * Creates an object that allows you to use local files as a source of feature flag state, * instead of connecting to LaunchDarkly. This would typically be used in a test environment. * * For more information about this feature, see the * [SDK features guide](https://docs.launchdarkly.com/sdk/features/flags-from-files#nodejs-server-side). * * To use this component, call `FileDataSource(options)` and store the result in the `updateProcessor` * property of your LaunchDarkly client configuration: * * const { FileDataSource } = require('launchdarkly-node-server-sdk/integrations'); * * const dataSource = FileDataSource({ paths: [ myFilePath ] }); * const config = { updateProcessor: dataSource }; * * This will cause the client not to connect to LaunchDarkly to get feature flags, and use * the file data instead. * * The client may still make network connections to send analytics events, unless you have * disabled this in your configuration by setting [[LDOptions.sendEvents]] to `false`. * * The supported file formats are as follows: * * - JSON files in the format described in the * [SDK features guide](https://docs.launchdarkly.com/sdk/features/flags-from-files#nodejs-server-side) * are always supported. * - The SDK can also read YAML files with an equivalent schema, if you explicitly install * the [`yaml`](https://www.npmjs.com/package/yaml) package in your application. This * package is not installed by default, to avoid adding to the size of the SDK bundle * for this rarely-used feature. The SDK is compatible with any version of the package * that supports calling `yaml.parse(string)` with no custom options. * * @param options * Configuration for the data source. You should at least set the `paths` property. * @returns * An object to put in the `updateProcessor` property for [[LDOptions]]. */ export function FileDataSource( options: FileDataSourceOptions ): object; /** * A mechanism for providing dynamically updatable feature flag state in a simplified form to * an SDK client in test scenarios. * * This function constructs a new [[TestData]] object. See [[TestData]] for usage details. * * @example * const { TestData } = require('launchdarkly-node-server-sdk/interfaces'); * * const td = TestData(); * testData.update(td.flag("flag-key-1").booleanFlag().variationForAll(true)); * const client = new LDClient(sdkKey, { updateProcessor: td }); * * // flags can be updated at any time: * td.update(td.flag("flag-key-2") * .variationForContext("user", "some-user-key", true) * .fallthroughVariation(false)); */ export function TestData(): TestData; /** * A mechanism for providing dynamically updatable feature flag state in a simplified form to an SDK * client in test scenarios. * * Unlike [[FileData]], this mechanism does not use any external resources. It provides only * the data that the application has put into it using the [[TestData.update]] method. * * @example * const { TestData } = require('launchdarkly-node-server-sdk/interfaces'); * * const td = TestData(); * testData.update(td.flag("flag-key-1").booleanFlag().variationForAll(true)); * const client = new LDClient(sdkKey, { updateProcessor: td }); * * // flags can be updated at any time: * td.update(td.flag("flag-key-2") * .variationForContext("user", "some-user-key", true) * .fallthroughVariation(false)); * * The above example uses a simple boolean flag, but more complex configurations are possible using * the methods of the [[TestDataFlagBuilder]] that is returned by [[TestData.flag]]. [[TestDataFlagBuilder]] * supports many of the ways a flag can be configured on the LaunchDarkly dashboard, but does not * currently support 1. rule operators other than "in" and "not in", or 2. percentage rollouts. * * If the same `TestData` instance is used to configure multiple `LDClient` instances, * any changes made to the data will propagate to all of the `LDClient`s. * * @see [[FileDataSource]] */ export interface TestData { /** * Creates or copies a [[TestDataFlagBuilder]] for building a test flag configuration. * * If the flag key has already been defined in this `TestData` instance, * then the builder starts with the same configuration that was last * provided for this flag. * * Otherwise, it starts with a new default configuration in which the flag * has `true` and `false` variations, is `true` for all users when targeting * is turned on and `false` otherwise, and currently has targeting turned on. * You can change any of those properties and provide more complex behavior * using the `TestDataFlagBuilder` methods. * * Once you have set the desired configuration, pass the builder to * [[TestData.update]]. * * @param key the flag key * @returns a flag configuration builder * */ flag(key: string): TestDataFlagBuilder; /** * Updates the test data with the specified flag configuration. * * This has the same effect as if a flag were added or modified in the * LaunchDarkly dashboard. It immediately propagates the flag changes to * any [[LDClient]] instance(s) that you have already configured to use * this `TestData`. If no `LDClient` has been started yet, it simply adds * this flag to the test data which will be provided to any `LDClient` * that you subsequently configure. * * Any subsequent changes to this `TestDataFlagBuilder` instance do not affect * the test data unless you call `update` again. * * @param flagBuilder a flag configuration builder * @return a promise that will resolve when the feature stores are updated */ update(flagBuilder: TestDataFlagBuilder): Promise; /** * Copies a full feature flag data model object into the test data. * * It immediately propagates the flag change to any [[LDClient]] instance(s) that you have already * configured to use this `TestData`. If no [[LDClient]] has been started yet, it simply adds * this flag to the test data which will be provided to any LDClient that you subsequently * configure. * * Use this method if you need to use advanced flag configuration properties that are not supported by * the simplified [[TestDataFlagBuilder]] API. Otherwise it is recommended to use the regular * [[flag]]/[[update]] mechanism to avoid dependencies on details of the data model. * * You cannot make incremental changes with [[flag]]/[[update]] to a flag that has been added in this way; * you can only replace it with an entirely new flag configuration. * * @param flagConfig the flag configuration as a JSON object * @return a promise that will resolve when the feature stores are updated */ usePreconfiguredFlag(flagConfig: any): Promise; /** * Copies a full segment data model object into the test data. * * It immediately propagates the change to any [[LDClient]] instance(s) that you have already * configured to use this `TestData`. If no [[LDClient]] has been started yet, it simply adds * this segment to the test data which will be provided to any LDClient that you subsequently * configure. * * This method is currently the only way to inject segment data, since there is no builder * API for segments. It is mainly intended for the SDK's own tests of segment functionality, * since application tests that need to produce a desired evaluation state could do so more easily * by just setting flag values. * * @param segmentConfig the segment configuration as a JSON object * @return a promise that will resolve when the feature stores are updated */ usePreconfiguredSegment(segmentConfig: any): Promise; } /** * A builder for feature flag configurations to be used with [[TestData]]. */ export interface TestDataFlagBuilder { /** * A shortcut for setting the flag to use the standard boolean configuration. * * This is the default for all new flags created with [[TestData.flag]]. The * flag will have two variations, `true` and `false` (in that order). It * will return `false` whenever targeting is off and `true` when targeting * is on unless other settings specify otherwise. * * @return the flag builder */ booleanFlag(): TestDataFlagBuilder; /** * Sets the allowable variation values for the flag. * * The values may be of any JSON-compatible type: boolean, number, string, array, * or object. For instance, a boolean flag normally has `variations(true, false)`; * a string-valued flag might have `variations("red", "green")`; etc. * * @param values any number of variation values * @return the flag builder */ variations(...values: any[]): TestDataFlagBuilder; /** * Sets targeting to be on or off for this flag. * * The effect of this depends on the rest of the flag configuration, just * as it does on the real LaunchDarkly dashboard. In the default configuration * that you get from calling [[TestData.flag]] with a new flag key, the flag * will return `false` whenever targeting is off and `true` when targeting * is on. * * @param targetingOn true if targeting should be on * @return the flag builder */ on(targetingOn: boolean): TestDataFlagBuilder; /** * Specifies the fallthrough variation for a flag. The fallthrough is * the value that is returned if targeting is on and the user was not * matched by a more specific target or rule. * * If a boolean is supplied, and the flag was previously configured with * other variations, this also changes it to a boolean flag. * * @param variation * either `true` or `false` or the index of the desired fallthrough * variation: 0 for the first, 1 for the second, etc. * @return the flag builder */ fallthroughVariation(variation: boolean | number): TestDataFlagBuilder; /** * Specifies the off variation for a flag. This is the variation that is * returned whenever targeting is off. * * If a boolean is supplied, and the flag was previously configured with * other variations, this also changes it to a boolean flag. * * @param variation * either `true` or `false` or the index of the desired off * variation: 0 for the first, 1 for the second, etc. * @return the flag builder */ offVariation(variation: boolean | number): TestDataFlagBuilder; /** * Sets the flag to always return the specified variation for all contexts. * * Targeting is switched on, any existing targets or rules are removed, * and the fallthrough variation is set to the specified value. The off * variation is left unchanged. * * If a boolean is supplied, and the flag was previously configured with * other variations, this also changes it to a boolean flag. * * @param varation * either `true` or `false` or the index of the desired variation: * 0 for the first, 1 for the second, etc. * @return the flag builder */ variationForAll(variation: boolean | number): TestDataFlagBuilder; /** * Sets the flag to always return the specified variation value for all contexts. * * The value may be of any valid JSON type. This method changes the flag to have * only a single variation, which is this value, and to return the same variation * regardless of whether targeting is on or off. Any existing targets or rules * are removed. * * @param value The desired value to be returned for all contexts. * @return the flag builder */ valueForAll(value: any): TestDataFlagBuilder; /** * Sets the flag to return the specified variation for a specific context key * when targeting is on. The context kind for contexts created with this method * will be 'user'. * * This has no effect when targeting is turned off for the flag. * * If the variation is a boolean value and the flag was not already a boolean * flag, this also changes it to be a boolean flag. * * If the variation is an integer, it specifies a variation out of whatever * variation values have already been defined. * * @param contextKey a context key * @param variation * either `true` or `false` or the index of the desired variation: * 0 for the first, 1 for the second, etc. * @return the flag builder */ variationForUser(contextKey: string, variation: boolean | number): TestDataFlagBuilder; /** * Sets the flag to return the specified variation for a specific context key * when targeting is on. * * This has no effect when targeting is turned off for the flag. * * If the variation is a boolean value and the flag was not already a boolean * flag, this also changes it to be a boolean flag. * * If the variation is an integer, it specifies a variation out of whatever * variation values have already been defined. * * @param contextKind a context kind * @param contextKey a context key * @param variation * either `true` or `false` or the index of the desired variation: * 0 for the first, 1 for the second, etc. * @return the flag builder */ variationForContext(contextKind: string, contextKey: string, variation: boolean | number): TestDataFlagBuilder; /** * Removes any existing rules from the flag. This undoes the effect of methods * like [[ifMatch]]. * * @return the same flag builder */ clearRules(): TestDataFlagBuilder; /** * Removes any existing targets from the flag. This undoes the effect of * methods like [[variationForContext]]. * * @return the same flag builder */ clearAlltargets(): TestDataFlagBuilder; /** * Starts defining a flag rule using the "is one of" operator. * * For example, this creates a rule that returnes `true` if the name is * "Patsy" or "Edina": * * testData.flag('flag') * .ifMatch('user', name', 'Patsy', 'Edina') * .thenReturn(true) * * @param contextKind the kind of the context * @param attribute the context attribute to match against * @param values values to compare to * @return * a flag rule builder; call `thenReturn` to finish the rule * or add more tests with another method like `andMatch` */ ifMatch(contextKind: string, attribute: string, ...values: any): TestDataRuleBuilder; /** * Starts defining a flag rule using the "is not one of" operator. * * For example, this creates a rule that returnes `true` if the name is * neither "Saffron" nor "Bubble": * * testData.flag('flag') * .ifNotMatch('user', 'name', 'Saffron', 'Bubble') * .thenReturn(true) * * @param contextKind the kind of the context * @param attribute the user attribute to match against * @param values values to compare to * @return * a flag rule builder; call `thenReturn` to finish the rule * or add more tests with another method like `andNotMatch` */ ifNotMatch(contextKind: string, attribute: string, ...values: any): TestDataRuleBuilder; } /** * A builder for feature flag rules to be used with [[TestDataFlagBuilder]]. * * In the LaunchDarkly model, a flag can have any number of rules, and * a rule can have any number of clauses. A clause is an individual test * such as "name is 'X'". A rule matches a user if all of the rule's * clauses match the user. * * To start defining a rule, use one of the flag builder's matching methods * such as `ifMatch`. This defines the first clause for the rule. Optionally, * you may add more clauses with the rule builder's methods such as `andMatch`. * Finally, call `thenReturn` to finish defining the rule. */ export interface TestDataRuleBuilder { /** * Adds another clause using the "is one of" operator. * * For example, this creates a rule that returns `true` if the name is * "Patsy" and the country is "gb": * * testData.flag('flag') * .ifMatch('name', 'Patsy') * .andMatch('country', 'gb') * .thenReturn(true) * * @param contextKind the kind of the context * @param attribute the user attribute to match against * @param values values to compare to * @return the flag rule builder */ andMatch(contextKind: string, attribute: string, ...values: any): TestDataRuleBuilder; /** * Adds another clause using the "is not one of" operator. * * For example, this creates a rule that returns `true` if the name is * "Patsy" and the country is not "gb": * * testData.flag('flag') * .ifMatch('name', 'Patsy') * .andNotMatch('country', 'gb') * .thenReturn(true) * * @param contextKind the kind of the context * @param attribute the user attribute to match against * @param values values to compare to * @return the flag rule builder */ andNotMatch(contextKind: string, attribute: string, ...values: any): TestDataRuleBuilder; /** * Finishes defining the rule, specifying the result value as either a boolean or an index * * If the variation is a boolean value and the flag was not already a boolean * flag, this also changes it to be a boolean flag. * * If the variation is an integer, it specifies a variation out of whatever * variation values have already been defined. * @param variation * either `true` or `false` or the index of the desired variation: * 0 for the first, 1 for the second, etc. * @return the flag rule builder */ thenReturn(variation: boolean | number): TestDataFlagBuilder; } } /** * This module contains types that allow customization of LaunchDarkly components, and * interfaces to other advanced SDK features. * * Most applications will not need to refer to these types. You will use them if you are creating a * plug-in component, such as a database integration, or if you use advanced SDK features. * * Currently this module contains no implementation code, but only TypeScript interfaces. */ declare module 'launchdarkly-node-server-sdk/interfaces' { import { EventEmitter } from 'events'; /** * A read-only data store that allows querying of user membership in Big Segments. * * Big Segments are a specific type of user segments. For more information, read the LaunchDarkly * documentation: https://docs.launchdarkly.com/home/users/big-segments */ export interface BigSegmentStore { /** * Queries information about the overall state of the store. * * The resolved value of the Promise should always be a [[BigSegmentStoreMetadata]] object. If * the store is accessible but contains no metadata, the object's `lastUpToDate` property can be * undefined. If the store is not accessible due to a database error, the method can throw an * exception/reject the promise. * * This method will be called only when the SDK needs the latest state, so it should not be cached. * * @returns a Promise for the result of the query */ getMetadata(): Promise; /** * Queries the store for a snapshot of the current segment state for a specific user. * * The userHash is a base64-encoded string produced by hashing the user key as defined by * the Big Segments specification; the store implementation does not need to know the details * of how this is done, because it deals only with already-hashed keys, but the string can be * assumed to only contain characters that are valid in base64. * * The resolved value of the Promise should be either a [[BigSegmentStoreMembership]], or * undefined if the user is not referenced in any Big Segments (this is equivalent to a * [[BigSegmentStoreMembership]] that has no properties). * * @param userHash identifies the user * @returns a Promise for the result of the query. */ getUserMembership(userHash: string): Promise; /** * Releases any resources being used by the store. */ close(): void; } /** * Values returned by BigSegmentStore.getMetadata(). */ export interface BigSegmentStoreMetadata { /** * The Unix epoch millisecond timestamp of the last update to the BigSegmentStore. It is * undefined if the store has never been updated. */ lastUpToDate?: number } /** * The return type of [[BigSegmentStore.getUserMembership]], describing which Big Segments a * specific user is included in or excluded from. * * This object may be cached by the SDK, so it should not be modified after it is created. It * is a snapshot of the segment membership state at one point in time. */ export interface BigSegmentStoreMembership { /** * Each property key in this object is a "segment reference", which is how segments are * identified in Big Segment data. This string is not identical to the segment key-- the SDK * will add other information. The store implementation should not be concerned with the * format of the string. * * A true value means that the user is explicitly included in the segment. A false value * means that the user is explicitly excluded from the segment-- and is not also explicitly * included (that is, if both an include and an exclude existed in the data, the include would * take precedence). If the user's status in a particular segment is undefined, there should * be no key or value for that segment. */ [segmentRef: string]: boolean; } /** * An interface for querying the status of a Big Segment store. * * The Big Segment store is the component that receives information about Big Segments, normally * from a database populated by the LaunchDarkly Relay Proxy. Big Segments are a specific type * of user segments. For more information, read the LaunchDarkly documentation: * https://docs.launchdarkly.com/home/users/big-segments * * An implementation of this interface is returned by {@link LDClient.bigSegmentStoreStatusProvider}. * Application code never needs to implement this interface. * * Note that this type inherits from `EventEmitter`, so you can use the standard `on()`, `once()`, * and `off()` methods to receive status change events. The standard `EventEmitter` methods are * not documented here; see the {@link https://nodejs.org/api/events.html#events_class_eventemitter|Node API documentation}. * The type of the status change event is `"change"`, and its value is the same value that would * be returned by {@link getStatus}. */ export interface BigSegmentStoreStatusProvider extends EventEmitter { /** * Gets the current status of the store, if known. * * @returns a {@link BigSegmentStoreStatus}, or `undefined` if the SDK has not yet queried the * Big Segment store status */ getStatus(): BigSegmentStoreStatus | undefined; /** * Gets the current status of the store, querying it if the status has not already been queried. * * @returns a Promise for the status of the store */ requireStatus(): Promise; } /** * Information about the status of a Big Segment store, provided by {@link BigSegmentStoreStatusProvider}. * * Big Segments are a specific type of user segments. For more information, read the LaunchDarkly * documentation: https://docs.launchdarkly.com/home/users/big-segments */ export interface BigSegmentStoreStatus { /** * True if the Big Segment store is able to respond to queries, so that the SDK can * evaluate whether a user is in a segment or not. * * If this property is false, the store is not able to make queries (for instance, it may not have * a valid database connection). In this case, the SDK will treat any reference to a Big Segment * as if no users are included in that segment. Also, the {@link LDEvaluationReason} associated * with any flag evaluation that references a Big Segment when the store is not available will * have a `bigSegmentsStatus` of `"STORE_ERROR"`. */ available: boolean; /** * True if the Big Segment store is available, but has not been updated within the amount of time * specified by {@link LDBigSegmentsOptions.staleAfter}. * * This may indicate that the LaunchDarkly Relay Proxy, which populates the store, has stopped * running or has become unable to receive fresh data from LaunchDarkly. Any feature flag * evaluations that reference a Big Segment will be using the last known data, which may be out * of date. */ stale: boolean; } /** * Used internally to describe the type of data being queried or updated, such as feature flags or * user segments. * * This is the actual type of the `kind` parameter in `LDFeatureStore` methods. Those methods are * still declared as taking `any` for backward compatibility, but in the future they will reference * this type. */ export interface DataKind { /** * A string such as `"features"` or `"segments"` which can be used in keys to distinguish this * kind of data from other kinds. */ namespace: string; } /** * Used internally to describe the basic properties of stored data such as feature flags or user * segments. * * This is the actual type of parameters and return values in `LDFeatureStore` methods that refer * to a flag or segment item. Those methods still use the `object` type for backward compatibility. */ export interface VersionedData { /** * The item's unique key, such as a feature flag key. */ key: string; /** * A version number that LaunchDarkly will increment each time this item is changed. */ version: number; /** * True if this is a deleted item placeholder (tombstone). */ deleted?: boolean; } /** * Used internally to describe a set of stored data items of the same kind, such as feature flags * or user segments. The string key for each item is the same as the item's `key` property. */ export type KeyedItems = Record; /** * Used internally for data store implementations that require items in an ordered list rather * than as object properties. */ export interface DataCollection { /** * Describes the kind of items, such as feature flags or user segments. */ kind: DataKind; /** * An ordered list of items of this kind. */ items: Array; } /** * Used internally to describe a full set of environment data, which can include both feature * flags and user segments. The string key for each item is the `namespace` property of a * [[DataKind]]. */ export type FullDataSet = Record>; /** * Base interface for a simplified subset of the functionality of `LDFeatureStore`, to be used in * conjunction with `CachingStoreWrapper`. * * @see [[PersistentDataStore]] * @see [[PersistentDataStoreNonAtomic]] */ export interface PersistentDataStoreBase { /** * Get an entity from the store. * * @param kind * The type of data to be accessed. The store should not make any assumptions about the format * of the data, but just return a JSON object. * * @param key * The unique key of the entity within the specified collection. * * @param callback * Will be called with the retrieved entity, or null if not found. */ getInternal(kind: DataKind, key: string, callback: (res: VersionedData) => void): void; /** * Get all entities from a collection. * * The store should filter out any entities with the property `deleted: true`. * * @param kind * The type of data to be accessed. The store should not make any assumptions about the format * of the data, but just return an object in which each key is the `key` property of an entity * and the value is the entity. The actual type of this parameter is [[interfaces.DataKind]]. * * @param callback * Will be called with the resulting map. */ getAllInternal(kind: DataKind, callback: (res: KeyedItems) => void): void; /** * Add an entity or update an existing entity. * * @param kind * The type of data to be accessed. * * @param item * The contents of the entity, as an object that can be converted to JSON. The store * should check the `version` property of this object, and should *not* overwrite any * existing data if the existing `version` is greater than or equal to that value. * * @param callback * Will be called after the upsert operation is complete. */ upsertInternal(kind: DataKind, item: VersionedData, callback: (err: Error, finalItem: VersionedData) => void): void; /** * Tests whether the store is initialized. * * "Initialized" means that the store has been populated with data, either by the client * having called `init()` within this process, or by another process (if this is a shared * database). * * @param callback * Will be called back with the boolean result. */ initializedInternal(callback: (isInitialized: boolean) => void): void; /** * Releases any resources being used by the feature store. */ close(): void; } /** * Interface for a simplified subset of the functionality of `LDFeatureStore`, to be used in * conjunction with `CachingStoreWrapper`. * * @see [[PersistentDataStoreNonAtomic]] */ export interface PersistentDataStore extends PersistentDataStoreBase { /** * Initialize the store, overwriting any existing data. * * @param allData * An object in which each key is the "namespace" of a collection (e.g. `"features"`) and * the value is an object that maps keys to entities. * * @param callback * Will be called when the store has been initialized. */ initInternal(allData: FullDataSet, callback: () => void): void; } /** * Interface for a simplified subset of the functionality of `LDFeatureStore`, to be used in * conjunction with `CachingStoreWrapper`. * * This is a variant of [[PersistentDataStore]] for databases that require somewhat different * initialization semantics, where we must specify a consistent ordering of writes. * * @see [[PersistentDataStore]] */ export interface PersistentDataStoreNonAtomic { /** * Initialize the store, overwriting any existing data. * * @param allData * A list of data item collections in the order they should be written. * * @param callback * Will be called when the store has been initialized. */ initOrderedInternal(allData: Array>, callback: () => void): void; } } /** * @ignore */ declare module 'launchdarkly-node-server-sdk/streaming' { import { LDOptions, LDFeatureRequestor, LDStreamProcessor } from 'launchdarkly-node-server-sdk'; function StreamProcessor( sdkKey: string, options: LDOptions, requestor: LDFeatureRequestor ): LDStreamProcessor; export = StreamProcessor; } /** * @ignore */ declare module 'launchdarkly-node-server-sdk/requestor' { import { LDOptions, LDFeatureRequestor } from 'launchdarkly-node-server-sdk'; function Requestor(sdkKey: string, options: LDOptions): LDFeatureRequestor; export = Requestor; } /** * @ignore */ declare module 'launchdarkly-node-server-sdk/feature_store' { import { LDFeatureStore } from 'launchdarkly-node-server-sdk'; function InMemoryFeatureStore(): LDFeatureStore; export = InMemoryFeatureStore; } /** * @ignore */ declare module 'launchdarkly-node-server-sdk/caching_store_wrapper' { import { LDFeatureStore } from 'launchdarkly-node-server-sdk'; import { PersistentDataStore, PersistentDataStoreNonAtomic } from 'launchdarkly-node-server-sdk/interfaces'; /** * A base feature store implementation used by database integrations. */ class CachingStoreWrapper implements LDFeatureStore { /** * Creates a feature store implementation with standard caching behavior for a persistent store. * * @param storeImplementation internal implementation object for a specific database type * @param ttl cache TTL in seconds, or 0 for no caching * @param description name of the database */ public constructor( storeImplementation: PersistentDataStore | PersistentDataStoreNonAtomic, ttl: number, description: string ); public get(kind: object, key: string, callback: (res: object) => void): void; public all(kind: object, callback: (res: object) => void): void; public init(allData: object, callback: () => void): void; public delete(kind: object, key: string, version: string, callback: () => void): void; public upsert(kind: object, data: object, callback: () => void): void; public initialized(callback: (isInitialized: boolean) => void): void; public close(): void; } export = CachingStoreWrapper; } /** * @ignore */ declare module 'launchdarkly-node-server-sdk/sharedtest/store_tests' { import * as ld from 'launchdarkly-node-server-sdk'; import * as interfaces from 'launchdarkly-node-server-sdk/interfaces'; /** * A standard test suite that should be run on every persistent feature store implementation. * * This test suite uses `jest` and should be run inside a `describe` block. * * Store implementations must meet the following requirements to be testable with this suite: * * - They must support setting a key prefix. The tests will always pass a non-empty prefix. * * - They must support caching with a positive cache TTL in seconds, or a zero cache TTL to * disable caching. * * - All instances created during the tests must share the same database, so that the tests * can verify that they can read pre-existing data and will not interfere with any keys * that use a different prefix. * * Do not call `runPersistentFeatureStoreTests` and `runBigSegmentStoreTests` from tests * in separate files, if `jest` parallelization is enabled; they can interfere with each * other's database state if they are interleaved. * * @param createStore A function that creates a feature store instance with the specified * key prefix and cache TTL. * @param clearExistingData An asynchronous function that removes any existing data from * the database for the specified key prefix only. * @param setConcurrentModificationHook If provided, this enables additional tests in which * another store instance is used to make a competing update to the same data while an * update is already in progress. The function should create a store instance which, * during any upsert operation, will call "hook" and await the result at a point when a * race condition is possible (for instance, after reading the old version of an item but * before writing the new version, if those are not atomic). Caching should be disabled. */ export function runPersistentFeatureStoreTests( createStore: (prefix: string, cacheTTL: number, logger: ld.LDLogger) => ld.LDFeatureStore, clearExistingData: (prefix: string) => Promise, createStoreWithConcurrentUpdateHook?: (prefix: string, logger: ld.LDLogger, hook: () => Promise) => void, ): void; /** * A standard test suite that should be run on every Big Segment store implementation. * * This test suite uses `jest` and should be run inside a `describe` block. * * Store implementations must meet the following requirements to be testable with this suite: * * - They must support setting a key prefix. The tests will always pass a non-empty prefix. * * - All instances created during the tests must share the same database, so that the tests * can verify that they can read pre-existing data and will not interfere with any keys * that use a different prefix. * * Do not call `runPersistentFeatureStoreTests` and `runBigSegmentStoreTests` from tests * in separate files, if `jest` parallelization is enabled; they can interfere with each * other's database state if they are interleaved. * * @param createStore A function that creates a Big Segment store instance with the * specified key prefix. * @param clearExistingData An asynchronous function that removes any existing data from * the database for the specified key prefix only. * @param setMetadata An asynchronous function that updates the store metadata. * @param setSegments An asynchronous function that sets a user's Big Segment state. */ export function runBigSegmentStoreTests( createStore: (prefix: string, logger: ld.LDLogger) => interfaces.BigSegmentStore, clearExistingData: (prefix: string) => Promise, setMetadata: (prefix: string, metadata: interfaces.BigSegmentStoreMetadata) => Promise, setSegments: (prefix: string, userHashKey: string, included: string[], excluded: string[]) => Promise ): void; }