A JavaScript library to operate .lenv files - an alternative to .env files that uses : (colon-space) instead of = for key-value separation and supports duplicate keys.
.lenv files are configuration files similar to .env files, but with a different syntax:
# .env format (traditional)
GITHUB_TOKEN=gh_...
API_KEY=abc123
# .lenv format (this library)
GITHUB_TOKEN: gh_...
API_KEY: abc123
The key difference is the use of : separator, which aligns with links-notation format. Additionally, .lenv files support duplicate keys, where multiple instances of the same key can exist.
npm install lino-env# create .lenv file
echo "HELLO: World" > .lenv
# create index.js
echo "import linoenv from 'lino-env'; linoenv.config(); console.log('Hello ' + process.env.HELLO)" > index.js
# run
node index.jsOutput:
Hello World
import linoenv from 'lino-env';
linoenv.config();
console.log(`Hello ${process.env.HELLO}`);require('lino-env').config();
console.log(`Hello ${process.env.HELLO}`);These functions provide a simple API similar to dotenvx for common use cases:
Load .lenv file and inject into process.env
import linoenv from 'lino-env';
linoenv.config(); // loads .lenv
// or specify a custom path
linoenv.config({ path: '.lenv.production' });Returns: { parsed: Object } - Object containing parsed key-value pairs
Get a value from the loaded .lenv file
import linoenv from 'lino-env';
const value = linoenv.get('API_KEY');
// or from a specific file
const value = linoenv.get('API_KEY', { path: '.lenv.production' });Returns: string | undefined
Set a value in a .lenv file
import linoenv from 'lino-env';
linoenv.set('API_KEY', 'new_value');
// or to a specific file
linoenv.set('API_KEY', 'new_value', { path: '.lenv.production' });You can also use named exports for tree-shaking:
import { config, get, set } from 'lino-env';
config();
console.log(get('HELLO'));
set('HELLO', 'Universe');The main class for reading and writing .lenv files.
import { LinoEnv } from 'lino-env';
const env = new LinoEnv('.lenv');Reads and parses the .lenv file. If the file doesn't exist, initializes with empty data.
const env = new LinoEnv('.lenv');
env.read();Returns: this (for method chaining)
Writes the current data back to the .lenv file.
env.set('API_KEY', 'value').write();Returns: this (for method chaining)
Gets the last instance of a reference (key).
env.add('API_KEY', 'value1');
env.add('API_KEY', 'value2');
console.log(env.get('API_KEY')); // 'value2'Returns: string | undefined
Gets all instances of a reference (key).
env.add('API_KEY', 'value1');
env.add('API_KEY', 'value2');
console.log(env.getAll('API_KEY')); // ['value1', 'value2']Returns: string[]
Sets a reference to a single value, replacing all existing instances.
env.set('API_KEY', 'new_value');Returns: this (for method chaining)
Adds a new instance of a reference, allowing duplicates.
env.add('API_KEY', 'value1');
env.add('API_KEY', 'value2'); // Now there are 2 instancesReturns: this (for method chaining)
Checks if a reference exists.
if (env.has('API_KEY')) {
console.log('API_KEY exists');
}Returns: boolean
Deletes all instances of a reference.
env.delete('API_KEY');Returns: this (for method chaining)
Gets all keys.
console.log(env.keys()); // ['GITHUB_TOKEN', 'API_KEY', ...]Returns: string[]
Converts to a plain object with the last instance of each key.
env.add('KEY1', 'value1a');
env.add('KEY1', 'value1b');
env.set('KEY2', 'value2');
console.log(env.toObject());
// { KEY1: 'value1b', KEY2: 'value2' }Returns: Object
Convenience function to read a .lenv file.
import { readLinoEnv } from 'lino-env';
const env = readLinoEnv('.lenv');
console.log(env.get('GITHUB_TOKEN'));Returns: LinoEnv
Convenience function to create and write a .lenv file from an object.
import { writeLinoEnv } from 'lino-env';
writeLinoEnv('.lenv', {
API_KEY: 'test_key',
SECRET: 'test_secret',
});Returns: LinoEnv
import { LinoEnv } from 'lino-env';
// Create and write
const env = new LinoEnv('.lenv');
env.set('GITHUB_TOKEN', 'gh_test123');
env.set('TELEGRAM_TOKEN', '054test456');
env.write();
// Read
const env2 = new LinoEnv('.lenv');
env2.read();
console.log(env2.get('GITHUB_TOKEN')); // 'gh_test123'import { LinoEnv } from 'lino-env';
const env = new LinoEnv('.lenv');
// Add multiple instances of the same key
env.add('SERVER', 'server1.example.com');
env.add('SERVER', 'server2.example.com');
env.add('SERVER', 'server3.example.com');
// Get the last one
console.log(env.get('SERVER')); // 'server3.example.com'
// Get all instances
console.log(env.getAll('SERVER'));
// ['server1.example.com', 'server2.example.com', 'server3.example.com']
env.write(); // Persist to fileimport { LinoEnv } from 'lino-env';
new LinoEnv('.lenv').set('API_KEY', 'abc123').set('SECRET', 'xyz789').write();The library correctly handles values with colons, spaces, and other special characters:
env.set('URL', 'https://example.com:8080');
env.set('MESSAGE', 'Hello World');
env.write();
const env2 = readLinoEnv('.lenv');
console.log(env2.get('URL')); // 'https://example.com:8080'
console.log(env2.get('MESSAGE')); // 'Hello World'.lenv files use the following format:
- Key-value separator:
:(colon followed by space) - One key-value pair per line
- Empty lines and lines starting with
#are ignored - Duplicate keys are allowed
- Values can contain spaces, colons, and other special characters
Example .lenv file:
# Configuration file
GITHUB_TOKEN: gh_abc123xyz
TELEGRAM_TOKEN: 054test456
# Multiple servers
SERVER: server1.example.com
SERVER: server2.example.com
# Values with special characters
URL: https://example.com:8080
MESSAGE: Hello World
This project is released into the public domain under The Unlicense.