Skip to content

Extensions remove language of previous extension with the same base #1658

@tomyam1

Description

@tomyam1

Context

  • node version: v8.10.0
  • joi version: 14.1.0
  • environment (node, browser): node
  • used with (hapi, standalone, ...): standalone
  • any other relevant information:

What are you trying to achieve or the steps to reproduce ?

Here is an example of two extensions for the number base type. The first extension loses its language definition.

After tracing the code, this seems to happen because language definitions are merged using Object.assign. Maybe something like lodash.merge would be more appropriate?

const BaseJoi = require('joi');
const Assert = require('assert');

const ExtendedJoi = BaseJoi.extend(
    function (joi) {
        return {
            base: joi.number(),
            name: 'number',
            language: {
                greaterThan10: `Must be > 10`
            },
            rules: [
                {
                    name: `greaterThan10`,
                    validate(params, value, state, options) {
                        return value > 10
                            ? value
                            : this.createError(`number.greaterThan10`, {v: value}, state, options)
                    }
                }
            ]
        }
    },
    function (joi) {
        return {
            base: joi.number(),
            name: 'number',
            language: {
                greaterThan20: `Must be > 20`
            },
            rules: [
                {
                    name: `greaterThan20`,
                    validate(params, value, state, options) {
                        return value > 20
                            ? value
                            : this.createError(`number.greaterThan20`, {v: value}, state, options)
                    }
                }
            ]
        }
    }
);

const schema = ExtendedJoi.number()
    .greaterThan10()
    .greaterThan20();

// Passes both rules
Assert.equal(schema.validate(30).value, 30);

// Failed second rule - message is OK
Assert.equal(schema.validate(15).error.message, '"value" Must be > 20');

// Failed first rule - can't use it's language
Assert.equal(schema.validate(5).error.message, 'Error code "number.greaterThan10" is not defined, your custom type is missing the correct language definition');

Which result you had ?

The first extension lost its language definition.

What did you expect ?

Both extension would work as expected

Metadata

Metadata

Assignees

Labels

bugBug or defect

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions