{"id":28955731,"url":"https://github.com/seancheung/kuconfig","last_synced_at":"2025-06-23T20:09:41.876Z","repository":{"id":33108955,"uuid":"152057777","full_name":"seancheung/kuconfig","owner":"seancheung","description":"Smart configuration control","archived":false,"fork":false,"pushed_at":"2022-02-11T12:24:12.000Z","size":149,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-29T00:58:13.860Z","etag":null,"topics":["config","dotenv","env"],"latest_commit_sha":null,"homepage":null,"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/seancheung.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":"2018-10-08T10:02:16.000Z","updated_at":"2022-01-04T06:27:56.000Z","dependencies_parsed_at":"2022-08-07T20:00:33.254Z","dependency_job_id":null,"html_url":"https://github.com/seancheung/kuconfig","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/seancheung/kuconfig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seancheung%2Fkuconfig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seancheung%2Fkuconfig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seancheung%2Fkuconfig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seancheung%2Fkuconfig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seancheung","download_url":"https://codeload.github.com/seancheung/kuconfig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seancheung%2Fkuconfig/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261548748,"owners_count":23175499,"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","dotenv","env"],"created_at":"2025-06-23T20:09:41.106Z","updated_at":"2025-06-23T20:09:41.865Z","avatar_url":"https://github.com/seancheung.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kuconfig\n\n[![Master Build][travis-master]][travis-url]\n\nSmart configuration control\n\n[travis-master]: https://img.shields.io/travis/seancheung/kuconfig/master.svg?label=master\n[travis-url]: https://travis-ci.org/seancheung/kuconfig\n\n[中文](https://github.com/seancheung/kuconfig/blob/master/README.zh.md)\n\n## Install\n\n```bash\nnpm i kuconfig\n```\n\n## Basic Usage\n\nThis package by default reads the _config_ folder in your working directory and merge all json files in it into one object, with each file name(without extension) being key and corresponding content being value:\n\n-   config\n    -   app.json\n    -   database.json\n    -   language.json\n\nLoaded as\n\n```json\n{\n    \"app\": {\n        /** content of app.json **/\n    },\n    \"database\": {\n        /** content of database.json **/\n    },\n    \"language\": {\n        /** content of language.json **/\n    }\n}\n```\n\n```javascript\nconst config = require('kuconfig');\nconsole.log(config.app.name);\nconsole.log(config.database.mysql.host);\nconsole.log(config.language.supported[0]);\n```\n\nIf folder _config_ does not exist, file _config.json_ will be checked instead.\n\n-   config.json\n\n```json\n{\n    \"app\": {\n        \"name\": \"MY APP\"\n    }\n}\n```\n\n```javascript\nconst config = require('kuconfig');\nconsole.log(config.app.name);\n```\n\nYou can override the config file path with an environment variable `CONFIG_FILE`(must be set before this module being loaded):\n\n```javascript\n// read a folder\nprocess.env.CONFIG_FILE = 'src/config';\n// read a file\nprocess.env.CONFIG_FILE = 'src/config.json';\n// with absolute path\nprocess.env.CONFIG_FILE = '/path/to/src/config.json';\nconst config = require('kuconfig');\nconsole.log(config.name);\n```\n\nIt won't be loaded again once done. To reload configs, you need to call:\n\n```javascript\n// delete cached config\nconfig.__.desolve();\n// reload\nconfig = require('kuconfig');\n```\n\n## Envs Mode\n\n```javascript\nrequire('kuconfig/override');\n```\n\n\u003e For esmodule style use `import config from 'kuconfig/override.js'` instead\n\nIn this mode, the `config/default.json` is loaded, followed by `config/xxx.json`(where `xxx` is equal to `process.env.NODE_ENV`). Then a deep merge of those two objects happends.\n\n_src/default.json_\n\n```json\n{\n    \"app\": {\n        \"name\": \"myapp\",\n        \"host\": \"localhost\"\n    }\n}\n```\n\n_src/development.json_\n\n```json\n{\n    \"app\": {\n        \"port\": 8080,\n        \"host\": \"myhost\"\n    }\n}\n```\n\n```javascript\nprocess.env.NODE_ENV = 'development';\nconst config = require('kuconfig/override');\n```\n\nThis merges config files to\n\n```json\n{\n    \"app\": {\n        \"name\": \"myapp\",\n        \"port\": 8080,\n        \"host\": \"myhost\"\n    }\n}\n```\n\n## Env File(optional)\n\nBy default, This package reads a _.env_ file in your working directory and gets extra environment variables from this file.\n\n```bash\nNODE_ENV=production\nCONFIG_FILE=src/config.json\n```\n\nYou may override this behaviour by passing the following environment variable:\n\n```javascript\nprocess.env.ENV_FILE = 'src/.env';\nconst config = require('kuconfig');\n```\n\nYou may optionally set `ENV_INJECT` to inject env file variables into `process.env`.\n\n**Existing environment variables won't be overrided.**\n\n```bash\nprocess.env.ENV_INJECT='true'\nNODE_ENV=development npm start\n```\n\n```plain\n# NODE_ENV won't be set because it already exists\nNODE_ENV=production\nCONFIG_FILE=src/config.json\n```\n\n## Smart Config File\n\nA bunch of **keywords** can be used in config files. The syntax is similar to mongodb query. Nested syntax is supported(they will be resolved inner to outer)\n\n```json\n{\n    \"name\": {\n        \"$env\": \"APP_NAME\"\n    },\n    \"database\": {\n        \"port\": {\n            \"$env\": [\"DB_PORT\", 3306]\n        },\n        \"host\": {\n            \"$env\": [\"DB_HOST\", \"localhost\"]\n        },\n        \"username\": {\n            \"$env\": \"DB_USER\"\n        },\n        \"password\": {\n            \"$env\": [\"DB_PASS\", { \"$env\": \"DB_USER\" }]\n        }\n    }\n}\n```\n\nThe `$env` object reads environment varaibles with an optional fallback value. With the following env set:\n\n```plain\nAPP_NAME=myapp\nDB_HOST=10.10.10.100\nDB_USER=admin\n```\n\nThe loaded config will be\n\n```json\n{\n    \"name\": \"myapp\",\n    \"database\": {\n        \"port\": 3306,\n        \"host\": \"10.10.10.100\",\n        \"username\": \"admin\",\n        \"password\": \"admin\"\n    }\n}\n```\n\nHere is a list of available **keywords**:\n\n**\\$env**\n\nGet value from environment variables(first try env file, then process.env) with an optional fallback value\n\n-   params: `string`|`[string, any]`\n-   returns `any`\n\n**\\$var**\n\nGet value from env file with an optional fallback value\n\n-   params: `string`|`[string, any]`\n-   returns `any`\n\n**\\$path**\n\nResolve the path to absolute from current working directory\n\n-   params: `string`\n-   returns `string`\n\n**\\$file**\n\nResolve the path and read the file with an optional encoding\n\n-   params: `string`|`[string, string]`\n-   returns `string`|`Buffer`\n\n**\\$json**\n\nParse the given string into object\n\n-   params: `string`\n-   returns `any`\n\n**\\$number**\n\nParse the given string into a number\n\n-   params: `string`|`number`\n-   returns `number`\n\n**\\$concat**\n\nConcat strings or arrays\n\n-   params: `string[]`|`[][]`\n-   returns `string`|`any[]`\n\n**\\$max**\n\nReturn the max number in the array\n\n-   params: `number[]`\n-   returns `number`\n\n**\\$min**\n\nReturn the min number in the array\n\n-   params: `number[]`\n-   returns `number`\n\n**\\$sum**\n\nSum the numbers in the array\n\n-   params: `number[]`\n-   returns `number`\n\n**\\$avg**\n\nReturn the average value of the array\n\n-   params: `number[]`\n-   returns `number`\n\n**\\$first**\n\nReturn the first element in the array\n\n-   params: `any[]`\n-   returns `any`\n\n**\\$last**\n\nReturn the last element in the array\n\n-   params: `any[]`\n-   returns `any`\n\n**\\$at**\n\nReturn element in the array at the given index\n\n-   params: `[any[], number]`\n-   returns `any`\n\n**\\$asce**\n\nSort the numbers in ascending order\n\n-   params: `number[]`\n-   returns `number[]`\n\n**\\$asce**\n\nSort the numbers in descending order\n\n-   params: `number[]`\n-   returns `number[]`\n\n**\\$rand**\n\nReturn an element at random index\n\n-   params: `any[]`\n-   returns `any`\n\n**\\$rands**\n\nReturn the given amount of elements at random indices\n\n-   params: `[any[], number]`\n-   returns `any[]`\n\n**\\$reverse**\n\nReverse an array\n\n-   params: `any[]`\n-   returns `any[]`\n\n**\\$slice**\n\nSlice an array from the given index to an optional end index\n\n-   params: `[any[], number]`|`[any[], number, number]`\n-   returns `any[]`\n\n**\\$count**\n\nReturn the length of an array\n\n-   params: `any[]`\n-   returns `number`\n\n**\\$join**\n\nJoin an array to string with an optional separator\n\n-   params: `[any[]]`|`[any[], string]`\n-   returns `string`\n\n**\\$merge**\n\nReturn the merge of two objects\n\n-   params: `[any, any]`\n-   returns `any`\n\n**\\$keys**\n\nReturn the keys of an object\n\n-   params: `any`\n-   returns `string[]`\n\n**\\$vals**\n\nReturn the values of an object\n\n-   params: `any`\n-   returns `any[]`\n\n**\\$zip**\n\nMerge a series of key-value pairs into an object\n\n-   params: `[any, any][]`\n-   returns `any`\n\n**\\$zap**\n\nSplit an object into key-value pairs\n\n-   params: `any`\n-   returns `[any, any][]`\n\n**$cond/$if**\n\nReturn the second or third element based on the boolean value of the first element\n\n-   params: `[boolean, any, any]`\n-   returns `any`\n\n**\\$and/\u0026\u0026**\n\nReturn true only if both two elements' boolean values are true\n\n-   params: `[boolean, boolean]`\n-   returns `boolean`\n\n**\\$or/||**\n\nReturn true if any of the two elements' boolean value is true\n\n-   params: `[boolean, boolean]`\n-   returns `boolean`\n\n**\\$not**\n\nReturn true only if the given value is false\n\n-   params: `boolean`\n-   returns `boolean`\n\n**\\$true**\n\nReturn true if the given value is true or 'true'(case insensitive) or 1 or '1'\n\n-   params: `boolean|string`\n-   returns `boolean`\n\n**\\$null**\n\nReturn true if the given value is null or undefined\n\n-   params: `any`\n-   returns `boolean`\n\n**\\$undefined**\n\nReturn true only if the given value is undefined\n\n-   params: `any`\n-   returns `boolean`\n\n**\\$type**\n\nReturn true only if the given value is of the given type\n\n-   params: `[any, string]`\n-   returns `boolean`\n\n**\\$test|!!**\n\nReturn boolean test result(!!) of the given value\n\n-   params: `[any, string]`\n-   returns `boolean`\n\n**\\$upper**\n\nTransform input string to upper case\n\n-   params: `string`\n-   returns `string`\n\n**\\$lower**\n\nTransform input string to lower case\n\n-   params: `string`\n-   returns `string`\n\n**\\$split**\n\nSplit input string into an array with optional delimiter and/or limit\n\n-   params: `string|[string, string]|[string, string, number]`\n-   returns `string[]`\n\n**\\$expand**\n\nExpand variables as in shellscript\n\n-   params: `string`\n-   returns `string`\n\n**\\$regex**\n\nTransform string to regex with optional flags\n\n-   params: `string|[string, string]`\n-   returns `RegExp`\n\n### Other Keywords\n\n**Operators**\n\n$abs, $add(+), $sub(-), $mul(\\*), $div(/), $mod(%), $ceil, $floor, $round, $trunc, \\$sign\n\n**Comparers**\n\n$gt(\u003e), $gte(\u003e=), $lt(\u003c), $lte(\u003c=), $eq(===), $eql(==), $ne(!==), $neql(!=), $in, $ni\n\n### Skip Parsing\n\nTo skip parsing a file or a part of a file, use **\\$skip** option:\n\n```json\n{\n    \"$skip\": true,\n    \"key\": {\n        \"$env\": \"APP_KEY\"\n    }\n}\n```\n\nThe loaded file will be\n\n```json\n{\n    \"key\": {\n        \"$env\": \"APP_KEY\"\n    }\n}\n```\n\n## Utils\n\nA utils object is attached to each config instance. You can acces it by the getter `__`:\n\n```javascript\n// make a deep cloned copy\nconst copy = config.__.clone(obj);\n\n// merge target object's copy into source object's copy deeply\nconst merged = config.__.merge(source, target);\n\n// load environment variables, optionally inject them into process.env\nconst envs = config.__.env('./.env', true);\n\n// parse config by json string\nlet conf = config.__.resolve(\n    JSON.parse(fs.readFileSync('./config.json', 'utf8')),\n    envs\n);\n\n// load config by path(absolute or relative to working directory)\nconf = config.__.load('./config.json');\n\n// delete config referenced cache(the next time you reference this module, config file will be reloaded)\nconfig.__.desolve();\n\n// parse config with custom expressions\nconfig.__.parse(\n    {\n        $encode(params) {\n            if (params == null) {\n                return params;\n            }\n            if (typeof params === 'string') {\n                return encodeURI(params);\n            }\n            throw new Error('$encode expects a string');\n        }\n    },\n    {\n        url: {\n            $encode: 'this is a test'\n        }\n    },\n    envs\n);\n\n// Expand variables as in shellscript\nconfig.__.substitute('Today is ${date} and I am ${name}.', {\n    date: new Date(),\n    name: 'Adam'\n});\n// To support dynamic code execution(using v8 vm module)\nconfig.__.substitute(\n    'I am ${age} years old and I will be ${age + 1} next year. You can call me ${profile.name}.',\n    {\n        age: 17,\n        profile: {\n            name: 'Tom'\n        }\n    },\n    true\n);\n```\n\nYou can also use utils without the config instance:\n\n```javascript\nconst utils = require('kuconfig/utils');\n// NOTE: utils.desolve will be undefined\n```\n\n## Plugins\n\nIf this module is used in a front-end project, the loading will happen in bundling step. A parsed config object will be injected to the output bundle. Accessing the config object at runtime is nothing difference to accessing a plain object.\n\n### Webpack\n\nTo integrate into webpack, there is a built-in plugin:\n\n```javascript\nconst KuconfigPlugin = require('kuconfig/plugins/webpack');\n```\n\n_webpack.config.js_\n\n```javascript\nplugins: [new KuconfigPlugin()];\n```\n\nUsage in your modules:\n\n```javascript\nimport * as config from 'kuconfig';\n```\n\nUse envs mode\n\n```javascript\nplugins: [new KuconfigPlugin({ mode: 'envs' })];\n```\n\n### Vite\n\n\u003e Same as Webpack integration, the loaded object will be a plain object at run time.\n\n```javascript\nimport kuconfig from 'kuconfig/plugins/vite';\n```\n\n_vite.config.js_\n\n```javascript\n{\n    optimizeDeps: {\n        exclude: ['kuconfig']\n    },\n    plugins: [kuconfig()]\n}\n```\n\nUsage in your modules:\n\n```javascript\nimport config from 'kuconfig';\n```\n\nUse envs mode\n\n```javascript\n{\n    optimizeDeps: {\n        exclude: ['kuconfig']\n    },\n    plugins: [kuconfig({ mode: 'envs' })]\n}\n```\n\n### Metro(React Native)\n\n\u003e Same as Webpack integration, the loaded object will be a plain object at run time.\n\nA metro babel transformer is provided:\n\n_metro.config.js_\n\n```javascript\nmodule.exports = {\n    transformer: {\n        babelTransformerPath: require.resolve('kuconfig/plugins/metro')\n    }\n};\n```\n\n**With other transformers**\n\n_transformers.js_\n\n```javascript\nconst svgTransformer = require('react-native-svg-transformer');\nconst configTransformer = require('kuconfig/plugins/metro');\n\nmodule.exports.getCacheKey = configTransformer.getCacheKey;\nmodule.exports.transform = function ({ src, filename, options }) {\n    if (filename.endsWith('.svg')) {\n        return svgTransformer.transform({ src, filename, options });\n    } else {\n        return configTransformer.transform({ src, filename, options });\n    }\n};\n```\n\n_metro.config.js_\n\n```javascript\nconst { assetExts, sourceExts } = require('metro-config/src/defaults/defaults');\n\nmodule.exports = {\n    transformer: {\n        getTransformOptions: () =\u003e ({\n            transform: {\n                experimentalImportSupport: false,\n                inlineRequires: false\n            }\n        }),\n        babelTransformerPath: require.resolve('./transformer.js')\n    },\n    resolver: {\n        assetExts: assetExts.filter(ext =\u003e ext !== 'svg'),\n        sourceExts: [...sourceExts, 'svg']\n    }\n};\n```\n\nUsage:\n\n```javascript\nimport * as config from 'kuconfig';\nimport * as config from 'kuconfig/override';\n```\n\n\u003e config file cannot be hot-reloaded, you must re-run `npm start` to make the changes to take effect\n\n## Using Typescript\n\nBy default the imported config object implements `Record\u003cstring, any\u003e`.\nYou can add a typing file to your project to overwite `kuconfig` module:\n\n_kuconfig.d.ts_\n\n```typescript\ndeclare module 'kuconfig' {\n    /**\n     * This interface will be merged with default Config interface\n     */\n    interface Config {\n        /**\n         * Here is the definition of your config\n         */\n        readonly name: string;\n        /**\n         * nested config\n         */\n        readonly db: Readonly\u003cConfig.DB\u003e;\n    }\n    namespace Config {\n        interface DB {\n            readonly host: string;\n            readonly port: number;\n        }\n    }\n}\n// don't miss this line\nexport {};\n```\n\nThe corresponding config file structure:\n\n```json\n{\n    \"name\": \"myapp\",\n    \"db\": {\n        \"host\": \"localhost\",\n        \"port\": 3306\n    }\n}\n```\n\n## Test\n\n```bash\nnpm test\n```\n\n## License\n\nSee [License](https://github.com/seancheung/kuconfig/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseancheung%2Fkuconfig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseancheung%2Fkuconfig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseancheung%2Fkuconfig/lists"}