bbb-mcp-server 0.1.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.
Files changed (66) hide show
  1. package/README.md +112 -0
  2. package/dist/api.d.ts +9 -0
  3. package/dist/api.d.ts.map +1 -0
  4. package/dist/api.js +276 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/config.d.ts +10 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +38 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/db/index.d.ts +6 -0
  11. package/dist/db/index.d.ts.map +1 -0
  12. package/dist/db/index.js +31 -0
  13. package/dist/db/index.js.map +1 -0
  14. package/dist/db/migrations.d.ts +9 -0
  15. package/dist/db/migrations.d.ts.map +1 -0
  16. package/dist/db/migrations.js +205 -0
  17. package/dist/db/migrations.js.map +1 -0
  18. package/dist/handlers/artifact.d.ts +30 -0
  19. package/dist/handlers/artifact.d.ts.map +1 -0
  20. package/dist/handlers/artifact.js +80 -0
  21. package/dist/handlers/artifact.js.map +1 -0
  22. package/dist/handlers/context.d.ts +28 -0
  23. package/dist/handlers/context.d.ts.map +1 -0
  24. package/dist/handlers/context.js +247 -0
  25. package/dist/handlers/context.js.map +1 -0
  26. package/dist/handlers/memory.d.ts +42 -0
  27. package/dist/handlers/memory.d.ts.map +1 -0
  28. package/dist/handlers/memory.js +97 -0
  29. package/dist/handlers/memory.js.map +1 -0
  30. package/dist/handlers/project.d.ts +22 -0
  31. package/dist/handlers/project.d.ts.map +1 -0
  32. package/dist/handlers/project.js +139 -0
  33. package/dist/handlers/project.js.map +1 -0
  34. package/dist/handlers/session.d.ts +25 -0
  35. package/dist/handlers/session.d.ts.map +1 -0
  36. package/dist/handlers/session.js +155 -0
  37. package/dist/handlers/session.js.map +1 -0
  38. package/dist/handlers/task.d.ts +41 -0
  39. package/dist/handlers/task.d.ts.map +1 -0
  40. package/dist/handlers/task.js +76 -0
  41. package/dist/handlers/task.js.map +1 -0
  42. package/dist/index.d.ts +3 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +45 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/server.d.ts +4 -0
  47. package/dist/server.d.ts.map +1 -0
  48. package/dist/server.js +307 -0
  49. package/dist/server.js.map +1 -0
  50. package/dist/utils/hash.d.ts +2 -0
  51. package/dist/utils/hash.d.ts.map +1 -0
  52. package/dist/utils/hash.js +5 -0
  53. package/dist/utils/hash.js.map +1 -0
  54. package/dist/utils/schemas.d.ts +6 -0
  55. package/dist/utils/schemas.d.ts.map +1 -0
  56. package/dist/utils/schemas.js +88 -0
  57. package/dist/utils/schemas.js.map +1 -0
  58. package/dist/utils/templates.d.ts +25 -0
  59. package/dist/utils/templates.d.ts.map +1 -0
  60. package/dist/utils/templates.js +138 -0
  61. package/dist/utils/templates.js.map +1 -0
  62. package/dist/utils/tokens.d.ts +6 -0
  63. package/dist/utils/tokens.d.ts.map +1 -0
  64. package/dist/utils/tokens.js +8 -0
  65. package/dist/utils/tokens.js.map +1 -0
  66. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # bbb-mcp-server
