lynnix 0.0.1
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.
- package/README.md +542 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/lynnix.d.ts +46 -0
- package/dist/lynnix.d.ts.map +1 -0
- package/dist/lynnix.js +199 -0
- package/dist/lynnix.js.map +1 -0
- package/dist/utils/augmentRequest.d.ts +12 -0
- package/dist/utils/augmentRequest.d.ts.map +1 -0
- package/dist/utils/augmentRequest.js +66 -0
- package/dist/utils/augmentRequest.js.map +1 -0
- package/dist/utils/augmentResponse.d.ts +17 -0
- package/dist/utils/augmentResponse.d.ts.map +1 -0
- package/dist/utils/augmentResponse.js +56 -0
- package/dist/utils/augmentResponse.js.map +1 -0
- package/dist/utils/buildRoutesMap.d.ts +19 -0
- package/dist/utils/buildRoutesMap.d.ts.map +1 -0
- package/dist/utils/buildRoutesMap.js +48 -0
- package/dist/utils/buildRoutesMap.js.map +1 -0
- package/dist/utils/error.d.ts +18 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +20 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/findClosestBoundary.d.ts +14 -0
- package/dist/utils/findClosestBoundary.d.ts.map +1 -0
- package/dist/utils/findClosestBoundary.js +29 -0
- package/dist/utils/findClosestBoundary.js.map +1 -0
- package/dist/utils/getMiddlewareChain.d.ts +19 -0
- package/dist/utils/getMiddlewareChain.d.ts.map +1 -0
- package/dist/utils/getMiddlewareChain.js +31 -0
- package/dist/utils/getMiddlewareChain.js.map +1 -0
- package/dist/utils/handleHttpError.d.ts +24 -0
- package/dist/utils/handleHttpError.d.ts.map +1 -0
- package/dist/utils/handleHttpError.js +23 -0
- package/dist/utils/handleHttpError.js.map +1 -0
- package/dist/utils/handleNotFound.d.ts +33 -0
- package/dist/utils/handleNotFound.d.ts.map +1 -0
- package/dist/utils/handleNotFound.js +71 -0
- package/dist/utils/handleNotFound.js.map +1 -0
- package/dist/utils/lruCache.d.ts +17 -0
- package/dist/utils/lruCache.d.ts.map +1 -0
- package/dist/utils/lruCache.js +36 -0
- package/dist/utils/lruCache.js.map +1 -0
- package/dist/utils/lynnixRequest.d.ts +22 -0
- package/dist/utils/lynnixRequest.d.ts.map +1 -0
- package/dist/utils/lynnixRequest.js +21 -0
- package/dist/utils/lynnixRequest.js.map +1 -0
- package/dist/utils/lynnixResponse.d.ts +53 -0
- package/dist/utils/lynnixResponse.d.ts.map +1 -0
- package/dist/utils/lynnixResponse.js +142 -0
- package/dist/utils/lynnixResponse.js.map +1 -0
- package/dist/utils/matchRoute.d.ts +20 -0
- package/dist/utils/matchRoute.d.ts.map +1 -0
- package/dist/utils/matchRoute.js +55 -0
- package/dist/utils/matchRoute.js.map +1 -0
- package/dist/utils/parseReqBody.d.ts +28 -0
- package/dist/utils/parseReqBody.d.ts.map +1 -0
- package/dist/utils/parseReqBody.js +415 -0
- package/dist/utils/parseReqBody.js.map +1 -0
- package/dist/utils/runMiddlewares.d.ts +5 -0
- package/dist/utils/runMiddlewares.d.ts.map +1 -0
- package/dist/utils/runMiddlewares.js +18 -0
- package/dist/utils/runMiddlewares.js.map +1 -0
- package/dist/utils/sortRoutes.d.ts +16 -0
- package/dist/utils/sortRoutes.d.ts.map +1 -0
- package/dist/utils/sortRoutes.js +44 -0
- package/dist/utils/sortRoutes.js.map +1 -0
- package/package.json +68 -0
package/dist/lynnix.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import { pathToFileURL } from "node:url";
|
|
10
|
+
import Mutor from "mutorjs/server";
|
|
11
|
+
import augmentRequest from "./utils/augmentRequest.js";
|
|
12
|
+
import augmentResponse from "./utils/augmentResponse.js";
|
|
13
|
+
import buildRoutes from "./utils/buildRoutesMap.js";
|
|
14
|
+
import { HttpError, NotFoundError } from "./utils/error.js";
|
|
15
|
+
import findClosestBoundary from "./utils/findClosestBoundary.js";
|
|
16
|
+
import { handleHttpError } from "./utils/handleHttpError.js";
|
|
17
|
+
import { handleNotFound } from "./utils/handleNotFound.js";
|
|
18
|
+
import LRUCache from "./utils/lruCache.js";
|
|
19
|
+
import matchRoute from "./utils/matchRoute.js";
|
|
20
|
+
import parseReqBody from "./utils/parseReqBody.js";
|
|
21
|
+
import runMiddlewares from "./utils/runMiddlewares.js";
|
|
22
|
+
import { sortRoutes } from "./utils/sortRoutes.js";
|
|
23
|
+
/**
|
|
24
|
+
* @param path The root directory of the mutor instance
|
|
25
|
+
* @returns A request handler function that serves the mutor instance
|
|
26
|
+
* @example
|
|
27
|
+
*
|
|
28
|
+
* import createLynnixApp from "lynnix";
|
|
29
|
+
* import * as http from "node:http";
|
|
30
|
+
* import sendStatic from "serve-static";
|
|
31
|
+
*
|
|
32
|
+
* const handler = createLynnixApp("app");
|
|
33
|
+
* const serve = serveStatic("./public", { index: false });
|
|
34
|
+
*
|
|
35
|
+
* const server = http.createServer((req, res) => {
|
|
36
|
+
* serve(req, res, () => handler(req, res));
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* // OR
|
|
40
|
+
*
|
|
41
|
+
* import express from "express";
|
|
42
|
+
*
|
|
43
|
+
* const server = express();
|
|
44
|
+
* const handler = createLynnixApp("app");
|
|
45
|
+
*
|
|
46
|
+
* server.use(express.urlencoded({ extended: true }));
|
|
47
|
+
* server.use(express.json());
|
|
48
|
+
* server.static("./public");
|
|
49
|
+
*
|
|
50
|
+
* server.use(handler);
|
|
51
|
+
*
|
|
52
|
+
* // FINALLY
|
|
53
|
+
*
|
|
54
|
+
* server.listen(3000);
|
|
55
|
+
*/
|
|
56
|
+
export default async function createLynnixApp(path, mutorConfig = {}, bodyParserOptions = {}) {
|
|
57
|
+
if (!path || typeof path !== "string") {
|
|
58
|
+
throw new Error("path must be a string");
|
|
59
|
+
}
|
|
60
|
+
const MATCHED_ROUTES_CACHE = new LRUCache();
|
|
61
|
+
const mutor = new Mutor({ rootDir: path, ...mutorConfig });
|
|
62
|
+
const routesMap = await buildRoutes(path);
|
|
63
|
+
const sortedRoutes = sortRoutes(Object.keys(routesMap));
|
|
64
|
+
// Add layouts from the root directory
|
|
65
|
+
await mutor.addLayoutsInDir(path);
|
|
66
|
+
return async (_req, _res) => {
|
|
67
|
+
const isHtmxReq = _req.headers["hx-request"] === "true";
|
|
68
|
+
const req = await augmentRequest(_req);
|
|
69
|
+
const res = await augmentResponse(_res, isHtmxReq);
|
|
70
|
+
const { url } = req.raw;
|
|
71
|
+
const method = req.raw.method?.toUpperCase() ?? "GET";
|
|
72
|
+
if (!url) {
|
|
73
|
+
return res.raw.end();
|
|
74
|
+
}
|
|
75
|
+
const { pathname } = new URL(url, `http://${req.raw.headers.host ?? "localhost"}`);
|
|
76
|
+
const match = MATCHED_ROUTES_CACHE.get(pathname) ?? matchRoute(pathname, sortedRoutes);
|
|
77
|
+
if (!match) {
|
|
78
|
+
await handleNotFound({
|
|
79
|
+
req,
|
|
80
|
+
res,
|
|
81
|
+
mutor,
|
|
82
|
+
isHtmxReq,
|
|
83
|
+
routes: sortedRoutes,
|
|
84
|
+
routesMap,
|
|
85
|
+
pathname,
|
|
86
|
+
error: new NotFoundError(),
|
|
87
|
+
}, true);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
let data;
|
|
91
|
+
try {
|
|
92
|
+
req.params = match.params;
|
|
93
|
+
await parseReqBody(req, res, bodyParserOptions);
|
|
94
|
+
if (!MATCHED_ROUTES_CACHE.has(pathname)) {
|
|
95
|
+
MATCHED_ROUTES_CACHE.set(pathname, match);
|
|
96
|
+
}
|
|
97
|
+
await runMiddlewares(req, res, match.route, routesMap);
|
|
98
|
+
// If the response has already been ended, skip the loader and return early
|
|
99
|
+
if (res.raw.writableEnded) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const loaderPath = routesMap[match.route].loader;
|
|
103
|
+
if (loaderPath) {
|
|
104
|
+
const mod = await import(pathToFileURL(loaderPath).href);
|
|
105
|
+
const handler = mod[method];
|
|
106
|
+
if (typeof handler !== "function") {
|
|
107
|
+
if (method !== "GET") {
|
|
108
|
+
res.status(405);
|
|
109
|
+
res.raw.end();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
data = await handler(req, res);
|
|
115
|
+
}
|
|
116
|
+
if (res.raw.writableEnded) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// Return 405 for non-GET requests if no loader is found
|
|
122
|
+
if (method !== "GET") {
|
|
123
|
+
res.status(405);
|
|
124
|
+
res.raw.end();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
if (err instanceof HttpError) {
|
|
131
|
+
handleHttpError({
|
|
132
|
+
res,
|
|
133
|
+
mutor,
|
|
134
|
+
isHtmxReq,
|
|
135
|
+
pathname,
|
|
136
|
+
routesMap,
|
|
137
|
+
routes: sortedRoutes,
|
|
138
|
+
data: err.meta,
|
|
139
|
+
code: err.code,
|
|
140
|
+
error: err,
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (err instanceof NotFoundError) {
|
|
145
|
+
handleNotFound({
|
|
146
|
+
res,
|
|
147
|
+
req,
|
|
148
|
+
mutor,
|
|
149
|
+
isHtmxReq,
|
|
150
|
+
pathname,
|
|
151
|
+
routesMap,
|
|
152
|
+
routes: sortedRoutes,
|
|
153
|
+
data: err.meta,
|
|
154
|
+
error: err,
|
|
155
|
+
});
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const boundaryKey = isHtmxReq ? "fragmentError" : "error";
|
|
159
|
+
const nearestError = findClosestBoundary(pathname, boundaryKey, sortedRoutes, routesMap);
|
|
160
|
+
if (!nearestError?.paths?.[boundaryKey]) {
|
|
161
|
+
res.status(500);
|
|
162
|
+
res.raw.end();
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const html = mutor.renderFile(nearestError.paths[boundaryKey], {
|
|
166
|
+
error: err,
|
|
167
|
+
pathname,
|
|
168
|
+
});
|
|
169
|
+
res.status(500).html(html);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (isHtmxReq) {
|
|
173
|
+
const fragmentPath = routesMap[match.route].fragment;
|
|
174
|
+
if (!fragmentPath) {
|
|
175
|
+
res.status(200);
|
|
176
|
+
res.raw.end();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const html = mutor.renderFile(fragmentPath, {
|
|
180
|
+
data,
|
|
181
|
+
isHtmxReq,
|
|
182
|
+
url: pathname,
|
|
183
|
+
});
|
|
184
|
+
res.status(200).html(html);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const pagePath = routesMap[match.route].page;
|
|
188
|
+
if (!pagePath) {
|
|
189
|
+
res.raw.end();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const html = mutor.renderFile(pagePath, {
|
|
193
|
+
data,
|
|
194
|
+
url: pathname,
|
|
195
|
+
});
|
|
196
|
+
res.status(200).html(html);
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=lynnix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lynnix.js","sourceRoot":"","sources":["../src/lynnix.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import type * as http from "node:http";
|
|
10
|
+
import LynnixRequest from "./lynnixRequest.js";
|
|
11
|
+
export default function augmentRequest(req: http.IncomingMessage): Promise<LynnixRequest>;
|
|
12
|
+
//# sourceMappingURL=augmentRequest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"augmentRequest.d.ts","sourceRoot":"","sources":["../../src/utils/augmentRequest.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAEvC,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAQ/C,wBAA8B,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,0BAmBrE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import LynnixRequest from "./lynnixRequest.js";
|
|
10
|
+
let cookieParserPromise = null;
|
|
11
|
+
let qsParserPromise = null;
|
|
12
|
+
export default async function augmentRequest(req) {
|
|
13
|
+
const augmentedRequest = new LynnixRequest(req);
|
|
14
|
+
const baseUrl = `http://${req.headers.host ?? "localhost"}`;
|
|
15
|
+
const cookieParser = await loadCookieParser();
|
|
16
|
+
augmentedRequest.cookies = cookieParser
|
|
17
|
+
? cookieParser(req.headers.cookie ?? "")
|
|
18
|
+
: {};
|
|
19
|
+
augmentedRequest.isHtmx = req.headers["hx-request"] === "true";
|
|
20
|
+
augmentedRequest.htmx = Object.fromEntries(Object.entries(req.headers).filter(([k]) => k.startsWith("hx-")));
|
|
21
|
+
augmentedRequest.query = await parseQueryString(new URL(req.url ?? "", baseUrl).search.slice(1));
|
|
22
|
+
augmentedRequest.body = {};
|
|
23
|
+
augmentedRequest.files = {};
|
|
24
|
+
return augmentedRequest;
|
|
25
|
+
}
|
|
26
|
+
async function parseQueryString(queryString) {
|
|
27
|
+
if (!queryString) {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
const qsParser = await loadQsParser();
|
|
31
|
+
if (qsParser) {
|
|
32
|
+
return qsParser(queryString);
|
|
33
|
+
}
|
|
34
|
+
const params = new URLSearchParams(queryString);
|
|
35
|
+
const result = {};
|
|
36
|
+
for (const [key, value] of params.entries()) {
|
|
37
|
+
const existing = result[key];
|
|
38
|
+
if (typeof existing === "undefined") {
|
|
39
|
+
result[key] = value;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (Array.isArray(existing)) {
|
|
43
|
+
existing.push(value);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
result[key] = [existing, value];
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
async function loadCookieParser() {
|
|
51
|
+
if (!cookieParserPromise) {
|
|
52
|
+
cookieParserPromise = import("cookie")
|
|
53
|
+
.then((mod) => mod.parse.bind(mod))
|
|
54
|
+
.catch(() => null);
|
|
55
|
+
}
|
|
56
|
+
return cookieParserPromise;
|
|
57
|
+
}
|
|
58
|
+
async function loadQsParser() {
|
|
59
|
+
if (!qsParserPromise) {
|
|
60
|
+
qsParserPromise = import("qs")
|
|
61
|
+
.then((mod) => mod.default.parse.bind(mod.default))
|
|
62
|
+
.catch(() => null);
|
|
63
|
+
}
|
|
64
|
+
return qsParserPromise;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=augmentRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"augmentRequest.js","sourceRoot":"","sources":["../../src/utils/augmentRequest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import type * as http from "node:http";
|
|
10
|
+
import LynnixResponse from "./lynnixResponse.js";
|
|
11
|
+
/**
|
|
12
|
+
* Augments the response object with utility methods.
|
|
13
|
+
*
|
|
14
|
+
* @param res The raw response object
|
|
15
|
+
*/
|
|
16
|
+
export default function augmentResponse(res: http.ServerResponse<http.IncomingMessage>, isHtmx: boolean): Promise<LynnixResponse>;
|
|
17
|
+
//# sourceMappingURL=augmentResponse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"augmentResponse.d.ts","sourceRoot":"","sources":["../../src/utils/augmentResponse.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAEvC,OAAO,cAAqC,MAAM,qBAAqB,CAAC;AAIxE;;;;GAIG;AACH,wBAA8B,eAAe,CAC5C,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,CAAC,EAC9C,MAAM,EAAE,OAAO,2BAMf"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import LynnixResponse from "./lynnixResponse.js";
|
|
10
|
+
let cookieModulePromise = null;
|
|
11
|
+
/**
|
|
12
|
+
* Augments the response object with utility methods.
|
|
13
|
+
*
|
|
14
|
+
* @param res The raw response object
|
|
15
|
+
*/
|
|
16
|
+
export default async function augmentResponse(res, isHtmx) {
|
|
17
|
+
const cookieModule = await loadCookieModule();
|
|
18
|
+
const responseCookies = readResponseCookies(res, cookieModule);
|
|
19
|
+
return new LynnixResponse(res, isHtmx, cookieModule, responseCookies);
|
|
20
|
+
}
|
|
21
|
+
function normalizeSetCookieHeader(header) {
|
|
22
|
+
if (Array.isArray(header)) {
|
|
23
|
+
return header.filter((value) => typeof value === "string");
|
|
24
|
+
}
|
|
25
|
+
if (typeof header === "string") {
|
|
26
|
+
return [header];
|
|
27
|
+
}
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
function readResponseCookies(res, cookieModule) {
|
|
31
|
+
const cookies = {};
|
|
32
|
+
const existingHeaders = normalizeSetCookieHeader(res.getHeader("Set-Cookie"));
|
|
33
|
+
if (!cookieModule) {
|
|
34
|
+
return cookies;
|
|
35
|
+
}
|
|
36
|
+
for (let i = 0; i < existingHeaders.length; i++) {
|
|
37
|
+
try {
|
|
38
|
+
const parsed = cookieModule.parseSetCookie(existingHeaders[i]);
|
|
39
|
+
cookies[parsed.name] = parsed.value;
|
|
40
|
+
}
|
|
41
|
+
catch { }
|
|
42
|
+
}
|
|
43
|
+
return cookies;
|
|
44
|
+
}
|
|
45
|
+
async function loadCookieModule() {
|
|
46
|
+
if (!cookieModulePromise) {
|
|
47
|
+
cookieModulePromise = import("cookie")
|
|
48
|
+
.then((mod) => ({
|
|
49
|
+
serialize: mod.serialize.bind(mod),
|
|
50
|
+
parseSetCookie: mod.parseSetCookie.bind(mod),
|
|
51
|
+
}))
|
|
52
|
+
.catch(() => null);
|
|
53
|
+
}
|
|
54
|
+
return cookieModulePromise;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=augmentResponse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"augmentResponse.js","sourceRoot":"","sources":["../../src/utils/augmentResponse.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,cAAqC,MAAM,qBAAqB,CAAC;AAExE,IAAI,mBAAmB,GAAwC,IAAI,CAAC;AAEpE;;;;GAIG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,eAAe,CAC5C,GAA8C,EAC9C,MAAe;IAEf,MAAM,YAAY,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAC9C,MAAM,eAAe,GAAG,mBAAmB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAE/D,OAAO,IAAI,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,wBAAwB,CAChC,MAA8C;IAE9C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,EAAE,CAAC;AACX,CAAC;AAED,SAAS,mBAAmB,CAC3B,GAA8C,EAC9C,YAAiC;IAEjC,MAAM,OAAO,GAAG,EAAa,CAAC;IAC9B,MAAM,eAAe,GAAG,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAE9E,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/D,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACX,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,gBAAgB;IAC9B,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC1B,mBAAmB,GAAG,MAAM,CAAC,QAAQ,CAAC;aACpC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACf,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;YAClC,cAAc,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;SAC5C,CAAC,CAAC;aACF,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,mBAAmB,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import type { RoutesMap } from "../types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Builds a file tree from the given path, recursively traversing directories and mapping file names to their full paths.
|
|
12
|
+
*
|
|
13
|
+
* @param path The root directory to build the file tree from.
|
|
14
|
+
* @param baseRoute The base route for the file tree.
|
|
15
|
+
* @param cache The cache to store the file tree.
|
|
16
|
+
* @returns The file tree.
|
|
17
|
+
*/
|
|
18
|
+
export default function buildRoutes(path: string, baseRoute?: string, cache?: RoutesMap): Promise<RoutesMap>;
|
|
19
|
+
//# sourceMappingURL=buildRoutesMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildRoutesMap.d.ts","sourceRoot":"","sources":["../../src/utils/buildRoutesMap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAe7C;;;;;;;GAOG;AACH,wBAA8B,WAAW,CACxC,IAAI,EAAE,MAAM,EACZ,SAAS,SAAM,EACf,KAAK,GAAE,SAAc,GACnB,OAAO,CAAC,SAAS,CAAC,CAsBpB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import { readdir } from "node:fs/promises";
|
|
10
|
+
import { resolve } from "node:path";
|
|
11
|
+
const FILE_MAP = {
|
|
12
|
+
"page.html": "page",
|
|
13
|
+
"fragment.html": "fragment",
|
|
14
|
+
"loader.js": "loader",
|
|
15
|
+
"loader.ts": "loader",
|
|
16
|
+
"error.html": "error",
|
|
17
|
+
"not-found.html": "notFound",
|
|
18
|
+
"fragment.not-found.html": "fragmentNotFound",
|
|
19
|
+
"fragment.error.html": "fragmentError",
|
|
20
|
+
"middleware.ts": "middleware",
|
|
21
|
+
"middleware.js": "middleware",
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Builds a file tree from the given path, recursively traversing directories and mapping file names to their full paths.
|
|
25
|
+
*
|
|
26
|
+
* @param path The root directory to build the file tree from.
|
|
27
|
+
* @param baseRoute The base route for the file tree.
|
|
28
|
+
* @param cache The cache to store the file tree.
|
|
29
|
+
* @returns The file tree.
|
|
30
|
+
*/
|
|
31
|
+
export default async function buildRoutes(path, baseRoute = "/", cache = {}) {
|
|
32
|
+
for (const entry of await readdir(path, { withFileTypes: true })) {
|
|
33
|
+
const fullPath = resolve(path, entry.name);
|
|
34
|
+
if (entry.isDirectory()) {
|
|
35
|
+
await buildRoutes(fullPath, `${baseRoute}/${entry.name}`, cache);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const key = FILE_MAP[entry.name];
|
|
39
|
+
if (!key) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const parsedBaseRoute = baseRoute.replace(/^\/\//, "/");
|
|
43
|
+
cache[parsedBaseRoute] ?? (cache[parsedBaseRoute] = {});
|
|
44
|
+
cache[parsedBaseRoute][key] = fullPath;
|
|
45
|
+
}
|
|
46
|
+
return cache;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=buildRoutesMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildRoutesMap.js","sourceRoot":"","sources":["../../src/utils/buildRoutesMap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,QAAQ,GAAG;IAChB,WAAW,EAAE,MAAM;IACnB,eAAe,EAAE,UAAU;IAC3B,WAAW,EAAE,QAAQ;IACrB,WAAW,EAAE,QAAQ;IACrB,YAAY,EAAE,OAAO;IACrB,gBAAgB,EAAE,UAAU;IAC5B,yBAAyB,EAAE,kBAAkB;IAC7C,qBAAqB,EAAE,eAAe;IACtC,eAAe,EAAE,YAAY;IAC7B,eAAe,EAAE,YAAY;CACpB,CAAC;AAEX;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW,CACxC,IAAY,EACZ,SAAS,GAAG,GAAG,EACf,QAAmB,EAAE;IAErB,KAAK,MAAM,KAAK,IAAI,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE3C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,MAAM,WAAW,CAAC,QAAQ,EAAE,GAAG,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;YACjE,SAAS;QACV,CAAC;QAED,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,IAA6B,CAAC,CAAC;QAE1D,IAAI,CAAC,GAAG,EAAE,CAAC;YACV,SAAS;QACV,CAAC;QAED,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAExD,KAAK,CAAC,eAAe,MAArB,KAAK,CAAC,eAAe,IAAM,EAAE,EAAC;QAC9B,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;IACxC,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
export declare class NotFoundError {
|
|
10
|
+
meta?: unknown;
|
|
11
|
+
constructor(meta?: unknown);
|
|
12
|
+
}
|
|
13
|
+
export declare class HttpError {
|
|
14
|
+
code: number;
|
|
15
|
+
meta?: unknown;
|
|
16
|
+
constructor(code: number, meta?: unknown);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qBAAa,aAAa;IACN,IAAI,CAAC,EAAE,OAAO;gBAAd,IAAI,CAAC,EAAE,OAAO;CACjC;AAED,qBAAa,SAAS;IAEb,IAAI,EAAE,MAAM;IACZ,IAAI,CAAC,EAAE,OAAO;gBADd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO;CAEtB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
export class NotFoundError {
|
|
10
|
+
constructor(meta) {
|
|
11
|
+
this.meta = meta;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class HttpError {
|
|
15
|
+
constructor(code, meta) {
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.meta = meta;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,OAAO,aAAa;IACzB,YAAmB,IAAc;QAAd,SAAI,GAAJ,IAAI,CAAU;IAAG,CAAC;CACrC;AAED,MAAM,OAAO,SAAS;IACrB,YACQ,IAAY,EACZ,IAAc;QADd,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAU;IACnB,CAAC;CACJ"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import type { BoundaryKey, RoutesMap } from "../types.js";
|
|
10
|
+
export default function findClosestBoundary(path: string, key: BoundaryKey, routes: string[], routesMap: RoutesMap): {
|
|
11
|
+
paths: RoutesMap[string];
|
|
12
|
+
accessedRoute: string;
|
|
13
|
+
} | null;
|
|
14
|
+
//# sourceMappingURL=findClosestBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findClosestBoundary.d.ts","sourceRoot":"","sources":["../../src/utils/findClosestBoundary.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG1D,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAC1C,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,SAAS,EAAE,SAAS,GAClB;IAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA6B5D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import matchRoute from "./matchRoute.js";
|
|
10
|
+
export default function findClosestBoundary(path, key, routes, routesMap) {
|
|
11
|
+
// Find the boundary at the root level if it exists
|
|
12
|
+
if (path === "/") {
|
|
13
|
+
const routeEntry = routesMap["/"];
|
|
14
|
+
return routeEntry?.[key] ? { paths: routeEntry, accessedRoute: "/" } : null;
|
|
15
|
+
}
|
|
16
|
+
const match = matchRoute(path, routes);
|
|
17
|
+
if (match) {
|
|
18
|
+
const matchedBoundary = routesMap[match.route][key];
|
|
19
|
+
// Routes are pre-sorted (static before dynamic at equal depth), so matchRoute
|
|
20
|
+
// will never return a dynamic sibling over a static match.
|
|
21
|
+
if (matchedBoundary) {
|
|
22
|
+
return { paths: routesMap[match.route], accessedRoute: match.route };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const routeChunks = path.split("/").filter(Boolean);
|
|
26
|
+
routeChunks.pop();
|
|
27
|
+
return findClosestBoundary(`/${routeChunks.join("/")}`, key, routes, routesMap);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=findClosestBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findClosestBoundary.js","sourceRoot":"","sources":["../../src/utils/findClosestBoundary.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,UAAU,MAAM,iBAAiB,CAAC;AAEzC,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAC1C,IAAY,EACZ,GAAgB,EAChB,MAAgB,EAChB,SAAoB;IAEpB,mDAAmD;IACnD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QAClB,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7E,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAEvC,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,eAAe,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;QAEpD,8EAA8E;QAC9E,2DAA2D;QAC3D,IAAI,eAAe,EAAE,CAAC;YACrB,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QACtE,CAAC;IACF,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEpD,WAAW,CAAC,GAAG,EAAE,CAAC;IAElB,OAAO,mBAAmB,CACzB,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAC3B,GAAG,EACH,MAAM,EACN,SAAS,CACT,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import type { RoutesMap } from "../types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Recursively extracts the middleware chain for a given route
|
|
12
|
+
*
|
|
13
|
+
* @param route The route to extract the middleware chain for
|
|
14
|
+
* @param routesMap A map of routes to middleware functions
|
|
15
|
+
* @param chain The middleware chain to build (default: [])
|
|
16
|
+
* @returns The middleware chain for the given route
|
|
17
|
+
*/
|
|
18
|
+
export default function getMiddlewareChain(route: string, routesMap: RoutesMap, chain?: string[]): string[];
|
|
19
|
+
//# sourceMappingURL=getMiddlewareChain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getMiddlewareChain.d.ts","sourceRoot":"","sources":["../../src/utils/getMiddlewareChain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACzC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,SAAS,EACpB,KAAK,GAAE,MAAM,EAAO,YAkBpB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Recursively extracts the middleware chain for a given route
|
|
11
|
+
*
|
|
12
|
+
* @param route The route to extract the middleware chain for
|
|
13
|
+
* @param routesMap A map of routes to middleware functions
|
|
14
|
+
* @param chain The middleware chain to build (default: [])
|
|
15
|
+
* @returns The middleware chain for the given route
|
|
16
|
+
*/
|
|
17
|
+
export default function getMiddlewareChain(route, routesMap, chain = []) {
|
|
18
|
+
if (route === "/") {
|
|
19
|
+
if (routesMap[route]?.middleware) {
|
|
20
|
+
chain.unshift(routesMap[route].middleware);
|
|
21
|
+
}
|
|
22
|
+
return chain;
|
|
23
|
+
}
|
|
24
|
+
if (routesMap[route]?.middleware) {
|
|
25
|
+
chain.unshift(routesMap[route].middleware);
|
|
26
|
+
}
|
|
27
|
+
const routesChunks = route.split("/").filter(Boolean);
|
|
28
|
+
routesChunks.pop();
|
|
29
|
+
return getMiddlewareChain(`/${routesChunks.join("/")}`, routesMap, chain);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=getMiddlewareChain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getMiddlewareChain.js","sourceRoot":"","sources":["../../src/utils/getMiddlewareChain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACzC,KAAa,EACb,SAAoB,EACpB,QAAkB,EAAE;IAEpB,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;QACnB,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;YAClC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,KAAK,CAAC;IACd,CAAC;IAED,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;QAClC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtD,YAAY,CAAC,GAAG,EAAE,CAAC;IAEnB,OAAO,kBAAkB,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lynnix
|
|
3
|
+
* File-based hypermedia routing middleware for Node.js, Mutor.js, and HTMX.
|
|
4
|
+
*
|
|
5
|
+
* @author Onah Victor <victoronah.dev@gmail.com>
|
|
6
|
+
* @repository https://github.com/allAboutJS/Lynnix
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
import type Mutor from "mutorjs/server";
|
|
10
|
+
import type { RoutesMap } from "../types.js";
|
|
11
|
+
import type { HttpError } from "./error.js";
|
|
12
|
+
import type LynnixResponse from "./lynnixResponse.js";
|
|
13
|
+
export declare function handleHttpError({ res, mutor, pathname, isHtmxReq, routes, routesMap, data, code, error, }: {
|
|
14
|
+
code: number;
|
|
15
|
+
error: HttpError;
|
|
16
|
+
res: LynnixResponse;
|
|
17
|
+
mutor: Mutor;
|
|
18
|
+
isHtmxReq: boolean;
|
|
19
|
+
routes: string[];
|
|
20
|
+
routesMap: RoutesMap;
|
|
21
|
+
pathname: string;
|
|
22
|
+
data?: unknown;
|
|
23
|
+
}): void;
|
|
24
|
+
//# sourceMappingURL=handleHttpError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handleHttpError.d.ts","sourceRoot":"","sources":["../../src/utils/handleHttpError.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AAEtD,wBAAgB,eAAe,CAAC,EAC/B,GAAG,EACH,KAAK,EACL,QAAQ,EACR,SAAS,EACT,MAAM,EACN,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,KAAK,GACL,EAAE;IACF,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf,QAoBA"}
|