1.2.8 • Published 1 year ago

@momsfriendlydevco/dotenv v1.2.8

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

@MomsFriendlyDevCo/DotEnv

DotEnv with schema, validation, expiring keys and multi-input support.

Features:

  • All standard DotEnv parser / reader
  • Mongo like Schema support
  • Entirely synchronous - config is available immediately, no waiting on promises or fixing up race conditions
  • Easy config key rewriting via .map(fn) / .camelCase() / .startCase() etc. to make config compatible with other systems
  • Support for destructing config - wipe values like passwords or API-keys after a set interval
import dotenv from '@momsfriendlydevco/dotenv';

let config = dotenv
    .parse(['.env.example', '.env']) // Import from one or more files in order of precidence
    .importEnv({prefix: 'MY_APP_'}) // Import from process.env
    .schema({ // Apply a schema
        port: Number, // Simple schemas (`required` is implied for these)
        host: {required: true, type: String}, // ...or be more explicit
        password: {
            type: 'string', // Custom support also for your own types
            cast: v => v.toLowerCase(), // Case incoming values
            destruct: '10s', // Variables not allowed to be read after this time from start (timestring)
        },
    })
    .value() //= {host: String, port: Number, password: String}

API

DotEnv (default export)

Returns an instance of the DotEnv class.

DotEnv.parse(source, options)

Read files from path (or relative to current directory) in presidence order. Source can be a path (string with no '='), paths (an array of strings) or raw blob data (string || buffer).

Later files with keys will overwrite earlier ones.

Options are:

OptionTypeDefaultDescription
fromString / BufferSource to parse instead of a file path
pathString / Array<String>Source file(s) to parse in order (later overrides former)
allowMissing=trueBooleantrueSkip over missing files, if falsy will throw instead

Returns the chainable DotEnv instance.

DotEnv.importEnv(options)

Import environment variables (from process.env by default).

Returns the chainable DotEnv instance.

Valid options are:

OptionTypeDefaultDescription
sourceObjectprocess.envSource object to import from
prefixString''Optional prefix to limit imports to
filterFunction(k, v)=> trueOptional function to filter by. Called as (key, val)
replaceFunction(k, v)=> vOptional function to rewrite the value. Called as (key, val) and expected to return the new value
trimBooleantrueTry to trum whitespace from variables, if any
trimPrefixBooleantrueIf using a prefix, remove this from the final keys to merge

DotEnv.schema(schema, options)

Apply a schema to the existing internal config state.

A schema is a object mapping each key to a FieldSchema.

Returns the chainable DotEnv instance.

FieldSchemas are made up of any of the following properties. If a simple string or built-in type is provided instead it is assumed as the type subkey.

OptionTypeDefaultDescription
requiredBooleantrueWhether the field is required
typeArray<*> / *Either a instance of class the object (lookup table via aliases) or the string representation of any key in types
default*Default value to use if none is specified. If a function it is run as (fieldSchema) and the result used.
defaultRaw*Default value to use without attempting evaluate functions or perform any casting if its a string. Set this as the default and don't ask any questions
validateFunction / StringFunction to validate an input, must return true. If a string is given the cast function is retrieved from the type instead. Called as (value, fieldSchema)
castFunction / StringOptional function to convert user input to a native type. If a string is given the validate is retrieved from that type instead. Called as (value, fieldSchema) and expected to either throw or return falsy - undefined is ignored
destructObject / String / DateOptional destruction config. See ConfigDestruct for details

Schema options can contain:

OptionTypeDefaultDescription
rejectBooleantrueReject unknown fields that arn't defined in a Schema

Required

The required boolean has the following logic: 1. If we have a value that isn't undefined or an empty string stop here 2. If any default / defaultRaw is specified - apply those (see next section) 3. If no value is still set - return undefined

Defaults

Defaults are applied with the following logic: 1. If we have a value that isn't undefined or an empty string stop here 2. If defaultRaw exists - use that 3. If default exists and is a function - evaluate it first, if not contiue with the default value 4. If the value from step 3 is NOT a string - assume the return value should be used as is, stop any further checks (e.g. casting, validation) 5. If the value from step 3 is a string - assume this is the same as what would be set in the .env file and continue on to cast + validate etc.

DotEnv.schemaGlob(glob, schema)

Apply a schema to all config keys matching a glob, array of globs or a RegExp.

DotEnv.export(options)

Export the current config to a string.

Options are:

OptionTypeDescription
headerRegExpHow to extract section headers as a RegExp with a capture group or null to disable
headerFormatFunctionFunction to format headers. Called as (headerTitle)
headerSpacingNumberHow many lines of spacing should be inserted before each (new) header
rewritePairFunctionFunction to rewrite a single key=val set

DotEnv.exportFile(path, options)

Utility function to call .export() and dump the contents into a file.

DotEnv.deep(value)

Indicates that key mutation functions (see below) should operate on nested objects. Set to any falsy value to revert to only applying mutations to top level keys only. Returns the DotEnv instance.

DotEnv.mutateKeys(alias, args)

Apply camelCase, startCase or envCase (with options) to all keys, returning the DotEnv instance.

DotEnv.camelCase() / DotEnv.startCase(spacing=false) / DotEnv.envCase()

Mutate the config keys by applying a common string mutator, returning the DotEnv instance.

DotEnv.replace(match, replacement)

Apply a replacement to all config keys, returning the DotEnv instance.

DotEnv.filter(match)

Remove all config keys that either dont have the string prefix or don't match a given RegEx, returning the DotEnv instance.

DotEnv.trim(match)

Apply a replacement to all config keys removing a given String prefix / RegExp match, returning the DotEnv instance.

