joi icon indicating copy to clipboard operation
joi copied to clipboard

"Item cannot come after itself" from ref with a duplicated property name

Open joshkel opened this issue 2 years ago • 2 comments

Support plan

  • is this issue currently blocking your project? (yes/no): no
  • is this issue affecting a production system? (yes/no): yes

Context

  • node version: 14.20.1
  • module version with issue: 17.7.0
  • last module version without issue: not tested
  • environment (e.g. node, browser, native): Node.js
  • used with (e.g. hapi application, another framework, standalone, ...): Hapi
  • any other relevant information:

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

I'm using a Knex ref with a nested key with a duplicate name.

For example:

const schema = Joi.object({
  id: Joi.number().required(),
  command: Joi.object({
    command: Joi.string().valid('run', 'jump').required(),
    params: Joi.alternatives().conditional('command', {
      switch: [
        {
          is: 'run',
          then: Joi.object({ howFast: Joi.number().required() }),
        },
        {
          is: 'jump',
          then: Joi.object({ howHigh: Joi.number().required() }),
        },
      ],
    }),
  })
});

A sample of a message that complies with this:

{
  id: 1,
  command: {
    command: 'run',
    params: { howFast: 1 },
  }
}

What was the result you got?

An error message is thrown within @hapi/topo:

Item cannot come after itself: command

What result did you expect?

Usable schema

I'm working around this by renaming one of my property keys.

joshkel avatar Nov 10 '22 16:11 joshkel

@joshkel You can try Joi.alternatives().conditional('/command.command', ...)

TMaszko avatar Nov 29 '22 14:11 TMaszko

This looks like a bug. You can work around it with this until I understand what's happening:

const schema = Joi.object({
  id: Joi.number().required(),
  command: Joi.object({
    command: Joi.string().valid('run', 'jump').required(),
    params: Joi.when('command', {
      switch: [
        {
          is: 'run',
          then: Joi.object({ howFast: Joi.number().required() }),
        },
        {
          is: 'jump',
          then: Joi.object({ howHigh: Joi.number().required() }),
        },
      ],
    }),
  })
});

Marsup avatar Mar 29 '23 17:03 Marsup