UNPKG

@aaronshaf/ger

Version:

Gerrit CLI and SDK - A modern CLI tool and TypeScript SDK for Gerrit Code Review, built with Effect-TS

700 lines (675 loc) 23.1 kB
import { Schema } from '@effect/schema' export const GerritCredentials: Schema.Schema<{ readonly host: string readonly username: string readonly password: string }> = Schema.Struct({ host: Schema.String.pipe( Schema.pattern(/^https?:\/\/.+$/), Schema.annotations({ description: 'Gerrit server URL' }), ), username: Schema.String.pipe( Schema.minLength(1), Schema.annotations({ description: 'Gerrit username' }), ), password: Schema.String.pipe( Schema.minLength(1), Schema.annotations({ description: 'HTTP password or API token' }), ), }) export type GerritCredentials = Schema.Schema.Type<typeof GerritCredentials> export const FileInfo: Schema.Schema<{ readonly status?: 'A' | 'D' | 'R' | 'C' | 'M' readonly lines_inserted?: number readonly lines_deleted?: number readonly size?: number readonly size_delta?: number readonly old_path?: string readonly binary?: boolean }> = Schema.Struct({ status: Schema.optional(Schema.Literal('A', 'D', 'R', 'C', 'M')), // Added, Deleted, Renamed, Copied, Modified lines_inserted: Schema.optional(Schema.Number), lines_deleted: Schema.optional(Schema.Number), size_delta: Schema.optional(Schema.Number), size: Schema.optional(Schema.Number), old_path: Schema.optional(Schema.String), binary: Schema.optional(Schema.Boolean), }) export type FileInfo = Schema.Schema.Type<typeof FileInfo> type PersonDate = { readonly name: string; readonly email: string; readonly date: string } type ChangeMessage = { readonly id: string readonly message: string readonly date: string readonly _revision_number?: number readonly tag?: string } type RevisionShape = { readonly kind?: string readonly _number: number readonly created: string readonly uploader: { readonly _account_id: number readonly name?: string readonly email?: string readonly username?: string } readonly ref: string readonly fetch?: Record<string, unknown> readonly description?: string readonly commit?: { readonly commit: string readonly parents: ReadonlyArray<{ readonly commit: string; readonly subject: string }> readonly author: PersonDate readonly committer: PersonDate readonly subject: string readonly message: string } readonly files?: Record<string, FileInfo> readonly actions?: Record<string, unknown> } type ChangeReviewerAccount = { readonly _account_id?: number readonly name?: string readonly email?: string readonly username?: string readonly display_name?: string readonly tags?: ReadonlyArray<string> } const ChangeReviewerAccountInfo: Schema.Schema<ChangeReviewerAccount> = Schema.Struct({ _account_id: Schema.optional(Schema.Number), name: Schema.optional(Schema.String), email: Schema.optional(Schema.String), username: Schema.optional(Schema.String), display_name: Schema.optional(Schema.String), tags: Schema.optional(Schema.Array(Schema.String)), }) type ChangeReviewerMap = Partial< Record<'REVIEWER' | 'CC' | 'REMOVED', ReadonlyArray<ChangeReviewerAccount>> > // Account/User schema (reusable for groups and reviewers) export const AccountInfo: Schema.Schema<{ readonly _account_id: number readonly name?: string readonly email?: string readonly username?: string readonly display_name?: string readonly tags?: ReadonlyArray<string> readonly inactive?: boolean readonly status?: string }> = Schema.Struct({ _account_id: Schema.Number, name: Schema.optional(Schema.String), email: Schema.optional(Schema.String), username: Schema.optional(Schema.String), display_name: Schema.optional(Schema.String), tags: Schema.optional(Schema.Array(Schema.String)), inactive: Schema.optional(Schema.Boolean), status: Schema.optional(Schema.String), }) export type AccountInfo = Schema.Schema.Type<typeof AccountInfo> export const ChangeInfo: Schema.Schema<{ readonly id: string readonly project: string readonly branch: string readonly change_id: string readonly subject: string readonly status: 'NEW' | 'MERGED' | 'ABANDONED' | 'DRAFT' readonly created?: string readonly updated?: string readonly submitted?: string readonly insertions?: number readonly deletions?: number readonly _number: number readonly owner?: AccountInfo readonly labels?: Record< string, { readonly approved?: AccountInfo readonly rejected?: AccountInfo readonly recommended?: AccountInfo readonly disliked?: AccountInfo readonly value?: number } > readonly submittable?: boolean readonly work_in_progress?: boolean readonly is_private?: boolean readonly current_revision?: string readonly revisions?: Record<string, RevisionShape> readonly topic?: string readonly hashtags?: ReadonlyArray<string> readonly reviewers?: ChangeReviewerMap readonly mergeable?: boolean readonly unresolved_comment_count?: number readonly total_comment_count?: number readonly attention_set?: Record<string, unknown> readonly submit_type?: string readonly messages?: ReadonlyArray<ChangeMessage> }> = Schema.Struct({ id: Schema.String, project: Schema.String, branch: Schema.String, change_id: Schema.String, subject: Schema.String, status: Schema.Literal('NEW', 'MERGED', 'ABANDONED', 'DRAFT'), created: Schema.optional(Schema.String), updated: Schema.optional(Schema.String), submitted: Schema.optional(Schema.String), insertions: Schema.optional(Schema.Number), deletions: Schema.optional(Schema.Number), _number: Schema.Number, owner: Schema.optional(AccountInfo), labels: Schema.optional( Schema.Record({ key: Schema.String, value: Schema.Struct({ approved: Schema.optional(AccountInfo), rejected: Schema.optional(AccountInfo), recommended: Schema.optional(AccountInfo), disliked: Schema.optional(AccountInfo), value: Schema.optional(Schema.Number), default_value: Schema.optional(Schema.Number), blocking: Schema.optional(Schema.Boolean), optional: Schema.optional(Schema.Boolean), description: Schema.optional(Schema.String), values: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.String })), all: Schema.optional( Schema.Array( Schema.Struct({ _account_id: Schema.optional(Schema.Number), name: Schema.optional(Schema.String), email: Schema.optional(Schema.String), username: Schema.optional(Schema.String), value: Schema.optional(Schema.Number), post_submit: Schema.optional(Schema.Boolean), permitted_voting_range: Schema.optional( Schema.Struct({ min: Schema.Number, max: Schema.Number }), ), date: Schema.optional(Schema.String), tag: Schema.optional(Schema.String), }), ), ), }), }), ), submittable: Schema.optional(Schema.Boolean), work_in_progress: Schema.optional(Schema.Boolean), is_private: Schema.optional(Schema.Boolean), current_revision: Schema.optional(Schema.String), revisions: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })), topic: Schema.optional(Schema.String), hashtags: Schema.optional(Schema.Array(Schema.String)), reviewers: Schema.optional( Schema.Struct({ REVIEWER: Schema.optional(Schema.Array(ChangeReviewerAccountInfo)), CC: Schema.optional(Schema.Array(ChangeReviewerAccountInfo)), REMOVED: Schema.optional(Schema.Array(ChangeReviewerAccountInfo)), }), ), mergeable: Schema.optional(Schema.Boolean), unresolved_comment_count: Schema.optional(Schema.Number), total_comment_count: Schema.optional(Schema.Number), attention_set: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })), submit_type: Schema.optional(Schema.String), messages: Schema.optional( Schema.Array( Schema.Struct({ id: Schema.String, message: Schema.String, date: Schema.String, _revision_number: Schema.optional(Schema.Number), tag: Schema.optional(Schema.String), }), ), ), }) export type ChangeInfo = Schema.Schema.Type<typeof ChangeInfo> export const CommentInput: Schema.Schema<{ readonly message: string readonly unresolved?: boolean }> = Schema.Struct({ message: Schema.String.pipe( Schema.minLength(1), Schema.annotations({ description: 'Comment message' }), ), unresolved: Schema.optional(Schema.Boolean), }) export type CommentInput = Schema.Schema.Type<typeof CommentInput> export const CommentInfo: Schema.Schema<{ readonly id: string readonly path?: string readonly patch_set?: number readonly side?: 'PARENT' | 'REVISION' readonly line?: number readonly range?: { readonly start_line: number readonly end_line: number readonly start_character?: number readonly end_character?: number } readonly message: string readonly author?: ChangeReviewerAccount readonly updated?: string readonly unresolved?: boolean readonly in_reply_to?: string readonly tag?: string readonly change_message_id?: string readonly commit_id?: string }> = Schema.Struct({ id: Schema.String, path: Schema.optional(Schema.String), patch_set: Schema.optional(Schema.Number), side: Schema.optional(Schema.Literal('PARENT', 'REVISION')), line: Schema.optional(Schema.Number), range: Schema.optional( Schema.Struct({ start_line: Schema.Number, end_line: Schema.Number, start_character: Schema.optional(Schema.Number), end_character: Schema.optional(Schema.Number), }), ), message: Schema.String, author: Schema.optional(ChangeReviewerAccountInfo), updated: Schema.optional(Schema.String), unresolved: Schema.optional(Schema.Boolean), in_reply_to: Schema.optional(Schema.String), tag: Schema.optional(Schema.String), change_message_id: Schema.optional(Schema.String), commit_id: Schema.optional(Schema.String), }) export type CommentInfo = Schema.Schema.Type<typeof CommentInfo> export const MessageInfo: Schema.Schema<{ readonly id: string readonly message: string readonly author?: AccountInfo readonly real_author?: AccountInfo readonly date: string readonly _revision_number?: number readonly tag?: string }> = Schema.Struct({ id: Schema.String, message: Schema.String, author: Schema.optional(AccountInfo), real_author: Schema.optional(AccountInfo), date: Schema.String, _revision_number: Schema.optional(Schema.Number), tag: Schema.optional(Schema.String), }) export type MessageInfo = Schema.Schema.Type<typeof MessageInfo> export const ReviewInput: Schema.Schema<{ readonly message?: string readonly labels?: Record<string, number> readonly comments?: Record< string, ReadonlyArray<{ readonly line?: number readonly range?: { readonly start_line: number readonly end_line: number readonly start_character?: number readonly end_character?: number } readonly message: string readonly side?: 'PARENT' | 'REVISION' readonly unresolved?: boolean readonly in_reply_to?: string }> > }> = Schema.Struct({ message: Schema.optional(Schema.String), labels: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Number })), comments: Schema.optional( Schema.Record({ key: Schema.String, value: Schema.Array( Schema.Struct({ line: Schema.optional(Schema.Number), range: Schema.optional( Schema.Struct({ start_line: Schema.Number, end_line: Schema.Number, start_character: Schema.optional(Schema.Number), end_character: Schema.optional(Schema.Number), }), ), message: Schema.String, side: Schema.optional(Schema.Literal('PARENT', 'REVISION')), unresolved: Schema.optional(Schema.Boolean), in_reply_to: Schema.optional(Schema.String), }), ), }), ), }) export type ReviewInput = Schema.Schema.Type<typeof ReviewInput> export const ProjectInfo: Schema.Schema<{ readonly id: string readonly name: string readonly parent?: string readonly description?: string readonly state?: 'ACTIVE' | 'READ_ONLY' | 'HIDDEN' }> = Schema.Struct({ id: Schema.String, name: Schema.String, parent: Schema.optional(Schema.String), description: Schema.optional(Schema.String), state: Schema.optional(Schema.Literal('ACTIVE', 'READ_ONLY', 'HIDDEN')), }) export type ProjectInfo = Schema.Schema.Type<typeof ProjectInfo> export const DiffFileMeta: Schema.Schema<{ readonly name: string readonly content_type: string readonly lines?: number }> = Schema.Struct({ name: Schema.String, content_type: Schema.String, lines: Schema.optional(Schema.Number), }) export type DiffFileMeta = Schema.Schema.Type<typeof DiffFileMeta> export const FileDiffContent: Schema.Schema<{ readonly meta_a?: DiffFileMeta readonly meta_b?: DiffFileMeta readonly binary?: boolean readonly change_type?: 'ADDED' | 'MODIFIED' | 'DELETED' | 'RENAMED' | 'COPIED' | 'REWRITE' readonly diff_header?: ReadonlyArray<string> readonly intraline_status?: 'OK' | 'TIMEOUT' | 'ERROR' readonly content: ReadonlyArray<{ readonly a?: ReadonlyArray<string> readonly b?: ReadonlyArray<string> readonly ab?: ReadonlyArray<string> readonly edit_list?: ReadonlyArray<{ readonly op: 'i' | 'd' | 'r' readonly a: ReadonlyArray<string> readonly b: ReadonlyArray<string> }> readonly due_to_rebase?: boolean readonly skip?: number }> }> = Schema.Struct({ meta_a: Schema.optional(DiffFileMeta), meta_b: Schema.optional(DiffFileMeta), binary: Schema.optional(Schema.Boolean), change_type: Schema.optional( Schema.Literal('ADDED', 'MODIFIED', 'DELETED', 'RENAMED', 'COPIED', 'REWRITE'), ), diff_header: Schema.optional(Schema.Array(Schema.String)), intraline_status: Schema.optional(Schema.Literal('OK', 'TIMEOUT', 'ERROR')), content: Schema.Array( Schema.Struct({ a: Schema.optional(Schema.Array(Schema.String)), // Lines from old file b: Schema.optional(Schema.Array(Schema.String)), // Lines from new file ab: Schema.optional(Schema.Array(Schema.String)), // Common lines edit_list: Schema.optional( Schema.Array( Schema.Struct({ op: Schema.Literal('i', 'd', 'r'), // insert, delete, replace a: Schema.Array(Schema.String), b: Schema.Array(Schema.String), }), ), ), due_to_rebase: Schema.optional(Schema.Boolean), skip: Schema.optional(Schema.Number), }), ), }) export type FileDiffContent = Schema.Schema.Type<typeof FileDiffContent> export const RevisionInfo: Schema.Schema<{ readonly kind?: string readonly _number: number readonly created: string readonly uploader: { readonly _account_id: number readonly name?: string readonly email?: string readonly username?: string } readonly ref: string readonly fetch?: Record<string, unknown> readonly description?: string readonly commit?: { readonly commit: string readonly parents: ReadonlyArray<{ readonly commit: string; readonly subject: string }> readonly author: PersonDate readonly committer: PersonDate readonly subject: string readonly message: string } readonly files?: Record< string, { readonly status?: 'A' | 'D' | 'R' | 'C' | 'M' readonly lines_inserted?: number readonly lines_deleted?: number readonly size?: number readonly size_delta?: number readonly old_path?: string readonly binary?: boolean } > readonly actions?: Record<string, unknown> }> = Schema.Struct({ kind: Schema.optional(Schema.String), _number: Schema.Number, created: Schema.String, uploader: Schema.Struct({ _account_id: Schema.Number, name: Schema.optional(Schema.String), email: Schema.optional(Schema.String), username: Schema.optional(Schema.String), }), ref: Schema.String, fetch: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })), description: Schema.optional(Schema.String), commit: Schema.optional( Schema.Struct({ commit: Schema.String, parents: Schema.Array( Schema.Struct({ commit: Schema.String, subject: Schema.String, }), ), author: Schema.Struct({ name: Schema.String, email: Schema.String, date: Schema.String, }), committer: Schema.Struct({ name: Schema.String, email: Schema.String, date: Schema.String, }), subject: Schema.String, message: Schema.String, }), ), files: Schema.optional(Schema.Record({ key: Schema.String, value: FileInfo })), actions: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })), }) export type RevisionInfo = Schema.Schema.Type<typeof RevisionInfo> // Backwards-compatible alias used by mock-generator and other consumers export type RevisionInfoType = RevisionShape // Diff output format options export const DiffFormat: Schema.Schema<'unified' | 'json' | 'files'> = Schema.Literal( 'unified', 'json', 'files', ) export type DiffFormat = Schema.Schema.Type<typeof DiffFormat> export const DiffOptions: Schema.Schema<{ readonly format?: 'unified' | 'json' | 'files' readonly patchset?: number readonly file?: string readonly filesOnly?: boolean readonly fullFiles?: boolean readonly base?: number readonly target?: number }> = Schema.Struct({ format: Schema.optional(DiffFormat), patchset: Schema.optional(Schema.Number), file: Schema.optional(Schema.String), filesOnly: Schema.optional(Schema.Boolean), fullFiles: Schema.optional(Schema.Boolean), base: Schema.optional(Schema.Number), target: Schema.optional(Schema.Number), }) export type DiffOptions = Schema.Schema.Type<typeof DiffOptions> // Command options schemas export const DiffCommandOptions: Schema.Schema<{ readonly xml?: boolean readonly json?: boolean readonly file?: string readonly filesOnly?: boolean readonly format?: 'unified' | 'json' | 'files' }> = Schema.Struct({ xml: Schema.optional(Schema.Boolean), json: Schema.optional(Schema.Boolean), file: Schema.optional(Schema.String.pipe(Schema.minLength(1))), filesOnly: Schema.optional(Schema.Boolean), format: Schema.optional(DiffFormat), }) export type DiffCommandOptions = Schema.Schema.Type<typeof DiffCommandOptions> // Reviewer schemas export const ReviewerInput: Schema.Schema<{ readonly reviewer: string readonly state?: 'REVIEWER' | 'CC' | 'REMOVED' readonly confirmed?: boolean readonly notify?: 'NONE' | 'OWNER' | 'OWNER_REVIEWERS' | 'ALL' }> = Schema.Struct({ reviewer: Schema.String, state: Schema.optional(Schema.Literal('REVIEWER', 'CC', 'REMOVED')), confirmed: Schema.optional(Schema.Boolean), notify: Schema.optional(Schema.Literal('NONE', 'OWNER', 'OWNER_REVIEWERS', 'ALL')), }) export type ReviewerInput = Schema.Schema.Type<typeof ReviewerInput> const ReviewerAccountInfo = Schema.Struct({ _account_id: Schema.Number, name: Schema.optional(Schema.String), email: Schema.optional(Schema.String), username: Schema.optional(Schema.String), }) export type { ReviewerListItem } from './reviewer' export const ReviewerResult: Schema.Schema<{ readonly input: string readonly reviewers?: ReadonlyArray<{ readonly _account_id: number readonly name?: string readonly email?: string readonly username?: string }> readonly ccs?: ReadonlyArray<{ readonly _account_id: number readonly name?: string readonly email?: string readonly username?: string }> readonly error?: string readonly confirm?: boolean }> = Schema.Struct({ input: Schema.String, reviewers: Schema.optional(Schema.Array(ReviewerAccountInfo)), ccs: Schema.optional(Schema.Array(ReviewerAccountInfo)), error: Schema.optional(Schema.String), confirm: Schema.optional(Schema.Boolean), }) export type ReviewerResult = Schema.Schema.Type<typeof ReviewerResult> // Rebase schemas export const RebaseInput: Schema.Schema<{ readonly base?: string }> = Schema.Struct({ base: Schema.optional(Schema.String), }) export type RebaseInput = Schema.Schema.Type<typeof RebaseInput> // Submit schemas export const SubmitInfo: Schema.Schema<{ readonly status: 'MERGED' | 'SUBMITTED' readonly change_id?: string }> = Schema.Struct({ status: Schema.Literal('MERGED', 'SUBMITTED'), change_id: Schema.optional(Schema.String), }) export type SubmitInfo = Schema.Schema.Type<typeof SubmitInfo> // API Response schemas export const GerritError: Schema.Schema<{ readonly message: string readonly status?: number }> = Schema.Struct({ message: Schema.String, status: Schema.optional(Schema.Number), }) export type GerritError = Schema.Schema.Type<typeof GerritError> // Groups schemas export const GroupInfo: Schema.Schema<{ readonly id: string readonly name?: string readonly url?: string readonly options?: { readonly visible_to_all?: boolean } readonly description?: string readonly group_id?: number readonly owner?: string readonly owner_id?: string readonly created_on?: string }> = Schema.Struct({ id: Schema.String, name: Schema.optional(Schema.String), url: Schema.optional(Schema.String), options: Schema.optional( Schema.Struct({ visible_to_all: Schema.optional(Schema.Boolean), }), ), description: Schema.optional(Schema.String), group_id: Schema.optional(Schema.Number), owner: Schema.optional(Schema.String), owner_id: Schema.optional(Schema.String), created_on: Schema.optional(Schema.String), }) export type GroupInfo = Schema.Schema.Type<typeof GroupInfo> export const GroupDetailInfo: Schema.Schema<{ readonly id: string readonly name?: string readonly url?: string readonly options?: { readonly visible_to_all?: boolean } readonly description?: string readonly group_id?: number readonly owner?: string readonly owner_id?: string readonly created_on?: string readonly members?: ReadonlyArray<AccountInfo> readonly includes?: ReadonlyArray<{ readonly id: string readonly name?: string }> }> = Schema.Struct({ id: Schema.String, name: Schema.optional(Schema.String), url: Schema.optional(Schema.String), options: Schema.optional( Schema.Struct({ visible_to_all: Schema.optional(Schema.Boolean), }), ), description: Schema.optional(Schema.String), group_id: Schema.optional(Schema.Number), owner: Schema.optional(Schema.String), owner_id: Schema.optional(Schema.String), created_on: Schema.optional(Schema.String), members: Schema.optional(Schema.Array(AccountInfo)), includes: Schema.optional( Schema.Array( Schema.Struct({ id: Schema.String, name: Schema.optional(Schema.String), }), ), ), }) export type GroupDetailInfo = Schema.Schema.Type<typeof GroupDetailInfo>