๐Ÿ›  Nodejs configuration the easy way.

Overview

@elite-libs/auto-config

CI Status NPM version GitHub stars

Intro

A Unified Config & Arguments Library for Node.js!

Featuring support for environment variables, command line arguments, and (soon) JSON/YAML/INI files!

Why

There are so many config libraries, do we really need another??? Well, possibly!

No existing library I tried met my requirements.

My goals & requirements include:

  • Enable dynamic app config. See '12 Factor App' on Config
  • TypeScript support.
  • Portable pattern (not filesystem-locked, browser support.)
  • Simple, memorable & terse config format.

Table of Contents

Install

npm install @elite-libs/auto-config

yarn add @elite-libs/auto-config

Example

// `./src/config.ts`
import { autoConfig } from '@elite-libs/auto-config';

export default autoConfig({
  databaseUrl: {
    help: 'The Postgres connection string.',
    args: ['--databaseUrl', '--db', 'DATABASE_URL'],
    required: true,
  },
  port: {
    help: 'The port to start server on.',
    args: ['--port', '-p', 'PORT'],
    type: 'number',
    required: true,
  },
  debugMode: {
    help: 'Debug mode.',
    args: ['--debug', '-D'],
    type: 'boolean',
    default: false,
  },
});
// `./src/app.js`
import config from './config';
console.log(config);

Configuring your App Dynamically

Command line arguments

node ./src/app.js \
  --port 8080 \
  --databaseUrl 'postgres://localhost/postgres' \
  --debug
# { port: 8080, databaseUrl: 'postgres://localhost/postgres', debug: true }

Mix of environment and command arguments

DATABASE_URL=postgres://localhost/postgres \
  node ./src/app.js \
    --port 8080 \
    --debug
# { port: 8080, databaseUrl: 'postgres://localhost/postgres', debug: true }

Single-letter flag arguments

node ./src/app.js \
  -D \
  --port 8080 \
  --databaseUrl 'postgres://localhost/postgres'
# { port: 8080, databaseUrl: 'postgres://localhost/postgres', debug: true }

Error on required fields

node ./src/app.js \
  --port 8080
# Error: databaseUrl is required.

CLI Help Output

node ./src/app.js --help
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚                           โ”‚                                            โ”‚                                                          โ”‚
โ”‚  Name                     โ”‚  Help                                      โ”‚  CLI Args, Env Name(s)                                   โ”‚
โ”‚                           โ”‚                                            โ”‚                                                          โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚databaseUrl*               โ”‚The Postgres connection string.             โ”‚--databaseUrl, DATABASE_URI, DATABASE_URL                 โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚port*                      โ”‚The port to serve content from.             โ”‚-p, --port                                                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚[debugMode] = false        โ”‚Debug mode.                                 โ”‚-D, --debug                                               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚help                       โ”‚Show this help.                             โ”‚--help                                                    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚version                    โ”‚Show the current version.                   โ”‚--version                                                 โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

TODO

  • Enum support.
  • Inverting boolean flags with --no-debug versus --debug.
  • Plugin modules with minimal overhead. (e.g. 3rd party loaders: AWS SSM, AppConfig, Firebase Config, etc.)
    • Example args: {ssm:/app/flags/path/admin_dashboard}
      • ['{ssm:/app/flags/path/admin_dashboard}', 'FLAG_ADMIN_DASHBOARD_ENABLED', '--flagAdminDashboard', '--flag-admin-dashboard']
  • Support for loading files, and structured data with dotted key paths.
    • Example args: {config.flags.admin_dashboard}
      • ['{config.flags.admin_dashboard}', 'FLAG_ADMIN_DASHBOARD_ENABLED', '--flagAdminDashboard', '--flag-admin-dashboard']
  • Auto --help output.
  • --version output.
  • default values.
  • required values.
  • Zod validators for optional, min, max, gt, gte, lt, lte.

Credit and References

Projects researched, with any notes on why it wasn't a good fit.

  • yargs - like the fluent API, and command syntax. Could use as base library. Env vars could be handled via default helper function to check for env keys. Or we could transform yargs config into overlapping format.
  • commander - like the many ways to configure arguments. Could probably be used as underlying library, however initial attempt was slower than starting from scratch.
  • cosmiconfig - focused too much on disk-backed config.
  • rc - focused on 'magically' locating disk-backed config.
  • node-convict - great pattern, but limited TypeScript support.
  • nconf - setter & getter, plus the hierarchy adds extra layers.
  • conf - too opinionated (writing to disk.) Interesting use of JSON Schemas, Versioning, and Migrations.
  • gluegun - great design, focused on opinionated design of CLI apps though.
  • configstore - replaced by conf.
