diff --git a/README.md b/README.md index e4b940e..2768570 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,20 @@ fastify if (err) console.error(err) console.log(fastify.config) // or fastify[options.confKey] + console.log(fastify.getEnvs()) // output: { PORT: 3000 } }) ``` +You can also use the function `getEnvs()` of the Request from within a handler function: +```js +fastify.get('/', (request, reply) => { + console.log(request.getEnvs()) + // output: { PORT: 3000 } +}) +``` +Note that the `getEnvs` decorators will not be added if they already exist. + This module is a wrapper around [env-schema](https://www.npmjs.com/package/env-schema). To read an `.env` file you must set `dotenv` in the options: @@ -53,7 +63,7 @@ const options = { dotenv: true // will read .env in root folder } -// or, pass config options avalible on dotenv module +// or, pass config options available on dotenv module const options = { dotenv: { path: `${__dirname}/.env`, @@ -81,18 +91,43 @@ await fastify **NB** Support for additional properties in the schema is disabled for this plugin, with the `additionalProperties` flag set to `false` internally. ### Typescript -In order to have typing for the fastify instance, you should follow the example below: +In order to have typing for the fastify instance, you should either: + +- use the `declaration merging` technique to enhance the `FastifyInstance` type with the property and its keys you have defined in the options: ```typescript declare module 'fastify' { interface FastifyInstance { config: { // this should be same as the confKey in options // specify your typing here + FOO: string }; } } + +const fastify = Fastify() +fastify.register(fastifyEnv) + +fastify.config.FOO // will be a string +fastify.config.BAR // error: Property BAR does not exist on type { FOO: string } ``` +- use the generic function `getEnvs()` to get the already typed object: + +```typescript +type Envs = { + FOO: string +} + +const fastify = Fastify() +await fastify.register(fastifyEnv) + +const envs = fastify.getEnvs() // envs will be of type Envs + +envs.FOO // will be a string +envs.BAR // error: Property BAR does not exist on type Envs +``` +If this is the case it is suggested to use [json-schema-to-ts ](https://github.com/ThomasAribart/json-schema-to-ts) to have the type always synchronized with the actual schema. ## Acknowledgements diff --git a/index.js b/index.js index b7f5bc5..95d3f5b 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,14 @@ function fastifyEnv (fastify, opts, done) { const config = envSchema(opts) const confKey = opts.confKey || 'config' fastify.decorate(confKey, config) + + if (!fastify.hasDecorator('getEnvs')) { + fastify.decorate('getEnvs', () => { return config }) + } + if (!fastify.hasRequestDecorator('getEnvs')) { + fastify.decorateRequest('getEnvs', () => { return config }) + } + done() } catch (err) { done(err) diff --git a/test/fastify-env.test.js b/test/fastify-env.test.js index 434a1bd..fe53e88 100644 --- a/test/fastify-env.test.js +++ b/test/fastify-env.test.js @@ -282,3 +282,66 @@ t.test('should use custom config key name', t => { t.strictSame(fastify.customConfigKeyName, { PORT: 6666 }) }) }) + +t.test('should use function `getEnvs` to retrieve the envs object', async t => { + t.plan(2) + + const schema = { + type: 'object', + properties: { + PORT: { type: 'integer', default: 6666 } + } + } + + const fastify = Fastify() + + let requestEnvs + fastify.get('/', (request) => { + requestEnvs = request.getEnvs() + return 'ok' + }) + + await fastify.register(fastifyEnv, { + schema + }) + + await fastify.inject({ + method: 'GET', + url: '/' + }) + + t.strictSame(requestEnvs, { PORT: 6666 }) + t.strictSame(fastify.getEnvs(), { PORT: 6666 }) +}) +t.test('should skip the getEnvs decorators if there is already one with the same name', async t => { + t.plan(2) + + const schema = { + type: 'object', + properties: { + PORT: { type: 'integer', default: 6666 } + } + } + + const fastify = Fastify() + fastify.decorate('getEnvs', () => { return 'another_value' }) + fastify.decorateRequest('getEnvs', () => { return 'another_value' }) + + let requestEnvs + fastify.get('/', (request) => { + requestEnvs = request.getEnvs() + return 'ok' + }) + + await fastify.register(fastifyEnv, { + schema + }) + + await fastify.inject({ + method: 'GET', + url: '/' + }) + + t.strictSame(requestEnvs, 'another_value') + t.strictSame(fastify.getEnvs(), 'another_value') +}) diff --git a/types/index.d.ts b/types/index.d.ts index 61614d4..7f29e8c 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,6 +1,18 @@ import { EnvSchemaOpt } from "env-schema" import { FastifyPluginCallback } from "fastify" +declare module 'fastify' { + export interface FastifyInstance { + // Returns the environment variables object. + getEnvs(): E, + } + + export interface FastifyRequest { + // Returns the environment variables object. + getEnvs(): E, + } +} + type FastifyEnv = FastifyPluginCallback declare namespace fastifyEnv { diff --git a/types/index.test-d.ts b/types/index.test-d.ts index 643f8a6..58486b6 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -1,4 +1,4 @@ -import Fastify from 'fastify' +import Fastify, {FastifyInstance, FastifyRequest} from 'fastify' import { expectDeprecated, expectType } from 'tsd' import fastifyEnv, { FastifyEnvOptions, fastifyEnvOpt } from '..' @@ -32,3 +32,11 @@ fastify.register(fastifyEnv, { expectDeprecated({} as fastifyEnvOpt) expectType({} as fastifyEnvOpt) + +type Envs = { + FOO: string +} +declare const instance: FastifyInstance +expectType(instance.getEnvs()) +declare const request: FastifyRequest +expectType(request.getEnvs())