import * as Cause from "effect/Cause";import * as DateTime from "effect/DateTime";import * as Exit from "effect/Exit";import * as Option from "effect/Option";import * as Result from "effect/Result";import * as Schema from "effect/Schema";import { PositiveInt, TrimmedNonEmptyString } from "@t3tools/contracts";import { decodeJsonResult, formatSchemaError } from "@t3tools/shared/schemaJson"; export interface NormalizedGitHubPullRequestRecord { readonly number: number; readonly title: string; readonly url: string; readonly baseRefName: string; readonly headRefName: string; readonly state: "open" | "closed" | "merged"; readonly updatedAt: Option.Option<DateTime.Utc>; readonly isCrossRepository?: boolean; readonly headRepositoryNameWithOwner?: string | null; readonly headRepositoryOwnerLogin?: string | null;} const GitHubPullRequestSchema = Schema.Struct({ number: PositiveInt, title: TrimmedNonEmptyString, url: TrimmedNonEmptyString, baseRefName: TrimmedNonEmptyString, headRefName: TrimmedNonEmptyString, state: Schema.optional(Schema.NullOr(Schema.String)), mergedAt: Schema.optional(Schema.NullOr(Schema.String)), updatedAt: Schema.optional(Schema.OptionFromNullOr(Schema.DateTimeUtcFromString)), isCrossRepository: Schema.optional(Schema.Boolean), headRepository: Schema.optional( Schema.NullOr( Schema.Struct({ nameWithOwner: Schema.String, }), ), ), headRepositoryOwner: Schema.optional( Schema.NullOr( Schema.Struct({ login: Schema.String, }), ), ),}); function trimOptionalString(value: string | null | undefined): string | null { const trimmed = value?.trim() ?? ""; return trimmed.length > 0 ? trimmed : null;} function normalizeGitHubPullRequestState(input: { state?: string | null | undefined; mergedAt?: string | null | undefined;}): "open" | "closed" | "merged" { const normalizedState = input.state?.trim().toUpperCase(); if ( (typeof input.mergedAt === "string" && input.mergedAt.trim().length > 0) || normalizedState === "MERGED" ) { return "merged"; } if (normalizedState === "CLOSED") { return "closed"; } return "open";} function normalizeGitHubPullRequestRecord( raw: Schema.Schema.Type<typeof GitHubPullRequestSchema>,): NormalizedGitHubPullRequestRecord { const headRepositoryNameWithOwner = trimOptionalString(raw.headRepository?.nameWithOwner); const headRepositoryOwnerLogin = trimOptionalString(raw.headRepositoryOwner?.login) ?? (typeof headRepositoryNameWithOwner === "string" && headRepositoryNameWithOwner.includes("/") ? (headRepositoryNameWithOwner.split("/")[0] ?? null) : null); return { number: raw.number, title: raw.title, url: raw.url, baseRefName: raw.baseRefName, headRefName: raw.headRefName, state: normalizeGitHubPullRequestState(raw), updatedAt: raw.updatedAt ?? Option.none(), ...(typeof raw.isCrossRepository === "boolean" ? { isCrossRepository: raw.isCrossRepository } : {}), ...(headRepositoryNameWithOwner ? { headRepositoryNameWithOwner } : {}), ...(headRepositoryOwnerLogin ? { headRepositoryOwnerLogin } : {}), };} const decodeGitHubPullRequestList = decodeJsonResult(Schema.Array(Schema.Unknown));const decodeGitHubPullRequest = decodeJsonResult(GitHubPullRequestSchema);const decodeGitHubPullRequestEntry = Schema.decodeUnknownExit(GitHubPullRequestSchema); export const formatGitHubJsonDecodeError = formatSchemaError; export function decodeGitHubPullRequestListJson( raw: string,): Result.Result< ReadonlyArray<NormalizedGitHubPullRequestRecord>, Cause.Cause<Schema.SchemaError>> { const result = decodeGitHubPullRequestList(raw); if (Result.isSuccess(result)) { const pullRequests: NormalizedGitHubPullRequestRecord[] = []; for (const entry of result.success) { const decodedEntry = decodeGitHubPullRequestEntry(entry); if (Exit.isFailure(decodedEntry)) { continue; } pullRequests.push(normalizeGitHubPullRequestRecord(decodedEntry.value)); } return Result.succeed(pullRequests); } return Result.fail(result.failure);} export function decodeGitHubPullRequestJson( raw: string,): Result.Result<NormalizedGitHubPullRequestRecord, Cause.Cause<Schema.SchemaError>> { const result = decodeGitHubPullRequest(raw); if (Result.isSuccess(result)) { return Result.succeed(normalizeGitHubPullRequestRecord(result.success)); } return Result.fail(result.failure);}
import * as Cause from "effect/Cause";
import * as DateTime from "effect/DateTime";
import * as Exit from "effect/Exit";
import * as Option from "effect/Option";
import * as Result from "effect/Result";
import * as Schema from "effect/Schema";
import { PositiveInt, TrimmedNonEmptyString } from "@t3tools/contracts";
import { decodeJsonResult, formatSchemaError } from "@t3tools/shared/schemaJson";
export interface NormalizedGitHubPullRequestRecord {
readonly number: number;
readonly title: string;
readonly url: string;
readonly baseRefName: string;
readonly headRefName: string;
readonly state: "open" | "closed" | "merged";
readonly updatedAt: Option.Option<DateTime.Utc>;
readonly isCrossRepository?: boolean;
readonly headRepositoryNameWithOwner?: string | null;
readonly headRepositoryOwnerLogin?: string | null;
}
const GitHubPullRequestSchema = Schema.Struct({
number: PositiveInt,
title: TrimmedNonEmptyString,
url: TrimmedNonEmptyString,
baseRefName: TrimmedNonEmptyString,
headRefName: TrimmedNonEmptyString,
state: Schema.optional(Schema.NullOr(Schema.String)),
mergedAt: Schema.optional(Schema.NullOr(Schema.String)),
updatedAt: Schema.optional(Schema.OptionFromNullOr(Schema.DateTimeUtcFromString)),
isCrossRepository: Schema.optional(Schema.Boolean),
headRepository: Schema.optional(
Schema.NullOr(
Schema.Struct({
nameWithOwner: Schema.String,
}),
),
),
headRepositoryOwner: Schema.optional(
Schema.NullOr(
Schema.Struct({
login: Schema.String,
}),
),
),
});
function trimOptionalString(value: string | null | undefined): string | null {
const trimmed = value?.trim() ?? "";
return trimmed.length > 0 ? trimmed : null;
}
function normalizeGitHubPullRequestState(input: {
state?: string | null | undefined;
mergedAt?: string | null | undefined;
}): "open" | "closed" | "merged" {
const normalizedState = input.state?.trim().toUpperCase();
if (
(typeof input.mergedAt === "string" && input.mergedAt.trim().length > 0) ||
normalizedState === "MERGED"
) {
return "merged";
}
if (normalizedState === "CLOSED") {
return "closed";
}
return "open";
}
function normalizeGitHubPullRequestRecord(
raw: Schema.Schema.Type<typeof GitHubPullRequestSchema>,
): NormalizedGitHubPullRequestRecord {
const headRepositoryNameWithOwner = trimOptionalString(raw.headRepository?.nameWithOwner);
const headRepositoryOwnerLogin =
trimOptionalString(raw.headRepositoryOwner?.login) ??
(typeof headRepositoryNameWithOwner === "string" && headRepositoryNameWithOwner.includes("/")
? (headRepositoryNameWithOwner.split("/")[0] ?? null)
: null);
return {
number: raw.number,
title: raw.title,
url: raw.url,
baseRefName: raw.baseRefName,
headRefName: raw.headRefName,
state: normalizeGitHubPullRequestState(raw),
updatedAt: raw.updatedAt ?? Option.none(),
...(typeof raw.isCrossRepository === "boolean"
? { isCrossRepository: raw.isCrossRepository }
: {}),
...(headRepositoryNameWithOwner ? { headRepositoryNameWithOwner } : {}),
...(headRepositoryOwnerLogin ? { headRepositoryOwnerLogin } : {}),
};
}
const decodeGitHubPullRequestList = decodeJsonResult(Schema.Array(Schema.Unknown));
const decodeGitHubPullRequest = decodeJsonResult(GitHubPullRequestSchema);
const decodeGitHubPullRequestEntry = Schema.decodeUnknownExit(GitHubPullRequestSchema);
export const formatGitHubJsonDecodeError = formatSchemaError;
export function decodeGitHubPullRequestListJson(
raw: string,
): Result.Result<
ReadonlyArray<NormalizedGitHubPullRequestRecord>,
Cause.Cause<Schema.SchemaError>
> {
const result = decodeGitHubPullRequestList(raw);
if (Result.isSuccess(result)) {
const pullRequests: NormalizedGitHubPullRequestRecord[] = [];
for (const entry of result.success) {
const decodedEntry = decodeGitHubPullRequestEntry(entry);
if (Exit.isFailure(decodedEntry)) {
continue;
}
pullRequests.push(normalizeGitHubPullRequestRecord(decodedEntry.value));
}
return Result.succeed(pullRequests);
}
return Result.fail(result.failure);
}
export function decodeGitHubPullRequestJson(
raw: string,
): Result.Result<NormalizedGitHubPullRequestRecord, Cause.Cause<Schema.SchemaError>> {
const result = decodeGitHubPullRequest(raw);
if (Result.isSuccess(result)) {
return Result.succeed(normalizeGitHubPullRequestRecord(result.success));
}
return Result.fail(result.failure);
}