Skip to content

Commit

Permalink
Support wrapping of strings inside arrays. Closes #2706
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Dec 2, 2021
1 parent 013af55 commit b4dbd59
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 13 deletions.
1 change: 1 addition & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,7 @@ Validates a value using the current schema and options where:
- `wrap` - overrides the way values are wrapped (e.g. `[]` around arrays, `""` around labels and variables prefixed with `:`). Each key can be set to a string with one (same character before and after the value) or two characters (first character before and second character after), or `false` to disable wrapping:
- `label` - the characters used around `{#label}` references. Defaults to `'"'`.
- `array` - the characters used around array values. Defaults to `'[]'`.
- `string` - the characters used around each array string values. Defaults to `false`.
- `wrapArrays` - if `true`, array values in error messages are wrapped in `[]`. Defaults to `true`.
- `externals` - if `false`, the external rules set with [`any.external()`](#anyexternalmethod-description) are ignored, which is required to ignore any external validations in synchronous mode (or an exception is thrown). Defaults to `true`.
- `messages` - overrides individual error messages. Defaults to no override (`{}`). Use the `'*'` error code as a catch-all for all error codes that do not have a message provided in the override. Messages use the same rules as [templates](#template-syntax). Variables in double braces `{{var}}` are HTML escaped if the option `errors.escapeHtml` is set to `true`.
Expand Down
9 changes: 8 additions & 1 deletion lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,18 @@ declare namespace Joi {
label?: string | false,

/**
* the characters used around array avlues. Defaults to `'[]'`
* the characters used around array values. Defaults to `'[]'`
*
* @default '[]'
*/
array?: string | false

/**
* the characters used around array string values. Defaults to no wrapping.
*
* @default false
*/
string?: string | false
};
}

Expand Down
3 changes: 2 additions & 1 deletion lib/schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ exports.preferences = Joi.object({
stack: Joi.boolean(),
wrap: {
label: internals.wrap,
array: internals.wrap
array: internals.wrap,
string: internals.wrap
}
},
externals: Joi.boolean(),
Expand Down
15 changes: 6 additions & 9 deletions lib/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,10 @@ internals.wrap = function (value, ends) {
};


internals.stringify = function (value, original, state, prefs, local, options) {
internals.stringify = function (value, original, state, prefs, local, options = {}) {

const type = typeof value;
const wrap = prefs && prefs.errors && prefs.errors.wrap || {};

let skipWrap = false;
if (Ref.isRef(value) &&
Expand All @@ -324,7 +325,7 @@ internals.stringify = function (value, original, state, prefs, local, options) {
}

if (type === 'string') {
return value;
return internals.wrap(value, options.arrayItems && wrap.string);
}

if (type === 'number' ||
Expand Down Expand Up @@ -355,16 +356,12 @@ internals.stringify = function (value, original, state, prefs, local, options) {
return value.toString();
}

let partial = '';
const values = [];
for (const item of value) {
partial = partial + (partial.length ? ', ' : '') + internals.stringify(item, original, state, prefs, local, options);
}

if (skipWrap) {
return partial;
values.push(internals.stringify(item, original, state, prefs, local, { arrayItems: true, ...options }));
}

return internals.wrap(partial, prefs.errors.wrap.array);
return internals.wrap(values.join(', '), !skipWrap && wrap.array);
};


Expand Down
7 changes: 5 additions & 2 deletions test/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,16 @@ describe('errors', () => {

const schema = Joi.object({
a: Joi.number().min(10),
lang: Joi.string().required()
lang: Joi.string().required(),
select: ['x']
})
.prefs({
messages,
errors: {
language: Joi.ref('/lang'),
wrap: {
label: '{}'
label: '{}',
string: '`\''
}
}
});
Expand All @@ -305,6 +307,7 @@ describe('errors', () => {
expect(schema.validate({ a: 1, lang: 'latin' }).error).to.be.an.error('{a} angustus');
expect(schema.validate({ a: 1, lang: 'unknown' }).error).to.be.an.error('{a} must be greater than or equal to 10');
expect(schema.validate({ a: 1, lang: 'empty' }).error).to.be.an.error('{a} must be greater than or equal to 10');
expect(schema.validate({ select: 'y', a: 20, lang: 'empty' }).error).to.be.an.error('{select} must be [`x\']');
});

it('supports render preference', () => {
Expand Down

0 comments on commit b4dbd59

Please sign in to comment.