npm package: @hiscojs/dotenv-updater
Description: Type-safe .env file parser and updater with formatting preservation, comment handling, and advanced value quoting
Author: hisco
Latest version: 1.0.0

# @hiscojs/dotenv-updater

Type-safe .env file parser and updater with formatting preservation, comment handling, and advanced value quoting.

## Installation

```bash
npm install @hiscojs/dotenv-updater
```

## Quick Start

```typescript
import { parse, editInString } from '@hiscojs/dotenv-updater';

// Parse .env content
const envContent = `
DATABASE_URL=postgres://localhost
API_KEY="secret-key"
DEBUG=true
`;

const parsed = parse(envContent);
// { DATABASE_URL: 'postgres://localhost', API_KEY: 'secret-key', DEBUG: 'true' }

// Update .env content
const updated = editInString(envContent, {
  DATABASE_URL: 'postgres://production',
  API_KEY: 'new-secret',
  NEW_VAR: 'new-value'
});
```

## Features

- **Parse .env files**: Convert .env file content to JavaScript objects
- **Update .env files**: Modify .env content while preserving formatting
- **Preserve comments**: Comments and empty lines are maintained
- **Smart quoting**: Automatically quotes values based on content (newlines, special chars)
- **Remove unused keys**: Keys not in the update object are removed
- **Handle invalid lines**: Gracefully handles lines without `=` signs
- **Type-safe**: Full TypeScript support

## API Reference

### `parse(src: string): Record<string, string | undefined>`

Parse a .env file content string into a key-value object.

**Parameters:**
- `src` - The .env file content as a string

**Returns:**
- An object with environment variable keys and values

**Example:**
```typescript
const envContent = `
DATABASE_URL=postgres://localhost
API_KEY="secret-key"
DEBUG=true
`;

const parsed = parse(envContent);
// {
//   DATABASE_URL: 'postgres://localhost',
//   API_KEY: 'secret-key',
//   DEBUG: 'true'
// }
```

### `editInString(src: string, object: Record<string, string | undefined>): string`

Update a .env file content string with new values while preserving formatting, comments, and structure.

**Features:**
- Preserves comments and empty lines
- Maintains original indentation and spacing
- Removes keys not present in the updates object
- Adds new keys at the end
- Intelligently quotes values based on their content

**Parameters:**
- `src` - The original .env file content
- `object` - An object with keys to update/add and their new values

**Returns:**
- The updated .env file content

**Example:**
```typescript
const original = `
# Database configuration
DATABASE_URL=localhost
API_KEY=old-key
UNUSED_KEY=will-be-removed
`;

const updates = {
  DATABASE_URL: 'production-db',
  API_KEY: 'new-key',
  NEW_SETTING: 'value'
};

const result = editInString(original, updates);
// Result:
// # Database configuration
// DATABASE_URL=production-db
// API_KEY=new-key
// NEW_SETTING=value
```

## Usage Examples

### Basic Parsing

```typescript
import { parse } from '@hiscojs/dotenv-updater';

const content = `
PORT=3000
HOST=localhost
DEBUG=true
`;

const env = parse(content);
console.log(env.PORT); // '3000'
console.log(env.HOST); // 'localhost'
console.log(env.DEBUG); // 'true'
```

### Updating Environment Variables

```typescript
import { editInString } from '@hiscojs/dotenv-updater';

const original = `
# Server configuration
PORT=3000
HOST=localhost

# Database
DB_HOST=localhost
DB_PORT=5432
`;

const updates = {
  PORT: '8080',
  HOST: '0.0.0.0',
  DB_HOST: 'production-db.example.com',
  DB_PORT: '5432',
  NEW_VAR: 'new-value'
};

const result = editInString(original, updates);
console.log(result);
// # Server configuration
// PORT=8080
// HOST=0.0.0.0
//
// # Database
// DB_HOST=production-db.example.com
// DB_PORT=5432
// NEW_VAR=new-value
```

### Handling Quoted Values

The library automatically handles different quoting styles:

```typescript
import { parse } from '@hiscojs/dotenv-updater';

const content = `
SINGLE='single quoted'
DOUBLE="double quoted"
BACKTICK=\`backtick quoted\`
UNQUOTED=no-quotes
`;

const env = parse(content);
// All values are unquoted in the result:
// {
//   SINGLE: 'single quoted',
//   DOUBLE: 'double quoted',
//   BACKTICK: 'backtick quoted',
//   UNQUOTED: 'no-quotes'
// }
```

When updating, values are automatically quoted based on content:

```typescript
import { editInString } from '@hiscojs/dotenv-updater';

const updates = {
  SIMPLE: 'simple-value',           // No quotes needed
  WITH_QUOTES: 'has "quotes"',      // Uses single quotes
  WITH_NEWLINE: 'line1\nline2',     // Uses backticks
  WITH_ALL: 'has \' and " quotes'   // Uses backticks with escaping
};

const result = editInString('', updates);
// SIMPLE=simple-value
// WITH_QUOTES='has "quotes"'
// WITH_NEWLINE=`line1
// line2`
// WITH_ALL=`has ' and " quotes`
```

### Preserving Comments

```typescript
import { editInString } from '@hiscojs/dotenv-updater';

const original = `
# Application settings
APP_NAME=myapp
APP_VERSION=1.0.0 # Current version

# Database configuration
DB_HOST=localhost # Development database
`;

const updates = {
  APP_NAME: 'myapp',
  APP_VERSION: '2.0.0',
  DB_HOST: 'production-db'
};

