From 23349f18621502b723f17af2cd083b9cb877f007 Mon Sep 17 00:00:00 2001 From: Spartak Date: Tue, 18 Jun 2024 15:20:18 +0200 Subject: [PATCH] docs(package): better README and more jsdocs everywhere --- LICENSE.md | 21 ++++++ README.md | 56 ++++++++++------ docs/assets/highlight.css | 7 ++ docs/coverage.svg | 8 +-- docs/functions/fromJSONFile.html | 16 ++++- docs/functions/fromObject.html | 14 +++- docs/functions/fromURL.html | 16 ++++- docs/index.html | 46 +++++++------ docs/types/_internal_.Validator.html | 3 +- .../_internal_.ValidatorCustomValidator.html | 4 +- docs/types/_internal_.ValidatorMyZod.html | 4 +- .../_internal_.ValidatorSuperstruct.html | 4 +- docs/types/_internal_.ValidatorValibot.html | 5 +- .../_internal_.ValidatorWithInputOutput.html | 5 +- .../_internal_.ValidatorWithoutInput.html | 4 +- docs/types/_internal_.ValidatorYup.html | 4 +- docs/types/_internal_.ValidatorZod.html | 5 +- docs/types/_internal_.inferValidator.html | 5 +- examples/jsonFileFactory.ts | 21 ++++++ examples/objectFactory.ts | 16 +++++ examples/urlFactory.ts | 16 +++++ package.json | 1 + pnpm-lock.yaml | 11 ++++ src/factories/jsonFileFactory.ts | 56 +++++++++------- src/factories/objectFactory.ts | 17 +++++ src/factories/urlFactory.ts | 66 +++++++++++-------- src/types/validator.d.ts | 43 ++++++++++++ src/util/exception.ts | 23 ++++++- src/util/mergeObjects.ts | 22 ++++++- src/util/readFile.ts | 14 +++- src/util/validation.ts | 27 +++++--- tsconfig.json | 2 +- typedoc.json | 7 +- vitest.config.ts | 2 +- 34 files changed, 444 insertions(+), 127 deletions(-) create mode 100644 LICENSE.md create mode 100644 examples/jsonFileFactory.ts create mode 100644 examples/objectFactory.ts create mode 100644 examples/urlFactory.ts diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..8aa2645 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 962114d..ac80ef3 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,43 @@ # Typescript runtime configuration resolver +@mrspartak/config is a robust TypeScript runtime configuration resolver designed to ensure that your application runs with the correct settings every time. It supports dynamic runtime validation, deep merging of configurations, and integrates seamlessly with your choice of data validation libraries. + ![GitHub Release](https://img.shields.io/github/v/release/mrspartak/config?style=for-the-badge&color=%231b1b1f) ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/min/%40mrspartak/config?style=for-the-badge&color=%231b1b1f) ![NPM Downloads](https://img.shields.io/npm/dw/%40mrspartak%2Fconfig?style=for-the-badge&color=%231b1b1f) -* ⚡️ Runtime validation (no more deployments with the wrong configuration) -* 🧙‍♂️ TypeScript intelissense -* 🍃 Light, zero external dependencies -* 🤲 Merge configurations (defaults overwrite strategy) -* 👓 Support for JSON file/url config, Object config, [soon] ENV -* 🐻 Bring your validator library of choise. We support **Zod**, **Valibot**, **Yup**, **Superstruct** etc... -* ✅ Well-tested and production ready. -* [soon] Works as a run-time config provider on a front-end +* ⚡️ Runtime Validation: Ensure your application never runs with the wrong configuration. +* 🧙‍♂️ TypeScript IntelliSense: Leverage auto-completion and type-checking at development time. +* 🍃 Zero Dependencies: Lightweight with no external dependencies +* 🤲 Flexible Configuration Merging: Supports merging multiple configurations with a default overwrite strategy. +* 👓 Versatile Configuration Sources: Load from JSON files, URLs, or direct objects. +* 🐻 Extensible Validation Support: Compatible with **Zod**, **Valibot**, **Yup**, **Superstruct**, and more. +* ✅ Production Ready: Thoroughly tested and stable for use. + +## Roadmap + +* 📁 Support for .env files. +* 🌐 Enhance front-end compatibility. +* 📚 Expand documentation. +* ⚙️ Integrate GitHub Actions for test coverage reporting. -## Quickstart +## Installation ```sh # yarn yarn add @mrspartak/config - # npm npm i @mrspartak/config - # pnpm pnpm add @mrspartak/config - # bun bun add @mrspartak/config ``` -## Usage +## Quick Start -1. Create a config resolver file +Create a config resolver file ```ts +// file: state/config.ts import { fromJSONFile } from "@mrspartak/config"; import * as z from "zod" @@ -53,10 +59,22 @@ const config = await fromJSONFile({ export default config ``` -2. Import resolved configuration anywhere you need +Import resolved configuration anywhere you need ```ts -import config from 'config.js' -import db from 'some-db-provider' +// file: index.ts +// Import your resolved configuration +import config from './state/config.js'; + +// Use the configuration in your application +import db from 'some-db-provider'; +const dbClient = db(config.db); // Enjoy IntelliSense here! +``` + +Full documentation is generated from TS declaration avialable here: https://mrspartak.github.io/config/ + +## Contributing +I welcome contributions from the community! Whether it's improving the documentation, adding new features, or reporting bugs, please feel free to make a pull request or open an issue. -const dbClient = db(config.db) // config.db will have full intelisense -``` \ No newline at end of file +## License +This project is licensed under the MIT License - see the LICENSE.md file for details. + \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css index ef2cd6c..9700e2c 100644 --- a/docs/assets/highlight.css +++ b/docs/assets/highlight.css @@ -17,6 +17,8 @@ --dark-hl-7: #4FC1FF; --light-hl-8: #098658; --dark-hl-8: #B5CEA8; + --light-hl-9: #267F99; + --dark-hl-9: #4EC9B0; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @@ -31,6 +33,7 @@ --hl-6: var(--light-hl-6); --hl-7: var(--light-hl-7); --hl-8: var(--light-hl-8); + --hl-9: var(--light-hl-9); --code-background: var(--light-code-background); } } @@ -44,6 +47,7 @@ --hl-6: var(--dark-hl-6); --hl-7: var(--dark-hl-7); --hl-8: var(--dark-hl-8); + --hl-9: var(--dark-hl-9); --code-background: var(--dark-code-background); } } @@ -57,6 +61,7 @@ --hl-6: var(--light-hl-6); --hl-7: var(--light-hl-7); --hl-8: var(--light-hl-8); + --hl-9: var(--light-hl-9); --code-background: var(--light-code-background); } @@ -70,6 +75,7 @@ --hl-6: var(--dark-hl-6); --hl-7: var(--dark-hl-7); --hl-8: var(--dark-hl-8); + --hl-9: var(--dark-hl-9); --code-background: var(--dark-code-background); } @@ -82,4 +88,5 @@ .hl-6 { color: var(--hl-6); } .hl-7 { color: var(--hl-7); } .hl-8 { color: var(--hl-8); } +.hl-9 { color: var(--hl-9); } pre, code { background: var(--code-background); } diff --git a/docs/coverage.svg b/docs/coverage.svg index 024c5b4..8ef031c 100644 --- a/docs/coverage.svg +++ b/docs/coverage.svg @@ -5,13 +5,13 @@ - - + + document document - 0% - 0% + 52% + 52% \ No newline at end of file diff --git a/docs/functions/fromJSONFile.html b/docs/functions/fromJSONFile.html index bf3b155..12139f2 100644 --- a/docs/functions/fromJSONFile.html +++ b/docs/functions/fromJSONFile.html @@ -156,7 +156,21 @@ --md-sys-color-surface-container-high: #eae7ec; --md-sys-color-surface-container-highest: #e4e1e6 } -

