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
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ The full line-by-line construction is in [`examples/threat-model.md` § 5](./exa

## Installation

### From npm (recommended)

```bash
npm install -g envault
```
Expand All @@ -161,10 +163,23 @@ Or run it without installing:
npx envault@^0.2.0 init
```

Or grab the prebuilt single-file bundle from the [releases page](https://github.com/wardsvelds2l/envault/releases) — `dist/envault.js` is one self-contained file, no `node_modules` needed at runtime.

Requires Node.js 20.0 or newer (we test 20 and 22 in CI on Ubuntu, macOS, and Windows).

### From source (local development)

```bash
git clone https://github.com/wardsvelds2l/envault.git
cd envault
npm install
npm run bundle # builds dist/envault.js
npm link # makes `envault` available globally
envault --help
```

`dist/envault.js` is one self-contained file — no `node_modules` needed at runtime. You can also grab a prebuilt bundle from the [releases page](https://github.com/wardsvelds2l/envault/releases).

After `npm link`, all `envault` commands used throughout this README work as written. To unlink later, run `npm unlink -g envault`.

## Quick start

```bash
Expand Down
7 changes: 6 additions & 1 deletion __tests__/commands/add.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ describe('add command', () => {
vaultPath = path.join(tmpDir, '.env.vault');
originalEnvPassword = process.env['ENVVAULT_PASSWORD'];
process.env['ENVVAULT_PASSWORD'] = TEST_PASSWORD;
// Pre-create vault with fast test KDF so addCommand doesn't use
// production-grade Argon2id params (which timeout in CI coverage runs).
writeVault(vaultPath, createVault(TEST_KDF));
});

afterEach(() => {
Expand All @@ -36,7 +39,9 @@ describe('add command', () => {
passwordPrompt: false,
});

it('creates a vault if none exists and adds a variable', async () => {
it('creates a vault if none exists and adds a variable', { timeout: 60000 }, async () => {
// Remove pre-created test vault so addCommand exercises the "create" path.
fs.rmSync(vaultPath, { force: true });
await addCommand('FOO=bar', {}, opts());
const v = readVault(vaultPath);
expect(v.version).toBe(1);
Expand Down
6 changes: 5 additions & 1 deletion __tests__/commands/get.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import * as path from 'node:path';
import * as os from 'node:os';
import { addCommand } from '../../src/commands/add.js';
import { getCommand } from '../../src/commands/get.js';
import { TEST_PASSWORD } from '../helpers.js';
import { createVault, writeVault } from '../../src/vault.js';
import { TEST_KDF, TEST_PASSWORD } from '../helpers.js';
import type { GlobalOptions } from '../../src/types.js';

describe('get command', () => {
Expand All @@ -25,6 +26,9 @@ describe('get command', () => {
stdout.push(typeof chunk === 'string' ? chunk : chunk.toString());
return true;
}) as typeof process.stdout.write;
// Pre-create vault with fast test KDF so addCommand doesn't use
// production-grade Argon2id params (which timeout in CI coverage runs).
writeVault(vaultPath, createVault(TEST_KDF));
await addCommand('FOO=bar', {}, opts());
await addCommand('EMPTY=', {}, opts());
await addCommand('WITH_NEWLINE=line1\nline2', {}, opts());
Expand Down
Loading