Comments
  • (chore) Upgrade Bundler to TSUP

    (chore) Upgrade Bundler to TSUP

    AC

    • [x] Migrate from parcel to tsup for easier x-compiling for many targets.
    • [x] Ensure bundle sizes do not regress.
    • [x] Add tests for ESM & CJS usage (in browser <script> tags too.)
    opened by justsml 0
  • (feat) easyConfig [a.k.a. shorthand config]

    (feat) easyConfig [a.k.a. shorthand config]

    Add support for simplified configuration:

    export const config = easyConfig({
      "url": ['--url', '-u', 'APP_URL'],
      "port": ['--port', '-p', 'PORT'],
      "debug": ['--debug', '-D'],
    });
    

    Type coercions can be provided by a convert function in the args array.

    import { easyConfig } from '@elite-libs/auto-config';
    
    // Example Validators
    const parsePort = port => (port = parseInt(port ?? 1234, 10), port > 1000 && port < 60000 ? port : null);
    const parseAcctId = input => zod.any(input).refine(Number).safeParse(input)?.data;
    
    export const config = easyConfig({
      "siteUrl": ['--site-url', 'SITE_URL'],
      "port": ['--port', 'PORT', parsePort],
      "accountId": ['--accountId', '-a', parseAcctId],
    });
    
    

    Post-MVP Stretch / Future Goal

    Options

    • Support type annotations and constraint tokens (starting with !, @, or #)
      • ['!required', '!string', '--url', 'URL']
      • { "string": ["URL", "--url"] }
    export const config = denseConfig({
      "url": ['!required', '!string', '--url', '-u', 'APP_URL'],
      "port": ['--port', '-p', 'PORT'],
      "debug": ['--debug', '-D'],
    });
    
    enhancement 
    opened by justsml 0
  • Add enum option support

    Add enum option support

    export const featureFlags = autoConfig({
      dashboard: {
        args: ['FEATURE_FLAG_DASHBOARD'],
        type: 'enum',
        enum: ['off', 'variant1'],
        default: 'off',
      },
      checkout: {
        args: ['FEATURE_FLAG_CHECKOUT'],
        type: 'enum',
        enum: ['off', 'variant1', 'variant2'],
        default: 'off',
      },
      signup: {
        args: ['FEATURE_FLAG_SIGNUP'],
        type: 'enum',
        enum: ['off', 'variant1', 'variant2', 'variant3', 'variant4'],
        default: 'off',
      },
    });
    
    opened by justsml 0
  • Nullable<string> on required:true

    Nullable on required:true

    KEY: {
        required: true
    }
    
    • Typescript is complaining that the type is still Nullable<string> instead of string
    • It appears that autoConfig is trying to figure out what the type is based upon default, but if there is no default then it presumes it can be Nullable even thought required is set to `true.

    When running tests, at runtime we receive the following error as well:

    ERROR: Found 1 Config Problem(s)!
    
        Fix the following 1 issue(s). (tip: try '--help' output for more details.)
    
          - Required: KEY invalid_type
    

    This error is resolved by adding default: '' to the config

    opened by dara-rockwell 0
  • Feature Request: Switchable Defaults

    Feature Request: Switchable Defaults

    Could be nice to have multiple defaults based upon a switch:

    const environment = process.env.NODE_ENV || 'development';
    
    export default autoConfig({
      host: {
        help: 'Host',
        args: ['--host', '-h', 'HOST'],
        default: {
            development: 'http://localhost:3001',
            production: 'http://api.production.com'
        },
        required: true
      }
    }, {
      default: environment
    } );
    
    opened by dara-rockwell 0
  • Extend `easyConfig` API

    Extend `easyConfig` API

    Extend easyConfig API

    • [ ] Add many examples, using easyConfig & autoConfig.
    • [ ] Consider renaming this repo generically to @elite-libs/config, and seamlessly combine the 2 use case/interfaces.
      • [ ] Look into combining the usage patterns of easyConfig & autoConfig (where each option is either defined using an object, or Array<string | Function> w/ optional last-position validation function.)
    • Alternatively, maintain 2 awkwardly differing modules for a bit longer - closer to v2.
      • [ ] autoConfig rename to cliConfig, configMap, appConfig, (should this be default export anyway?)
      • [ ] easyConfig, keep name? Might change to: appConfig?
    • [ ] Make sure the JSDoc content shows up where it's needed. (Not primarily on types, internals.)
    • [ ] Current easyConfig doesn't support the optional formatter function in tail position.

    Current EasyConfig

    • [x] Minimalist way to centralize your app configuration, handling both Argument & Environment key-value mapping.

    Limits: Everything is a string. No built-in Zod validation like auto-config. No nesting, no arrays, no booleans, no numbers.

    export const config = easyConfig({
      "url": ['--url', '-u', 'APP_URL'],
      "port": ['--port', '-p', 'PORT'],
      "debug": ['--debug', '-D'],
    });
    

    Well, it lives up to the name at least!

    Proposed API Changes

    Validator function interface:

    type ValidatorFunction<TReturnType> = (
      value: string,     // The value to validate: '08080'
      sourceKey: string, // `--port`
      fieldName: string, // `port`
      allMatchedKeys: Record<string, string> // { 'PORT': '8080', '--port': '08080' };
    ) => TReturnType;
    

    Example Validators

    To support custom logic while getting types for free we'll support a trailing function pattern.

    After the list of input args & env keys, include a ValidatorFunction as the last array element.

    export const config = easyConfig({
      "debug": ['--debug', '-D', Boolean],
      "url": ['--url', '-u', 'APP_URL', url => new URL(url)],
    });
    config.debug; // boolean
    config.url; // URL instance
    

    Tip 1: Auto-type keys using JS' built-in methods Boolean(), Number(), String(), etc

    A quick way to add type hints: use the language's primitive constructors.

    export const config = easyConfig({
      "port": ['--port', '-p', Number],
      "debug": ['--debug', '-D', Boolean],
    });
    
    config.port; // number
    config.debug; // boolean
    

    ProTip 2: Convert inputs into advanced types

    This snippet takes a url string and returns a new URL() instance.

    If an error is encountered, the app will prevent invalid runtime states by exiting & re-throwing the original error message!

    // Example used anonymous arrow function, but you can use a named function too.
    const parseUrl = (url: string) => new URL(url);
    

    ProTip 3: Parse JSON input strings

    Note: Advanced example. Feel free to skip & revisit later.

    The following example is a fair bit more complex. The goal is showing a 'real-world' JSON parsing pattern evolves with this library.

    Since arguments and environment variables can support long strings, it can sometimes be a convenient strategy to use stringified JSON. For example adding/removing features is easier if you know that theres only 1 place it's configured. A related issue: most enterprise apps eventually have to manage dozens to 100+'s of environment & configuration variables. The sprawl can quickly be a drag to manage and difficult to trace when things go wrong.

    Let's visualize combining 2 keys into PRODUCT_PAGE={json}.

    Given

    • PRODUCT_PAGE_SCROLL=infinite
    • PRODUCT_PAGE_LIMIT=10

    We want to combine them into a single JSON key:

    • PRODUCT_PAGE={"scroll": "infinite", "limit": 10}

    Future product additions can be added to the JSON with relative ease:

    Let's say, your legal team has requested a new disclaimer be added to the product page.

    We might have named this DISCLAIMER_PRODUCT, which could easily be overlooked when sorting and looking for PRODUCT_* in a sea of keys.

    • PRODUCT_PAGE={"scroll": "infinite", "limit": 10, "disclaimer": "..."}
    • SUGGESTIONS_PAGE={"scroll": "none", "limit": 10, "disclaimer": "(items other shoppers purchased)"}

    When adding legal text to a website, it may be more important to see the disclaimers co-located in one key.

    • DISCLAIMERS={"product": "...", "home": "all rights reversed", "partner_content": "rights owned by their respective owners"}

    Design to make features more serviceable & manageable. โœจ

    Let's look at more examples of JSON embedded keys.

    export DATADOG_CONFIGS='{"apiKey":"my-key","sampling":"0.25","tags":["env:prod"]}'
    export ACTIVE_FEATURES='["checkout_v4","cta_ab_test_v55","rewards_v3"]'
    

    The following example shows how to tie this all together:

    export const config = easyConfig({
      "datadog": ['DATADOG_CONFIGS', safeJsonParser],
      "features": ['--active-features', 'ACTIVE_FEATURES', safeJsonParser],
    });
    

    Example Strict & Safe JSON Parsers

    // Throws on invalid JSON.
    const strictJsonParser = (json: string) => JSON.parse(json);
    
    // Invalid JSON will get logged, and the app will return false.
    const safeJsonParser = (json: string, sourceKey: string) => {
      try {
        if (!json || json.length < 2) return false;
        return JSON.parse(json);
      } catch (error) {
        console.error('Invalid JSON supplied', error, {json, sourceKey});
        // NOTE: Change your default fall-back json value: instead of `false`, maybe `null` or an empty object or array might make more sense.
        return false; 
      }
    };
    

    4. ProTip: Configurable Port number validator

    // Using the curried `portRangeChecker()` helper (see below)
    const isHttpIsh = portRangeChecker({min: 80, max: 443});
    // The func `isHttpIsh(port)` accepts a number, and if outside the range provided it'll fail, and if inside the.
    isHttpIsh(79) //-> false
    isHttpIsh(80) //-> true
    isHttpIsh(444) //-> false
    isHttpIsh(79) //-> false
    
    
    const portRangeChecker = ({min = 1_000, max = 60_000}: PortRange) =>
      (port: number | string) => {
        port = parseInt(`${port}`);
        if (port > 65_535) throw Error(`Port number ${port} can't exceed 65535`);
        if (port < 1) throw Error(`Port number ${port} must be at least 1`);
        if (port >= min && port <= max) return port;
        throw new Error(`Unexpected Port ${port} value detected.`);
      }
    
    type PortRange = {min: number, max: number};
    

    5. ProTip: Zod-based type validation

    // Use a Zod schema to validate, type check any config values.
    const parseAcctId = input => zod.any(input).refine(Number).safeParse(input)?.data;
    
    export const config = easyConfig({
      "accountId": ['--accountId', 'ACCOUNT_ID', parseAcctId],
    });
    
    opened by justsml 0
  • Validate on access

    Validate on access

    Why

    Some applications may prefer to delay evaluation of the validation.

    Pros

    • Stack trace leads to the usage location, not the config file.

    Cons

    • May hide config problems during development & testing.

    Dev notes

    Possible implementations:

    • get getter wrapper object?
    • Or ES6 Proxy?

    Considerations

    • Set via an option?
      • Per value?
      • Set per config set?

    Usage?

    Option naming:

    • deferred: true
    • delayed: true
    • validate: 'delayed',
    • validateOn: 'load' | 'access'
    • ?

    Some Examples

    1/3: Per Config: deferred option

    import { autoConfig } from '@elite-libs/auto-config';
    
    const config = autoConfig({
      port: {
        args: ['--port', 'PORT'],
        deferred: true,
        required: true,
      },
    });
    

    2/3: autoConfig Instance Default

    import { autoConfig } from '@elite-libs/auto-config';
    
    const config = autoConfig({
      port: {
        args: ['--port', 'PORT'],
        required: true,
      },
    }, {
      deferred: true
    });
    

    3/3: Global Override

    import { autoConfig } from '@elite-libs/auto-config';
    
    autoConfig.deferred = true;
    
    const config = autoConfig({
      port: {
        args: ['--port', 'PORT'],
        required: true,
      },
    });
    
    opened by justsml 0
