lockbox-vault 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -0
- package/dist/cli/env-utils.d.ts +46 -0
- package/dist/cli/env-utils.d.ts.map +1 -0
- package/dist/cli/env-utils.js +97 -0
- package/dist/cli/env-utils.js.map +1 -0
- package/dist/cli/helpers.d.ts +49 -0
- package/dist/cli/helpers.d.ts.map +1 -0
- package/dist/cli/helpers.js +168 -0
- package/dist/cli/helpers.js.map +1 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +728 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/session.d.ts +52 -0
- package/dist/cli/session.d.ts.map +1 -0
- package/dist/cli/session.js +188 -0
- package/dist/cli/session.js.map +1 -0
- package/dist/crypto/encryption.d.ts +32 -0
- package/dist/crypto/encryption.d.ts.map +1 -0
- package/dist/crypto/encryption.js +54 -0
- package/dist/crypto/encryption.js.map +1 -0
- package/dist/crypto/keyDerivation.d.ts +22 -0
- package/dist/crypto/keyDerivation.d.ts.map +1 -0
- package/dist/crypto/keyDerivation.js +47 -0
- package/dist/crypto/keyDerivation.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/audit.d.ts +31 -0
- package/dist/mcp/audit.d.ts.map +1 -0
- package/dist/mcp/audit.js +69 -0
- package/dist/mcp/audit.js.map +1 -0
- package/dist/mcp/server.d.ts +22 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +189 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/types/index.d.ts +35 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/vault/config.d.ts +29 -0
- package/dist/vault/config.d.ts.map +1 -0
- package/dist/vault/config.js +66 -0
- package/dist/vault/config.js.map +1 -0
- package/dist/vault/vault.d.ts +130 -0
- package/dist/vault/vault.d.ts.map +1 -0
- package/dist/vault/vault.js +296 -0
- package/dist/vault/vault.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Lockbox
|
|
2
|
+
|
|
3
|
+
**Encrypted API key vault with MCP integration for AI coding tools.**
|
|
4
|
+
|
|
5
|
+
Lockbox stores your API keys in an AES-256-GCM encrypted vault on your machine. Access them from the CLI, pipe them into scripts, or let AI coding agents (Claude Code, Cursor, Windsurf) retrieve secrets through the Model Context Protocol — without ever putting real keys in your codebase.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g lockbox-vault
|
|
11
|
+
|
|
12
|
+
lockbox init # create your encrypted vault
|
|
13
|
+
lockbox add openai API_KEY sk-... # store a secret
|
|
14
|
+
lockbox get openai API_KEY # retrieve it
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g lockbox-vault
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Requires Node.js 18+.
|
|
24
|
+
|
|
25
|
+
## CLI Commands
|
|
26
|
+
|
|
27
|
+
### Vault Lifecycle
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
lockbox init # create a new encrypted vault
|
|
31
|
+
lockbox unlock # unlock with your master password (15-min session)
|
|
32
|
+
lockbox lock # lock the vault immediately
|
|
33
|
+
lockbox status # show vault info, lock state, key count
|
|
34
|
+
lockbox doctor # run health checks on the vault
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Secret Management
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
lockbox add openai API_KEY sk-abc123 # store a secret
|
|
41
|
+
lockbox add stripe SECRET --project myapp # organize by project
|
|
42
|
+
lockbox add aws ACCESS_KEY # prompts for value (hidden)
|
|
43
|
+
lockbox get openai API_KEY # print to stdout
|
|
44
|
+
lockbox get openai API_KEY --copy # copy to clipboard (clears in 30s)
|
|
45
|
+
lockbox remove openai API_KEY # delete (with confirmation)
|
|
46
|
+
lockbox list # show all keys (never values)
|
|
47
|
+
lockbox list --project myapp # filter by project
|
|
48
|
+
lockbox search stripe # search by name, service, or notes
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Import & Export
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
lockbox import .env # import from .env file
|
|
55
|
+
lockbox import creds.json --project myapp # import from JSON
|
|
56
|
+
lockbox export > .env # export as .env format
|
|
57
|
+
lockbox export --format json # export as JSON
|
|
58
|
+
lockbox export --format shell >> ~/.bashrc # export as shell exports
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Proxy Key System
|
|
62
|
+
|
|
63
|
+
The proxy key system lets you commit `.env` files to git without exposing real secrets. Instead of actual values, your env file contains `lockbox://` references that are resolved at runtime.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# generate a .env.proxy file (safe to commit)
|
|
67
|
+
lockbox proxy-init --project myapp
|
|
68
|
+
|
|
69
|
+
# the generated file looks like:
|
|
70
|
+
# OPENAI_API_KEY=lockbox://openai/API_KEY
|
|
71
|
+
# STRIPE_SECRET_KEY=lockbox://stripe/SECRET_KEY
|
|
72
|
+
|
|
73
|
+
# run your app with real values injected
|
|
74
|
+
lockbox run --env-file .env.proxy "npm start"
|
|
75
|
+
lockbox run --env-file .env.proxy "python app.py"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Non-proxy values (like `DATABASE_URL=postgresql://localhost/mydb`) are passed through unchanged.
|
|
79
|
+
|
|
80
|
+
### Audit & Security
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
lockbox audit # show last 50 audit entries
|
|
84
|
+
lockbox audit --since 2025-01-01 # filter by date
|
|
85
|
+
lockbox audit -n 10 # limit entries
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## MCP Setup
|
|
89
|
+
|
|
90
|
+
Lockbox exposes your vault to AI coding agents via the Model Context Protocol. The MCP server provides 6 tools: `store_secret`, `get_secret`, `list_secrets`, `delete_secret`, `export_env`, and `list_projects`.
|
|
91
|
+
|
|
92
|
+
**Prerequisites:** Unlock your vault before using MCP tools:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
lockbox unlock
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Claude Code
|
|
99
|
+
|
|
100
|
+
Add to your project's `.mcp.json`:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"mcpServers": {
|
|
105
|
+
"lockbox": {
|
|
106
|
+
"command": "npx",
|
|
107
|
+
"args": ["lockbox-mcp"]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Cursor
|
|
114
|
+
|
|
115
|
+
Add to `.cursor/mcp.json` in your project root (or `~/.cursor/mcp.json` for global):
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"mcpServers": {
|
|
120
|
+
"lockbox": {
|
|
121
|
+
"command": "npx",
|
|
122
|
+
"args": ["lockbox-mcp"]
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Windsurf
|
|
129
|
+
|
|
130
|
+
Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"mcpServers": {
|
|
135
|
+
"lockbox": {
|
|
136
|
+
"command": "npx",
|
|
137
|
+
"args": ["lockbox-mcp"]
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Security Model
|
|
144
|
+
|
|
145
|
+
| Layer | Implementation |
|
|
146
|
+
|-------|---------------|
|
|
147
|
+
| **Encryption** | AES-256-GCM with 12-byte random IV (fresh on every save) |
|
|
148
|
+
| **Key Derivation** | Argon2id (64 MB memory, 3 iterations, 4 threads) |
|
|
149
|
+
| **Integrity** | HMAC-SHA256 verified before decryption attempt |
|
|
150
|
+
| **Session** | Derived key encrypted to temp file, auto-expires after 15 minutes |
|
|
151
|
+
| **Rate Limiting** | 5 failed unlock attempts per 60s triggers 60s lockout |
|
|
152
|
+
| **Audit Trail** | Append-only log of all operations (values never logged) |
|
|
153
|
+
| **Clipboard** | Auto-clears after 30 seconds when using `--copy` |
|
|
154
|
+
| **Memory** | Derived key zeroed on lock; secrets only in memory while unlocked |
|
|
155
|
+
|
|
156
|
+
### Vault File Format
|
|
157
|
+
|
|
158
|
+
The vault is a single encrypted JSON file at `~/.config/lockbox/vault.enc`:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
{ salt, iv, tag, ciphertext, hmac } (all base64-encoded)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The decrypted payload contains versioned key entries with per-key metadata (project, notes, timestamps, expiry).
|
|
165
|
+
|
|
166
|
+
## Contributing
|
|
167
|
+
|
|
168
|
+
Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/brentschroeter/lockbox).
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
git clone https://github.com/brentschroeter/lockbox.git
|
|
172
|
+
cd lockbox
|
|
173
|
+
npm install
|
|
174
|
+
npm run build
|
|
175
|
+
npm test
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
MIT
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared .env parsing, key-name conversion, and proxy URI utilities
|
|
3
|
+
*/
|
|
4
|
+
/** Proxy URI prefix */
|
|
5
|
+
export declare const PROXY_PREFIX = "lockbox://";
|
|
6
|
+
/**
|
|
7
|
+
* Convert a vault key name (e.g. "openai/API_KEY") to an env-style name.
|
|
8
|
+
* "openai/API_KEY" → "OPENAI_API_KEY"
|
|
9
|
+
*/
|
|
10
|
+
export declare function envKeyName(name: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Split a key name into [service, keyName].
|
|
13
|
+
* If no "/" present, defaults to service "imported".
|
|
14
|
+
*/
|
|
15
|
+
export declare function splitKeyName(key: string): [string, string];
|
|
16
|
+
/**
|
|
17
|
+
* Parse a .env file into key-value pairs.
|
|
18
|
+
* Supports: KEY=value, KEY="value", KEY='value'
|
|
19
|
+
* Skips blank lines and # comments.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseEnvFile(raw: string): {
|
|
22
|
+
key: string;
|
|
23
|
+
value: string;
|
|
24
|
+
}[];
|
|
25
|
+
/**
|
|
26
|
+
* Parse a JSON file into key-value pairs.
|
|
27
|
+
* Expects a flat { "KEY": "value" } object.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseJsonImport(raw: string): {
|
|
30
|
+
key: string;
|
|
31
|
+
value: string;
|
|
32
|
+
}[];
|
|
33
|
+
/**
|
|
34
|
+
* Parse a lockbox proxy URI: "lockbox://service/KEY_NAME"
|
|
35
|
+
* Returns { service, keyName } or null if the value is not a proxy URI.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseProxyUri(value: string): {
|
|
38
|
+
service: string;
|
|
39
|
+
keyName: string;
|
|
40
|
+
} | null;
|
|
41
|
+
/**
|
|
42
|
+
* Build a proxy URI from service and key name.
|
|
43
|
+
* "openai", "API_KEY" → "lockbox://openai/API_KEY"
|
|
44
|
+
*/
|
|
45
|
+
export declare function buildProxyUri(service: string, keyName: string): string;
|
|
46
|
+
//# sourceMappingURL=env-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-utils.d.ts","sourceRoot":"","sources":["../../src/cli/env-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,uBAAuB;AACvB,eAAO,MAAM,YAAY,eAAe,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAW1D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CA4B1E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAU7E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgBxF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtE"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared .env parsing, key-name conversion, and proxy URI utilities
|
|
3
|
+
*/
|
|
4
|
+
/** Proxy URI prefix */
|
|
5
|
+
export const PROXY_PREFIX = 'lockbox://';
|
|
6
|
+
/**
|
|
7
|
+
* Convert a vault key name (e.g. "openai/API_KEY") to an env-style name.
|
|
8
|
+
* "openai/API_KEY" → "OPENAI_API_KEY"
|
|
9
|
+
*/
|
|
10
|
+
export function envKeyName(name) {
|
|
11
|
+
return name.replace(/\//g, '_').toUpperCase();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Split a key name into [service, keyName].
|
|
15
|
+
* If no "/" present, defaults to service "imported".
|
|
16
|
+
*/
|
|
17
|
+
export function splitKeyName(key) {
|
|
18
|
+
if (key.includes('/')) {
|
|
19
|
+
const idx = key.indexOf('/');
|
|
20
|
+
return [key.slice(0, idx), key.slice(idx + 1)];
|
|
21
|
+
}
|
|
22
|
+
// Best guess: split on first underscore for service (e.g. OPENAI_API_KEY → openai, API_KEY)
|
|
23
|
+
const parts = key.split('_');
|
|
24
|
+
if (parts.length >= 2) {
|
|
25
|
+
return [parts[0].toLowerCase(), parts.slice(1).join('_')];
|
|
26
|
+
}
|
|
27
|
+
return ['imported', key];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse a .env file into key-value pairs.
|
|
31
|
+
* Supports: KEY=value, KEY="value", KEY='value'
|
|
32
|
+
* Skips blank lines and # comments.
|
|
33
|
+
*/
|
|
34
|
+
export function parseEnvFile(raw) {
|
|
35
|
+
const entries = [];
|
|
36
|
+
for (const line of raw.split('\n')) {
|
|
37
|
+
const trimmed = line.trim();
|
|
38
|
+
// Skip empty lines and comments
|
|
39
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
40
|
+
continue;
|
|
41
|
+
// Skip lines without '='
|
|
42
|
+
const eqIdx = trimmed.indexOf('=');
|
|
43
|
+
if (eqIdx === -1)
|
|
44
|
+
continue;
|
|
45
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
46
|
+
let value = trimmed.slice(eqIdx + 1).trim();
|
|
47
|
+
// Strip surrounding quotes
|
|
48
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
49
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
50
|
+
value = value.slice(1, -1);
|
|
51
|
+
}
|
|
52
|
+
if (key) {
|
|
53
|
+
entries.push({ key, value });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return entries;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Parse a JSON file into key-value pairs.
|
|
60
|
+
* Expects a flat { "KEY": "value" } object.
|
|
61
|
+
*/
|
|
62
|
+
export function parseJsonImport(raw) {
|
|
63
|
+
const obj = JSON.parse(raw);
|
|
64
|
+
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
|
|
65
|
+
throw new Error('JSON import expects a flat { "KEY": "value" } object');
|
|
66
|
+
}
|
|
67
|
+
return Object.entries(obj).map(([key, value]) => ({
|
|
68
|
+
key,
|
|
69
|
+
value: String(value),
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Parse a lockbox proxy URI: "lockbox://service/KEY_NAME"
|
|
74
|
+
* Returns { service, keyName } or null if the value is not a proxy URI.
|
|
75
|
+
*/
|
|
76
|
+
export function parseProxyUri(value) {
|
|
77
|
+
if (!value.startsWith(PROXY_PREFIX)) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const path = value.slice(PROXY_PREFIX.length);
|
|
81
|
+
const slashIdx = path.indexOf('/');
|
|
82
|
+
if (slashIdx === -1 || slashIdx === 0 || slashIdx === path.length - 1) {
|
|
83
|
+
return null; // malformed: "lockbox://", "lockbox:///KEY", "lockbox://service/"
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
service: path.slice(0, slashIdx),
|
|
87
|
+
keyName: path.slice(slashIdx + 1),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Build a proxy URI from service and key name.
|
|
92
|
+
* "openai", "API_KEY" → "lockbox://openai/API_KEY"
|
|
93
|
+
*/
|
|
94
|
+
export function buildProxyUri(service, keyName) {
|
|
95
|
+
return `${PROXY_PREFIX}${service}/${keyName}`;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=env-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-utils.js","sourceRoot":"","sources":["../../src/cli/env-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI helper utilities — prompts, clipboard, table formatting, colours
|
|
3
|
+
*/
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
/**
|
|
6
|
+
* Prompt for a password with hidden (muted) input.
|
|
7
|
+
*/
|
|
8
|
+
export declare function promptPassword(message: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Prompt for a password and confirm it matches.
|
|
11
|
+
* @returns The confirmed password
|
|
12
|
+
* @throws If passwords don't match
|
|
13
|
+
*/
|
|
14
|
+
export declare function promptPasswordWithConfirm(): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Ask a yes/no confirmation question.
|
|
17
|
+
*/
|
|
18
|
+
export declare function promptConfirm(message: string): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* Copy text to the system clipboard (platform-aware).
|
|
21
|
+
*/
|
|
22
|
+
export declare function copyToClipboard(text: string): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Copy value to clipboard and schedule auto-clear after N seconds.
|
|
25
|
+
* Keeps the process alive until the clipboard is cleared.
|
|
26
|
+
*/
|
|
27
|
+
export declare function copyAndScheduleClear(value: string, seconds: number): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Format data as a simple aligned table.
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatTable(headers: string[], rows: string[][]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Print an error message and exit.
|
|
34
|
+
*/
|
|
35
|
+
export declare function exitWithError(message: string): never;
|
|
36
|
+
/**
|
|
37
|
+
* Format an ISO date string as a short readable date.
|
|
38
|
+
*/
|
|
39
|
+
export declare function shortDate(iso: string | null): string;
|
|
40
|
+
/**
|
|
41
|
+
* Prompt the user to choose from a set of options.
|
|
42
|
+
* Returns the key of the chosen option.
|
|
43
|
+
*/
|
|
44
|
+
export declare function promptChoice(message: string, choices: {
|
|
45
|
+
key: string;
|
|
46
|
+
label: string;
|
|
47
|
+
}[]): Promise<string>;
|
|
48
|
+
export { chalk };
|
|
49
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBrE;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,CAAC,CAajE;AAID;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYrE;AAID;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB3D;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWxF;AAID;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAiBvE;AAID;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAGpD;AAID;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAQpD;AAID;;;GAGG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,GACxC,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAGD,OAAO,EAAE,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI helper utilities — prompts, clipboard, table formatting, colours
|
|
3
|
+
*/
|
|
4
|
+
import { createInterface } from 'node:readline';
|
|
5
|
+
import { Writable } from 'node:stream';
|
|
6
|
+
import { exec } from 'node:child_process';
|
|
7
|
+
import { platform } from 'node:os';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
// ─── Password prompt (hidden input) ─────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Prompt for a password with hidden (muted) input.
|
|
12
|
+
*/
|
|
13
|
+
export async function promptPassword(message) {
|
|
14
|
+
// Create a muted output so readline doesn't echo typed characters
|
|
15
|
+
const muted = new Writable({
|
|
16
|
+
write(_chunk, _encoding, callback) {
|
|
17
|
+
callback();
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const rl = createInterface({
|
|
21
|
+
input: process.stdin,
|
|
22
|
+
output: muted,
|
|
23
|
+
terminal: true,
|
|
24
|
+
});
|
|
25
|
+
process.stderr.write(message);
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
rl.question('', (answer) => {
|
|
28
|
+
rl.close();
|
|
29
|
+
process.stderr.write('\n');
|
|
30
|
+
resolve(answer);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Prompt for a password and confirm it matches.
|
|
36
|
+
* @returns The confirmed password
|
|
37
|
+
* @throws If passwords don't match
|
|
38
|
+
*/
|
|
39
|
+
export async function promptPasswordWithConfirm() {
|
|
40
|
+
const pw1 = await promptPassword(chalk.cyan('Enter master password: '));
|
|
41
|
+
const pw2 = await promptPassword(chalk.cyan('Confirm master password: '));
|
|
42
|
+
if (pw1 !== pw2) {
|
|
43
|
+
throw new Error('Passwords do not match');
|
|
44
|
+
}
|
|
45
|
+
if (pw1.length < 8) {
|
|
46
|
+
throw new Error('Password must be at least 8 characters');
|
|
47
|
+
}
|
|
48
|
+
return pw1;
|
|
49
|
+
}
|
|
50
|
+
// ─── Confirm prompt ──────────────────────────────────────────────────────────
|
|
51
|
+
/**
|
|
52
|
+
* Ask a yes/no confirmation question.
|
|
53
|
+
*/
|
|
54
|
+
export async function promptConfirm(message) {
|
|
55
|
+
const rl = createInterface({
|
|
56
|
+
input: process.stdin,
|
|
57
|
+
output: process.stderr,
|
|
58
|
+
});
|
|
59
|
+
return new Promise((resolve) => {
|
|
60
|
+
rl.question(`${message} (y/N): `, (answer) => {
|
|
61
|
+
rl.close();
|
|
62
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// ─── Clipboard ───────────────────────────────────────────────────────────────
|
|
67
|
+
/**
|
|
68
|
+
* Copy text to the system clipboard (platform-aware).
|
|
69
|
+
*/
|
|
70
|
+
export function copyToClipboard(text) {
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
const p = platform();
|
|
73
|
+
let cmd;
|
|
74
|
+
if (p === 'win32') {
|
|
75
|
+
cmd = 'clip';
|
|
76
|
+
}
|
|
77
|
+
else if (p === 'darwin') {
|
|
78
|
+
cmd = 'pbcopy';
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
cmd = 'xclip -selection clipboard';
|
|
82
|
+
}
|
|
83
|
+
const child = exec(cmd, (err) => {
|
|
84
|
+
if (err)
|
|
85
|
+
reject(err);
|
|
86
|
+
else
|
|
87
|
+
resolve();
|
|
88
|
+
});
|
|
89
|
+
child.stdin?.write(text);
|
|
90
|
+
child.stdin?.end();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Copy value to clipboard and schedule auto-clear after N seconds.
|
|
95
|
+
* Keeps the process alive until the clipboard is cleared.
|
|
96
|
+
*/
|
|
97
|
+
export async function copyAndScheduleClear(value, seconds) {
|
|
98
|
+
await copyToClipboard(value);
|
|
99
|
+
process.stderr.write(chalk.green(`✓ Copied to clipboard. Auto-clearing in ${seconds}s...\n`));
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
setTimeout(async () => {
|
|
102
|
+
await copyToClipboard('');
|
|
103
|
+
process.stderr.write(chalk.dim(`✓ Clipboard cleared.\n`));
|
|
104
|
+
resolve();
|
|
105
|
+
}, seconds * 1000);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// ─── Table formatting ────────────────────────────────────────────────────────
|
|
109
|
+
/**
|
|
110
|
+
* Format data as a simple aligned table.
|
|
111
|
+
*/
|
|
112
|
+
export function formatTable(headers, rows) {
|
|
113
|
+
// Calculate column widths
|
|
114
|
+
const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] || '').length)));
|
|
115
|
+
const divider = widths.map((w) => '─'.repeat(w + 2)).join('┼');
|
|
116
|
+
const headerLine = headers
|
|
117
|
+
.map((h, i) => chalk.bold(h.padEnd(widths[i])))
|
|
118
|
+
.join(' │ ');
|
|
119
|
+
const body = rows
|
|
120
|
+
.map((row) => row.map((cell, i) => (cell || '').padEnd(widths[i])).join(' │ '))
|
|
121
|
+
.join('\n');
|
|
122
|
+
return `${headerLine}\n${divider}\n${body}`;
|
|
123
|
+
}
|
|
124
|
+
// ─── Error formatting ────────────────────────────────────────────────────────
|
|
125
|
+
/**
|
|
126
|
+
* Print an error message and exit.
|
|
127
|
+
*/
|
|
128
|
+
export function exitWithError(message) {
|
|
129
|
+
process.stderr.write(chalk.red(`✗ ${message}\n`));
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
// ─── Date formatting ─────────────────────────────────────────────────────────
|
|
133
|
+
/**
|
|
134
|
+
* Format an ISO date string as a short readable date.
|
|
135
|
+
*/
|
|
136
|
+
export function shortDate(iso) {
|
|
137
|
+
if (!iso)
|
|
138
|
+
return '—';
|
|
139
|
+
const d = new Date(iso);
|
|
140
|
+
return d.toLocaleDateString('en-US', {
|
|
141
|
+
year: 'numeric',
|
|
142
|
+
month: 'short',
|
|
143
|
+
day: 'numeric',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// ─── Choice prompt ───────────────────────────────────────────────────────────
|
|
147
|
+
/**
|
|
148
|
+
* Prompt the user to choose from a set of options.
|
|
149
|
+
* Returns the key of the chosen option.
|
|
150
|
+
*/
|
|
151
|
+
export async function promptChoice(message, choices) {
|
|
152
|
+
const rl = createInterface({
|
|
153
|
+
input: process.stdin,
|
|
154
|
+
output: process.stderr,
|
|
155
|
+
});
|
|
156
|
+
const optionStr = choices.map((c) => c.label).join('/');
|
|
157
|
+
return new Promise((resolve) => {
|
|
158
|
+
rl.question(`${message} (${optionStr}): `, (answer) => {
|
|
159
|
+
rl.close();
|
|
160
|
+
const lower = answer.toLowerCase().trim();
|
|
161
|
+
const match = choices.find((c) => c.key === lower || c.label.toLowerCase().startsWith(lower));
|
|
162
|
+
resolve(match ? match.key : choices[0].key);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// Re-export chalk for use in commands
|
|
167
|
+
export { chalk };
|
|
168
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+CzC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4xBvD"}
|