@aaronshaf/ger
Version:
Gerrit CLI and SDK - A modern CLI tool and TypeScript SDK for Gerrit Code Review, built with Effect-TS
84 lines (77 loc) • 2.9 kB
text/typescript
import { Schema } from '@effect/schema'
import { Effect, pipe } from 'effect'
import { type ApiError, GerritApiService } from '@/api/gerrit'
import type { DiffOptions, DiffCommandOptions } from '@/schemas/gerrit'
import { DiffCommandOptions as DiffCommandOptionsSchema } from '@/schemas/gerrit'
import { formatDiffPretty, formatFilesList } from '@/utils/diff-formatters'
import { sanitizeCDATA, escapeXML } from '@/utils/shell-safety'
export const diffCommand = (
changeId: string,
options: DiffCommandOptions,
): Effect.Effect<void, ApiError | Error, GerritApiService> =>
Effect.gen(function* () {
// Validate input options using Effect Schema
const validatedOptions = yield* pipe(
options,
Schema.decodeUnknown(DiffCommandOptionsSchema, {
errors: 'all',
onExcessProperty: 'ignore',
}),
Effect.mapError(() => new Error('Invalid diff command options')),
)
const apiService = yield* GerritApiService
const diffOptions: DiffOptions = {
format: validatedOptions.filesOnly ? 'files' : validatedOptions.format || 'unified',
file: validatedOptions.file,
}
const diff = yield* apiService
.getDiff(changeId, diffOptions)
.pipe(
Effect.catchTag('ApiError', (error) =>
Effect.fail(new Error(`Failed to get diff: ${error.message}`)),
),
)
if (validatedOptions.json) {
// JSON output
const jsonOutput: Record<string, unknown> = {
status: 'success',
change_id: changeId,
}
if (Array.isArray(diff)) {
jsonOutput.files = diff
} else {
jsonOutput.content = diff
}
console.log(JSON.stringify(jsonOutput, null, 2))
} else if (validatedOptions.xml) {
// XML output for LLM consumption
console.log(`<?xml version="1.0" encoding="UTF-8"?>`)
console.log(`<diff_result>`)
console.log(` <status>success</status>`)
console.log(` <change_id>${escapeXML(changeId)}</change_id>`)
if (Array.isArray(diff)) {
console.log(` <files>`)
diff.forEach((file) => {
console.log(` <file>${escapeXML(file)}</file>`)
})
console.log(` </files>`)
} else if (typeof diff === 'string') {
console.log(` <content><![CDATA[${sanitizeCDATA(diff)}]]></content>`)
} else {
console.log(
` <content><![CDATA[${sanitizeCDATA(JSON.stringify(diff, null, 2))}]]></content>`,
)
}
console.log(`</diff_result>`)
} else {
// Human-readable output (default) - pretty formatted
if (Array.isArray(diff)) {
console.log(formatFilesList(diff))
} else if (typeof diff === 'string') {
console.log(formatDiffPretty(diff))
} else {
// JSON data - format as pretty JSON for readability
console.log(JSON.stringify(diff, null, 2))
}
}
})