Giter Club home page Giter Club logo

env-schema's Introduction

CI Package Manager CI Web SIte js-standard-style CII Best Practices

NPM version NPM downloads Security Responsible Disclosure Discord Contribute with Gitpod Open Collective backers and sponsors


An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users. How can you efficiently handle the resources of your server, knowing that you are serving the highest number of requests as possible, without sacrificing security validations and handy development?

Enter Fastify. Fastify is a web framework highly focused on providing the best developer experience with the least overhead and a powerful plugin architecture. It is inspired by Hapi and Express and as far as we know, it is one of the fastest web frameworks in town.

The main branch refers to the Fastify v5 release, which is not released/LTS yet. Check out the 4.x branch for v4.

Table of Contents

Quick start

Create a folder and make it your current working directory:

mkdir my-app
cd my-app

Generate a fastify project with npm init:

npm init fastify

Install dependencies:

npm i

To start the app in dev mode:

npm run dev

For production mode:

npm start

Under the hood npm init downloads and runs Fastify Create, which in turn uses the generate functionality of Fastify CLI.

Install

To install Fastify in an existing project as a dependency:

Install with npm:

npm i fastify

Install with yarn:

yarn add fastify

Example

// Require the framework and instantiate it

// ESM
import Fastify from 'fastify'

const fastify = Fastify({
  logger: true
})
// CommonJs
const fastify = require('fastify')({
  logger: true
})

// Declare a route
fastify.get('/', (request, reply) => {
  reply.send({ hello: 'world' })
})

// Run the server!
fastify.listen({ port: 3000 }, (err, address) => {
  if (err) throw err
  // Server is now listening on ${address}
})

with async-await:

// ESM
import Fastify from 'fastify'

const fastify = Fastify({
  logger: true
})
// CommonJs
const fastify = require('fastify')({
  logger: true
})

fastify.get('/', async (request, reply) => {
  reply.type('application/json').code(200)
  return { hello: 'world' }
})

fastify.listen({ port: 3000 }, (err, address) => {
  if (err) throw err
  // Server is now listening on ${address}
})

Do you want to know more? Head to the Getting Started.

Note

.listen binds to the local host, localhost, interface by default (127.0.0.1 or ::1, depending on the operating system configuration). If you are running Fastify in a container (Docker, GCP, etc.), you may need to bind to 0.0.0.0. Be careful when deciding to listen on all interfaces; it comes with inherent security risks. See the documentation for more information.

Core features

  • Highly performant: as far as we know, Fastify is one of the fastest web frameworks in town, depending on the code complexity we can serve up to 76+ thousand requests per second.
  • Extensible: Fastify is fully extensible via its hooks, plugins and decorators.
  • Schema based: even if it is not mandatory we recommend to use JSON Schema to validate your routes and serialize your outputs, internally Fastify compiles the schema in a highly performant function.
  • Logging: logs are extremely important but are costly; we chose the best logger to almost remove this cost, Pino!
  • Developer friendly: the framework is built to be very expressive and help the developer in their daily use, without sacrificing performance and security.

Benchmarks

Machine: EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD.

Method:: autocannon -c 100 -d 40 -p 10 localhost:3000 * 2, taking the second average

Framework Version Router? Requests/sec
Express 4.17.3 14,200
hapi 20.2.1 42,284
Restify 8.6.1 50,363
Koa 2.13.0 54,272
Fastify 4.0.0 77,193
-
http.Server 16.14.2 74,513

Benchmarks taken using https://github.com/fastify/benchmarks. This is a synthetic, "hello world" benchmark that aims to evaluate the framework overhead. The overhead that each framework has on your application depends on your application, you should always benchmark if performance matters to you.

Documentation

中文文档地址

Ecosystem

  • Core - Core plugins maintained by the Fastify team.
  • Community - Community supported plugins.
  • Live Examples - Multirepo with a broad set of real working examples.
  • Discord - Join our discord server and chat with the maintainers.

Support

Please visit Fastify help to view prior support issues and to ask new support questions.

Contributing