Owner
Collection of Modern Open Source libraries for Node, TypeScript, and JavaScript.
null
This is a simple Image popup Jquery plugin. With a very simple configuration, you can show a popup on your webpage. By the way, this plugin works after page load.

Jquery-SingleImagePopup This is a simple Image popup Jquery plugin. With a very simple configuration, you can show a popup on your webpage. By the way

Rajan Karmaker 1 Aug 22, 2022
๐ŸŽจ Beautify your github profile with this amazing tool, creating the readme your way in a simple and fast way ๐Ÿš€ The best profile readme generator you will find โšก

Demo Profile Readme Generator The best profile readme generator you will find! About | Technologies | Requirements | Starting | Contributing ?? About

Mauro de Souza 476 Jan 1, 2023
CLI Progress Bar implemented in NodeJS to track Time, ETA and Steps for any long running jobs in any loops in JS, NodeJS code

NodeJS-ProgressBar CLI Progress Bar for NodeJS and JavaScript to track Time, ETA and Steps for any long running jobs in any loops in JS, NodeJS code D

Atanu Sarkar 5 Nov 14, 2022
A CLI tool to create a NodeJS project with TypeScript CTSP is a CLI tool to make easier to start a new NodeJS project and configure Typescript on it.

CTSP- Create TS Project A CLI tool to create a NodeJS project with TypeScript CTSP is a CLI tool to make easier to start a new NodeJS project and conf

