refactor: create monorepo

This commit is contained in:
Artemy
2024-05-12 16:24:50 +03:00
parent b21ee84629
commit 30977d1357
89 changed files with 9364 additions and 1641 deletions

View File

@ -0,0 +1,52 @@
import Route from "route-parser";
import {
HandlerInput,
IHandlerOutput,
EngineFunction,
RouteValues,
} from "./types/handler";
import { NoHandlerFoundError } from "./types/errors";
interface IRoute<TParams extends RouteValues> {
route: Route;
handler: EngineFunction<TParams>;
}
export class Engine {
name: string;
description: string;
domains: string[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
routes: IRoute<any>[] = [];
constructor(name: string, description: string, domains: string[] = []) {
this.domains = domains;
this.name = name;
this.description = description;
}
route<TParams extends RouteValues>(
path: string,
handler: EngineFunction<TParams>
) {
this.routes.push({ route: new Route<TParams>(path), handler });
}
async handle(input: HandlerInput): Promise<IHandlerOutput> {
const url = new URL(input.getUrl());
const path = url.pathname + url.search + url.hash;
for (const route of this.routes) {
const match = route.route.match(path);
if (match) {
return await route.handler(input, {
q: match,
reverse: (req) => route.route.reverse(req),
});
}
}
throw new NoHandlerFoundError(`${path}. [${this.name}]`);
}
}

3
packages/sdk/src/lib.ts Normal file
View File

@ -0,0 +1,3 @@
import { Engine } from "./engine";
export { Engine };

View File

@ -0,0 +1,24 @@
export abstract class TxtDotError extends Error {
code: number;
name: string;
description: string;
constructor(code: number, name: string, description: string) {
super(description);
this.code = code;
this.name = name;
this.description = description;
}
}
export class NoHandlerFoundError extends TxtDotError {
constructor(message: string) {
super(404, "NoHandlerFoundError", `No handler found for: ${message}`);
}
}
export class EngineParseError extends TxtDotError {
constructor(message: string) {
super(422, "EngineParseError", `Parse error: ${message}`);
}
}

View File

@ -0,0 +1,78 @@
import { parseHTML } from "linkedom";
import { Engine } from "../engine";
export class HandlerInput {
private data: string;
private url: string;
private dom?: Window;
constructor(data: string, url: string) {
this.data = data;
this.url = url;
}
getUrl(): string {
return this.url;
}
parseDom(): Window {
if (this.dom) {
return this.dom;
}
this.dom = parseHTML(this.data);
return this.dom;
}
}
export interface IHandlerOutput {
content: string;
textContent: string;
title?: string;
lang?: string;
}
export const handlerSchema = {
type: "object",
properties: {
content: {
type: "string",
},
textContent: {
type: "string",
},
title: {
type: "string",
},
lang: {
type: "string",
},
},
};
export interface Engines {
[key: string]: Engine;
}
export type EngineMatch<TParams extends RouteValues> = {
pattern: string | string[];
engine: EngineFunction<TParams>;
};
export interface RouteValues {
[key: string]: string;
}
export type EngineFunction<TParams extends RouteValues> = (
input: HandlerInput,
ro: Route<TParams>
) => Promise<IHandlerOutput>;
export type EnginesMatch<TParams extends RouteValues> = EngineMatch<TParams>[];
export interface Route<TParams extends RouteValues> {
q: TParams;
reverse: (req: { [K in keyof TParams]: string | number | boolean }) =>
| string
| false;
}