Whether reporting bugs, discussing improvements and new ideas or writing code, we welcome contributions from anyone and everyone. Please read the CONTRIBUTING guidelines before submitting pull requests.

Team

Fastify is the result of the work of a great community. Team members are listed in alphabetical order.

Lead Maintainers:

Fastify Core team

Fastify Plugins team

Great Contributors

Great contributors on a specific area in the Fastify ecosystem will be invited to join this group by Lead Maintainers.

Past Collaborators

Hosted by

We are a At-Large Project in the OpenJS Foundation.

Sponsors

Support this project by becoming a SPONSOR! Fastify has an Open Collective page where we accept and manage financial contributions.

Acknowledgements

This project is kindly sponsored by:

Past Sponsors:

This list includes all companies that support one or more of the team members in the maintenance of this project.

License

Licensed under MIT.

For your convenience, here is a list of all the licenses of our production dependencies:

  • MIT
  • ISC
  • BSD-3-Clause
  • BSD-2-Clause

env-schema's People

Contributors

aderchox avatar adrianpacala avatar batovpasha avatar bwyx avatar climba03003 avatar delvedor avatar dependabot[bot] avatar eomm avatar fdawgs avatar fox1t avatar francisbrito avatar github-actions[bot] avatar greenkeeper[bot] avatar is2ei avatar jimmyhurrah avatar jsumners avatar klaseca avatar lirantal avatar marcolanaro avatar mcollina avatar mse99 avatar nigelhanlon avatar serdnam avatar sniperwolf avatar tommarien avatar uzlopak avatar zekth avatar zigastrgar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

env-schema's Issues

`customOptions` is not typed, so TypeScript is giving errors

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

N/A

Plugin version

"env-schema": "^3.5",

Node.js version

14

Operating system

Windows

Operating system version (i.e. 20.04, 11.3, 10)

N/A

Description

Following error when using customOptions:

TS2322: Type '{ customOptions(ajvInstance: any): any; }' is not assignable to type 'Ajv'.   Object literal may only specify known properties, and 'customOptions' does not exist in type 'Ajv'

Because it's not in the types.

Steps to Reproduce

Just use customOptions in a TS file

Expected Behavior

Typings know about this extra feature, so there are no TS errors

config.data in the README file has to be config.ALLOWED_HOSTS?

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

In the README file, below an example you have this comment:

// config.data => ['127.0.0.1', '0.0.0.0']

but it seems that it has to be this:

// config.ALLOWED_HOSTS => ['127.0.0.1', '0.0.0.0']

I tried on Runkit too, config.data logs undefined. Or I might be missing something...

Cast boolean from env variable

There is no type in env variable so for that how deal with casting boolean type ?

const envSchema = require('env-schema').default;

const schema = {
  type: 'object',
  properties: {
    BOOL_VAL: {
      type: 'boolean',
    },
  },
};

['0', 'f', 'F', 'false', 'FALSE', 'False'].forEach((v) => {
  const r = envSchema({
    schema,
    data: {
      BOOL_VAL: v,
    },
  });
  console.log(r.BOOL_VAL === false);
});

['1', 't', 'T', 'true', 'TRUE', 'True'].forEach((v) => {
  const r = envSchema({
    schema,
    data: {
      BOOL_VAL: v,
    },
  });
  console.log(r.BOOL_VAL === true);
});

/**
Error: should be boolean
    at loadAndValidateEnvironment (./node_modules/env-schema/index.js:97:19)
    at ./test.js:13:13
    at Array.forEach (<anonymous>)
    at Object.<anonymous> (./test.js:12:44)
    at Module._compile (node:internal/modules/cjs/loader:1109:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
    at Module.load (node:internal/modules/cjs/loader:989:32)
    at Function.Module._load (node:internal/modules/cjs/loader:829:14)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
    at node:internal/main/run_main_module:17:47 {
  errors: [
    {
      keyword: 'type',
      dataPath: '/BOOL_VAL',
      schemaPath: '#/properties/BOOL_VAL/type',
      params: { type: 'boolean' },
      message: 'should be boolean'
    }
  ]
}
 */

Sample golang source code:
https://golang.org/src/strconv/atob.go#L10

