diff --git a/docs/build/schema.md b/docs/build/schema.md index 6f0cca7..aa969ce 100644 --- a/docs/build/schema.md +++ b/docs/build/schema.md @@ -546,6 +546,7 @@ Key | Required | Type | Description `dict` | no | `boolean` | Is this field a key/value input? `computed` | no | `boolean` | Is this field automatically populated (and hidden from the user)? `altersDynamicFields` | no | `boolean` | Does the value of this field affect the definitions of other fields in the set? +`inputFormat` | no | `string` | Useful when you expect the input to be part of a longer string. Put "{{input}}" in place of the user's input (IE: "https://{{input}}.yourdomain.com"). ----- diff --git a/exported-schema.json b/exported-schema.json index 112955d..29092f5 100644 --- a/exported-schema.json +++ b/exported-schema.json @@ -150,6 +150,11 @@ "altersDynamicFields": { "description": "Does the value of this field affect the definitions of other fields in the set?", "type": "boolean" + }, + "inputFormat": { + "description": "Useful when you expect the input to be part of a longer string. Put \"{{input}}\" in place of the user's input (IE: \"https://{{input}}.yourdomain.com\").", + "type": "string", + "pattern": "^.*{{input}}.*$" } }, "additionalProperties": false diff --git a/lib/schemas/FieldSchema.js b/lib/schemas/FieldSchema.js index e5d2f8e..f106ed4 100644 --- a/lib/schemas/FieldSchema.js +++ b/lib/schemas/FieldSchema.js @@ -101,6 +101,12 @@ module.exports = makeSchema({ description: 'Does the value of this field affect the definitions of other fields in the set?', type: 'boolean', }, + inputFormat: { + description: 'Useful when you expect the input to be part of a longer string. Put "{{input}}" in place of the user\'s input (IE: "https://{{input}}.yourdomain.com").', + type: 'string', + // TODO: Check if it contains one and ONLY ONE '{{input}}' + pattern: '^.*\{\{input\}\}.*$' + }, }, additionalProperties: false, }, [ diff --git a/test/index.js b/test/index.js index c46815c..28f600e 100644 --- a/test/index.js +++ b/test/index.js @@ -129,6 +129,50 @@ describe('app', () => { results.errors[1].stack.should.eql('instance.searchOrCreates.fooSearchOrCreate.search must match a "key" from a search (options: fooSearch)'); results.errors[2].stack.should.eql('instance.searchOrCreates.fooSearchOrCreate.create must match a "key" from a create (options: fooCreate)'); }); + + it('should validate inputFormat', () => { + const appCopy = copy(appDefinition); + appCopy.authentication = { + type: 'custom', + test: { + url: 'https://example.com', + }, + fields: [ + { + key: 'subdomain', + type: 'string', + required: true, + inputFormat: 'https://{{input}}.example.com', + }, + ], + }; + const results = schema.validateAppDefinition(appCopy); + results.errors.should.eql([]); + }); + + it('should invalidate illegal inputFormat', () => { + const appCopy = copy(appDefinition); + appCopy.authentication = { + type: 'custom', + test: { + url: 'https://example.com', + }, + fields: [ + { + key: 'subdomain', + type: 'string', + required: true, + inputFormat: 'https://{{input}.example.com', + }, + ], + }; + const results = schema.validateAppDefinition(appCopy); + results.errors.length.should.eql(1); + + const error = results.errors[0]; + error.name.should.eql('pattern'); + error.instance.should.eql('https://{{input}.example.com'); + }); }); describe('export', () => {