cumulocity-cypress
Version:
Cypress commands for Cumulocity IoT
271 lines (270 loc) • 10.2 kB
TypeScript
import { C8yPact, C8yPactRecord } from "./c8ypact";
/**
* Interface for a preprocessor to apply transformations to `C8yPact` records
* before critical operations such as matching or saving. A preprocessor can be used to
* unify records by removing or obfuscating sensitive data, picking only certain keys to keep,
* or applying regex substitutions to values. Preprocessors operate in-place on the
* given object, which can be a full `C8yPact`, an individual `C8yPactRecord`, or a
* plain object such as `Cypress.Response`.
*
* The default implementation is `C8yDefaultPactPreprocessor`, which supports the
* operations and key-path syntax described in `C8yPactPreprocessorOptions`.
*
* See {@link C8yDefaultPactPreprocessor} for default implementation.
*
*/
export interface C8yPactPreprocessor {
/**
* Configuration options used by the preprocessor.
*/
readonly options?: C8yPactPreprocessorOptions;
/**
* Applies the preprocessor options (rules) to the given object in-place.
*
* When `obj` is a `C8yPact` (i.e. contains a `records` array), all records
* are processed individually. For a plain object, including `Cypress.Response`
* or `C8yPactRecord`, the object itself is processed.
*
* Operations are applied in this sequence:
* 1. **pick** — remove any keys not listed
* 2. **obfuscate** — replace values with the obfuscation pattern
* 3. **regexReplace** — apply regex substitutions
* 4. **ignore** — delete values entirely
*
* @param obj Object to preprocess. Modified in place.
* @param options Options that override the instance-level options for this
* single call.
*/
apply: (obj: Partial<Cypress.Response<any> | C8yPactRecord | C8yPact>, options?: C8yPactPreprocessorOptions) => void;
}
/**
* Configuration options for `C8yPactPreprocessor`.
*
* All key-path strings support:
* - Dot-separated segments: `response.body.password`
* - Bracket / numeric-index notation: `response.body.items[0].token`
* - Array fan-out: `response.body.users.password` (applied to every element)
* - Recursive descent: `response.body..password` (any depth below `body`)
*
* Key resolution is case-insensitive when `ignoreCase` is `true` (default).
*/
export interface C8yPactPreprocessorOptions {
/**
* Key paths whose values should be replaced with `obfuscationPattern`.
*
* For `Authorization` headers whose value begins with `Bearer` or `Basic`,
* the scheme prefix is kept and only the credential token is replaced, e.g.
* `Bearer ****`.
*
* Cookie values can be targeted by appending the cookie name as an extra
* segment: `request.headers.cookie.XSRF-TOKEN`.
*
* @example
* obfuscate: [
* "response.body.password",
* "request.headers.authorization",
* "response.body.users.password", // every user object
* "response.body..token", // any depth
* ]
*/
obfuscate?: string[];
/**
* Key paths whose values should be deleted entirely from the record.
*
* Cookie values can be targeted by appending the cookie name as an extra
* segment: `request.headers.cookie.XSRF-TOKEN`.
*
* @example
* ignore: [
* "request.headers.accept-encoding",
* "response.headers.cache-control",
* "response.body..internalDebugField", // any depth
* ]
*/
ignore?: string[];
/**
* Restricts which child keys are retained under the specified parent paths.
* All other sibling keys are removed.
*
* Two forms are accepted:
*
* **Object form** — maps a parent key path to an array of child keys to keep:
* ```ts
* pick: {
* "response.headers": ["content-type", "location"],
* "request.headers": ["authorization"]
* }
* ```
*
* **Array form** — keeps only the listed top-level keys of the record:
* ```ts
* pick: ["request", "response"]
* ```
*/
pick?: {
[key: string]: string[];
} | string[];
/**
* Applies one or more regex substitutions to the value at the given key path.
*
* The key is a key path (same syntax as `obfuscate` / `ignore`). The value
* is a single regex string or an ordered array of regex strings applied in
* sequence. Each regex string must use the format:
* ```
* /pattern/replacement/flags
* ```
* Capture groups (`$1`, `$2`, …) and all standard JS regex flags are
* supported.
*
* @example
* // Redact all but the first four characters of a token:
* // key: "response.body.token"
* // value: "/^(.{4}).+$/$1----/"
* //
* // Normalise a date field, then strip milliseconds in sequence:
* // key: "response.body.timestamp"
* // value: ["/T\\d{2}:\\d{2}:\\d{2}/THH:MM:SS/", "/\\.\\d+Z$/Z/"]
*/
regexReplace?: {
[key: string]: string | string[];
};
/**
* Replacement string used by the `obfuscate` operation.
* Defaults to `"****"`.
*/
obfuscationPattern?: string;
/**
* When `true` (default), key segments are matched case-insensitively at
* every level of the path. The actual casing of the key found in the object
* is always used for mutations — the original structure is never changed.
*/
ignoreCase?: boolean;
}
/**
* Default options for `C8yPactPreprocessor`. Used when constructing an instance
* without custom options, and as fallback for missing properties when applying
* with partial options.
*/
export declare const C8yPactPreprocessorDefaultOptions: {
ignore: string[];
obfuscate: string[];
obfuscationPattern: string;
ignoreCase: boolean;
};
/**
* Preprocessor for `C8yPact` objects. A preprocessor is applied when a pact
* record is **saved** (recording mode) and before it is applied (matched)
* against any other record. This is used to unify records before they are
* **matched**. A preprocessor transforms objects such as `Cypress.Response`,
* `C8yPactRecord` or a full `C8yPact` in-place. It supports various operations
* to remove or obfuscate sensitive data, or to pick only certain keys to keep.
*
* The default implementation is `C8yDefaultPactPreprocessor`.
*
* ### Supported operations (configured via `C8yPactPreprocessorOptions`)
*
* | Option | Effect |
* |---|---|
* | `ignore` | Removes the value at each key path |
* | `obfuscate` | Replaces the value at each key path with `obfuscationPattern` |
* | `pick` | Keeps only the specified child keys; removes all others |
* | `regexReplace` | Applies one or more `/pattern/replacement/flags` expressions |
*
* ### Key-path syntax
*
* All key paths use dot-separated segments. Bracket notation and numeric array
* indices are supported:
* ```
* response.body.password
* response.body.items[0].token
* response.body.items.0.token
* ```
* When a path segment resolves to an **array of objects** and the next segment
* is *not* a numeric index, the operation fans out to every element:
* ```
* response.body.users.password // applied to every object in `users`
* ```
*
* ### Recursive-descent operator (`..`)
*
* Prefix a leaf key with `..` to match it at **any depth** below the optional
* prefix path:
* ```
* ..password // `password` anywhere in the record
* response.body..password // `password` anywhere inside `body`
* ```
*
* ### Case-insensitive matching
*
* When `ignoreCase` is `true` (the default), each path segment is resolved
* without regard to capitalization. Mutations always use the actual key name
* found in the object.
*
* ### Cookie / Set-Cookie shorthand
*
* Preprocessors automatically parse `Cookie` and `Set-Cookie` header strings and
* apply obfuscation or ignoring to individual cookie values when the key path
* is appended with the cookie name as an extra segment:
*
* ```
* request.headers.cookie.XSRF-TOKEN
* response.headers.set-cookie.authorization
* ```
*
* ### Authorization-header obfuscation
*
* When obfuscating an `Authorization` header whose value starts with `Bearer`
* or `Basic`, the scheme prefix is preserved and only the credential is
* replaced:
* ```
* Bearer ********
* Basic ********
* ```
*/
export declare class C8yDefaultPactPreprocessor implements C8yPactPreprocessor {
static defaultObfuscationPattern: string;
options?: C8yPactPreprocessorOptions;
protected reservedKeys: string[];
constructor(options?: C8yPactPreprocessorOptions);
/** {@inheritDoc C8yPactPreprocessor.apply} */
apply(obj: Partial<Cypress.Response<any> | C8yPactRecord | C8yPact>, options?: C8yPactPreprocessorOptions): void;
private filterObjectByKeepPaths;
private applyKeepArray;
private removeKey;
private removeSetCookie;
private removeCookie;
private filterValidKeys;
/**
* Unified key-path traversal. Calls `fn(parent, resolvedKey)` on every
* matching leaf. Handles recursive descent (`..leafKey` / `prefix..leafKey`)
* and regular dot-/bracket-separated paths including array indices.
*/
private traverseKeyPath;
/**
* Applies a list of regex-replace patterns to the value at the given key path.
*/
private applyRegexReplace;
/**
* Recursively walks `obj` (depth-first) and calls `fn` on every node whose
* key matches `leafKey` (case-sensitively, or case-insensitively when
* `ignoreCase` is true). Traverses into arrays and plain objects.
*/
private applyRecursive;
private obfuscateKey;
private obfuscateSetCookie;
private obfuscateCookie;
protected resolveOptions(options?: Partial<C8yPactPreprocessorOptions>): C8yPactPreprocessorOptions;
private hasKey;
private getCookieObject;
}
export declare function parseRegexReplace(input: string): {
pattern: RegExp;
replacement: string;
};
export declare function performRegexReplace(input: string | any, regexes: {
pattern: RegExp;
replacement: string;
}[] | {
pattern: RegExp;
replacement: string;
}): string | any;