Function fromJSONFile

Function fromJSONFile

  • Asynchronously reads and validates JSON data from one or more files against a provided schema.

    +

    This function allows for the loading of configuration or data from JSON files specified by path or paths. +It handles reading multiple files in parallel, parses them as JSON, and then merges all objects into a single +object to be validated against a given schema. Exception handling is integrated to manage and report errors +effectively during file reading and parsing stages.

    +

    Example


    import { fromJSONFile } from "@mrspartak/config";
    import * as z from "zod";

    const schema = z.object({
    environment: z.enum(["development", "production"]),
    port: z.number().default(3000),
    db: z.object({
    host: z.string(),
    port: z.number(),
    user: z.string(),
    password: z.string(),
    }),
    });

    const data = await fromJSONFile({
    path: ["config/default.json", "config/production.json"],
    schema,
    });

    console.log(data); // { environment: 'production', port: 3000, db: { host: 'localhost', port: 5432, user: 'admin', password: 'admin' } }
    const db = data.db; // Object { host: 'localhost', port: 5432, user: 'admin', password: 'admin' }
    +
    +

    Type Parameters

    Parameters

    • params: {
          path: string | string[];
          schema: $Validator;
      }

      The parameters object containing the path(s) and schema.

      +
      • path: string | string[]

        Path or array of paths to JSON files that need to be read.

        +
      • schema: $Validator

        The schema against which the data is validated after merging.

        +

    Returns Promise<inferValidator<$Validator>["out"]>

    A promise that resolves with the validated data object.

    +

    Throws

      +
    • Throws an enhanced exception with contextual information if file reading or parsing fails.
    • +
    +

