@kozojs/core 0.2.7 → 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/index.js CHANGED
@@ -1,7 +1,23 @@
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";
17
+
1
18
  // src/app.ts
2
19
  import { Hono } from "hono/quick";
3
20
  import { serve } from "@hono/node-server";
4
- import { createServer } from "http";
5
21
 
6
22
  // src/client-generator.ts
7
23
  function generateMethodName(method, path) {
@@ -388,19 +404,19 @@ var ValidationFailedError = class extends KozoError {
388
404
  return new Response(JSON.stringify(body), INIT_400);
389
405
  }
390
406
  };
391
- var NotFoundError = class extends KozoError {
407
+ var NotFoundError2 = class extends KozoError {
392
408
  constructor(message = "Resource Not Found") {
393
409
  super(message, 404, "not-found");
394
410
  this.name = "NotFoundError";
395
411
  }
396
412
  };
397
- var UnauthorizedError = class extends KozoError {
413
+ var UnauthorizedError2 = class extends KozoError {
398
414
  constructor(message = "Unauthorized") {
399
415
  super(message, 401, "unauthorized");
400
416
  this.name = "UnauthorizedError";
401
417
  }
402
418
  };
403
- var ForbiddenError = class extends KozoError {
419
+ var ForbiddenError2 = class extends KozoError {
404
420
  constructor(message = "Forbidden") {
405
421
  super(message, 403, "forbidden");
406
422
  this.name = "ForbiddenError";
@@ -501,11 +517,11 @@ function uwsWrite404(uwsRes) {
501
517
  });
502
518
  }
503
519
  function getFreePort() {
504
- return new Promise((resolve2, reject) => {
520
+ return new Promise((resolve, reject) => {
505
521
  const srv = netCreateServer();
506
522
  srv.listen(0, "0.0.0.0", () => {
507
523
  const port = srv.address().port;
508
- srv.close((err) => err ? reject(err) : resolve2(port));
524
+ srv.close((err) => err ? reject(err) : resolve(port));
509
525
  });
510
526
  });
511
527
  }
@@ -522,7 +538,7 @@ async function createUwsServer(opts) {
522
538
  const { uws, routes } = opts;
523
539
  const port = opts.port === 0 ? await getFreePort() : opts.port;
524
540
  const emptyParams = Object.freeze({});
525
- return new Promise((resolve2, reject) => {
541
+ return new Promise((resolve, reject) => {
526
542
  const uwsApp = uws.App();
527
543
  for (const route of routes) {
528
544
  const fn = UWS_METHOD[route.method];
@@ -590,7 +606,7 @@ async function createUwsServer(opts) {
590
606
  return;
591
607
  }
592
608
  listenToken = token;
593
- resolve2({
609
+ resolve({
594
610
  port,
595
611
  server: {
596
612
  close() {
@@ -1252,569 +1268,6 @@ function parseNativeQuery(url) {
1252
1268
  });
1253
1269
  return result;
1254
1270
  }
1255
- function readNativeBody(req) {
1256
- return new Promise((resolve2, reject) => {
1257
- const chunks = [];
1258
- req.on("data", (chunk) => chunks.push(chunk));
1259
- req.on("end", () => {
1260
- try {
1261
- const str = Buffer.concat(chunks).toString("utf8");
1262
- resolve2(str ? JSON.parse(str) : {});
1263
- } catch {
1264
- resolve2({});
1265
- }
1266
- });
1267
- req.on("error", reject);
1268
- });
1269
- }
1270
- function compileNativeHandler(handler, schema, services, compiled) {
1271
- const { validateBody, validateQuery, validateParams, serialize } = compiled;
1272
- const hasServices = services != null && Object.keys(services).length > 0;
1273
- const hasQuery = !!validateQuery;
1274
- const hasParams = !!validateParams;
1275
- const hasBody = !!validateBody;
1276
- const hasSer = !!serialize;
1277
- const handlerIgnoresArgs = handler.length === 0;
1278
- if (!hasBody && !hasQuery && !hasParams && !hasServices) {
1279
- if (hasSer) {
1280
- const ser = serialize;
1281
- if (handlerIgnoresArgs) {
1282
- return function native_s1_bare_ser_noargs(req, res, _p) {
1283
- try {
1284
- const result = handler();
1285
- if (result != null && typeof result.then === "function") {
1286
- result.then(
1287
- (r) => fastWriteJson(res, ser(r)),
1288
- (err) => fastWriteError(err, res)
1289
- );
1290
- return;
1291
- }
1292
- fastWriteJson(res, ser(result));
1293
- } catch (err) {
1294
- fastWriteError(err, res);
1295
- }
1296
- };
1297
- }
1298
- return function native_s1_bare_ser(req, res, _p) {
1299
- try {
1300
- const result = handler({ req });
1301
- if (result != null && typeof result.then === "function") {
1302
- result.then(
1303
- (r) => fastWriteJson(res, ser(r)),
1304
- (err) => fastWriteError(err, res)
1305
- );
1306
- return;
1307
- }
1308
- fastWriteJson(res, ser(result));
1309
- } catch (err) {
1310
- fastWriteError(err, res);
1311
- }
1312
- };
1313
- }
1314
- if (handlerIgnoresArgs) {
1315
- return function native_s1_bare_noargs(req, res, _p) {
1316
- try {
1317
- const result = handler();
1318
- if (result != null && typeof result.then === "function") {
1319
- result.then(
1320
- (r) => fastWriteJson(res, toJsonBody(r)),
1321
- (err) => fastWriteError(err, res)
1322
- );
1323
- return;
1324
- }
1325
- fastWriteJson(res, toJsonBody(result));
1326
- } catch (err) {
1327
- fastWriteError(err, res);
1328
- }
1329
- };
1330
- }
1331
- return function native_s1_bare(req, res, _p) {
1332
- try {
1333
- const result = handler({ req });
1334
- if (result != null && typeof result.then === "function") {
1335
- result.then(
1336
- (r) => fastWriteJson(res, toJsonBody(r)),
1337
- (err) => fastWriteError(err, res)
1338
- );
1339
- return;
1340
- }
1341
- fastWriteJson(res, toJsonBody(result));
1342
- } catch (err) {
1343
- fastWriteError(err, res);
1344
- }
1345
- };
1346
- }
1347
- if (!hasBody && !hasQuery && !hasParams && hasServices) {
1348
- if (hasSer) {
1349
- const ser = serialize;
1350
- if (handlerIgnoresArgs) {
1351
- return function native_s1_svc_ser_noargs(req, res, _p) {
1352
- try {
1353
- const result = handler();
1354
- if (result != null && typeof result.then === "function") {
1355
- result.then(
1356
- (r) => fastWriteJson(res, ser(r)),
1357
- (err) => fastWriteError(err, res)
1358
- );
1359
- return;
1360
- }
1361
- fastWriteJson(res, ser(result));
1362
- } catch (err) {
1363
- fastWriteError(err, res);
1364
- }
1365
- };
1366
- }
1367
- return function native_s1_svc_ser(req, res, _p) {
1368
- try {
1369
- const result = handler({ req, services });
1370
- if (result != null && typeof result.then === "function") {
1371
- result.then(
1372
- (r) => fastWriteJson(res, ser(r)),
1373
- (err) => fastWriteError(err, res)
1374
- );
1375
- return;
1376
- }
1377
- fastWriteJson(res, ser(result));
1378
- } catch (err) {
1379
- fastWriteError(err, res);
1380
- }
1381
- };
1382
- }
1383
- if (handlerIgnoresArgs) {
1384
- return function native_s1_svc_noargs(req, res, _p) {
1385
- try {
1386
- const result = handler();
1387
- if (result != null && typeof result.then === "function") {
1388
- result.then(
1389
- (r) => fastWriteJson(res, toJsonBody(r)),
1390
- (err) => fastWriteError(err, res)
1391
- );
1392
- return;
1393
- }
1394
- fastWriteJson(res, toJsonBody(result));
1395
- } catch (err) {
1396
- fastWriteError(err, res);
1397
- }
1398
- };
1399
- }
1400
- return function native_s1_svc(req, res, _p) {
1401
- try {
1402
- const result = handler({ req, services });
1403
- if (result != null && typeof result.then === "function") {
1404
- result.then(
1405
- (r) => fastWriteJson(res, toJsonBody(r)),
1406
- (err) => fastWriteError(err, res)
1407
- );
1408
- return;
1409
- }
1410
- fastWriteJson(res, toJsonBody(result));
1411
- } catch (err) {
1412
- fastWriteError(err, res);
1413
- }
1414
- };
1415
- }
1416
- if (hasQuery && !hasParams && !hasBody) {
1417
- const vq = validateQuery;
1418
- if (hasSer) {
1419
- const ser = serialize;
1420
- if (!hasServices) {
1421
- return function native_s2a_q_ser(req, res, _p) {
1422
- try {
1423
- const query = parseNativeQuery(req.url ?? "/");
1424
- if (!vq(query)) {
1425
- fastWrite400("query", vq.errors, res);
1426
- return;
1427
- }
1428
- const result = handlerIgnoresArgs ? handler() : handler({ req, query });
1429
- if (result != null && typeof result.then === "function") {
1430
- result.then(
1431
- (r) => fastWriteJson(res, ser(r)),
1432
- (err) => fastWriteError(err, res)
1433
- );
1434
- return;
1435
- }
1436
- fastWriteJson(res, ser(result));
1437
- } catch (err) {
1438
- fastWriteError(err, res);
1439
- }
1440
- };
1441
- }
1442
- return function native_s2a_q_svc_ser(req, res, _p) {
1443
- try {
1444
- const query = parseNativeQuery(req.url ?? "/");
1445
- if (!vq(query)) {
1446
- fastWrite400("query", vq.errors, res);
1447
- return;
1448
- }
1449
- const result = handlerIgnoresArgs ? handler() : handler({ req, query, services });
1450
- if (result != null && typeof result.then === "function") {
1451
- result.then(
1452
- (r) => fastWriteJson(res, ser(r)),
1453
- (err) => fastWriteError(err, res)
1454
- );
1455
- return;
1456
- }
1457
- fastWriteJson(res, ser(result));
1458
- } catch (err) {
1459
- fastWriteError(err, res);
1460
- }
1461
- };
1462
- }
1463
- if (!hasServices) {
1464
- return function native_s2a_q(req, res, _p) {
1465
- try {
1466
- const query = parseNativeQuery(req.url ?? "/");
1467
- if (!vq(query)) {
1468
- fastWrite400("query", vq.errors, res);
1469
- return;
1470
- }
1471
- const result = handlerIgnoresArgs ? handler() : handler({ req, query });
1472
- if (result != null && typeof result.then === "function") {
1473
- result.then(
1474
- (r) => fastWriteJson(res, toJsonBody(r)),
1475
- (err) => fastWriteError(err, res)
1476
- );
1477
- return;
1478
- }
1479
- fastWriteJson(res, toJsonBody(result));
1480
- } catch (err) {
1481
- fastWriteError(err, res);
1482
- }
1483
- };
1484
- }
1485
- return function native_s2a_q_svc(req, res, _p) {
1486
- try {
1487
- const query = parseNativeQuery(req.url ?? "/");
1488
- if (!vq(query)) {
1489
- fastWrite400("query", vq.errors, res);
1490
- return;
1491
- }
1492
- const result = handlerIgnoresArgs ? handler() : handler({ req, query, services });
1493
- if (result != null && typeof result.then === "function") {
1494
- result.then(
1495
- (r) => fastWriteJson(res, toJsonBody(r)),
1496
- (err) => fastWriteError(err, res)
1497
- );
1498
- return;
1499
- }
1500
- fastWriteJson(res, toJsonBody(result));
1501
- } catch (err) {
1502
- fastWriteError(err, res);
1503
- }
1504
- };
1505
- }
1506
- if (hasParams && !hasQuery && !hasBody) {
1507
- const vp = validateParams;
1508
- if (hasSer) {
1509
- const ser = serialize;
1510
- if (!hasServices) {
1511
- return function native_s2b_p_ser(req, res, params) {
1512
- try {
1513
- if (!vp(params)) {
1514
- fastWrite400("params", vp.errors, res);
1515
- return;
1516
- }
1517
- const result = handlerIgnoresArgs ? handler() : handler({ req, params });
1518
- if (result != null && typeof result.then === "function") {
1519
- result.then(
1520
- (r) => fastWriteJson(res, ser(r)),
1521
- (err) => fastWriteError(err, res)
1522
- );
1523
- return;
1524
- }
1525
- fastWriteJson(res, ser(result));
1526
- } catch (err) {
1527
- fastWriteError(err, res);
1528
- }
1529
- };
1530
- }
1531
- return function native_s2b_p_svc_ser(req, res, params) {
1532
- try {
1533
- if (!vp(params)) {
1534
- fastWrite400("params", vp.errors, res);
1535
- return;
1536
- }
1537
- const result = handlerIgnoresArgs ? handler() : handler({ req, params, services });
1538
- if (result != null && typeof result.then === "function") {
1539
- result.then(
1540
- (r) => fastWriteJson(res, ser(r)),
1541
- (err) => fastWriteError(err, res)
1542
- );
1543
- return;
1544
- }
1545
- fastWriteJson(res, ser(result));
1546
- } catch (err) {
1547
- fastWriteError(err, res);
1548
- }
1549
- };
1550
- }
1551
- if (!hasServices) {
1552
- return function native_s2b_p(req, res, params) {
1553
- try {
1554
- if (!vp(params)) {
1555
- fastWrite400("params", vp.errors, res);
1556
- return;
1557
- }
1558
- const result = handlerIgnoresArgs ? handler() : handler({ req, params });
1559
- if (result != null && typeof result.then === "function") {
1560
- result.then(
1561
- (r) => fastWriteJson(res, toJsonBody(r)),
1562
- (err) => fastWriteError(err, res)
1563
- );
1564
- return;
1565
- }
1566
- fastWriteJson(res, toJsonBody(result));
1567
- } catch (err) {
1568
- fastWriteError(err, res);
1569
- }
1570
- };
1571
- }
1572
- return function native_s2b_p_svc(req, res, params) {
1573
- try {
1574
- if (!vp(params)) {
1575
- fastWrite400("params", vp.errors, res);
1576
- return;
1577
- }
1578
- const result = handlerIgnoresArgs ? handler() : handler({ req, params, services });
1579
- if (result != null && typeof result.then === "function") {
1580
- result.then(
1581
- (r) => fastWriteJson(res, toJsonBody(r)),
1582
- (err) => fastWriteError(err, res)
1583
- );
1584
- return;
1585
- }
1586
- fastWriteJson(res, toJsonBody(result));
1587
- } catch (err) {
1588
- fastWriteError(err, res);
1589
- }
1590
- };
1591
- }
1592
- if (hasQuery && hasParams && !hasBody) {
1593
- const vq = validateQuery;
1594
- const vp = validateParams;
1595
- if (hasSer) {
1596
- const ser = serialize;
1597
- if (!hasServices) {
1598
- return function native_s2c_qp_ser(req, res, params) {
1599
- try {
1600
- const query = parseNativeQuery(req.url ?? "/");
1601
- if (!vq(query)) {
1602
- fastWrite400("query", vq.errors, res);
1603
- return;
1604
- }
1605
- if (!vp(params)) {
1606
- fastWrite400("params", vp.errors, res);
1607
- return;
1608
- }
1609
- const result = handlerIgnoresArgs ? handler() : handler({ req, query, params });
1610
- if (result != null && typeof result.then === "function") {
1611
- result.then(
1612
- (r) => fastWriteJson(res, ser(r)),
1613
- (err) => fastWriteError(err, res)
1614
- );
1615
- return;
1616
- }
1617
- fastWriteJson(res, ser(result));
1618
- } catch (err) {
1619
- fastWriteError(err, res);
1620
- }
1621
- };
1622
- }
1623
- return function native_s2c_qp_svc_ser(req, res, params) {
1624
- try {
1625
- const query = parseNativeQuery(req.url ?? "/");
1626
- if (!vq(query)) {
1627
- fastWrite400("query", vq.errors, res);
1628
- return;
1629
- }
1630
- if (!vp(params)) {
1631
- fastWrite400("params", vp.errors, res);
1632
- return;
1633
- }
1634
- const result = handlerIgnoresArgs ? handler() : handler({ req, query, params, services });
1635
- if (result != null && typeof result.then === "function") {
1636
- result.then(
1637
- (r) => fastWriteJson(res, ser(r)),
1638
- (err) => fastWriteError(err, res)
1639
- );
1640
- return;
1641
- }
1642
- fastWriteJson(res, ser(result));
1643
- } catch (err) {
1644
- fastWriteError(err, res);
1645
- }
1646
- };
1647
- }
1648
- if (!hasServices) {
1649
- return function native_s2c_qp(req, res, params) {
1650
- try {
1651
- const query = parseNativeQuery(req.url ?? "/");
1652
- if (!vq(query)) {
1653
- fastWrite400("query", vq.errors, res);
1654
- return;
1655
- }
1656
- if (!vp(params)) {
1657
- fastWrite400("params", vp.errors, res);
1658
- return;
1659
- }
1660
- const result = handlerIgnoresArgs ? handler() : handler({ req, query, params });
1661
- if (result != null && typeof result.then === "function") {
1662
- result.then(
1663
- (r) => fastWriteJson(res, toJsonBody(r)),
1664
- (err) => fastWriteError(err, res)
1665
- );
1666
- return;
1667
- }
1668
- fastWriteJson(res, toJsonBody(result));
1669
- } catch (err) {
1670
- fastWriteError(err, res);
1671
- }
1672
- };
1673
- }
1674
- return function native_s2c_qp_svc(req, res, params) {
1675
- try {
1676
- const query = parseNativeQuery(req.url ?? "/");
1677
- if (!vq(query)) {
1678
- fastWrite400("query", vq.errors, res);
1679
- return;
1680
- }
1681
- if (!vp(params)) {
1682
- fastWrite400("params", vp.errors, res);
1683
- return;
1684
- }
1685
- const result = handlerIgnoresArgs ? handler() : handler({ req, query, params, services });
1686
- if (result != null && typeof result.then === "function") {
1687
- result.then(
1688
- (r) => fastWriteJson(res, toJsonBody(r)),
1689
- (err) => fastWriteError(err, res)
1690
- );
1691
- return;
1692
- }
1693
- fastWriteJson(res, toJsonBody(result));
1694
- } catch (err) {
1695
- fastWriteError(err, res);
1696
- }
1697
- };
1698
- }
1699
- if (hasBody && hasSer) {
1700
- const vb = validateBody;
1701
- const ser = serialize;
1702
- const vq = validateQuery;
1703
- const vp = validateParams;
1704
- if (!hasServices) {
1705
- return async function native_s3_body_ser(req, res, params) {
1706
- try {
1707
- const body = await readNativeBody(req);
1708
- if (!vb(body)) {
1709
- fastWrite400("body", vb.errors, res);
1710
- return;
1711
- }
1712
- let query;
1713
- if (vq) {
1714
- query = parseNativeQuery(req.url ?? "/");
1715
- if (!vq(query)) {
1716
- fastWrite400("query", vq.errors, res);
1717
- return;
1718
- }
1719
- }
1720
- if (vp && !vp(params)) {
1721
- fastWrite400("params", vp.errors, res);
1722
- return;
1723
- }
1724
- const result = await handler({ req, body, query, params });
1725
- fastWriteJson(res, ser(result));
1726
- } catch (err) {
1727
- fastWriteError(err, res);
1728
- }
1729
- };
1730
- }
1731
- return async function native_s3_body_ser_svc(req, res, params) {
1732
- try {
1733
- const body = await readNativeBody(req);
1734
- if (!vb(body)) {
1735
- fastWrite400("body", vb.errors, res);
1736
- return;
1737
- }
1738
- let query;
1739
- if (vq) {
1740
- query = parseNativeQuery(req.url ?? "/");
1741
- if (!vq(query)) {
1742
- fastWrite400("query", vq.errors, res);
1743
- return;
1744
- }
1745
- }
1746
- if (vp && !vp(params)) {
1747
- fastWrite400("params", vp.errors, res);
1748
- return;
1749
- }
1750
- const result = await handler({ req, body, query, params, services });
1751
- fastWriteJson(res, ser(result));
1752
- } catch (err) {
1753
- fastWriteError(err, res);
1754
- }
1755
- };
1756
- }
1757
- if (hasBody && !hasSer) {
1758
- const vb = validateBody;
1759
- const vq = validateQuery;
1760
- const vp = validateParams;
1761
- if (!hasServices) {
1762
- return async function native_s4_body_noser(req, res, params) {
1763
- try {
1764
- const body = await readNativeBody(req);
1765
- if (!vb(body)) {
1766
- fastWrite400("body", vb.errors, res);
1767
- return;
1768
- }
1769
- let query;
1770
- if (vq) {
1771
- query = parseNativeQuery(req.url ?? "/");
1772
- if (!vq(query)) {
1773
- fastWrite400("query", vq.errors, res);
1774
- return;
1775
- }
1776
- }
1777
- if (vp && !vp(params)) {
1778
- fastWrite400("params", vp.errors, res);
1779
- return;
1780
- }
1781
- const result = await handler({ req, body, query, params });
1782
- fastWriteJson(res, toJsonBody(result));
1783
- } catch (err) {
1784
- fastWriteError(err, res);
1785
- }
1786
- };
1787
- }
1788
- return async function native_s4_body_noser_svc(req, res, params) {
1789
- try {
1790
- const body = await readNativeBody(req);
1791
- if (!vb(body)) {
1792
- fastWrite400("body", vb.errors, res);
1793
- return;
1794
- }
1795
- let query;
1796
- if (vq) {
1797
- query = parseNativeQuery(req.url ?? "/");
1798
- if (!vq(query)) {
1799
- fastWrite400("query", vq.errors, res);
1800
- return;
1801
- }
1802
- }
1803
- if (vp && !vp(params)) {
1804
- fastWrite400("params", vp.errors, res);
1805
- return;
1806
- }
1807
- const result = await handler({ req, body, query, params, services });
1808
- fastWriteJson(res, toJsonBody(result));
1809
- } catch (err) {
1810
- fastWriteError(err, res);
1811
- }
1812
- };
1813
- }
1814
- return function native_fallback(req, res, _p) {
1815
- fastWriteError(new Error("Route scenario not implemented"), res);
1816
- };
1817
- }
1818
1271
  function compileUwsNativeHandler(handler, schema, services, compiled) {
1819
1272
  const { validateBody, validateQuery, validateParams, serialize } = compiled;
1820
1273
  const hasServices = services != null && Object.keys(services).length > 0;
@@ -2422,8 +1875,8 @@ function createInflightTracker() {
2422
1875
  function trackRequest(tracker) {
2423
1876
  tracker.count++;
2424
1877
  let resolvePromise;
2425
- const promise = new Promise((resolve2) => {
2426
- resolvePromise = resolve2;
1878
+ const promise = new Promise((resolve) => {
1879
+ resolvePromise = resolve;
2427
1880
  });
2428
1881
  tracker.requests.add(promise);
2429
1882
  return () => {
@@ -2518,10 +1971,10 @@ var ShutdownManager = class {
2518
1971
  });
2519
1972
  }
2520
1973
  const drainPromise = this.drainRequests();
2521
- const timeoutPromise = new Promise((resolve2) => {
1974
+ const timeoutPromise = new Promise((resolve) => {
2522
1975
  setTimeout(() => {
2523
1976
  onShutdownTimeout?.(this.tracker.count);
2524
- resolve2();
1977
+ resolve();
2525
1978
  }, timeoutMs);
2526
1979
  });
2527
1980
  await Promise.race([drainPromise, timeoutPromise]);
@@ -2701,192 +2154,14 @@ function routeScore(path) {
2701
2154
  return score;
2702
2155
  }
2703
2156
 
2704
- // src/wasm-router.ts
2705
- import { readFile } from "fs/promises";
2706
- import { fileURLToPath } from "url";
2707
- import { dirname, join as join2 } from "path";
2708
- var METHOD_INDEX = {
2709
- GET: 0,
2710
- POST: 1,
2711
- PUT: 2,
2712
- PATCH: 3,
2713
- DELETE: 4,
2714
- OPTIONS: 5,
2715
- HEAD: 6
2716
- };
2717
- function methodToIndex(m) {
2718
- switch (m.length) {
2719
- case 3:
2720
- return m.charCodeAt(0) === 71 ? 0 : 2;
2721
- case 4:
2722
- return m.charCodeAt(0) === 80 ? 1 : 6;
2723
- case 5:
2724
- return 3;
2725
- case 6:
2726
- return 4;
2727
- case 7:
2728
- return 5;
2729
- default:
2730
- return METHOD_INDEX[m] ?? -1;
2731
- }
2732
- }
2733
- var WasmRadixRouter = class {
2734
- exports = null;
2735
- urlView = null;
2736
- paramView = null;
2737
- patternView = null;
2738
- // v2: plain arrays indexed by route_id — O(1) with no hash overhead
2739
- handlers = [];
2740
- paramNames = [];
2741
- /** monotonic route counter */
2742
- nextRouteId = 0;
2743
- /** whether the WASM module loaded successfully */
2744
- ready = false;
2745
- // v3: pre-allocated match result — reused across calls to avoid allocation.
2746
- // Safe because dispatch() reads result synchronously and never stores it.
2747
- _emptyParams = Object.freeze({});
2748
- // ── Lifecycle ─────────────────────────────────────────────────────────
2749
- /**
2750
- * Attempt to load and instantiate the WASM module.
2751
- * Returns `true` on success, `false` if the .wasm file is missing or
2752
- * instantiation fails (caller should fall back to JS routing).
2753
- */
2754
- async init() {
2755
- try {
2756
- const thisDir = dirname(fileURLToPath(import.meta.url));
2757
- const wasmPath = join2(thisDir, "wasm", "radix.wasm");
2758
- const wasmBytes = await readFile(wasmPath);
2759
- const { instance } = await WebAssembly.instantiate(wasmBytes);
2760
- this.exports = instance.exports;
2761
- const mem = this.exports.memory;
2762
- const urlPtr = this.exports.get_url_buf_ptr();
2763
- const paramPtr = this.exports.get_param_buf_ptr();
2764
- const patPtr = this.exports.get_pattern_buf_ptr();
2765
- this.urlView = new Uint8Array(mem.buffer, urlPtr, 4096);
2766
- this.paramView = new DataView(mem.buffer, paramPtr, 32);
2767
- this.patternView = new Uint8Array(mem.buffer, patPtr, 2048);
2768
- this.exports.init();
2769
- this.ready = true;
2770
- return true;
2771
- } catch {
2772
- this.ready = false;
2773
- return false;
2774
- }
2775
- }
2776
- /** Is the WASM module loaded and operational? */
2777
- get isReady() {
2778
- return this.ready;
2779
- }
2780
- // ── Route registration (called at startup, not hot-path) ──────────────
2781
- /**
2782
- * Register a route in the WASM radix trie.
2783
- *
2784
- * @param method HTTP method (GET, POST, …)
2785
- * @param path Express-style pattern, e.g. `/api/users/:id` or `/blog/*`
2786
- * @param handler Compiled native handler (same type used by nativeListen)
2787
- * @returns The assigned route ID
2788
- */
2789
- addRoute(method, path, handler) {
2790
- if (!this.ready) throw new Error("WasmRadixRouter not initialized");
2791
- const routeId = this.nextRouteId++;
2792
- const methodIdx = METHOD_INDEX[method.toUpperCase()];
2793
- if (methodIdx === void 0) throw new Error(`Unsupported method: ${method}`);
2794
- const names = [];
2795
- const segments = path.split("/");
2796
- for (const seg of segments) {
2797
- if (seg.startsWith(":")) names.push(seg.slice(1));
2798
- else if (seg === "*") names.push("*");
2799
- }
2800
- this.paramNames[routeId] = names;
2801
- this.handlers[routeId] = handler;
2802
- const patLen = this.writeAscii(this.patternView, path);
2803
- this.exports.insert_route(methodIdx, patLen, routeId);
2804
- return routeId;
2805
- }
2806
- // ── Hot-path matching ─────────────────────────────────────────────────
2807
- /**
2808
- * Match a request path against the radix trie.
2809
- *
2810
- * ZERO-COPY: the path string is written byte-by-byte into WASM memory
2811
- * without allocating a Buffer or Uint8Array. Param values are read
2812
- * back as slices of the **original JS string** (the offsets produced by
2813
- * WASM coincide with JS character indices for ASCII paths).
2814
- *
2815
- * v3: Returns a pre-allocated result object that is reused across calls.
2816
- * For static routes (paramCount === 0), the params object is a frozen
2817
- * singleton — ZERO allocations per request on the hot path.
2818
- *
2819
- * @returns `null` on miss; otherwise the handler + extracted params.
2820
- */
2821
- match(method, path) {
2822
- const methodIdx = methodToIndex(method);
2823
- if (methodIdx === -1) return null;
2824
- const urlView = this.urlView;
2825
- const len = path.length;
2826
- for (let i = 0; i < len; i++) {
2827
- urlView[i] = path.charCodeAt(i);
2828
- }
2829
- const routeId = this.exports.match_url(methodIdx, len);
2830
- if (routeId === -1) return null;
2831
- const handler = this.handlers[routeId];
2832
- if (!handler) return null;
2833
- const paramCount = this.exports.get_param_count();
2834
- if (paramCount === 0) {
2835
- return { handler, params: this._emptyParams };
2836
- }
2837
- const names = this.paramNames[routeId];
2838
- const params = {};
2839
- const pv = this.paramView;
2840
- for (let i = 0; i < paramCount && i < names.length; i++) {
2841
- const byteOff = i * 4;
2842
- const offset = pv.getUint16(byteOff, true);
2843
- const plen = pv.getUint16(byteOff + 2, true);
2844
- params[names[i]] = path.slice(offset, offset + plen);
2845
- }
2846
- return { handler, params };
2847
- }
2848
- // ── Exposed internals for inline dispatch in app.ts ────────────────────
2849
- /**
2850
- * Expose raw WASM buffers + handler arrays for zero-overhead inline
2851
- * dispatch in app.ts. Avoids the match() → WasmMatchResult wrapper
2852
- * allocation on dynamic routes (~30-50 ns saved per request).
2853
- *
2854
- * SAFETY: single-threaded — no concurrent access.
2855
- */
2856
- getInternals() {
2857
- return {
2858
- urlView: this.urlView,
2859
- exports: this.exports,
2860
- handlers: this.handlers,
2861
- paramNames: this.paramNames,
2862
- paramView: this.paramView,
2863
- emptyParams: this._emptyParams
2864
- };
2865
- }
2866
- // ── Internals ─────────────────────────────────────────────────────────
2867
- /**
2868
- * Fast ASCII write — avoids TextEncoder allocation overhead (~50 ns).
2869
- * URL paths are always ASCII, so charCodeAt() is byte-identical.
2870
- */
2871
- writeAscii(view, str) {
2872
- const len = str.length;
2873
- for (let i = 0; i < len; i++) {
2874
- view[i] = str.charCodeAt(i);
2875
- }
2876
- return len;
2877
- }
2878
- };
2879
-
2880
2157
  // src/app.ts
2881
2158
  var Kozo = class {
2882
2159
  app;
2883
2160
  services;
2884
2161
  routes = [];
2885
- nativeRoutes = [];
2162
+ /** Routes registered directly with the uWS C++ radix router. */
2163
+ uwsRoutes = [];
2886
2164
  shutdownManager = new ShutdownManager();
2887
- wasmRouter = new WasmRadixRouter();
2888
- /** Maps each NativeRouteHandler to its zero-shim uWS counterpart */
2889
- uwsHandlerMap = /* @__PURE__ */ new Map();
2890
2165
  _routesDir;
2891
2166
  constructor(config = {}) {
2892
2167
  this.app = new Hono();
@@ -2925,8 +2200,15 @@ var Kozo = class {
2925
2200
  this.services,
2926
2201
  compiled
2927
2202
  );
2928
- this.routes.push({ method, path, schema });
2203
+ this.routes.push({ method, path, schema, meta: module.meta });
2929
2204
  this.app[method](path, optimizedHandler);
2205
+ const paramNames = [];
2206
+ path.replace(/:([^/]+)/g, (_, name) => {
2207
+ paramNames.push(name);
2208
+ return name;
2209
+ });
2210
+ const uwsHandler = compileUwsNativeHandler((ctx) => userHandler(ctx), schema, this.services, compiled);
2211
+ this.uwsRoutes.push({ method: method.toUpperCase(), path, paramNames, handler: uwsHandler });
2930
2212
  }
2931
2213
  return this;
2932
2214
  }
@@ -2964,147 +2246,37 @@ var Kozo = class {
2964
2246
  compiled
2965
2247
  );
2966
2248
  this.app[method](path, optimizedHandler);
2967
- const nativeHandler = compileNativeHandler(handler, schema, this.services, compiled);
2968
- const uwsHandler = compileUwsNativeHandler(handler, schema, this.services, compiled);
2969
- this.uwsHandlerMap.set(nativeHandler, uwsHandler);
2970
2249
  const paramNames = [];
2971
- const regexStr = path.replace(/:([^/]+)/g, (_, name) => {
2250
+ path.replace(/:([^/]+)/g, (_, name) => {
2972
2251
  paramNames.push(name);
2973
- return "([^/]+)";
2252
+ return name;
2974
2253
  });
2975
- if (paramNames.length === 0) {
2976
- this.nativeRoutes.push({ method: method.toUpperCase(), path, staticPath: path, handler: nativeHandler });
2977
- } else {
2978
- this.nativeRoutes.push({
2979
- method: method.toUpperCase(),
2980
- path,
2981
- regex: new RegExp(`^${regexStr}$`),
2982
- paramNames,
2983
- handler: nativeHandler
2984
- });
2985
- }
2254
+ const uwsHandler = compileUwsNativeHandler(handler, schema, this.services, compiled);
2255
+ this.uwsRoutes.push({ method: method.toUpperCase(), path, paramNames, handler: uwsHandler });
2986
2256
  return this;
2987
2257
  }
2988
2258
  /**
2989
- * Start a raw Node.js HTTP server (no @hono/node-server adapter).
2990
- * Writes directly to ServerResponse — eliminates Web API Request/Response
2991
- * allocation and adapter overhead for maximum throughput.
2992
- *
2993
- * When the Zig WASM radix trie is available (`src/wasm/radix.wasm`),
2994
- * ALL route matching (static + dynamic) runs through the zero-copy
2995
- * trie — one call into WASM per request.
2259
+ * Start a uWebSockets.js HTTP server.
2996
2260
  *
2997
- * When the .wasm file is absent (Edge deploy, CI without Zig, etc.)
2998
- * routing falls back transparently to the JS Map + RegExp approach.
2261
+ * All routes are registered directly with uWS's C++ radix trie router
2262
+ * zero JS routing overhead per request. The C++ HTTP parser (µHttpParser)
2263
+ * eliminates all IncomingMessage/ServerResponse allocations.
2999
2264
  *
3000
- * Returns { port, server } so the caller can close the server when done.
2265
+ * Throws if uWebSockets.js is not installed.
2266
+ * Returns { port, server } so callers can close the server when done.
3001
2267
  */
3002
2268
  async nativeListen(port = 3e3) {
3003
- const wasmOk = await this.wasmRouter.init();
3004
- if (wasmOk) {
3005
- for (const entry of this.nativeRoutes) {
3006
- const path = entry.staticPath ?? entry.regex?.source.replace(/^\^/, "").replace(/\$$/, "").replace(/\(\[\\^\/\]\+\)/g, () => `:${entry.paramNames?.shift() ?? "p"}`) ?? "/";
3007
- this.wasmRouter.addRoute(entry.method, entry.staticPath ?? path, entry.handler);
3008
- }
3009
- console.log("\u26A1 WASM radix router active (zero-copy Zig trie)");
3010
- } else {
3011
- console.log("\u2139\uFE0F WASM radix router unavailable \u2014 using JS fallback");
3012
- }
3013
- const staticMap = /* @__PURE__ */ new Map();
3014
- const dynamicRoutes = [];
3015
- for (const entry of this.nativeRoutes) {
3016
- if (entry.staticPath !== void 0) {
3017
- staticMap.set(`${entry.method}:${entry.staticPath}`, entry.handler);
3018
- } else {
3019
- dynamicRoutes.push({
3020
- method: entry.method,
3021
- regex: entry.regex,
3022
- paramNames: entry.paramNames,
3023
- handler: entry.handler
3024
- });
3025
- }
3026
- }
3027
- const wasm = wasmOk ? this.wasmRouter : null;
3028
- const emptyParams = Object.freeze({});
3029
- const matchRoute = (method, path) => {
3030
- if (wasm) {
3031
- const r = wasm.match(method, path);
3032
- if (r) return { handler: r.handler, params: r.params };
3033
- return null;
3034
- }
3035
- const staticHandler = staticMap.get(`${method}:${path}`);
3036
- if (staticHandler) return { handler: staticHandler, params: emptyParams };
3037
- for (const route of dynamicRoutes) {
3038
- if (route.method !== method) continue;
3039
- const m = route.regex.exec(path);
3040
- if (!m) continue;
3041
- const params = {};
3042
- for (let i = 0; i < route.paramNames.length; i++) {
3043
- params[route.paramNames[i]] = m[i + 1];
3044
- }
3045
- return { handler: route.handler, params };
3046
- }
3047
- return null;
3048
- };
3049
2269
  const uwsBindings = await tryLoadUws();
3050
- if (uwsBindings) {
3051
- console.log("\u{1F680} uWebSockets.js transport active (native per-route C++ matching)");
3052
- const uwsMap = this.uwsHandlerMap;
3053
- const uwsRoutes = [];
3054
- for (const entry of this.nativeRoutes) {
3055
- const uwsH = uwsMap.get(entry.handler);
3056
- if (!uwsH) continue;
3057
- uwsRoutes.push({
3058
- method: entry.method,
3059
- path: entry.path,
3060
- paramNames: entry.paramNames ?? [],
3061
- handler: uwsH
3062
- });
3063
- }
3064
- return createUwsServer({
3065
- uws: uwsBindings,
3066
- routes: uwsRoutes,
3067
- port
3068
- });
2270
+ if (!uwsBindings) {
2271
+ throw new Error(
2272
+ "[Kozo] uWebSockets.js is required but not installed.\nRun: pnpm add uWebSockets.js"
2273
+ );
3069
2274
  }
3070
- const dispatch = (req, res) => {
3071
- const method = req.method;
3072
- const rawUrl = req.url;
3073
- const qIdx = rawUrl.indexOf("?");
3074
- const path = qIdx === -1 ? rawUrl : rawUrl.slice(0, qIdx);
3075
- if (wasm) {
3076
- const result = wasm.match(method, path);
3077
- if (result) {
3078
- result.handler(req, res, result.params);
3079
- return;
3080
- }
3081
- fastWrite404(res);
3082
- return;
3083
- }
3084
- const staticHandler = staticMap.get(`${method}:${path}`);
3085
- if (staticHandler) {
3086
- staticHandler(req, res, emptyParams);
3087
- return;
3088
- }
3089
- for (const route of dynamicRoutes) {
3090
- if (route.method !== method) continue;
3091
- const match = route.regex.exec(path);
3092
- if (!match) continue;
3093
- const params = {};
3094
- for (let i = 0; i < route.paramNames.length; i++) {
3095
- params[route.paramNames[i]] = match[i + 1];
3096
- }
3097
- route.handler(req, res, params);
3098
- return;
3099
- }
3100
- fastWrite404(res);
3101
- };
3102
- return new Promise((resolve2) => {
3103
- const server = createServer(dispatch);
3104
- server.listen(port, () => {
3105
- const addr = server.address();
3106
- resolve2({ port: addr.port, server });
3107
- });
2275
+ console.log("\u{1F680} uWebSockets.js transport active (C++ HTTP parser + native radix router)");
2276
+ return createUwsServer({
2277
+ uws: uwsBindings,
2278
+ routes: this.uwsRoutes,
2279
+ port
3108
2280
  });
3109
2281
  }
3110
2282
  async listen(port) {
@@ -3543,212 +2715,23 @@ function generateSwaggerHtml(specUrl, title = "API Documentation") {
3543
2715
  function createOpenAPIGenerator(config) {
3544
2716
  return new OpenAPIGenerator(config);
3545
2717
  }
3546
-
3547
- // src/middleware/logger.ts
3548
- function logger(options = {}) {
3549
- const { prefix = "\u{1F310}", colorize = true } = options;
3550
- return async (c, next) => {
3551
- const start = Date.now();
3552
- const method = c.req.method;
3553
- const path = new URL(c.req.url).pathname;
3554
- await next();
3555
- const duration = Date.now() - start;
3556
- const status = c.res.status;
3557
- const statusColor = status >= 500 ? "\u{1F534}" : status >= 400 ? "\u{1F7E1}" : "\u{1F7E2}";
3558
- const log = `${prefix} ${method.padEnd(6)} ${path} ${statusColor} ${status} ${duration}ms`;
3559
- console.log(log);
3560
- };
3561
- }
3562
-
3563
- // src/middleware/cors.ts
3564
- import { cors as honoCors } from "hono/cors";
3565
- function cors(options = {}) {
3566
- return honoCors({
3567
- origin: options.origin || "*",
3568
- allowMethods: options.allowMethods || ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
3569
- allowHeaders: options.allowHeaders || ["Content-Type", "Authorization"],
3570
- exposeHeaders: options.exposeHeaders || [],
3571
- maxAge: options.maxAge || 86400,
3572
- credentials: options.credentials || false
3573
- });
3574
- }
3575
-
3576
- // src/middleware/rate-limit.ts
3577
- var store = /* @__PURE__ */ new Map();
3578
- function rateLimit(options) {
3579
- const {
3580
- max = 100,
3581
- window = 60,
3582
- keyGenerator = (c) => c.req.header("x-forwarded-for") ?? c.req.header("x-real-ip") ?? "anonymous",
3583
- message = "Too many requests"
3584
- } = options;
3585
- return async (c, next) => {
3586
- const key = keyGenerator(c);
3587
- const now = Date.now();
3588
- const windowMs = window * 1e3;
3589
- let record = store.get(key);
3590
- if (!record || now > record.resetAt) {
3591
- record = { count: 0, resetAt: now + windowMs };
3592
- }
3593
- record.count++;
3594
- store.set(key, record);
3595
- c.header("X-RateLimit-Limit", String(max));
3596
- c.header("X-RateLimit-Remaining", String(Math.max(0, max - record.count)));
3597
- c.header("X-RateLimit-Reset", String(Math.ceil(record.resetAt / 1e3)));
3598
- if (record.count > max) {
3599
- return c.json({ error: message }, 429);
3600
- }
3601
- await next();
3602
- };
3603
- }
3604
- function clearRateLimitStore() {
3605
- store.clear();
3606
- }
3607
-
3608
- // src/middleware/error-handler.ts
3609
- var HttpError = class extends Error {
3610
- constructor(statusCode, message, details) {
3611
- super(message);
3612
- this.statusCode = statusCode;
3613
- this.details = details;
3614
- this.name = "HttpError";
3615
- }
3616
- };
3617
- var BadRequestError = class extends HttpError {
3618
- constructor(message = "Bad Request", details) {
3619
- super(400, message, details);
3620
- }
3621
- };
3622
- var UnauthorizedError2 = class extends HttpError {
3623
- constructor(message = "Unauthorized") {
3624
- super(401, message);
3625
- }
3626
- };
3627
- var ForbiddenError2 = class extends HttpError {
3628
- constructor(message = "Forbidden") {
3629
- super(403, message);
3630
- }
3631
- };
3632
- var NotFoundError2 = class extends HttpError {
3633
- constructor(message = "Not Found") {
3634
- super(404, message);
3635
- }
3636
- };
3637
- var ConflictError = class extends HttpError {
3638
- constructor(message = "Conflict", details) {
3639
- super(409, message, details);
3640
- }
3641
- };
3642
- var InternalServerError = class extends HttpError {
3643
- constructor(message = "Internal Server Error") {
3644
- super(500, message);
3645
- }
3646
- };
3647
- function errorHandler() {
3648
- return async (c, next) => {
3649
- try {
3650
- await next();
3651
- } catch (err) {
3652
- if (err instanceof HttpError) {
3653
- return c.json({
3654
- error: err.message,
3655
- status: err.statusCode,
3656
- ...err.details ? { details: err.details } : {}
3657
- }, err.statusCode);
3658
- }
3659
- console.error("Unhandled error:", err);
3660
- return c.json({
3661
- error: "Internal Server Error",
3662
- status: 500
3663
- }, 500);
3664
- }
3665
- };
3666
- }
3667
-
3668
- // src/middleware/fileSystemRouting.ts
3669
- import { readFile as readFile2 } from "fs/promises";
3670
- import { resolve } from "path";
3671
- import { pathToFileURL as pathToFileURL2 } from "url";
3672
- async function readManifest(manifestPath, onMissing) {
3673
- try {
3674
- const raw = await readFile2(manifestPath, "utf-8");
3675
- return JSON.parse(raw);
3676
- } catch (err) {
3677
- onMissing(err instanceof Error ? err : new Error(String(err)));
3678
- return null;
3679
- }
3680
- }
3681
- async function importHandler(handlerPath) {
3682
- try {
3683
- const url = handlerPath.startsWith("file://") ? handlerPath : pathToFileURL2(handlerPath).href;
3684
- const mod = await import(url);
3685
- if (typeof mod.default !== "function") {
3686
- console.warn(
3687
- `[kozo:fsr] Skipping ${handlerPath}: no default export function`
3688
- );
3689
- return null;
3690
- }
3691
- return mod.default;
3692
- } catch (err) {
3693
- console.warn(
3694
- `[kozo:fsr] Failed to import handler ${handlerPath}:`,
3695
- err.message
3696
- );
3697
- return null;
3698
- }
3699
- }
3700
- async function applyFileSystemRouting(app, options = {}) {
3701
- const {
3702
- manifestPath = resolve(process.cwd(), "routes-manifest.json"),
3703
- verbose = false,
3704
- onMissingManifest = () => {
3705
- },
3706
- logger: logger2 = console.log
3707
- } = options;
3708
- const manifest = await readManifest(manifestPath, onMissingManifest);
3709
- if (!manifest) return;
3710
- const log = logger2;
3711
- if (verbose) {
3712
- log(
3713
- `
3714
- \u{1F4CB} [kozo:fsr] Loading ${manifest.routes.length} route(s) from manifest
3715
- `
3716
- );
3717
- }
3718
- for (const route of manifest.routes) {
3719
- const handler = await importHandler(route.handler);
3720
- if (!handler) continue;
3721
- app[route.method](route.path, handler);
3722
- if (verbose) {
3723
- log(
3724
- ` ${route.method.toUpperCase().padEnd(6)} ${route.path} \u2192 ${route.handler}`
3725
- );
3726
- }
3727
- }
3728
- if (verbose) {
3729
- log("");
3730
- }
3731
- }
3732
- function createFileSystemRouting(options = {}) {
3733
- return (app) => applyFileSystemRouting(app, options);
3734
- }
3735
2718
  export {
3736
2719
  ERROR_RESPONSES,
3737
- ForbiddenError,
2720
+ ForbiddenError2 as ForbiddenError,
3738
2721
  BadRequestError as HttpBadRequestError,
3739
2722
  ConflictError as HttpConflictError,
3740
2723
  HttpError,
3741
- ForbiddenError2 as HttpForbiddenError,
2724
+ ForbiddenError as HttpForbiddenError,
3742
2725
  InternalServerError as HttpInternalServerError,
3743
- NotFoundError2 as HttpNotFoundError,
3744
- UnauthorizedError2 as HttpUnauthorizedError,
2726
+ NotFoundError as HttpNotFoundError,
2727
+ UnauthorizedError as HttpUnauthorizedError,
3745
2728
  Kozo,
3746
2729
  KozoError,
3747
- NotFoundError,
2730
+ NotFoundError2 as NotFoundError,
3748
2731
  OpenAPIGenerator,
3749
2732
  SchemaCompiler,
3750
2733
  ShutdownManager,
3751
- UnauthorizedError,
2734
+ UnauthorizedError2 as UnauthorizedError,
3752
2735
  ValidationFailedError,
3753
2736
  applyFileSystemRouting,
3754
2737
  buildNativeContext,
@@ -3784,4 +2767,3 @@ export {
3784
2767
  validationErrorResponse,
3785
2768
  z
3786
2769
  };
3787
- //# sourceMappingURL=index.js.map