Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/add-debug-logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chkit": patch
---

Add debug logging via `CHKIT_DEBUG=1` environment variable. Logs config loading, command dispatch, plugin lifecycle hooks, ClickHouse queries with timing, journal operations, and per-command details to stderr.
47 changes: 38 additions & 9 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@
"@biomejs/biome": "^2.3.14",
"@changesets/cli": "^2.29.8",
"@chkit/plugin-backfill": "workspace:*",
"@chkit/plugin-obsessiondb": "workspace:*",
"@orpc/client": "1.13.4",
"@orpc/contract": "1.13.4",
"@types/node": "^24.0.0",
"p-map": "^7.0.4",
"turbo": "^2.8.20",
"typescript": "^5.8.0"
"turbo": "^2.8.21",
"typescript": "^5.8.0",
"zod": "3.25.76"
},
"dependencies": {
"wrangler": "^4.65.0"
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/src/bin/chkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { formatGlobalHelp, formatCommandHelp } from './help.js'
import { loadPluginRuntime } from './plugin-runtime.js'
import { getInternalPlugins } from './internal-plugins/index.js'
import { CLI_VERSION } from './version.js'
import { debug } from './debug.js'

const WELL_KNOWN_PLUGIN_COMMANDS: Record<string, string> = {
codegen: 'Codegen',
Expand Down Expand Up @@ -74,6 +75,7 @@ function collectPluginCommands(runtime: Awaited<ReturnType<typeof loadPluginRunt
async function main(): Promise<void> {
const argv = process.argv.slice(2)
const commandName = argv[0]
debug('cli', `chkit ${CLI_VERSION} — argv: [${argv.join(', ')}]`)

if (!commandName || commandName === '-h' || commandName === '--help') {
const configPathArg = extractConfigPath(argv)
Expand Down Expand Up @@ -135,6 +137,7 @@ async function main(): Promise<void> {
})

const resolved = registry.get(commandName)
debug('cli', `command "${commandName}" resolved: ${resolved ? (resolved.isPlugin ? 'plugin' : 'core') : 'not found'}`)

if (!resolved) {
const wellKnown = WELL_KNOWN_PLUGIN_COMMANDS[commandName]
Expand Down Expand Up @@ -188,6 +191,7 @@ main()
} catch {
// onComplete errors must not mask the original error
}
debug('cli', 'fatal error', error instanceof Error ? { message: error.message, stack: error.stack, ...(('code' in error) ? { code: (error as NodeJS.ErrnoException).code } : {}) } : error)
console.error(formatFatalError(error))
process.exit(1)
})
3 changes: 3 additions & 0 deletions packages/cli/src/bin/command-dispatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { parseFlags, UnknownFlagError, MissingFlagValueError, type ParsedFlags }
import { typedFlags } from '../plugins.js'
import type { CommandRegistry, RegisteredCommand } from './command-registry.js'
import { resolveDirs } from './config.js'
import { debug } from './debug.js'
import { GLOBAL_FLAGS } from './global-flags.js'
import { printOutput } from './json-output.js'
import type { PluginRuntime } from './plugin-runtime.js'
Expand Down Expand Up @@ -214,8 +215,10 @@ export async function runResolvedCommand(input: {
onAmbiguousPluginSubcommand?: () => void
}): Promise<void> {
if (input.resolved.isPlugin && !input.resolved.run) {
debug('dispatch', `routing to plugin command "${input.commandName}"`)
await runPluginCommand(input)
return
}
debug('dispatch', `routing to core command "${input.commandName}"`)
await runCoreOrBuiltinCommand(input)
}
3 changes: 3 additions & 0 deletions packages/cli/src/bin/commands/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { mkdir } from 'node:fs/promises'

import { summarizeDriftReasons } from '../../drift.js'
import { typedFlags, type CommandDef, type CommandRunContext } from '../../plugins.js'
import { debug } from '../debug.js'
import { GLOBAL_FLAGS } from '../global-flags.js'
import { emitJson } from '../json-output.js'
import { createJournalStore } from '../journal-store.js'
Expand All @@ -25,6 +26,7 @@ async function cmdCheck(runCtx: CommandRunContext): Promise<void> {
const jsonMode = f['--json'] === true
const tableSelector = f['--table']
const { migrationsDir, metaDir } = dirs
debug('check', `flags: strict=${strict}, json=${jsonMode}`)
await mkdir(migrationsDir, { recursive: true })

if (!ctx.hasExecutor) {
Expand Down Expand Up @@ -100,6 +102,7 @@ async function cmdCheck(runCtx: CommandRunContext): Promise<void> {
failedChecks.push(`plugin:${result.plugin}`)
}
}
debug('check', `results: pending=${pending.length}, checksumMismatches=${checksumMismatches.length}, drift=${drift?.drifted ?? 'n/a'}, pluginChecks=${pluginResults.length}, failedChecks=[${failedChecks.join(', ')}]`)
const ok = failedChecks.length === 0
const driftReasonSummary = drift
? summarizeDriftReasons({
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/src/bin/commands/drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
type ObjectDriftDetail,
type TableDriftDetail,
} from '../../drift.js'
import { debug } from '../debug.js'
import { emitJson } from '../json-output.js'
import { readSnapshot } from '../migration-store.js'
import { resolveTableScope, tableKeysFromDefinitions, type TableScope } from '../table-scope.js'
Expand Down Expand Up @@ -49,6 +50,7 @@ export async function buildDriftPayload(
if (!executor) throw new Error('clickhouse config is required for drift checks')
const db = executor

debug('drift', `building drift payload — expected: ${snapshot.definitions.length} definitions`)
let actualObjects: SchemaObjectRef[]
try {
actualObjects = await db.listSchemaObjects()
Expand Down Expand Up @@ -115,6 +117,8 @@ export async function buildDriftPayload(
.filter((item): item is NonNullable<typeof item> => item !== null)
.sort((a, b) => a.table.localeCompare(b.table))

debug('drift', `comparison: missing=${missing.length}, extra=${extra.length}, kindMismatches=${kindMismatches.length}, objectDrift=${objectDrift.length}, tableDrift=${tableDrift.length}`)

const drifted =
missing.length > 0 ||
extra.length > 0 ||
Expand Down
7 changes: 7 additions & 0 deletions packages/cli/src/bin/commands/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
resolveActiveTableMappings,
} from './generate/rename-mappings.js'
import { emitGenerateApplyOutput, emitGeneratePlanOutput } from './generate/output.js'
import { debug } from '../debug.js'

const GENERATE_FLAGS = defineFlags([
{ name: '--name', type: 'string', description: 'Migration name', placeholder: '<name>' },
Expand All @@ -60,6 +61,8 @@ async function cmdGenerate(ctx: CommandRunContext): Promise<void> {
const planMode = f['--dryrun'] === true
const jsonMode = f['--json'] === true

debug('generate', `flags: name=${migrationName ?? '(auto)'}, dryrun=${planMode}, json=${jsonMode}`)

await pluginRuntime.runOnConfigLoaded({
command: 'generate',
config,
Expand Down Expand Up @@ -119,6 +122,8 @@ async function cmdGenerate(ctx: CommandRunContext): Promise<void> {
activeTableMappings
)

debug('generate', `previous snapshot: ${previousDefinitions.length} definitions, current: ${definitions.length} definitions`)

let plan: ReturnType<typeof planDiff>
try {
plan = planDiff(remappedPreviousDefinitions, definitions)
Expand Down Expand Up @@ -173,6 +178,8 @@ async function cmdGenerate(ctx: CommandRunContext): Promise<void> {
})
: definitions

debug('generate', `plan: ${plan.operations.length} operations — writing artifacts`)

const result = await generateArtifacts({
definitions: artifactDefinitions,
migrationsDir,
Expand Down
8 changes: 8 additions & 0 deletions packages/cli/src/bin/commands/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
type DestructiveOperationMarker,
} from '../safety-markers.js'
import { databaseKeyFromOperationKey, resolveTableScope, tableKeyFromOperationKey, tableKeysFromDefinitions } from '../table-scope.js'
import { debug } from '../debug.js'

const MIGRATE_FLAGS = defineFlags([
{ name: '--apply', type: 'boolean', description: 'Apply pending migrations on ClickHouse (no prompt)' },
Expand Down Expand Up @@ -103,6 +104,7 @@ async function cmdMigrate(runCtx: CommandRunContext): Promise<void> {
const jsonMode = f['--json'] === true

const { migrationsDir, metaDir } = dirs
debug('migrate', `flags: execute=${executeRequested}, allowDestructive=${allowDestructive}, json=${jsonMode}`)

if (!ctx.hasExecutor) {
throw new Error('clickhouse config is required for migrate (journal is stored in ClickHouse)')
Expand All @@ -127,7 +129,11 @@ async function cmdMigrate(runCtx: CommandRunContext): Promise<void> {
const journal = await journalStore.readJournal()
const appliedNames = new Set(journal.applied.map((entry) => entry.name))
const pendingAll = files.filter((f) => !appliedNames.has(f))
debug('migrate', `migrations: total=${files.length}, applied=${journal.applied.length}, pending=${pendingAll.length}`)
const checksumMismatches = await findChecksumMismatches(migrationsDir, journal)
if (checksumMismatches.length > 0) {
debug('migrate', `checksum mismatches: ${checksumMismatches.map((m) => m.name).join(', ')}`)
}

if (checksumMismatches.length > 0) {
if (jsonMode) {
Expand Down Expand Up @@ -275,10 +281,12 @@ async function cmdMigrate(runCtx: CommandRunContext): Promise<void> {
const appliedNow: MigrationJournalEntry[] = []

for (const file of pending) {
debug('migrate', `applying ${file}`)
const fullPath = join(migrationsDir, file)
const sql = await readFile(fullPath, 'utf8')
const parsedStatements = extractExecutableStatements(sql)
const operationSummaries = extractMigrationOperationSummaries(sql)
debug('migrate', `${file}: ${parsedStatements.length} statements, ${operationSummaries.length} operations`)
const statements = await pluginRuntime.runOnBeforeApply({
command: 'migrate',
config,
Expand Down
3 changes: 3 additions & 0 deletions packages/cli/src/bin/commands/status.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { mkdir } from 'node:fs/promises'

import type { CommandDef, CommandRunContext } from '../../plugins.js'
import { debug } from '../debug.js'
import { emitJson } from '../json-output.js'
import { createJournalStore } from '../journal-store.js'
import { findChecksumMismatches, listMigrations } from '../migration-store.js'
Expand Down Expand Up @@ -31,6 +32,8 @@ async function cmdStatus(runCtx: CommandRunContext): Promise<void> {
const pending = files.filter((f) => !appliedNames.has(f))
const checksumMismatches = await findChecksumMismatches(migrationsDir, journal)

debug('status', `files=${files.length}, applied=${journal.applied.length}, pending=${pending.length}, checksumMismatches=${checksumMismatches.length}`)

const databaseMissing = journalStore.databaseMissing
const payload = {
migrationsDir,
Expand Down
Loading
Loading