Function fromObject

Function fromObject

  • Asynchronously validates a data object against a provided schema.

    +

    This function serves as a high-level utility for ensuring that data conforms +to a specified schema using the validator defined in the schema's structure. +It is useful for runtime validation where the schema and data are dynamically +provided.

    +

    Example


    import { fromObject } from "@mrspartak/config";
    import * as z from "zod";

    const schema = z.object({
    name: z.string(),
    age: z.number(),
    isStudent: z.boolean(),
    });

    const data = await fromObject({
    data: { name: "Alice", age: 25, isStudent: true },
    schema,
    });

    console.log(data); // { name: 'Alice', age: 25, isStudent: true }
    const name: string = data.name; // OK
    +
    +

    Type Parameters

    Parameters

    • params: {
          data: unknown;
          schema: $Validator;
      }

      The parameters object.

      +
      • data: unknown

        The data object to validate.

        +
      • schema: $Validator

        The validator schema against which to validate the data.

        +

    Returns Promise<inferValidator<$Validator>["out"]>

    A promise that resolves with the validated data.

    +

    Throws

    Throws an error if validation fails.

    +

Function fromURL

Function fromURL

  • Asynchronously fetches and validates data from one or more URLs against a provided schema.

    +

    This function is designed to handle fetching JSON data from specified URLs, which can either be +a single URL or an array of URLs. It fetches all URLs in parallel, parses the JSON, merges the results +into a single object, and then validates the merged object against the provided schema. The function +leverages exception handling to manage errors during the fetch process.

    +

    Example


    import { fromURL } from "@mrspartak/config";
    import * as z from "zod";

    const schema = z.object({
    name: z.string(),
    age: z.number(),
    isStudent: z.boolean(),
    });

    const data = await fromURL({
    url: "https://example.com/data.json",
    schema,
    });

    console.log(data); // { name: 'Alice', age: 25, isStudent: true }
    const name: string = data.name; // OK
    +
    +

    Type Parameters

    Parameters

    • params: {
          schema: $Validator;
          url: string | string[];
      }

      The parameters object.

      +
      • schema: $Validator

        The schema against which the merged data will be validated.

        +
      • url: string | string[]

        One or more URLs from which to fetch data.

        +

    Returns Promise<inferValidator<$Validator>["out"]>

    A promise that resolves with the result of the validation.

    +

    Throws

      +
    • Captures and rethrows exceptions with context if the fetch or parsing fails.
    • +
    +

@mrspartak/config

