2.0.0 • Published 3 years ago

jsvrx v2.0.0

Weekly downloads
1
License
MIT
Repository
github
Last release
3 years ago

jsvrx

RxJS operators to validate/discriminate data objects using JSON Schema(s).

npm rxjs npm bundle size Top Language MIT License

Features

  • Basic DataValidator interface to validate/discriminate data objects
    • validate a data object using single JSON Schema
    • discriminate a data object using set of JSON Schemas
  • Data validation and JSON Schema processing can be provided by third-party libraries
  • Compatible with standard RxJS data processing
  • ECMAScript module, typings available

Usage

The package declares an abstract DataValidator interface. Use existing implementations or create your own.

Known implementations:

Examples

Parse a string and validate objects array

const data: string = ...; // JSON encoded array of objects T
const schema: JSONSchema = { $id: 'SCHEMA', ... }; // JSON Schema of type T

const dv: DataValidator = new someDataValidator(...);
dv.addSchemas([schema]);

of(data).pipe(
  map((s) => JSON.Parse(s)),
  mergeMap((arr) => from(arr)),
  dv.validate(schema.$id)
); // <-- Observable<T>

Parse a string and discriminate object array

const data: string = ...; // JSON encoded array of objects
const schemas: JSONSchema[] = [...]; // JSON Schemas of types in data

const dv: DataValidator = new someDataValidator(...);
dv.addSchemas(schemas);

of(data).pipe(
  map((s) => JSON.Parse(s)),
  switchMap((arr) => from(arr)),
  dv.discriminate(schemas.map((s) => s.$id), 'invalid'),
  mergeMap((group) => 
    group.pipe(
      // Processing specific to object validated by JSON Schema group.key
      toArray(),
      map((arr) => ({ [group.key]: arr }))
    )
  )
  reduce((acc, g) => ({ ...acc, ...g }), {} as Record<string, unknown[]>)
); // <-- Observable<{ ID1: [...], ID2: [...], ... , invalid: [...] }>

DataValidator interface constructs validators and discriminators to use in RxJS data stream processing to validate unknown data object or produce new data streams based on validation results using a set of JSON Schemas.

DataValidator interface

DataValidator interface provides methods to add JSON Schemas and to construct validate and dicriminate RxJS operators for a set of Schema ids. To start processing data is RxJS stream one can take the following steps: 1. Instantiate an implementation of DataValidator interface; 2. Add required JSON Schema using addSchemas() method or by other means provided. Every schema should have a unique identifier that is used to reference the schema in validate() and discriminate() methods. 3. Get required RxJS operator for a set of JSON Schema identifiers using validate() or discriminate() methods. 4. Use the operator in RxJS data processing pipe().

Validator

A validate operator uses a single JSON Schema to validate data objects and throw an error if failed. Consider discriminate operator if multiple JSON Schemas validation or custom error handling is required.

validate(id: JSONSchemaID) constructs RxJS operator to validate data objects using JSON Schema selected by id. If validation fails a ValidationError() error is thrown.

The operator returns Observable.

Discriminator

A discriminate operator uses a set of JSON Schemas to validate data objects and creates new RxJS output data streams. Every input object is validated and placed in the output data stream according to the object's validated type. Invalid objects are placed in a dedicated output data stream.

discriminate(ids: JSONSchemaID[], unk?: JSONSchemaID) constructs RxJS operator to discriminate data objects using a set of JSON Schemas defined by ids array. Validated objects are grouped by JSON Schema and are marked with the schema's id, invalid objects are reported in a group marked with unk value. If validation fails and unk is not set a ValidationError() error is thrown.

The operator returns GroupedObservable for every unique schema id.

Validation resultunk parameterGroupedObservable.key
Validated by a schema id-id
Invalidpresentinv
InvalidabsentValidationError is thrown

Typing

DataValidator interface provides typing information for validate and discriminate methods using generics.

validate<T>(...): OperatorFunction<unknown, T>

T is unknown by default.

It's possible to create a JSON Schema -> Type mapping type to control discriminate operator typing.

// IDx - JSON schema ids, Tx - corresponding typescript types
type M = { ID1: T1, ID2: T2 }; 

discriminate<M>(...): OperatorFunction<
  unknown,
  GroupedObservable<ID1, T1> | GroupedObservable<ID2, T2>>
>

M is { [JSONSchemaID]: unknown } by default.

discriminate(...): OperatorFunction<
  unknown, 
  GroupedObservable<string, unknown>
>

A custom implementation

The package declares two functions to help implementing custom provider DataValidator interface:

  • validate<T>(v: (obj: unknown) => T)): ValidatorOperator<T>
  • discriminate<M>(d: (obj: unknown) => keyof M)) DiscriminatorOperator<M>

Both functions with a projector provided as a parameter return correct RxJS operator to implement DataValidator interface requirements.

To design a custom provider: 1. Declare a class that implements the DataValidator interface. 2. Desing a custom constructor method. 3. Implement addSchemas(schemas: JSONSchema[]) method. 4. In validate(id: JSONSchemaID) method implementation define a functions that validates unknown object with JSONSchema. Return helper validate() with the function as the parameter. 5. In discriminate(ids: JSONSchemaID[], unk?: JSONSchemaID) method implementation define a functions that validates unknown object with set of JSONSchemas and choose the schema id or unk value. Return helper discriminate() with the function as the parameter.