Skip to content

Commit

Permalink
Merge 04c92c3 into bd33a51
Browse files Browse the repository at this point in the history
  • Loading branch information
giuliowaitforitdavide committed Jan 26, 2023
2 parents bd33a51 + 04c92c3 commit 164e4c7
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 48 deletions.
36 changes: 12 additions & 24 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const addPostDecorator = require('./lib/postDecorator')
const ajvSetup = require('./lib/ajvSetup')
const HttpClient = require('./lib/httpClient')
const { extraHeadersKeys } = require('./lib/util')
const { mergeDeepWithKey, concat } = require('ramda')

const USERID_HEADER_KEY = 'USERID_HEADER_KEY'
const USER_PROPERTIES_HEADER_KEY = 'USER_PROPERTIES_HEADER_KEY'
Expand Down Expand Up @@ -95,29 +96,15 @@ const baseSchema = {
}

function mergeJsonSchemas(schema, otherSchema) {
const { properties: schemaProperties, required: requiredSchema = [], ...schemaRemainingProperties } = schema
const {
properties: otherSchemaProperties,
required: requiredOtherSchema = [],
...otherSchemaRemainingProperties
} = otherSchema
const mergedSchema = {
type: 'object',
properties: {
...schemaProperties,
...otherSchemaProperties,
},
required: [...requiredSchema, ...requiredOtherSchema],
allOf: [
schemaRemainingProperties,
otherSchemaRemainingProperties,
],
additionalProperties: false,
}
return mergedSchema
return mergeDeepWithKey(
(_, left, right) => (typeof left === 'object' && typeof right === 'object' ? concat(left, right) : right),
schema,
otherSchema
)
}