DotEnv.filterAndTrim(match, replacement)

Apply both a filter + trim to a config keys - removing all config that doesnt match the string prefix (or RegEx) whilst also removing the given prefix (or RegExp). Returns the DotEnv instance.

DotEnv.template(context)

Applies a JavaScript string template (via @MomsFriendlyDevCo/Template) to all values with the given context. If no context is provided the current state is used. Returns the DotEnv instance.

DotEnv.map(func)

Run a function on all state config keys, potencially mutating the key / value. Returns the DotEnv instance afterwards.

  • If the function returns a tuple array its assumed to mutate the key+val of the input config key+val combo
  • If the function returns a object, that object return (all keys) replace the state for that config key
  • If the function returns boolean false the key is removed completely
  • If the funciton returns boolean true OR undefined, no action or mutation is taken

DotEnv.tap(fn)

Run an arbitrary function passing in this DotEnv instance as the first argument and context. Returns the chainable DotEnv instance.

new DotEnv()
    .parse(...)
    .tap(dotEnv => console.log('Raw config:', dotEnv.value())
    .toTree(/_/)
    .tap(dotEnv => console.log('Config as a tree:', dotEnv.value())
    .value()

Note that if you intend to copy the state inside tap() it is advisable to use .value({clone: true}) as functions such as .toTree() mutate sub-keys which can change state.

DotEnv.thru(fn)

Like DotEnv.tap(fn) only the return value is used as the new state. Returns the chainable DotEnv instance.

DotEnv.toTree(options)

Transform a flat key/val config item a hierarchical object-of-objects based on rules. Returns the chainable DotEnv instance.

let result = new DotEnv()
    .parse([
        'FOO_BAR_FOO=Foo!',
        'FOO_BAR_BAR=123',
        'FOO_BAR_BAZ=true',
        'BAR_BAR_FOO=Foo2!',
        'BAR_BAR_BAR=456',
        'BAR_BAR_BAZ=false',
    ].join('\n'))
    .toTree(/_/)
    .value()

/**
// Will return
{
    FOO: {
        BAR: {
            FOO: 'Foo!',
            BAR: '123',
            BAZ: 'true',
        },
    },
    BAR: {
        BAR: {
            FOO: 'Foo2!',
            BAR: '456',
            BAZ: 'false',
        },
    },
}

Options are:

OptionTypeDefaultDescription
branchesFunctionA RegExp where each capture group denotes a branch of a tree
splitterFunctionA RegExp to split keys by a given string
rewriteFunction / RegExpRun a given funciton (or replacement RegExp) over each extracted key segment
matchingString'remove'Operation to perform on matching keys. ENUM: 'keep', 'remove'
nonMatchingString'remove'Operation to perform on non-matching keys (branching method only). ENUM: 'keep', 'remove'
prefixString / Array<String>''Optional path segment prefix when setting keys
clearBooleanfalseStart with a blank tree, if falsey will instead muatete the existing state

DotEnv.value(options)

Return the final, computed config object.

Options are:

OptionTypeDefaultDescription
cloneBooleanfalseReturn a deep clone of the value - this prevents future mangling via toTree()

Built in types

The following is a list of built in types which provide a handy shorthand for various functionality.

TypeExampleNotesAdditional properties
anyKEY=somethingAny type is valid
arrayKEY=foo,Bar, BazCSV of string valuesmin / max for array length
booleanKEY=yes / KEY=trueParse common 'truthy' strings into a booleantrue=[...], false=[] (accepted strings to validate true / false
dateKEY=2022-12-06 / KEY=2022-12-06T13:20+10:00Parse Date-like or ISO dates into a Date object |min/max` for date period
durationKEY=2h37mParse a valid timestring duration into millisecondsunit=ms for the unit to parse to
emailKEY=a@b.com / KEY=Simon Jones <simon@thing.com>A single email in short or long formname=true to allow a long form address
emailsKEY=a@b.com, someone@somewhere.com, J Smith <j@smith.com>A CSV of email addresesname=true to allow a long form address
fileKEY=/some/path/file.txtA file on disk, read into the valuebuffer=true or string=true to describe how to read the file
floatKEY=3.1415Any floating valuemin / max for value
keyvalsKEY=key1=val1, key2 = val 2, key3=val3An object composed of key=valsmin / max for key count, noValue to specify the content if only the key portion of the spec is given but not a value (e.g. key4)
mongoUriKEY=mongodb+src://URL...A valid MongoDB URI
numberKEY=123A string parsed into a numberfloat to accept floating values, min / max for value
objectAlias for keyvals
percentKEY=10%, KEY=10A string parsed into a number (with suffix removed)float to accept floating values, min / max for value
regexpKEY=/^a(.)c$/iRegExp with surrounding slashessurrounds=true to accept raw strings without '/' surroundings, flags to set default flags (e.g. flags=i), allowPlain=true (with surrounds=true) to parse non-surround strings as plain-text, plainPrefix + plainSuffix to decorate the plain text RegExp
setKEY=foo, bar, bazCSV of values cast into a Setmin / max for value count
stringKEY=some long stringAny valid stringenum for an array of values, min / max for string length
styleKEY=bold red / KEY=bgwhite + yellowChalk compatible color styling
uriKEY=https://somewhere.comA valid URIparse=false to specify that the parsed URL object should be returned rather than the string
1.2.8

1 year ago

1.2.7

1 year ago

1.2.6

1 year ago

1.2.5

1 year ago

1.2.4

1 year ago

1.2.3

1 year ago

1.2.2

1 year ago

1.2.1

1 year ago

1.2.0

1 year ago

1.1.2

1 year ago

1.1.1

1 year ago

1.1.0

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago