spindb 0.34.3 → 0.34.5
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/cli/commands/attach.ts +38 -9
- package/cli/commands/backups.ts +5 -0
- package/cli/commands/connect.ts +6 -6
- package/cli/commands/detach.ts +16 -9
- package/cli/commands/doctor.ts +2 -2
- package/cli/commands/duckdb.ts +273 -0
- package/cli/commands/edit.ts +31 -21
- package/cli/commands/info.ts +26 -16
- package/cli/commands/list.ts +44 -26
- package/cli/commands/menu/update-handlers.ts +2 -2
- package/cli/commands/sqlite.ts +21 -0
- package/cli/index.ts +2 -0
- package/engines/duckdb/scanner.ts +22 -0
- package/engines/file-based-utils.ts +262 -0
- package/engines/sqlite/scanner.ts +11 -88
- package/package.json +1 -1
|
@@ -1,99 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SQLite Scanner
|
|
3
|
-
*
|
|
4
|
-
* Scans directories for unregistered SQLite database files.
|
|
5
|
-
* Used to detect SQLite databases in the current working directory
|
|
6
|
-
* that are not yet registered with SpinDB.
|
|
2
|
+
* SQLite Scanner — thin wrapper around shared file-based-utils
|
|
7
3
|
*/
|
|
8
4
|
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
import { Engine } from '../../types'
|
|
6
|
+
import {
|
|
7
|
+
scanForUnregisteredFiles,
|
|
8
|
+
deriveContainerName as sharedDeriveContainerName,
|
|
9
|
+
type UnregisteredFile,
|
|
10
|
+
} from '../file-based-utils'
|
|
13
11
|
|
|
14
|
-
export type UnregisteredFile
|
|
15
|
-
fileName: string
|
|
16
|
-
absolutePath: string
|
|
17
|
-
}
|
|
12
|
+
export type { UnregisteredFile }
|
|
18
13
|
|
|
19
|
-
/**
|
|
20
|
-
* Scan a directory for unregistered SQLite files
|
|
21
|
-
* Returns files with .sqlite, .sqlite3, or .db extensions
|
|
22
|
-
* that are not already in the registry
|
|
23
|
-
*
|
|
24
|
-
* @param directory Directory to scan (defaults to CWD)
|
|
25
|
-
* @returns Array of unregistered SQLite files
|
|
26
|
-
*/
|
|
27
14
|
export async function scanForUnregisteredSqliteFiles(
|
|
28
|
-
directory
|
|
15
|
+
directory?: string,
|
|
29
16
|
): Promise<UnregisteredFile[]> {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Check if folder is ignored
|
|
33
|
-
if (await sqliteRegistry.isFolderIgnored(absoluteDir)) {
|
|
34
|
-
return []
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Check if directory exists
|
|
38
|
-
if (!existsSync(absoluteDir)) {
|
|
39
|
-
return []
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
// Get all files in directory
|
|
44
|
-
const entries = await readdir(absoluteDir, { withFileTypes: true })
|
|
45
|
-
|
|
46
|
-
// Filter for SQLite files
|
|
47
|
-
const sqliteFiles = entries
|
|
48
|
-
.filter((e) => e.isFile())
|
|
49
|
-
.filter((e) => /\.(sqlite3?|db)$/i.test(e.name))
|
|
50
|
-
.map((e) => ({
|
|
51
|
-
fileName: e.name,
|
|
52
|
-
absolutePath: resolve(absoluteDir, e.name),
|
|
53
|
-
}))
|
|
54
|
-
|
|
55
|
-
// Filter out already registered files
|
|
56
|
-
const unregistered: UnregisteredFile[] = []
|
|
57
|
-
for (const file of sqliteFiles) {
|
|
58
|
-
if (!(await sqliteRegistry.isPathRegistered(file.absolutePath))) {
|
|
59
|
-
unregistered.push(file)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return unregistered
|
|
64
|
-
} catch {
|
|
65
|
-
// If we can't read the directory, return empty
|
|
66
|
-
return []
|
|
67
|
-
}
|
|
17
|
+
return scanForUnregisteredFiles(Engine.SQLite, directory)
|
|
68
18
|
}
|
|
69
19
|
|
|
70
|
-
/**
|
|
71
|
-
* Derive a valid container name from a filename
|
|
72
|
-
* Removes extension and converts to valid container name format:
|
|
73
|
-
* - Must start with a letter
|
|
74
|
-
* - Can contain letters, numbers, hyphens, underscores
|
|
75
|
-
*
|
|
76
|
-
* @param fileName The SQLite filename (e.g., "my-database.sqlite")
|
|
77
|
-
* @returns A valid container name (e.g., "my-database")
|
|
78
|
-
*/
|
|
79
20
|
export function deriveContainerName(fileName: string): string {
|
|
80
|
-
|
|
81
|
-
const base = fileName.replace(/\.(sqlite3?|db)$/i, '')
|
|
82
|
-
|
|
83
|
-
// Convert to valid container name (alphanumeric, hyphens, underscores)
|
|
84
|
-
// Replace invalid chars with hyphens
|
|
85
|
-
let name = base.replace(/[^a-zA-Z0-9_-]/g, '-')
|
|
86
|
-
|
|
87
|
-
// Ensure starts with letter
|
|
88
|
-
if (!/^[a-zA-Z]/.test(name)) {
|
|
89
|
-
name = 'db-' + name
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Remove consecutive hyphens
|
|
93
|
-
name = name.replace(/-+/g, '-')
|
|
94
|
-
|
|
95
|
-
// Trim leading/trailing hyphens
|
|
96
|
-
name = name.replace(/^-+|-+$/g, '')
|
|
97
|
-
|
|
98
|
-
return name || 'sqlite-db'
|
|
21
|
+
return sharedDeriveContainerName(fileName, Engine.SQLite)
|
|
99
22
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spindb",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.5",
|
|
4
4
|
"author": "Bob Bass <bob@bbass.co>",
|
|
5
5
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
6
6
|
"description": "Zero-config Docker-free local database containers. Create, backup, and clone a variety of popular databases.",
|