function getOverlappingKeys(properties, otherProperties) {
if (!otherProperties) { return [] }
const propertiesNames = Object.keys(properties)
const otherPropertiesNames = Object.keys(otherProperties)
const overlappingProperties = propertiesNames.filter(propertyName =>
Expand Down Expand Up @@ -315,16 +302,17 @@ async function decorateRequestAndFastifyInstance(fastify, { asyncInitFunction, s
})
}

const defaultSchema = { type: 'object', required: [], properties: {} }

function initCustomServiceEnvironment(envSchema = defaultSchema) {
function initCustomServiceEnvironment(envSchema) {
return function customService(asyncInitFunction, serviceOptions) {
async function index(fastify, opts) {
const overlappingPropertiesNames = getOverlappingKeys(baseSchema.properties, envSchema.properties)
const overlappingPropertiesNames = getOverlappingKeys(baseSchema.properties, envSchema?.properties)
if (overlappingPropertiesNames.length > 0) {
throw new Error(`The provided Environment JSON Schema includes properties declared in the Base JSON Schema of the custom-plugin-lib, please remove them from your schema. The properties to remove are: ${overlappingPropertiesNames.join(', ')}`)
}
fastify.register(fastifyEnv, { schema: mergeJsonSchemas(baseSchema, envSchema), data: opts })

const schema = envSchema ? mergeJsonSchemas(baseSchema, envSchema) : baseSchema
fastify.register(fastifyEnv, { schema, data: opts })
fastify.register(fastifyFormbody)
fastify.register(fp(decorateRequestAndFastifyInstance), { asyncInitFunction, serviceOptions })
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"nock": "^13.2.4",
"pre-commit": "^1.2.2",
"proxy": "^1.0.2",
"ramda": "^0.28.0",
"split2": "^4.1.0",
"swagger-parser": "^10.0.3",
"tap": "^16.1.0",
Expand Down
72 changes: 72 additions & 0 deletions test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"type": "object",
"required": [
"USERID_HEADER_KEY",
"GROUPS_HEADER_KEY",
"CLIENTTYPE_HEADER_KEY",
"BACKOFFICE_HEADER_KEY",
"MICROSERVICE_GATEWAY_SERVICE_NAME",
"MY_AWESOME_ENV",
"MY_REQUIRED_ENV_VAR"
],
"properties": {
"USERID_HEADER_KEY": {
"type": "string",
"description": "the header key to get the user id",
"minLength": 1
},
"USER_PROPERTIES_HEADER_KEY": {
"type": "string",
"description": "the header key to get the user permissions",
"minLength": 1,
"default": "miauserproperties"
},
"GROUPS_HEADER_KEY": {
"type": "string",
"description": "the header key to get the groups comma separated list",
"minLength": 1
},
"CLIENTTYPE_HEADER_KEY": {
"type": "string",
"description": "the header key to get the client type",
"minLength": 1
},
"BACKOFFICE_HEADER_KEY": {
"type": "string",
"description": "the header key to get if the request is from backoffice (any truly string is true!!!)",
"minLength": 1
},
"MICROSERVICE_GATEWAY_SERVICE_NAME": {
"type": "string",
"description": "the service name of the microservice gateway",
"pattern": "^(?=.{1,253}.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*.?$"
},
"ADDITIONAL_HEADERS_TO_PROXY": {
"type": "string",
"default": "",
"description": "comma separated list of additional headers to proxy"
},
"ENABLE_HTTP_CLIENT_METRICS": {
"type": "boolean",
"default": false,
"description": "flag to enable the httpClient metrics"
},
"MY_AWESOME_ENV": {
"type": "string",
"default": "the default value"
},
"MY_REQUIRED_ENV_VAR": {
"type": "string"
}
},
"additionalProperties": true,
"patternProperties": {
"^S_": {
"type": "string"
},
"^I_": {
"type": "number"
}
},
"minProperties": 1
}
22 changes: 22 additions & 0 deletions tests/environment.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,5 +230,27 @@ tap.test('Test Environment variables', test => {
}
})

test.test('Should pass since all of the required fields are present', async assert => {
const env = {
...baseEnv,
MY_REQUIRED_ENV_VAR: 'value',
}

await assert.resolves(async() => {
await setupFastify('./tests/services/advanced-first-level-properties-service.js', env)
})
})

test.test('Should fail since one of the required fields is not present', async assert => {
// NOTE: use try catch instead of assert.reject to customize error message assertion
assert.plan(1)
try {
await setupFastify('./tests/services/advanced-first-level-properties-service.js', baseEnv)
} catch (error) {
const errorMessage = 'env must have required property \'MY_REQUIRED_ENV_VAR\''
assert.strictSame(error.message, errorMessage)
}
})

test.end()
})
34 changes: 18 additions & 16 deletions tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const GROUPS_HEADER_KEY = 'groups-header-key'
const CLIENTTYPE_HEADER_KEY = 'clienttype-header-key'
const BACKOFFICE_HEADER_KEY = 'backoffice-header-key'
const MICROSERVICE_GATEWAY_SERVICE_NAME = 'microservice-gateway'
const MY_REQUIRED_ENV_VAR = 'value'

const baseEnv = {
USERID_HEADER_KEY,
Expand All @@ -48,7 +49,7 @@ tap.test('Plain Custom Service', test => {
}

test.test('Hello World', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })

const response = await fastify.inject({
method: 'GET',
Expand All @@ -62,7 +63,7 @@ tap.test('Plain Custom Service', test => {
})

test.test('Access platform values', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'GET',
url: '/platform-values',
Expand Down Expand Up @@ -90,6 +91,7 @@ tap.test('Plain Custom Service', test => {
test.test('Access platform "miauserproperties" - when USER_PROPERTIES_HEADER_KEY NOT defined - uses default header key', async assert => {
const envarWithoutUserProperties = {
...baseEnv,
MY_REQUIRED_ENV_VAR,
}
delete envarWithoutUserProperties.USER_PROPERTIES_HEADER_KEY

Expand Down Expand Up @@ -117,7 +119,7 @@ tap.test('Plain Custom Service', test => {
})

test.test('Access platform values when not declared', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'GET',
url: '/platform-values',
Expand All @@ -138,7 +140,7 @@ tap.test('Plain Custom Service', test => {
})

test.test('Send form encoded data', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })

const response = await fastify.inject({
method: 'POST',
Expand All @@ -162,7 +164,7 @@ tap.test('Plain Custom Service', test => {
test.test('Can return a stream', async assert => {
const filename = './tests/services/plain-custom-service.js'
const readFile = promisify(fs.readFile)
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'GET',
url: '/stream',
Expand All @@ -177,7 +179,7 @@ tap.test('Plain Custom Service', test => {

test.test('Send some json, with validation', async assert => {
const payload = { some: 'stuff' }
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'POST',
url: '/validation',
Expand Down Expand Up @@ -254,7 +256,7 @@ tap.test('Plain Custom Service', test => {
test.test('custom body parsing', async assert => {
const customType = 'application/custom-type'
const payload = { hello: 'world' }
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'POST',
url: '/',
Expand All @@ -269,7 +271,7 @@ tap.test('Plain Custom Service', test => {
})

test.test('Healtiness handler can see decoration', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'GET',
url: '/-/healthz',
Expand All @@ -279,7 +281,7 @@ tap.test('Plain Custom Service', test => {
})

test.test('returns mia headers - empty', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })

const response = await fastify.inject({
method: 'GET',
Expand All @@ -291,7 +293,7 @@ tap.test('Plain Custom Service', test => {
})

test.test('returns mia headers - filled', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })

const response = await fastify.inject({
method: 'GET',
Expand Down Expand Up @@ -329,7 +331,7 @@ tap.test('Advanced Custom Service', test => {

test.test('Require some environment variables', async assert => {
const MY_AWESOME_ENV = 'foobar'
const fastify = await setupFastify({ ...baseEnv, MY_AWESOME_ENV })
const fastify = await setupFastify({ ...baseEnv, MY_AWESOME_ENV, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'GET',
url: '/env',
Expand All @@ -344,7 +346,7 @@ tap.test('Advanced Custom Service', test => {
test.test('Decorate fastify with custom functionalities', async assert => {
const MY_AWESOME_ENV = 'foobar'
const payload = { hello: 'world' }
const fastify = await setupFastify({ ...baseEnv, MY_AWESOME_ENV })
const fastify = await setupFastify({ ...baseEnv, MY_AWESOME_ENV, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'POST',
url: '/custom',
Expand All @@ -359,7 +361,7 @@ tap.test('Advanced Custom Service', test => {
})

test.test('default env var', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })
const response = await fastify.inject({
method: 'GET',
url: '/env',
Expand All @@ -383,7 +385,7 @@ tap.test('Advanced config', test => {
}

test.test('it accepts advanced config', async assert => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })

const response = await fastify.inject({
method: 'POST',
Expand Down Expand Up @@ -431,7 +433,7 @@ tap.test('Service with API formats', t => {
}

t.test('it validates date-time', async t => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })
const someDate = '2021-10-12T15:46:39.081Z'

const response = await fastify.inject({
Expand All @@ -454,7 +456,7 @@ tap.test('Service with API formats', t => {
})

t.test('fails for invalid date', async t => {
const fastify = await setupFastify(baseEnv)
const fastify = await setupFastify({ ...baseEnv, MY_REQUIRED_ENV_VAR })

const response = await fastify.inject({
method: 'POST',
Expand Down
Loading

0 comments on commit 164e4c7

Please sign in to comment.