@captainsafia/burrow 1.0.0-preview.0d335f8 → 1.0.0-preview.2be53e0

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 CHANGED
@@ -30,7 +30,7 @@ burrow set DATABASE_URL=postgres://localhost/mydb --path ~/projects
30
30
  ### Get a secret
31
31
 
32
32
  ```bash
33
- burrow get API_KEY --show
33
+ burrow get API_KEY
34
34
  burrow get API_KEY --format json
35
35
  ```
36
36
 
@@ -44,8 +44,14 @@ burrow list --format json
44
44
  ### Export to your shell
45
45
 
46
46
  ```bash
47
+ # Auto-detects your shell (bash, fish, powershell, cmd)
47
48
  eval "$(burrow export)"
48
- eval "$(burrow export --format shell)" && npm start
49
+
50
+ # Or specify a format explicitly
51
+ burrow export --format fish
52
+ burrow export --format powershell
53
+ burrow export --format dotenv
54
+ burrow export --format json
49
55
  ```
50
56
 
51
57
  ### Block inheritance
@@ -84,13 +90,26 @@ import { BurrowClient } from '@captainsafia/burrow';
84
90
 
85
91
  const client = new BurrowClient();
86
92
 
87
- await client.set('API_KEY', 'secret123', { path: '/my/project' });
93
+ try {
94
+ await client.set('API_KEY', 'secret123', { path: '/my/project' });
95
+
96
+ const secret = await client.get('API_KEY', { cwd: '/my/project/subdir' });
97
+ console.log(secret?.value); // 'secret123'
98
+ console.log(secret?.sourcePath); // '/my/project'
88
99
 
89
- const secret = await client.get('API_KEY', { cwd: '/my/project/subdir' });
90
- console.log(secret?.value); // 'secret123'
91
- console.log(secret?.sourcePath); // '/my/project'
100
+ const allSecrets = await client.list({ cwd: '/my/project' });
101
+ } finally {
102
+ client.close(); // Clean up database connection
103
+ }
104
+ ```
92
105
 
93
- const allSecrets = await client.list({ cwd: '/my/project' });
106
+ Or with TypeScript's `using` declarations for automatic cleanup:
107
+
108
+ ```typescript
109
+ {
110
+ using client = new BurrowClient();
111
+ await client.set('API_KEY', 'secret123');
112
+ } // Automatically cleaned up
94
113
  ```
95
114
 
96
115
  ## Contributing
package/dist/api.d.ts CHANGED
@@ -5,7 +5,7 @@ export interface ResolvedSecret {
5
5
  value: string;
6
6
  sourcePath: string;
7
7
  }
8
- export type ExportFormat = "shell" | "dotenv" | "json";
8
+ export type ExportFormat = "shell" | "bash" | "fish" | "powershell" | "cmd" | "dotenv" | "json";
9
9
  /**
10
10
  * Configuration options for creating a BurrowClient instance.
11
11
  */
@@ -21,7 +21,7 @@ export interface BurrowClientOptions {
21
21
  configDir?: string;
22
22
  /**
23
23
  * Custom filename for the secrets store.
24
- * Defaults to `store.json`.
24
+ * Defaults to `store.db`.
25
25
  */
26
26
  storeFileName?: string;
27
27
  /**
@@ -99,10 +99,6 @@ export interface ExportOptions {
99
99
  * - `json`: Exports as a JSON object
100
100
  */
101
101
  format?: ExportFormat;
102
- /**
103
- * Whether to show actual values (currently unused, reserved for future use).
104
- */
105
- showValues?: boolean;
106
102
  /**
107
103
  * Whether to include source paths in JSON output.
108
104
  * When true, JSON output includes `{ key: { value, sourcePath } }` format.
@@ -151,7 +147,7 @@ export declare class BurrowClient {
151
147
  * The secret will be available to the specified directory and all its
152
148
  * subdirectories, unless overridden or blocked at a deeper level.
153
149
  *
154
- * @param key - Environment variable name. Must match `^[A-Z_][A-Z0-9_]*$`
150
+ * @param key - Environment variable name. Must match `^[A-Za-z_][A-Za-z0-9_]*$`
155
151
  * @param value - Secret value to store
156
152
  * @param options - Set options including target path
157
153
  * @throws Error if the key format is invalid
@@ -215,7 +211,7 @@ export declare class BurrowClient {
215
211
  *
216
212
  * A blocked key can be re-enabled by calling `set` at the same or deeper path.
217
213
  *
218
- * @param key - Environment variable name to block. Must match `^[A-Z_][A-Z0-9_]*$`
214
+ * @param key - Environment variable name to block. Must match `^[A-Za-z_][A-Za-z0-9_]*$`
219
215
  * @param options - Block options including target path
220
216
  * @throws Error if the key format is invalid
221
217
  *
@@ -240,7 +236,7 @@ export declare class BurrowClient {
240
236
  * `remove` completely deletes the secret entry. After removal, the key
241
237
  * may still be inherited from parent directories if defined there.
242
238
  *
243
- * @param key - Environment variable name to remove. Must match `^[A-Z_][A-Z0-9_]*$`
239
+ * @param key - Environment variable name to remove. Must match `^[A-Za-z_][A-Za-z0-9_]*$`
244
240
  * @param options - Remove options including target path
245
241
  * @returns true if the secret was found and removed, false if it didn't exist
246
242
  * @throws Error if the key format is invalid
package/dist/api.js CHANGED
@@ -66,10 +66,10 @@ class Storage {
66
66
  await chmod(this.configDir, 448);
67
67
  }
68
68
  this.db = new Database(this.storePath);
69
- this.db.run("PRAGMA journal_mode = WAL");
70
69
  if (!isWindows()) {
71
70
  await chmod(this.storePath, 384);
72
71
  }
72
+ this.db.run("PRAGMA journal_mode = WAL");
73
73
  this.db.run(`