const result = editInString(original, updates);
// Comments are preserved:
// # Application settings
// APP_NAME=myapp
// APP_VERSION=2.0.0 # Current version
//
// # Database configuration
// DB_HOST=production-db # Development database
```

### Removing Keys

Keys not present in the updates object are automatically removed:

```typescript
import { editInString } from '@hiscojs/dotenv-updater';

const original = `
KEEP_ME=value1
REMOVE_ME=value2
ALSO_KEEP=value3
`;

const updates = {
  KEEP_ME: 'updated1',
  ALSO_KEEP: 'updated3'
};

const result = editInString(original, updates);
// KEEP_ME=updated1
// ALSO_KEEP=updated3
```

### Handling Invalid Lines

The library gracefully handles lines without equals signs:

```typescript
import { editInString } from '@hiscojs/dotenv-updater';

const original = `
VALID_KEY=value
INVALID_LINE_NO_EQUALS
ANOTHER_VALID=123
`;

const updates = {
  VALID_KEY: 'newvalue',
  INVALID_LINE_NO_EQUALS: 'fixed',
  ANOTHER_VALID: '456'
};

const result = editInString(original, updates);
// VALID_KEY=newvalue
// INVALID_LINE_NO_EQUALS=fixed
// ANOTHER_VALID=456
```

### Working with File System

```typescript
import fs from 'fs';
import { parse, editInString } from '@hiscojs/dotenv-updater';

// Read .env file
const envPath = '.env';
const content = fs.readFileSync(envPath, 'utf-8');

// Parse to get current values
const currentEnv = parse(content);
console.log('Current PORT:', currentEnv.PORT);

// Update with new values
const updates = {
  ...currentEnv,
  PORT: '8080',
  NEW_FEATURE_FLAG: 'true'
};

const updatedContent = editInString(content, updates);

// Write back to file
fs.writeFileSync(envPath, updatedContent, 'utf-8');
```

### Merging Environment Variables

```typescript
import { parse, editInString } from '@hiscojs/dotenv-updater';

const defaultEnv = `
PORT=3000
HOST=localhost
`;

const productionOverrides = {
  PORT: '80',
  HOST: '0.0.0.0',
  SSL_ENABLED: 'true'
};

// Merge defaults with overrides
const defaultParsed = parse(defaultEnv);
const merged = {
  ...defaultParsed,
  ...productionOverrides
};

const result = editInString(defaultEnv, merged);
// PORT=80
// HOST=0.0.0.0
// SSL_ENABLED=true
```

## Edge Cases

### Empty Values

```typescript
const content = `KEY1=
KEY2=value2`;

const parsed = parse(content);
// { KEY1: undefined, KEY2: 'value2' }
```

### Multiline Values

```typescript
const content = `MULTILINE=\`line1
line2
line3\``;

const parsed = parse(content);
// { MULTILINE: 'line1\nline2\nline3' }
```

### Keys with Dots and Hyphens

```typescript
const content = `
my.dotted.key=value1
my-hyphenated-key=value2
`;

const parsed = parse(content);
// {
//   'my.dotted.key': 'value1',
//   'my-hyphenated-key': 'value2'
// }
```

### Special Characters in Values

```typescript
const content = `
URL=https://example.com?foo=bar&baz=qux
EMAIL=test@example.com
PATH=/usr/local/bin:/usr/bin
`;

const parsed = parse(content);
// All special characters are preserved
```

## Comparison with Other Libraries

### vs. dotenv

- **dotenv**: Loads .env files into `process.env`, read-only
- **@hiscojs/dotenv-updater**: Parse AND update .env files, preserves formatting

### vs. dotenv-expand

- **dotenv-expand**: Expands variables in .env files
- **@hiscojs/dotenv-updater**: Updates .env file content, removes unused keys

### vs. Manual string manipulation

- **Manual**: Error-prone, doesn't preserve formatting
- **@hiscojs/dotenv-updater**: Robust parsing, formatting preservation, comment handling

## Best Practices

### 1. Always Read Before Update

```typescript
// ✅ Good - Preserves existing structure
const content = fs.readFileSync('.env', 'utf-8');
const updated = editInString(content, newVars);
fs.writeFileSync('.env', updated);

// ❌ Avoid - Loses all formatting
const updated = editInString('', newVars);
fs.writeFileSync('.env', updated);
```

### 2. Keep Comments in Original File

```typescript
// ✅ Good - Comments provide context
const original = `
# Production database
DB_HOST=prod-db.example.com
`;

// Comments are preserved when updating
```

### 3. Use Consistent Quoting

```typescript
// ✅ Good - Let the library handle quoting
const updates = {
  SIMPLE: 'value',
  COMPLEX: 'value with spaces'
};

// ❌ Avoid - Manual quoting
const updates = {
  SIMPLE: '"value"',  // Will be double-quoted
};
```

### 4. Validate Values Before Update

```typescript
// ✅ Good - Validate first
const updates = {
  PORT: isValidPort(port) ? port : '3000',
  HOST: isValidHost(host) ? host : 'localhost'
};

const result = editInString(content, updates);
```

## TypeScript Support

Full TypeScript support with type definitions included:

```typescript
import { parse, editInString } from '@hiscojs/dotenv-updater';

const content: string = fs.readFileSync('.env', 'utf-8');
const parsed: Record<string, string | undefined> = parse(content);

const updates: Record<string, string | undefined> = {
  PORT: '8080',
  HOST: 'localhost'
};

const result: string = editInString(content, updates);
```

## License

MIT

## Repository

[https://github.com/hisco/dotenv-updater](https://github.com/hisco/dotenv-updater)

## Contributing

Issues and pull requests welcome!