Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/use-getenv-package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'lino-arguments': patch
---

Replace custom getenv implementation with official npm package. Now uses the robust `getenv` package for type casting and validation, enhanced with case-insensitive lookup across multiple naming conventions. Also enforces stricter no-unused-vars linting with catch { } syntax.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ const config = makeConfig({

Smart environment variable lookup with type preservation and case conversion.

**Built on [getenv](https://www.npmjs.com/package/getenv):** This function uses the official `getenv` npm package internally for robust type casting and validation, enhanced with case-insensitive lookup across multiple naming conventions.

**Parameters:**

- `name` (string): Environment variable name (any case format)
Expand All @@ -125,10 +127,10 @@ getenv('apiKey', ''); // camelCase
getenv('api-key', ''); // kebab-case
getenv('api_key', ''); // snake_case

// Type preservation:
getenv('PORT', 3000); // Returns number
getenv('DEBUG', false); // Returns boolean
getenv('API_KEY', ''); // Returns string
// Type preservation (powered by getenv package):
getenv('PORT', 3000); // Returns number (uses getenv.int())
getenv('DEBUG', false); // Returns boolean (uses getenv.boolish())
getenv('API_KEY', ''); // Returns string (uses getenv.string())
```

### Case Conversion Utilities
Expand Down Expand Up @@ -351,6 +353,7 @@ npm run changeset:status
- [links-notation](https://github.com/link-foundation/links-notation) - Links Notation parser
- [lino-env](https://github.com/link-foundation/lino-env) - .lenv file operations
- [test-anywhere](https://github.com/link-foundation/test-anywhere) - Universal JavaScript testing
- [getenv](https://www.npmjs.com/package/getenv) - Environment variable helper with type casting (used internally)

## License

Expand Down
9 changes: 1 addition & 8 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,7 @@ export default [
'prettier/prettier': 'error',

// Code quality rules
'no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
'no-unused-vars': 'error', // No exceptions - use catch { } for ignored errors
'no-console': 'off', // Allow console in this project
'no-debugger': 'error',

Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"node": ">=20.0.0"
},
"dependencies": {
"getenv": "^2.0.0",
"links-notation": "^0.11.2",
"lino-env": "^0.2.6",
"yargs": "^17.7.2"
Expand Down
2 changes: 1 addition & 1 deletion scripts/format-release-notes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ try {
if (relevantPr) {
prNumber = relevantPr.number;
}
} catch (_error) {
} catch {
console.log('⚠️ Could not find PR for commit', commitHash);
}

Expand Down
47 changes: 25 additions & 22 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Parser } from 'links-notation';
import { LinoEnv } from 'lino-env';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import baseGetenv from 'getenv';

/**
* lino-arguments - A unified configuration library
Expand Down Expand Up @@ -108,7 +109,8 @@ export function toPascalCase(str) {

/**
* Get environment variable with default value and case conversion
* Tries multiple case formats to find the variable
* Uses the official getenv npm package internally, with enhanced case-insensitive lookup.
* Tries multiple case formats to find the variable.
*
* @param {string} key - Variable name (any case format)
* @param {string|number|boolean} [defaultValue=''] - Default value if not found
Expand All @@ -130,29 +132,30 @@ export function getenv(key, defaultValue = '') {
toPascalCase(key), // PascalCase
];

// Try to find the variable using any case variant
for (const variant of variants) {
if (process.env[variant] !== undefined) {
const value = process.env[variant];

// If default is a number, try to parse the env value as a number
if (typeof defaultValue === 'number') {
const parsed = Number(value);
return isNaN(parsed) ? defaultValue : parsed;
}

// If default is a boolean, try to parse the env value as a boolean
if (typeof defaultValue === 'boolean') {
if (value.toLowerCase() === 'true') {
return true;
// Use the official getenv package based on the type of defaultValue
try {
if (typeof defaultValue === 'number') {
// Use getenv.int or getenv.float
const isFloat = !Number.isInteger(defaultValue);
return isFloat
? baseGetenv.float(variant, defaultValue)
: baseGetenv.int(variant, defaultValue);
}
if (value.toLowerCase() === 'false') {
return false;

if (typeof defaultValue === 'boolean') {
// Use getenv.boolish for flexible boolean parsing
return baseGetenv.boolish(variant, defaultValue);
}

// Otherwise use getenv.string
return baseGetenv.string(variant, defaultValue);
} catch {
// If getenv throws, return the default value
return defaultValue;
}

// Otherwise return as string
return value;
}
}

Expand All @@ -174,7 +177,7 @@ function loadLinoEnv(filePath = '.lenv') {
const env = new LinoEnv(filePath);
env.read();
return env;
} catch (_error) {
} catch {
return null;
}
}
Expand Down Expand Up @@ -247,7 +250,7 @@ async function loadDotenvx(options = {}) {
try {
const dotenvx = await import('@dotenvx/dotenvx');
return dotenvx.config({ ...options, quiet: true });
} catch (_error) {
} catch {
if (!quiet) {
console.error('⚠️ dotenvx not installed, skipping .env loading');
}
Expand Down Expand Up @@ -344,7 +347,7 @@ export function makeConfig(config = {}) {
let initialParsed;
try {
initialParsed = initialYargs.parseSync();
} catch (_error) {
} catch {
initialParsed = {};
}

Expand Down Expand Up @@ -419,7 +422,7 @@ export function parseLinoArguments(linoString) {
return args.filter(
(arg) => arg && arg.trim() && !arg.trim().startsWith('#')
);
} catch (_error) {
} catch {
return linoString
.split('\n')
.map((line) => line.trim())
Expand Down