Skip to content

fix: treat example objects as values when rebuilding from describe() - #3157

Open
00200200 wants to merge 3 commits into
hapijs:masterfrom
00200200:fix-build-examples-with-type
Open

00200200 wants to merge 3 commits into
hapijs:masterfrom
00200200:fix-build-examples-with-type

Conversation

@00200200

@00200200 00200200 commented Sep 29, 2026 •

Copy link
Copy Markdown

Fixes #2480.

Joi.build() treated every object with a type property as a nested schema description. That is correct for keys, rules, and other schema terms, but examples are values. Rebuilding a schema whose example is { type: 'some-type' } (or constructing the same spec by hand) threw TypeError: this.joi[desc.type] is not a function.

This keeps example terms as literals during rebuild so describe() / build() round-trips, matching the existing { name: 'some-type' } case.

Testing

  • Added a regression in example() plus a describe() round-trip in the manifest builder tests.
  • Added native-type checks for Buffer, RegExp, and reference examples. Special descriptor decoding stays unchanged; the follow-up that treated reserved descriptor keys as plain objects was withdrawn.
  • Confirmed the new tests fail on current master (this.joi[desc.type] is not a function) and pass with this change.
  • Full suite: npm test — 1839 tests, 100% coverage, lint and types clean.

Joi.build() parsed example objects with a `type` property as nested
schemas, so describe()/build() round-trips failed for valid examples
such as { type: 'some-type' }. Fixes hapijs#2480.
Comment thread lib/manifest.js

if (desc.type) {
if (desc.type &&
!options.literal) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check only guards desc.type with options.literal. A single value, ref, regex, buffer, function or override key still unwraps above this line, so build still misreads those examples.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Handled options.literal before the single-key descriptor checks so literal objects containing value, ref, regex, override, buffer, or function are preserved as plain objects during rebuild. Added tests covering each of those cases.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving options.literal above the single-key checks makes build return Buffer, RegExp and ref examples as plain objects. Joi.build(Joi.binary().example(Buffer.from('abc')).describe()) gives an object example, where master gives a Buffer.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in c0ef7e4. Special single-key descriptors are decoded before checking the literal flag again. I withdrew the follow-up that treated reserved descriptor keys as plain objects, keeping this PR scoped to examples containing type. New tests verify actual Buffer, RegExp and reference types, not just describe() equality. Full npm test: 1839 tests, 100% coverage, lint and types clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

building Joi from spec fails when example object contains type property

2 participants