import { z } from 'zod/v4'; import { logger } from '../../../logger/index.ts'; import { regEx } from '../../../util/regex.ts'; import { LooseArray } from '../../../util/schema-utils/index.ts'; const BitbucketSourceType = z.enum(['commit_directory', 'commit_file']); const SourceResults = z.object({ path: z.string(), type: BitbucketSourceType, commit: z.object({ hash: z.string(), }), }); const Paged = z.object({ page: z.number().optional(), pagelen: z.number(), size: z.number().optional(), next: z.string().optional(), }); export const PagedSourceResults = Paged.extend({ values: z.array(SourceResults), }); export const RepoInfo = z .object({ parent: z.unknown().optional().catch(undefined), mainbranch: z.object({ name: z.string(), }), uuid: z.string(), full_name: z .string() .regex( regEx(/^[^/]+\/[^/]+$/), 'Expected repository full_name to be in the format "owner/repo"', ), is_private: z.boolean().catch(() => { logger.once.warn('Bitbucket: "is_private" field missing from repo info'); return true; }), project: z .object({ name: z.string(), }) .nullable() .catch(null), }) .transform((repoInfoBody) => { const isFork = !!repoInfoBody.parent; const [owner, name] = repoInfoBody.full_name.split('/'); return { isFork, owner, name, mainbranch: repoInfoBody.mainbranch.name, mergeMethod: 'merge', uuid: repoInfoBody.uuid, is_private: repoInfoBody.is_private, projectName: repoInfoBody.project?.name, }; }); export type RepoInfo = z.infer; export const Repositories = z .object({ values: LooseArray(RepoInfo), }) .transform((body) => body.values); const TaskState = z.union([z.literal('RESOLVED'), z.literal('UNRESOLVED')]); const PrTask = z.object({ id: z.number(), state: TaskState, content: z.object({ raw: z.string(), }), }); export type PrTask = z.infer; export const UnresolvedPrTasks = z .object({ values: z.array(PrTask), }) .transform((data) => data.values.filter((task) => task.state === 'UNRESOLVED'), ); const WorkspaceAccess = z.object({ workspace: z.object({ slug: z.string(), }), }); export const WorkspaceAccesses = z .object({ values: z.array(WorkspaceAccess), }) .transform((body) => body.values.map(({ workspace }) => workspace.slug));