2
+
3
+ **BrainBrainBrains** — persistent memory + context layer for AI-assisted dev teams, exposed via the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/).
4
+
5
+ Store decisions, conventions, constraints, and architecture notes. Query them with full-text search. Assemble smart context for any task. Snapshot and rehydrate sessions across tools.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ npx bbb-mcp-server --project my-project
11
+ ```
12
+
13
+ ## Setup
14
+
15
+ ### Claude Desktop
16
+
17
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
18
+
19
+ ```json
20
+ {
21
+ "mcpServers": {
22
+ "bbb": {
23
+ "command": "npx",
24
+ "args": ["-y", "bbb-mcp-server", "--project", "my-project"]
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ ### Claude Code
31
+
32
+ ```bash
33
+ claude mcp add bbb -- npx -y bbb-mcp-server --project my-project
34
+ ```
35
+
36
+ ### Codex
37
+
38
+ Add to `~/.codex/config.toml`:
39
+
40
+ ```toml
41
+ [mcp_servers.bbb]
42
+ command = "npx"
43
+ args = ["-y", "bbb-mcp-server", "--project", "my-project"]
44
+ ```
45
+
46
+ ### Cursor
47
+
48
+ Add to `.cursor/mcp.json`:
49
+
50
+ ```json
51
+ {
52
+ "mcpServers": {
53
+ "bbb": {
54
+ "command": "npx",
55
+ "args": ["-y", "bbb-mcp-server", "--project", "my-project"]
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ ## Tools (17)
62
+
63
+ ### Memory (5)
64
+ | Tool | Description |
65
+ |------|-------------|
66
+ | `memory_store` | Store a memory (decision, convention, constraint, etc.) |
67
+ | `memory_query` | Full-text search with BM25 ranking |
68
+ | `memory_list` | Paginated listing with filters |
69
+ | `memory_update` | Version-aware update (supersedes old) |
70
+ | `memory_delete` | Delete by ID |
71
+
72
+ ### Artifacts (3)
73
+ | Tool | Description |
74
+ |------|-------------|
75
+ | `artifact_store` | Store/update ADRs, PRDs, API contracts, etc. |
76
+ | `artifact_get` | Fetch by ID or search by type/title |
77
+ | `artifact_list` | Paginated listing with filters |
78
+
79
+ ### Tasks (3)
80
+ | Tool | Description |
81
+ |------|-------------|
82
+ | `task_create` | Create task with dependencies |
83
+ | `task_update` | Update status, linked artifacts |
84
+ | `task_get_dag` | Dependency graph view |
85
+
86
+ ### Context (2)
87
+ | Tool | Description |
88
+ |------|-------------|
89
+ | `context_assemble` | Smart context assembly with token budgeting |
90
+ | `search_memories` | Direct FTS5 search |
91
+
92
+ ### Project (2)
93
+ | Tool | Description |
94
+ |------|-------------|
95
+ | `project_init` | Initialize a new project |
96
+ | `ingest_codebase` | Auto-index repository files |
97
+
98
+ ### Session (2)
99
+ | Tool | Description |
100
+ |------|-------------|
101
+ | `session_snapshot` | Capture full session state |
102
+ | `session_rehydrate` | Restore snapshot + generate tool config |
103
+
104
+ ## How It Works
105
+
106
+ - **SQLite + FTS5** — One `.db` file per project at `~/.bbb/data/`. Full-text search with BM25 ranking. WAL mode for performance.
107
+ - **Context Assembly** — Extracts keywords from your task, searches memories + codebase, scores by relevance (BM25 + recency + tag overlap), and assembles a token-budgeted context block.
108
+ - **Session Portability** — Snapshot your entire project state and rehydrate it in any tool (Claude Code, Cursor, Claude Desktop, VS Code, Codex).
109
+
110
+ ## License
111
+
112
+ MIT
package/dist/api.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * HTTP API server for the BBB React frontend.
4
+ * Reuses the same SQLite database and handler functions as the MCP server.
5
+ *
6
+ * Usage: node dist/api.js --project brainbrainbrains --port 3001
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
package/dist/api.js ADDED
@@ -0,0 +1,276 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * HTTP API server for the BBB React frontend.
4
+ * Reuses the same SQLite database and handler functions as the MCP server.
5
+ *
6
+ * Usage: node dist/api.js --project brainbrainbrains --port 3001
7
+ */
8
+ import { createServer as createHttpServer } from "node:http";
9
+ import { loadConfig, ensureDirectories } from "./config.js";
10
+ import { getDb, closeAll } from "./db/index.js";
11
+ import { memoryList, memoryQuery, memoryPut } from "./handlers/memory.js";
12
+ import { artifactList } from "./handlers/artifact.js";
13
+ import { contextAssemble, searchMemories } from "./handlers/context.js";
14
+ import { sessionSnapshot, sessionRehydrate } from "./handlers/session.js";
15
+ function parseArgs() {
16
+ const args = process.argv.slice(2);
17
+ const projectIdx = args.indexOf("--project");
18
+ const portIdx = args.indexOf("--port");
19
+ return {
20
+ project: projectIdx !== -1 ? args[projectIdx + 1] : undefined,
21
+ port: portIdx !== -1 ? parseInt(args[portIdx + 1], 10) : undefined,
22
+ };
23
+ }
24
+ function cors(res) {
25
+ res.setHeader("Access-Control-Allow-Origin", "*");
26
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
27
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
28
+ }
29
+ function json(res, data, status = 200) {
30
+ cors(res);
31
+ res.writeHead(status, { "Content-Type": "application/json" });
32
+ res.end(JSON.stringify(data));
33
+ }
34
+ function error(res, message, status = 400) {
35
+ json(res, { ok: false, error: message }, status);
36
+ }
37
+ function parseUrl(req) {
38
+ return new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
39
+ }
40
+ async function readBody(req) {
41
+ return new Promise((resolve, reject) => {
42
+ let data = "";
43
+ req.on("data", (chunk) => (data += chunk));
44
+ req.on("end", () => {
45
+ try {
46
+ resolve(data ? JSON.parse(data) : {});
47
+ }
48
+ catch {
49
+ reject(new Error("Invalid JSON body"));
50
+ }
51
+ });
52
+ req.on("error", reject);
53
+ });
54
+ }
55
+ /** Transform a raw DB memory row into the shape the frontend expects */
56
+ function formatMemory(row) {
57
+ return {
58
+ id: row.id,
59
+ projectId: row.project_id,
60
+ category: row.category,
61
+ title: row.title,
62
+ content: row.content,
63
+ tags: typeof row.tags === "string" ? JSON.parse(row.tags) : row.tags ?? [],
64
+ createdAt: row.created_at,
65
+ updatedAt: row.updated_at,
66
+ source: row.source ?? "BBB",
67
+ };
68
+ }
69
+ /** Transform a raw DB artifact row into the shape the frontend expects */
70
+ function formatArtifact(row) {
71
+ return {
72
+ id: row.id,
73
+ projectId: row.project_id,
74
+ type: row.type,
75
+ title: row.title,
76
+ description: row.content?.toString().slice(0, 120) ?? "",
77
+ content: row.content ?? "",
78
+ version: String(row.version ?? "1"),
79
+ createdAt: row.created_at,
80
+ updatedAt: row.updated_at,
81
+ };
82
+ }
83
+ async function main() {
84
+ const args = parseArgs();
85
+ const config = loadConfig(args.project);
86
+ ensureDirectories(config);
87
+ const db = getDb(config.project, config.storagePath);
88
+ // Resolve slug → UUID
89
+ let projectRow = db
90
+ .prepare(`SELECT id, name, slug, description FROM projects WHERE slug = ?`)
91
+ .get(config.project);
92
+ if (!projectRow) {
93
+ const { randomUUID } = await import("node:crypto");
94
+ const id = randomUUID();
95
+ db.prepare(`INSERT INTO projects (id, name, slug) VALUES (?, ?, ?)`).run(id, config.project, config.project);
96
+ projectRow = { id, name: config.project, slug: config.project, description: null };
97
+ }
98
+ const projectId = projectRow.id;
99
+ const port = args.port ?? 3001;
100
+ const httpServer = createHttpServer(async (req, res) => {
101
+ // Handle CORS preflight
102
+ if (req.method === "OPTIONS") {
103
+ cors(res);
104
+ res.writeHead(204);
105
+ res.end();
106
+ return;
107
+ }
108
+ const url = parseUrl(req);
109
+ const path = url.pathname;
110
+ try {
111
+ // ── GET /api/projects ──
112
+ if (path === "/api/projects" && req.method === "GET") {
113
+ const projects = db
114
+ .prepare(`SELECT * FROM projects ORDER BY created_at DESC`)
115
+ .all();
116
+ const result = projects.map((p) => {
117
+ const memCount = db
118
+ .prepare(`SELECT COUNT(*) as cnt FROM memories WHERE project_id = ? AND superseded_by IS NULL`)
119
+ .get(p.id).cnt;
120
+ const artCount = db
121
+ .prepare(`SELECT COUNT(*) as cnt FROM artifacts WHERE project_id = ? AND status = 'active'`)
122
+ .get(p.id).cnt;
123
+ return {
124
+ id: p.id,
125
+ name: p.name,
126
+ slug: p.slug,
127
+ description: p.description ?? "",
128
+ status: p.status ?? "active",
129
+ lastActive: p.updated_at ?? p.created_at,
130
+ memoryCount: memCount,
131
+ artifactCount: artCount,
132
+ };
133
+ });
134
+ return json(res, { ok: true, data: result });
135
+ }
136
+ // ── GET /api/memories ──
137
+ if (path === "/api/memories" && req.method === "GET") {
138
+ const category = url.searchParams.get("category") ?? undefined;
139
+ const search = url.searchParams.get("search") ?? undefined;
140
+ const limit = parseInt(url.searchParams.get("limit") ?? "100", 10);
141
+ let rows;
142
+ if (search) {
143
+ try {
144
+ rows = memoryQuery(db, projectId, {
145
+ query: search,
146
+ category,
147
+ limit,
148
+ });
149
+ }
150
+ catch {
151
+ // FTS query failed, fall back to LIKE search
152
+ rows = memoryList(db, projectId, { category, limit });
153
+ if (search) {
154
+ const q = search.toLowerCase();
155
+ rows = rows.filter((r) => r.title.toLowerCase().includes(q) ||
156
+ r.content.toLowerCase().includes(q));
157
+ }
158
+ }
159
+ }
160
+ else {
161
+ rows = memoryList(db, projectId, { category, limit });
162
+ }
163
+ return json(res, { ok: true, data: rows.map(formatMemory) });
164
+ }
165
+ // ── POST /api/memories ──
166
+ if (path === "/api/memories" && req.method === "POST") {
167
+ const body = await readBody(req);
168
+ const result = memoryPut(db, projectId, {
169
+ category: body.category,
170
+ title: body.title,
171
+ content: body.content,
172
+ tags: body.tags,
173
+ source: body.source,
174
+ });
175
+ return json(res, { ok: true, data: result }, 201);
176
+ }
177
+ // ── GET /api/artifacts ──
178
+ if (path === "/api/artifacts" && req.method === "GET") {
179
+ const type = url.searchParams.get("type") ?? undefined;
180
+ const rows = artifactList(db, projectId, { type });
181
+ return json(res, { ok: true, data: rows.map(formatArtifact) });
182
+ }
183
+ // ── POST /api/context/assemble ──
184
+ if (path === "/api/context/assemble" && req.method === "POST") {
185
+ const body = await readBody(req);
186
+ const result = contextAssemble(db, projectId, {
187
+ task: body.task,
188
+ max_tokens: body.max_tokens,
189
+ categories: body.categories,
190
+ });
191
+ return json(res, { ok: true, data: result });
192
+ }
193
+ // ── GET /api/search ──
194
+ if (path === "/api/search" && req.method === "GET") {
195
+ const query = url.searchParams.get("q") ?? "";
196
+ const category = url.searchParams.get("category") ?? undefined;
197
+ const limit = parseInt(url.searchParams.get("limit") ?? "20", 10);
198
+ if (!query)
199
+ return json(res, { ok: true, data: [] });
200
+ try {
201
+ const results = searchMemories(db, projectId, {
202
+ query,
203
+ category,
204
+ limit,
205
+ });
206
+ return json(res, { ok: true, data: results });
207
+ }
208
+ catch {
209
+ return json(res, { ok: true, data: [] });
210
+ }
211
+ }
212
+ // ── GET /api/snapshots ──
213
+ if (path === "/api/snapshots" && req.method === "GET") {
214
+ const rows = db
215
+ .prepare(`SELECT id, project_id, snapshot_name, context_summary, source_tool, created_at
216
+ FROM session_snapshots
217
+ WHERE project_id = ?
218
+ ORDER BY created_at DESC`)
219
+ .all(projectId);
220
+ const snapshots = rows.map((s) => ({
221
+ id: s.id,
222
+ projectId: s.project_id,
223
+ label: s.snapshot_name,
224
+ tool: s.source_tool ?? "MCP",
225
+ machine: "Local",
226
+ memoriesCount: 0,
227
+ artifactsCount: 0,
228
+ envVarsCount: 0,
229
+ createdAt: s.created_at,
230
+ size: "—",
231
+ }));
232
+ return json(res, { ok: true, data: snapshots });
233
+ }
234
+ // ── POST /api/snapshots ──
235
+ if (path === "/api/snapshots" && req.method === "POST") {
236
+ const body = await readBody(req);
237
+ const result = sessionSnapshot(db, projectId, config.snapshotsPath, {
238
+ label: body.label,
239
+ include_env: body.include_env,
240
+ });
241
+ return json(res, { ok: true, data: result }, 201);
242
+ }
243
+ // ── POST /api/rehydrate ──
244
+ if (path === "/api/rehydrate" && req.method === "POST") {
245
+ const body = await readBody(req);
246
+ const result = sessionRehydrate(db, projectId, config.snapshotsPath, {
247
+ snapshot_id: body.snapshot_id,
248
+ target_tool: body.target_tool,
249
+ });
250
+ return json(res, { ok: true, data: result });
251
+ }
252
+ // ── 404 ──
253
+ return error(res, "Not found", 404);
254
+ }
255
+ catch (err) {
256
+ console.error("API error:", err);
257
+ return error(res, err.message, 500);
258
+ }
259
+ });
260
+ httpServer.listen(port, () => {
261
+ console.log(`BBB API server running on http://localhost:${port}`);
262
+ console.log(`Project: ${config.project} (${projectId})`);
263
+ });
264
+ const shutdown = () => {
265
+ httpServer.close();
266
+ closeAll();
267
+ process.exit(0);
268
+ };
269
+ process.on("SIGINT", shutdown);
270
+ process.on("SIGTERM", shutdown);
271
+ }
272
+ main().catch((err) => {
273
+ console.error("Fatal error:", err);
274
+ process.exit(1);
275
+ });
276
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface BbbConfig {
2
+ project: string;
3
+ storagePath: string;
4
+ snapshotsPath: string;
5
+ logLevel: string;
6
+ snapshotId?: string;
7
+ }
8
+ export declare function loadConfig(projectOverride?: string): BbbConfig;
9
+ export declare function ensureDirectories(config: BbbConfig): void;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAgBD,wBAAgB,UAAU,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAwB9D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAMzD"}
package/dist/config.js ADDED
@@ -0,0 +1,38 @@
1
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ const BBB_HOME = join(homedir(), ".bbb");
5
+ function loadConfigFile() {
6
+ const configPath = join(BBB_HOME, "config.json");
7
+ if (existsSync(configPath)) {
8
+ try {
9
+ return JSON.parse(readFileSync(configPath, "utf8"));
10
+ }
11
+ catch {
12
+ return {};
13
+ }
14
+ }
15
+ return {};
16
+ }
17
+ export function loadConfig(projectOverride) {
18
+ const fileConfig = loadConfigFile();
19
+ const project = projectOverride ??
20
+ process.env["BBB_PROJECT"] ??
21
+ fileConfig["project"] ??
22
+ "default";
23
+ const storagePath = process.env["BBB_STORAGE_PATH"] ??
24
+ fileConfig["storagePath"] ??
25
+ join(BBB_HOME, "data");
26
+ const snapshotsPath = fileConfig["snapshotsPath"] ?? join(BBB_HOME, "snapshots");
27
+ const logLevel = process.env["BBB_LOG_LEVEL"] ?? fileConfig["logLevel"] ?? "info";
28
+ const snapshotId = process.env["BBB_SNAPSHOT_ID"] ?? fileConfig["snapshotId"] ?? undefined;
29
+ return { project, storagePath, snapshotsPath, logLevel, snapshotId };
30
+ }
31
+ export function ensureDirectories(config) {
32
+ for (const dir of [config.storagePath, config.snapshotsPath]) {
33
+ if (!existsSync(dir)) {
34
+ mkdirSync(dir, { recursive: true });
35
+ }
36
+ }
37
+ }
38
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAUjC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;AAEzC,SAAS,cAAc;IACrB,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,eAAwB;IACjD,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IAEpC,MAAM,OAAO,GACX,eAAe;QACf,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QAC1B,UAAU,CAAC,SAAS,CAAC;QACrB,SAAS,CAAC;IAEZ,MAAM,WAAW,GACf,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAC/B,UAAU,CAAC,aAAa,CAAC;QACzB,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEzB,MAAM,aAAa,GACjB,UAAU,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAE7D,MAAM,QAAQ,GACZ,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC;IAEnE,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC;IAE1E,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC7D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import Database from "better-sqlite3";
2
+ export declare function getDb(projectSlug: string, storagePath: string): Database.Database;
3
+ /** For testing: create an in-memory database with migrations applied */
4
+ export declare function getMemoryDb(): Database.Database;
5
+ export declare function closeAll(): void;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAMtC,wBAAgB,KAAK,CACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,QAAQ,CAAC,QAAQ,CAenB;AAED,wEAAwE;AACxE,wBAAgB,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAK/C;AAED,wBAAgB,QAAQ,IAAI,IAAI,CAK/B"}
@@ -0,0 +1,31 @@
1
+ import Database from "better-sqlite3";
2
+ import { join } from "node:path";
3
+ import { runMigrations } from "./migrations.js";
4
+ const connections = new Map();
5
+ export function getDb(projectSlug, storagePath) {
6
+ const key = `${storagePath}/${projectSlug}`;
7
+ let db = connections.get(key);
8
+ if (db)
9
+ return db;
10
+ const dbPath = join(storagePath, `${projectSlug}.db`);
11
+ db = new Database(dbPath);
12
+ db.pragma("journal_mode = WAL");
13
+ db.pragma("foreign_keys = ON");
14
+ runMigrations(db);
15
+ connections.set(key, db);
16
+ return db;
17
+ }
18
+ /** For testing: create an in-memory database with migrations applied */
19
+ export function getMemoryDb() {
20
+ const db = new Database(":memory:");
21
+ db.pragma("foreign_keys = ON");
22
+ runMigrations(db);
23
+ return db;
24
+ }
25
+ export function closeAll() {
26
+ for (const db of connections.values()) {
27
+ db.close();
28
+ }
29
+ connections.clear();
30
+ }
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,WAAW,GAAG,IAAI,GAAG,EAA6B,CAAC;AAEzD,MAAM,UAAU,KAAK,CACnB,WAAmB,EACnB,WAAmB;IAEnB,MAAM,GAAG,GAAG,GAAG,WAAW,IAAI,WAAW,EAAE,CAAC;IAC5C,IAAI,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAElB,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,WAAW,KAAK,CAAC,CAAC;IACtD,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE1B,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAE/B,aAAa,CAAC,EAAE,CAAC,CAAC;IAElB,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACzB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,WAAW;IACzB,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC;IACpC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC/B,aAAa,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,KAAK,MAAM,EAAE,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;IACD,WAAW,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type Database from "better-sqlite3";
2
+ export interface Migration {
3
+ version: number;
4
+ name: string;
5
+ up: (db: Database.Database) => void;
6
+ }
7
+ export declare const migrations: Migration[];
8
+ export declare function runMigrations(db: Database.Database): void;
9
+ //# sourceMappingURL=migrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC;CACrC;AAED,eAAO,MAAM,UAAU,EAAE,SAAS,EAkMjC,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAWzD"}