Typescript runtime configuration resolver

    -
  • ⚡️ Runtime validation (no more deployments with the wrong configuration)
  • -
  • 🧙‍♂️ TypeScript intelissense
  • -
  • 🍃 Light, zero external dependencies
  • -
  • 🤲 Merge configurations (defaults overwrite strategy)
  • -
  • 👓 Support for JSON file/url config, Object config, [soon] ENV
  • -
  • 🐻 Bring your validator library of choise. We support Zod, Valibot, Yup, Superstruct etc...
  • -
  • ✅ Well-tested and production ready.
  • -
  • [soon] Works as a run-time config provider on a front-end
  • +

    @mrspartak/config

    Typescript runtime configuration resolver

    @mrspartak/config is a robust TypeScript runtime configuration resolver designed to ensure that your application runs with the correct settings every time. It supports dynamic runtime validation, deep merging of configurations, and integrates seamlessly with your choice of data validation libraries.

    +

    GitHub Release +npm bundle size (scoped) +NPM Downloads

    +
      +
    • ⚡️ Runtime Validation: Ensure your application never runs with the wrong configuration.
    • +
    • 🧙‍♂️ TypeScript IntelliSense: Leverage auto-completion and type-checking at development time.
    • +
    • 🍃 Zero Dependencies: Lightweight with no external dependencies
    • +
    • 🤲 Flexible Configuration Merging: Supports merging multiple configurations with a default overwrite strategy.
    • +
    • 👓 Versatile Configuration Sources: Load from JSON files, URLs, or direct objects.
    • +
    • 🐻 Extensible Validation Support: Compatible with Zod, Valibot, Yup, Superstruct, and more.
    • +
    • ✅ Production Ready: Thoroughly tested and stable for use.
    -

    Quickstart

    # yarn
    yarn add @mrspartak/config

    # npm
    npm i @mrspartak/config

    # pnpm
    pnpm add @mrspartak/config

    # bun
    bun add @mrspartak/config +

    Roadmap

      +
    • 📁 Support for .env files.
    • +
    • 🌐 Enhance front-end compatibility.
    • +
    • 📚 Expand documentation.
    • +
    • ⚙️ Integrate GitHub Actions for test coverage reporting.
    • +
    +

    Installation

    # yarn
    yarn add @mrspartak/config
    # npm
    npm i @mrspartak/config
    # pnpm
    pnpm add @mrspartak/config
    # bun
    bun add @mrspartak/config
    -

    Usage

      -
    1. Create a config resolver file
    2. -
    -
    import { fromJSONFile } from "@mrspartak/config";
    import * as z from "zod"

    const config = await fromJSONFile({
    path: ["../config/default.json", "../config/runtime.json"],
    schema: z.object({
    db: z.object({
    host: z.string(),
    port: zv.number(),
    username: z.string(),
    password: z.string()
    }),
    app: z.object({
    port: z.number().optional().default(3000)
    })
    }),
    });

    export default config +

    Quick Start

    Create a config resolver file

    +
    // file: state/config.ts
    import { fromJSONFile } from "@mrspartak/config";
    import * as z from "zod"

    const config = await fromJSONFile({
    path: ["../config/default.json", "../config/runtime.json"],
    schema: z.object({
    db: z.object({
    host: z.string(),
    port: zv.number(),
    username: z.string(),
    password: z.string()
    }),
    app: z.object({
    port: z.number().optional().default(3000)
    })
    }),
    });

    export default config
    -
      -
    1. Import resolved configuration anywhere you need
    2. -
    -
    import config from 'config.js'
    import db from 'some-db-provider'

    const dbClient = db(config.db) // config.db will have full intelisense +

    Import resolved configuration anywhere you need

    +
    // file: index.ts
    // Import your resolved configuration
    import config from './state/config.js';

    // Use the configuration in your application
    import db from 'some-db-provider';
    const dbClient = db(config.db); // Enjoy IntelliSense here!
    -

    A base type representing any kind of validator, either distinguishing between input/output types or not.

    +

    Type alias ValidatorCustomValidator<TI>

    ValidatorCustomValidator<TI>: ((input) => Promise<TI> | TI)

    Type Parameters

    • TI

    Type declaration

      • (input): Promise<TI> | TI
      • Parameters

        • input: unknown

        Returns Promise<TI> | TI

    Type alias ValidatorCustomValidator<TI>

    ValidatorCustomValidator<TI>: ((input) => Promise<TI> | TI)

    Represents a generic validator function that may return a promise or a direct value.

    +

    Type Parameters

    • TI

      The type that the input is validated against and returned.

      +

    Type declaration

      • (input): Promise<TI> | TI
      • Parameters

        • input: unknown

        Returns Promise<TI> | TI

    Type alias ValidatorMyZod<TI>

    ValidatorMyZod<TI>: {
        parse: ((input) => TI);
    }

    Type Parameters

    • TI

    Type declaration

    • parse: ((input) => TI)
        • (input): TI
        • Parameters

          • input: any

          Returns TI

    Type alias ValidatorMyZod<TI>

    ValidatorMyZod<TI>: {
        parse: ((input) => TI);
    }

    Represents a MyZod validator which contains a parse method for input data.

    +

    Type Parameters

    • TI

      The type into which the input data will be parsed.

      +

    Type declaration

    • parse: ((input) => TI)
        • (input): TI
        • Parameters

          • input: any

          Returns TI

    Type alias ValidatorSuperstruct<TI>

    ValidatorSuperstruct<TI>: {
        create: ((input) => TI);
    }

    Type Parameters

    • TI

    Type declaration

    • create: ((input) => TI)
        • (input): TI
        • Parameters

          • input: unknown

          Returns TI

    Type alias ValidatorSuperstruct<TI>

    ValidatorSuperstruct<TI>: {
        create: ((input) => TI);
    }

    Represents a Superstruct validator which contains a create method to construct a typed object.

    +

    Type Parameters

    • TI

      The type that the input will be validated against and created as.

      +

    Type declaration

    • create: ((input) => TI)
        • (input): TI
        • Parameters

          • input: unknown

          Returns TI

    Type alias ValidatorValibot<TI, TPI>

    ValidatorValibot<TI, TPI>: {
        types?: {
            input: TI;
            output: TPI;
        };
    }

    Type Parameters

    • TI
    • TPI

    Type declaration

    • Optional types?: {
          input: TI;
          output: TPI;
      }

    Type alias ValidatorValibot<TI, TPI>

    ValidatorValibot<TI, TPI>: {
        types?: {
            input: TI;
            output: TPI;
        };
    }

    Represents a Valibot validator with optional input and output types specification.

    +

    Type Parameters

    • TI

      The expected input type.

      +
    • TPI

      The output type after validation.

      +

    Type declaration

    • Optional types?: {
          input: TI;
          output: TPI;
      }

    Type alias ValidatorWithInputOutput<TI, TPI>

    ValidatorWithInputOutput<TI, TPI>: ValidatorZod<TI, TPI> | ValidatorValibot<TI, TPI>

    Type Parameters

    • TI
    • TPI

    Type alias ValidatorWithInputOutput<TI, TPI>

    ValidatorWithInputOutput<TI, TPI>: ValidatorZod<TI, TPI> | ValidatorValibot<TI, TPI>

    A union type for validators that clearly separate input and output types.

    +

    Type Parameters

    • TI

      The input type.

      +
    • TPI

      The output type.

      +

    Type alias ValidatorWithoutInput<TI>

    Type Parameters

    • TI

    Type alias ValidatorWithoutInput<TI>

    A union type for validators that do not distinguish between input and output types.

    +

    Type Parameters

    • TI

      The type for input which is also used as the output type.

      +

    Type alias ValidatorYup<TI>

    ValidatorYup<TI>: {
        validateSync: ((input) => TI);
    }

    Type Parameters

    • TI

    Type declaration

    • validateSync: ((input) => TI)
        • (input): TI
        • Parameters

          • input: unknown

          Returns TI

    Type alias ValidatorYup<TI>

    ValidatorYup<TI>: {
        validateSync: ((input) => TI);
    }

    Represents a Yup validator which contains a synchronous validate method.

    +

    Type Parameters

    • TI

      The type that the input is validated against and returned.

      +

    Type declaration

    • validateSync: ((input) => TI)
        • (input): TI
        • Parameters

          • input: unknown

          Returns TI

    Type alias ValidatorZod<TI, TPI>

    ValidatorZod<TI, TPI>: {
        _input: TI;
        _output: TPI;
    }

    Type Parameters

    • TI
    • TPI

    Type declaration

    Type alias ValidatorZod<TI, TPI>

    ValidatorZod<TI, TPI>: {
        _input: TI;
        _output: TPI;
    }

    Represents a Zod validator with input and parsed output types.

    +

    Type Parameters

    • TI

      The expected input type.

      +
    • TPI

      The parsed output type.

      +

    Type declaration

    Type alias inferValidator<$Validator>

    inferValidator<$Validator>: $Validator extends ValidatorWithInputOutput<infer $TIn, infer $TOut>
        ? {
            in: $TIn;
            out: $TOut;
        }
        : $Validator extends ValidatorWithoutInput<infer $InOut>
            ? {
                in: $InOut;
                out: $InOut;
            }
            : never

    Type Parameters

    Type alias inferValidator<$Validator>

    inferValidator<$Validator>: $Validator extends ValidatorWithInputOutput<infer $TIn, infer $TOut>
        ? {
            in: $TIn;
            out: $TOut;
        }
        : $Validator extends ValidatorWithoutInput<infer $InOut>
            ? {
                in: $InOut;
                out: $InOut;
            }
            : never

    Type utility to infer input and output types from a Validator type.

    +

    Type Parameters

    • $Validator extends Validator

      The validator type.

      +

    Returns

    The inferred input and output types based on the validator specification.

    +