Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Facilitate extension of serialization of values in messages #3065

Open
GerkinDev opened this issue Feb 17, 2025 · 0 comments
Open

Facilitate extension of serialization of values in messages #3065

GerkinDev opened this issue Feb 17, 2025 · 0 comments
Labels
feature New functionality or improvement

Comments

@GerkinDev
Copy link

GerkinDev commented Feb 17, 2025

Runtime

NodeJS

Runtime version

22

Module version

17.13.3

Used with

Standalone

Any other relevant information

No response

What problem are you trying to solve?

The default serialization of values using template {#value} does not match our expected outcomes. I was looking for a way to improve it (by relying on require('node:utils').inspect.

  • I've tried using expressions only to switch formatting depending on value (I want to quote strings, but not int, and do this deeply within objects/array). For object, it resulted in [object Object]
  • I've tried to declare global functions I could use in expression without passing it explicitly everytime.
  • I ended up doing Joi.expression('{#label} expected to be ..., have {inspectValue(#value)}', { inspectValue(value) { return inspect(value) }}) for every overridden message. It works, but requires a lot of boilerplate code for something I'd like to make available for the whole app.

Do you have a new or modified API suggestion to solve the problem?

  • Add a method to declare template functions available for every expressions
  • Or add a way to customize Template's internal.stringify:

    joi/lib/template.js

    Lines 330 to 385 in 239ec33

    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) &&
    value.render) {
    skipWrap = value.in;
    value = value.resolve(original, state, prefs, local, { in: value.in, ...options });
    }
    if (value === null) {
    return 'null';
    }
    if (type === 'string') {
    return internals.wrap(value, options.arrayItems && wrap.string);
    }
    if (type === 'number' ||
    type === 'function' ||
    type === 'symbol') {
    return value.toString();
    }
    if (type !== 'object') {
    return JSON.stringify(value);
    }
    if (value instanceof Date) {
    return internals.Template.date(value, prefs);
    }
    if (value instanceof Map) {
    const pairs = [];
    for (const [key, sym] of value.entries()) {
    pairs.push(`${key.toString()} -> ${sym.toString()}`);
    }
    value = pairs;
    }
    if (!Array.isArray(value)) {
    return value.toString();
    }
    const values = [];
    for (const item of value) {
    values.push(internals.stringify(item, original, state, prefs, local, { arrayItems: true, ...options }));
    }
    return internals.wrap(values.join(', '), !skipWrap && wrap.array);
    };
@GerkinDev GerkinDev added the feature New functionality or improvement label Feb 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New functionality or improvement
Projects
None yet
Development

No branches or pull requests

1 participant