@kform/core
Version:
JavaScript bindings for KForm.
1,292 lines (1,180 loc) • 95.1 kB
TypeScript
/// <reference lib="es2015.iterable" />
/// <reference lib="es2018.asynciterable" />
// Form manager ================================================================
/**
* Form manager validation mode.
* - `auto`: Automatic validations. A background process is launched that runs
* validations as needed.
* - `manual`: Manual validations. Validations only run when
* {@link FormManager.validate} (or {@link FormManager.isValid}) is called.
*/
export type ValidationMode = "auto" | "manual";
/**
* Class responsible for managing the data and state of a form.
*
* The form manager stores, provides access, and allows manipulating the content
* of a form with a provided schema in a concurrent and controlled manner. It
* further manages state associated with the different fields of the form such
* as keeping track of validation issues, "dirty" and "touched" states, and
* others.
*
* All form value/state accesses and manipulations should go through an instance
* of the form manager, to make sure that changes are tracked and no "dangerous"
* concurrent operations are performed. As such, storing non-copied form values
* outside the form manager is highly discouraged. Certain methods like
* {@link valueInfo}, {@link get}, and {@link validate} take callbacks as
* arguments to guarantee that data access only happens within a "controlled
* environment", i.e. during the lifetime of the callback.
*/
export declare class FormManager {
/**
* Constructs a new instance of a form manager.
* @param formSchema Schema of the form.
* @param initialValue Initial form value.
* @param externalContexts External contexts available to validations.
* @param validationMode Validation mode (defaults to `"auto"`).
* @param autoInit Whether to automatically initialise the form manager
* (defaults to `true`). When set to `false`, {@link init} should be called
* before interacting with the form manager instance.
*/
constructor(
formSchema: Schema | SchemaKt,
initialValue?: unknown,
externalContexts?: Record<string, unknown>,
validationMode?: ValidationMode,
autoInit?: boolean,
);
/**
* Initialises the form manager.
*
* This method is automatically called when constructing a new form manager
* instance when `autoInit` is set to `true` (the default). Calling
* {@link init} on an already initted form manager has no effect.
* @param externalContexts External contexts available to validations.
* @param validationMode Validation mode (defaults to `"auto"`).
*/
init(
externalContexts?: Record<string, unknown>,
validationMode?: ValidationMode,
): CancellablePromise<void>;
/**
* Destroys this form manager instance by cancelling its coroutine scope.
*
* Destroying an already destroyed form manager has no effect.
*/
destroy(): CancellablePromise<void>;
/**
* Status of the automatic validations.
*/
get autoValidationStatus(): AutoValidationStatus;
/**
* Method used to subscribe to changes on the status of the automatic
* validations. Returns a function that should be used to unsubscribe from
* change notifications. Note that the subscription itself is asynchronous.
*
* An {@link onSubscription} function may be provided, which is guaranteed to
* run after the subscription has completed, but before changes are emitted to
* {@link statusChangeHandler}
* @param statusChangeHandler Function called with the new status of the
* automatic validations whenever the status changes.
* @param onSubscription Function called after the subscription completes but
* before any events are emitted to
* {@link statusChangeHandler}.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the subscription has been registered with another
* [cancellable promise]{@link CancellablePromise} that can be used to
* unsubscribe from change notifications.
*/
onAutoValidationStatusChange(
statusChangeHandler: (
status: AutoValidationStatus,
) => void | PromiseLike<void>,
onSubscription?: () => void | PromiseLike<void>,
): CancellablePromise<() => CancellablePromise<void>>;
/**
* Sets the validation mode (automatic or manual). Note that this action is
* asynchronous.
* @param validationMode New validation mode.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the mode has been set.
*/
setValidationMode(validationMode: ValidationMode): CancellablePromise<void>;
/**
* Returns whether there exists at least one schema at a path matching
* {@link path}.
*
* Paths that match no schema paths are deemed invalid by the form manager and
* most methods called with them will throw.
* @param path Path to check if valid.
* @returns Whether {@link path} is valid according to the manager's schema.
*/
isValidPath(path?: Path | string): boolean;
/**
* Returns an iterable over schema-information about the schemas at paths
* matching {@link path}.
* @param path Path matching path of schemas from which to get information
* (defaults to `/**`).
* @returns Iterable over schema-information of schemas at paths mathing
* {@link path}.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
schemaInfo<T = unknown>(path?: Path | string): Iterable<SchemaInfo<T>>;
/**
* Runs the {@link infoHandler} callback with the value-information of values
* at paths matching {@link path}. Returns the result of {@link infoHandler}.
*
* This method receives a callback to ensure that no conflicting concurrent
* operations occur during the lifetime of said callback.
* @param path Path matching path of values from which to get information
* (defaults to `/**`).
* @param infoHandler Function that receives an async iterable over the
* value-information of values matching {@link path}.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the result of {@link infoHandler}.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
valueInfo<T = unknown, TResult = unknown>(
path: Path | string | undefined,
infoHandler: (
infoIterable: AsyncIterable<ValueInfo<T>>,
) => TResult | PromiseLike<TResult>,
): CancellablePromise<TResult>;
/**
* Runs the {@link infoHandler} callback with all information of values at
* paths matching {@link path}. Returns the result of {@link infoHandler}.
*
* This method receives a callback to ensure that no conflicting concurrent
* operations occur during the lifetime of said callback.
* @param path Path matching path of values from which to get information
* (defaults to `/**`).
* @param infoHandler Function that receives an async iterable over all the
* information of values matching {@link path}.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the result of {@link infoHandler}.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
info<T = unknown, TResult = unknown>(
path: Path | string | undefined,
infoHandler: (
infoIterable: AsyncIterable<Info<T>>,
) => TResult | PromiseLike<TResult>,
): CancellablePromise<TResult>;
/**
* Returns the single schema matching {@link path}.
*
* To get information about all schemas at paths matching a given path use
* {@link schemaInfo} instead.
* @param path Path of the schema to get (defaults to `/`).
* @returns Schema at {@link path}.
* @throws {InvalidPathException} If {@link path} matches no schema paths or
* more than one schema path.
*/
schema<T = unknown>(path?: Path | string): Schema<T>;
/**
* Returns whether there exists at least one value at a path matching
* {@link path}.
* @param path Path to check.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with whether there exists at least one value at a path matching
* {@link path}.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
has(path: Path | string): CancellablePromise<boolean>;
/**
* Runs the provided {@link valueHandler} with the single value at
* {@link path}. Returns the result of {@link valueHandler}.
*
* Because this method is meant to return a single value, paths with wildcards
* are not accepted. To get all values at paths matching a path containing
* wildcards, use {@link valueInfo} instead.
*
* This method receives a callback to ensure that no conflicting concurrent
* operations occur during the lifetime of said callback.
* @param path Path of the value to get (defaults to `/`).
* @param valueHandler Function called with the value at {@link path}.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the result of {@link valueHandler}.
* @throws {InvalidPathException} If {@link path} contains wildcards, matches
* no schemas, or matches more than one value.
* @throws {IllegalStateException} If {@link path} matches more than one
* value.
* @throws {NoSuchElementException} If no value matches {@link path}.
*/
get<T = unknown, TResult = unknown>(
path: Path | string | undefined,
valueHandler: (value: T) => TResult | PromiseLike<TResult>,
): CancellablePromise<TResult>;
/**
* Returns a clone (deep copy) of the single value at {@link path}. Equivalent
* to:
* ```typescript
* formManager.get(path, (value) => formManager.schema(path).clone(value))
* ```
* @param path Path of the value to get (defaults to `/`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with a clone of the value at {@link path}.
* @throws {InvalidPathException} If {@link path} contains wildcards or
* matches no schemas.
* @throws {IllegalStateException} If {@link path} matches more than one
* value.
* @throws {NoSuchElementException} If no value matches {@link path}.
*/
getClone<T = unknown>(path?: Path | string): CancellablePromise<T>;
/**
* Sets values at {@link path} with {@link toSet}.
*
* If the path has a trailing non-recursive wildcard, then all existing
* children of its parent value are set to {@link toSet}. E.g. assume that the
* list `[1, 2, 3]` exists at `"/list"`; setting the value `5` at `"/list/∗"`
* will cause `"/list"` to end up with `[5, 5, 5]`.
*
* Setting a value on a path with a trailing recursive wildcard is considered
* equivalent to setting the value on said path without such wildcard. E.g.
* setting the value at `"/x/∗∗"` is equivalent to setting the same value at
* `"/x"`.
* @param path Path of values to set (defaults to `/`).
* @param toSet Value to set at {@link path}.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
set(
path: Path | string | undefined,
toSet: unknown,
): CancellablePromise<void>;
/**
* Resets the values at {@link path} to their initial value.
*
* If the path has a trailing non-recursive wildcard, then all existing
* children of its parent value will have their value reset. E.g. assume that
* the list `[1, 2, 3]` exists at `"/list"` and that the schema of `"/list/∗"`
* has an initial value of `0`; resetting `"/list/∗"` will thus cause
* `"/list"` to end up with `[0, 0, 0]`.
*
* Resetting the value on a path with a trailing recursive wildcard is
* considered equivalent to resetting the value on said path without such
* wildcard. E.g. resetting the value at `"/x/∗∗"` is equivalent to resetting
* the value at `"/x"`.
* @param path Path of values to reset (defaults to `/`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
reset(path?: Path | string): CancellablePromise<void>;
/**
* Removes the values matching {@link path} from their parent collection(s).
*
* It is possible to clear a collection by providing a path with a trailing
* wildcard.
*
* Removing the value on a path with a trailing recursive wildcard is
* considered equivalent to removing the value on said path without such
* wildcard. E.g. removing the value at `"/x/∗∗"` is equivalent to removing
* the value at `"/x"`.
* @param path Path of values to remove.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths,
* when attempting to remove the root value, or when a parent of {@link path}
* is not a collection.
*/
remove(path: Path | string): CancellablePromise<void>;
/**
* Runs {@link externalContextHandler} with the external context named
* {@link externalContextName} currently available to validations.
*
* This method receives a callback to ensure that no conflicting concurrent
* operations occur during the lifetime of said callback.
* @param externalContextName Name of the external context to get.
* @param externalContextHandler Function called with the external context
* named {@link externalContextName} currently available to validations.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the result of {@link externalContextHandler}.
*/
getExternalContext<T = unknown, TResult = unknown>(
externalContextName: string,
externalContextHandler: (
externalContext: T,
) => TResult | PromiseLike<TResult>,
): CancellablePromise<TResult>;
/**
* Sets an [external context]{@link externalContext} with name
* {@link externalContextName} to be available to validations and returns the
* previous external context associated with the same name if one existed.
* @param externalContextName Name of the external context to set.
* @param externalContext Value of the external context to set.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the previous external context associated with
* {@link externalContextName} if one existed.
*/
setExternalContext<T = unknown>(
externalContextName: string,
externalContext: T,
): CancellablePromise<T | null>;
/**
* Removes the external context with name {@link externalContextName}
* available to validations and returns it if it existed.
* @param externalContextName Name of the external context to remove.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the removed external context associated with
* {@link externalContextName} if it existed.
*/
removeExternalContext<T = unknown>(
externalContextName: string,
): CancellablePromise<T | null>;
/**
* Validates all values at paths matching {@link path} by running a function
* {@link issuesHandler} with an async interable over all found
* [validation issues]{@link LocatedValidationIssue}. Returns the result of
* {@link issuesHandler}.
*
* This method receives a callback to ensure that no conflicting concurrent
* operations occur during the lifetime of said callback.
* @param path Path of values to validate (defaults to `/**`).
* @param issuesHandler Function that receives an async iterable over all
* found [validation issues]{@link LocatedValidationIssue} at {@link path}.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the result of {@link issuesHandler}.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
validate<T = unknown>(
path: Path | string | undefined,
issuesHandler: (
issuesIterable: AsyncIterable<SealedLocatedValidationIssue>,
) => T | PromiseLike<T>,
): CancellablePromise<T>;
/**
* Validates all values at paths matching {@link path}. Returns the list of
* all found [validation issues]{@link LocatedValidationIssue}.
* @param path Path of values to validate (defaults to `/**`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the list all found [validation issues]{@link LocatedValidationIssue}.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
validate(
path?: Path | string,
): CancellablePromise<SealedLocatedValidationIssue[]>;
/**
* Returns whether the values at paths matching {@link path} are valid
* according to their schemas.
*
* Values are said to be valid if they contain no validation errors.
* @param path Path of values to check if valid (defaults to `/**`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with whether all values at {@link path} are valid.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
isValid(path?: Path | string): CancellablePromise<boolean>;
/**
* Adds external issues to the form manager. Once added, each issue can be
* removed either manually via {@link removeExternalIssues} or automatically
* when the value referenced by the issue or one of the values referenced by
* the issue's dependencies change.
* @param issues External issues to add to the form manager.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If any of the issue's paths or dependencies
* match no schema paths.
*/
addExternalIssues(
issues:
| (SealedLocatedValidationIssue | LocatedValidationIssueKt)[]
| KtList<SealedLocatedValidationIssue | LocatedValidationIssueKt>,
): CancellablePromise<void>;
/**
* Removes all external issues currently added to the form manager with paths
* matching {@link path}. If a {@link code} is provided, only the issues with
* the provided code are removed.
* @param path Path of values with external issues to remove.
* @param code Code of issues to remove.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws InvalidPathException If [path] matches no schema paths.
*/
removeExternalIssues(
path?: Path | string,
code?: string | null,
): CancellablePromise<void>;
/**
* Returns whether at least one value at a path matching {@link path} is
* dirty.
* @param path Path of values to check if dirty (defaults to `/`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with whether at least one value at a path matching {@link path} is
* dirty.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
isDirty(path?: Path | string): CancellablePromise<boolean>;
/**
* Returns whether all values at a path matching {@link path} are pristine
* (i.e. are not dirty).
* @param path Path of values to check if pristine (defaults to `/`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with whether all values at a path matching {@link path} are pristine.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
isPristine(path?: Path | string): CancellablePromise<boolean>;
/**
* Sets all values at a path matching {@link path} as dirty, as well as their
* parents.
* @param path Path of values to set as dirty (defaults to `/**`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
setDirty(path?: Path | string): CancellablePromise<void>;
/**
* Sets all values at a path matching {@link path} as pristine (i.e. as not
* dirty), as well as their descendents.
* @param path Path of values to set as pristine (defaults to `/`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
setPristine(path?: Path | string): CancellablePromise<void>;
/**
* Returns whether at least one value at a path matching {@link path} has been
* touched.
* @param path Path of values to check if touched (defaults to `/`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with whether at least one value at a path matching {@link path} has been
* touched.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
isTouched(path?: Path | string): CancellablePromise<boolean>;
/**
* Returns whether all values at a path matching {@link path} are untouched
* (i.e. are not touched).
* @param path Path of values to check if untouched (defaults to `/`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with whether all values at a path matching {@link path} are untouched.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
isUntouched(path?: Path | string): CancellablePromise<boolean>;
/**
* Sets all values at a path matching {@link path} as touched, as well as
* their parents.
* @param path Path of values to set as touched (defaults to `/**`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
setTouched(path?: Path | string): CancellablePromise<void>;
/**
* Sets all values at a path matching {@link path} as untouched (i.e. as not
* touched), as well as their descendents.
* @param path Path of values to set as untouched (defaults to `/`).
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
setUntouched(path?: Path | string): CancellablePromise<void>;
/**
* Subscribes to all events with paths matching {@link path} by running
* {@link eventHandler} for each event. Returns a function that should be
* called to unsubscribe from the subscription. Note that the subscription
* itself is asynchronous.
*
* An {@link onSubscription} function may be provided, which is guaranteed to
* run after the subscription has completed but before any events are emitted
* to the {@link eventHandler}.
*
* All subscriptions are automatically cancelled when the form manager is
* [destroyed]{@link destroy}.
* @param path Path of events to subscribe to (defaults to `/**`).
* @param eventHandler Function called whenever an event occurs at a path
* matching {@link path}. It receives the event in question as argument.
* @param onSubscription Function called after the subscription completes, but
* before any event are emitted to {@link eventHandler}.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the subscription has been registered with another
* [cancellable promise]{@link CancellablePromise} that can be used to
* unsubscribe from new event notifications.
* @throws {InvalidPathException} If {@link path} matches no schema paths.
*/
subscribe<T = unknown, TChildren = unknown>(
path: Path | string | undefined,
eventHandler: (
event: SealedFormManagerEvent<T, TChildren>,
) => void | PromiseLike<void>,
onSubscription?: () => void | PromiseLike<void>,
): CancellablePromise<() => CancellablePromise<void>>;
}
// Form util ===================================================================
/**
* Validates that the provided {@link path} points to a schema of
* {@link formSchema}.
* @param formSchema Schema of the form.
* @param path Path to validate against {@link formSchema}.
* @throws {InvalidPathException} If the {@link path} is invalid.
*/
export function validatePath(
formSchema: Schema | SchemaKt,
path: Path | string,
): void;
/**
* Validates all validations of the provided {@link formSchema} by checking that
* all validation dependencies are valid (i.e. that they point to valid
* locations and have valid types).
* @param formSchema Schema of the form.
* @throws {InvalidDependencyPathException} If a validation has an invalid
* dependency path.
* @throws {InvalidDependencyTypeException} If a validation has an invalid
* dependency type.
*/
export function validateSchemaValidations(formSchema: Schema | SchemaKt): void;
/**
* Validates the provided [external validations]{@link externalValidations} in
* the context of the given {@link formSchema} by checking that all validation
* dependencies are valid (i.e. that they point to valid locations and have
* valid types).
* @param formSchema Schema of the form.
* @param externalValidations External validations to validate.
* @throws {InvalidPathException} If an external validation path is invalid.
* @throws {InvalidDependencyPathException} If a validation has an invalid
* dependency path.
* @throws {InvalidDependencyTypeException} If a validation has an invalid
* dependency type.
*/
export function validateExternalValidations(
formSchema: Schema | SchemaKt,
externalValidations: Record<string, Validation[]>,
): void;
/**
* Returns whether there exists at least one schema within {@link formSchema}
* matching {@link path}.
*
* Paths that match no schemas are deemed invalid, and most functions called
* with them will throw.
* @param formSchema Schema of the form.
* @param path Path to check if valid.
* @returns Whether {@link path} is valid according to {@link formSchema}.
*/
export function isValidPath(
formSchema: Schema | SchemaKt,
path: Path | string,
): boolean;
/**
* Returns a sequence of information about the schemas within {@link formSchema}
* matching {@link path}.
* @param formSchema Schema of the form.
* @param path Path matching path of schemas from which to get information
* (defaults to `/**`).
* @returns Iterable over schema-information of schemas at paths mathing
* {@link path}.
* @throws {InvalidPathException} If {@link path} matches no schemas.
*/
export function schemaInfo<T = unknown>(
formSchema: Schema | SchemaKt,
path?: Path | string,
): Iterable<SchemaInfo<T>>;
/**
* Returns the single schema within {@link formSchema} matching {@link path}.
*
* To get information about all schemas matching a path use {@link schemaInfo}
* instead.
* @param formSchema Schema of the form.
* @param path Path of the schema to get.
* @returns Schema at {@link path}.
* @throws {InvalidPathException} If {@link path} matches no schemas or more
* than one schema.
*/
export function schema<T = unknown>(
formSchema: Schema | SchemaKt,
path: Path | string,
): Schema<T>;
/**
* Returns information about the parts of the form value {@link formValue}
* (with schema {@link formSchema}) matching {@link path}.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path matching path of values from which to get information
* (defaults to `/**`).
* @returns An async iterable over the information about the parts of the form
* value {@link formValue} matching {@link path}.
* @throws {InvalidPathException} If {@link path} matches no schemas.
*/
export function valueInfo<T = unknown, TInfo = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path?: Path | string,
): AsyncIterable<ValueInfo<TInfo>>;
/**
* Returns whether there exists a part of the form value {@link formValue} (with
* schema {@link formSchema}) matching {@link path}.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path to check.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with whether there exists at least one value at a path matching {@link path}.
* @throws {InvalidPathException} If {@link path} matches no schemas.
*/
export function has<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
): CancellablePromise<boolean>;
/**
* Returns the single part of the form value {@link formValue} (with schema
* {@link formSchema}) matching {@link path}.
*
* To get information about multiple parts of a form value at once, use
* {@link valueInfo} instead.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of the value to get.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the single part of the form value {@link formValue} matching
* {@link path}.
* @throws {InvalidPathException} If {@link path} contains wildcards or matches
* no schemas.
* @throws {IllegalStateException} If {@link path} matches more than one value.
* @throws {NoSuchElementException} If no part of {@link formValue} matches
* {@link path}.
*/
export function get<T = unknown, TValue = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
): CancellablePromise<TValue>;
/**
* Returns a clone (deep copy) of the single part of the form value
* {@link formValue} (with schema {@link formSchema}) matching {@link path}.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of the value to get.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with a clone of the value at {@link path}.
* @throws {InvalidPathException} If {@link path} contains wildcards or matches
* no schemas.
* @throws {IllegalStateException} If {@link path} matches more than one value.
* @throws {NoSuchElementException} If no part of {@link formValue} matches
* {@link path}.
*/
export function getClone<T = unknown, TValue = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
): CancellablePromise<TValue>;
/**
* Sets values at {@link path} that are part of the form value {@link formValue}
* (with schema {@link formSchema}) with {@link toSet}.
*
* If the path has a trailing non-recursive wildcard, then all existing
* children of its parent value are set to {@link toSet}. E.g. assume that the
* list `[1, 2, 3]` exists at `"/list"`; setting the value `5` at `"/list/∗"`
* will cause `"/list"` to end up with `[5, 5, 5]`.
*
* Setting a value on a path with a trailing recursive wildcard is considered
* equivalent to setting the value on said path without such wildcard. E.g.
* setting the value at `"/x/∗∗"` is equivalent to setting the same value at
* `"/x"`.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of values to set (defaults to `/`).
* @param toSet Value to set at {@link path}.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths, or
* when attempting to set the root value.
*/
export function set<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
toSet: unknown,
): CancellablePromise<void>;
/**
* Resets the values at {@link path} that are part of the form value
* {@link formValue} (with schema {@link formSchema}) to their initial value.
*
* If the path has a trailing non-recursive wildcard, then all existing
* children of its parent value will have their value reset. E.g. assume that
* the list `[1, 2, 3]` exists at `"/list"` and that the schema of `"/list/∗"`
* has an initial value of `0`; resetting `"/list/∗"` will thus cause
* `"/list"` to end up with `[0, 0, 0]`.
*
* Resetting the value on a path with a trailing recursive wildcard is
* considered equivalent to resetting the value on said path without such
* wildcard. E.g. resetting the value at `"/x/∗∗"` is equivalent to resetting
* the value at `"/x"`.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of values to reset.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths, or
* when attempting to reset the root value.
*/
export function reset<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
): CancellablePromise<void>;
/**
* Removes the values matching {@link path} that are part of the form value
* {@link formValue} (with schema {@link formSchema}) from their parent
* collection(s).
*
* It is possible to clear a collection by providing a path with a trailing
* wildcard.
*
* Removing the value on a path with a trailing recursive wildcard is
* considered equivalent to removing the value on said path without such
* wildcard. E.g. removing the value at `"/x/∗∗"` is equivalent to removing
* the value at `"/x"`.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of values to remove.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* once the operation completes.
* @throws {InvalidPathException} If {@link path} matches no schema paths,
* when attempting to remove the root value, or when a parent of {@link path}
* is not a collection.
*/
export function remove<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
): CancellablePromise<void>;
/**
* Validates the parts of the form value {@link formValue} matching {@link path}
* against {@link formSchema}. Returns an async iterable over all found
* [validation issues]{@link LocatedValidationIssue}.
*
* A map of external contexts may be provided for validations that depend on
* them.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of values to validate (defaults to `/**`).
* @param externalContexts External contexts used by validations.
* @returns Async iterable over all found
* [validation issues]{@link LocatedValidationIssue}.
* @throws {InvalidPathException} If {@link path} matches no schemas.
*/
export function validate<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
externalContexts?: Record<string, unknown>,
): AsyncIterable<LocatedValidationIssue>;
export function validate<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
externalContexts?: Record<string, unknown>,
): AsyncIterable<LocatedValidationIssue>;
/**
* Validates the parts of the form value {@link formValue} matching {@link path}
* with schema {@link formSchema} against the provided
* [external validations]{@link externalValidations}. Returns an async iterable
* over all found [validation issues]{@link LocatedValidationIssue}.
*
* A map of external contexts may be provided for validations that depend on
* them.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of values to validate (defaults to `/**`).
* @param externalValidations External validations to validate the form value
* against.
* @param externalContexts External contexts used by validations.
* @returns Async iterable over all found
* [validation issues]{@link LocatedValidationIssue}.
* @throws {InvalidPathException} If {@link path} matches no schemas.
*/
export function validateExternally<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
externalValidations: Record<string, Validation[]>,
externalContexts?: Record<string, unknown>,
): AsyncIterable<LocatedValidationIssue>;
export function validateExternally<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
externalValidations: Record<string, Validation[]>,
externalContexts?: Record<string, unknown>,
): AsyncIterable<LocatedValidationIssue>;
/**
* Returns whether the parts of the form value {@link formValue} (with schema
* {@link formSchema}) matching {@link path} are valid according to their
* schemas. These parts are said to be valid if they contain no validation
* errors.
*
* A map of external contexts may be provided for validations that depend on
* them.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of values to check if valid (defaults to `/**`).
* @param externalContexts External contexts used by validations.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with whether all values at {@link path} are valid.
* @throws {InvalidPathException} If {@link path} matches no schemas.
*/
export function isValid<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path?: Path | string,
externalContexts?: Record<string, unknown>,
): CancellablePromise<boolean>;
export function isValid<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
externalContexts?: Record<string, unknown>,
): CancellablePromise<boolean>;
/**
* Returns whether the parts of the form value {@link formValue} (with schema
* {@link formSchema}) matching {@link path} are valid according to the provided
* [external validations]{@link externalValidations}. These parts are said to be
* valid if they contain no validation errors.
*
* A map of external contexts may be provided for validations that depend on
* them.
* @param formSchema Schema of the form.
* @param formValue Value of the form.
* @param path Path of values to validate (defaults to `/**`).
* @param externalValidations External validations to validate the form value
* against.
* @param externalContexts External contexts used by validations.
* @returns Async iterable over all found
* [validation issues]{@link LocatedValidationIssue}.
* @throws {InvalidPathException} If {@link path} matches no schemas.
*/
export function isValidExternally<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
path: Path | string,
externalValidations: Record<string, Validation[]>,
externalContexts?: Record<string, unknown>,
): CancellablePromise<boolean>;
export function isValidExternally<T = unknown>(
formSchema: Schema<T> | SchemaKt,
formValue: T,
externalValidations: Record<string, Validation[]>,
externalContexts?: Record<string, unknown>,
): CancellablePromise<boolean>;
// Cancellable promise =========================================================
/**
* A [promise-like]{@link PromiseLike} object that represents the eventual
* completion (or failure) of an asynchronous cancellable operation and its
* resulting value.
*
* It differs from a regular {@link Promise} in that it exposes a {@link cancel}
* method that, when called, possibly cancels the asynchronous operation. When
* cancelled, the promise will fail with a {@link PromiseCancellationException}.
*/
export declare class CancellablePromise<T> implements PromiseLike<T> {
private constructor();
then<TResult1 = T, TResult2 = never>(
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
): CancellablePromise<TResult1 | TResult2>;
catch<TResult = never>(
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null,
): CancellablePromise<T | TResult>;
finally(onFinally?: (() => void) | null): CancellablePromise<T>;
/**
* Method used to (possibly) cancel an ongoing asynchronous operation.
* @param causeMessage Reason for the cancellation.
*/
cancel(causeMessage?: string): void;
}
/**
* Exception emitted when a {@link CancellablePromise} has been successfully
* cancelled.
*/
export declare class PromiseCancellationException {
constructor(message?: string);
get message(): string;
}
// Schemas =====================================================================
/**
* Type of value represented by a schema.
*/
export declare class TypeInfo {
private constructor();
/**
* Name of the type.
*/
get name(): string;
/**
* Whether the type is nullable.
*/
get nullable(): boolean;
/**
* Type arguments.
*/
get arguments(): TypeInfo[];
/**
* Type and validation related "simple" restrictions, e.g. ("required", "min",
* "max", etc.).
*/
get restrictions(): Record<string, unknown>;
equals(other: unknown): boolean;
hashCode(): number;
toString(): string;
}
/**
* Kotlin representation of a [schema]{@link Schema}.
*/
export declare abstract class SchemaKt {}
/**
* Schema representing metadata on values of type `T`.
*
* The schema of a form is responsible for specifying which validations to run
* on it, as well as how to "manage" the form data. If a certain form contains a
* field of, for example, type `number`, then there should be a schema of type
* `Schema<number>` that holds the metadata required for knowing how to, for
* example, initialise said field and validate it.
*
* The [form manager]{@link FormManager} uses schemas extensively to, amongst
* others, initialise data, set data, and validate data; the schema is
* responsible for specifying **how** each different type of data is initialised
* or set.
*/
export declare abstract class Schema<T = unknown> {
private constructor();
/**
* Information about the type of value represented by this schema.
*/
get typeInfo(): TypeInfo;
/**
* List of validations used to validate this schema.
*/
get validations(): Validation<T>[];
/**
* Initial value for a value of this schema.
*
* New values of this schema will hold this value by default. Moreover, when a
* value of this schema is [reset]{@link FormManager.reset} by the
* [form manager]{@link FormManager}, it is set to this value.
*/
get initialValue(): T;
/**
* Returns a clone (deep copy) of {@link value}.
* @param value Value to clone.
* @returns A [cancellable promise]{@link CancellablePromise} that resolves
* with the cloned value.
*/
clone(value: T): CancellablePromise<T>;
}
/**
* Schema representing metadata on parent values of type `T`.
*
* "Parent" values, in this context, simply means values with children (children
* themselves also represented by their own schemas).
*/
export declare abstract class ParentSchema<T = unknown> extends Schema<T> {
private constructor();
}
/**
* Schema representing metadata on collections of type `T`.
*
* "Collections", in this context, simply means data structures that hold
* children of the same type and that support the addition and removal of
* values.
*/
export declare abstract class CollectionSchema<
T = unknown,
> extends ParentSchema<T> {
private constructor();
}
// Schema constructor functions:
export interface SchemaOptions<T = unknown> {
validations?: Validation<T>[];
initialValue?: T;
}
export declare function arraySchema<T = unknown>(
options: SchemaOptions<T[]>,
elementsSchema: Schema<T>,
): CollectionSchema<T[]>;
export declare function arraySchema<T = unknown>(
elementsSchema: Schema<T>,
): CollectionSchema<T[]>;
export declare function booleanSchema(
options?: SchemaOptions<boolean>,
): Schema<boolean>;
export declare function dateSchema(options?: SchemaOptions<Date>): Schema<Date>;
export declare function fileSchema(options?: SchemaOptions<File>): Schema<File>;
export declare function nullableSchema<T = unknown>(
options: SchemaOptions<T | null>,
childSchema: CollectionSchema<T>,
): CollectionSchema<T | null>;
export declare function nullableSchema<T = unknown>(
options: SchemaOptions<T | null>,
childSchema: ParentSchema<T>,
): ParentSchema<T | null>;
export declare function nullableSchema<T = unknown>(
options: SchemaOptions<T | null>,
childSchema: Schema<T>,
): Schema<T | null>;
export declare function nullableSchema<T = unknown>(
childSchema: CollectionSchema<T>,
): CollectionSchema<T | null>;
export declare function nullableSchema<T = unknown>(
childSchema: ParentSchema<T>,
): ParentSchema<T | null>;
export declare function nullableSchema<T = unknown>(
childSchema: Schema<T>,
): Schema<T | null>;
export declare function numberSchema(
options?: SchemaOptions<number>,
): Schema<number>;
export declare function bigIntegerSchema(
options?: SchemaOptions<BigInteger>,
): Schema<BigInteger>;
export declare function bigDecimalSchema(
options?: SchemaOptions<BigDecimal>,
): Schema<BigDecimal>;
export declare function objectSchema<
T extends Record<keyof T, unknown> = Record<string, unknown>,
TSchema extends { [TKey in keyof T]: Schema<T[TKey]> } = {
[TKey in keyof T]: Schema<T[TKey]>;
},
>(options: SchemaOptions<T>, fieldsSchemas: TSchema): ParentSchema<T>;
export declare function objectSchema<
T extends Record<keyof T, unknown> = Record<string, unknown>,
TSchema extends { [TKey in keyof T]: Schema<T[TKey]> } = {
[TKey in keyof T]: Schema<T[TKey]>;
},
>(fieldsSchemas: TSchema): ParentSchema<T>;
export declare function stringSchema(
options?: SchemaOptions<string>,
): Schema<string>;
export declare function tableSchema<T = unknown>(
options: SchemaOptions<Table<T>>,
elementsSchema: Schema<T>,
): CollectionSchema<Table<T>>;
export declare function tableSchema<T = unknown>(
elementsSchema: Schema<T>,
): CollectionSchema<Table<T>>;
// Paths =======================================================================
/**
* Possible path fragments.
*/
export type SealedPathFragment =
| typeof PathFragment.Root
| typeof PathFragment.CurrentPath
| typeof PathFragment.ParentPath
| SealedAbsolutePathFragment;
/**
* Fragment of a path.
*/
export declare abstract class PathFragment {
protected constructor();
equals(other: unknown): boolean;
hashCode(): number;
toString(): string;
/**
* Path fragment representing the root path.
*/
static get Root(): PathFragment & { toString(): "Root" };
/**
* Path fragment representing the current path (`"."` in string notation).
*/
static get CurrentPath(): PathFragment & { toString(): "CurrentPath" };
/**
* Path fragment representing the parent path (`".."` in string notation).
*/
static get ParentPath(): PathFragment & { toString(): "ParentPath" };
}
/**
* Possible absolute path fragments.
*/
export type SealedAbsolutePathFragment =
| AbsolutePathFragment.Id
| typeof AbsolutePathFragment.CollectionEnd
| typeof AbsolutePathFragment.Wildcard
| typeof AbsolutePathFragment.RecursiveWildcard;
/**
* Fragment of an absolute path.
*/
export declare abstract class AbsolutePathFragment extends PathFragment {
protected constructor();
/**
* Path fragment representing the "end" of a collection (`"-"` in string
* notation).
*
* This fragment represents the fictional element after the last element of a
* collection.
*/
static get CollectionEnd(): AbsolutePathFragment & {
toString(): "CollectionEnd";
};
/**
* Wildcard fragment (`"*"` in string notation).
*
* Wildcard fragments match against any other fragments.
*/
static get Wildcard(): AbsolutePathFragment & { toString(): "Wildcard" };
/**
* Recursive wildcard fragment (`"**"` in string notation).
*
* Recursive wildcard fragments match against zero or more any other fragments.
*/
static get RecursiveWildcard(): AbsolutePathFragment & {
toString(): "RecursiveWildcard";
};
}
export declare namespace AbsolutePathFragment {
/**
* Path fragment representing an identifier. In string notation, the id
* fragment `new AbsolutePathFragment.Id("x")` would be represented as `x`; if
* the string version of the fragment conflicts with a different fragment,
* then the fragment is escaped, e.g. the id fragment declared as
* `new AbsolutePathFragment.Id("*")` would be represented as `~*` in string
* notation.
*/
class Id extends AbsolutePathFragment {
constructor(id: NonNullable<unknown>);
/**
* Path fragment identifier.
*/
get id(): string;
}
}
/**
* Representation of a path as a list of path fragments.
*
* Paths represent locations of data, possibly relatively to other locations:
* e.g. the location of a value relative to the location of another value. They
* can also represent locations of data from the root when they contain a root
* fragment.
*/
export declare class Path {
constructor(path?: Path | string | SealedPathFragment[]);
/**
* List of fragments representing this path.
*/
get fragments(): SealedPathFragment[];
/**
* Returns the fragment of this path with index {@link index}.
* @param index Index of fragment to get.
* @throws {IndexOutOfBoundsException} When an out of bounds {@link index} is
* provided.
* @returns Fragment of this path with index {@link index}.
*/
fragment(index: number): SealedPathFragment;
/**
* Returns a new path representing the parent of this path.
*
* Note that the parent of the root path is the root path itself.
* @returns New path representing the parent of this path.
*/
parent(): Path;
/**
* Returns the path resulting from appending {@link fragments} to this path.
* @param fragments Fragments to append to this path.
* @returns Path resulting from appending {@link fragments} to this path.
*/
append(...fragments: SealedPathFragment[]): Path;
/**
* Returns the path resulting from joining {@link paths} together with this
* path.
* @param paths Paths to join with this path.
* @returns Path resulting from joining {@link paths} together with this path.
*/
join(...paths: (Path | string)[]): Path;
/**
* Returns the path resulting from resolving a list of {@link paths} against
* this path.
* @param paths Paths to