Skip to content

Commit

Permalink
feat: add generic function to retrieve the already typed object (#183)
Browse files Browse the repository at this point in the history
* Added generic function getEnvs() to retrieve the already typed envs.

* Check if the decorator already exists

* Applied readme suggestions
  • Loading branch information
edocrippaofficial committed Jun 24, 2024
1 parent 040f3e9 commit 61367f4
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 3 deletions.
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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`,
Expand Down Expand Up @@ -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>() // 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

Expand Down
8 changes: 8 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
63 changes: 63 additions & 0 deletions test/fastify-env.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
12 changes: 12 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -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<const E>(): E,
}

export interface FastifyRequest {
// Returns the environment variables object.
getEnvs<const E>(): E,
}
}

type FastifyEnv = FastifyPluginCallback<fastifyEnv.FastifyEnvOptions>

declare namespace fastifyEnv {
Expand Down
10 changes: 9 additions & 1 deletion types/index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Fastify from 'fastify'
import Fastify, {FastifyInstance, FastifyRequest} from 'fastify'
import { expectDeprecated, expectType } from 'tsd'
import fastifyEnv, { FastifyEnvOptions, fastifyEnvOpt } from '..'

Expand Down Expand Up @@ -32,3 +32,11 @@ fastify.register(fastifyEnv, {

expectDeprecated({} as fastifyEnvOpt)
expectType<FastifyEnvOptions>({} as fastifyEnvOpt)

type Envs = {
FOO: string
}
declare const instance: FastifyInstance
expectType<Envs>(instance.getEnvs<Envs>())
declare const request: FastifyRequest
expectType<Envs>(request.getEnvs<Envs>())

0 comments on commit 61367f4

Please sign in to comment.