@better-agnostic/handler 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ import type { SchemaContribution } from "@better-agnostic/schema";
2
+ import type { Route } from "./types.js";
3
+ export interface Plugin<THooks = Record<string, never>, TEngine = unknown> {
4
+ name: string;
5
+ version?: string;
6
+ routes?: Route<TEngine>[];
7
+ hooks?: Partial<THooks>;
8
+ createServices?: (engine: TEngine) => Record<string, unknown>;
9
+ init?(engine: TEngine): Promise<void> | void;
10
+ schemaContribution?: SchemaContribution;
11
+ }
12
+ //# sourceMappingURL=Plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Plugin.d.ts","sourceRoot":"","sources":["../src/Plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9D,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC"}
package/dist/Plugin.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Plugin.js","sourceRoot":"","sources":["../src/Plugin.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { CoreRequest, CoreResponse } from "./types.js";
2
+ export interface DispatchableEngine<TAuth = unknown> {
3
+ getRoutes(): Array<{
4
+ method: string;
5
+ path: string;
6
+ handler: (ctx: unknown) => Promise<CoreResponse> | CoreResponse;
7
+ }>;
8
+ init?(): Promise<void>;
9
+ }
10
+ export declare function dispatch<TEngine extends DispatchableEngine>(engine: TEngine, req: CoreRequest, basePath?: string): Promise<CoreResponse>;
11
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG5D,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,OAAO;IACjD,SAAS,IAAI,KAAK,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;KACjE,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,QAAQ,CAAC,OAAO,SAAS,kBAAkB,EAC/D,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,WAAW,EAChB,QAAQ,SAAK,GACZ,OAAO,CAAC,YAAY,CAAC,CA4BvB"}
@@ -0,0 +1,30 @@
1
+ import { findRoute } from "./routes.js";
2
+ import { errorToResponse } from "./utils.js";
3
+ export async function dispatch(engine, req, basePath = "") {
4
+ if (typeof engine.init === "function") {
5
+ await engine.init();
6
+ }
7
+ const path = basePath
8
+ ? req.path.startsWith(basePath)
9
+ ? req.path.slice(basePath.length) || "/"
10
+ : req.path
11
+ : req.path;
12
+ const normalizedPath = path.replace(/\/$/, "") || "/";
13
+ const routes = engine.getRoutes();
14
+ const found = findRoute(routes, req.method, normalizedPath);
15
+ if (!found) {
16
+ return {
17
+ status: 404,
18
+ body: { code: "NOT_FOUND", message: "Route not found" },
19
+ };
20
+ }
21
+ const { route, params } = found;
22
+ const reqWithParams = { ...req, params };
23
+ try {
24
+ return await route.handler({ engine, req: reqWithParams });
25
+ }
26
+ catch (err) {
27
+ return errorToResponse(err);
28
+ }
29
+ }
30
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAW7C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAe,EACf,GAAgB,EAChB,QAAQ,GAAG,EAAE;IAEb,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACtC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ;QACnB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC7B,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG;YACxC,CAAC,CAAC,GAAG,CAAC,IAAI;QACZ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IACb,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;IAEtD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,EAAE;SACxD,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAChC,MAAM,aAAa,GAAG,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,CAAC;IAEzC,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ export type { CoreRequest, CoreResponse, Route, RouteHandler } from "./types.js";
2
+ export { matchPath } from "./path.js";
3
+ export type { PathMatch } from "./path.js";
4
+ export { queryToRecord, parseJsonBody, errorToResponse, successResponse, parseLimit, streamResponse, } from "./utils.js";
5
+ export { parseBody } from "./parseBody.js";
6
+ export { buildRoutes, findRoute } from "./routes.js";
7
+ export { dispatch } from "./dispatch.js";
8
+ export type { DispatchableEngine } from "./dispatch.js";
9
+ export type { Plugin } from "./Plugin.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { matchPath } from "./path.js";
2
+ export { queryToRecord, parseJsonBody, errorToResponse, successResponse, parseLimit, streamResponse, } from "./utils.js";
3
+ export { parseBody } from "./parseBody.js";
4
+ export { buildRoutes, findRoute } from "./routes.js";
5
+ export { dispatch } from "./dispatch.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ZodType } from "zod";
2
+ import type { CoreRequest } from "./types.js";
3
+ /**
4
+ * Parses and validates request body against a Zod schema.
5
+ * Throws ValidationError (with issues) on failure.
6
+ */
7
+ export declare function parseBody<T>(req: CoreRequest, schema: ZodType<T>): T;
8
+ //# sourceMappingURL=parseBody.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseBody.d.ts","sourceRoot":"","sources":["../src/parseBody.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CA4BpE"}
@@ -0,0 +1,32 @@
1
+ import { ValidationError } from "@better-agnostic/errors";
2
+ /**
3
+ * Parses and validates request body against a Zod schema.
4
+ * Throws ValidationError (with issues) on failure.
5
+ */
6
+ export function parseBody(req, schema) {
7
+ const raw = req.body;
8
+ if (raw === null || raw === undefined) {
9
+ throw new ValidationError("Request body is required", {
10
+ metadata: { issues: [{ message: "Body is null or undefined" }] },
11
+ });
12
+ }
13
+ if (typeof raw !== "object" || Array.isArray(raw)) {
14
+ throw new ValidationError("Request body must be an object", {
15
+ metadata: { issues: [{ message: "Expected object" }] },
16
+ });
17
+ }
18
+ const result = schema.safeParse(raw);
19
+ if (result.success) {
20
+ return result.data;
21
+ }
22
+ const zodError = result.error;
23
+ const issues = zodError.issues.map((issue) => ({
24
+ path: issue.path.join("."),
25
+ message: issue.message,
26
+ code: issue.code,
27
+ }));
28
+ throw new ValidationError(zodError.message, {
29
+ metadata: { issues },
30
+ });
31
+ }
32
+ //# sourceMappingURL=parseBody.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseBody.js","sourceRoot":"","sources":["../src/parseBody.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI1D;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAI,GAAgB,EAAE,MAAkB;IAC/D,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC;IACrB,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,IAAI,eAAe,CAAC,0BAA0B,EAAE;YACpD,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC,EAAE;SACjE,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,eAAe,CAAC,gCAAgC,EAAE;YAC1D,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,EAAE;SACvD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC,IAAS,CAAC;IAC1B,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;IAC9B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7C,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC,CAAC;IAEJ,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE;QAC1C,QAAQ,EAAE,EAAE,MAAM,EAAE;KACrB,CAAC,CAAC;AACL,CAAC"}
package/dist/path.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export interface PathMatch {
2
+ matches: boolean;
3
+ params: Record<string, string>;
4
+ }
5
+ export declare function matchPath(pattern: string, path: string): PathMatch;
6
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAmBlE"}
package/dist/path.js ADDED
@@ -0,0 +1,20 @@
1
+ export function matchPath(pattern, path) {
2
+ const patternParts = pattern.split("/").filter(Boolean);
3
+ const pathParts = path.replace(/^\//, "").split("/").filter(Boolean);
4
+ if (patternParts.length !== pathParts.length) {
5
+ return { matches: false, params: {} };
6
+ }
7
+ const params = {};
8
+ for (let i = 0; i < patternParts.length; i++) {
9
+ const p = patternParts[i];
10
+ const v = pathParts[i];
11
+ if (p?.startsWith(":")) {
12
+ params[p.slice(1)] = v ?? "";
13
+ }
14
+ else if (p !== v) {
15
+ return { matches: false, params: {} };
16
+ }
17
+ }
18
+ return { matches: true, params };
19
+ }
20
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,IAAY;IACrD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAErE,IAAI,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;aAAM,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACxC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from "./Plugin.js";
2
+ import type { Route } from "./types.js";
3
+ export declare function buildRoutes<TEngine, TPlugin extends Plugin<Record<string, never>, TEngine>>(coreRoutes: Route<TEngine>[], plugins?: TPlugin[]): Route<TEngine>[];
4
+ export declare function findRoute<TEngine>(routesToSearch: Route<TEngine>[], method: string, path: string): {
5
+ route: Route<TEngine>;
6
+ params: Record<string, string>;
7
+ } | null;
8
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,EACzF,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,EAC5B,OAAO,CAAC,EAAE,OAAO,EAAE,GAClB,KAAK,CAAC,OAAO,CAAC,EAAE,CAGlB;AAED,wBAAgB,SAAS,CAAC,OAAO,EAC/B,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,EAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX;IAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAQlE"}
package/dist/routes.js ADDED
@@ -0,0 +1,17 @@
1
+ import { matchPath } from "./path.js";
2
+ export function buildRoutes(coreRoutes, plugins) {
3
+ const pluginRoutes = plugins?.flatMap((p) => p.routes ?? []) ?? [];
4
+ return [...coreRoutes, ...pluginRoutes];
5
+ }
6
+ export function findRoute(routesToSearch, method, path) {
7
+ const normalizedPath = path.replace(/\/$/, "") || "/";
8
+ for (const route of routesToSearch) {
9
+ if (route.method !== method)
10
+ continue;
11
+ const { matches, params } = matchPath(route.path, normalizedPath);
12
+ if (matches)
13
+ return { route, params };
14
+ }
15
+ return null;
16
+ }
17
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,UAAU,WAAW,CACzB,UAA4B,EAC5B,OAAmB;IAEnB,MAAM,YAAY,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IACnE,OAAO,CAAC,GAAG,UAAU,EAAE,GAAG,YAAY,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,cAAgC,EAChC,MAAc,EACd,IAAY;IAEZ,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;IACtD,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;YAAE,SAAS;QACtC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAClE,IAAI,OAAO;YAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,24 @@
1
+ export interface CoreRequest<TAuth = unknown> {
2
+ method: string;
3
+ path: string;
4
+ params: Record<string, string>;
5
+ query: Record<string, string>;
6
+ body: unknown;
7
+ auth?: TAuth;
8
+ }
9
+ export interface CoreResponse {
10
+ status: number;
11
+ body?: unknown;
12
+ headers?: Record<string, string>;
13
+ stream?: ReadableStream;
14
+ }
15
+ export type RouteHandler<TEngine = unknown, TAuth = unknown> = (ctx: {
16
+ engine: TEngine;
17
+ req: CoreRequest<TAuth>;
18
+ }) => Promise<CoreResponse> | CoreResponse;
19
+ export interface Route<TEngine = unknown, TAuth = unknown> {
20
+ method: string;
21
+ path: string;
22
+ handler: RouteHandler<TEngine, TAuth>;
23
+ }
24
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,OAAO;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,MAAM,MAAM,YAAY,CAAC,OAAO,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,IAAI,CAAC,GAAG,EAAE;IACnE,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;CACzB,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;AAE3C,MAAM,WAAW,KAAK,CAAC,OAAO,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;CACvC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { CoreResponse } from "./types.js";
2
+ export declare function queryToRecord(q: Record<string, unknown> | null | undefined): Record<string, string>;
3
+ export declare function parseJsonBody(raw: string | null): unknown;
4
+ export declare function errorToResponse(err: unknown): CoreResponse;
5
+ export declare function successResponse(data: unknown, status?: number): CoreResponse;
6
+ export declare function parseLimit(queryLimit: string | undefined, defaultLimit?: number): number;
7
+ export declare function streamResponse(stream: ReadableStream, headers?: Record<string, string>): CoreResponse;
8
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,aAAa,CAC3B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAC5C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAOzD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAY1D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,SAAM,GAAG,YAAY,CAEzE;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,SAAK,GAAG,MAAM,CAIpF;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,YAAY,CAWd"}
package/dist/utils.js ADDED
@@ -0,0 +1,55 @@
1
+ import { isBaseError, toJsonPayload } from "@better-agnostic/errors";
2
+ export function queryToRecord(q) {
3
+ const out = {};
4
+ for (const [k, v] of Object.entries(q ?? {})) {
5
+ if (v !== undefined && v !== null) {
6
+ out[k] = Array.isArray(v) ? v[0] : String(v);
7
+ }
8
+ }
9
+ return out;
10
+ }
11
+ export function parseJsonBody(raw) {
12
+ if (!raw || raw.trim() === "")
13
+ return null;
14
+ try {
15
+ return JSON.parse(raw);
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ export function errorToResponse(err) {
22
+ if (isBaseError(err) && err.expose) {
23
+ const payload = toJsonPayload(err);
24
+ return {
25
+ status: err.statusCode,
26
+ body: payload,
27
+ };
28
+ }
29
+ return {
30
+ status: 500,
31
+ body: { code: "INTERNAL_ERROR", message: "An unexpected error occurred" },
32
+ };
33
+ }
34
+ export function successResponse(data, status = 200) {
35
+ return { status, body: data };
36
+ }
37
+ export function parseLimit(queryLimit, defaultLimit = 50) {
38
+ const raw = queryLimit ? Number.parseInt(queryLimit, 10) : defaultLimit;
39
+ if (Number.isNaN(raw) || raw < 1)
40
+ return defaultLimit;
41
+ return Math.min(raw, 100);
42
+ }
43
+ export function streamResponse(stream, headers) {
44
+ return {
45
+ status: 200,
46
+ headers: {
47
+ "Content-Type": "text/event-stream",
48
+ "Cache-Control": "no-cache",
49
+ Connection: "keep-alive",
50
+ ...headers,
51
+ },
52
+ stream,
53
+ };
54
+ }
55
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGrE,MAAM,UAAU,aAAa,CAC3B,CAA6C;IAE7C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAClC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAkB;IAC9C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QACnC,OAAO;YACL,MAAM,EAAE,GAAG,CAAC,UAAU;YACtB,IAAI,EAAE,OAAO;SACd,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,8BAA8B,EAAE;KAC1E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAa,EAAE,MAAM,GAAG,GAAG;IACzD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,UAA8B,EAAE,YAAY,GAAG,EAAE;IAC1E,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IACxE,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,YAAY,CAAC;IACtD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAsB,EACtB,OAAgC;IAEhC,OAAO;QACL,MAAM,EAAE,GAAG;QACX,OAAO,EAAE;YACP,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,UAAU,EAAE,YAAY;YACxB,GAAG,OAAO;SACX;QACD,MAAM;KACP,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@better-agnostic/handler",
3
+ "version": "0.0.2",
4
+ "description": "Core HTTP dispatch, routing, and utilities for better-agnostic handlers",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/elydelva/better-agnostic",
9
+ "directory": "packages/handler"
10
+ },
11
+ "keywords": ["handler", "better-agnostic", "http", "dispatch", "routing"],
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js",
22
+ "default": "./dist/index.js"
23
+ }
24
+ },
25
+ "scripts": {
26
+ "build": "tsc"
27
+ },
28
+ "dependencies": {
29
+ "@better-agnostic/errors": "workspace:*",
30
+ "@better-agnostic/schema": "workspace:*",
31
+ "zod": "^4.3.6"
32
+ },
33
+ "devDependencies": {
34
+ "typescript": "^5.7.0"
35
+ },
36
+ "files": ["dist"]
37
+ }