@marblejs/middleware-io
yarn add @marblejs/middleware-io
Requires
@marblejs/core
to be installed.// HTTP
import { requestValidator$ } from '@marblejs/middleware-io';
// Events, eg. WebSockets
import { eventValidator$ } from '@marblejs/middleware-io';
requestValidator$ :: (RequestSchema, ValidatorOptions) -> Observable<HttpRequest> -> Observable<HttpRequest>
eventValidator$ :: (Schema, ValidatorOptions) -> Observable<Event> -> Observable<Event>
requestValidator$
parameter | definition |
schema | |
options | <optional> ValidatorOptions |
eventValidator$
parameter | definition |
schema | |
options | <optional> ValidatorOptions |
ValidatorOptions
parameter | definition |
reporter | <optional> Reporter |
context | <optional> string |
Let's define a user schema that will be used for I/O validation.
user.schema.ts
export const userSchema = t.type({
id: t.string,
firstName: t.string,
lastName: t.string,
roles: t.array(t.union([
t.literal('ADMIN'),
t.literal('GUEST'),
])),
});
export type User = t.TypeOf<typeof userSchema>;
import { use, r } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { userSchema } from './user.schema.ts';
const effect$ = r.pipe(
r.matchPath('/'),
r.matchType('POST'),
r.useEffect(req$ => req$.pipe(
requestValidator$({ body: userSchema }),
// ..
)));
You can also reuse the same schema for Events validation if you want.
import { matchEvent, act } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';
import { eventValidator$, t } from '@marblejs/middleware-io';
import { userSchema } from './user.schema.ts';
const postUser$: WsEffect = event$ =>
event$.pipe(
matchEvent('CREATE_USER'),
act(eventValidator$(userSchema)),
act(event => { ... }),
);
The inferred
req.body
/ event.payload
type of provided schema, will be of the following form:type User = {
id: string;
firstName: string;
lastName: string;
roles: ('ADMIN' | 'GUEST')[];
};
Please note that each
eventValidator$
must be applied inside act
operator to prevent closing of the main observable stream.Lets take a look at the default reported validation error thrown by
eventValidator$
. Let's assume that client passed wrong values for firstName
and roles
fields.payload.lastName = false;
payload.roles = ['TEST'];
The reported error intercepted via default error effect will look like follows.
{
type: 'CREATE_USER',
error: {
message: 'Validation error',
data: [
{
path: 'lastName',
expected: 'string',
got: 'false'
},
{
path: 'roles.0.0',
got: '"TEST"',
expected: '"ADMIN"'
},
{
path: 'roles.0.1',
got: '"TEST"',
expected: '"GUEST"'
}
]
}
}
interface Reporter<A> {
report: (validation: Validation<any>) => A
}
In order to use custom reporter you have to pass it with
options
object as a second argument.requestValidator$(schema, { reporter: customReporter });
Last modified 2yr ago