{"id":16673639,"url":"https://github.com/nathan-fiscaletti/logical-config","last_synced_at":"2026-02-13T07:39:08.212Z","repository":{"id":57701609,"uuid":"496794003","full_name":"nathan-fiscaletti/logical-config","owner":"nathan-fiscaletti","description":"Invoke JavaScript from config files","archived":false,"fork":false,"pushed_at":"2022-05-27T19:16:58.000Z","size":46,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-15T17:33:01.693Z","etag":null,"topics":["config","configuration","functions","javascript","js","json","json-config","json-configuration","yaml","yaml-configuration"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nathan-fiscaletti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-26T22:49:39.000Z","updated_at":"2022-07-27T02:21:59.000Z","dependencies_parsed_at":"2022-08-29T04:31:43.412Z","dependency_job_id":null,"html_url":"https://github.com/nathan-fiscaletti/logical-config","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathan-fiscaletti%2Flogical-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathan-fiscaletti%2Flogical-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathan-fiscaletti%2Flogical-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathan-fiscaletti%2Flogical-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nathan-fiscaletti","download_url":"https://codeload.github.com/nathan-fiscaletti/logical-config/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236791148,"owners_count":19205328,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["config","configuration","functions","javascript","js","json","json-config","json-configuration","yaml","yaml-configuration"],"created_at":"2024-10-12T12:27:36.548Z","updated_at":"2026-02-13T07:39:03.170Z","avatar_url":"https://github.com/nathan-fiscaletti.png","language":"JavaScript","funding_links":["https://github.com/sponsors/nathan-fiscaletti"],"categories":[],"sub_categories":[],"readme":"# Logical Config\n\n[![Sponsor Me!](https://img.shields.io/badge/%F0%9F%92%B8-Sponsor%20Me!-blue)](https://github.com/sponsors/nathan-fiscaletti)\n[![Downloads](https://img.shields.io/npm/dw/logical-config)](https://www.npmjs.com/package/logical-config)\n[![GitHub stars](https://img.shields.io/github/stars/nathan-fiscaletti/logical-config)](https://github.com/nathan-fiscaletti/logical-config/stargazers)\n[![GitHub issues](https://img.shields.io/github/issues/nathan-fiscaletti/logical-config)](https://github.com/nathan-fiscaletti/logical-config/issues)\n[![GitHub license](https://img.shields.io/github/license/nathan-fiscaletti/logical-config)](https://github.com/nathan-fiscaletti/logical-config/blob/main/LICENSE)\n\nThe logical-config JavaScript package allows you, through short-hand notation, to invoke functions directly from your configuration files at load-time and map configuration entries to variables, classes, or functions.\n\n## Install\n\n```sh\n$ yarn add logical-config\n```\n\n## Index\n\n- [Practical Example](#practical-example)\n- [Simple Example](#simple-example)\n- [Documentation](#documentation)\n  - [Path Objects](#path-objects)\n    - [Short-hand](#path-object-short-hand)\n    - [Child Path Objects](#child-path-objects)\n  - [The `.fill()` function](#the-fill-function)\n- [Advanced Examples](#advanced-examples)\n  - [Retrieving Properties](#retrieving-properties)\n  - [Using Functions](#using-functions)\n  - [Using Classes](#using-classes)\n\n## Practical Example\n\nSee [Winston Logical Config](https://github.com/nathan-fiscaletti/winston-logical-config) for a practical example of using a Logical Config file. Winston Logical Config allows you to configure a [Winston](https://github.com/winstonjs/winston) logger directly from a config file.\n\n## Simple Example\n\n`config.yaml`\n```yaml\nData:\n  Connection: \"{database.getConnection}\"\n```\n\n**Code**\n```js\nconst LogicalConfig = require('logical-config');\n\nconst yaml = require('js-yaml');\nconst fs   = require('fs');\n\nconst config = await LogicalConfig.fill({\n    input: yaml.load(fs.readFileSync('./config.yaml', 'utf8')),\n    data: {\n        database: {\n            getConnection: async () =\u003e Promise.resolve({ connected: true })\n        }\n    }\n});\n\nconsole.log(config);\n```\n\n**Output**\n```js\n{ Data: { Connection: { connected: true } } }\n```\n\n## Documentation\n\n### Path Objects\n\nPath objects tell the LogicalConfig how to look up the desired value.\n\nEach path object consists of three properties.\n\n|Property|Required|Default|Description|\n|---|---|---|---|\n|`$fill`|Yes|`undefined`|The dot path at which the desired value can be found in the map.|\n|`parameters`|No|`[]`|When the value found at the specified path is callable, and the `call` property is enabled, this is a list of parameters that will be passed to it.|\n|`call`|No|`true`|If the value found at the specified path is callable, this boolean indicates if the response of calling that value should be used, or the value itself.|\n\n**Example Path Object**\n```js\n{\n    '$fill': 'user.isOlderThan',\n    parameters: [ 18 ],\n    call: true\n}\n```\n\n#### Path Object Short-hand\n\n- Short-hand path objects should be written as strings and wrapped with `{}`.\n- Each property should be dilmited with a semi-colon `;`.\n- The properties should be listed in the order of (`$fill`, `parameters`, `call`).\n- The `parameters` property should be a JSON encoded array.\n- At least the `$fill` property must be specified.\n\nThe above example path object can be written in short-hand like this:\n\n```js\n\"{user.isOlderThan;[18]}\"\n```\n\nYou can attempt to parse a short-hand path object yourself using the `.parsePathObject()` function.\n\n```js\nconst parsed = LogicalConfig.parsePathObject(`{user.setName;[\"Nathan\"];true}`);\nconsole.log(parsed);\n```\n```js\n{ '$fill': 'user.setName', parameters: [ 'Nathan' ], call: true }\n```\n\n#### Child Path Objects\n\nYou can use Path Objects anywhere within the `parameters` array property of another Path Object. Please note however that **nested Path Objects are not supported in [short-hand path objects](#path-object-short-hand)**.\n\nIn this example we:\n\n1. Retrieve the users age using `user.getAgeAsStr`. The return value of this function is a string.\n2. Retrieve the numeric value by sending the users age to the `funcs.toInt` Number function.\n3. Evaluate the expression by passing the users age to the `user.isOlderThan` function and returning the response.\n\n**Code**\n\n```js\nconst canBuyAlcohol = await LogicalConfig.fill({\n    input: {\n        '$fill': 'item.canBuy',\n        parameters: [{\n            '$fill': 'Number',\n            parameters: [\"{user.getAgeAsStr}\"]\n        }]\n    },\n    data: {\n        Number,\n        item: {\n            name: 'alcohol',\n            canBuy: age =\u003e age \u003e 21,\n        },\n        user: {\n            getAgeAsStr: () =\u003e \"27\",\n        }\n    }\n});\n```\n\n### The `.fill()` function\n\n```js\nconst config = await LogicalConfig.fill(...\n```\n\nThe `.fill()` function takes an input object and data object containing data that [Path Objects](#path-objects) can access. Itt will replace each instance of a Path Object with the value it describes from the datab object. This will be performed on the input object recursively until all path objects have been resolved, at which point the finalized object will be returned.\n\n**Parameters**\n\n|Parameter|Required|Description|\n|---|---|---|\n|`input`|Yes|The input object that will be parsed. Can be an array of [Path Objects](#path-objects), a single Path Object, or an object in which any value (at any depth) is either an array of Path Objects or a Path Object.|\n|`data`|Yes|An object containing data to which path objects can correspond|\n|`ignoredPaths`|No|An array containing dot paths to keys in the input property that can be ignored when searching for Path Objects.|\n\n**Return**\n\nThe new object.\n\n## Advanced Examples\n\n### Retrieving Properties\n\n1. **Retrieve a property from the map using short-hand**\n\n   ```js\n   const res = await LogicalConfig.fill({\n      input: '{user.age}', \n      data: {\n          user: {\n              age: 27\n          }\n      }\n   });\n   console.log(res); // Outputs: 27\n   ```\n\n### Using Functions\n\n1. **Call a function from the map using short-hand**\n\n   ```js\n   const res = await LogicalConfig.fill({\n       input: '{user.getName}',\n       data: {\n           user: {\n               getName: () =\u003e \"Nathan\"\n           }\n       }\n   });\n   console.log(res); // Outputs: \"Nathan\"\n   ```\n\n2. **Call a function with parameters from the map using short-hand**\n\n   ```js\n   const res = await LogicalConfig.fill({\n       input: `{user.info;[{\"name\":\"Nathan\"}, 27]}`,\n       data: {\n           user: {\n               info: ({name}, age) =\u003e ({name, age})\n           }\n       }\n   });\n   console.log(res); // Outputs: { name: 'Nathan', age: 27 }\n   ```\n\n3. **Retrieve a function as a value from the map using short-hand**\n\n   By default, if a property is callable (is a class or a function), it will be invoked and it's return value will be used. You can override this by setting the `call` property of the [Path Object](#path-objects) to `false`.\n\n   ```js\n   const res = await LogicalConfig.fill({\n       input: `{user.info;;false}`,\n       data: {\n           user: {\n               info: () =\u003e {}\n           }\n       }\n   });\n   console.log(res); // Outputs: [Function: info]\n   ```\n\n### Using Classes\n\n1. **Retrieve a new instance of a class from the map using short-hand**\n\n   ```js\n   const res = await LogicalConfig.fill({\n       input: '{person.c}',\n       data: {\n           person: {\n               c: class {\n                   constructor() {\n                       this.name = \"Nathan\";\n                   }\n               }\n           }\n       }\n   });\n   console.log(res); // Outputs: c { name: 'Nathan' }\n   ```\n\n2. **Retrieve a new instance of a class with parameters from the map using short-hand**\n\n   ```js\n   const res = await LogicalConfig.fill({\n       input: '{person.c;[\"Nathan\"]}',\n       data: {\n           person: {\n               c: class {\n                   constructor(name) {\n                       this.name = name;\n                   }\n               }\n           }\n       }\n   });\n   console.log(res); // Outputs: c { name: 'Nathan' }\n   ```\n\n3. **Retrieve a class as a value from the map using short-hand.**\n\n   By default, if a property is callable (is a class or a function), it will be invoked and it's return value will be used. You can override this by setting the `call` property of the [Path Object](#path-objects) to `false`.\n\n   ```js\n   const res = await LogicalConfig.fill({\n       input:'{person.c;;false}',\n       data: {\n           person: {\n               c: class {}\n           }\n       }\n   });\n   console.log(res); // Outputs: [class c]\n   ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnathan-fiscaletti%2Flogical-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnathan-fiscaletti%2Flogical-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnathan-fiscaletti%2Flogical-config/lists"}