From a2f1808b2f2a2cc7cb18a57ccc81c68e6a16dfc2 Mon Sep 17 00:00:00 2001 From: Mariusz Nowak Date: Thu, 8 Apr 2021 13:13:18 +0200 Subject: [PATCH] refactor(Variables): Testing purpose variable resolution util --- lib/configuration/variables/index.js | 53 +++++++++++++++++++ .../lib/configuration/variables/index.test.js | 37 +++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 lib/configuration/variables/index.js create mode 100644 test/unit/lib/configuration/variables/index.test.js diff --git a/lib/configuration/variables/index.js b/lib/configuration/variables/index.js new file mode 100644 index 000000000..3a1649855 --- /dev/null +++ b/lib/configuration/variables/index.js @@ -0,0 +1,53 @@ +// Resolves all non instance dependent variables in a provided configuraton +// This util is not used in Serveless process flow, but is handy for side resolution of variables + +'use strict'; + +const ensureString = require('type/string/ensure'); +const ensurePlainObject = require('type/plain-object/ensure'); +const resolveMeta = require('./resolve-meta'); +const resolve = require('./resolve'); + +const sources = { + env: require('./sources/env'), + file: require('./sources/file'), + opt: require('./sources/opt'), + self: require('./sources/self'), + strToBool: require('./sources/str-to-bool'), +}; + +const reportEventualErrors = (variablesMeta) => { + const resolutionErrors = new Set( + Array.from(variablesMeta.values(), ({ error }) => error).filter(Boolean) + ); + + if (!resolutionErrors.size) return; + + throw new Error( + `Variables resolution errored with:${Array.from( + resolutionErrors, + (error) => `\n - ${error.message}` + )}`, + 'VARIABLES_RESOLUTION_ERROR' + ); +}; + +module.exports = async ({ servicePath, configuration, options }) => { + servicePath = ensureString(servicePath); + ensurePlainObject(configuration); + options = ensurePlainObject(options, { default: {} }); + + const variablesMeta = resolveMeta(configuration); + reportEventualErrors(variablesMeta); + + await resolve({ + servicePath, + configuration, + variablesMeta, + sources, + options, + fulfilledSources: new Set(['env', 'file', 'opt', 'self', 'strToBool']), + }); + + reportEventualErrors(variablesMeta); +}; diff --git a/test/unit/lib/configuration/variables/index.test.js b/test/unit/lib/configuration/variables/index.test.js new file mode 100644 index 000000000..ba09378c1 --- /dev/null +++ b/test/unit/lib/configuration/variables/index.test.js @@ -0,0 +1,37 @@ +'use strict'; + +const { expect } = require('chai'); + +const fs = require('fs').promises; +const resolve = require('../../../../../lib/configuration/variables'); + +describe('test/unit/lib/configuration/variables/index.test.js', () => { + let configuration; + before(async () => { + process.env.ENV_SOURCE_TEST = 'foobar'; + await fs.writeFile('foo.json', JSON.stringify({ json: 'content' })); + configuration = { + env: '${env:ENV_SOURCE_TEST}', + file: '${file(foo.json)}', + opt: '${opt:option}', + self: '${self:opt}', + strToBool: "${strToBool('false')}", + }; + await resolve({ + servicePath: process.cwd(), + configuration, + options: { option: 'bar' }, + }); + }); + + after(() => { + delete process.env.ENV_SOURCE_TEST; + }); + + it('should resolve "env" source', () => expect(configuration.env).to.equal('foobar')); + it('should resolve "file" source', () => + expect(configuration.file).to.deep.equal({ json: 'content' })); + it('should resolve "opt" source', () => expect(configuration.opt).to.equal('bar')); + it('should resolve "self" source', () => expect(configuration.self).to.equal('bar')); + it('should resolve "strToBool" source', () => expect(configuration.strToBool).to.equal(false)); +});