Giter Site home page Giter Site logo

fastify-env's Introduction

@fastify/env

CI NPM version js-standard-style

Fastify plugin to check environment variables

Install

npm i @fastify/env

Usage

const fastify = require('fastify')()
const fastifyEnv = require('@fastify/env')

const schema = {
  type: 'object',
  required: [ 'PORT' ],
  properties: {
    PORT: {
      type: 'string',
      default: 3000
    }
  }
}

const options = {
  confKey: 'config', // optional, default: 'config'
  schema: schema,
  data: data // optional, default: process.env
}

fastify
  .register(fastifyEnv, options)
  .ready((err) => {
    if (err) console.error(err)

    console.log(fastify.config) // or fastify[options.confKey]
    // output: { PORT: 3000 }
  })

This module is a wrapper around env-schema. To read an .env file you must set dotenv in the options:

const options = {
  dotenv: true // will read .env in root folder
}

// or, pass config options avalible on dotenv module
const options = {
  dotenv: {
    path: `${__dirname}/.env`,
    debug: true
  }
}

Using @fastify/env to configure other plugins

The @fastify/env plugin loads asynchronously. If you wish to use its values in a different plugin before the boot sequence, you need to make sure that:

  1. @fastify/env is registered first.
  2. Await the plugin registration or await after()
await fastify.register(fastifyEnv)
// fastify.config can be used in here

OR

fastify.register(fastifyEnv)
await fastify
// fastify.config can be used in here

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:

declare module 'fastify' {
  interface FastifyInstance {
    config: { // this should be same as the confKey in options
      // specify your typing here
    };
  }
}

Acknowledgements

Kindly sponsored by Mia Platform

fastify-env's People

Contributors

allevo avatar bbonamin avatar cemremengu avatar climba03003 avatar dependabot-preview[bot] avatar dependabot[bot] avatar eomm avatar fdawgs avatar frikille avatar github-actions[bot] avatar greenkeeper[bot] avatar gustawdaniel avatar jsumners avatar lavir avatar lependu avatar mandaputtra avatar mcollina avatar nmarus avatar salmanm avatar sinchang avatar uzlopak avatar voxpelli avatar zekth 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  avatar  avatar

fastify-env's Issues

Disable Fastify logger in production

Prerequisites

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

Issue

I want to disable Fastify logger in production mode using fastify-env, but I'm not able to collect NODE_ENV from process.env when using fastify-env.

import fastify from 'fastify';
import fastifyEnv from 'fastify-env';

declare module 'fastify' {
  interface FastifyInstance {
    config: {
      NODE_ENV: string;
    };
  }
}

const app = fastify({
  logger:
    process.env.NODE_ENV === 'development'
      ? {
          prettyPrint: {
            levelFirst: true,
            translateTime: 'HH:MM:ss Z',
            ignore: 'pid,hostname',
          },
        }
      : false,
});

const start = async () => {
  try {
    await app.register(fastifyEnv, {
      dotenv: true,
      confKey: 'config',
      schema: {
        type: 'object',
        properties: {
          NODE_ENV: {
            type: 'string',
            enum: ['development', 'production'],
          },
        },
        required: ['NODE_ENV'],
      },
    });

    await app.ready();
    await app.listen(3000);
  } catch (error) {
    app.log.error(error);
    process.exit(1);
  }
};
start();

ChainAlert: npm package release (2.2.0) has no matching tag in this repo

Dear fastify-env maintainers,
Thank you for your contribution to the open-source community.

This issue was automatically created to inform you a new version (2.2.0) of fastify-env was published without a matching tag in this repo.

As part of our efforts to fight software supply chain attacks, we would like to verify this release is known and intended, and not a result of an unauthorized activity.

If you find this behavior legitimate, kindly close and ignore this issue. Read more

badge

Your .dependabot/config.yml contained invalid details

Dependabot encountered the following error when parsing your .dependabot/config.yml:

The property '#/' did not contain a required property of 'update_configs'
The property '#/' contains additional properties ["update_conigs"] outside of the schema when none are allowed

Please update the config file to conform with Dependabot's specification using our docs and online validator.

sync loading

Is there any way I can make sure all the env are loaded?

when I register the plugin I can't call fastify.config and its say undefined, even fastify.config.PORT

so I make .ready to make sure it load first and then calling start() function which have fastify.config.PORT. this work for me, but when I tried to use it with another plugins like fastify-mongodb it makes error say root plugin has already booted

fastify.register(fastifyEnv, options).ready(err => { if (err) { console.log(err) } fastify.register(require('fastify-mongodb'), { forceClose: true, url: fastify.env.DB_URL }) start() })

I just want to find is there any way I can call this synchronously to make sure it load all my env variables.

  • node version: 12
  • fastify version: >=2.14.0
  • os: Windows

