@vibesdotdev/localdb 0.0.1
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 +121 -0
- package/SPEC.md +119 -0
- package/dist/cli/commands/_shared.consumer.d.ts +5 -0
- package/dist/cli/commands/_shared.consumer.d.ts.map +1 -0
- package/dist/cli/commands/_shared.consumer.js +17 -0
- package/dist/cli/commands/_shared.consumer.js.map +1 -0
- package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.d.ts +19 -0
- package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.js +19 -0
- package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.js.map +1 -0
- package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.d.ts +5 -0
- package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.d.ts.map +1 -0
- package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.js +80 -0
- package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.js.map +1 -0
- package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.d.ts +19 -0
- package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.js +16 -0
- package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.js.map +1 -0
- package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.d.ts +5 -0
- package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.js +33 -0
- package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.js.map +1 -0
- package/dist/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.d.ts +15 -0
- package/dist/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.js +15 -0
- package/dist/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.js.map +1 -0
- package/dist/cli/commands/pools/dev.localdb.pools.cli-command.impl.d.ts +5 -0
- package/dist/cli/commands/pools/dev.localdb.pools.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/commands/pools/dev.localdb.pools.cli-command.impl.js +28 -0
- package/dist/cli/commands/pools/dev.localdb.pools.cli-command.impl.js.map +1 -0
- package/dist/cli/commands/query/dev.localdb.query.cli-command.descriptor.d.ts +24 -0
- package/dist/cli/commands/query/dev.localdb.query.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/commands/query/dev.localdb.query.cli-command.descriptor.js +20 -0
- package/dist/cli/commands/query/dev.localdb.query.cli-command.descriptor.js.map +1 -0
- package/dist/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.d.ts +5 -0
- package/dist/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.d.ts.map +1 -0
- package/dist/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.js +63 -0
- package/dist/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.js.map +1 -0
- package/dist/cli/commands/status/dev.localdb.status.cli-command.descriptor.d.ts +19 -0
- package/dist/cli/commands/status/dev.localdb.status.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/commands/status/dev.localdb.status.cli-command.descriptor.js +19 -0
- package/dist/cli/commands/status/dev.localdb.status.cli-command.descriptor.js.map +1 -0
- package/dist/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.d.ts +5 -0
- package/dist/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.d.ts.map +1 -0
- package/dist/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.js +73 -0
- package/dist/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.js.map +1 -0
- package/dist/core/connection-pool.d.ts +84 -0
- package/dist/core/connection-pool.d.ts.map +1 -0
- package/dist/core/connection-pool.js +191 -0
- package/dist/core/connection-pool.js.map +1 -0
- package/dist/core/database.d.ts +137 -0
- package/dist/core/database.d.ts.map +1 -0
- package/dist/core/database.js +347 -0
- package/dist/core/database.js.map +1 -0
- package/dist/core/error-context.d.ts +2 -0
- package/dist/core/error-context.d.ts.map +1 -0
- package/dist/core/error-context.js +17 -0
- package/dist/core/error-context.js.map +1 -0
- package/dist/core/migration-registry.d.ts +89 -0
- package/dist/core/migration-registry.d.ts.map +1 -0
- package/dist/core/migration-registry.js +226 -0
- package/dist/core/migration-registry.js.map +1 -0
- package/dist/core/runtime.d.ts +3 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +17 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/dev.localdb.cli-group.descriptor.d.ts +9 -0
- package/dist/dev.localdb.cli-group.descriptor.d.ts.map +1 -0
- package/dist/dev.localdb.cli-group.descriptor.js +17 -0
- package/dist/dev.localdb.cli-group.descriptor.js.map +1 -0
- package/dist/dev.localdb.context.descriptor.d.ts +21 -0
- package/dist/dev.localdb.context.descriptor.d.ts.map +1 -0
- package/dist/dev.localdb.context.descriptor.js +12 -0
- package/dist/dev.localdb.context.descriptor.js.map +1 -0
- package/dist/dev.localdb.context.impl.consumer.d.ts +9 -0
- package/dist/dev.localdb.context.impl.consumer.d.ts.map +1 -0
- package/dist/dev.localdb.context.impl.consumer.js +10 -0
- package/dist/dev.localdb.context.impl.consumer.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/localdb.cloud.plugin.d.ts +17 -0
- package/dist/localdb.cloud.plugin.d.ts.map +1 -0
- package/dist/localdb.cloud.plugin.js +23 -0
- package/dist/localdb.cloud.plugin.js.map +1 -0
- package/dist/localdb.plugin.d.ts +8 -0
- package/dist/localdb.plugin.d.ts.map +1 -0
- package/dist/localdb.plugin.js +38 -0
- package/dist/localdb.plugin.js.map +1 -0
- package/dist/migrations/load-sql.d.ts +45 -0
- package/dist/migrations/load-sql.d.ts.map +1 -0
- package/dist/migrations/load-sql.js +117 -0
- package/dist/migrations/load-sql.js.map +1 -0
- package/dist/schemas/api.d.ts +82 -0
- package/dist/schemas/api.d.ts.map +1 -0
- package/dist/schemas/api.js +2 -0
- package/dist/schemas/api.js.map +1 -0
- package/package.json +146 -0
- package/src/cli/commands/_shared.consumer.ts +20 -0
- package/src/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.ts +20 -0
- package/src/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.ts +97 -0
- package/src/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.ts +17 -0
- package/src/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.ts +46 -0
- package/src/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.ts +16 -0
- package/src/cli/commands/pools/dev.localdb.pools.cli-command.impl.ts +37 -0
- package/src/cli/commands/query/dev.localdb.query.cli-command.descriptor.ts +21 -0
- package/src/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.ts +69 -0
- package/src/cli/commands/status/dev.localdb.status.cli-command.descriptor.ts +20 -0
- package/src/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.ts +93 -0
- package/src/core/connection-pool.ts +240 -0
- package/src/core/database.ts +419 -0
- package/src/core/error-context.ts +19 -0
- package/src/core/migration-registry.ts +321 -0
- package/src/core/runtime.ts +17 -0
- package/src/dev.localdb.cli-group.descriptor.ts +20 -0
- package/src/dev.localdb.context.descriptor.ts +13 -0
- package/src/dev.localdb.context.impl.consumer.ts +12 -0
- package/src/index.ts +28 -0
- package/src/localdb.cloud.plugin.ts +24 -0
- package/src/localdb.plugin.ts +43 -0
- package/src/migrations/atlas/001-initial-schema.sql +173 -0
- package/src/migrations/atlas/002-lang-server-fields.sql +12 -0
- package/src/migrations/atlas/003-config-id-dedup.sql +31 -0
- package/src/migrations/atlas/004-fix-on-conflict-constraints.sql +25 -0
- package/src/migrations/atlas/005-diagnostics.sql +66 -0
- package/src/migrations/atlas/006-diagnostic-summaries.sql +65 -0
- package/src/migrations/atlas/007-diagnostic-slice.sql +83 -0
- package/src/migrations/load-sql.ts +133 -0
- package/src/schemas/api.ts +92 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev LocalDB Query CLI Command Descriptor
|
|
3
|
+
*/
|
|
4
|
+
import { createRuntimeAsset } from '@vibesdotdev/runtime';
|
|
5
|
+
export default createRuntimeAsset({
|
|
6
|
+
id: 'dev.localdb.query',
|
|
7
|
+
kind: 'cli/command',
|
|
8
|
+
name: 'query',
|
|
9
|
+
description: 'Execute an SQL query on a database',
|
|
10
|
+
group: 'dev.localdb',
|
|
11
|
+
surfaces: ['cli'],
|
|
12
|
+
hardware: ['consumer'],
|
|
13
|
+
enabled: true,
|
|
14
|
+
arguments: [{ name: 'sql', description: 'SQL statement to execute', required: true }],
|
|
15
|
+
options: [
|
|
16
|
+
{ flags: '--db <path>', description: 'Database file path (required)' },
|
|
17
|
+
{ flags: '--json', description: 'Output results as JSON' }
|
|
18
|
+
]
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=dev.localdb.query.cli-command.descriptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.localdb.query.cli-command.descriptor.js","sourceRoot":"","sources":["../../../../src/cli/commands/query/dev.localdb.query.cli-command.descriptor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,eAAe,kBAAkB,CAAC;IACjC,EAAE,EAAE,mBAAmB;IACvB,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,oCAAoC;IACjD,KAAK,EAAE,aAAa;IACpB,QAAQ,EAAE,CAAC,KAAK,CAAC;IACjB,QAAQ,EAAE,CAAC,UAAU,CAAC;IACtB,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,0BAA0B,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACrF,OAAO,EAAE;QACR,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,+BAA+B,EAAE;QACtE,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;KAC1D;CACD,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.localdb.query.cli-command.impl.consumer.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.ts"],"names":[],"mappings":";kBAOqB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;;AAD3F,wBA8DE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { getVibesRuntime } from '@vibesdotdev/runtime';
|
|
3
|
+
import { resolveFromCwd } from '../_shared.consumer.js';
|
|
4
|
+
export default {
|
|
5
|
+
async execute(args, opts) {
|
|
6
|
+
const runtime = getVibesRuntime();
|
|
7
|
+
const ui = (await runtime.context('cli/ui'));
|
|
8
|
+
const localdb = (await runtime.context('dev/localdb'));
|
|
9
|
+
const sql = typeof args.sql === 'string' ? args.sql : '';
|
|
10
|
+
const dbOpt = typeof opts.db === 'string' ? opts.db : '';
|
|
11
|
+
if (!sql.trim()) {
|
|
12
|
+
ui.error('Missing SQL statement');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
if (!dbOpt.trim()) {
|
|
16
|
+
ui.error('Missing required option: --db <path>');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const fullPath = resolveFromCwd(dbOpt);
|
|
20
|
+
if (!existsSync(fullPath)) {
|
|
21
|
+
ui.error(`Database not found: ${dbOpt}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const db = localdb.getRawDatabase(fullPath, 'localdb-query');
|
|
26
|
+
const isSelect = sql.trim().toLowerCase().startsWith('select');
|
|
27
|
+
if (isSelect) {
|
|
28
|
+
const results = db.query(sql).all();
|
|
29
|
+
if (opts.json) {
|
|
30
|
+
ui.json(results);
|
|
31
|
+
}
|
|
32
|
+
else if (results.length === 0) {
|
|
33
|
+
ui.info('No results.');
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
ui.table(results);
|
|
37
|
+
ui.info(`(${results.length} row${results.length !== 1 ? 's' : ''})`);
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const stmt = db.prepare(sql);
|
|
42
|
+
const result = stmt.run();
|
|
43
|
+
const payload = {
|
|
44
|
+
changes: result.changes,
|
|
45
|
+
lastInsertRowid: result.lastInsertRowid
|
|
46
|
+
};
|
|
47
|
+
if (opts.json) {
|
|
48
|
+
ui.json(payload);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
ui.success('Query executed successfully.');
|
|
52
|
+
ui.log(`Changes: ${payload.changes}`);
|
|
53
|
+
if (payload.lastInsertRowid)
|
|
54
|
+
ui.log(`Last Insert Row ID: ${String(payload.lastInsertRowid)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
ui.error(`Error executing query: ${String(error)}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=dev.localdb.query.cli-command.impl.consumer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.localdb.query.cli-command.impl.consumer.js","sourceRoot":"","sources":["../../../../src/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev LocalDB Status CLI Command Descriptor
|
|
3
|
+
*/
|
|
4
|
+
declare const _default: {
|
|
5
|
+
id: string;
|
|
6
|
+
kind: "cli/command";
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
group: string;
|
|
10
|
+
surfaces: string[];
|
|
11
|
+
hardware: string[];
|
|
12
|
+
enabled: true;
|
|
13
|
+
options: {
|
|
14
|
+
flags: string;
|
|
15
|
+
description: string;
|
|
16
|
+
}[];
|
|
17
|
+
};
|
|
18
|
+
export default _default;
|
|
19
|
+
//# sourceMappingURL=dev.localdb.status.cli-command.descriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.localdb.status.cli-command.descriptor.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/dev.localdb.status.cli-command.descriptor.ts"],"names":[],"mappings":"AAAA;;GAEG;;;;;;;;;;;;;;;AAIH,wBAaG"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev LocalDB Status CLI Command Descriptor
|
|
3
|
+
*/
|
|
4
|
+
import { createRuntimeAsset } from '@vibesdotdev/runtime';
|
|
5
|
+
export default createRuntimeAsset({
|
|
6
|
+
id: 'dev.localdb.status',
|
|
7
|
+
kind: 'cli/command',
|
|
8
|
+
name: 'status',
|
|
9
|
+
description: 'Show database and migration status',
|
|
10
|
+
group: 'dev.localdb',
|
|
11
|
+
surfaces: ['cli'],
|
|
12
|
+
hardware: ['consumer'],
|
|
13
|
+
enabled: true,
|
|
14
|
+
options: [
|
|
15
|
+
{ flags: '--namespace <name>', description: 'Show status for specific namespace' },
|
|
16
|
+
{ flags: '--verbose', description: 'Show detailed migration and connection information' }
|
|
17
|
+
]
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=dev.localdb.status.cli-command.descriptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.localdb.status.cli-command.descriptor.js","sourceRoot":"","sources":["../../../../src/cli/commands/status/dev.localdb.status.cli-command.descriptor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,eAAe,kBAAkB,CAAC;IACjC,EAAE,EAAE,oBAAoB;IACxB,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,oCAAoC;IACjD,KAAK,EAAE,aAAa;IACpB,QAAQ,EAAE,CAAC,KAAK,CAAC;IACjB,QAAQ,EAAE,CAAC,UAAU,CAAC;IACtB,OAAO,EAAE,IAAI;IACb,OAAO,EAAE;QACR,EAAE,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,oCAAoC,EAAE;QAClF,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,oDAAoD,EAAE;KACzF;CACD,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.localdb.status.cli-command.impl.consumer.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.ts"],"names":[],"mappings":";mBAOsB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;;AAD5F,wBAsFE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { getVibesRuntime } from '@vibesdotdev/runtime';
|
|
3
|
+
import { requestCLIExit } from '@vibesdotdev/cli/providers';
|
|
4
|
+
import { formatAgeMs, resolveDatabasePathForNamespace, resolveFromCwd } from '../_shared.consumer';
|
|
5
|
+
export default {
|
|
6
|
+
async execute(_args, opts) {
|
|
7
|
+
const runtime = getVibesRuntime();
|
|
8
|
+
const ui = (await runtime.context('cli/ui'));
|
|
9
|
+
const localdb = (await runtime.context('dev/localdb'));
|
|
10
|
+
const namespaceOpt = typeof opts.namespace === 'string' ? opts.namespace : undefined;
|
|
11
|
+
const verbose = Boolean(opts.verbose);
|
|
12
|
+
ui.log('\n=== LocalDB Status ===\n');
|
|
13
|
+
const namespaces = localdb.listNamespaces();
|
|
14
|
+
if (namespaces.length === 0) {
|
|
15
|
+
ui.info('No migration namespaces registered.');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const namespacesToShow = namespaceOpt
|
|
19
|
+
? namespaces.filter((ns) => ns === namespaceOpt)
|
|
20
|
+
: namespaces;
|
|
21
|
+
if (namespacesToShow.length === 0) {
|
|
22
|
+
ui.error(`Namespace '${namespaceOpt}' not found.`);
|
|
23
|
+
ui.info(`Available namespaces: ${namespaces.join(', ')}`);
|
|
24
|
+
requestCLIExit(1);
|
|
25
|
+
}
|
|
26
|
+
const { migrationRegistry } = (await import('../../../core/migration-registry'));
|
|
27
|
+
for (const ns of namespacesToShow) {
|
|
28
|
+
ui.log(`\nNamespace: ${ns}`);
|
|
29
|
+
ui.log('─'.repeat(50));
|
|
30
|
+
const dbPath = resolveDatabasePathForNamespace(ns);
|
|
31
|
+
if (!dbPath) {
|
|
32
|
+
ui.warn('No known database path for this namespace');
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const fullPath = resolveFromCwd(dbPath);
|
|
36
|
+
const exists = existsSync(fullPath);
|
|
37
|
+
ui.log(`Database: ${dbPath}`);
|
|
38
|
+
ui.log(`Exists: ${exists ? 'yes' : 'no'}`);
|
|
39
|
+
if (!exists)
|
|
40
|
+
continue;
|
|
41
|
+
try {
|
|
42
|
+
const db = localdb.getRawDatabase(fullPath, 'localdb-status');
|
|
43
|
+
const status = migrationRegistry.getDatabaseStatus(db, ns);
|
|
44
|
+
ui.log(`Schema Version: v${status.currentVersion}`);
|
|
45
|
+
ui.log(`Target Version: v${status.targetVersion}`);
|
|
46
|
+
ui.log(`Status: ${status.pendingMigrations > 0 ? 'migrations pending' : 'up to date'}`);
|
|
47
|
+
if (verbose && status.migrations.length > 0) {
|
|
48
|
+
ui.log('\nMigrations:');
|
|
49
|
+
for (const m of status.migrations) {
|
|
50
|
+
ui.log(` ${m.applied ? '✓' : '○'} v${m.version}: ${m.name}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
ui.error(`Error reading migration status: ${String(error)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (verbose) {
|
|
59
|
+
ui.log('\n\n=== Connection Pool ===\n');
|
|
60
|
+
const poolStats = localdb.getPoolStats();
|
|
61
|
+
ui.log(`Total Connections: ${poolStats.total}`);
|
|
62
|
+
ui.log(`Active: ${poolStats.active}`);
|
|
63
|
+
ui.log(`Idle: ${poolStats.idle}`);
|
|
64
|
+
if (poolStats.connections.length > 0) {
|
|
65
|
+
ui.log('\nConnections:');
|
|
66
|
+
for (const conn of poolStats.connections) {
|
|
67
|
+
ui.log(` • ${conn.path} (refs: ${conn.refCount}, age: ${formatAgeMs(conn.ageMs)}, consumer: ${conn.consumer})`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=dev.localdb.status.cli-command.impl.consumer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.localdb.status.cli-command.impl.consumer.js","sourceRoot":"","sources":["../../../../src/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Connection Pool
|
|
3
|
+
*
|
|
4
|
+
* Centralized connection management for all SQLite databases in vibes dev.
|
|
5
|
+
* Ensures only one connection per database file to prevent SQLITE_BUSY errors.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Singleton pattern per database path
|
|
9
|
+
* - Automatic WAL mode and busy timeout configuration
|
|
10
|
+
* - Connection reuse across consumers
|
|
11
|
+
* - Safe cleanup on process exit
|
|
12
|
+
* - Connection statistics and monitoring
|
|
13
|
+
*/
|
|
14
|
+
import { Database } from 'bun:sqlite';
|
|
15
|
+
export interface PooledConnection {
|
|
16
|
+
db: Database;
|
|
17
|
+
refCount: number;
|
|
18
|
+
lastUsed: number;
|
|
19
|
+
createdAt: number;
|
|
20
|
+
consumer: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ConnectionStats {
|
|
23
|
+
total: number;
|
|
24
|
+
active: number;
|
|
25
|
+
idle: number;
|
|
26
|
+
connections: Array<{
|
|
27
|
+
path: string;
|
|
28
|
+
refCount: number;
|
|
29
|
+
ageMs: number;
|
|
30
|
+
consumer: string;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
declare class SQLiteConnectionPool {
|
|
34
|
+
private connections;
|
|
35
|
+
private cleanupInterval?;
|
|
36
|
+
private readonly STALE_THRESHOLD_MS;
|
|
37
|
+
private readonly CLEANUP_INTERVAL_MS;
|
|
38
|
+
constructor();
|
|
39
|
+
/**
|
|
40
|
+
* Get or create a database connection with optimal configuration
|
|
41
|
+
*/
|
|
42
|
+
getConnection(dbPath: string, consumer?: string): Database;
|
|
43
|
+
/**
|
|
44
|
+
* Configure database with optimal settings for concurrent access
|
|
45
|
+
*/
|
|
46
|
+
private configureDatabase;
|
|
47
|
+
/**
|
|
48
|
+
* Release a connection (decrement reference count)
|
|
49
|
+
* Connection remains in pool for reuse
|
|
50
|
+
*/
|
|
51
|
+
releaseConnection(dbPath: string): void;
|
|
52
|
+
/**
|
|
53
|
+
* Close a specific connection immediately
|
|
54
|
+
* Only closes if reference count is zero (unless forced)
|
|
55
|
+
*/
|
|
56
|
+
closeConnection(dbPath: string, force?: boolean): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Clean up stale connections (unused for 30+ minutes with zero references)
|
|
59
|
+
*/
|
|
60
|
+
private cleanupStale;
|
|
61
|
+
/**
|
|
62
|
+
* Start periodic cleanup
|
|
63
|
+
*/
|
|
64
|
+
private startCleanup;
|
|
65
|
+
/**
|
|
66
|
+
* Stop periodic cleanup
|
|
67
|
+
*/
|
|
68
|
+
private stopCleanup;
|
|
69
|
+
/**
|
|
70
|
+
* Close all connections (typically on shutdown)
|
|
71
|
+
*/
|
|
72
|
+
closeAll(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Get pool statistics
|
|
75
|
+
*/
|
|
76
|
+
getStats(): ConnectionStats;
|
|
77
|
+
/**
|
|
78
|
+
* Register process exit handlers for cleanup
|
|
79
|
+
*/
|
|
80
|
+
private registerExitHandlers;
|
|
81
|
+
}
|
|
82
|
+
export declare const connectionPool: SQLiteConnectionPool;
|
|
83
|
+
export {};
|
|
84
|
+
//# sourceMappingURL=connection-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-pool.d.ts","sourceRoot":"","sources":["../../src/core/connection-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAMtC,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,QAAQ,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACH;AAED,cAAM,oBAAoB;IACzB,OAAO,CAAC,WAAW,CAAuC;IAC1D,OAAO,CAAC,eAAe,CAAC,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAkB;IACrD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAiB;;IAUrD;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,QAAQ;IA2B7D;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiBzB;;;OAGG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQvC;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,OAAO;IAoBvD;;OAEG;IACH,OAAO,CAAC,YAAY;IAWpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACH,QAAQ,IAAI,IAAI;IAgBhB;;OAEG;IACH,QAAQ,IAAI,eAAe;IA6B3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAW5B;AAGD,eAAO,MAAM,cAAc,sBAA6B,CAAC"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Connection Pool
|
|
3
|
+
*
|
|
4
|
+
* Centralized connection management for all SQLite databases in vibes dev.
|
|
5
|
+
* Ensures only one connection per database file to prevent SQLITE_BUSY errors.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Singleton pattern per database path
|
|
9
|
+
* - Automatic WAL mode and busy timeout configuration
|
|
10
|
+
* - Connection reuse across consumers
|
|
11
|
+
* - Safe cleanup on process exit
|
|
12
|
+
* - Connection statistics and monitoring
|
|
13
|
+
*/
|
|
14
|
+
import { Database } from 'bun:sqlite';
|
|
15
|
+
import { getLogger } from '@vibesdotdev/logging';
|
|
16
|
+
import { toErrorContext } from './error-context.js';
|
|
17
|
+
const logger = getLogger('localdb:pool');
|
|
18
|
+
class SQLiteConnectionPool {
|
|
19
|
+
connections = new Map();
|
|
20
|
+
cleanupInterval;
|
|
21
|
+
STALE_THRESHOLD_MS = 30 * 60 * 1000; // 30 minutes
|
|
22
|
+
CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
|
|
23
|
+
constructor() {
|
|
24
|
+
// Periodic cleanup of stale connections
|
|
25
|
+
this.startCleanup();
|
|
26
|
+
// Ensure proper cleanup on process exit
|
|
27
|
+
this.registerExitHandlers();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get or create a database connection with optimal configuration
|
|
31
|
+
*/
|
|
32
|
+
getConnection(dbPath, consumer = 'unknown') {
|
|
33
|
+
let pooled = this.connections.get(dbPath);
|
|
34
|
+
if (!pooled) {
|
|
35
|
+
const db = new Database(dbPath);
|
|
36
|
+
// Configure for optimal concurrent access
|
|
37
|
+
this.configureDatabase(db);
|
|
38
|
+
pooled = {
|
|
39
|
+
db,
|
|
40
|
+
refCount: 0,
|
|
41
|
+
lastUsed: Date.now(),
|
|
42
|
+
createdAt: Date.now(),
|
|
43
|
+
consumer
|
|
44
|
+
};
|
|
45
|
+
this.connections.set(dbPath, pooled);
|
|
46
|
+
logger.debug(`Created connection: ${dbPath} (${consumer})`);
|
|
47
|
+
}
|
|
48
|
+
pooled.refCount++;
|
|
49
|
+
pooled.lastUsed = Date.now();
|
|
50
|
+
return pooled.db;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Configure database with optimal settings for concurrent access
|
|
54
|
+
*/
|
|
55
|
+
configureDatabase(db) {
|
|
56
|
+
// WAL mode: Readers don't block writers, writers don't block readers
|
|
57
|
+
db.exec('PRAGMA journal_mode = WAL;');
|
|
58
|
+
// Busy timeout: Wait up to 5 seconds for locks instead of failing immediately
|
|
59
|
+
db.exec('PRAGMA busy_timeout = 5000;');
|
|
60
|
+
// Foreign keys: Enable referential integrity
|
|
61
|
+
db.exec('PRAGMA foreign_keys = ON;');
|
|
62
|
+
// Synchronous: NORMAL is safe with WAL and much faster
|
|
63
|
+
db.exec('PRAGMA synchronous = NORMAL;');
|
|
64
|
+
// Temp store: Use memory for temp tables (faster)
|
|
65
|
+
db.exec('PRAGMA temp_store = MEMORY;');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Release a connection (decrement reference count)
|
|
69
|
+
* Connection remains in pool for reuse
|
|
70
|
+
*/
|
|
71
|
+
releaseConnection(dbPath) {
|
|
72
|
+
const pooled = this.connections.get(dbPath);
|
|
73
|
+
if (pooled) {
|
|
74
|
+
pooled.refCount = Math.max(0, pooled.refCount - 1);
|
|
75
|
+
pooled.lastUsed = Date.now();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Close a specific connection immediately
|
|
80
|
+
* Only closes if reference count is zero (unless forced)
|
|
81
|
+
*/
|
|
82
|
+
closeConnection(dbPath, force = false) {
|
|
83
|
+
const pooled = this.connections.get(dbPath);
|
|
84
|
+
if (!pooled)
|
|
85
|
+
return false;
|
|
86
|
+
if (force || pooled.refCount === 0) {
|
|
87
|
+
try {
|
|
88
|
+
pooled.db.close();
|
|
89
|
+
this.connections.delete(dbPath);
|
|
90
|
+
// Use stderr to avoid breaking MCP stdio protocol
|
|
91
|
+
logger.debug(`[LocalDB] Closed connection: ${dbPath}`);
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
logger.error(`[LocalDB] Error closing ${dbPath}:`, toErrorContext(error));
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Clean up stale connections (unused for 30+ minutes with zero references)
|
|
103
|
+
*/
|
|
104
|
+
cleanupStale() {
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
for (const [dbPath, pooled] of this.connections.entries()) {
|
|
107
|
+
const age = now - pooled.lastUsed;
|
|
108
|
+
if (pooled.refCount === 0 && age > this.STALE_THRESHOLD_MS) {
|
|
109
|
+
this.closeConnection(dbPath, true);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Start periodic cleanup
|
|
115
|
+
*/
|
|
116
|
+
startCleanup() {
|
|
117
|
+
this.cleanupInterval = setInterval(() => this.cleanupStale(), this.CLEANUP_INTERVAL_MS);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Stop periodic cleanup
|
|
121
|
+
*/
|
|
122
|
+
stopCleanup() {
|
|
123
|
+
if (this.cleanupInterval) {
|
|
124
|
+
clearInterval(this.cleanupInterval);
|
|
125
|
+
this.cleanupInterval = undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Close all connections (typically on shutdown)
|
|
130
|
+
*/
|
|
131
|
+
closeAll() {
|
|
132
|
+
this.stopCleanup();
|
|
133
|
+
for (const [dbPath, pooled] of this.connections.entries()) {
|
|
134
|
+
try {
|
|
135
|
+
pooled.db.close();
|
|
136
|
+
// Use stderr to avoid breaking MCP stdio protocol
|
|
137
|
+
logger.debug(`[LocalDB] Closed connection on shutdown: ${dbPath}`);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
logger.error(`[LocalDB] Error closing ${dbPath}:`, toErrorContext(error));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
this.connections.clear();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get pool statistics
|
|
147
|
+
*/
|
|
148
|
+
getStats() {
|
|
149
|
+
let active = 0;
|
|
150
|
+
let idle = 0;
|
|
151
|
+
const connections = [];
|
|
152
|
+
const now = Date.now();
|
|
153
|
+
for (const [path, pooled] of this.connections.entries()) {
|
|
154
|
+
if (pooled.refCount > 0) {
|
|
155
|
+
active++;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
idle++;
|
|
159
|
+
}
|
|
160
|
+
connections.push({
|
|
161
|
+
path,
|
|
162
|
+
refCount: pooled.refCount,
|
|
163
|
+
ageMs: now - pooled.createdAt,
|
|
164
|
+
consumer: pooled.consumer
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
total: this.connections.size,
|
|
169
|
+
active,
|
|
170
|
+
idle,
|
|
171
|
+
connections
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Register process exit handlers for cleanup
|
|
176
|
+
*/
|
|
177
|
+
registerExitHandlers() {
|
|
178
|
+
process.on('beforeExit', () => this.closeAll());
|
|
179
|
+
process.on('SIGINT', () => {
|
|
180
|
+
this.closeAll();
|
|
181
|
+
process.exit(0);
|
|
182
|
+
});
|
|
183
|
+
process.on('SIGTERM', () => {
|
|
184
|
+
this.closeAll();
|
|
185
|
+
process.exit(0);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Singleton instance
|
|
190
|
+
export const connectionPool = new SQLiteConnectionPool();
|
|
191
|
+
//# sourceMappingURL=connection-pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-pool.js","sourceRoot":"","sources":["../../src/core/connection-pool.ts"],"names":[],"mappings":"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"}
|