@codexa/cli 9.0.35 → 9.0.36
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/commands/migrate.ts +137 -0
- package/package.json +1 -1
- package/workflow.ts +10 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { createClient, type Client } from "@libsql/client";
|
|
2
|
+
import { initSchema } from "../db/schema";
|
|
3
|
+
import { getDb } from "../db/connection";
|
|
4
|
+
import { existsSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
|
|
7
|
+
const TABLES_IN_ORDER = [
|
|
8
|
+
"specs",
|
|
9
|
+
"project",
|
|
10
|
+
"standards",
|
|
11
|
+
"product_context",
|
|
12
|
+
"lib_contexts",
|
|
13
|
+
"agent_lib_mappings",
|
|
14
|
+
"implementation_patterns",
|
|
15
|
+
"architectural_analyses",
|
|
16
|
+
"project_utilities",
|
|
17
|
+
"schema_migrations",
|
|
18
|
+
"context",
|
|
19
|
+
"tasks",
|
|
20
|
+
"decisions",
|
|
21
|
+
"artifacts",
|
|
22
|
+
"review",
|
|
23
|
+
"snapshots",
|
|
24
|
+
"knowledge",
|
|
25
|
+
"gate_bypasses",
|
|
26
|
+
"product_goals",
|
|
27
|
+
"product_features",
|
|
28
|
+
"knowledge_graph",
|
|
29
|
+
"reasoning_log",
|
|
30
|
+
"agent_performance",
|
|
31
|
+
"knowledge_acknowledgments",
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
interface MigrateOptions {
|
|
35
|
+
dbPath?: string;
|
|
36
|
+
dryRun?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function migrateToTurso(options: MigrateOptions = {}): Promise<void> {
|
|
40
|
+
const localPath = options.dbPath || join(process.cwd(), ".codexa", "db", "workflow.db");
|
|
41
|
+
|
|
42
|
+
if (!existsSync(localPath)) {
|
|
43
|
+
console.error(`\nArquivo nao encontrado: ${localPath}`);
|
|
44
|
+
console.error("Use --db-path para especificar o caminho do workflow.db\n");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(`\n${"═".repeat(50)}`);
|
|
49
|
+
console.log("MIGRACAO: SQLite local → Turso");
|
|
50
|
+
console.log(`${"═".repeat(50)}\n`);
|
|
51
|
+
console.log(`Origem: ${localPath}`);
|
|
52
|
+
|
|
53
|
+
// 1. Abrir DB local via @libsql/client file: mode
|
|
54
|
+
const localClient = createClient({ url: `file:${localPath}` });
|
|
55
|
+
|
|
56
|
+
// 2. Garantir que o schema remoto esta atualizado
|
|
57
|
+
console.log("Destino: inicializando schema no Turso...");
|
|
58
|
+
await initSchema();
|
|
59
|
+
const remoteClient = getDb();
|
|
60
|
+
|
|
61
|
+
const remoteUrl = process.env.CODEXA_DB_URL || "(config.json)";
|
|
62
|
+
console.log(`Destino: ${remoteUrl}\n`);
|
|
63
|
+
|
|
64
|
+
if (options.dryRun) {
|
|
65
|
+
console.log("[DRY RUN] Nenhum dado sera escrito.\n");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 3. Para cada tabela, ler colunas do schema remoto
|
|
69
|
+
let totalRows = 0;
|
|
70
|
+
let totalTables = 0;
|
|
71
|
+
|
|
72
|
+
for (const table of TABLES_IN_ORDER) {
|
|
73
|
+
// Verificar se a tabela existe no local
|
|
74
|
+
const localTableCheck = await localClient.execute({
|
|
75
|
+
sql: "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
|
|
76
|
+
args: [table],
|
|
77
|
+
});
|
|
78
|
+
if (localTableCheck.rows.length === 0) continue;
|
|
79
|
+
|
|
80
|
+
// Pegar colunas do schema remoto (as que importam)
|
|
81
|
+
const remoteColumns = await remoteClient.execute(`PRAGMA table_info(${table})`);
|
|
82
|
+
const columnNames = remoteColumns.rows.map((r: any) => r.name as string);
|
|
83
|
+
|
|
84
|
+
if (columnNames.length === 0) continue;
|
|
85
|
+
|
|
86
|
+
// Pegar colunas do local para saber quais existem nos dois
|
|
87
|
+
const localColumns = await localClient.execute(`PRAGMA table_info(${table})`);
|
|
88
|
+
const localColumnNames = new Set(localColumns.rows.map((r: any) => r.name as string));
|
|
89
|
+
|
|
90
|
+
// Usar apenas colunas que existem em ambos
|
|
91
|
+
const commonColumns = columnNames.filter((c) => localColumnNames.has(c));
|
|
92
|
+
if (commonColumns.length === 0) continue;
|
|
93
|
+
|
|
94
|
+
// Ler dados do local (apenas colunas comuns)
|
|
95
|
+
const selectSql = `SELECT ${commonColumns.map((c) => `"${c}"`).join(", ")} FROM "${table}"`;
|
|
96
|
+
const localData = await localClient.execute(selectSql);
|
|
97
|
+
|
|
98
|
+
if (localData.rows.length === 0) continue;
|
|
99
|
+
|
|
100
|
+
const count = localData.rows.length;
|
|
101
|
+
totalRows += count;
|
|
102
|
+
totalTables++;
|
|
103
|
+
|
|
104
|
+
if (options.dryRun) {
|
|
105
|
+
console.log(` ${table}: ${count} registros`);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Inserir no remoto em batches (max 20 statements por batch)
|
|
110
|
+
const placeholders = commonColumns.map(() => "?").join(", ");
|
|
111
|
+
const insertSql = `INSERT OR IGNORE INTO "${table}" (${commonColumns.map((c) => `"${c}"`).join(", ")}) VALUES (${placeholders})`;
|
|
112
|
+
|
|
113
|
+
const BATCH_SIZE = 20;
|
|
114
|
+
for (let i = 0; i < localData.rows.length; i += BATCH_SIZE) {
|
|
115
|
+
const batch = localData.rows.slice(i, i + BATCH_SIZE);
|
|
116
|
+
await remoteClient.batch(
|
|
117
|
+
batch.map((row: any) => ({
|
|
118
|
+
sql: insertSql,
|
|
119
|
+
args: commonColumns.map((col) => row[col] ?? null),
|
|
120
|
+
})),
|
|
121
|
+
"write"
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
console.log(` ${table}: ${count} registros migrados`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
localClient.close();
|
|
129
|
+
|
|
130
|
+
console.log(`\n${"─".repeat(50)}`);
|
|
131
|
+
if (options.dryRun) {
|
|
132
|
+
console.log(`[DRY RUN] ${totalRows} registros em ${totalTables} tabelas seriam migrados.`);
|
|
133
|
+
} else {
|
|
134
|
+
console.log(`Migracao concluida: ${totalRows} registros em ${totalTables} tabelas.`);
|
|
135
|
+
}
|
|
136
|
+
console.log();
|
|
137
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codexa/cli",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.36",
|
|
4
4
|
"description": "Orchestrated workflow system for Claude Code - manages feature development through parallel subagents with structured phases, gates, and quality enforcement.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/workflow.ts
CHANGED
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
architectCancel,
|
|
42
42
|
} from "./commands/architect";
|
|
43
43
|
import { teamSuggest } from "./commands/team";
|
|
44
|
+
import { migrateToTurso } from "./commands/migrate";
|
|
44
45
|
import { initSchema } from "./db/schema";
|
|
45
46
|
import { closeDb, dbGet, dbRun, ensureDatabase, getResolvedDbUrl } from "./db/connection";
|
|
46
47
|
import { execSync } from "child_process";
|
|
@@ -574,6 +575,15 @@ program
|
|
|
574
575
|
console.log(`\nBanco de dados inicializado: ${url}\n`);
|
|
575
576
|
});
|
|
576
577
|
|
|
578
|
+
program
|
|
579
|
+
.command("migrate")
|
|
580
|
+
.description("Migra dados do SQLite local (.codexa/db/workflow.db) para o Turso")
|
|
581
|
+
.option("--db-path <path>", "Caminho do workflow.db local (padrao: .codexa/db/workflow.db)")
|
|
582
|
+
.option("--dry-run", "Simula a migracao sem escrever dados")
|
|
583
|
+
.action(async (options) => {
|
|
584
|
+
await migrateToTurso({ dbPath: options.dbPath, dryRun: options.dryRun });
|
|
585
|
+
});
|
|
586
|
+
|
|
577
587
|
// ═══════════════════════════════════════════════════════════════
|
|
578
588
|
// DISCOVER
|
|
579
589
|
// ═══════════════════════════════════════════════════════════════
|