@captainsafia/burrow 1.0.0-preview.0a24dbc → 1.0.0-preview.6e67e96
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 -57
- 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,66 +57,70 @@ class Storage {
|
|
|
63
57
|
get storePath() {
|
|
64
58
|
return join2(this.configDir, this.storeFileName);
|
|
65
59
|
}
|
|
66
|
-
async
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const store = JSON.parse(content);
|
|
70
|
-
if (store.version !== STORE_VERSION) {
|
|
71
|
-
throw new Error(`Unsupported store version: ${store.version}. Expected: ${STORE_VERSION}`);
|
|
72
|
-
}
|
|
73
|
-
return store;
|
|
74
|
-
} catch (error) {
|
|
75
|
-
if (error.code === "ENOENT") {
|
|
76
|
-
return createEmptyStore();
|
|
77
|
-
}
|
|
78
|
-
throw error;
|
|
60
|
+
async ensureDb() {
|
|
61
|
+
if (this.db) {
|
|
62
|
+
return this.db;
|
|
79
63
|
}
|
|
80
|
-
}
|
|
81
|
-
async write(store) {
|
|
82
64
|
await mkdir(this.configDir, { recursive: true });
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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`);
|
|
95
83
|
}
|
|
84
|
+
return this.db;
|
|
96
85
|
}
|
|
97
86
|
async setSecret(canonicalPath, key, value) {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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);
|
|
107
96
|
}
|
|
108
97
|
async getPathSecrets(canonicalPath) {
|
|
109
|
-
const
|
|
110
|
-
|
|
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;
|
|
111
111
|
}
|
|
112
112
|
async getAllPaths() {
|
|
113
|
-
const
|
|
114
|
-
|
|
113
|
+
const db = await this.ensureDb();
|
|
114
|
+
const rows = db.query("SELECT DISTINCT path FROM secrets").all();
|
|
115
|
+
return rows.map((row) => row.path);
|
|
115
116
|
}
|
|
116
117
|
async removeKey(canonicalPath, key) {
|
|
117
|
-
const
|
|
118
|
-
|
|
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) {
|
|
119
121
|
return false;
|
|
120
122
|
}
|
|
121
|
-
|
|
122
|
-
if (Object.keys(store.paths[canonicalPath]).length === 0) {
|
|
123
|
-
delete store.paths[canonicalPath];
|
|
124
|
-
}
|
|
125
|
-
await this.write(store);
|
|
123
|
+
db.query("DELETE FROM secrets WHERE path = ? AND key = ?").run(canonicalPath, key);
|
|
126
124
|
return true;
|
|
127
125
|
}
|
|
128
126
|
}
|