feat(middleware-joi): type extraction from "joi" schema object
MODIFY
packages/middleware-joi/package.json
packages/middleware-joi/package.json
"rxjs": "~6.2.2"
},
"dependencies": {
- "joi": "^14.0.6"
+ "joi": "14.0.6",
+ "@types/joi": "^14.0.0"
},
"devDependencies": {
"@marblejs/core": "^1.2.1",
- "@marblejs/middleware-body": "^1.2.1",
- "@types/joi": "^14.0.0"
+ "@marblejs/middleware-body": "^1.2.1"
},
"publishConfig": {
"access": "public"

ADD
packages/middleware-joi/src/joi.types.ts
+import 'joi';
+
+declare module 'joi' {
+ // Object Schema
+ export function object<T>(schema: T): ObjectSchema<T>;
+ export interface ObjectSchema<T = null> {
+ keys<T>(schema: T): ObjectSchema<ExtractType<T>>;
+ }
+
+ // ArraySchema
+ export function array<T>(schema: T): ArraySchema<ExtractType<T>>;
+ export interface ArraySchema<T = null> {
+ items<T>(schema: T): ArraySchema<ExtractType<T>>;
+ }
+
+ // ExtractType
+ export type ExtractType<T> =
+ T extends NumberSchema ? number :
+ T extends BooleanSchema ? boolean :
+ T extends StringSchema ? string :
+ T extends DateSchema ? Date :
+ T extends ObjectSchema<infer U> ?
+ U extends null ? Record<string, any> : { [K in keyof U]: ExtractType<U[K]> } :
+ T extends ArraySchema<infer U> ?
+ U extends null ? any[] : U[] :
+ any;
+}

DELETE
packages/middleware-joi/src/schema.ts
-import * as Joi from 'joi';
-
-export const SchemaValidator = Joi.object().keys({
- headers: Joi.object(),
- params: Joi.object(),
- query: Joi.object(),
- body: Joi.object(),
-}).min(1);
-
-export type ExtractType<T extends Joi.SchemaLike> =
- T extends Joi.NumberSchema ? number :
- T extends Joi.BooleanSchema ? boolean :
- T extends Joi.StringSchema ? string :
- T extends Joi.ObjectSchema ? object :
- any;
-
-export interface Schema<
- TBody = any,
- TParams = any,
- TQuery = any,
- THeaders = any,
-> {
- body: TBody;
- params: TParams;
- query: TQuery;
- headers: THeaders;
-}

MODIFY
packages/middleware-joi/src/validator.middleware.ts
packages/middleware-joi/src/validator.middleware.ts
import * as Joi from 'joi';
-import { Schema, SchemaValidator, ExtractType } from './schema';
+import './joi.types';
import { HttpRequest, HttpError, HttpStatus } from '@marblejs/core';
import { from, of, throwError, Observable } from 'rxjs';
import { mergeMap, flatMap, catchError, mapTo, switchMap, toArray, map } from 'rxjs/operators';
+import { Schema, SchemaValidator } from './validator.schema';
const validateSource = (rules: Map<string, any>, options: Joi.ValidationOptions) => (req: HttpRequest) =>
from(rules.keys()).pipe(
@@ -34,10 +35,9 @@ export const validator$ = <TBody = any, TParams = any, TQuery = any>
return throwError(result.error);
}
- type ValidatorSchema = Schema<TBody, TParams, TQuery>;
type ExtractedSchema = {
- [K1 in keyof ValidatorSchema]: {
- [K2 in keyof ValidatorSchema[K1]]: ExtractType<ValidatorSchema[K1][K2]>;
+ [K1 in keyof typeof schema]: {
+ [K2 in keyof typeof schema[K1]]: Joi.ExtractType<typeof schema[K1][K2]>;
}
};

ADD
packages/middleware-joi/src/validator.schema.ts
+import * as Joi from 'joi';
+
+export const SchemaValidator = Joi.object().keys({
+ headers: Joi.object(),
+ params: Joi.object(),
+ query: Joi.object(),
+ body: Joi.object(),
+}).min(1);
+
+export interface Schema<TBody = any, TParams = any, TQuery = any, THeaders = any> {
+ body: TBody;
+ params: TParams;
+ query: TQuery;
+ headers: THeaders;
+}

MODIFY
packages/middleware-joi/test/helpers/api.spec-util.ts
packages/middleware-joi/test/helpers/api.spec-util.ts
@@ -21,10 +21,12 @@ const getUser$ = EffectFactory
.use(req$ => req$
.pipe(
use(validator$({
- params: { id: Joi.number().integer().min(1).max(10).required() }
+ params: {
+ id: Joi.number().integer().min(1).max(10).required(),
+ }
})),
map(req => req.params),
- map(params => ({ status: 200, body: { id: params!.id } }))
+ map(params => ({ status: 200, body: { id: params.id } }))
));
const storePost$ = EffectFactory

MODIFY
yarn.lock
yarn.lock
@@ -3339,7 +3339,7 @@ jest@^23.5.0:
import-local "^1.0.0"
jest-cli "^23.5.0"
-joi@^14.0.6:
+joi@14.0.6:
version "14.0.6"
resolved "https://registry.yarnpkg.com/joi/-/joi-14.0.6.tgz#8c72314af6dba13ca48028a4f0af992ddc5a7472"
dependencies:

feat(middleware-joi): type extraction from "joi" schema object