@captainsafia/burrow 1.0.0-preview.c3f07e0 → 1.0.0-preview.ddd1e9d
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/dist/api.js +55 -58
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/storage/index.ts
|
|
2
|
-
import {
|
|
2
|
+
import { Database } from "bun:sqlite";
|
|
3
|
+
import { mkdir } from "node:fs/promises";
|
|
3
4
|
import { join as join2 } from "node:path";
|
|
4
|
-
import { randomBytes } from "node:crypto";
|
|
5
5
|
|
|
6
6
|
// src/platform/index.ts
|
|
7
7
|
import { homedir } from "node:os";
|
|
@@ -44,18 +44,12 @@ function isWindows() {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// src/storage/index.ts
|
|
47
|
-
var
|
|
48
|
-
var DEFAULT_STORE_FILE = "store.json";
|
|
49
|
-
function createEmptyStore() {
|
|
50
|
-
return {
|
|
51
|
-
version: STORE_VERSION,
|
|
52
|
-
paths: {}
|
|
53
|
-
};
|
|
54
|
-
}
|
|
47
|
+
var DEFAULT_STORE_FILE = "store.db";
|
|
55
48
|
|
|
56
49
|
class Storage {
|
|
57
50
|
configDir;
|
|
58
51
|
storeFileName;
|
|
52
|
+
db = null;
|
|
59
53
|
constructor(options = {}) {
|
|
60
54
|
this.configDir = options.configDir ?? getConfigDir();
|
|
61
55
|
this.storeFileName = options.storeFileName ?? DEFAULT_STORE_FILE;
|
|
@@ -63,67 +57,70 @@ class Storage {
|
|
|
63
57
|
get storePath() {
|
|
64
58
|
return join2(this.configDir, this.storeFileName);
|
|
65
59
|
}
|
|
66
|
-
async
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const content = await file.text();
|
|
70
|
-
const store = JSON.parse(content);
|
|
71
|
-
if (store.version !== STORE_VERSION) {
|
|
72
|
-
throw new Error(`Unsupported store version: ${store.version}. Expected: ${STORE_VERSION}`);
|
|
73
|
-
}
|
|
74
|
-
return store;
|
|
75
|
-
} catch (error) {
|
|
76
|
-
if (error.code === "ENOENT") {
|
|
77
|
-
return createEmptyStore();
|
|
78
|
-
}
|
|
79
|
-
throw error;
|
|
60
|
+
async ensureDb() {
|
|
61
|
+
if (this.db) {
|
|
62
|
+
return this.db;
|
|
80
63
|
}
|
|
81
|
-
}
|
|
82
|
-
async write(store) {
|
|
83
64
|
await mkdir(this.configDir, { recursive: true });
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
65
|
+
this.db = new Database(this.storePath);
|
|
66
|
+
this.db.run("PRAGMA journal_mode = WAL");
|
|
67
|
+
this.db.run(`
|
|
68
|
+
CREATE TABLE IF NOT EXISTS secrets (
|
|
69
|
+
path TEXT NOT NULL,
|
|
70
|
+
key TEXT NOT NULL,
|
|
71
|
+
value TEXT,
|
|
72
|
+
updated_at TEXT NOT NULL,
|
|
73
|
+
PRIMARY KEY (path, key)
|
|
74
|
+
)
|
|
75
|
+
`);
|
|
76
|
+
this.db.run("CREATE INDEX IF NOT EXISTS idx_secrets_path ON secrets (path)");
|
|
77
|
+
const versionResult = this.db.query("PRAGMA user_version").get();
|
|
78
|
+
const currentVersion = versionResult?.user_version ?? 0;
|
|
79
|
+
if (currentVersion === 0) {
|
|
80
|
+
this.db.run("PRAGMA user_version = 1");
|
|
81
|
+
} else if (currentVersion !== 1) {
|
|
82
|
+
throw new Error(`Unsupported store version: ${currentVersion}. Expected: 1`);
|
|
96
83
|
}
|
|
84
|
+
return this.db;
|
|
97
85
|
}
|
|
98
86
|
async setSecret(canonicalPath, key, value) {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
87
|
+
const db = await this.ensureDb();
|
|
88
|
+
const updatedAt = new Date().toISOString();
|
|
89
|
+
db.query(`
|
|
90
|
+
INSERT INTO secrets (path, key, value, updated_at)
|
|
91
|
+
VALUES (?, ?, ?, ?)
|
|
92
|
+
ON CONFLICT(path, key) DO UPDATE SET
|
|
93
|
+
value = excluded.value,
|
|
94
|
+
updated_at = excluded.updated_at
|
|
95
|
+
`).run(canonicalPath, key, value, updatedAt);
|
|
108
96
|
}
|
|
109
97
|
async getPathSecrets(canonicalPath) {
|
|
110
|
-
const
|
|
111
|
-
|
|
98
|
+
const db = await this.ensureDb();
|
|
99
|
+
const rows = db.query("SELECT key, value, updated_at FROM secrets WHERE path = ?").all(canonicalPath);
|
|
100
|
+
if (rows.length === 0) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const secrets = {};
|
|
104
|
+
for (const row of rows) {
|
|
105
|
+
secrets[row.key] = {
|
|
106
|
+
value: row.value,
|
|
107
|
+
updatedAt: row.updated_at
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return secrets;
|
|
112
111
|
}
|
|
113
112
|
async getAllPaths() {
|
|
114
|
-
const
|
|
115
|
-
|
|
113
|
+
const db = await this.ensureDb();
|
|
114
|
+
const rows = db.query("SELECT DISTINCT path FROM secrets").all();
|
|
115
|
+
return rows.map((row) => row.path);
|
|
116
116
|
}
|
|
117
117
|
async removeKey(canonicalPath, key) {
|
|
118
|
-
const
|
|
119
|
-
|
|
118
|
+
const db = await this.ensureDb();
|
|
119
|
+
const existing = db.query("SELECT path FROM secrets WHERE path = ? AND key = ?").get(canonicalPath, key);
|
|
120
|
+
if (!existing) {
|
|
120
121
|
return false;
|
|
121
122
|
}
|
|
122
|
-
|
|
123
|
-
if (Object.keys(store.paths[canonicalPath]).length === 0) {
|
|
124
|
-
delete store.paths[canonicalPath];
|
|
125
|
-
}
|
|
126
|
-
await this.write(store);
|
|
123
|
+
db.query("DELETE FROM secrets WHERE path = ? AND key = ?").run(canonicalPath, key);
|
|
127
124
|
return true;
|
|
128
125
|
}
|
|
129
126
|
}
|