Add environment variables for fine-grained control over TTS rate limiting and Better Auth behavior. Move documentation to external Docusaurus site with automated deployment workflows. - TTS rate limiting can now be enabled/disabled via TTS_ENABLE_RATE_LIMIT - Customizable daily limits for anonymous/authenticated users and IP backstops - Better Auth rate limiting can be disabled via DISABLE_AUTH_RATE_LIMIT - Rename library import env vars to IMPORT_LIBRARY_DIRS/DIR - Add docs-site with Docusaurus and GitHub Actions workflows - Update README to reference external documentation
48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
import path from 'path';
|
|
|
|
export const DOCSTORE_DIR = path.join(process.cwd(), 'docstore');
|
|
export const DEFAULT_LIBRARY_DIR = path.join(DOCSTORE_DIR, 'library');
|
|
|
|
export function parseLibraryRoots(): string[] {
|
|
const raw = process.env.IMPORT_LIBRARY_DIRS ?? process.env.IMPORT_LIBRARY_DIR ?? '';
|
|
|
|
const roots = raw
|
|
.split(/[,:;]/g)
|
|
.map((value) => value.trim())
|
|
.filter(Boolean);
|
|
|
|
if (roots.length > 0) {
|
|
return roots;
|
|
}
|
|
|
|
return [DEFAULT_LIBRARY_DIR];
|
|
}
|
|
|
|
export function contentTypeForName(name: string): string {
|
|
const ext = path.extname(name).toLowerCase();
|
|
if (ext === '.pdf') return 'application/pdf';
|
|
if (ext === '.epub') return 'application/epub+zip';
|
|
if (ext === '.md' || ext === '.mdown' || ext === '.markdown') return 'text/markdown; charset=utf-8';
|
|
if (ext === '.html' || ext === '.htm') return 'text/html; charset=utf-8';
|
|
return 'text/plain; charset=utf-8';
|
|
}
|
|
|
|
export function decodeLibraryId(id: string): { rootIndex: number; relativePath: string } | null {
|
|
try {
|
|
const decoded = Buffer.from(id, 'base64url').toString('utf8');
|
|
const sepIndex = decoded.indexOf(':');
|
|
if (sepIndex <= 0) return null;
|
|
const rootIndex = Number(decoded.slice(0, sepIndex));
|
|
if (!Number.isInteger(rootIndex) || rootIndex < 0) return null;
|
|
const relativePath = decoded.slice(sepIndex + 1);
|
|
if (!relativePath) return null;
|
|
return { rootIndex, relativePath };
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function isPathWithinRoot(resolvedRoot: string, resolvedFile: string): boolean {
|
|
return resolvedFile === resolvedRoot || resolvedFile.startsWith(resolvedRoot + path.sep);
|
|
}
|
|
|