Jean Rodrรญguez 7 Sep 13, 2022
An easy way to animate SVG elements.

Walkway I loved the animations for the polygon ps4 review a few months back and decided to create a small library to re-create them (simple demo). It

Connor Atherton 4.4k Jan 2, 2023
An easy and simple way to manage your financial transactions.

MyWallet An easy and simple way to manage your financial transactions. With MyWallet you can track your incomes and expenses and always keep track of

Caroline Oliveira 7 Nov 16, 2022
NFT Info: An easy way to create customizable pages about NFTs

NFT Info: An easy way to create customizable pages about NFTs Submission for the BuildQuest hackathon 2022. My goal is for NFT project creators and th

Mathijs Vogelzang 2 Mar 23, 2022
An easy and simply way to create your own image classifier AI using ml5.js and Google's Teachable Machine

An easy and simply way to create your own image classifier AI using ml5.js and Google's Teachable Machine

Mateus Vinรญcius de Lima 2 Apr 5, 2022
DropSpace is an easy way to self-host a file drop.

DropSpace Simple file sharing made in Laravel About DropSpace DropSpace is an easy way to self-host a file drop. Simply upload your file, and share th

Kazรณ Levente 25 Dec 9, 2022
An easy way to mass download osu! beatmaps

Batch Beatmap Downloader (Beta) Download Latest Release Table of Contents About Screenshots Getting Started Prerequisites Usage Build instructions Con

