Skip to content

Commit

Permalink
Rename var(). Closes #1935
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Jun 26, 2019
1 parent 0298e88 commit 054681e
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 36 deletions.
6 changes: 3 additions & 3 deletions API.md
Expand Up @@ -15,7 +15,7 @@
- [`ref(key, [options])`](#refkey-options)
- [Relative references](#relative-references)
- [`isRef(ref)`](#isrefref)
- [`var(template, [options])`](#vartemplate-options)
- [`expression(template, [options])` - aliases: `x`](#expressiontemplate-options---aliases-x)
- [Template syntax](#template-syntax)
- [`isSchema(schema, [options])`](#isschemaschema-options)
- [`reach(schema, path)`](#reachschema-path)
Expand Down Expand Up @@ -564,9 +564,9 @@ const ref = Joi.ref('a');
Joi.isRef(ref); // returns true
```

### `var(template, [options])`
### `expression(template, [options])` - aliases: `x`

Generates a dyanmic variable using a template string where:
Generates a dyanmic expression using a template string where:
- `template` - the template string using the [template syntax](#template-syntax).
- `options` - optional settings used when creating internal references. Supports the same options
as [`ref()`](#refkey-options).
Expand Down
4 changes: 3 additions & 1 deletion lib/index.js
Expand Up @@ -109,11 +109,13 @@ internals.root = function () {
return Common.callWithDefaults(this, internals.symbol, args);
};

root.var = function (...args) {
root.expression = function (...args) {

return new Template(...args);
};

root.x = root.expression;

root.isVar = function (template) {

return Template.isTemplate(template);
Expand Down
2 changes: 1 addition & 1 deletion test/cast.js
Expand Up @@ -21,7 +21,7 @@ describe('cast', () => {

const schema = Joi.object({
a: Joi.number(),
b: Joi.var('{a + 1}')
b: Joi.x('{a + 1}')
});

expect(schema.validate({ a: 5, b: 6 }).error).to.not.exist();
Expand Down
6 changes: 3 additions & 3 deletions test/errors.js
Expand Up @@ -166,7 +166,7 @@ describe('errors', () => {
},
latin: {
root: 'valorem',
'number.min': Joi.var('{@label} angustus', { prefix: { local: '@' } })
'number.min': Joi.x('{@label} angustus', { prefix: { local: '@' } })
},
empty: {}
};
Expand Down Expand Up @@ -203,7 +203,7 @@ describe('errors', () => {
'number.min': '{#label} too small'
},
latin: {
'number.min': Joi.var('{@label} angustus', { prefix: { local: '@' } })
'number.min': Joi.x('{@label} angustus', { prefix: { local: '@' } })
},
empty: {}
};
Expand Down Expand Up @@ -232,7 +232,7 @@ describe('errors', () => {
'number.min': '{#label} too small'
},
latin: {
'number.min': Joi.var('{@label} angustus', { prefix: { local: '@' } })
'number.min': Joi.x('{@label} angustus', { prefix: { local: '@' } })
},
empty: {}
};
Expand Down
30 changes: 15 additions & 15 deletions test/template.js
Expand Up @@ -17,7 +17,7 @@ describe('Template', () => {
it('skips template without {', () => {

const source = 'text without variables';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.isDynamic()).to.be.false();
Expand All @@ -27,7 +27,7 @@ describe('Template', () => {
it('skips template without variables', () => {

const source = 'text {{{ without }}} any }} variables';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.isDynamic()).to.be.false();
Expand All @@ -37,7 +37,7 @@ describe('Template', () => {
it('skips template without variables (trailing {)', () => {

const source = 'text {{{ without }}} any }} variables {';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.isDynamic()).to.be.false();
Expand All @@ -47,7 +47,7 @@ describe('Template', () => {
it('skips template without variables (trailing {{)', () => {

const source = 'text {{{ without }}} any }} variables {{';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.isDynamic()).to.be.false();
Expand All @@ -57,7 +57,7 @@ describe('Template', () => {
it('skips template without reference variables (trailing {{)', () => {

const source = 'text {"x"} {{{ without }}} any }} variables {{';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.isDynamic()).to.be.false();
Expand All @@ -67,7 +67,7 @@ describe('Template', () => {
it('skips template without variables (escaped)', () => {

const source = 'text {{{ without }}} any }} \\{{escaped}} variables';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.isDynamic()).to.be.false();
Expand All @@ -77,7 +77,7 @@ describe('Template', () => {
it('parses template (escaped)', () => {

const source = 'text {{$x}}{{$y}}{{$z}} \\{{escaped}} xxx abc {{{ignore}} 123 {{x';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.render({}, {}, { context: { x: 'hello', y: '!' } })).to.equal('text hello! {{escaped}} xxx abc {{{ignore}} 123 {{x');
Expand All @@ -87,7 +87,7 @@ describe('Template', () => {
it('parses template with single variable', () => {

const source = '{$x}';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.render({}, {}, { context: { x: 'hello' } })).to.equal('hello');
Expand All @@ -96,7 +96,7 @@ describe('Template', () => {
it('parses template (raw)', () => {

const source = 'text {$x}{$y}{$z} \\{{escaped}} xxx abc {{{ignore}} 123 {{x';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.render({}, {}, { context: { x: 'hello', y: '!' } })).to.equal('text hello! {{escaped}} xxx abc {{{ignore}} 123 {{x');
Expand All @@ -105,16 +105,16 @@ describe('Template', () => {
it('parses template with odd {{ variables', () => {

const source = 'text {{$\\{{\\}} }} \\{{boom}} {{!\\}}';
const template = Joi.var(source);
const template = Joi.x(source);

expect(template.source).to.equal(source);
expect(template.render({}, {}, { context: { '{{}}': 'and' } })).to.equal('text and {{boom}} {{!}}');
});

it('throws on invalid characters', () => {

expect(() => Joi.var('test\u0000')).to.throw('Template source cannot contain reserved control characters');
expect(() => Joi.var('test\u0001')).to.throw('Template source cannot contain reserved control characters');
expect(() => Joi.x('test\u0000')).to.throw('Template source cannot contain reserved control characters');
expect(() => Joi.x('test\u0001')).to.throw('Template source cannot contain reserved control characters');
});

describe('isVar()', () => {
Expand All @@ -124,7 +124,7 @@ describe('Template', () => {
expect(Joi.isVar(null)).to.be.false();
expect(Joi.isVar({})).to.be.false();
expect(Joi.isVar('test')).to.be.false();
expect(Joi.isVar(Joi.var('test'))).to.be.true();
expect(Joi.isVar(Joi.x('test'))).to.be.true();
});
});

Expand All @@ -133,7 +133,7 @@ describe('Template', () => {
it('errors on tempalte with invalid formula', () => {

const source = '{x +}';
expect(() => Joi.var(source)).to.throw('Invalid template variable "x +" fails due to: Formula contains invalid trailing operator');
expect(() => Joi.x(source)).to.throw('Invalid template variable "x +" fails due to: Formula contains invalid trailing operator');
});
});

Expand All @@ -143,7 +143,7 @@ describe('Template', () => {

it('casts values to numbers', () => {

const schema = Joi.valid(Joi.var('{number(1) + number(true) + number(false) + number("1") + number($x)}'));
const schema = Joi.valid(Joi.x('{number(1) + number(true) + number(false) + number("1") + number($x)}'));
expect(schema.validate(3, { context: { x: {} } }).error).to.not.exist();
expect(schema.validate(4, { context: { x: {} } }).error).to.be.an.error('"value" must be one of [{number(1) + number(true) + number(false) + number("1") + number($x)}]');
});
Expand Down
14 changes: 7 additions & 7 deletions test/types/any.js
Expand Up @@ -1865,7 +1865,7 @@ describe('any', () => {
it('overrides message with template', () => {

const schema = Joi.number()
.min(10).message(Joi.var('way too small'));
.min(10).message(Joi.x('way too small'));

expect(schema.validate(1).error).to.be.an.error('way too small');
});
Expand All @@ -1879,7 +1879,7 @@ describe('any', () => {
},
latin: {
root: 'valorem',
'number.min': Joi.var('{@label} angustus', { prefix: { local: '@' } })
'number.min': Joi.x('{@label} angustus', { prefix: { local: '@' } })
}
};

Expand Down Expand Up @@ -1926,7 +1926,7 @@ describe('any', () => {

const messages = {
root: 'valorem',
'number.min': Joi.var('{@label} angustus', { prefix: { local: '@' } })
'number.min': Joi.x('{@label} angustus', { prefix: { local: '@' } })
};

const schema = Joi.object({ a: Joi.number().min(10).message(messages) });
Expand Down Expand Up @@ -2666,7 +2666,7 @@ describe('any', () => {

const schema = Joi.object({
a: Joi.number(),
b: Joi.valid(Joi.var('{a + 1}'))
b: Joi.valid(Joi.x('{a + 1}'))
});

expect(schema.validate({ a: 5, b: 6 }).error).to.not.exist();
Expand All @@ -2677,7 +2677,7 @@ describe('any', () => {

const schema = Joi.object({
a: Joi.number(),
b: Joi.valid(Joi.var('x{a + 1}'))
b: Joi.valid(Joi.x('x{a + 1}'))
});

expect(schema.validate({ a: 5, b: 'x6' }).error).to.not.exist();
Expand All @@ -2688,7 +2688,7 @@ describe('any', () => {

const schema = Joi.object({
a: Joi.number(),
b: Joi.valid(Joi.var('x'))
b: Joi.valid(Joi.x('x'))
});

expect(schema.validate({ a: 5, b: 'x' }).error).to.not.exist();
Expand All @@ -2700,7 +2700,7 @@ describe('any', () => {
const schema = Joi.object({
a: Joi.number(),
b: Joi.boolean(),
c: Joi.valid(Joi.var('{if(a == 5 && b == true, a * 2, null)}'))
c: Joi.valid(Joi.x('{if(a == 5 && b == true, a * 2, null)}'))
});

expect(schema.validate({ a: 5, b: true, c: 10 }).error).to.not.exist();
Expand Down
2 changes: 1 addition & 1 deletion test/types/date.js
Expand Up @@ -888,7 +888,7 @@ describe('date', () => {

it('supports template operations', () => {

const ref = Joi.var('{number(from) + 364 * day}');
const ref = Joi.x('{number(from) + 364 * day}');
const schema = Joi.object({
annual: Joi.boolean().required(),
from: Joi.date().required(),
Expand Down
10 changes: 5 additions & 5 deletions test/types/object.js
Expand Up @@ -1432,7 +1432,7 @@ describe('object', () => {
it('uses template', async () => {

const schema = Joi.object()
.rename(/^(\d+)$/, Joi.var('x{#1}x'))
.rename(/^(\d+)$/, Joi.x('x{#1}x'))
.pattern(/^x\d+x$/, Joi.any());

const input = {
Expand Down Expand Up @@ -1474,7 +1474,7 @@ describe('object', () => {
it('uses template with prefix override', async () => {

const schema = Joi.object()
.rename(/^(\d+)$/, Joi.var('x{@1}x', { prefix: { local: '@' } }))
.rename(/^(\d+)$/, Joi.x('x{@1}x', { prefix: { local: '@' } }))
.pattern(/^x\d+x$/, Joi.any());

const input = {
Expand Down Expand Up @@ -1518,7 +1518,7 @@ describe('object', () => {
const schema = Joi.object({
prefix: Joi.string().lowercase().required()
})
.rename(/^(\d+)$/, Joi.var('{.prefix}{#1}'))
.rename(/^(\d+)$/, Joi.x('{.prefix}{#1}'))
.unknown();

const input = {
Expand All @@ -1541,7 +1541,7 @@ describe('object', () => {

const schema = Joi.object({
a: Joi.object()
.rename(/^(\d+)$/, Joi.var('{b.prefix}{#1}'))
.rename(/^(\d+)$/, Joi.x('{b.prefix}{#1}'))
.unknown(),
b: {
prefix: Joi.string().lowercase()
Expand All @@ -1560,7 +1560,7 @@ describe('object', () => {
it('uses template without refs', async () => {

const schema = Joi.object()
.rename(/^(\d+)$/, Joi.var('x'))
.rename(/^(\d+)$/, Joi.x('x'))
.unknown();

const value = await Joi.compile(schema).validate({ 1: 'x' });
Expand Down

0 comments on commit 054681e

Please sign in to comment.