@metamask/keyring-utils
Version:
MetaMask Keyring utils
97 lines • 3.12 kB
JavaScript
import { Struct, assert, object as stObject, type as stType } from "@metamask/superstruct";
/**
* Change the return type of a superstruct's `object` function to support
* exact optional properties.
*
* @param schema - The object schema.
* @returns A struct representing an object with a known set of properties.
*/
export function object(schema) {
return stObject(schema);
}
/**
* Change the return type of a superstruct's `type` function to support
* exact optional properties.
*
* @param schema - The object schema.
* @returns A struct representing an object with a known set of properties
* and ignore unknown properties.
*/
export function type(schema) {
return stType(schema);
}
/**
* Check if the current property is present in its parent object.
*
* @param ctx - The context to check.
* @returns `true` if the property is present, `false` otherwise.
*/
function hasOptional(ctx) {
const property = ctx.path[ctx.path.length - 1];
const parent = ctx.branch[ctx.branch.length - 2];
return property in parent;
}
/**
* Augment a struct to allow exact-optional values. Exact-optional values can
* be omitted but cannot be `undefined`.
*
* ```ts
* const foo = object({ bar: exactOptional(string()) });
* type Foo = Infer<typeof foo>;
* // Foo = { bar?: string }
* ```
*
* @param struct - The struct to augment.
* @returns The augmented struct.
*/
export function exactOptional(struct) {
return new Struct({
...struct,
validator: (value, ctx) => !hasOptional(ctx) || struct.validator(value, ctx),
refiner: (value, ctx) => !hasOptional(ctx) || struct.refiner(value, ctx),
});
}
/**
* Assert that a value is valid according to a struct.
*
* It is similar to superstruct's mask function, but it does not ignore extra
* properties.
*
* @param value - Value to check.
* @param struct - Struct to validate the value against.
* @param message - Error message to throw if the value is not valid.
* @returns The value if it is valid.
*/
export function strictMask(value, struct, message) {
assert(value, struct, message);
return value;
}
/**
* Create a custom union struct that uses a `selector` function for choosing
* the validation path.
*
* @param selector - The selector function choosing the struct to validate with.
* @returns The `superstruct` struct, which validates that the value satisfies
* one of the structs.
*/
export function selectiveUnion(selector) {
return new Struct({
type: 'union',
schema: null,
*entries(value, context) {
yield* selector(value).entries(value, context);
},
*refiner(value, context) {
yield* selector(value).refiner(value, context);
},
coercer(value, context) {
return selector(value).coercer(value, context);
},
validator(value, context) {
// This only validates the root of the struct, entries does the rest of
// the work.
return selector(value).validator(value, context);
},
});
}
//# sourceMappingURL=superstruct.mjs.map