@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,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQL Migration Loader
|
|
3
|
+
*
|
|
4
|
+
* Utility for loading SQL migration files from the filesystem.
|
|
5
|
+
* Uses Bun's file API for fast synchronous reads.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
10
|
+
import { isLocaldbServerRuntime } from "../core/runtime.js";
|
|
11
|
+
const isServerRuntime = isLocaldbServerRuntime();
|
|
12
|
+
const __dirname = isServerRuntime ? dirname(fileURLToPath(import.meta.url)) : '';
|
|
13
|
+
function throwIfBrowser() {
|
|
14
|
+
if (!isServerRuntime) {
|
|
15
|
+
throw new Error('SQL migrations are not available in browser builds');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Load a SQL migration file by namespace and filename (async)
|
|
20
|
+
*
|
|
21
|
+
* @param namespace - The migration namespace (atlas, session, external)
|
|
22
|
+
* @param filename - The SQL filename (e.g., '001-initial-schema.sql')
|
|
23
|
+
* @returns Promise resolving to the SQL content as a string
|
|
24
|
+
*/
|
|
25
|
+
export function loadMigrationSQL(namespace, filename) {
|
|
26
|
+
throwIfBrowser();
|
|
27
|
+
const namespaceDir = resolveMigrationNamespaceDir(namespace);
|
|
28
|
+
if (!namespaceDir) {
|
|
29
|
+
throw new Error(`Migration namespace not found: ${namespace}`);
|
|
30
|
+
}
|
|
31
|
+
const filePath = join(namespaceDir, filename);
|
|
32
|
+
if (!existsSync(filePath)) {
|
|
33
|
+
throw new Error(`Migration file not found: ${filePath}`);
|
|
34
|
+
}
|
|
35
|
+
return Bun.file(filePath).text();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Synchronously load a SQL migration file
|
|
39
|
+
* Uses Node's fs.readFileSync for truly synchronous reads
|
|
40
|
+
*
|
|
41
|
+
* @param namespace - The migration namespace (atlas, session, external)
|
|
42
|
+
* @param filename - The SQL filename (e.g., '001-initial-schema.sql')
|
|
43
|
+
* @returns The SQL content as a string
|
|
44
|
+
*/
|
|
45
|
+
export function loadMigrationSQLSync(namespace, filename) {
|
|
46
|
+
throwIfBrowser();
|
|
47
|
+
const namespaceDir = resolveMigrationNamespaceDir(namespace);
|
|
48
|
+
if (!namespaceDir) {
|
|
49
|
+
throw new Error(`Migration namespace not found: ${namespace}`);
|
|
50
|
+
}
|
|
51
|
+
const filePath = join(namespaceDir, filename);
|
|
52
|
+
if (!existsSync(filePath)) {
|
|
53
|
+
throw new Error(`Migration file not found: ${filePath}`);
|
|
54
|
+
}
|
|
55
|
+
return readFileSync(filePath, 'utf-8');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* List all SQL files in a namespace directory
|
|
59
|
+
*
|
|
60
|
+
* @param namespace - The migration namespace (atlas, session, external)
|
|
61
|
+
* @returns Array of SQL filenames sorted by version number
|
|
62
|
+
*/
|
|
63
|
+
export function listMigrationFiles(namespace) {
|
|
64
|
+
throwIfBrowser();
|
|
65
|
+
const dirPath = resolveMigrationNamespaceDir(namespace);
|
|
66
|
+
if (!dirPath || !existsSync(dirPath)) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
return readdirSync(dirPath)
|
|
70
|
+
.filter((f) => f.endsWith('.sql') && !f.startsWith('.'))
|
|
71
|
+
.sort((a, b) => {
|
|
72
|
+
// Extract version numbers (e.g., '001' from '001-initial-schema.sql')
|
|
73
|
+
const versionA = parseInt(a.split('-')[0], 10);
|
|
74
|
+
const versionB = parseInt(b.split('-')[0], 10);
|
|
75
|
+
return versionA - versionB;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function resolveMigrationNamespaceDir(namespace) {
|
|
79
|
+
// If the namespace is already an absolute path that exists, use it directly.
|
|
80
|
+
// External packages (e.g. PM) pass their own migration directory as a full path.
|
|
81
|
+
if (namespace.startsWith('/') && existsSync(namespace)) {
|
|
82
|
+
return namespace;
|
|
83
|
+
}
|
|
84
|
+
// Bundled migrations are loaded from the package-local migrations directory.
|
|
85
|
+
const bundledPath = join(__dirname, namespace);
|
|
86
|
+
if (existsSync(bundledPath)) {
|
|
87
|
+
return bundledPath;
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Parse version number from a migration filename
|
|
93
|
+
*
|
|
94
|
+
* @param filename - The SQL filename (e.g., '001-initial-schema.sql')
|
|
95
|
+
* @returns The version number
|
|
96
|
+
*/
|
|
97
|
+
export function parseVersionFromFilename(filename) {
|
|
98
|
+
const match = filename.match(/^(\d+)-/);
|
|
99
|
+
if (!match) {
|
|
100
|
+
throw new Error(`Invalid migration filename format: ${filename}`);
|
|
101
|
+
}
|
|
102
|
+
return parseInt(match[1], 10);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Parse migration name from a filename
|
|
106
|
+
*
|
|
107
|
+
* @param filename - The SQL filename (e.g., '001-initial-schema.sql')
|
|
108
|
+
* @returns The migration name (e.g., 'initial_schema')
|
|
109
|
+
*/
|
|
110
|
+
export function parseMigrationName(filename) {
|
|
111
|
+
// Remove version prefix and .sql extension
|
|
112
|
+
const withoutVersion = filename.replace(/^\d+-/, '');
|
|
113
|
+
const withoutExtension = withoutVersion.replace(/\.sql$/, '');
|
|
114
|
+
// Convert hyphens to underscores
|
|
115
|
+
return withoutExtension.replace(/-/g, '_');
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=load-sql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-sql.js","sourceRoot":"","sources":["../../src/migrations/load-sql.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { Database } from 'bun:sqlite';
|
|
2
|
+
export type LocaldbBinding = string | number | bigint | boolean | null | Uint8Array;
|
|
3
|
+
export interface LocaldbQuery<T> {
|
|
4
|
+
all(...params: LocaldbBinding[]): T[];
|
|
5
|
+
get(...params: LocaldbBinding[]): T | null;
|
|
6
|
+
}
|
|
7
|
+
export interface LocaldbStatementResult {
|
|
8
|
+
changes: number;
|
|
9
|
+
lastInsertRowid: number | bigint | null;
|
|
10
|
+
}
|
|
11
|
+
export interface LocaldbStatement {
|
|
12
|
+
run(...params: LocaldbBinding[]): LocaldbStatementResult;
|
|
13
|
+
get<T>(...params: LocaldbBinding[]): T;
|
|
14
|
+
all<T>(...params: LocaldbBinding[]): T[];
|
|
15
|
+
}
|
|
16
|
+
export interface LocaldbRawDatabase {
|
|
17
|
+
exec(sql: string): void;
|
|
18
|
+
query<T>(sql: string): LocaldbQuery<T>;
|
|
19
|
+
prepare(sql: string): LocaldbStatement;
|
|
20
|
+
run(sql: string, ...params: LocaldbBinding[]): LocaldbStatementResult;
|
|
21
|
+
}
|
|
22
|
+
export type MigrationFunction = (db: Database) => void | Promise<void>;
|
|
23
|
+
export interface Migration {
|
|
24
|
+
version: number;
|
|
25
|
+
name: string;
|
|
26
|
+
up: MigrationFunction;
|
|
27
|
+
down?: MigrationFunction;
|
|
28
|
+
}
|
|
29
|
+
export interface LocalDatabase {
|
|
30
|
+
initialize(): Promise<void>;
|
|
31
|
+
getDatabase(): Database;
|
|
32
|
+
close(): void;
|
|
33
|
+
}
|
|
34
|
+
export interface ConnectionStats {
|
|
35
|
+
total: number;
|
|
36
|
+
active: number;
|
|
37
|
+
idle: number;
|
|
38
|
+
connections: Array<{
|
|
39
|
+
path: string;
|
|
40
|
+
refCount: number;
|
|
41
|
+
ageMs: number;
|
|
42
|
+
consumer: string;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
export interface MigrationRegistryApi {
|
|
46
|
+
listNamespaces(): string[];
|
|
47
|
+
getMigrations(namespace: string): Migration[];
|
|
48
|
+
getDatabaseStatus(db: Database, namespace: string): {
|
|
49
|
+
namespace: string;
|
|
50
|
+
currentVersion: number;
|
|
51
|
+
targetVersion: number;
|
|
52
|
+
pendingMigrations: number;
|
|
53
|
+
migrations: Array<{
|
|
54
|
+
version: number;
|
|
55
|
+
name: string;
|
|
56
|
+
applied: boolean;
|
|
57
|
+
}>;
|
|
58
|
+
};
|
|
59
|
+
needsMigration(db: Database, namespace: string): boolean;
|
|
60
|
+
runMigrations(db: Database, namespace: string): Promise<void>;
|
|
61
|
+
getStatus(): Array<{
|
|
62
|
+
namespace: string;
|
|
63
|
+
currentVersion: number;
|
|
64
|
+
targetVersion: number;
|
|
65
|
+
pendingMigrations: number;
|
|
66
|
+
}>;
|
|
67
|
+
}
|
|
68
|
+
export interface ConnectionPoolApi {
|
|
69
|
+
getStats(): ConnectionStats;
|
|
70
|
+
closeAll(): void;
|
|
71
|
+
}
|
|
72
|
+
export interface LocaldbApi {
|
|
73
|
+
registerMigrations(namespace: string, migrations: Migration[]): void;
|
|
74
|
+
getDatabase(namespace: string, dbPath: string, consumer?: string): Promise<LocalDatabase>;
|
|
75
|
+
getRawDatabase(dbPath: string, consumer?: string): Database;
|
|
76
|
+
releaseDatabase(namespace: string, dbPath: string): Promise<void>;
|
|
77
|
+
getPoolStats(): ConnectionStats;
|
|
78
|
+
getMigrationStatus(): ReturnType<MigrationRegistryApi['getStatus']>;
|
|
79
|
+
listNamespaces(): string[];
|
|
80
|
+
closeAll(): Promise<void>;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/schemas/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/schemas/api.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vibesdotdev/localdb",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"bun": "./src/index.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./plugin": {
|
|
15
|
+
"types": "./dist/localdb.plugin.d.ts",
|
|
16
|
+
"bun": "./src/localdb.plugin.ts",
|
|
17
|
+
"import": "./dist/localdb.plugin.js",
|
|
18
|
+
"default": "./dist/localdb.plugin.js"
|
|
19
|
+
},
|
|
20
|
+
"./cloud.plugin": {
|
|
21
|
+
"types": "./dist/localdb.cloud.plugin.d.ts",
|
|
22
|
+
"bun": "./src/localdb.cloud.plugin.ts",
|
|
23
|
+
"import": "./dist/localdb.cloud.plugin.js",
|
|
24
|
+
"default": "./dist/localdb.cloud.plugin.js"
|
|
25
|
+
},
|
|
26
|
+
"./schemas": {
|
|
27
|
+
"types": "./dist/schemas/api.d.ts",
|
|
28
|
+
"bun": "./src/schemas/api.ts",
|
|
29
|
+
"import": "./dist/schemas/api.js",
|
|
30
|
+
"default": "./dist/schemas/api.js"
|
|
31
|
+
},
|
|
32
|
+
"./migrations/load-sql": {
|
|
33
|
+
"types": "./dist/migrations/load-sql.d.ts",
|
|
34
|
+
"bun": "./src/migrations/load-sql.ts",
|
|
35
|
+
"import": "./dist/migrations/load-sql.js",
|
|
36
|
+
"default": "./dist/migrations/load-sql.js"
|
|
37
|
+
},
|
|
38
|
+
"./*": {
|
|
39
|
+
"types": "./dist/*.d.ts",
|
|
40
|
+
"bun": "./src/*.ts",
|
|
41
|
+
"import": "./dist/*.js",
|
|
42
|
+
"default": "./dist/*.js"
|
|
43
|
+
},
|
|
44
|
+
"./*.js": {
|
|
45
|
+
"types": "./dist/*.d.ts",
|
|
46
|
+
"bun": "./src/*.ts",
|
|
47
|
+
"import": "./dist/*.js",
|
|
48
|
+
"default": "./dist/*.js"
|
|
49
|
+
},
|
|
50
|
+
"./*/*": {
|
|
51
|
+
"types": "./dist/*/*.d.ts",
|
|
52
|
+
"bun": "./src/*/*.ts",
|
|
53
|
+
"import": "./dist/*/*.js",
|
|
54
|
+
"default": "./dist/*/*.js"
|
|
55
|
+
},
|
|
56
|
+
"./*/*.js": {
|
|
57
|
+
"types": "./dist/*/*.d.ts",
|
|
58
|
+
"bun": "./src/*/*.ts",
|
|
59
|
+
"import": "./dist/*/*.js",
|
|
60
|
+
"default": "./dist/*/*.js"
|
|
61
|
+
},
|
|
62
|
+
"./*/*/*": {
|
|
63
|
+
"types": "./dist/*/*/*.d.ts",
|
|
64
|
+
"bun": "./src/*/*/*.ts",
|
|
65
|
+
"import": "./dist/*/*/*.js",
|
|
66
|
+
"default": "./dist/*/*/*.js"
|
|
67
|
+
},
|
|
68
|
+
"./*/*/*.js": {
|
|
69
|
+
"types": "./dist/*/*/*.d.ts",
|
|
70
|
+
"bun": "./src/*/*/*.ts",
|
|
71
|
+
"import": "./dist/*/*/*.js",
|
|
72
|
+
"default": "./dist/*/*/*.js"
|
|
73
|
+
},
|
|
74
|
+
"./*/*/*/*": {
|
|
75
|
+
"types": "./dist/*/*/*/*.d.ts",
|
|
76
|
+
"bun": "./src/*/*/*/*.ts",
|
|
77
|
+
"import": "./dist/*/*/*/*.js",
|
|
78
|
+
"default": "./dist/*/*/*/*.js"
|
|
79
|
+
},
|
|
80
|
+
"./*/*/*/*.js": {
|
|
81
|
+
"types": "./dist/*/*/*/*.d.ts",
|
|
82
|
+
"bun": "./src/*/*/*/*.ts",
|
|
83
|
+
"import": "./dist/*/*/*/*.js",
|
|
84
|
+
"default": "./dist/*/*/*/*.js"
|
|
85
|
+
},
|
|
86
|
+
"./*/*/*/*/*": {
|
|
87
|
+
"types": "./dist/*/*/*/*/*.d.ts",
|
|
88
|
+
"bun": "./src/*/*/*/*/*.ts",
|
|
89
|
+
"import": "./dist/*/*/*/*/*.js",
|
|
90
|
+
"default": "./dist/*/*/*/*/*.js"
|
|
91
|
+
},
|
|
92
|
+
"./*/*/*/*/*.js": {
|
|
93
|
+
"types": "./dist/*/*/*/*/*.d.ts",
|
|
94
|
+
"bun": "./src/*/*/*/*/*.ts",
|
|
95
|
+
"import": "./dist/*/*/*/*/*.js",
|
|
96
|
+
"default": "./dist/*/*/*/*/*.js"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"publishConfig": {
|
|
100
|
+
"registry": "https://registry.npmjs.org",
|
|
101
|
+
"access": "public"
|
|
102
|
+
},
|
|
103
|
+
"repository": {
|
|
104
|
+
"type": "git",
|
|
105
|
+
"url": "git+https://github.com/vibesdotdev/monorepo.git",
|
|
106
|
+
"directory": "packages/localdb"
|
|
107
|
+
},
|
|
108
|
+
"peerDependencies": {
|
|
109
|
+
"@vibesdotdev/runtime": "0.0.1",
|
|
110
|
+
"@vibesdotdev/logging": "0.0.1",
|
|
111
|
+
"@vibesdotdev/cli": "0.0.1"
|
|
112
|
+
},
|
|
113
|
+
"scripts": {
|
|
114
|
+
"test": "bun test",
|
|
115
|
+
"check": "bun --bun tsc -p tsconfig.json --noEmit",
|
|
116
|
+
"build": "tsc -p tsconfig.json"
|
|
117
|
+
},
|
|
118
|
+
"license": "MIT",
|
|
119
|
+
"files": [
|
|
120
|
+
"dist",
|
|
121
|
+
"src",
|
|
122
|
+
"bin",
|
|
123
|
+
"README.md",
|
|
124
|
+
"SPEC.md",
|
|
125
|
+
"LICENSE",
|
|
126
|
+
"!src/**/__tests__/**",
|
|
127
|
+
"!src/**/__stubs__/**",
|
|
128
|
+
"!src/**/*.test.ts",
|
|
129
|
+
"!src/**/*.test.tsx",
|
|
130
|
+
"!src/**/*.spec.ts",
|
|
131
|
+
"!src/**/*.spec.tsx",
|
|
132
|
+
"!dist/**/__tests__/**",
|
|
133
|
+
"!dist/**/__stubs__/**",
|
|
134
|
+
"!dist/**/*.test.js",
|
|
135
|
+
"!dist/**/*.test.js.map",
|
|
136
|
+
"!dist/**/*.test.d.ts",
|
|
137
|
+
"!dist/**/*.test.d.ts.map",
|
|
138
|
+
"!dist/**/*.spec.js",
|
|
139
|
+
"!dist/**/*.spec.js.map",
|
|
140
|
+
"!dist/**/*.spec.d.ts",
|
|
141
|
+
"!dist/**/*.spec.d.ts.map"
|
|
142
|
+
],
|
|
143
|
+
"vibes": {
|
|
144
|
+
"visibility": "public-framework"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
|
|
3
|
+
export const databasePathsByNamespace: Record<string, string> = {
|
|
4
|
+
atlas: '.vibes/atlas/vibes.db',
|
|
5
|
+
session: '.vibes/session/sessions.db'
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function resolveDatabasePathForNamespace(namespace: string): string | undefined {
|
|
9
|
+
return databasePathsByNamespace[namespace];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function resolveFromCwd(p: string): string {
|
|
13
|
+
return resolve(process.cwd(), p);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function formatAgeMs(ageMs: number): string {
|
|
17
|
+
const ageMin = Math.floor(ageMs / 60000);
|
|
18
|
+
const ageSec = Math.floor((ageMs % 60000) / 1000);
|
|
19
|
+
return ageMin > 0 ? `${ageMin}m ${ageSec}s` : `${ageSec}s`;
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev LocalDB Migrate CLI Command Descriptor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createRuntimeAsset } from '@vibesdotdev/runtime';
|
|
6
|
+
|
|
7
|
+
export default createRuntimeAsset({
|
|
8
|
+
id: 'dev.localdb.migrate',
|
|
9
|
+
kind: 'cli/command',
|
|
10
|
+
name: 'migrate',
|
|
11
|
+
description: 'Run pending migrations',
|
|
12
|
+
group: 'dev.localdb',
|
|
13
|
+
surfaces: ['cli'],
|
|
14
|
+
hardware: ['consumer'],
|
|
15
|
+
enabled: true,
|
|
16
|
+
options: [
|
|
17
|
+
{ flags: '--namespace <name>', description: 'Run migrations for a specific namespace' },
|
|
18
|
+
{ flags: '--dry-run', description: 'Show pending migrations without applying them' }
|
|
19
|
+
]
|
|
20
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { getVibesRuntime } from '@vibesdotdev/runtime';
|
|
3
|
+
import { requestCLIExit, type UIContext } from '@vibesdotdev/cli/providers';
|
|
4
|
+
import type { LocaldbApi, MigrationRegistryApi } from '../../..';
|
|
5
|
+
import { resolveDatabasePathForNamespace, resolveFromCwd } from '../_shared.consumer';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
async execute(_args: Record<string, unknown>, opts: Record<string, unknown>): Promise<void> {
|
|
9
|
+
const runtime = getVibesRuntime();
|
|
10
|
+
const ui = (await runtime.context('cli/ui')) as UIContext;
|
|
11
|
+
const localdb = (await runtime.context('dev/localdb')) as LocaldbApi;
|
|
12
|
+
|
|
13
|
+
const namespaceOpt = typeof opts.namespace === 'string' ? opts.namespace : undefined;
|
|
14
|
+
const dryRun = Boolean(opts.dryRun);
|
|
15
|
+
|
|
16
|
+
ui.log(`\n=== LocalDB Migrate${dryRun ? ' (Dry Run)' : ''} ===\n`);
|
|
17
|
+
|
|
18
|
+
const namespaces = localdb.listNamespaces();
|
|
19
|
+
if (namespaces.length === 0) {
|
|
20
|
+
ui.info('No migration namespaces registered.');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const namespacesToMigrate = namespaceOpt
|
|
25
|
+
? namespaces.filter((ns) => ns === namespaceOpt)
|
|
26
|
+
: namespaces;
|
|
27
|
+
|
|
28
|
+
if (namespacesToMigrate.length === 0) {
|
|
29
|
+
ui.error(`Namespace '${namespaceOpt}' not found.`);
|
|
30
|
+
ui.info(`Available namespaces: ${namespaces.join(', ')}`);
|
|
31
|
+
requestCLIExit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { migrationRegistry } =
|
|
35
|
+
(await import('../../../core/migration-registry')) as {
|
|
36
|
+
migrationRegistry: MigrationRegistryApi;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let migratedCount = 0;
|
|
40
|
+
let errorCount = 0;
|
|
41
|
+
|
|
42
|
+
for (const ns of namespacesToMigrate) {
|
|
43
|
+
const dbPath = resolveDatabasePathForNamespace(ns);
|
|
44
|
+
if (!dbPath) {
|
|
45
|
+
ui.warn(`Skipping '${ns}': no known database path`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const fullPath = resolveFromCwd(dbPath);
|
|
50
|
+
if (!existsSync(fullPath)) {
|
|
51
|
+
ui.warn(`Skipping '${ns}': database not found (${dbPath})`);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
ui.log(`\nNamespace: ${ns}`);
|
|
56
|
+
ui.log(`Database: ${dbPath}`);
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const db = localdb.getRawDatabase(fullPath, 'localdb-migrate');
|
|
60
|
+
const needsMigration = migrationRegistry.needsMigration(db, ns);
|
|
61
|
+
|
|
62
|
+
if (!needsMigration) {
|
|
63
|
+
ui.success('Already up to date');
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const status = migrationRegistry.getDatabaseStatus(db, ns);
|
|
68
|
+
ui.log(
|
|
69
|
+
`Pending: ${status.pendingMigrations} migration(s) (v${status.currentVersion} → v${status.targetVersion})`
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
if (dryRun) {
|
|
73
|
+
ui.log('Would apply:');
|
|
74
|
+
for (const m of status.migrations) {
|
|
75
|
+
if (!m.applied) ui.log(` • v${m.version}: ${m.name}`);
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
await migrationRegistry.runMigrations(db, ns);
|
|
79
|
+
ui.success('Migrations completed');
|
|
80
|
+
migratedCount++;
|
|
81
|
+
}
|
|
82
|
+
} catch (error) {
|
|
83
|
+
ui.error(`Error: ${String(error)}`);
|
|
84
|
+
errorCount++;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
ui.log('\n' + '─'.repeat(50));
|
|
89
|
+
if (dryRun) {
|
|
90
|
+
ui.info(`Dry run complete. Checked ${namespacesToMigrate.length} namespace(s).`);
|
|
91
|
+
} else {
|
|
92
|
+
ui.info(`Migration complete: ${migratedCount} migrated, ${errorCount} errors`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (errorCount > 0) requestCLIExit(1);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev LocalDB Namespaces CLI Command Descriptor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createRuntimeAsset } from '@vibesdotdev/runtime';
|
|
6
|
+
|
|
7
|
+
export default createRuntimeAsset({
|
|
8
|
+
id: 'dev.localdb.namespaces',
|
|
9
|
+
kind: 'cli/command',
|
|
10
|
+
name: 'namespaces',
|
|
11
|
+
description: 'List registered migration namespaces',
|
|
12
|
+
group: 'dev.localdb',
|
|
13
|
+
surfaces: ['cli'],
|
|
14
|
+
hardware: ['consumer'],
|
|
15
|
+
enabled: true,
|
|
16
|
+
options: [{ flags: '--verbose', description: 'Show migration details for each namespace' }]
|
|
17
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getVibesRuntime } from '@vibesdotdev/runtime';
|
|
2
|
+
import type { UIContext } from '@vibesdotdev/cli/providers';
|
|
3
|
+
import type { LocaldbApi, MigrationRegistryApi } from '../../..';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
async execute(_args: Record<string, unknown>, opts: Record<string, unknown>): Promise<void> {
|
|
7
|
+
const runtime = getVibesRuntime();
|
|
8
|
+
const ui = (await runtime.context('cli/ui')) as UIContext;
|
|
9
|
+
const localdb = (await runtime.context('dev/localdb')) as LocaldbApi;
|
|
10
|
+
|
|
11
|
+
const verbose = Boolean(opts.verbose);
|
|
12
|
+
|
|
13
|
+
ui.log('\n=== Registered Migration Namespaces ===\n');
|
|
14
|
+
|
|
15
|
+
const namespaces = localdb.listNamespaces();
|
|
16
|
+
if (namespaces.length === 0) {
|
|
17
|
+
ui.info('No migration namespaces registered.');
|
|
18
|
+
ui.info('Namespaces are registered when their modules are loaded.');
|
|
19
|
+
ui.info('Try running a command that uses the database first.');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!verbose) {
|
|
24
|
+
ui.table(namespaces.map((ns) => ({ namespace: ns })));
|
|
25
|
+
ui.info('\nUse --verbose to see migration details\n');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { migrationRegistry } =
|
|
30
|
+
(await import('../../../core/migration-registry')) as {
|
|
31
|
+
migrationRegistry: MigrationRegistryApi;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
for (const ns of namespaces) {
|
|
35
|
+
ui.log(`\nNamespace: ${ns}`);
|
|
36
|
+
const migrations = migrationRegistry.getMigrations(ns);
|
|
37
|
+
ui.log(`Migrations: ${migrations.length}`);
|
|
38
|
+
|
|
39
|
+
for (const m of migrations) {
|
|
40
|
+
ui.log(` • v${m.version}: ${m.name}${m.down ? ' (reversible)' : ''}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
ui.log('\n');
|
|
45
|
+
}
|
|
46
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev LocalDB Pools CLI Command Descriptor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createRuntimeAsset } from '@vibesdotdev/runtime';
|
|
6
|
+
|
|
7
|
+
export default createRuntimeAsset({
|
|
8
|
+
id: 'dev.localdb.pools',
|
|
9
|
+
kind: 'cli/command',
|
|
10
|
+
name: 'pools',
|
|
11
|
+
description: 'Show connection pool statistics',
|
|
12
|
+
group: 'dev.localdb',
|
|
13
|
+
surfaces: ['cli'],
|
|
14
|
+
hardware: ['consumer'],
|
|
15
|
+
enabled: true
|
|
16
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getVibesRuntime } from '@vibesdotdev/runtime';
|
|
2
|
+
import type { UIContext } from '@vibesdotdev/cli/providers';
|
|
3
|
+
import type { LocaldbApi } from '../../..';
|
|
4
|
+
import { formatAgeMs } from '../_shared.consumer';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
async execute(_args: Record<string, unknown>, _opts: Record<string, unknown>): Promise<void> {
|
|
8
|
+
const runtime = getVibesRuntime();
|
|
9
|
+
const ui = (await runtime.context('cli/ui')) as UIContext;
|
|
10
|
+
const localdb = (await runtime.context('dev/localdb')) as LocaldbApi;
|
|
11
|
+
|
|
12
|
+
ui.log('\n=== Connection Pool Statistics ===\n');
|
|
13
|
+
|
|
14
|
+
const stats = localdb.getPoolStats();
|
|
15
|
+
|
|
16
|
+
ui.log(`Total Connections: ${stats.total}`);
|
|
17
|
+
ui.log(`Active (in use): ${stats.active}`);
|
|
18
|
+
ui.log(`Idle (pooled): ${stats.idle}`);
|
|
19
|
+
|
|
20
|
+
if (stats.connections.length === 0) {
|
|
21
|
+
ui.info('\nNo active connections.\n');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
ui.log('\nConnections:\n' + '─'.repeat(80));
|
|
26
|
+
ui.table(
|
|
27
|
+
stats.connections.map((c) => ({
|
|
28
|
+
path: c.path,
|
|
29
|
+
status: c.refCount > 0 ? 'ACTIVE' : 'IDLE',
|
|
30
|
+
refs: c.refCount,
|
|
31
|
+
age: formatAgeMs(c.ageMs),
|
|
32
|
+
consumer: c.consumer
|
|
33
|
+
}))
|
|
34
|
+
);
|
|
35
|
+
ui.log('');
|
|
36
|
+
}
|
|
37
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev LocalDB Query CLI Command Descriptor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createRuntimeAsset } from '@vibesdotdev/runtime';
|
|
6
|
+
|
|
7
|
+
export default createRuntimeAsset({
|
|
8
|
+
id: 'dev.localdb.query',
|
|
9
|
+
kind: 'cli/command',
|
|
10
|
+
name: 'query',
|
|
11
|
+
description: 'Execute an SQL query on a database',
|
|
12
|
+
group: 'dev.localdb',
|
|
13
|
+
surfaces: ['cli'],
|
|
14
|
+
hardware: ['consumer'],
|
|
15
|
+
enabled: true,
|
|
16
|
+
arguments: [{ name: 'sql', description: 'SQL statement to execute', required: true }],
|
|
17
|
+
options: [
|
|
18
|
+
{ flags: '--db <path>', description: 'Database file path (required)' },
|
|
19
|
+
{ flags: '--json', description: 'Output results as JSON' }
|
|
20
|
+
]
|
|
21
|
+
});
|