From 054681ef4cabd33ad4b7e3804362af32dc8bb38f Mon Sep 17 00:00:00 2001 From: Eran Hammer Date: Tue, 25 Jun 2019 23:42:58 -0700 Subject: [PATCH] Rename var(). Closes #1935 --- API.md | 6 +++--- lib/index.js | 4 +++- test/cast.js | 2 +- test/errors.js | 6 +++--- test/template.js | 30 +++++++++++++++--------------- test/types/any.js | 14 +++++++------- test/types/date.js | 2 +- test/types/object.js | 10 +++++----- 8 files changed, 38 insertions(+), 36 deletions(-) diff --git a/API.md b/API.md index 59ff77f9a..e23e8ccc6 100755 --- a/API.md +++ b/API.md @@ -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) @@ -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). diff --git a/lib/index.js b/lib/index.js index ffbda78ae..36acfaee6 100755 --- a/lib/index.js +++ b/lib/index.js @@ -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); diff --git a/test/cast.js b/test/cast.js index 115e0550d..43ac1f387 100755 --- a/test/cast.js +++ b/test/cast.js @@ -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(); diff --git a/test/errors.js b/test/errors.js index c0d7e75a3..5183d85e9 100755 --- a/test/errors.js +++ b/test/errors.js @@ -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: {} }; @@ -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: {} }; @@ -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: {} }; diff --git a/test/template.js b/test/template.js index fbd41f178..b68301268 100755 --- a/test/template.js +++ b/test/template.js @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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'); @@ -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'); @@ -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'); @@ -105,7 +105,7 @@ 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}} {{!}}'); @@ -113,8 +113,8 @@ describe('Template', () => { 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()', () => { @@ -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(); }); }); @@ -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'); }); }); @@ -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)}]'); }); diff --git a/test/types/any.js b/test/types/any.js index 1203e68aa..f5ffc9faf 100755 --- a/test/types/any.js +++ b/test/types/any.js @@ -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'); }); @@ -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: '@' } }) } }; @@ -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) }); @@ -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(); @@ -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(); @@ -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(); @@ -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(); diff --git a/test/types/date.js b/test/types/date.js index 8eb9c3a69..01cc32378 100755 --- a/test/types/date.js +++ b/test/types/date.js @@ -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(), diff --git a/test/types/object.js b/test/types/object.js index 312070937..6a746fed4 100755 --- a/test/types/object.js +++ b/test/types/object.js @@ -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 = { @@ -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 = { @@ -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 = { @@ -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() @@ -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' });