README instructions seem to be wrong for TS

Prerequisites

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

Fastify version

Latest

Plugin version

Latest

Node.js version

18

Operating system

Windows

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

11

Description

For TS, the docs say that we just have to augment the fastify interface but I had to do more to get the plugin working without TS errors:

import FastifyEnv from '@fastify/env'
import { JSONSchemaType } from 'env-schema'

<redacted>

type Env = {
  JWT_SECRET: string
}

const envSchema: JSONSchemaType<Env> = {
  type: 'object',
  properties: {
    JWT_SECRET: {
      type: 'string',
    },
  },
  required: ['JWT_SECRET'],
  additionalProperties: false,
}

const app: FastifyPluginAsync<AppOptions> = async (
  fastify,
  opts
): Promise<void> => {
  await fastify.register(FastifyEnv, {
    schema: envSchema,
    dotenv: {
      path: path.join(__dirname, isProduction ? '.env' : '.env.development'),
      debug: isProduction === false,
    },
  })
 
  <redacted>
}

Without all this, either the runtime was complaining about the schema passed to the options, or TS was complaining about the overload used.

Also, there was nothing in the docs about how to copy the .env file to dist/ - I know it's not directly your responsibility but would be nice to add.

Steps to Reproduce

  • Create project with fastify-cli --lang=ts --esm
  • Add code from TS instructions

Expected Behavior

No response

usability issue and major refactoring

I'm thinking the usage of this library is not providing the best user experience for Fastify users.

I've seen the following:
I think we should be recommending a synchronous approach.

const fp = require("fastify-plugin")
const fastifyEnv = require("fastify-env")

module.exports = fp(async (fastify, opts) => {
  fastify.register(fastifyEnv, {
    schema: {
      type: "object",
      required: ["PG_URL"],
      properties: {
        PG_URL: {
          type: "string",
          format: "uri"
        }
      }
    },
    confKey: "pgconfig",
    data: opts,
    dotenv: true
  })

  // this is extremely complicated to write and "guess"
  fastify.register(fp(async fastify => {
    fastify.register(require("fastify-postgres"), {
      connectionString: fastify.pgconfig.PG_URL
    })
  }))
})

I think we should aim for:

const fp = require("fastify-plugin")
const env = require("validate-env") // different module

module.exports = fp(async (fastify, opts) => {
  const config = env({
    schema: {
      type: "object",
      required: ["PG_URL"],
      properties: {
        PG_URL: {
          type: "string",
          format: "uri"
        }
      }
    },
   data: opts,
   dotenv: true
  })

    fastify.register(require("fastify-postgres"), {
      connectionString: config.PG_URL
    })
})

Then this module could use the new module to add a config property.

What do you think @allevo?

An in-range update of ajv is breaking the build 🚨

Version 5.4.0 of ajv was just published.

Branch Build failing 🚨
Dependency ajv
Current Version 5.3.0
Type dependency

This version is covered by your current version range and after updating it in your project the build failed.

ajv is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details

Release Notes v5.4.0