74
74
  CREATE TABLE IF NOT EXISTS secrets (
75
75
  path TEXT NOT NULL,
@@ -122,7 +122,12 @@ class Storage {
122
122
  }
123
123
  async getAncestorPaths(canonicalPath) {
124
124
  const db = await this.ensureDb();
125
- const rows = db.query("SELECT DISTINCT path FROM secrets WHERE ? = path OR ? LIKE path || '/' || '%' OR path = '/'").all(canonicalPath, canonicalPath);
125
+ let rows;
126
+ if (isWindows()) {
127
+ rows = db.query("SELECT DISTINCT path FROM secrets WHERE ? = path OR ? LIKE path || '\\' || '%' OR (length(path) = 3 AND path LIKE '_:\\' AND ? LIKE path || '%')").all(canonicalPath, canonicalPath, canonicalPath);
128
+ } else {
129
+ rows = db.query("SELECT DISTINCT path FROM secrets WHERE ? = path OR ? LIKE path || '/' || '%' OR path = '/'").all(canonicalPath, canonicalPath);
130
+ }
126
131
  return rows.map((row) => row.path);
127
132
  }
128
133
  async removeKey(canonicalPath, key) {
@@ -246,6 +251,9 @@ function escapeShellValue(value) {
246
251
  function escapeDoubleQuotes(value) {
247
252
  return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
248
253
  }
254
+ function escapePowerShellValue(value) {
255
+ return value.replace(/'/g, "''");
256
+ }
249
257
  function formatShell(secrets) {
250
258
  const lines = [];
251
259
  const sortedKeys = Array.from(secrets.keys()).sort();
@@ -258,6 +266,42 @@ function formatShell(secrets) {
258
266
  return lines.join(`
259
267
  `);
260
268
  }
269
+ function formatFish(secrets) {
270
+ const lines = [];
271
+ const sortedKeys = Array.from(secrets.keys()).sort();
272
+ for (const key of sortedKeys) {
273
+ const secret = secrets.get(key);
274
+ assertValidEnvKey(key);
275
+ const escapedValue = escapeShellValue(secret.value);
276
+ lines.push(`set -gx ${key} '${escapedValue}'`);
277
+ }
278
+ return lines.join(`
279
+ `);
280
+ }
281
+ function formatPowerShell(secrets) {
282
+ const lines = [];
283
+ const sortedKeys = Array.from(secrets.keys()).sort();
284
+ for (const key of sortedKeys) {
285
+ const secret = secrets.get(key);
286
+ assertValidEnvKey(key);
287
+ const escapedValue = escapePowerShellValue(secret.value);
288
+ lines.push(`$env:${key} = '${escapedValue}'`);
289
+ }
290
+ return lines.join(`
291
+ `);
292
+ }
293
+ function formatCmd(secrets) {
294
+ const lines = [];
295
+ const sortedKeys = Array.from(secrets.keys()).sort();
296
+ for (const key of sortedKeys) {
297
+ const secret = secrets.get(key);
298
+ assertValidEnvKey(key);
299
+ const escapedValue = secret.value.replace(/([&|<>^])/g, "^$1");
300
+ lines.push(`set ${key}=${escapedValue}`);
301
+ }
302
+ return lines.join(`
303
+ `);
304
+ }
261
305
  function formatDotenv(secrets) {
262
306
  const lines = [];
263
307
  const sortedKeys = Array.from(secrets.keys()).sort();
@@ -295,7 +339,14 @@ function formatJson(secrets, includeSources = false) {
295
339
  function format(secrets, fmt, options = {}) {
296
340
  switch (fmt) {
297
341
  case "shell":
342
+ case "bash":
298
343
  return formatShell(secrets);
344
+ case "fish":
345
+ return formatFish(secrets);
346
+ case "powershell":
347
+ return formatPowerShell(secrets);
348
+ case "cmd":
349
+ return formatCmd(secrets);
299
350
  case "dotenv":
300
351
  return formatDotenv(secrets);
301
352
  case "json":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@captainsafia/burrow",
3
- "version": "1.0.0-preview.0d335f8",
3
+ "version": "1.0.0-preview.2be53e0",
4
4
  "description": "Platform-agnostic, directory-scoped secrets manager",
5
5
  "type": "module",
6
6
  "main": "dist/api.js",