719032b19f
Update Schema / Update configuration json schema (push) Has been cancelled
Memory Benchmark / Memory Test (Full Analysis) (push) Has been cancelled
CI Quality / Lint GitHub Actions (actionlint) (push) Has been cancelled
CI Quality / Lint GitHub Actions (zizmor) (push) Has been cancelled
CI Quality / Check typos (push) Has been cancelled
CI / Test coverage (push) Has been cancelled
CI / Test (22.x, windows-latest) (push) Has been cancelled
CI / Test (24.x, macos-latest) (push) Has been cancelled
CI / Test (24.x, ubuntu-latest) (push) Has been cancelled
CI / Test (24.x, windows-latest) (push) Has been cancelled
CI / Test (26.x, macos-latest) (push) Has been cancelled
CI / Test (26.x, ubuntu-latest) (push) Has been cancelled
CI / Test (26.x, windows-latest) (push) Has been cancelled
CI / Test with Bun (latest, macos-latest) (push) Has been cancelled
CI / Test with Bun (latest, ubuntu-latest) (push) Has been cancelled
CI / Test with Bun (latest, windows-latest) (push) Has been cancelled
CI / Build and run (22.x, macos-latest) (push) Has been cancelled
CI / Build and run (22.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (22.x, windows-latest) (push) Has been cancelled
autofix.ci / autofix (push) Has been cancelled
CI Browser Extension / Lint Browser Extension (push) Has been cancelled
CI Browser Extension / Test Browser Extension (push) Has been cancelled
Memory Benchmark / Memory Test (push) Has been cancelled
CI Website / Lint Website Client (push) Has been cancelled
CI Website / Lint Website Server (push) Has been cancelled
CI Website / Test Website Server (push) Has been cancelled
CI Website / Bundle Website Server (push) Has been cancelled
CI / Lint Biome (push) Has been cancelled
CI / Lint oxlint (push) Has been cancelled
CI / Lint TypeScript (push) Has been cancelled
CI / Lint Secretlint (push) Has been cancelled
CI / Test (22.x, macos-latest) (push) Has been cancelled
CI / Test (22.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (24.x, macos-latest) (push) Has been cancelled
CI / Build and run (24.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (24.x, windows-latest) (push) Has been cancelled
CI / Build and run (26.x, macos-latest) (push) Has been cancelled
CI / Build and run (26.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (26.x, windows-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, macos-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, ubuntu-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Docker / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Docker / build (linux/arm/v7, ubuntu-24.04-arm) (push) Has been cancelled
Docker / build (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Docker / merge (push) Has been cancelled
Pack repository with Repomix / pack-repo (push) Has been cancelled
Performance Benchmark History / Benchmark (macos-latest) (push) Has been cancelled
Performance Benchmark History / Benchmark (ubuntu-latest) (push) Has been cancelled
Performance Benchmark History / Benchmark (windows-latest) (push) Has been cancelled
Performance Benchmark History / Store Results (push) Has been cancelled
Test Repomix Action / Test Node.js 22 (push) Has been cancelled
Test Repomix Action / Test Node.js 24 (push) Has been cancelled
Test Repomix Action / Test Node.js 26 (push) Has been cancelled
181 lines
4.7 KiB
TypeScript
181 lines
4.7 KiB
TypeScript
export interface PackOptions {
|
|
removeComments: boolean;
|
|
removeEmptyLines: boolean;
|
|
showLineNumbers: boolean;
|
|
fileSummary?: boolean;
|
|
directoryStructure?: boolean;
|
|
includePatterns?: string;
|
|
ignorePatterns?: string;
|
|
outputParsable?: boolean;
|
|
compress?: boolean;
|
|
}
|
|
|
|
export interface FileInfo {
|
|
path: string;
|
|
charCount: number;
|
|
selected?: boolean;
|
|
}
|
|
|
|
export interface PackRequest {
|
|
url: string;
|
|
format: 'xml' | 'markdown' | 'plain';
|
|
options: PackOptions;
|
|
file?: File;
|
|
}
|
|
|
|
export interface SuspiciousFile {
|
|
filePath: string;
|
|
messages: string[];
|
|
}
|
|
|
|
export interface PackResult {
|
|
content: string;
|
|
format: string;
|
|
metadata: {
|
|
repository: string;
|
|
timestamp: string;
|
|
summary: {
|
|
totalFiles: number;
|
|
totalCharacters: number;
|
|
totalTokens: number;
|
|
};
|
|
topFiles: {
|
|
path: string;
|
|
charCount: number;
|
|
tokenCount: number;
|
|
}[];
|
|
allFiles?: FileInfo[];
|
|
suspiciousFiles?: SuspiciousFile[];
|
|
};
|
|
}
|
|
|
|
export interface ErrorResponse {
|
|
error: string;
|
|
}
|
|
|
|
export class ApiError extends Error {
|
|
constructor(message: string) {
|
|
super(message);
|
|
this.name = 'ApiError';
|
|
}
|
|
}
|
|
|
|
// Wire-protocol stages — must stay aligned with the server-emitted SSE
|
|
// values (`website/server/src/types.ts:PackProgressStage`). `onProgress`
|
|
// callbacks receive only these, so any new server stage requires a
|
|
// deliberate type update on both sides.
|
|
export type PackProgressStage = 'cache-check' | 'cloning' | 'repository-fetch' | 'extracting' | 'processing';
|
|
|
|
// Display-only superset. `verifying` is a client-only synthetic stage
|
|
// shown while the server runs Turnstile siteverify (before any SSE event
|
|
// arrives); usePackRequest sets it locally between `takeToken()` returning
|
|
// and the first onProgress callback firing, so the loading UI shows a
|
|
// meaningful step instead of a generic "...". Keeping it out of
|
|
// `PackProgressStage` prevents the wire contract from drifting silently
|
|
// when display-only stages get added or renamed.
|
|
export type DisplayProgressStage = PackProgressStage | 'verifying';
|
|
|
|
export interface PackStreamCallbacks {
|
|
onProgress?: (stage: PackProgressStage, message?: string) => void;
|
|
signal?: AbortSignal;
|
|
}
|
|
|
|
const API_BASE_URL = import.meta.env.PROD ? 'https://api.repomix.com' : 'http://localhost:8080';
|
|
|
|
// NDJSON stream event types
|
|
interface ProgressEvent {
|
|
type: 'progress';
|
|
stage: PackProgressStage;
|
|
message?: string;
|
|
}
|
|
|
|
interface ResultEvent {
|
|
type: 'result';
|
|
data: PackResult;
|
|
}
|
|
|
|
interface StreamErrorEvent {
|
|
type: 'error';
|
|
message: string;
|
|
}
|
|
|
|
type StreamEvent = ProgressEvent | ResultEvent | StreamErrorEvent;
|
|
|
|
export async function packRepository(
|
|
request: PackRequest,
|
|
callbacks?: PackStreamCallbacks,
|
|
turnstileToken?: string,
|
|
): Promise<PackResult> {
|
|
const formData = new FormData();
|
|
|
|
if (request.file) {
|
|
formData.append('file', request.file);
|
|
} else {
|
|
formData.append('url', request.url);
|
|
}
|
|
formData.append('format', request.format);
|
|
formData.append('options', JSON.stringify(request.options));
|
|
|
|
// Token rides as a header rather than a form field to keep packRequestSchema
|
|
// free of cross-cutting concerns; the server-side turnstileMiddleware reads
|
|
// it before the schema validation runs.
|
|
const headers: HeadersInit = turnstileToken ? { 'X-Turnstile-Token': turnstileToken } : {};
|
|
|
|
const response = await fetch(`${API_BASE_URL}/api/pack`, {
|
|
method: 'POST',
|
|
headers,
|
|
body: formData,
|
|
signal: callbacks?.signal,
|
|
});
|
|
|
|
// Handle non-streaming error responses (validation errors return JSON)
|
|
if (!response.ok) {
|
|
const data = await response.json();
|
|
throw new ApiError((data as ErrorResponse).error);
|
|
}
|
|
|
|
// Handle NDJSON stream
|
|
if (!response.body) {
|
|
throw new ApiError('No response body received');
|
|
}
|
|
|
|
const reader = response.body.getReader();
|
|
const decoder = new TextDecoder();
|
|
let buffer = '';
|
|
let result: PackResult | null = null;
|
|
|
|
try {
|
|
while (true) {
|
|
const { value, done } = await reader.read();
|
|
if (done) break;
|
|
|
|
buffer += decoder.decode(value, { stream: true });
|
|
|
|
// Parse complete lines from buffer
|
|
const lines = buffer.split('\n');
|
|
buffer = lines.pop() || '';
|
|
|
|
for (const line of lines) {
|
|
if (!line.trim()) continue;
|
|
|
|
const event = JSON.parse(line) as StreamEvent;
|
|
if (event.type === 'progress') {
|
|
callbacks?.onProgress?.(event.stage, event.message);
|
|
} else if (event.type === 'result') {
|
|
result = event.data;
|
|
} else if (event.type === 'error') {
|
|
throw new ApiError(event.message);
|
|
}
|
|
}
|
|
}
|
|
} finally {
|
|
reader.releaseLock();
|
|
}
|
|
|
|
if (!result) {
|
|
throw new ApiError('No result received from server');
|
|
}
|
|
|
|
return result;
|
|
}
|