@amadeus-it-group/kassette
Version:
Development server, used mainly for testing, which proxies requests and is able to easily manage local mocks.
1,257 lines (1,230 loc) • 71.4 kB
TypeScript
/**
* kassette is a development server, used mainly for testing, which proxies requests and is able to easily manage local mocks.
*
* @packageDocumentation
*/
import * as crypto_2 from 'crypto';
import { Http2ServerRequest } from 'http2';
import { Http2ServerResponse } from 'http2';
import { IncomingHttpHeaders } from 'http';
import { IncomingMessage } from 'http';
import { ServerHttp2Stream } from 'http2';
import { ServerResponse } from 'http';
import { Socket } from 'net';
import { URL as URL_2 } from 'url';
/**
* Specifies the argument expected to start kassette programmatically with {@link runFromAPI}.
*
* @public
*/
export declare interface APIOptions {
/**
* kassette configuration passed through the API.
*
* @remarks
*
* If {@link APIOptions.configurationPath|configurationPath} is also specified, both configurations are merged,
* but `apiConfiguration` has the least precedence.
* However, this object is also forwarded to the configuration file's {@link IConfigurationFile.getConfiguration|getConfiguration}
* method, as {@link GetConfigurationProps.apiConfiguration|apiConfiguration}, so you can apply your own logic to determine what configuration
* to actually use.
*/
readonly apiConfiguration?: ConfigurationSpec;
/**
* Path to a configuration file, if the configuration should be loaded from a configuration file.
*/
readonly configurationPath?: string;
/**
* Specifies the context argument passed to the {@link IConfigurationFile.getConfiguration|getConfiguration} function defined in the
* configuration file (only used if {@link APIOptions.configurationPath|configurationPath} is specified).
*/
readonly fileConfigurationContext?: any;
}
/**
* Type of the argument expected by {@link IMock.checksum|checksum}.
* It specifies which data from the request to include in the checksum.
*
* @remarks
* To include or exclude data, not every kind of data from the request has the
* same complexity. For instance, the HTTP method is simple: use it or don't
* use it. But for things like query parameters, headers, body: you might want to
* select/filter.
*
* @public
*/
export declare interface ChecksumArgs {
/**
* Specifies the hash algorithm. Default value is `sha256`.
* Check Node.js API for more information: {@link https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options|crypto.createHash(type)}.
*/
type?: string;
/**
* Specifies the output format. Default value is `hex`.
* Check Node.js API for more information: {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding|hash.digest(format)}.
*/
format?: crypto_2.BinaryToTextEncoding;
/**
* Specifies whether to include the protocol in the hash. The default value is `false`.
*/
protocol?: IncludableSpec | boolean;
/**
* Specifies whether and how to include the hostname in the hash. The default value is `false`.
*/
hostname?: FilterableSpec<string> | boolean;
/**
* Specifies whether to include the port in the hash. The default value is `false`.
*/
port?: IncludableSpec | boolean;
/**
* Specifies whether to include the method in the hash. The default value is `false`.
*/
method?: IncludableSpec | boolean;
/**
* Specifies whether and how to include the pathname part of the url in the hash. The default value is `false`.
*/
pathname?: FilterableSpec<string> | boolean;
/**
* Specifies whether and how to include the body of the request in the hash. The default value is `true`.
*/
body?: FilterableSpec<Buffer, Buffer | string> | boolean;
/**
* Specifies whether and how to include the query part of the url in the hash. The default value is `true`.
*/
query?: ListOrFilter | boolean;
/**
* Specifies whether and how to include the headers in the hash.
* The default value is `false`.
*/
headers?: ListOrFilter | boolean;
/**
* Any custom value (which can be JSON stringified) to be added in the content
* to be hashed.
*/
customData?: any | null;
}
/**
* The set of possible properties defined through the CLI
* (it is reduced since it can't contain runtime values)
*
* @public
*/
export declare interface CLIConfigurationSpec {
/**
* If true, will simplify the logging output, logging only one line
* when the request is received but nothing else afterwards.
*/
readonly skipLog?: boolean;
/**
* The port on which the proxy should listen. Note that kassette accepts both http and https connections on this port.
*
* @remarks
*
* If the port is not available, it will fail and stop the program; try again with another, available port.
* If the port is set to 0, the proxy will listen on a random port
* (actually depends on the OS implementation): use the callback {@link ConfigurationSpec.onListen|onListen} to catch its value.
*/
readonly port?: number;
/**
* The hostname on which the proxy should listen.
* Uses `127.0.0.1` by default, which only allows local connections.
* To allow remote connections, use the ip address of the specific network interface that should be allowed to connect
* or the unspecified IPv4 (`0.0.0.0`) or IPv6 (`::`) address.
*
* @remarks
*
* Note that kassette has not been reviewed for security issues.
* It is intended to be used in a safe local/testing environment.
* Binding it to an open connection can result in compromising your
* computer or your network.
*/
readonly hostname?: string;
/**
* The default mode.
*
* @remarks
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setMode|mock.setMode}.
*/
readonly mode?: Mode;
/**
* The default mocks format.
*
* @remarks
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setMocksFormat|mock.setMocksFormat}.
*
* The default value of the global `mocksFormat` setting is `folder`, except in the following case:
* if the global {@link CLIConfigurationSpec.mocksHarFile|mocksHarFile} setting is defined
* and the global {@link CLIConfigurationSpec.mocksFolder|mocksFolder} setting is not defined,
* then the default value of the global `mocksFormat` setting is `har`.
*/
readonly mocksFormat?: MocksFormat;
/**
* Whether to save the content used to create a checksum when creating a new mock with a checksum.
*
* @remarks
*
* The default value of the global `saveChecksumContent` setting is `true`.
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setSaveChecksumContent|mock.setSaveChecksumContent}.
*/
readonly saveChecksumContent?: boolean;
/**
* Whether to save {@link RequestTimings | detailed timings} when creating a new mock.
*
* @remarks
*
* The default value of the global `saveDetailedTimings` setting is `true`.
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setSaveDetailedTimings|mock.setSaveDetailedTimings}.
*/
readonly saveDetailedTimings?: boolean;
/**
* Whether to save the input request data (headers, method, URL) when creating a new mock.
*
* @remarks
*
* The default value of the global `saveInputRequestData` setting is `true`.
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setSaveInputRequestData|mock.setSaveInputRequestData}.
*/
readonly saveInputRequestData?: boolean;
/**
* Whether to save the content of the input request body when creating a new mock.
*
* @remarks
*
* The default value of the global `saveInputRequestBody` setting is `true`.
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setSaveInputRequestBody|mock.setSaveInputRequestBody}.
*/
readonly saveInputRequestBody?: boolean;
/**
* Whether to save the forwarded request data (headers, method, URL) when creating a new mock.
*
* @remarks
*
* The default value of the global `saveForwardedRequestData` setting is `null`, which means
* `true` when `mocksFormat` is `folder` (for backward-compatibility), and
* `false` when `mocksFormat` is `har`.
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setSaveForwardedRequestData|mock.setSaveForwardedRequestData}.
*/
readonly saveForwardedRequestData?: boolean | null;
/**
* Whether to save the forwarded request body when creating a new mock.
*
* @remarks
*
* The default value of the global `saveForwardedRequestData` setting is `null`, which means
* `true` when `mocksFormat` is `folder` (for backward-compatibility), and
* `false` when `mocksFormat` is `har`.
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setSaveForwardedRequestBody|mock.setSaveForwardedRequestBody}.
*/
readonly saveForwardedRequestBody?: boolean | null;
/**
* The default delay.
*
* @remarks
*
* It can be changed at request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setDelay|mock.setDelay}.
*/
readonly delay?: Delay;
/**
* When the {@link CLIConfigurationSpec.mocksFormat|mocks format} is 'folder', specifies
* the default root folder of all mocks, from which specific mocks paths will be resolved.
*
* @remarks
*
* It can be changed at a request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setMocksFolder|mock.setMocksFolder}.
*/
readonly mocksFolder?: string;
/**
* When the {@link CLIConfigurationSpec.mocksFormat|mocks format} is 'har', specifies
* the default har file to use. If the file name has the `.yml` or `.yaml` extension, the YAML format
* is used instead of the standard JSON format to read and write the file.
*
* @remarks
*
* It can be changed at a request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setMocksHarFile|mock.setMocksHarFile}.
*/
readonly mocksHarFile?: string;
/**
* Time in milliseconds during which a har file is kept in memory after its last usage.
*/
readonly harFileCacheTime?: number;
/**
* The URL of the remote backend, from which only the protocol, hostname and port are used.
* Can be left `null`, in which case anything leading to sending the request to the remote backend will trigger an exception.
* Can also contain the special `"*"` value, which means reading from the request the remote backend to target. This is useful when using kassette as a browser proxy.
*
* @remarks
*
* It can be changed at a request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setRemoteURL|mock.setRemoteURL}.
*/
readonly remoteURL?: string | null;
/**
* Default mode for `CONNECT` requests.
*
* @remarks
*
* It can be changed at a request level in the {@link ConfigurationSpec.onProxyConnect|onProxyConnect} method
* through {@link IProxyConnectAPI.setMode|setMode}.
*/
readonly proxyConnectMode?: ProxyConnectMode;
/**
* Path to a PEM-encoded CA (Certificate Authority) certificate and key file,
* created if it does not exist. If not provided, the certificate and key are
* generated but only kept in memory. This certificate and key are used as needed
* to sign certificates generated on the fly for any HTTPS connection intercepted
* by kassette.
*
* @remarks
*
* You can optionally import in the browser the TLS certificate from this
* file in order to remove the warning when connecting to HTTPS websites
* through kassette.
*/
readonly tlsCAKeyPath?: string | null;
/**
* Size in bits of generated RSA keys.
*/
readonly tlsKeySize?: number;
/**
* Enables http/2.0 protocol in the kassette server.
*/
readonly http2?: boolean;
}
/* Excluded from this release type: CLIOptions */
/**
* The id of the source of the resolved value.
*
* @public
*/
export declare type ConfigurationPropertySource = 'cli' | 'file' | 'api' | 'default';
/**
* Augments the CLI spec to add all pure runtime properties,
* that can be defined through the configuration file only
*
* @public
*/
export declare interface ConfigurationSpec extends CLIConfigurationSpec {
/**
* Callback called for every HTTP request that kassette receives (with the exception of `CONNECT` requests,
* which trigger the call of {@link ConfigurationSpec.onProxyConnect|onProxyConnect} instead).
* @param parameters - exposes the API to control how to process the request
*/
hook?(parameters: HookAPI): void | Promise<void>;
/**
* Function called to get or set the key of a mock in a har file, as explained in {@link HarKeyManager}.
*
* @remarks
*
* It can be changed at a request level in the {@link ConfigurationSpec.hook|hook} method
* through {@link IMock.setMocksHarKeyManager|mock.setMocksHarKeyManager}.
*/
readonly mocksHarKeyManager?: HarKeyManager;
/**
* Callback called when kassette receives a request with the
* {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT|HTTP CONNECT method},
* which usually happens when kassette is used as a browser proxy and the browser is trying to
* connect to a secure web site with the https protocol.
* @param parameters - exposes the API to control how to process the request
*/
onProxyConnect?(parameters: IProxyConnectAPI): void | Promise<void>;
/**
* Callback called when the proxy is started and listening.
*
* @param parameters - the port property contains the port on which the
* proxy is listening.
*/
onListen?(parameters: {
port: number;
}): void;
/**
* Callback called when the proxy is programmatically closed (which can
* be done by using the callback returned from {@link runFromAPI})
*/
onExit?(): void;
/**
* Custom implementation of the {@link ConsoleSpec} interface, with methods
* {@link ConsoleSpec.log|log} and {@link ConsoleSpec.error|error},
* each receiving one single argument of any type.
* Useful to capture the logs of the application.
*/
readonly console?: ConsoleSpec;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'har',
* specifies a list of mime types that will attempt to parse the request/response body as JSON.
* If the list includes an empty string: '' and there is no mimeType set in the request, it will attempt to parse the body as JSON.
* This will only be applicable to request bodies if {@link IMock.saveInputRequestBody|saveInputRequestBody} is set to true
* Default value will be [] and will only be overridden by {@link IMock.setHarMimeTypesParseJson|setHarMimeTypesParseJson}
*/
readonly harMimeTypesParseJson?: string[];
}
/**
* A connection intercepted by kassette
*
* @public
*/
export declare interface Connection {
/** protocol such as `http` or `https`, without the trailing `:` */
protocol: string;
/** target hostname */
hostname: string;
/** target port */
port: number;
}
/**
* Console with logging methods.
* @public
*/
export declare interface ConsoleSpec {
/**
* Logs a message.
* @param message - message to log
*/
log(message: any): void;
/**
* Logs an error message.
* @param message - error message to log
*/
error(message: any): void;
}
/**
* Delay that will be used to send the response to the client
* when the data is taken from the local mock.
*
* @remarks
*
* It can be expressed either as a direct value (in milliseconds) or as the
* `'recorded'` string, which means to use the delay recorded
* in the local mock (in the {@link MockData.time|time} field).
*
* @public
*/
export declare type Delay = 'recorded' | number;
/**
* Interface used in {@link ChecksumArgs} for each piece of data that can be filtered (i.e. modified) before it is included
* in the hash computed by the {@link IMock.checksum|checksum} method.
*
* @public
*/
export declare interface FilterableSpec<I, O = I> extends IncludableSpec {
/**
* A function used to filter (i.e. modify) the piece of data before it is included in the hash.
* If no function is given, the unmodified piece of data is used.
* @param input - piece of data to filter
* @returns The modified piece of data. Note that the filter function can optionally be
* asynchronous, in which case it is expected to return a promise of the modified piece
* of data.
*/
filter?(input: I): O | Promise<O>;
}
/**
* Parameter of the {@link IConfigurationFile.getConfiguration|getConfiguration} function
* (which a kassette configuration file is supposed to export).
*
* @public
*/
export declare interface GetConfigurationProps {
/**
* If run from the CLI, this is the configuration coming from the CLI.
* Otherwise it is an empty object.
*/
cliConfiguration: CLIConfigurationSpec;
/**
* If run from the API, this is the configuration coming from the {@link runFromAPI} call.
* Otherwise it is an empty object.
*/
apiConfiguration: ConfigurationSpec;
/**
* If run from the API, this is the context value provided (if any) through {@link runFromAPI}.
* Otherwise it is undefined.
*/
context: any;
}
/**
* Information about the response body, as stored in a har file.
*
* @public
*/
export declare interface HarFormatContent {
/**
* Size of the content in bytes.
*/
size?: number;
/**
* Number of bytes saved by compression. This is not implemented by kassette.
*/
compression?: number;
/**
* Value of the `Content-Type` response header.
*/
mimeType?: string;
/**
* Response body.
*
* @remarks
*
* The response body can be encoded in base64 if this is specified in the {@link HarFormatContent.encoding | encoding} field.
*/
text?: string;
/**
* Encoding used for the {@link HarFormatContent.text | text} field, such as "base64".
*/
encoding?: string;
/**
* Any comment as a string. This is not used by kassette.
*/
comment?: string;
/**
* Response body saved as an object.
*/
json?: any;
}
/**
* Detailed information about a request and its response, as stored in a har file.
*
* @public
*/
export declare interface HarFormatEntry {
/**
* Content used to create a checksum
*
* @remarks
*
* kassette only includes this field if {@link IMock.saveChecksumContent | saveChecksumContent} is true and
* if the {@link IMock.checksum | checksum} method was called.
*/
_kassetteChecksumContent?: string;
/**
* Key used by kassette to select the correct mock to replay.
*
* @remarks
*
* This field contains the value passed to {@link IMock.setMockHarKey} when used with the default
* {@link ConfigurationSpec.mocksHarKeyManager | mocksHarKeyManager}.
*/
_kassetteMockKey?: string;
/**
* Detailed information about the request forwarded to the remote server.
*
* @remarks
*
* kassette only includes this field if {@link IMock.saveForwardedRequestData | saveInputRequestData} is true.
*/
_kassetteForwardedRequest?: HarFormatRequest;
/**
* Reference to the parent page. This is not implemented in kassette.
*/
pageref?: string;
/**
* Date and time of the request start, as a string in ISO format (YYYY-MM-DDThh:mm:ss.sTZD).
*/
startedDateTime?: string;
/**
* Total time of the request, in milliseconds. This is the sum of all timings in the {@link HarFormatEntry.timings | timings object}.
*/
time?: number;
/**
* Detailed information about the input request.
*
* @remarks
*
* kassette only includes this field if {@link IMock.saveInputRequestData | saveInputRequestData} is true.
*/
request?: HarFormatRequest;
/**
* Detailed information about the response.
*/
response?: HarFormatResponse;
/**
* Information about the cache. This is not implemented in kassette.
*/
cache?: any;
/**
* Detailed timing information about request/response round trip.
*
* @remarks
*
* kassette only includes this field if {@link IMock.saveDetailedTimings | saveDetailedTimings} is true.
*/
timings?: HarFormatTimings;
/**
* Server IP address. This is not implemented in kassette.
*/
serverIPAddress?: string;
/**
* Unique ID of the TCP/IP connection. This is not implemented in kassette.
*/
connection?: string;
/**
* Any comment as a string. This is not used by kassette.
*/
comment?: string;
}
/**
* Information about a header or a query parameter, as stored in a har file.
*
* @public
*/
export declare interface HarFormatNameValuePair {
/**
* Name of the header or query parameter.
*/
name: string;
/**
* Value of the header or the query parameter.
*/
value: string;
/**
* Any comment as a string. This is not used by kassette.
*/
comment?: string;
}
/**
* Information about a request body, as stored in a har file.
*
* @public
*/
export declare interface HarFormatPostData {
/**
* Value of the `Content-Type` request header, if present.
*/
mimeType?: string;
/**
* List of posted parameters. This is not implemented in kassette.
*
* @remarks
*
* kassette always fills the {@link HarFormatPostData.text | text field} and never uses the params field.
*/
params?: any[];
/**
* Posted data, as a (binary) string.
*/
text?: string;
/**
* Any comment as a string. This is not used by kassette.
*/
comment?: string;
/**
* Response body saved as an object.
*/
json?: any;
}
/**
* Detailed information about a request, as stored in a har file.
*
* @public
*/
export declare interface HarFormatRequest {
/**
* Request method, such as "GET" or "POST".
*/
method?: string;
/**
* Request URL.
*/
url?: string;
/**
* Request HTTP version, such as "HTTP/1.1".
*/
httpVersion?: string;
/**
* Information about cookies. This is not implemented in kassette.
*/
cookies?: any[];
/**
* List of request headers.
*/
headers?: HarFormatNameValuePair[];
/**
* List of query parameters.
*/
queryString?: HarFormatNameValuePair[];
/**
* Information about the request body.
*
* @remarks
*
* kassette only includes this field if {@link IMock.saveInputRequestBody | saveInputRequestBody} is true
* (or, for the {@link HarFormatEntry._kassetteForwardedRequest | _kassetteForwardedRequest}.postData field,
* if {@link IMock.saveForwardedRequestBody | saveForwardedRequestBody} is true).
*/
postData?: HarFormatPostData;
/**
* Total number of bytes from the start of the HTTP request message until (and including) the double CRLF before the body,
* or -1 if it is unknown. kassette always sets -1 for this field.
*/
headersSize?: number;
/**
* Size of the request body in bytes or -1 if it is unknown.
*/
bodySize?: number;
/**
* Any comment as a string. This is not used by kassette.
*/
comment?: string;
}
/**
* Detailed information about a response, as stored in a har file.
*
* @public
*/
export declare interface HarFormatResponse {
/**
* Response status.
*/
status?: number;
/**
* Response status text.
*/
statusText?: string;
/**
* Response HTTP version, such as "HTTP/1.1".
*/
httpVersion?: string;
/**
* Information about cookies. This is not implemented in kassette.
*/
cookies?: any[];
/**
* List of response headers.
*/
headers?: HarFormatNameValuePair[];
/**
* Information about the response body.
*/
content?: HarFormatContent;
/**
* Content of the `Location` response header if present.
*/
redirectURL?: string;
/**
* Total number of bytes from the start of the HTTP response message until (and including) the double CRLF before the body,
* or -1 if it is unknown. kassette always sets -1 for this field.
*/
headersSize?: number;
/**
* Size of the response body in bytes, or -1 if it is unknown.
*/
bodySize?: number;
/**
* Any comment as a string. This is not used by kassette.
*/
comment?: string;
}
/**
* Details about the time spent for each phase of a request-response round trip, as stored in a har file.
*
* @public
*/
export declare interface HarFormatTimings extends RequestTimings {
/**
* Any comment as a string. This is not used by kassette.
*/
comment?: string;
}
/**
* Each entry in a har file is supposed to have a corresponding unique key (a string).
* The har key manager is both a getter and a setter for the key of an entry.
*
* @remarks
*
* The har key manager is a function that is called either to get the key of an entry (when
* the key parameter is undefined) or to set it (when the key parameter is defined).
*
* It should not modify the entry when the key parameter is undefined.
*
* When the key parameter is defined, the har key manager is supposed to change the provided entry, in order to store the
* key in it, because after the call, the entry will be persisted in the har file. In this case, the key parameter either
* comes from a call to {@link IMock.setMockHarKey}, or from {@link IMock.defaultMockHarKey | defaultMockHarKey}.
*
* In order to compute the {@link IMock.defaultMockHarKey | defaultMockHarKey} property, the har key manager
* is called with an entry that includes the request but not the response (and with an undefined key parameter).
*
* In all cases, the har key manager is expected to return the key of the entry. If an array is returned (which can
* be nested), it is flattened with null items removed, and joined with forward slashes to produce a string.
*
* The default har key manager is expected to work fine for most use cases, especially when working with a har file recorded
* with kassette. With the default har key manager, if a key is set with {@link IMock.setMockHarKey}, it is stored in the
* {@link HarFormatEntry._kassetteMockKey | _kassetteMockKey} field. Otherwise, the default key is the concatenation of the request
* method and url, with a separating forward slash. It can be useful to replace the default har key manager with a custom one especially
* when working with har files that are produced by other applications than kassette, if the default key is not convenient.
*
* @example
*
* Here is the default har key manager:
* ```ts
* export const defaultHarKeyManager: HarKeyManager = (entry: HarFormatEntry, key?: string) => {
* const defaultKey = joinPath(entry._kassetteMockKey ?? [entry.request?.method, entry.request?.url]);
* if (key && key !== defaultKey) {
* entry._kassetteMockKey = key;
* return key;
* }
* return defaultKey;
* };
* ```
*
* @public
*/
export declare type HarKeyManager = (entry: HarFormatEntry, key?: string) => RecursiveArray<string | null | undefined>;
/**
* A map from strings to strings or array of strings
*
* @public
*/
declare type Headers_2 = IncomingHttpHeaders;
export { Headers_2 as Headers }
/**
* Parameter of the {@link ConfigurationSpec.hook|hook} callback, that is called for every
* HTTP request that kassette receives.
* @public
*/
export declare interface HookAPI {
/**
* Provides the API to specify how to handle the HTTP request.
*/
mock: IMock;
/**
* The console object as specified in the {@link ConfigurationSpec.console|configuration},
* otherwise it is the global console object (usually the one of the platform).
*/
console: ConsoleSpec;
}
/**
* Interface that a kassette configuration file should export.
*
* @public
*/
export declare interface IConfigurationFile {
/**
* Function returning the configuration to be used by kassette.
* @param arg - contains information that can be used to build
* the configuration.
*/
getConfiguration(arg: GetConfigurationProps): ConfigurationSpec | Promise<ConfigurationSpec>;
}
/**
* Contains the value and origin of a configuration property.
* @public
*/
export declare interface IConfigurationProperty<PropertyType> {
/** The resolved value of the property */
readonly value: PropertyType;
/** The id of the source of the resolved value of the property */
readonly origin: ConfigurationPropertySource;
}
/**
* A handier wrapper around a request
*
* @public
*/
export declare interface IFetchedRequest {
/** The original Node.js object representing the request */
readonly original: IncomingMessage | Http2ServerRequest;
/** The connections stack */
readonly connectionsStack: readonly Readonly<Connection>[];
/** The last connection in connectionsStack */
readonly connection: Readonly<Connection>;
/** The URL */
readonly url: URL_2;
/** The headers */
readonly headers: IncomingHttpHeaders;
/** The query parameters taken from the URL, as a read-only map of strings */
readonly queryParameters: Readonly<Record<string, string>>;
/** The protocol part of the URL, without the trailing `:` */
readonly protocol: string;
/** The hostname part of the URL */
readonly hostname: string;
/** The port part of the URL */
readonly port: string;
/** The HTTP method */
readonly method: string;
/** The path part of the URL */
readonly pathname: string;
/** The body content */
readonly body: Buffer;
}
/**
* The resulting configuration that was merged from its different {@link ConfigurationPropertySource|sources}.
*
* @remarks
*
* It contains the path to the configuration file in `filePath`, and also for each property defined in {@link ConfigurationSpec},
* there is an {@link IConfigurationProperty} object describing the {@link IConfigurationProperty.origin|origin} of the property
* and its {@link IConfigurationProperty.value|value}.
*
* @public
*/
export declare type IMergedConfiguration = {
/**
* The path of the configuration file
*/
readonly filePath: string | null;
} & {
readonly [k in keyof ConfigurationSpec]-?: IConfigurationProperty<Required<ConfigurationSpec>[k]>;
};
/**
* The public interface exposed to the end user to handle a given request and the associated mock and response.
*
* An object implementing this interface is passed to the {@link ConfigurationSpec.hook|hook} function, under property `mock` of the single argument object.
*
* @public
*/
export declare interface IMock {
/**
* The wrapper around the input request
*/
readonly request: IFetchedRequest;
/**
* The wrapper around the output response
*/
readonly response: IResponse;
/**
* Link to global configuration options
*/
readonly options: MockingOptions;
/**
* The current mode, configured either by a call to {@link IMock.setMode|setMode},
* or by {@link CLIConfigurationSpec.mode|the global setting}.
*/
readonly mode: Mode;
/**
* Sets the {@link IMock.mode|mode} for the current request.
* @param mode - mode to set, or null to use the default value from {@link CLIConfigurationSpec.mode|the global setting}
*/
setMode(mode: Mode | null): void;
/**
* The current remote URL, configured either by a call to {@link IMock.setRemoteURL|setRemoteURL},
* or by {@link CLIConfigurationSpec.remoteURL|the global setting}.
*/
readonly remoteURL: string | null;
/**
* Sets the {@link IMock.remoteURL|remote URL} for the current request.
* @param url - the URL to set, or null to use the default value from {@link CLIConfigurationSpec.remoteURL|the global setting}
*/
setRemoteURL(url: string | null): void;
/**
* The currently computed delay that will be applied, configured either by a call to {@link IMock.setDelay|setDelay},
* or by {@link CLIConfigurationSpec.delay|the global setting}. Note that if the delay is set to `recorded` and the local mock
* to use is not yet loaded, the value returned by this getter will be the default delay and not the recorded delay.
*/
readonly delay: number;
/**
* Sets the {@link IMock.delay|delay} that will be used to send the response to the client
* when the data is taken from the local mock.
* @param delay - can be either a number (to directly specify the delay in milliseconds),
* `'recorded'` (to read the delay from the {@link MockData.time|time} property of an already recorded mock if any)
* or `null` (to remove the effect of any previous call of `setDelay` and use the default value from {@link CLIConfigurationSpec.delay|the global setting} instead).
*/
setDelay(delay: Delay | null): void;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'folder', specifies the root folder of all mocks,
* from which specific mocks paths will be resolved
* (resolved against {@link MockingOptions.root|options.root}).
*/
readonly mocksFolder: string;
/**
* Sets the {@link IMock.mocksFolder|mocksFolder} value.
*
* @param value - any combination of arrays of path parts,
* (as it is also possible for {@link IMock.setLocalPath|setLocalPath}).
* You can pass an absolute path, or a relative one which will be resolved against {@link MockingOptions.root|options.root}.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.mocksFolder|the global setting}.
*/
setMocksFolder(value: RecursiveArray<string | null | undefined> | null): void;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'har', contains the full path of the the har file to use.
* If the file name has the `.yml` or `.yaml` extension, the YAML format is used instead of the standard JSON format to read and write the file.
*/
readonly mocksHarFile: string;
/**
* Sets the {@link IMock.mocksHarFile|mocksHarFile} value.
*
* @param value - any combination of arrays of path parts.
* You can pass an absolute path, or a relative one which will be resolved against {@link MockingOptions.root|options.root}.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.mocksHarFile|the global setting}.
*/
setMocksHarFile(value: RecursiveArray<string | null | undefined> | null): void;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'har', specifies the default mock har key to use in case
* {@link IMock.setMockHarKey | setMockHarKey} is not called with a non-null value.
* It is computed by calling the {@link IMock.mocksHarKeyManager|mocks har key manager} with the current request.
*
* @remarks
*
* Note that it is lazily computed, but once computed, it is not re-computed even if
* {@link IMock.mocksHarKeyManager | mocksHarKeyManager} changes.
*/
readonly defaultMockHarKey?: string;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'har', specifies the key to use inside the har file to either
* read or write a mock.
*
* @remarks
*
* The way the key is stored inside the har file depends on the value of {@link IMock.mocksHarKeyManager|mocksHarKeyManager}.
*/
readonly mockHarKey?: string;
/**
* Sets the {@link IMock.mockHarKey|mockHarKey} value.
*
* @param value - specifies the key to use inside the har file to either read or write a mock. If an array is set (which can be nested),
* it is flattened with null items removed, and joined with forward slashes to produce a string.
* Passing null resets the value to {@link IMock.defaultMockHarKey|the default value}.
*/
setMockHarKey(value: RecursiveArray<string | null | undefined> | null): void;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'har', specifies the {@link HarKeyManager|har key manager} to use.
*/
readonly mocksHarKeyManager: HarKeyManager;
/**
* Sets the {@link IMock.mocksHarKeyManager|mocksHarKeyManager} value.
*
* @param value - the {@link HarKeyManager|har key manager} to use for this request.
* Passing null resets the value to the default coming from {@link ConfigurationSpec.mocksHarKeyManager|the global setting}.
*/
setMocksHarKeyManager(value: HarKeyManager | null): void;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'har',
* specifies a list of mime types that will attempt to parse the request/response body as JSON.
* This will only be applicable to request bodies if {@link IMock.saveInputRequestBody|saveInputRequestBody} is set to true
* Default value will be [] and will only be overridden by {@link IMock.setHarMimeTypesParseJson|setHarMimeTypesParseJson}
*/
readonly harMimeTypesParseJson: string[];
/**
* Sets the {@link IMock.harMimeTypesParseJson|harMimeTypesParseJson} value.
*
* @param value - The mime types that should attempt to parse the body as json
*/
setHarMimeTypesParseJson(value: string[]): void;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'folder', specifies the local path of the mock, relative to {@link IMock.mocksFolder|mocksFolder}.
* It is either the one set by the user through {@link IMock.setLocalPath|setLocalPath} or {@link IMock.defaultLocalPath|defaultLocalPath}.
*/
readonly localPath: string;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'folder', specifies the default local path of the mock, relative to {@link IMock.mocksFolder|mocksFolder}, .
* It uses the URL pathname to build an equivalent folders hierarchy,
* and appends the HTTP method as a leaf folder.
*/
readonly defaultLocalPath: string;
/**
* Used only when the {@link IMock.mocksFormat|mocks format} is 'folder', specifies the full, absolute path of the mock, built from {@link IMock.localPath|localPath}/{@link IMock.defaultLocalPath|defaultLocalPath}, {@link IMock.mocksFolder|mocksFolder}
* and possibly {@link MockingOptions.root|options.root} if {@link IMock.mocksFolder|mocksFolder} is not absolute.
*/
readonly mockFolderFullPath: string;
/**
* Content produced by the last call to the {@link IMock.checksum|checksum} method,
* as it was passed to the hash algorithm.
*/
readonly checksumContent: string | null;
/**
* Compute a checksum using content from the request.
*
* @remarks
* The computed checksum is intended to be added to the path of the mock
* so that semantically different requests use different mocks.
*
* It is difficult to predict what will actually be relevant to include in
* the checksum or not for your use case, and that's why we provide many options
* to include/exclude/transform data (cf {@link ChecksumArgs}).
*
* Note that we designed the API so that it is usually not needed to
* call the checksum method more than once for a given request/mock.
*
* The method stores the computed content (which is passed to the hash
* algorithm) in property {@link IMock.checksumContent|checksumContent}
* (in the `mock` object), as a string. It is built according to your options
* and the request's data. It is also persisted, so that you can debug more easily,
* especially by committing it into your SCM to analyze changes across versions of
* your code. File is along with the other files of the mock under file name `checksum`.
*
* @param spec - specifies which data from the request to include in the checksum
* @returns The actual checksum value, that you can then
* use for instance to add to the mock's path.
*/
checksum(spec: ChecksumArgs): Promise<string>;
/**
* Sets the {@link IMock.localPath|localPath} value.
*
* @param pathParts - Any combination of values and array of values,
* which will eventually all be flattened, converted to strings and
* joined to build a path.
*
* @example
* The following example will use the HTTP method followed by the URL pathname:
* ```
* mock.setLocalPath([mock.request.method, mock.request.pathname])
* ```
* @example
* The following example will concatenate `prefix`, all portions of the
* URL pathname except the first one (also excluding the very first one which is empty since {@link IFetchedRequest.pathname} has a leading slash)
* and optionally a suffix sequence depending on a boolean.
*
* ```
* mock.setLocalPath([prefix, mock.request.pathname.split('/').slice(2), addSuffix ? [suffix, '-static-suffix'] : null])
* ```
*/
setLocalPath(pathParts: RecursiveArray<string | null | undefined>): void;
/**
* Returns true if the mock exists locally.
*
* @deprecated Use {@link IMock.hasLocalMock} instead.
*
* @remarks
*
* {@link IMock.hasNoLocalFiles|hasNoLocalFiles} returns the opposite boolean value.
*/
hasLocalFiles(): Promise<boolean>;
/**
* Returns true if the mock does not exist locally.
*
* @deprecated Use {@link IMock.hasNoLocalMock} instead.
*
* @remarks
*
* {@link IMock.hasLocalFiles|hasLocalFiles} returns the opposite boolean value.
*/
hasNoLocalFiles(): Promise<boolean>;
/**
* Returns true if the mock exists locally.
*
* @remarks
*
* {@link IMock.hasNoLocalMock|hasNoLocalMock} returns the opposite boolean value.
*/
hasLocalMock(): Promise<boolean>;
/**
* Returns true if the mock does not exist locally.
*
* @remarks
*
* {@link IMock.hasLocalMock|hasLocalMock} returns the opposite boolean value.
*/
hasNoLocalMock(): Promise<boolean>;
/**
* The mocks format used for this request.
*/
readonly mocksFormat: MocksFormat;
/**
* Sets the {@link IMock.mocksFormat|mocksFormat} value.
*
* @param value - the mocks format to use for this request.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.mocksFormat|the global setting}.
*/
setMocksFormat(value: MocksFormat | null): void;
/**
* Whether to save the content used to create a checksum when creating a new mock with a checksum for this request.
*/
readonly saveChecksumContent: boolean;
/**
* Sets the {@link IMock.saveChecksumContent|saveChecksumContent} value.
*
* @param value - whether to save the content used to create a checksum when creating a new mock with a checksum for this request.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.saveChecksumContent|the global setting}.
*/
setSaveChecksumContent(value: boolean | null): void;
/**
* Whether to save {@link RequestTimings | detailed timings} when creating a new mock for this request.
*/
readonly saveDetailedTimings: boolean;
/**
* Sets the {@link IMock.saveDetailedTimings|saveDetailedTimings} value.
*
* @param value - whether to save {@link RequestTimings | detailed timings} when creating a new mock with a checksum for this request.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.saveDetailedTimings|the global setting}.
*/
setSaveDetailedTimings(value: boolean | null): void;
/**
* Whether to save the input request data (headers, method, URL) when creating a new mock for this request.
*/
readonly saveInputRequestData: boolean;
/**
* Sets the {@link IMock.saveInputRequestData|saveInputRequestData} value.
*
* @param value - whether to save the input request data (headers, method, URL) when creating a new mock for this request.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.saveInputRequestData|the global setting}.
*/
setSaveInputRequestData(value: boolean | null): void;
/**
* Whether to save the content of the input request body when creating a new mock for this request.
*/
readonly saveInputRequestBody: boolean;
/**
* Sets the {@link IMock.saveInputRequestBody|saveInputRequestBody} value.
*
* @param value - whether to save the content of the input request body when creating a new mock for this request.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.saveInputRequestBody|the global setting}.
*/
setSaveInputRequestBody(value: boolean | null): void;
/**
* Whether to save the forwarded request data (headers, method, URL) when creating a new mock for this request.
*/
readonly saveForwardedRequestData: boolean;
/**
* Sets the {@link IMock.saveForwardedRequestData|saveForwardedRequestData} value.
*
* @param value - whether to save the forwarded request data (headers, method, URL) when creating a new mock for this request.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.saveForwardedRequestData|the global setting}.
*/
setSaveForwardedRequestData(value: boolean | null): void;
/**
* Whether to save the forwarded request body when creating a new mock for this request.
*/
readonly saveForwardedRequestBody: boolean;
/**
* Sets the {@link IMock.saveForwardedRequestBody|saveForwardedRequestBody} value.
*
* @param value - whether to save the forwarded request body when creating a new mock for this request.
* Passing null resets the value to the default coming from {@link CLIConfigurationSpec.saveForwardedRequestBody|the global setting}.
*/
setSaveForwardedRequestBody(value: boolean | null): void;
/**
* Returns a wrapped payload built from data persisted in local files.
* If no local file is present, returns `undefined`.
*/
readLocalPayload(): Promise<PayloadWithOrigin<'local' | 'user'> | undefined>;
/**
* Take the given wrapped payload and persist it in local files.
* @param payload - payload to persist in local files
*/
persistPayload(payload: PayloadWithOrigin): Promise<void>;
/**
* Forward the client request to the remote backend and get a wrapped payload from the response in output.
*/
fetchPayload(): Promise<RemotePayload>;
/**
* Create a wrapped payload (with `user` origin) from the given payload data.
* @param payload - payload data
*/
createPayload(payload: Payload): PayloadWithOrigin<'user'>;
/**
* Sets the current local payload, with a custom one you would have created.
* @param payload - payload to set
*/
setPayload(payload: PayloadWithOrigin<'local' | 'user'>): void;
/**
* Combines {@link IMock.fetchPayload|fetchPayload} and {@link IMock.persistPayload|persistPayload}
* and returns the wrapped payload.
*/
downloadPayload(): Promise<RemotePayload>;
/**
* Returns the wrapped local payload using {@link IMock.readLocalPayload|readLocalPayload} if it exists,
* otherwise use {@link IMock.downloadPayload