JSs Implementation:
https://github.com/validatorjs/validator.js/blob/master/src/lib/toBoolean.js

Type.RegExp fails at Ajv compilation

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.26.0

Plugin version

5.2.1

Node.js version

20.10.0

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

Sonoma 14.3

Description

Type.RegExp() throw an error no matter what pattern I use.

The error:

Error: schema is invalid: data/properties/JWT_MAX_AGE/type must be equal to one of the allowed values, data/properties/JWT_MAX_AGE/type must be array, data/properties/JWT_MAX_AGE/type must match a schema in anyOf
    at Ajv.validateSchema

I used Type.String({ pattern: '....'}) as a work around.

Steps to Reproduce

import { Static, Type } from '@sinclair/typebox';

import { envSchema } from 'env-schema';

const schema = Type.Object({
    JWT_SECRET: Type.String({ minLength: 1 }),
    JWT_MAX_AGE: Type.RegExp( '^[1-9]\\d*d$' ),
});

export type Env = Static<typeof schema>;

export const config = envSchema<Env>({ schema });

Expected Behavior

To be able to use Type.RegExp() instead of using Type.String({ pattern}) work around.

Add method for process env validation

I need to know is there any method for preprocess env variable such as.

export TRUSTED_IPS=192.168.1.10,192.168.1.10
nodejs app.js
const schema = {
  type: 'object',
  required: [ 'TRUSTED_IPS' ],
  properties: {
    TRUSTED_IPS: {
      type: 'array',
      items: {
          type: 'string',
          format: 'ipv4',      
      },
      process(var) {
        return var.split(',');
      },
      default: [],
    }
  }
}

console.log(process.env.TRUSTED_IPS); // [ '192.168.1.10' , '192.168.1.10' ]

process could be array or json object like:

export SAMPLE='{"foo": { "bar": "baz" }}';

In schema could be:

process: 'Array'
// or
process: 'JSON'
// or user define like above example

Typing `separator` with an array instead of just string

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.19.2

Plugin version

No response

Node.js version

20.x

Operating system

Linux

Operating system version (i.e. 20.04, 11.3, 10)

6.4.1

Description

Hello,

I would like to type ALLOWED_HOSTS as string[] instead of string.

interface ConfigEnv {
  ALLOWED_HOSTS: string
}

export function loadConfig(): ConfigEnv {
  return envSchema({
    schema: {
      type: 'object',
      required: [
        'ALLOWED_HOSTS',
      ],
      properties: {
        ALLOWED_HOSTS: {
          type: 'string',
          separator: ',',
        },
      },
    },
  })
}

Now the actual type of loadConfig().ALLOWED_HOSTS is an array, empty or not. Here the type is incorrect to be string and not string[]. But if I change it I get the error on the line of type: "string":

Type '"string"' is not assignable to type '"array"'.ts(2322)

How can I do? Thanks.

Steps to Reproduce

// a.js
import envSchema = require("env-schema")

interface ConfigEnv {
  ALLOWED_HOSTS: string[]
}

export function loadConfig(): ConfigEnv {
  return envSchema({
    schema: {
      type: 'object',
      required: [
        'ALLOWED_HOSTS',
      ],
      properties: {
        ALLOWED_HOSTS: {
          type: 'string',
          separator: ',',
        },
      },
    },
  })
}

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": [
      "es2020",
      "dom"
    ],
    "declaration": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": false,
    "inlineSourceMap": true,
    "inlineSources": true,
    "experimentalDecorators": true,
    "strictPropertyInitialization": false,
    "typeRoots": [
      "./node_modules/@types"
    ],
    "outDir": "dist",
    "resolveJsonModule": true
  },
  "exclude": [
    "node_modules",
    "cdk.out",
    "dist"
  ]
}

Run:

$ ts-node a.ts

Error:

TSError: ⨯ Unable to compile TypeScript:
a.ts(16,11): error TS2322: Type '"string"' is not assignable to type '"array"'.

Expected Behavior

Type ALLOWED_HOSTS as:

interface ConfigEnv {
  ALLOWED_HOSTS: string[]
}

