(args: string[])
| 223 | // --------------------------------------------------------------------------- |
| 224 | |
| 225 | export default async function dbSchema(args: string[]): Promise<void> { |
| 226 | const parsed = parseArgs(args); |
| 227 | |
| 228 | if (parsed.help === "true") { |
| 229 | console.log(`Usage: pnpm action db-schema [--db <path>] [--format json] |
| 230 | |
| 231 | Options: |
| 232 | --db <path> Path to SQLite database (default: data/app.db) |
| 233 | --format json Output as JSON instead of human-readable text |
| 234 | --help Show this help message`); |
| 235 | return; |
| 236 | } |
| 237 | |
| 238 | // Resolve database URL: --db flag → DATABASE_URL env → default file path |
| 239 | let url: string; |
| 240 | if (parsed.db) { |
| 241 | url = "file:" + path.resolve(parsed.db); |
| 242 | } else if (getDatabaseUrl()) { |
| 243 | url = getDatabaseUrl(); |
| 244 | } else { |
| 245 | url = "file:" + path.resolve(process.cwd(), "data", "app.db"); |
| 246 | } |
| 247 | |
| 248 | // Postgres path |
| 249 | if (isPostgresUrl(url)) { |
| 250 | return introspectPostgres(url, parsed); |
| 251 | } |
| 252 | |
| 253 | // SQLite / libsql path |
| 254 | const client = createClient({ |
| 255 | url, |
| 256 | authToken: getDatabaseAuthToken(), |
| 257 | }); |
| 258 | |
| 259 | try { |
| 260 | const tablesResult = await client.execute( |
| 261 | `SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`, |
| 262 | ); |
| 263 | const tables = tablesResult.rows.map((row) => ({ |
| 264 | name: row[0] as string, |
| 265 | })); |
| 266 | |
| 267 | const tableInfos: TableInfo[] = []; |
| 268 | |
| 269 | for (const t of tables) { |
| 270 | const escaped = t.name.replace(/"/g, '""'); |
| 271 | |
| 272 | const columns = await pragma(client, `PRAGMA table_info("${escaped}")`); |
| 273 | const fks = await pragma(client, `PRAGMA foreign_key_list("${escaped}")`); |
| 274 | const idxList = await pragma(client, `PRAGMA index_list("${escaped}")`); |
| 275 | |
| 276 | const indexes: { name: string; unique: boolean; columns: string[] }[] = |
| 277 | []; |
| 278 | for (const idx of idxList) { |
| 279 | const idxName = idx.name as string; |
| 280 | if (idxName.startsWith("sqlite_")) continue; |
| 281 | const idxInfo = await pragma( |
| 282 | client, |
nothing calls this directly
no test coverage detected