Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./node_modules/@kaliber/eslint-plugin/.eslintrc",
"rules": {
"@kaliber/no-relative-parent-import": "off",
"import/no-unresolved": "off"
},
"settings": {
"@kaliber/eslint-plugin/lib/absolute-path-resolver-plugin": null
}
}
3 changes: 2 additions & 1 deletion bin/get-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ try {

const load = require('../load')
const config = load(configEnv)
const result = path.split('.').reduce((result, part) => result[part], config)
const result = path.split('.').reduce((result, part) => result[part], /** @type {any} */ (config))
process.stdout.write(result)
process.exit(0)
} catch (e) {
exit(e)
}

/** @arg {any} e */
function exit(e) {
console.error(e)
process.exit(1)
Expand Down
4 changes: 4 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const load = require('./load')

module.exports = load(configEnv)

/**
* @arg {string} error
* @returns {never}
*/
function exit(error) {
console.error(error)
process.exit(1)
Expand Down
52 changes: 44 additions & 8 deletions load.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
const { resolve } = require('path')
const fs = require('fs')
const { resolve } = require('node:path')
const fs = require('node:fs')

module.exports = function load(configEnv) {
module.exports = load

/**
* @arg {string} configEnv
* @returns {unknown}
*/
function load(configEnv) {
const configDir = resolve(process.cwd(), 'config')
const configFiles = [
{ name: 'default', required: false },
{ name: configEnv, required: true },
{ name: 'local' , required: false }
{ name: 'local', required: false }
]

return configFiles.reduce(
Expand All @@ -16,19 +22,22 @@ module.exports = function load(configEnv) {

if (exists) {
let config
try { config = require(configFile) }
catch (e) { exit(e) }
try { config = require(configFile) } catch (e) { exit(e) }

return mergeDeep(result, config)
} else {
if (required) exit(`Could not find configuration for '${name}'`)
if (required) return exit(`Could not find configuration for '${name}'`)
else return result
}
},
{}
/** @type {Record<string, any>} */ ({})
)
}

/**
* @arg {Record<string, any>} target
* @arg {Record<string, any>} source
*/
function mergeDeep(target, source) {
return Object.keys(source).reduce((result, key) => {
const targetValue = result[key]
Expand All @@ -46,17 +55,44 @@ function mergeDeep(target, source) {
}, target)
}

/**
* @arg {any} error
* @returns {never}
*/
function exit(error) {
console.error(error)
process.exit(1)
}

/**
* @template A
* @template B
* @arg {A} x
* @arg {B} y
* @returns {x is B}
*/
function canMerge(x, y) { return (isObject(x) && isObject(y)) || (isArray(x) && isArray(y)) }
/**
* @arg {any} x
* @returns {x is Record<string, any> | Array<any>}
*/
function shouldClone(x) { return isObject(x) || isArray(x) }
/**
* @arg {any} x
* @returns {x is Record<string, any>}
*/
function isObject(x) {
const constructor = getConstructor(x)
return constructor && constructor instanceof constructor
}
Comment on lines 84 to 87
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid shadowing the global constructor name.
This trips lint (noShadowRestrictedNames) and is easy to fix by renaming the local variable.

🔧 Proposed fix
 function isObject(x) {
-  const constructor = getConstructor(x)
-  return constructor && constructor instanceof constructor
+  const ctor = getConstructor(x)
+  return ctor && ctor instanceof ctor
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function isObject(x) {
const constructor = getConstructor(x)
return constructor && constructor instanceof constructor
}
function isObject(x) {
const ctor = getConstructor(x)
return ctor && ctor instanceof ctor
}
🧰 Tools
🪛 Biome (2.1.2)

[error] 85-85: Do not shadow the global "constructor" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🤖 Prompt for AI Agents
In `@load.js` around lines 84 - 87, The local variable named "constructor" in
function isObject shadows the global constructor and violates
noShadowRestrictedNames; rename it (e.g., to "ctor" or "cons") by changing const
constructor = getConstructor(x) to const ctor = getConstructor(x) and update the
subsequent check (replace uses of "constructor" with "ctor") so the function
isObject and the call to getConstructor(x) use the new name consistently.

/**
* @arg {any} x
* @returns {x is Array<any>}
*/
function isArray(x) { return Array.isArray(x) }
/** @arg {any} x */
function getConstructor(x) { return isObjectLike(x) && Object.getPrototypeOf(x).constructor }
/**
* @arg {any} x
*/
function isObjectLike(x) { return typeof x === 'object' && x !== null }
16 changes: 15 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
{
"version": "0.0.8",
"version": "0.9.9",
"name": "@kaliber/config",
"main": "index.js",
"description": "Zero dependency, minimal configuration library operating on CONFIG_ENV",
"type": "commonjs",
"publishConfig": {
"access": "public"
},
"files": [
"index.js",
"load.js",
"README.md",
"bin/get-config.js"
],
"scripts": {
"test": "node test/index.js"
},
Expand All @@ -19,5 +29,9 @@
"license": "MIT",
"bugs": {
"url": "https://github.com/kaliberjs/config/issues"
},
"devDependencies": {
"@kaliber/eslint-plugin": "^1.0.0",
"@types/node": "^22.0.0"
}
}
Loading