62 lines
1.6 KiB
TypeScript
62 lines
1.6 KiB
TypeScript
import {
|
|
type ContextFileEntry,
|
|
resolveContextPath,
|
|
scanDir,
|
|
tryRead,
|
|
} from "./files";
|
|
import { resolvePaths } from "./resolver";
|
|
|
|
export interface BuildResult {
|
|
content: string | null;
|
|
loadedPaths: Map<string, string>;
|
|
}
|
|
|
|
export async function build(cwd: string): Promise<BuildResult> {
|
|
const paths = resolvePaths(cwd);
|
|
const files: ContextFileEntry[] = [];
|
|
const loadedPaths = new Map<string, string>();
|
|
|
|
for (const entry of paths) {
|
|
if (entry.endsWith("/*.md")) {
|
|
const dir = resolveContextPath(entry.slice(0, -4), cwd);
|
|
const before = files.length;
|
|
await scanDir(dir, files);
|
|
for (let index = before; index < files.length; index++) {
|
|
const file = files[index];
|
|
if (file) loadedPaths.set(file.rel, fileHash(file.content));
|
|
}
|
|
continue;
|
|
}
|
|
|
|
const abs = resolveContextPath(entry, cwd);
|
|
const before = files.length;
|
|
await tryRead(abs, entry, files);
|
|
if (files.length > before) {
|
|
const file = files[files.length - 1];
|
|
if (file) loadedPaths.set(abs, fileHash(file.content));
|
|
}
|
|
}
|
|
|
|
const nonEmpty = files.filter((file) => file.content.length > 0);
|
|
|
|
return {
|
|
content:
|
|
nonEmpty.length > 0
|
|
? nonEmpty
|
|
.map(
|
|
(file) => `<file path="${file.rel}">\n${file.content}\n</file>`,
|
|
)
|
|
.join("\n\n")
|
|
: null,
|
|
loadedPaths,
|
|
};
|
|
}
|
|
|
|
export function fileHash(content: string): string {
|
|
let hash = 0;
|
|
for (let index = 0; index < content.length; index++) {
|
|
hash = ((hash << 5) - hash + content.charCodeAt(index)) | 0;
|
|
}
|
|
return hash.toString(16);
|
|
}
|