refactor: create monorepo
This commit is contained in:
52
packages/sdk/src/engine.ts
Normal file
52
packages/sdk/src/engine.ts
Normal 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
3
packages/sdk/src/lib.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { Engine } from "./engine";
|
||||
|
||||
export { Engine };
|
24
packages/sdk/src/types/errors.ts
Normal file
24
packages/sdk/src/types/errors.ts
Normal 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}`);
|
||||
}
|
||||
}
|
78
packages/sdk/src/types/handler.ts
Normal file
78
packages/sdk/src/types/handler.ts
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user