94 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { createHash } from "node:crypto";
 | 
						|
import { promises, type Stats } from "node:fs";
 | 
						|
import path, { extname } from "node:path";
 | 
						|
import type { DocumentBody } from "dbtype";
 | 
						|
import { oshash } from "src/util/oshash.ts";
 | 
						|
/**
 | 
						|
 * content file or directory referrer
 | 
						|
 */
 | 
						|
export interface ContentFile {
 | 
						|
	getHash(): Promise<string>;
 | 
						|
	createDocumentBody(): Promise<DocumentBody>;
 | 
						|
	readonly path: string;
 | 
						|
	readonly type: string;
 | 
						|
}
 | 
						|
 | 
						|
export type ContentConstructOption = {
 | 
						|
	hash: string;
 | 
						|
};
 | 
						|
type ContentFileConstructor = (new (
 | 
						|
	path: string,
 | 
						|
	option?: ContentConstructOption,
 | 
						|
) => ContentFile) & {
 | 
						|
	content_type: string;
 | 
						|
};
 | 
						|
export const createDefaultClass = (type: string): ContentFileConstructor => {
 | 
						|
	const cons = class implements ContentFile {
 | 
						|
		readonly path: string;
 | 
						|
		// type = type;
 | 
						|
		static content_type = type;
 | 
						|
		protected hash: string | undefined;
 | 
						|
		protected stat: Stats | undefined;
 | 
						|
 | 
						|
		protected getStat(){
 | 
						|
			return this.stat;
 | 
						|
		}
 | 
						|
 | 
						|
		constructor(path: string, option?: ContentConstructOption) {
 | 
						|
			this.path = path;
 | 
						|
			this.hash = option?.hash;
 | 
						|
			this.stat = undefined;
 | 
						|
		}
 | 
						|
		async createDocumentBody(): Promise<DocumentBody> {
 | 
						|
			console.log(`createDocumentBody: ${this.path}`);
 | 
						|
			const { base, dir, name } = path.parse(this.path);
 | 
						|
			
 | 
						|
			const ret = {
 | 
						|
				title: name,
 | 
						|
				basepath: dir,
 | 
						|
				additional: {},
 | 
						|
				content_type: cons.content_type,
 | 
						|
				filename: base,
 | 
						|
				tags: [],
 | 
						|
				content_hash: await this.getHash(),
 | 
						|
				modified_at: await this.getMtime(),
 | 
						|
				pagenum: 0,
 | 
						|
			} as DocumentBody;
 | 
						|
			return ret;
 | 
						|
		}
 | 
						|
		get type(): string {
 | 
						|
			return cons.content_type;
 | 
						|
		}
 | 
						|
		async getHash(): Promise<string> {
 | 
						|
			if (this.hash !== undefined) return this.hash;
 | 
						|
			const hash = await oshash(this.path);
 | 
						|
			this.hash = hash.toString();
 | 
						|
			return this.hash;
 | 
						|
		}
 | 
						|
		async getMtime(): Promise<number> {
 | 
						|
			const oldStat = this.getStat();
 | 
						|
			if (oldStat !== undefined) return oldStat.mtimeMs;
 | 
						|
			const stat = await promises.stat(this.path);
 | 
						|
			this.stat = stat;
 | 
						|
			return stat.mtimeMs;
 | 
						|
		}
 | 
						|
	};
 | 
						|
	return cons;
 | 
						|
};
 | 
						|
const ContstructorTable: { [k: string]: ContentFileConstructor } = {};
 | 
						|
export function registerContentReferrer(s: ContentFileConstructor) {
 | 
						|
	console.log(`registered content type: ${s.content_type}`);
 | 
						|
	ContstructorTable[s.content_type] = s;
 | 
						|
}
 | 
						|
export function createContentFile(type: string, path: string, option?: ContentConstructOption) {
 | 
						|
	const constructorMethod = ContstructorTable[type];
 | 
						|
	if (constructorMethod === undefined) {
 | 
						|
		console.log(`${type} are not in ${JSON.stringify(ContstructorTable)}`);
 | 
						|
		throw new Error("construction method of the content type is undefined");
 | 
						|
	}
 | 
						|
	return new constructorMethod(path, option);
 | 
						|
}
 | 
						|
export function getContentFileConstructor(type: string): ContentFileConstructor | undefined {
 | 
						|
	const ret = ContstructorTable[type];
 | 
						|
	return ret;
 | 
						|
}
 |