📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Time parsing utilities for status gatherers
|
||||
*/
|
||||
|
||||
const TIME_UNITS: Record<string, number> = {
|
||||
h: 60 * 60 * 1000,
|
||||
d: 24 * 60 * 60 * 1000,
|
||||
w: 7 * 24 * 60 * 60 * 1000,
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse time constraint string to milliseconds
|
||||
* @example parseTimeConstraint("24h") → 86400000
|
||||
* @example parseTimeConstraint("7d") → 604800000
|
||||
* @example parseTimeConstraint("2w") → 1209600000
|
||||
*/
|
||||
export function parseTimeConstraint(input: string): number {
|
||||
const match = input.match(/^(\d+)([hdw])$/i);
|
||||
if (!match) {
|
||||
throw new Error(
|
||||
`Invalid time constraint: ${input}. Use format like "24h", "7d", or "2w"`,
|
||||
);
|
||||
}
|
||||
const [, value, unit] = match;
|
||||
const multiplier = TIME_UNITS[unit.toLowerCase()];
|
||||
if (!multiplier) {
|
||||
throw new Error(`Unknown time unit: ${unit}`);
|
||||
}
|
||||
return parseInt(value, 10) * multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cutoff Date from milliseconds offset
|
||||
*/
|
||||
export function toCutoffDate(ms: number): Date {
|
||||
return new Date(Date.now() - ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to git --since format
|
||||
* @example toGitSince(86400000) → "2024-12-21T12:00:00"
|
||||
*/
|
||||
export function toGitSince(ms: number): string {
|
||||
return toCutoffDate(ms).toISOString().replace("Z", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to ISO 8601 duration for Linear
|
||||
* @example toISOPeriod(86400000) → "-P1D" (1 day)
|
||||
* @example toISOPeriod(604800000) → "-P7D" (7 days)
|
||||
*/
|
||||
export function toISOPeriod(ms: number): string {
|
||||
const hours = ms / (60 * 60 * 1000);
|
||||
if (hours < 24) {
|
||||
return `-PT${Math.round(hours)}H`;
|
||||
}
|
||||
const days = Math.round(hours / 24);
|
||||
return `-P${days}D`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to human-readable relative time
|
||||
* @example toRelativeTime(new Date(Date.now() - 3600000)) → "1 hour ago"
|
||||
*/
|
||||
export function toRelativeTime(date: Date | string): string {
|
||||
const d = typeof date === "string" ? new Date(date) : date;
|
||||
const ms = Date.now() - d.getTime();
|
||||
|
||||
if (ms < 60 * 1000) return "just now";
|
||||
if (ms < 60 * 60 * 1000) {
|
||||
const mins = Math.floor(ms / (60 * 1000));
|
||||
return `${mins} minute${mins === 1 ? "" : "s"} ago`;
|
||||
}
|
||||
if (ms < 24 * 60 * 60 * 1000) {
|
||||
const hours = Math.floor(ms / (60 * 60 * 1000));
|
||||
return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
||||
}
|
||||
const days = Math.floor(ms / (24 * 60 * 60 * 1000));
|
||||
return `${days} day${days === 1 ? "" : "s"} ago`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items by updated_at field within time window
|
||||
*/
|
||||
export function filterByTime<
|
||||
T extends { updated_at?: string; updatedAt?: string },
|
||||
>(items: T[], ms: number): T[] {
|
||||
const cutoff = toCutoffDate(ms);
|
||||
return items.filter((item) => {
|
||||
const updatedAt = item.updated_at || item.updatedAt;
|
||||
if (!updatedAt) return false;
|
||||
return new Date(updatedAt) >= cutoff;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time constraint for display
|
||||
* @example formatTimeConstraint("24h") → "last 24 hours"
|
||||
*/
|
||||
export function formatTimeConstraint(input: string): string {
|
||||
const match = input.match(/^(\d+)([hdw])$/i);
|
||||
if (!match) return input;
|
||||
|
||||
const [, value, unit] = match;
|
||||
const num = parseInt(value, 10);
|
||||
|
||||
switch (unit.toLowerCase()) {
|
||||
case "h":
|
||||
return `last ${num} hour${num === 1 ? "" : "s"}`;
|
||||
case "d":
|
||||
return `last ${num} day${num === 1 ? "" : "s"}`;
|
||||
case "w":
|
||||
return `last ${num} week${num === 1 ? "" : "s"}`;
|
||||
default:
|
||||
return input;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Shared types for status gatherers
|
||||
*/
|
||||
|
||||
/** Possible states for a gatherer operation. */
|
||||
export type GathererStatus = "success" | "unavailable" | "error";
|
||||
|
||||
/**
|
||||
* Result returned by a status gatherer.
|
||||
* @typeParam T - Type of gathered data
|
||||
*/
|
||||
export interface GathererResult<T = unknown> {
|
||||
/** Source identifier */
|
||||
source: string;
|
||||
/** Operation status */
|
||||
status: GathererStatus;
|
||||
/** Gathered data (present when success) */
|
||||
data?: T;
|
||||
/** Error message (present when error) */
|
||||
error?: string;
|
||||
/** Unavailability reason (present when unavailable) */
|
||||
reason?: string;
|
||||
/** ISO timestamp of when data was gathered */
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue from Beads local issue tracking.
|
||||
*/
|
||||
export interface BeadsIssue {
|
||||
id: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
status: "open" | "in_progress" | "blocked" | "closed";
|
||||
issue_type: "bug" | "feature" | "task" | "epic" | "chore";
|
||||
priority: 0 | 1 | 2 | 3 | 4;
|
||||
assignee?: string;
|
||||
labels: string[];
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
closed_at?: string;
|
||||
dependency_count: number;
|
||||
dependent_count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregated statistics for Beads issues.
|
||||
*/
|
||||
export interface BeadsStats {
|
||||
total: number;
|
||||
open: number;
|
||||
in_progress: number;
|
||||
blocked: number;
|
||||
closed: number;
|
||||
ready: number;
|
||||
average_lead_time?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data gathered from Beads issue tracker.
|
||||
*/
|
||||
export interface BeadsData {
|
||||
stats: BeadsStats;
|
||||
inProgress: BeadsIssue[];
|
||||
ready: BeadsIssue[];
|
||||
blocked: BeadsIssue[];
|
||||
recentlyClosed: BeadsIssue[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull request from GitHub.
|
||||
*/
|
||||
export interface GitHubPR {
|
||||
number: number;
|
||||
title: string;
|
||||
state: "OPEN" | "CLOSED" | "MERGED";
|
||||
isDraft: boolean;
|
||||
author: { login: string };
|
||||
updatedAt: string;
|
||||
url: string;
|
||||
headRefName: string;
|
||||
statusCheckRollup?: {
|
||||
state: "SUCCESS" | "FAILURE" | "PENDING" | "EXPECTED";
|
||||
contexts?: Array<{
|
||||
name: string;
|
||||
state: string;
|
||||
conclusion?: string;
|
||||
}>;
|
||||
};
|
||||
reviewDecision?: "APPROVED" | "CHANGES_REQUESTED" | "REVIEW_REQUIRED" | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* GitHub Actions workflow run.
|
||||
*/
|
||||
export interface GitHubWorkflowRun {
|
||||
name: string;
|
||||
status: string;
|
||||
conclusion: string | null;
|
||||
createdAt: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data gathered from GitHub.
|
||||
*/
|
||||
export interface GitHubData {
|
||||
repo: string;
|
||||
openPRs: GitHubPR[];
|
||||
recentRuns: GitHubWorkflowRun[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Branch in a Graphite stack.
|
||||
*/
|
||||
export interface GraphiteBranch {
|
||||
name: string;
|
||||
prNumber?: number;
|
||||
prStatus?: "draft" | "open" | "ready" | "merged" | "closed";
|
||||
prUrl?: string;
|
||||
parent?: string;
|
||||
children: string[];
|
||||
isCurrent: boolean;
|
||||
needsRestack: boolean;
|
||||
needsSubmit: boolean;
|
||||
commitCount: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data gathered from Graphite.
|
||||
*/
|
||||
export interface GraphiteData {
|
||||
currentBranch: string;
|
||||
trunk: string;
|
||||
branches: GraphiteBranch[];
|
||||
stacks: string[][]; // Each stack as array of branch names
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue from Linear.
|
||||
*/
|
||||
export interface LinearIssue {
|
||||
identifier: string;
|
||||
title: string;
|
||||
state: {
|
||||
name: string;
|
||||
type: string;
|
||||
};
|
||||
priority: number;
|
||||
assignee?: { name: string };
|
||||
labels: Array<{ name: string }>;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data gathered from Linear.
|
||||
*/
|
||||
export interface LinearData {
|
||||
team?: string;
|
||||
issues: LinearIssue[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregated status report result.
|
||||
*/
|
||||
export interface SitrepResult {
|
||||
timeConstraint: string;
|
||||
timestamp: string;
|
||||
sources: string[];
|
||||
results: {
|
||||
graphite?: GathererResult<GraphiteData>;
|
||||
github?: GathererResult<GitHubData>;
|
||||
linear?: GathererResult<LinearData>;
|
||||
beads?: GathererResult<BeadsData>;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user