@kozojs/core 0.2.8 → 0.3.0
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/lib/chunk-W44TTZNJ.js +205 -0
- package/lib/index.js +63 -1081
- package/lib/middleware/index.js +16 -189
- package/package.json +10 -10
- package/lib/index.d.ts +0 -658
- package/lib/index.js.map +0 -1
- package/lib/middleware/index.d.ts +0 -160
- package/lib/middleware/index.js.map +0 -1
- package/lib/wasm/radix.wasm +0 -0
package/lib/middleware/index.js
CHANGED
|
@@ -1,191 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// src/middleware/cors.ts
|
|
18
|
-
import { cors as honoCors } from "hono/cors";
|
|
19
|
-
function cors(options = {}) {
|
|
20
|
-
return honoCors({
|
|
21
|
-
origin: options.origin || "*",
|
|
22
|
-
allowMethods: options.allowMethods || ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
|
|
23
|
-
allowHeaders: options.allowHeaders || ["Content-Type", "Authorization"],
|
|
24
|
-
exposeHeaders: options.exposeHeaders || [],
|
|
25
|
-
maxAge: options.maxAge || 86400,
|
|
26
|
-
credentials: options.credentials || false
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// src/middleware/rate-limit.ts
|
|
31
|
-
var store = /* @__PURE__ */ new Map();
|
|
32
|
-
function rateLimit(options) {
|
|
33
|
-
const {
|
|
34
|
-
max = 100,
|
|
35
|
-
window = 60,
|
|
36
|
-
keyGenerator = (c) => c.req.header("x-forwarded-for") ?? c.req.header("x-real-ip") ?? "anonymous",
|
|
37
|
-
message = "Too many requests"
|
|
38
|
-
} = options;
|
|
39
|
-
return async (c, next) => {
|
|
40
|
-
const key = keyGenerator(c);
|
|
41
|
-
const now = Date.now();
|
|
42
|
-
const windowMs = window * 1e3;
|
|
43
|
-
let record = store.get(key);
|
|
44
|
-
if (!record || now > record.resetAt) {
|
|
45
|
-
record = { count: 0, resetAt: now + windowMs };
|
|
46
|
-
}
|
|
47
|
-
record.count++;
|
|
48
|
-
store.set(key, record);
|
|
49
|
-
c.header("X-RateLimit-Limit", String(max));
|
|
50
|
-
c.header("X-RateLimit-Remaining", String(Math.max(0, max - record.count)));
|
|
51
|
-
c.header("X-RateLimit-Reset", String(Math.ceil(record.resetAt / 1e3)));
|
|
52
|
-
if (record.count > max) {
|
|
53
|
-
return c.json({ error: message }, 429);
|
|
54
|
-
}
|
|
55
|
-
await next();
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
function clearRateLimitStore() {
|
|
59
|
-
store.clear();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// src/middleware/error-handler.ts
|
|
63
|
-
var HttpError = class extends Error {
|
|
64
|
-
constructor(statusCode, message, details) {
|
|
65
|
-
super(message);
|
|
66
|
-
this.statusCode = statusCode;
|
|
67
|
-
this.details = details;
|
|
68
|
-
this.name = "HttpError";
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
var BadRequestError = class extends HttpError {
|
|
72
|
-
constructor(message = "Bad Request", details) {
|
|
73
|
-
super(400, message, details);
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
var UnauthorizedError = class extends HttpError {
|
|
77
|
-
constructor(message = "Unauthorized") {
|
|
78
|
-
super(401, message);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
var ForbiddenError = class extends HttpError {
|
|
82
|
-
constructor(message = "Forbidden") {
|
|
83
|
-
super(403, message);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
var NotFoundError = class extends HttpError {
|
|
87
|
-
constructor(message = "Not Found") {
|
|
88
|
-
super(404, message);
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
var ConflictError = class extends HttpError {
|
|
92
|
-
constructor(message = "Conflict", details) {
|
|
93
|
-
super(409, message, details);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
var InternalServerError = class extends HttpError {
|
|
97
|
-
constructor(message = "Internal Server Error") {
|
|
98
|
-
super(500, message);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
function errorHandler() {
|
|
102
|
-
return async (c, next) => {
|
|
103
|
-
try {
|
|
104
|
-
await next();
|
|
105
|
-
} catch (err) {
|
|
106
|
-
if (err instanceof HttpError) {
|
|
107
|
-
return c.json({
|
|
108
|
-
error: err.message,
|
|
109
|
-
status: err.statusCode,
|
|
110
|
-
...err.details ? { details: err.details } : {}
|
|
111
|
-
}, err.statusCode);
|
|
112
|
-
}
|
|
113
|
-
console.error("Unhandled error:", err);
|
|
114
|
-
return c.json({
|
|
115
|
-
error: "Internal Server Error",
|
|
116
|
-
status: 500
|
|
117
|
-
}, 500);
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// src/middleware/fileSystemRouting.ts
|
|
123
|
-
import { readFile } from "fs/promises";
|
|
124
|
-
import { resolve } from "path";
|
|
125
|
-
import { pathToFileURL } from "url";
|
|
126
|
-
async function readManifest(manifestPath, onMissing) {
|
|
127
|
-
try {
|
|
128
|
-
const raw = await readFile(manifestPath, "utf-8");
|
|
129
|
-
return JSON.parse(raw);
|
|
130
|
-
} catch (err) {
|
|
131
|
-
onMissing(err instanceof Error ? err : new Error(String(err)));
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
async function importHandler(handlerPath) {
|
|
136
|
-
try {
|
|
137
|
-
const url = handlerPath.startsWith("file://") ? handlerPath : pathToFileURL(handlerPath).href;
|
|
138
|
-
const mod = await import(url);
|
|
139
|
-
if (typeof mod.default !== "function") {
|
|
140
|
-
console.warn(
|
|
141
|
-
`[kozo:fsr] Skipping ${handlerPath}: no default export function`
|
|
142
|
-
);
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
return mod.default;
|
|
146
|
-
} catch (err) {
|
|
147
|
-
console.warn(
|
|
148
|
-
`[kozo:fsr] Failed to import handler ${handlerPath}:`,
|
|
149
|
-
err.message
|
|
150
|
-
);
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
async function applyFileSystemRouting(app, options = {}) {
|
|
155
|
-
const {
|
|
156
|
-
manifestPath = resolve(process.cwd(), "routes-manifest.json"),
|
|
157
|
-
verbose = false,
|
|
158
|
-
onMissingManifest = () => {
|
|
159
|
-
},
|
|
160
|
-
logger: logger2 = console.log
|
|
161
|
-
} = options;
|
|
162
|
-
const manifest = await readManifest(manifestPath, onMissingManifest);
|
|
163
|
-
if (!manifest) return;
|
|
164
|
-
const log = logger2;
|
|
165
|
-
if (verbose) {
|
|
166
|
-
log(
|
|
167
|
-
`
|
|
168
|
-
\u{1F4CB} [kozo:fsr] Loading ${manifest.routes.length} route(s) from manifest
|
|
169
|
-
`
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
for (const route of manifest.routes) {
|
|
173
|
-
const handler = await importHandler(route.handler);
|
|
174
|
-
if (!handler) continue;
|
|
175
|
-
app[route.method](route.path, handler);
|
|
176
|
-
if (verbose) {
|
|
177
|
-
log(
|
|
178
|
-
` ${route.method.toUpperCase().padEnd(6)} ${route.path} \u2192 ${route.handler}`
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (verbose) {
|
|
183
|
-
log("");
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
function createFileSystemRouting(options = {}) {
|
|
187
|
-
return (app) => applyFileSystemRouting(app, options);
|
|
188
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
BadRequestError,
|
|
3
|
+
ConflictError,
|
|
4
|
+
ForbiddenError,
|
|
5
|
+
HttpError,
|
|
6
|
+
InternalServerError,
|
|
7
|
+
NotFoundError,
|
|
8
|
+
UnauthorizedError,
|
|
9
|
+
applyFileSystemRouting,
|
|
10
|
+
clearRateLimitStore,
|
|
11
|
+
cors,
|
|
12
|
+
createFileSystemRouting,
|
|
13
|
+
errorHandler,
|
|
14
|
+
logger,
|
|
15
|
+
rateLimit
|
|
16
|
+
} from "../chunk-W44TTZNJ.js";
|
|
189
17
|
export {
|
|
190
18
|
BadRequestError as HttpBadRequestError,
|
|
191
19
|
ConflictError as HttpConflictError,
|
|
@@ -202,4 +30,3 @@ export {
|
|
|
202
30
|
logger,
|
|
203
31
|
rateLimit
|
|
204
32
|
};
|
|
205
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kozojs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "High-performance TypeScript framework with type-safe client generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -41,6 +41,13 @@
|
|
|
41
41
|
"require": "./lib/middleware/index.js"
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"dev": "tsup --watch",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"test:coverage": "vitest run --coverage"
|
|
50
|
+
},
|
|
44
51
|
"dependencies": {
|
|
45
52
|
"@hono/node-server": "^1.13.0",
|
|
46
53
|
"@sinclair/typebox": "^0.34.47",
|
|
@@ -49,7 +56,7 @@
|
|
|
49
56
|
"fast-json-stringify": "^6.0.0",
|
|
50
57
|
"glob": "^11.0.0",
|
|
51
58
|
"hono": "^4.6.0",
|
|
52
|
-
"uWebSockets.js": "github:uNetworking/uWebSockets.js#
|
|
59
|
+
"uWebSockets.js": "github:uNetworking/uWebSockets.js#6609a88ffa9a16ac5158046761356ce03250a0df",
|
|
53
60
|
"zod": "^3.23.0",
|
|
54
61
|
"zod-to-json-schema": "^3.23.0"
|
|
55
62
|
},
|
|
@@ -59,12 +66,5 @@
|
|
|
59
66
|
"tsup": "^8.3.0",
|
|
60
67
|
"typescript": "^5.6.0",
|
|
61
68
|
"vitest": "^2.1.0"
|
|
62
|
-
},
|
|
63
|
-
"scripts": {
|
|
64
|
-
"build": "tsup",
|
|
65
|
-
"dev": "tsup --watch",
|
|
66
|
-
"test": "vitest run",
|
|
67
|
-
"test:watch": "vitest",
|
|
68
|
-
"test:coverage": "vitest run --coverage"
|
|
69
69
|
}
|
|
70
|
-
}
|
|
70
|
+
}
|