James 65 Jan 3, 2023
An easy way to discover and manage your cloud like a local filesystem

cfs An easy way to discover and manage your cloud like a local filesystem. The swiss army knife for finding any resource in your AWS account. โฌ instal

Khalid Zoabi 4 Jun 4, 2022
Veloorum. An easy way to organize a community or work team

Veloorum โ—๏ธ โ—๏ธ ะŸั€ะธะปะพะถะตะฝะธะต ะฝะฐั…ะพะดะธั‚ัั ะฝะฐ ั€ะฐะฝะฝะตะผ ัั‚ะฐะฟะต ั€ะฐะทั€ะฐะฑะพั‚ะบะธ โ—๏ธ โ—๏ธ โ—๏ธ โ—๏ธ ะžะฑะฝะพะฒะปะตะฝะธั ะฑัƒะดัƒั‚ ะฒั‹ั…ะพะดะธั‚ัŒ ะฟะพ ะผะตั€ะต ะฒะพะทะผะพะถะฝะพัั‚ะธ โ—๏ธ โ—๏ธ ะ˜ัั…ะพะดะฝั‹ะน ะบะพะด ัะตั€ะฒะตั€ะฐ Ve

Vladislav Wagner 2 Jan 30, 2022
BCash is an app to help you keep track of who you owe and who owes you money in an easy way. Split your tabs and more.

BCash BCash is an app to help you keep track of who you owe and who owes you money in an easy way. Split your tabs and more. Routes for develpment: lo

Cuitlahuac Maldonado 3 Aug 11, 2022
Tracing the easy way using JSON.

MikroTrace Tracing the easy way using JSON. JSON tracer that tries to emulate OpenTelemetry semantics and behavior. Built as a ligher-weight way to ha

Mikael Vesavuori 11 Nov 14, 2022
Easy and simple way to share data via mobileโ€™s built-in share module.

React-Mobile-Share Provides an easy and simple way to share data (such as text, url and media) via mobileโ€™s built-in share module. It is based on Web

EncoreSky Technologies 36 Dec 28, 2022
An easy way to create a TypeScript library without hassle.

ts-lib-template An easy way to create a TypeScript library without hassle. ts-lib-template is a template for creating a TypeScript library. It comes b

Snehil K 7 Sep 13, 2022
Easy way to know how many visitors are viewing your Github, Website

Visit Counter Easy way to know how many visitors are viewing your Github, Website Reference for Image query Usage Default Example page It can be your

DevXprite 7 Dec 24, 2022
Save time by managing bills & expenses, invoicing & easy reconciliation all in one app. Generate clear dynamic statements and get your reports, the way you like them

expense-manager-app (Opensource Expense Tracking App built with React) ?? Save time by managing bills & expenses, invoicing & easy reconciliation all

Muhammad Awais 3 Oct 12, 2022
Easy way to change filament theme color on the fly.

Filament Theme Color Easy way to change filament theme color on the fly. In some projects, it is interesting to be able to change the main colors of a

Uccello Labs 8 Nov 20, 2022