hammerstone/src/vault.ts
2024-05-08 11:09:37 -04:00

88 lines
2.2 KiB
TypeScript

import { globSync } from "glob";
import MarkdownDocument from "./document.js";
/**
* Load documents from an Obsidian vault
* @param vaultPath The path to the vault to load
* @param ignorePatterns A glob pattern to ignore files for
* @returns A promise which resolves as an array of laoded Documents
*/
function loadVaultDocuments(
vaultPath: string,
ignorePatterns: string[] = [],
): MarkdownDocument[] {
const discoveredMarkdownDocuments = globSync(`${vaultPath}/**/*.md`, {
ignore: ignorePatterns,
});
const markdownDocuments: MarkdownDocument[] = [];
for (const filePath of discoveredMarkdownDocuments) {
const file = new MarkdownDocument(filePath, vaultPath);
if (markdownDocuments.some((check) => check.slug === file.slug)) {
throw new Error("Duplicate slug: " + file.slug);
}
markdownDocuments.push(file);
}
return markdownDocuments;
}
/**
* Build a VaultIndex from a list of loaded Documents
* @param vaultDocs An array of all the documents to index
* @returns A VaultIndex, which is an object that maps document slugs to information
*/
function buildVaultIndex(
vaultDocs: MarkdownDocument[],
): Record<string, MarkdownDocument> {
const index: Record<string, MarkdownDocument> = {};
for (const document of vaultDocs) {
index[document.slug] = document;
}
return index;
}
interface VaultOptions {
ignorePatterns?: string[];
}
export default class Vault {
documents: MarkdownDocument[] = [];
slugs: string[] = [];
index: Record<string, MarkdownDocument> = {};
readonly vaultPath: string;
readonly size: number = 0;
private ignorePatterns: string[] = [];
constructor(vaultRootPath: string, options?: VaultOptions) {
this.vaultPath = vaultRootPath;
this.ignorePatterns = options?.ignorePatterns ?? [];
const allFiles = loadVaultDocuments(this.vaultPath, this.ignorePatterns);
const allSlugs = allFiles.map((doc) => doc.slug);
this.documents = allFiles;
this.slugs = allSlugs;
this.size = allFiles.length;
this.index = buildVaultIndex(allFiles);
}
map(fn: (document: MarkdownDocument) => MarkdownDocument) {
this.documents = this.documents.map(fn);
return this;
}
write() {
this.documents.forEach((doc) => {
doc.write();
});
}
}