@hardlydifficult/repo-processor
v1.0.150
Published
Opinionated GitHub repo processing with git-backed YAML results.
Readme
@hardlydifficult/repo-processor
Opinionated GitHub repo processing with git-backed YAML results.
The package is built around one happy path:
- Open a processor for one source repo.
- Describe how to turn files and directories into results.
- Run it or attach a watcher.
Installation
npm install @hardlydifficult/repo-processorQuick Start
import { RepoProcessor } from "@hardlydifficult/repo-processor";
const processor = await RepoProcessor.open({
repo: "hardlydifficult/typescript",
ref: "main",
results: {
repo: "hardlydifficult/repo-data",
directory: "./repo-data",
},
include(file) {
return file.path.endsWith(".ts");
},
async processFile(file) {
return {
path: file.path,
sha: file.sha,
length: file.content.length,
};
},
async processDirectory(directory) {
return {
path: directory.path,
fileCount: directory.files.length,
};
},
});
const result = await processor.run({
onProgress(progress) {
console.log(progress.phase, progress.message);
},
});
console.log(result);
// {
// repo: "hardlydifficult/typescript",
// sourceSha: "...",
// processedFiles: 12,
// removedFiles: 0,
// processedDirectories: 5
// }Why This API
RepoProcessor.open()binds the source repo once.run()does not ask forownerandrepoagain.- GitHub auth and git-backed YAML persistence are built in.
- The default results layout is
repos/<owner>/<repo>.
API
await RepoProcessor.open(options)
interface RepoProcessorOptions<TFileResult, TDirResult = never> {
repo: string;
githubToken?: string;
ref?: string;
concurrency?: number;
results: {
repo: string;
directory: string;
root?: string;
branch?: string;
gitUser?: { name: string; email: string };
};
include?: (file: {
path: string;
sha: string;
size?: number;
}) => boolean;
processFile(file: {
repo: string;
path: string;
sha: string;
content: string;
}): Promise<TFileResult>;
processDirectory?: (directory: {
repo: string;
path: string;
sha: string;
files: readonly string[];
children: readonly {
name: string;
path: string;
type: "file" | "directory";
}[];
}) => Promise<TDirResult>;
}Notes:
repoandresults.repoaccept eitherowner/repoor a GitHub URL.githubTokendefaults toGH_PAT, thenGITHUB_TOKEN.results.rootdefaults to"repos".results.branchdefaults to the checked-out branch in the results clone.results.gitUserdefaults to local git config (user.nameanduser.email).
await processor.run({ onProgress? })
type RepoProcessorRunResult = {
repo: string;
sourceSha: string;
processedFiles: number;
removedFiles: number;
processedDirectories: number;
};type RepoProcessorProgress = {
phase: "loading" | "files" | "directories" | "committing";
message: string;
files: { total: number; completed: number };
directories: { total: number; completed: number };
};If processDirectory is omitted, directory diffing and directory result writes are skipped.
Reading Stored Results
const fileResult = await processor.readFileResult(
"src/index.ts",
schema
);
const directoryResult = await processor.readDirectoryResult(
"src",
schema
);Watching A Repo
const watcher = await processor.watch({
stateDirectory: "./state",
maxAttempts: 3,
onComplete(result, sha) {
console.log("processed", sha, result.processedFiles);
},
});
watcher.handlePush("abc123");
await watcher.runNow();Watcher methods:
handlePush(sha)runNow()isRunning()getLastSha()setLastSha(sha)
