@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.
Files changed (130) hide show
  1. package/README.md +121 -0
  2. package/SPEC.md +119 -0
  3. package/dist/cli/commands/_shared.consumer.d.ts +5 -0
  4. package/dist/cli/commands/_shared.consumer.d.ts.map +1 -0
  5. package/dist/cli/commands/_shared.consumer.js +17 -0
  6. package/dist/cli/commands/_shared.consumer.js.map +1 -0
  7. package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.d.ts +19 -0
  8. package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.d.ts.map +1 -0
  9. package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.js +19 -0
  10. package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.js.map +1 -0
  11. package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.d.ts +5 -0
  12. package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.d.ts.map +1 -0
  13. package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.js +80 -0
  14. package/dist/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.js.map +1 -0
  15. package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.d.ts +19 -0
  16. package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.d.ts.map +1 -0
  17. package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.js +16 -0
  18. package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.js.map +1 -0
  19. package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.d.ts +5 -0
  20. package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.d.ts.map +1 -0
  21. package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.js +33 -0
  22. package/dist/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.js.map +1 -0
  23. package/dist/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.d.ts +15 -0
  24. package/dist/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.d.ts.map +1 -0
  25. package/dist/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.js +15 -0
  26. package/dist/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.js.map +1 -0
  27. package/dist/cli/commands/pools/dev.localdb.pools.cli-command.impl.d.ts +5 -0
  28. package/dist/cli/commands/pools/dev.localdb.pools.cli-command.impl.d.ts.map +1 -0
  29. package/dist/cli/commands/pools/dev.localdb.pools.cli-command.impl.js +28 -0
  30. package/dist/cli/commands/pools/dev.localdb.pools.cli-command.impl.js.map +1 -0
  31. package/dist/cli/commands/query/dev.localdb.query.cli-command.descriptor.d.ts +24 -0
  32. package/dist/cli/commands/query/dev.localdb.query.cli-command.descriptor.d.ts.map +1 -0
  33. package/dist/cli/commands/query/dev.localdb.query.cli-command.descriptor.js +20 -0
  34. package/dist/cli/commands/query/dev.localdb.query.cli-command.descriptor.js.map +1 -0
  35. package/dist/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.d.ts +5 -0
  36. package/dist/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.d.ts.map +1 -0
  37. package/dist/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.js +63 -0
  38. package/dist/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.js.map +1 -0
  39. package/dist/cli/commands/status/dev.localdb.status.cli-command.descriptor.d.ts +19 -0
  40. package/dist/cli/commands/status/dev.localdb.status.cli-command.descriptor.d.ts.map +1 -0
  41. package/dist/cli/commands/status/dev.localdb.status.cli-command.descriptor.js +19 -0
  42. package/dist/cli/commands/status/dev.localdb.status.cli-command.descriptor.js.map +1 -0
  43. package/dist/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.d.ts +5 -0
  44. package/dist/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.d.ts.map +1 -0
  45. package/dist/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.js +73 -0
  46. package/dist/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.js.map +1 -0
  47. package/dist/core/connection-pool.d.ts +84 -0
  48. package/dist/core/connection-pool.d.ts.map +1 -0
  49. package/dist/core/connection-pool.js +191 -0
  50. package/dist/core/connection-pool.js.map +1 -0
  51. package/dist/core/database.d.ts +137 -0
  52. package/dist/core/database.d.ts.map +1 -0
  53. package/dist/core/database.js +347 -0
  54. package/dist/core/database.js.map +1 -0
  55. package/dist/core/error-context.d.ts +2 -0
  56. package/dist/core/error-context.d.ts.map +1 -0
  57. package/dist/core/error-context.js +17 -0
  58. package/dist/core/error-context.js.map +1 -0
  59. package/dist/core/migration-registry.d.ts +89 -0
  60. package/dist/core/migration-registry.d.ts.map +1 -0
  61. package/dist/core/migration-registry.js +226 -0
  62. package/dist/core/migration-registry.js.map +1 -0
  63. package/dist/core/runtime.d.ts +3 -0
  64. package/dist/core/runtime.d.ts.map +1 -0
  65. package/dist/core/runtime.js +17 -0
  66. package/dist/core/runtime.js.map +1 -0
  67. package/dist/dev.localdb.cli-group.descriptor.d.ts +9 -0
  68. package/dist/dev.localdb.cli-group.descriptor.d.ts.map +1 -0
  69. package/dist/dev.localdb.cli-group.descriptor.js +17 -0
  70. package/dist/dev.localdb.cli-group.descriptor.js.map +1 -0
  71. package/dist/dev.localdb.context.descriptor.d.ts +21 -0
  72. package/dist/dev.localdb.context.descriptor.d.ts.map +1 -0
  73. package/dist/dev.localdb.context.descriptor.js +12 -0
  74. package/dist/dev.localdb.context.descriptor.js.map +1 -0
  75. package/dist/dev.localdb.context.impl.consumer.d.ts +9 -0
  76. package/dist/dev.localdb.context.impl.consumer.d.ts.map +1 -0
  77. package/dist/dev.localdb.context.impl.consumer.js +10 -0
  78. package/dist/dev.localdb.context.impl.consumer.js.map +1 -0
  79. package/dist/index.d.ts +12 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +11 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/localdb.cloud.plugin.d.ts +17 -0
  84. package/dist/localdb.cloud.plugin.d.ts.map +1 -0
  85. package/dist/localdb.cloud.plugin.js +23 -0
  86. package/dist/localdb.cloud.plugin.js.map +1 -0
  87. package/dist/localdb.plugin.d.ts +8 -0
  88. package/dist/localdb.plugin.d.ts.map +1 -0
  89. package/dist/localdb.plugin.js +38 -0
  90. package/dist/localdb.plugin.js.map +1 -0
  91. package/dist/migrations/load-sql.d.ts +45 -0
  92. package/dist/migrations/load-sql.d.ts.map +1 -0
  93. package/dist/migrations/load-sql.js +117 -0
  94. package/dist/migrations/load-sql.js.map +1 -0
  95. package/dist/schemas/api.d.ts +82 -0
  96. package/dist/schemas/api.d.ts.map +1 -0
  97. package/dist/schemas/api.js +2 -0
  98. package/dist/schemas/api.js.map +1 -0
  99. package/package.json +146 -0
  100. package/src/cli/commands/_shared.consumer.ts +20 -0
  101. package/src/cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.ts +20 -0
  102. package/src/cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.ts +97 -0
  103. package/src/cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.ts +17 -0
  104. package/src/cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.ts +46 -0
  105. package/src/cli/commands/pools/dev.localdb.pools.cli-command.descriptor.ts +16 -0
  106. package/src/cli/commands/pools/dev.localdb.pools.cli-command.impl.ts +37 -0
  107. package/src/cli/commands/query/dev.localdb.query.cli-command.descriptor.ts +21 -0
  108. package/src/cli/commands/query/dev.localdb.query.cli-command.impl.consumer.ts +69 -0
  109. package/src/cli/commands/status/dev.localdb.status.cli-command.descriptor.ts +20 -0
  110. package/src/cli/commands/status/dev.localdb.status.cli-command.impl.consumer.ts +93 -0
  111. package/src/core/connection-pool.ts +240 -0
  112. package/src/core/database.ts +419 -0
  113. package/src/core/error-context.ts +19 -0
  114. package/src/core/migration-registry.ts +321 -0
  115. package/src/core/runtime.ts +17 -0
  116. package/src/dev.localdb.cli-group.descriptor.ts +20 -0
  117. package/src/dev.localdb.context.descriptor.ts +13 -0
  118. package/src/dev.localdb.context.impl.consumer.ts +12 -0
  119. package/src/index.ts +28 -0
  120. package/src/localdb.cloud.plugin.ts +24 -0
  121. package/src/localdb.plugin.ts +43 -0
  122. package/src/migrations/atlas/001-initial-schema.sql +173 -0
  123. package/src/migrations/atlas/002-lang-server-fields.sql +12 -0
  124. package/src/migrations/atlas/003-config-id-dedup.sql +31 -0
  125. package/src/migrations/atlas/004-fix-on-conflict-constraints.sql +25 -0
  126. package/src/migrations/atlas/005-diagnostics.sql +66 -0
  127. package/src/migrations/atlas/006-diagnostic-summaries.sql +65 -0
  128. package/src/migrations/atlas/007-diagnostic-slice.sql +83 -0
  129. package/src/migrations/load-sql.ts +133 -0
  130. package/src/schemas/api.ts +92 -0
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Migration Registry
3
+ *
4
+ * Centralized registration and execution of database migrations.
5
+ * Consumers register their migrations with the registry, which ensures
6
+ * they run in order with proper error handling and version tracking.
7
+ */
8
+
9
+ import type { Database } from 'bun:sqlite';
10
+ import { getLogger } from '@vibesdotdev/logging';
11
+ import { toErrorContext } from './error-context';
12
+
13
+ const logger = getLogger('localdb:migrations');
14
+
15
+ export interface MigrationFunction {
16
+ (db: Database): void | Promise<void>;
17
+ }
18
+
19
+ export interface Migration {
20
+ version: number;
21
+ name: string;
22
+ up: MigrationFunction;
23
+ down?: MigrationFunction;
24
+ }
25
+
26
+ export interface MigrationNamespace {
27
+ namespace: string;
28
+ migrations: Migration[];
29
+ currentVersion: number;
30
+ }
31
+
32
+ class MigrationRegistry {
33
+ private namespaces = new Map<string, MigrationNamespace>();
34
+
35
+ private hasVersionTable(db: Database): boolean {
36
+ const row = db
37
+ .query<
38
+ { name: string },
39
+ []
40
+ >("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'vibes_schema_versions'")
41
+ .get();
42
+ return row?.name === 'vibes_schema_versions';
43
+ }
44
+
45
+ private ensureVersionTable(db: Database): void {
46
+ if (this.hasVersionTable(db)) return;
47
+
48
+ db.exec(`
49
+ CREATE TABLE IF NOT EXISTS vibes_schema_versions (
50
+ namespace TEXT PRIMARY KEY,
51
+ version INTEGER NOT NULL DEFAULT 0,
52
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
53
+ )
54
+ `);
55
+ }
56
+
57
+ private getLegacyUserVersion(db: Database): number {
58
+ let lastError: Error | undefined;
59
+ const maxRetries = 3;
60
+ const baseDelay = 100;
61
+
62
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
63
+ try {
64
+ const result = db.query('PRAGMA user_version').get() as { user_version: number };
65
+ return result.user_version;
66
+ } catch (error) {
67
+ lastError = error as Error;
68
+ if ((error as { code?: string })?.code === 'SQLITE_BUSY' && attempt < maxRetries - 1) {
69
+ const delay = baseDelay * Math.pow(2, attempt);
70
+ Bun.sleepSync(delay);
71
+ continue;
72
+ }
73
+ throw error;
74
+ }
75
+ }
76
+
77
+ throw lastError ?? new Error('All retries exhausted');
78
+ }
79
+
80
+ private getTrackedSchemaVersion(db: Database, namespace: string): number | null {
81
+ this.ensureVersionTable(db);
82
+
83
+ const row = db
84
+ .query<
85
+ { version: number },
86
+ [string]
87
+ >('SELECT version FROM vibes_schema_versions WHERE namespace = ?')
88
+ .get(namespace);
89
+
90
+ return row ? row.version : null;
91
+ }
92
+
93
+ private bootstrapSchemaVersion(db: Database, namespace: string): number {
94
+ const tracked = this.getTrackedSchemaVersion(db, namespace);
95
+ if (tracked !== null) return tracked;
96
+
97
+ const ns = this.namespaces.get(namespace);
98
+ if (!ns) {
99
+ throw new Error(`Unknown migration namespace: ${namespace}`);
100
+ }
101
+
102
+ const legacyVersion = this.getLegacyUserVersion(db);
103
+ const trackedNamespaceCount =
104
+ db.query<{ count: number }, []>('SELECT COUNT(*) as count FROM vibes_schema_versions').get()
105
+ ?.count ?? 0;
106
+
107
+ const bootstrapVersion =
108
+ trackedNamespaceCount === 0 && legacyVersion > 0 && legacyVersion <= ns.currentVersion
109
+ ? legacyVersion
110
+ : 0;
111
+
112
+ this.setSchemaVersion(db, namespace, bootstrapVersion);
113
+ return bootstrapVersion;
114
+ }
115
+
116
+ /**
117
+ * Register migrations for a namespace (e.g., 'atlas', 'session')
118
+ */
119
+ register(namespace: string, migrations: Migration[]): void {
120
+ if (this.namespaces.has(namespace)) {
121
+ throw new Error(`Migration namespace '${namespace}' is already registered`);
122
+ }
123
+
124
+ // Sort migrations by version
125
+ const sorted = [...migrations].sort((a, b) => a.version - b.version);
126
+
127
+ // Validate version sequence
128
+ for (let i = 0; i < sorted.length; i++) {
129
+ const expected = i + 1;
130
+ const actual = sorted[i].version;
131
+ if (actual !== expected) {
132
+ throw new Error(
133
+ `Invalid migration sequence in '${namespace}': expected version ${expected}, got ${actual}`
134
+ );
135
+ }
136
+ }
137
+
138
+ const currentVersion = sorted.length > 0 ? sorted[sorted.length - 1].version : 0;
139
+
140
+ this.namespaces.set(namespace, {
141
+ namespace,
142
+ migrations: sorted,
143
+ currentVersion
144
+ });
145
+
146
+ logger.debug(`Registered ${migrations.length} migration(s) for namespace '${namespace}'`);
147
+ }
148
+
149
+ /**
150
+ * Get current schema version from database
151
+ */
152
+ getSchemaVersion(db: Database, namespace: string): number {
153
+ return this.bootstrapSchemaVersion(db, namespace);
154
+ }
155
+
156
+ /**
157
+ * Set schema version in database
158
+ */
159
+ private setSchemaVersion(db: Database, namespace: string, version: number): void {
160
+ this.ensureVersionTable(db);
161
+
162
+ db.query(
163
+ `INSERT INTO vibes_schema_versions (namespace, version, updated_at)
164
+ VALUES (?, ?, datetime('now'))
165
+ ON CONFLICT(namespace) DO UPDATE SET
166
+ version = excluded.version,
167
+ updated_at = datetime('now')`
168
+ ).run(namespace, version);
169
+ }
170
+
171
+ /**
172
+ * Check if database needs migration
173
+ */
174
+ needsMigration(db: Database, namespace: string): boolean {
175
+ const ns = this.namespaces.get(namespace);
176
+ if (!ns) {
177
+ throw new Error(`Unknown migration namespace: ${namespace}`);
178
+ }
179
+
180
+ const currentVersion = this.getSchemaVersion(db, namespace);
181
+ return currentVersion < ns.currentVersion;
182
+ }
183
+
184
+ /**
185
+ * Check if database is from an incompatible/old migration system
186
+ * This happens when the version is higher than our max (legacy system)
187
+ */
188
+ isIncompatibleDatabase(db: Database, namespace: string): boolean {
189
+ const ns = this.namespaces.get(namespace);
190
+ if (!ns) {
191
+ return false;
192
+ }
193
+
194
+ const trackedVersion = this.getTrackedSchemaVersion(db, namespace);
195
+ if (trackedVersion === null) {
196
+ return false;
197
+ }
198
+
199
+ return trackedVersion > ns.currentVersion;
200
+ }
201
+
202
+ /**
203
+ * Run all pending migrations for a namespace
204
+ */
205
+ async runMigrations(db: Database, namespace: string): Promise<void> {
206
+ const ns = this.namespaces.get(namespace);
207
+ if (!ns) {
208
+ throw new Error(`Unknown migration namespace: ${namespace}`);
209
+ }
210
+
211
+ let currentVersion = this.getSchemaVersion(db, namespace);
212
+
213
+ logger.debug(
214
+ `Running migrations for '${namespace}' (v${currentVersion} → v${ns.currentVersion})`
215
+ );
216
+
217
+ for (const migration of ns.migrations) {
218
+ if (migration.version > currentVersion) {
219
+ logger.debug(`Applying migration ${migration.version}: ${migration.name}`);
220
+
221
+ try {
222
+ await migration.up(db);
223
+ currentVersion = migration.version;
224
+ this.setSchemaVersion(db, namespace, currentVersion);
225
+ logger.debug(`[LocalDB] Migration ${migration.version} completed`);
226
+ } catch (error) {
227
+ logger.error(
228
+ `[LocalDB] Migration ${migration.version} failed:`,
229
+ toErrorContext(error)
230
+ );
231
+ throw new Error(`Migration ${migration.version} (${migration.name}) failed: ${error}`);
232
+ }
233
+ }
234
+ }
235
+
236
+ logger.debug(`[LocalDB] All migrations completed for '${namespace}'`);
237
+ }
238
+
239
+ /**
240
+ * Get migration status for all namespaces
241
+ */
242
+ getStatus(): Array<{
243
+ namespace: string;
244
+ currentVersion: number;
245
+ targetVersion: number;
246
+ pendingMigrations: number;
247
+ }> {
248
+ const status: Array<{
249
+ namespace: string;
250
+ currentVersion: number;
251
+ targetVersion: number;
252
+ pendingMigrations: number;
253
+ }> = [];
254
+
255
+ for (const ns of this.namespaces.values()) {
256
+ status.push({
257
+ namespace: ns.namespace,
258
+ currentVersion: 0, // Will be determined per-database
259
+ targetVersion: ns.currentVersion,
260
+ pendingMigrations: 0 // Will be determined per-database
261
+ });
262
+ }
263
+
264
+ return status;
265
+ }
266
+
267
+ /**
268
+ * Get migration status for a specific database and namespace
269
+ */
270
+ getDatabaseStatus(
271
+ db: Database,
272
+ namespace: string
273
+ ): {
274
+ namespace: string;
275
+ currentVersion: number;
276
+ targetVersion: number;
277
+ pendingMigrations: number;
278
+ migrations: Array<{ version: number; name: string; applied: boolean }>;
279
+ } {
280
+ const ns = this.namespaces.get(namespace);
281
+ if (!ns) {
282
+ throw new Error(`Unknown migration namespace: ${namespace}`);
283
+ }
284
+
285
+ const currentVersion = this.getSchemaVersion(db, namespace);
286
+ const pending = Math.max(0, ns.currentVersion - currentVersion);
287
+
288
+ return {
289
+ namespace,
290
+ currentVersion,
291
+ targetVersion: ns.currentVersion,
292
+ pendingMigrations: pending,
293
+ migrations: ns.migrations.map((m) => ({
294
+ version: m.version,
295
+ name: m.name,
296
+ applied: m.version <= currentVersion
297
+ }))
298
+ };
299
+ }
300
+
301
+ /**
302
+ * List all registered namespaces
303
+ */
304
+ listNamespaces(): string[] {
305
+ return Array.from(this.namespaces.keys());
306
+ }
307
+
308
+ /**
309
+ * Get migrations for a namespace
310
+ */
311
+ getMigrations(namespace: string): Migration[] {
312
+ const ns = this.namespaces.get(namespace);
313
+ if (!ns) {
314
+ throw new Error(`Unknown migration namespace: ${namespace}`);
315
+ }
316
+ return [...ns.migrations];
317
+ }
318
+ }
319
+
320
+ // Singleton instance
321
+ export const migrationRegistry = new MigrationRegistry();
@@ -0,0 +1,17 @@
1
+ function hasRuntimeProcessVersion(name: 'bun' | 'node'): boolean {
2
+ if (typeof process === 'undefined') return false;
3
+ const value = process.versions?.[name];
4
+ return typeof value === 'string' && value.length > 0;
5
+ }
6
+
7
+ export function isLocaldbBrowserRuntime(scope: typeof globalThis = globalThis): boolean {
8
+ const globals = scope as typeof globalThis & Record<string, unknown>;
9
+ const hasWindow = typeof globals.window !== 'undefined' && globals.window !== null;
10
+ const hasDocument = typeof globals.document !== 'undefined' && globals.document !== null;
11
+ const hasServerRuntime = hasRuntimeProcessVersion('bun') || hasRuntimeProcessVersion('node');
12
+ return hasDocument || (hasWindow && !hasServerRuntime);
13
+ }
14
+
15
+ export function isLocaldbServerRuntime(scope: typeof globalThis = globalThis): boolean {
16
+ return !isLocaldbBrowserRuntime(scope);
17
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Dev LocalDB CLI Group Descriptor
3
+ *
4
+ * Groups LocalDB development commands under `vibes dev localdb`.
5
+ */
6
+
7
+ import type { CLIGroupAssetDescriptor } from '@vibesdotdev/cli/schemas/types';
8
+
9
+ const descriptor: CLIGroupAssetDescriptor = {
10
+ kind: 'cli/group',
11
+ id: 'dev.localdb',
12
+ name: 'localdb',
13
+ description: 'Manage local SQLite databases (migrations, connections, status)',
14
+ parent: 'dev',
15
+ surfaces: ['cli'],
16
+ hardware: ['consumer'],
17
+ enabled: true
18
+ };
19
+
20
+ export default descriptor;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Dev LocalDB Context Descriptor
3
+ *
4
+ * Provides LocalDB API for dev commands and workflows.
5
+ */
6
+
7
+ import { createContextDescriptor } from '@vibesdotdev/runtime';
8
+
9
+ export default createContextDescriptor({
10
+ id: 'dev/localdb',
11
+ description: 'LocalDB API for managing local SQLite databases.',
12
+ hardware: ['consumer']
13
+ });
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Dev LocalDB Context Implementation (Consumer)
3
+ */
4
+
5
+ import type { LocaldbApi } from './schemas/api';
6
+
7
+ export default {
8
+ provide: async (): Promise<LocaldbApi> => {
9
+ const { localdb } = await import('./index');
10
+ return localdb;
11
+ }
12
+ };
package/src/index.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Local Database (LocalDB)
3
+ *
4
+ * Unified SQLite database management for vibes dev toolkit.
5
+ * Provides connection pooling, migration management, and consistent configuration.
6
+ */
7
+
8
+ export type {
9
+ LocaldbApi,
10
+ LocaldbRawDatabase,
11
+ LocalDatabase as LocalDatabaseInterface,
12
+ Migration,
13
+ MigrationFunction,
14
+ ConnectionStats,
15
+ ConnectionPoolApi,
16
+ MigrationRegistryApi
17
+ } from './schemas/api';
18
+
19
+ export { LocalDatabase, localdb } from './core/database';
20
+ export { connectionPool } from './core/connection-pool';
21
+ export { migrationRegistry } from './core/migration-registry';
22
+ export {
23
+ loadMigrationSQL,
24
+ loadMigrationSQLSync,
25
+ listMigrationFiles,
26
+ parseVersionFromFilename,
27
+ parseMigrationName
28
+ } from './migrations/load-sql';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * LocalDB Cloud Plugin
3
+ *
4
+ * Cloud-bundle-safe variant of `localdb.plugin.ts`.
5
+ *
6
+ * LocalDB manages on-disk SQLite (libsql / better-sqlite3) for consumer
7
+ * environments. Every loader in `localdb.plugin.ts` is `.impl.consumer.ts`
8
+ * and reaches `bun:sqlite` / `node:fs`. None of it is reachable from a
9
+ * cloudflare-workers bundle.
10
+ *
11
+ * ai-web's plugin chain still loads localdb for shape uniformity per
12
+ * `apps/ai-web (consolidated)/SPEC.md` line 14. This empty cloud variant satisfies
13
+ * the chain without pulling consumer-only code into the cloud bundle.
14
+ */
15
+
16
+ import { createRuntimePlugin } from '@vibesdotdev/runtime';
17
+
18
+ export default createRuntimePlugin({
19
+ // Same id as the consumer `localdb` plugin per AGENT-CONSTITUTION
20
+ // §PLUGIN ID PARITY: the bare id is the public capability.
21
+ id: 'localdb',
22
+ name: 'LocalDB (Cloud)',
23
+ description: 'Cloud-safe localdb registration — empty (localdb is consumer-only)'
24
+ });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * LocalDB Plugin
3
+ *
4
+ * Local SQLite database management — migrations, connections, status.
5
+ */
6
+
7
+ import { createRuntimePlugin, loader } from '@vibesdotdev/runtime';
8
+
9
+ // CLI
10
+ import localdbGroup from './dev.localdb.cli-group.descriptor.ts';
11
+ import localdbMigrate from './cli/commands/migrate/dev.localdb.migrate.cli-command.descriptor.ts';
12
+ import localdbNamespaces from './cli/commands/namespaces/dev.localdb.namespaces.cli-command.descriptor.ts';
13
+ import localdbPools from './cli/commands/pools/dev.localdb.pools.cli-command.descriptor.ts';
14
+ import localdbQuery from './cli/commands/query/dev.localdb.query.cli-command.descriptor.ts';
15
+ import localdbStatus from './cli/commands/status/dev.localdb.status.cli-command.descriptor.ts';
16
+
17
+ // Context
18
+ import localdbContextDescriptor from './dev.localdb.context.descriptor.ts';
19
+
20
+ export default createRuntimePlugin({
21
+ id: 'localdb',
22
+ name: 'LocalDB',
23
+ description: 'Local SQLite database management — migrations, connections, status',
24
+
25
+ descriptors: [
26
+ localdbGroup,
27
+ localdbMigrate,
28
+ localdbNamespaces,
29
+ localdbPools,
30
+ localdbQuery,
31
+ localdbStatus,
32
+ localdbContextDescriptor
33
+ ],
34
+
35
+ loaders: [
36
+ loader('dev.localdb.migrate', 'consumer', () => import('./cli/commands/migrate/dev.localdb.migrate.cli-command.impl.consumer.ts')),
37
+ loader('dev.localdb.namespaces', () => import('./cli/commands/namespaces/dev.localdb.namespaces.cli-command.impl.ts')),
38
+ loader('dev.localdb.pools', () => import('./cli/commands/pools/dev.localdb.pools.cli-command.impl.ts')),
39
+ loader('dev.localdb.query', 'consumer', () => import('./cli/commands/query/dev.localdb.query.cli-command.impl.consumer.ts')),
40
+ loader('dev.localdb.status', 'consumer', () => import('./cli/commands/status/dev.localdb.status.cli-command.impl.consumer.ts')),
41
+ loader('dev/localdb', 'consumer', () => import('./dev.localdb.context.impl.consumer.ts'))
42
+ ]
43
+ });
@@ -0,0 +1,173 @@
1
+ -- Atlas Migration 001: Initial Schema
2
+ -- Creates all tables for code indexing
3
+
4
+ -- Index configurations
5
+ CREATE TABLE IF NOT EXISTS index_configs (
6
+ id TEXT PRIMARY KEY,
7
+ project_id TEXT NOT NULL,
8
+ branch TEXT NOT NULL DEFAULT 'main',
9
+ git_commit TEXT,
10
+ workspace_path TEXT NOT NULL,
11
+ paths TEXT NOT NULL,
12
+ exclude_paths TEXT NOT NULL,
13
+ languages TEXT NOT NULL,
14
+ storage_backend TEXT NOT NULL,
15
+ runtime TEXT NOT NULL,
16
+ package_manager TEXT NOT NULL,
17
+ enable_embeddings INTEGER NOT NULL DEFAULT 0,
18
+ redact_patterns TEXT NOT NULL,
19
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
20
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
21
+ );
22
+
23
+ CREATE INDEX idx_configs_project ON index_configs(project_id);
24
+
25
+ -- Index runs
26
+ CREATE TABLE IF NOT EXISTS index_runs (
27
+ id TEXT PRIMARY KEY,
28
+ config_id TEXT NOT NULL,
29
+ status TEXT NOT NULL CHECK(status IN ('pending', 'running', 'completed', 'failed', 'cancelled')),
30
+ started_at TEXT NOT NULL,
31
+ completed_at TEXT,
32
+ files_processed INTEGER NOT NULL DEFAULT 0,
33
+ symbols_captured INTEGER NOT NULL DEFAULT 0,
34
+ errors TEXT NOT NULL DEFAULT '[]',
35
+ worker_job_id TEXT,
36
+ duration_ms INTEGER,
37
+ memory_usage_bytes INTEGER,
38
+ cpu_usage_percent REAL,
39
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
40
+ FOREIGN KEY (config_id) REFERENCES index_configs(id) ON DELETE CASCADE
41
+ );
42
+
43
+ CREATE INDEX idx_runs_config ON index_runs(config_id);
44
+ CREATE INDEX idx_runs_status ON index_runs(status);
45
+ CREATE INDEX idx_runs_started_at ON index_runs(started_at DESC);
46
+
47
+ -- Symbols
48
+ CREATE TABLE IF NOT EXISTS symbols (
49
+ id TEXT PRIMARY KEY,
50
+ run_id TEXT NOT NULL,
51
+ name TEXT NOT NULL,
52
+ kind TEXT NOT NULL CHECK(kind IN (
53
+ 'class', 'function', 'method', 'variable', 'constant',
54
+ 'interface', 'type', 'enum', 'namespace', 'module',
55
+ 'property', 'parameter', 'import', 'export'
56
+ )),
57
+ language TEXT NOT NULL,
58
+ file_path TEXT NOT NULL,
59
+ start_line INTEGER NOT NULL,
60
+ start_column INTEGER NOT NULL,
61
+ end_line INTEGER NOT NULL,
62
+ end_column INTEGER NOT NULL,
63
+ signature TEXT,
64
+ documentation TEXT,
65
+ exported INTEGER NOT NULL DEFAULT 0,
66
+ parent_symbol_id TEXT,
67
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
68
+ FOREIGN KEY (run_id) REFERENCES index_runs(id) ON DELETE CASCADE,
69
+ FOREIGN KEY (parent_symbol_id) REFERENCES symbols(id) ON DELETE SET NULL
70
+ );
71
+
72
+ CREATE INDEX idx_symbols_run ON symbols(run_id);
73
+ CREATE INDEX idx_symbols_name ON symbols(name);
74
+ CREATE INDEX idx_symbols_file ON symbols(file_path);
75
+ CREATE INDEX idx_symbols_kind ON symbols(kind);
76
+ CREATE INDEX idx_symbols_parent ON symbols(parent_symbol_id);
77
+
78
+ -- Full-text search index for symbols
79
+ CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(
80
+ name,
81
+ signature,
82
+ documentation,
83
+ content=symbols,
84
+ content_rowid=rowid
85
+ );
86
+
87
+ -- Triggers to keep FTS index in sync
88
+ CREATE TRIGGER IF NOT EXISTS symbols_fts_insert AFTER INSERT ON symbols BEGIN
89
+ INSERT INTO symbols_fts(rowid, name, signature, documentation)
90
+ VALUES (new.rowid, new.name, new.signature, new.documentation);
91
+ END;
92
+
93
+ CREATE TRIGGER IF NOT EXISTS symbols_fts_delete AFTER DELETE ON symbols BEGIN
94
+ DELETE FROM symbols_fts WHERE rowid = old.rowid;
95
+ END;
96
+
97
+ CREATE TRIGGER IF NOT EXISTS symbols_fts_update AFTER UPDATE ON symbols BEGIN
98
+ DELETE FROM symbols_fts WHERE rowid = old.rowid;
99
+ INSERT INTO symbols_fts(rowid, name, signature, documentation)
100
+ VALUES (new.rowid, new.name, new.signature, new.documentation);
101
+ END;
102
+
103
+ -- File metadata
104
+ CREATE TABLE IF NOT EXISTS files (
105
+ id TEXT PRIMARY KEY,
106
+ run_id TEXT NOT NULL,
107
+ path TEXT NOT NULL,
108
+ checksum TEXT NOT NULL,
109
+ size_bytes INTEGER NOT NULL,
110
+ language TEXT NOT NULL,
111
+ lines_of_code INTEGER NOT NULL DEFAULT 0,
112
+ imports TEXT NOT NULL DEFAULT '[]',
113
+ exports TEXT NOT NULL DEFAULT '[]',
114
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
115
+ FOREIGN KEY (run_id) REFERENCES index_runs(id) ON DELETE CASCADE
116
+ );
117
+
118
+ CREATE INDEX idx_files_run ON files(run_id);
119
+ CREATE INDEX idx_files_path ON files(path);
120
+ CREATE INDEX idx_files_checksum ON files(checksum);
121
+
122
+ -- Dependency edges
123
+ CREATE TABLE IF NOT EXISTS edges (
124
+ id TEXT PRIMARY KEY,
125
+ run_id TEXT NOT NULL,
126
+ source_file_id TEXT,
127
+ source_symbol_id TEXT,
128
+ target_file_id TEXT,
129
+ target_symbol_id TEXT,
130
+ edge_type TEXT NOT NULL CHECK(edge_type IN (
131
+ 'imports', 'calls', 'extends', 'implements', 'references'
132
+ )),
133
+ weight INTEGER NOT NULL DEFAULT 1,
134
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
135
+ FOREIGN KEY (run_id) REFERENCES index_runs(id) ON DELETE CASCADE,
136
+ FOREIGN KEY (source_file_id) REFERENCES files(id) ON DELETE CASCADE,
137
+ FOREIGN KEY (source_symbol_id) REFERENCES symbols(id) ON DELETE CASCADE,
138
+ FOREIGN KEY (target_file_id) REFERENCES files(id) ON DELETE CASCADE,
139
+ FOREIGN KEY (target_symbol_id) REFERENCES symbols(id) ON DELETE CASCADE
140
+ );
141
+
142
+ CREATE INDEX idx_edges_run ON edges(run_id);
143
+ CREATE INDEX idx_edges_source_file ON edges(source_file_id);
144
+ CREATE INDEX idx_edges_source_symbol ON edges(source_symbol_id);
145
+ CREATE INDEX idx_edges_target_file ON edges(target_file_id);
146
+ CREATE INDEX idx_edges_target_symbol ON edges(target_symbol_id);
147
+ CREATE INDEX idx_edges_type ON edges(edge_type);
148
+
149
+ -- Embeddings (for semantic search)
150
+ CREATE TABLE IF NOT EXISTS embeddings (
151
+ id TEXT PRIMARY KEY,
152
+ run_id TEXT NOT NULL,
153
+ symbol_id TEXT,
154
+ file_id TEXT,
155
+ vector_id TEXT NOT NULL,
156
+ embedding BLOB,
157
+ metadata TEXT,
158
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
159
+ FOREIGN KEY (run_id) REFERENCES index_runs(id) ON DELETE CASCADE,
160
+ FOREIGN KEY (symbol_id) REFERENCES symbols(id) ON DELETE CASCADE,
161
+ FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE CASCADE
162
+ );
163
+
164
+ CREATE INDEX idx_embeddings_run ON embeddings(run_id);
165
+ CREATE INDEX idx_embeddings_symbol ON embeddings(symbol_id);
166
+ CREATE INDEX idx_embeddings_file ON embeddings(file_id);
167
+
168
+ -- Performance optimizations
169
+ PRAGMA journal_mode = WAL;
170
+ PRAGMA synchronous = NORMAL;
171
+ PRAGMA cache_size = -64000; -- 64MB cache
172
+ PRAGMA temp_store = memory;
173
+ PRAGMA mmap_size = 30000000000; -- 30GB mmap
@@ -0,0 +1,12 @@
1
+ -- Atlas Migration 002: Language Server Integration Fields
2
+ -- Adds fields for lang server enrichment and validation
3
+
4
+ -- Add lang server config options to index_configs
5
+ ALTER TABLE index_configs ADD COLUMN enable_lang_server_enrichment INTEGER NOT NULL DEFAULT 0;
6
+ ALTER TABLE index_configs ADD COLUMN enable_lang_server_validation INTEGER NOT NULL DEFAULT 1;
7
+ ALTER TABLE index_configs ADD COLUMN lang_server_timeout INTEGER NOT NULL DEFAULT 2000;
8
+
9
+ -- Add lang server enrichment fields to symbols
10
+ ALTER TABLE symbols ADD COLUMN type_signature TEXT;
11
+ ALTER TABLE symbols ADD COLUMN has_errors INTEGER DEFAULT 0;
12
+ ALTER TABLE symbols ADD COLUMN error_messages TEXT;