Use Ajv.errorsText instead of errors.map, otherwise you loose context

🚀 Feature Proposal

Suggestion to use the errorsText instead of the current custom formatter

Motivation

Atm you loose context of which variable is wrong

Error: must be equal to one of the allowed values

Example

If we would change the code to

 if (!valid) {
    const error = new Error(ajv.errorsText(valid.errors, { dataVar: 'process.env'}))
    error.errors = ajv.errors
    throw error
  }

we would get following output

Error: process.env/LOG_LEVEL must be equal to one of the allowed values

I would not mind creating a pull request for it

Use with fluent-json-schema now requires to call valueOf in ObjectSchema when using Typescript

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the regression has not already been reported

Last working version

5.1.0

Stopped working in version

5.1.1

Node.js version

18.x

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

12.3

💥 Regression Report

Typings in Typescript now throw an error when using a fluent-json-schema generated schema as input for envSchema

Steps to Reproduce

In a Typescript file the next block of code reproduces the issue

import envSchema from 'env-schema'
import S from 'fluent-json-schema'

envSchema({
  schema: S.object()
})
Type 'ObjectSchema' is not assignable to type 'AnySchema | UncheckedJSONSchemaType<EnvSchemaData, false> | undefined'.
  Type 'ObjectSchema' is not assignable to type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; ... 7 more ...; maxProperties?: number | undefined; } & { ...; } & { ...; } & { ...; }'.
    Property 'type' is missing in type 'ObjectSchema' but required in type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; ... 7 more ...; maxProperties?: number | undefined; }'.ts(2322)

Nevertheless the following block of code does not throw an error

import envSchema from 'env-schema'
import S from 'fluent-json-schema'

envSchema({
  schema: S.object().valueOf
})

Expected Behavior

As ObjectSchema from fluent-json-schema was removed from typings in #137 it might be solved otherwise or maybe be documented to avoid future confusion

TS: Open up envSchemaData

🚀 Feature Proposal

Allow a type to be specified when using envSchema().

Motivation

This can be used to give a an interface or a typebox from json schema inferred interface

Example

// change in type
declare const loadAndValidateEnvironment: {
  <T = EnvSchemaData>(_opts?: EnvSchemaOpt): T;
  keywords: {
    separator: KeywordDefinition;
  }
}
const schema = Schema.object()
  .prop('PORT', Schema.string());

interface Env {
  PORT?: string;
  LOG_LEVEL?: string;
  MONGO_URI: string;
  NODE_ENV?: string;
}

const env = envSchema<Env>({
  dotenv: !process.env.TAP,
  schema,
});

feature: allow custom ajv instance

Instead of adding the support one by one. I suggest to allow user pass a custom ajv instance.

Originally posted by @climba03003 in #52 (comment)

Goal:

  1. allow pass in custom ajv instance through option
  2. expose the current keyword for the user to use
  3. optional: add the current keyword to the custom ajv instance

Expand environment variables

🚀 Feature Proposal

It would be great to add the ability to interpolate variables.

Motivation

Often boxes come with some env variables that you want to use to declare other environment variables.

Example

Given the machine comes with an env variable like the following:

K8S_NAMESPACE=my_k8s_namespace

When in .env file we define the following

SERVICE_URL=https://prefix.$K8S_NAMESPACE.my.domain.com

Then the variable should be valued like:

SERVICE_URL=https://prefix.my_k8s_namespace.my.domain.com

This could be done in the app code, but consider the scenario where for local development the service url needs to have the following value:

SERVICE_URL=https://some.staging.environment.my.domain.com

In this case the app code should check the type of environment and then declare different strategies. It would be useful to just declare composable variables in the .env file.

Help

I could open a PR if you agree with the implementation.
From my point of view env-schema should provide a boolean expand options defaulted to false. When expand=true, internally use dotenv-expand.

Delete stale Greenkeeper branches

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

Greenkeeper shutdown in 2020, so these can be removed.
Would make forking and working on this repo a bit quicker without the forks flooding the CLI when running git branch.

I've removed old Greenkeeper branches in repos where i have permissions, but do not have it for this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.