joi icon indicating copy to clipboard operation
joi copied to clipboard

Question: Is there a way to create a subschema without some fields of base schema dynamically?

Open AndriiNyzhnyk opened this issue 2 years ago • 2 comments

Context

  • node version: 12+
  • module version: 17.6.0
  • environment (e.g. node, browser, native): node

How can we help?

I have a case where I need to create a function which accepts joi schema as the first argument and array of string(object's keys) as the second argument. The main idea here is to return a new schema which consists of a base schema without keys which was mentioned as the second argument. Also, it would be cool to know how to do it with nested schemas.

I have tried different approaches(with different Joi methods), but I did not get the right behavior. Could someone help me to resolve this case?

const schema = Joi.object({
    a: Joi.any(),
    b: Joi.any()
});

exclude(schema, ['b']) // should return new schema, like Joi.object({ a: Joi.any() })

Also, it will be cool to be able do like this:

const schema = Joi.object({
    a: Joi.any(),
    b: Joi.any(),
    c:  Joi.object({
      d: Joi.any(),
      e: Joi.any()
    })
});

exclude(schema, ['c.d']) // should return new schema, like
Joi.object({
    a: Joi.any(),
    b: Joi.any(),
    c:  Joi.object({
      e: Joi.any()
    })
});

AndriiNyzhnyk avatar Jun 20 '22 15:06 AndriiNyzhnyk

Hey, have you tried the combination of append with extract? I think it'll only work for objects, but should work for your intended use case:

'use strict';

const Joi = require('joi');

function extract(schema, ignore) {
    let result = Joi.object();

    for (const key of Object.keys(schema.describe().keys)) {
        if (!ignore.includes(key)) {
            result = result.append({ [key]: schema.extract(key) });
        }
    }

    return result;
}

const Schema = Joi.object({
    a: Joi.string(),
    b: Joi.string(),
    c: Joi.object({
        d: Joi.string(),
    }),
});

const CSchema = extract(Schema, ['a', 'b']);

Joi.assert({ c: { d: 'value' } }, CSchema); // ok
Joi.assert({ a: 'value' }, CSchema); // "a" is not allowed
Joi.assert({ b: 'value' }, CSchema); // "b" is not allowed

const BCSchema = extract(Schema, ['a']);

Joi.assert({ c: { d: 'value' } }, BCSchema); // ok
Joi.assert({ b: 'value' }, BCSchema); // ok
Joi.assert({ a: 'value' }, BCSchema); // "a" is not allowed

jonathansamines avatar Sep 04 '22 23:09 jonathansamines

Am getting this error - I have cross check everything ever the spelling..Will appreciate any reply or support on this.Thanks in advance

loginForm.jsx:24 Uncaught TypeError: schema.extract is not a function

Am using joi-browser

These are my code: const schema = Joi.object({ username: Joi.string().required().min(4).label("Username"), password: Joi.string().required().label("Password"), })

const rule = schema.extract("username"); console.log(rule)

IbrahimO123 avatar Oct 21 '22 04:10 IbrahimO123