diff --git a/README.md b/README.md index a798dce..d172d2b 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,24 @@ console.log(config) // output: { PORT: 3000 } ``` -It is possible to enhance the default ajv instance providing the `customOptions` function parameter. +It is possible to enhance the default ajv instance providing the `customOptions` as a function or object parameter. + +When `customOptions` is an object, the provided ajv options override the default ones: + +```js +const config = envSchema({ + schema: schema, + data: data, + dotenv: true, + ajv: { + customOptions: { + coerceTypes: true + } + } +}) +``` + +When `customOptions` is a function, it must return the updated ajv instance. This example shows how to use the `format` keyword in your schemas. ```js @@ -100,8 +117,6 @@ const config = envSchema({ }) ``` -Note that it is mandatory to return the ajv instance. - ### Order of configuration loading The order of precedence for configuration data is as follows, from least diff --git a/index.js b/index.js index 0b0095a..f87daa6 100644 --- a/index.js +++ b/index.js @@ -91,19 +91,22 @@ function envSchema (_opts) { } function chooseAjvInstance (defaultInstance, ajvOpts) { - if (!ajvOpts) { - return defaultInstance - } else if (typeof ajvOpts === 'object' && typeof ajvOpts.customOptions === 'function') { - const ajv = ajvOpts.customOptions(getDefaultInstance()) + if (ajvOpts instanceof Ajv) { + return ajvOpts + } + let ajv = defaultInstance + if (typeof ajvOpts === 'object' && typeof ajvOpts.customOptions === 'function') { + ajv = ajvOpts.customOptions(getDefaultInstance()) if (!(ajv instanceof Ajv)) { throw new TypeError('customOptions function must return an instance of Ajv') } - return ajv + } else if (typeof ajvOpts === 'object' && typeof ajvOpts.customOptions === 'object') { + ajv = getDefaultInstance(ajvOpts.customOptions) } - return ajvOpts + return ajv } -function getDefaultInstance () { +function getDefaultInstance (overrideOpts = {}) { return new Ajv({ allErrors: true, removeAdditional: true, @@ -111,7 +114,8 @@ function getDefaultInstance () { coerceTypes: true, allowUnionTypes: true, addUsedSchema: false, - keywords: [separator] + keywords: [separator], + ...overrideOpts }) } diff --git a/test/custom-ajv.test.js b/test/custom-ajv.test.js index df76021..4949a68 100644 --- a/test/custom-ajv.test.js +++ b/test/custom-ajv.test.js @@ -298,8 +298,8 @@ const strictValidator = new Ajv({ }) test('ajv enhancement', async t => { - t.plan(2) - const testCase = { + t.plan(3) + const testCaseFn = { schema: { type: 'object', required: ['MONGODB_URL'], @@ -316,11 +316,27 @@ test('ajv enhancement', async t => { MONGODB_URL: 'mongodb://localhost/pippo' } } + const testCaseObj = { + schema: { + type: 'object', + required: ['PORT'], + properties: { + PORT: { + type: 'string', + } + } + }, + data: [{ PORT: 3333 }], + isOk: true, + confExpected: { + PORT: '3333' + } + } - await t.test('return', async t => { + await t.test('customOptions fn return', async t => { const options = { - schema: testCase.schema, - data: testCase.data, + schema: testCaseFn.schema, + data: testCaseFn.data, ajv: { customOptions (ajvInstance) { require('ajv-formats')(ajvInstance) @@ -328,13 +344,13 @@ test('ajv enhancement', async t => { } } } - makeTest(t, options, testCase.isOk, testCase.confExpected) + makeTest(t, options, testCaseFn.isOk, testCaseFn.confExpected) }) - await t.test('no return', async t => { + await t.test('customOptions fn no return', async t => { const options = { - schema: testCase.schema, - data: testCase.data, + schema: testCaseFn.schema, + data: testCaseFn.data, ajv: { customOptions (_ajvInstance) { // do nothing @@ -343,4 +359,17 @@ test('ajv enhancement', async t => { } makeTest(t, options, false, undefined, 'customOptions function must return an instance of Ajv') }) + + await t.test('customOptions object override', async t => { + const options = { + schema: testCaseObj.schema, + data: testCaseObj.data, + ajv: { + customOptions: { + coerceTypes: true, + } + } + } + makeTest(t, options, testCaseObj.isOk, testCaseObj.confExpected) + }) })