128 lines · 4.7 KB · TypeScript
RawDownload
import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import { SourceControlProviderError, type ChangeRequest } from "@t3tools/contracts"; import * as BitbucketApi from "./BitbucketApi.ts";import * as BitbucketPullRequests from "./bitbucketPullRequests.ts";import * as SourceControlProvider from "./SourceControlProvider.ts";import type * as SourceControlProviderDiscovery from "./SourceControlProviderDiscovery.ts"; function providerError(  operation: string,  cause: BitbucketApi.BitbucketApiError,): SourceControlProviderError {  return new SourceControlProviderError({    provider: "bitbucket",    operation,    detail: cause.detail,    cause,  });} function toChangeRequest(  summary: BitbucketPullRequests.NormalizedBitbucketPullRequestRecord,): ChangeRequest {  return {    provider: "bitbucket",    number: summary.number,    title: summary.title,    url: summary.url,    baseRefName: summary.baseRefName,    headRefName: summary.headRefName,    state: summary.state,    updatedAt: summary.updatedAt ?? Option.none(),    ...(summary.isCrossRepository !== undefined      ? { isCrossRepository: summary.isCrossRepository }      : {}),    ...(summary.headRepositoryNameWithOwner !== undefined      ? { headRepositoryNameWithOwner: summary.headRepositoryNameWithOwner }      : {}),    ...(summary.headRepositoryOwnerLogin !== undefined      ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin }      : {}),  };} export const make = Effect.fn("makeBitbucketSourceControlProvider")(function* () {  const bitbucket = yield* BitbucketApi.BitbucketApi;   return SourceControlProvider.SourceControlProvider.of({    kind: "bitbucket",    listChangeRequests: (input) => {      const source = SourceControlProvider.sourceControlRefFromInput(input);      return bitbucket        .listPullRequests({          cwd: input.cwd,          ...(input.context ? { context: input.context } : {}),          headSelector: input.headSelector,          ...(source ? { source } : {}),          state: input.state,          ...(input.limit !== undefined ? { limit: input.limit } : {}),        })        .pipe(          Effect.map((items) => items.map(toChangeRequest)),          Effect.mapError((error) => providerError("listChangeRequests", error)),        );    },    getChangeRequest: (input) =>      bitbucket.getPullRequest(input).pipe(        Effect.map(toChangeRequest),        Effect.mapError((error) => providerError("getChangeRequest", error)),      ),    createChangeRequest: (input) => {      const source = SourceControlProvider.sourceControlRefFromInput(input);      return bitbucket        .createPullRequest({          cwd: input.cwd,          ...(input.context ? { context: input.context } : {}),          baseBranch: input.baseRefName,          headSelector: input.headSelector,          ...(source ? { source } : {}),          ...(input.target ? { target: input.target } : {}),          title: input.title,          bodyFile: input.bodyFile,        })        .pipe(Effect.mapError((error) => providerError("createChangeRequest", error)));    },    getRepositoryCloneUrls: (input) =>      bitbucket        .getRepositoryCloneUrls(input)        .pipe(Effect.mapError((error) => providerError("getRepositoryCloneUrls", error))),    createRepository: (input) =>      bitbucket        .createRepository(input)        .pipe(Effect.mapError((error) => providerError("createRepository", error))),    getDefaultBranch: (input) =>      bitbucket        .getDefaultBranch({          cwd: input.cwd,          ...(input.context ? { context: input.context } : {}),        })        .pipe(Effect.mapError((error) => providerError("getDefaultBranch", error))),    checkoutChangeRequest: (input) =>      bitbucket        .checkoutPullRequest({          cwd: input.cwd,          ...(input.context ? { context: input.context } : {}),          reference: input.reference,          ...(input.force !== undefined ? { force: input.force } : {}),        })        .pipe(Effect.mapError((error) => providerError("checkoutChangeRequest", error))),  });}); export const layer = Layer.effect(SourceControlProvider.SourceControlProvider, make()); export const makeDiscovery = Effect.fn("makeBitbucketSourceControlProviderDiscovery")(function* () {  const bitbucket = yield* BitbucketApi.BitbucketApi;   return {    type: "api",    kind: "bitbucket",    label: "Bitbucket",    installHint:      "Set T3CODE_BITBUCKET_EMAIL and T3CODE_BITBUCKET_API_TOKEN on the server (use a Bitbucket API token with pull request and repository scopes).",    probeAuth: bitbucket.probeAuth,  } satisfies SourceControlProviderDiscovery.SourceControlApiDiscoverySpec;});