Option logger to disable logging or to specify a custom logger (#618, @meirotstein).

Commits

The new version differs by 20 commits.

  • f336cda 5.4.0
  • 00be319 Merge branch 'meirotstein-master'
  • 89a80ca check that console has log, warn and error methods as well
  • 5ba22a3 remove Logger class, resolve logger object on Ajv ctor instead
  • e0c7eac create logger instance per Ajv instance
  • 4cdfcaa Merge branch 'master' into master
  • 4fe1c21 update readme with logger option
  • ceb552a logger option tests
  • b0e28ee logger component tests
  • 91374ac add logger option
  • cdd93a6 Merge pull request #621 from stuartpb/patch-1
  • 0196611 Update draft-06 meta-schema
  • 0cafcf6 docs: version 6 beta
  • c73ff44 Merge pull request #616 from kpping/patch-1
  • bddda60 make available types more noticeable

There are 20 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

[Proposal] Environment-specific dotenv files

Prerequisites

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

🚀 Feature Proposal

First things first, thanks for this utility, it really helps to save time 😃

While working on one of the projects, I came across the need to use several .env files. For example:

  • .env file with common settings and expansions.
  • .env.local file with local overrides (ignored in VCS).

This can be achieved by using data property from fastify-env configuration. But it require additional code which will most likely use dotenv and dotenv-expand packages that are already used by fastify-env.

I think it would be nice to be able to use multiple dotenv files. A similar technique is described in Create-React-App documentation.

Configuration example:

const options = {
    expandEnv: ['path-to-dotenv-1', 'path-to-dotenv-2']
};

Example

Input:

# .env
DATABASE_CONNECTION_STRING = postgres://user:secret@host:5432/databasename
# .env.test
DATABASE_CONNECTION_STRING = postgres://test-user:test-secret@test-host:5432/test-databasename
# .env.test.local
DEBUG = true

Configuration:

const options = {
    dotenv: true,
    expandEnv: [
        `${__dirname}/.env.test`,
        `${__dirname}/.env.test.local`
    ]
};

Result:

console.log(fastify.config);
/* ** Output:
    {
        DATABASE_CONNECTION_STRING: 'postgres://test-user:test-secret@test-host:5432/test-databasename',
        DEBUG: true
    }
*/

An in-range update of env-schema is breaking the build 🚨

The dependency env-schema was updated from 1.0.0 to 1.1.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

env-schema is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Commits

The new version differs by 6 commits.

  • 6c2f7a9 Bumped v1.1.0
  • 41c68be Add support for parsing delimiter-separeted-strings (#10)
  • 5faf902 chore(package): update standard to version 14.0.2 (#9)
  • 21a754e Update standard to the latest version 🚀 (#7)
  • a22c4ca Fix standard
  • dd24f16 chore(package): update standard to version 13.0.1

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

[Regression] AJV validation error does not render the responsible field name anymore

🐛 Bug Report

When AJV validation fail, you see an error like that: "Error: should be number".
In that case for instance the field is configured as a number.

In previous versions (don't know when it stopped working, didn't search), you would have a normal message that mention the field name responsible.

To Reproduce

server.register(require('fastify-env') as any, { schema });

with schema being whatever ajv schema is valid.

Expected behavior

I would like to know which field is in error. By default the field name should be used.

Your Environment

  • node version: 12.18.3
  • fastify version: 3.5.1
  • fastify env version: 2.0.1
  • os: Mac

snyc loading of env

Prerequisites

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

Fastify version

3.17.0

Plugin version

2.1.1

Node.js version

16.3.0

Operating system

macOS

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

11.3

Description

The problem is when i try to pass env (config) to fastify logger, is allways undefind.

I think the problem is with async loading of plugins and i cant pass env information to another plugin or constructor or fastify?

How can first load env variable then the rest of the app?

const fastify = require('fastify')({
  logger: {
    level: fastify.config.LEVEL,
    prettyPrint: true,
    serializers: {
      req: (req) => {
        return {
          method: req.method,
          url: req.url,
          path: req.path,
          parameters: req.parameters,
          hostname: req.hostname
        }
      }
    }
  }
})

const redis = require('redis').createClient({ host: fastify.config.REDIS_HOST, port: 6379, password: 'xxxx' })

Steps to Reproduce

const fastify = require('fastify')({
  logger: {
    level: fastify.config.LEVEL,
    prettyPrint: true,
    serializers: {
      req: (req) => {
        return {
          method: req.method,
          url: req.url,
          path: req.path,
          parameters: req.parameters,
          hostname: req.hostname
        }
      }
    }
  }
})

const fastifyEnv = require('fastify-env')

const schema = {
  type: 'object',
  required: ['PORT'],
  properties: {
    LEVEL: {
      type: 'string',
      default: 'info'
    },
    PORT: {
      type: 'string',
      default: 3000
    },
    REDIS_HOST: {
      type: 'string',
      default: "xxxx"
    },
    REDIS_PORT: {
      type: 'string',
      default: 3000
    },
    REDIS_PASSWORD: {
      type: 'string',
      default: 3000
    }
  }
}

const redis = require('redis').createClient({ host: fastify.config.REDIS_HOST, port: 6379, password: 'xxxx' })

fastify.register(require('fastify-redis'), {
  client: redis,
  closeClient: true
})

const options = {
  schema: schema
}

fastify.register(fastifyEnv, options).ready((err) => {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
  fastify.log.debug(fastify.config.PORT)
})

Expected Behavior

No response

An in-range update of ajv is breaking the build 🚨

The dependency ajv was updated from 6.5.3 to 6.5.4.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

ajv is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Commits

The new version differs by 8 commits.

  • 8578816 6.5.4
  • 5c41a84 Merge pull request #863 from epoberezkin/fix-861-property-names
  • c1f929b fix: propertyNames with empty schema, closes #861
  • 70362b9 test: failing test for #861
  • 12e1655 Merge pull request #862 from billytrend/patch-2
  • f01e92a Fixes grammar
  • 851b73c Merge pull request #858 from epoberezkin/greenkeeper/bluebird-pin-3.5.1
  • 9aa65f7 fix: pin bluebird to 3.5.1

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Exporting 'env-schema' dependency needed

Prerequisites

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

🚀 Feature Proposal

Using the fastify-env plugin in our fastify project I came on a scenario when I should load the env variables before I boot the application and register the plugin to the fastify instance (currently on the database migration part, on which I should access the env variables). I can use env-schema with the existing options that I have build for the plugin but it would be adding an extra dependency, keeping in mind that plugin is already using it. Being able to get the env-schema from the plugin library would help me to solve the issue.

Motivation

No response

Example

No response

Default option in schema not populated to property.

Using the example on the README.md

const fastify = require('fastify')()
const fastifyEnv = require('fastify-env')

const schema = {
  type: 'object',
  required: [ 'PORT' ],
  properties: {
    PORT: {
      type: 'string',
      default: 3000
    }
  }
}

const options = {
  confKey: 'config', // optional
  schema: schema,
}
fastify.register(fastifyEnv, options, function (err) {
   // or fastify[options.confKey]
  console.log(fastify.config)
  // output: { PORT: 3000 }
})

Nothing is logged to console and it seems that the default key of the schema properties is not getting applied to the resulting object.

fastify-env does not support Fastify version 4.0

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.0.1

Plugin version

2.2.0

Node.js version

16.13.2

Operating system

Linux

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

Ubuntu 20.04

Description

"FastifyError","code":"FST_ERR_PLUGIN_VERSION_MISMATCH","statusCode":500},"msg":"fastify-plugin: fastify-env - expected '3.x' fastify version, '4.0.1' is installed"}

Steps to Reproduce

  1. Install fastify 4.0.1
  2. Install fastify-env
  3. Start your server
  4. Server won't start

Expected Behavior

No response

Different way to expand the FastifyInstance which works better for me.

Prerequisites

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

Issue

You can see that in my solution you do can add the config attribute and expand the FastifyInstance interface much easier. Here is my implementation: https://github.com/kasir-barati/fastify-worktime/blob/main/src/types/fastify-config.type.d.ts

Suggestion

Change the doc to advocate this solution since it is easier and better IMO

Typescript Typings

🚀 Feature Proposal

Add the missing typescript typing.

Motivation

Better integration with typescript.

Example

No additional file like fastify-env.d.ts is needed for typescript project.

Property 'config' does not exist on type 'FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>'.

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.24.2"

Plugin version

^4.2.0

Node.js version

v18.12.0

Operating system

macOS

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

14.0 (23A344)

Description

The code structure is created with fastify-cli using typescript template.

// file: authorization.ts
import { FastifyInstance } from "fastify"

const authorization = async (fastify:FastifyInstance, opts) => {
	const { httpErrors, config } = fastify // got error: Property 'config' does not exist on type 'FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>'.
}

Steps to Reproduce

The code structure is created with fastify-cli using typescript template.
maybe the error is cause by @fastify/env not extending the fastify instance object like this

declare module 'fastify' {
  export interface FastifyInstance {
    someSupport(): string;
  }
}

My code

// file: authorization.ts
import { FastifyInstance } from "fastify"

const authorization = async (fastify:FastifyInstance, opts) => {
	const { httpErrors, config } = fastify // got error: Property 'config' does not exist on type 'FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>'.
}

I already registerred the "@fastify/env"

// file: app.ts
import Env from "@fastify/env"
const app: FastifyPluginAsync<AppOptions> = async (
	fastify,
	opts
): Promise<void> => {
	// Place here your custom code!
	// env
	void fastify.register(Env, {
		schema: S.object()
			.prop("NODE_ENV", S.string().default("development"))
			.valueOf(),
	})

is it bec

Expected Behavior

No response

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! 🎊

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml

If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didn’t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖


FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Cannot use env before fastify has started

Prerequisites

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

Fastify version

3.18.1

Plugin version

2.1.1

Node.js version

15.12

Operating system

macOS

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

11.5

Description

As described in the documentation, we have to wait for environment variables to be read:

fastify
  .register(fastifyEnv, options)
  .ready((err) => {
    if (err) console.error(err)
    // fastify.config is available!
    console.log(fastify.config) // or fastify[options.confKey]
  })

However a typical usage of environment reading is to parameterize other plugins, and no more plugins can be registered after ready(), which states that the fastify server has been started.

Steps to Reproduce

Try to register another plugin in ready callback:

const server = fastify.register(fastifyEnv, options) 
server.ready((err) => {
    if (err) console.error(err)
    // fastify.config is available!
    server.register(otherPlugin, {param: fastify.config.someParam}) // ERROR: root plugin has already booted
  })

Expected Behavior

Resolved env should be available to other plugins, before server listening.

Custom data with env

I like this utility!
I think could be nice to have process.env and some optional data together instead of data or process.env.

const data = Object.assign(opts.data || {}, process.env)

In this way you can share some custom config and process.env at the same time in the same place :)
What do you think?

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.