gemi 0.3.5 → 0.3.7

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/dist/app/App.d.ts CHANGED
@@ -38,18 +38,20 @@ export declare class App {
38
38
  private prepare;
39
39
  printName(): void;
40
40
  getComponentTree(): ComponentTree;
41
- private flattenApiRoutes;
42
41
  private resolvePageData;
43
42
  handleRequest(req: Request): Promise<{
44
- kind: string;
45
- data?: undefined;
46
- headers?: undefined;
47
- } | {
48
43
  kind: string;
49
44
  data: {};
50
45
  headers: {
51
46
  "Set-Cookie": string;
52
47
  };
48
+ } | {
49
+ kind: string;
50
+ data?: undefined;
51
+ meta?: undefined;
52
+ headers?: undefined;
53
+ head?: undefined;
54
+ status?: undefined;
53
55
  } | {
54
56
  kind: string;
55
57
  data: {
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../app/App.ts"],"names":[],"mappings":";;;AAAA,OAAO,KAAK,EAGV,SAAS,EACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAsB,MAAM,oBAAoB,CAAC;AAKpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAS3C,OAAO,EAAE,aAAa,EAA2B,MAAM,OAAO,CAAC;AAE/D,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACrC;AAED,UAAU,SAAS;IACjB,UAAU,EAAE,UAAU,UAAU,CAAC;IACjC,SAAS,EAAE,UAAU,SAAS,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,EAAE,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,UAAU,CAAC,CAAC;IACzD,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,qBAAa,GAAG;IACd,OAAO,CAAC,cAAc,CAGf;IACP,OAAO,CAAC,aAAa,CAA2B;IAChD,OAAO,CAAC,aAAa,CAAgC;IAC9C,IAAI,SAAS;IACpB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,aAAa,CAAgB;IAC9B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,UAAU,CAAC,CAAM;IAC7D,UAAU,SAAK;IACtB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,IAAI,CAAgB;gBAEhB,MAAM,EAAE,SAAS;IAU7B,OAAO,CAAC,OAAO;IAkCR,SAAS;IAIT,gBAAgB;IAIvB,OAAO,CAAC,gBAAgB;YA6DV,eAAe;IAsDvB,aAAa,CAAC,GAAG,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA2J1B,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY;IA2GpD,OAAO,CAAC,sBAAsB,CAGtB;IACR,OAAO,CAAC,mBAAmB,CAEzB;IACF,OAAO,CAAC,oBAAoB,CAM1B;IAEF,SAAS;sBAdH,eAAe,WACV,MAAM,GAAG,MAAM;mBAES,eAAe;oBAI5C,eAAe,QACb,MAAM,UACJ,MAAM;MASd;CACH"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../app/App.ts"],"names":[],"mappings":";;;AAAA,OAAO,KAAK,EAGV,SAAS,EACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAsB,MAAM,oBAAoB,CAAC;AAKpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAU3C,OAAO,EAAE,aAAa,EAA2B,MAAM,OAAO,CAAC;AAK/D,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACrC;AAED,UAAU,SAAS;IACjB,UAAU,EAAE,UAAU,UAAU,CAAC;IACjC,SAAS,EAAE,UAAU,SAAS,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,EAAE,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,UAAU,CAAC,CAAC;IACzD,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,qBAAa,GAAG;IACd,OAAO,CAAC,cAAc,CAGf;IACP,OAAO,CAAC,aAAa,CASd;IACP,OAAO,CAAC,aAAa,CAAgC;IAC9C,IAAI,SAAS;IACpB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,aAAa,CAAgB;IAC9B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,UAAU,CAAC,CAAM;IAC7D,UAAU,SAAK;IACtB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,IAAI,CAAgB;gBAEhB,MAAM,EAAE,SAAS;IAU7B,OAAO,CAAC,OAAO;IAkCR,SAAS;IAIT,gBAAgB;YAIT,eAAe;IAsDvB,aAAa,CAAC,GAAG,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoL1B,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY;IA2GpD,OAAO,CAAC,sBAAsB,CAGtB;IACR,OAAO,CAAC,mBAAmB,CAEzB;IACF,OAAO,CAAC,oBAAoB,CAM1B;IAEF,SAAS;sBAdH,eAAe,WACV,MAAM,GAAG,MAAM;mBAES,eAAe;oBAI5C,eAAe,QACb,MAAM,UACJ,MAAM;MASd;CACH"}
@@ -0,0 +1,8 @@
1
+ import { Middleware } from "../http";
2
+ import { ApiRouteChildren, ApiRouteExec } from "../http/ApiRouter";
3
+ import { RouterMiddleware } from "../http/Router";
4
+ export declare function createFlatApiRoutes(routes: ApiRouteChildren): Record<string, Record<string, {
5
+ exec: ApiRouteExec;
6
+ middleware: (string | (new () => Middleware) | RouterMiddleware)[];
7
+ }>>;
8
+ //# sourceMappingURL=createFlatApiRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFlatApiRoutes.d.ts","sourceRoot":"","sources":["../../app/createFlatApiRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB;UAM9C,YAAY;gBACN,CAAC,MAAM,GAAG,CAAC,UAAU,UAAU,CAAC,GAAG,gBAAgB,CAAC,EAAE;IAoDzE"}
package/dist/app/index.js CHANGED
@@ -54,7 +54,7 @@ var require_validate = __commonJS((exports) => {
54
54
  var _interopRequireDefault = function(obj) {
55
55
  return obj && obj.__esModule ? obj : { default: obj };
56
56
  };
57
- var validate = function(uuid) {
57
+ var validate2 = function(uuid) {
58
58
  return typeof uuid === "string" && _regex.default.test(uuid);
59
59
  };
60
60
  Object.defineProperty(exports, "__esModule", {
@@ -62,7 +62,7 @@ var require_validate = __commonJS((exports) => {
62
62
  });
63
63
  exports.default = undefined;
64
64
  var _regex = _interopRequireDefault(require_regex());
65
- var _default = validate;
65
+ var _default = validate2;
66
66
  exports.default = _default;
67
67
  });
68
68
 
@@ -489,6 +489,378 @@ var require_dist = __commonJS((exports) => {
489
489
  var _parse = _interopRequireDefault(require_parse());
490
490
  });
491
491
 
492
+ // http/Controller.ts
493
+ class Controller {
494
+ app;
495
+ requests = {};
496
+ static kind = "controller";
497
+ constructor(app) {
498
+ this.app = app;
499
+ }
500
+ }
501
+ // http/Error.ts
502
+ class RequestBreakerError extends Error {
503
+ constructor() {
504
+ super(...arguments);
505
+ }
506
+ payload = { api: {}, view: {} };
507
+ }
508
+
509
+ // http/Router.ts
510
+ class AuthenticationError extends RequestBreakerError {
511
+ constructor() {
512
+ super("Authentication error");
513
+ this.name = "AuthenticationError";
514
+ }
515
+ payload = {
516
+ api: {
517
+ status: 401,
518
+ data: { error: "Authentication error" }
519
+ },
520
+ view: {
521
+ status: 302,
522
+ headers: {
523
+ "Cache-Control": "private, no-cache, no-store, max-age=0, must-revalidate",
524
+ Location: "/auth/sign-in"
525
+ }
526
+ }
527
+ };
528
+ }
529
+
530
+ class ValidationError extends RequestBreakerError {
531
+ errors = {};
532
+ constructor(errors) {
533
+ console.log("ValidationError", { errors });
534
+ super("Validation error");
535
+ this.name = "ValidationError";
536
+ this.errors = errors;
537
+ this.payload = {
538
+ api: {
539
+ status: 400,
540
+ data: {
541
+ error: {
542
+ kind: "validation_error",
543
+ messages: errors
544
+ }
545
+ },
546
+ headers: {
547
+ "Content-Type": "application/json"
548
+ }
549
+ },
550
+ view: {
551
+ status: 400
552
+ }
553
+ };
554
+ }
555
+ }
556
+
557
+ // http/HttpRequest.ts
558
+ var validate = function(ruleName) {
559
+ const [rule, param] = ruleName.split(":");
560
+ switch (rule) {
561
+ case "required":
562
+ return (value) => {
563
+ return value !== null && value !== undefined;
564
+ };
565
+ case "password":
566
+ return (value) => {
567
+ const passwordRegex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;
568
+ return passwordRegex.test(value);
569
+ };
570
+ case "number":
571
+ return (value) => {
572
+ if (typeof value !== "number")
573
+ return false;
574
+ return !isNaN(value);
575
+ };
576
+ case "min":
577
+ return (value) => {
578
+ return value.length >= parseInt(param);
579
+ };
580
+ case "max":
581
+ return (value) => {
582
+ return value.length <= parseInt(param);
583
+ };
584
+ case "email":
585
+ return (value) => {
586
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
587
+ return emailRegex.test(value);
588
+ };
589
+ default:
590
+ return () => true;
591
+ }
592
+ };
593
+
594
+ class Input extends Map {
595
+ constructor() {
596
+ super();
597
+ }
598
+ toJSON() {
599
+ return Object.fromEntries(this);
600
+ }
601
+ }
602
+
603
+ class HttpRequest {
604
+ rawRequest;
605
+ headers;
606
+ cookies;
607
+ schema = {};
608
+ constructor(req) {
609
+ this.rawRequest = req;
610
+ this.headers = req.headers;
611
+ const cookie = this.rawRequest.headers.get("Cookie");
612
+ const cookies = new Map;
613
+ if (cookie) {
614
+ const cookieArray = cookie.split(";");
615
+ for (const c of cookieArray) {
616
+ const [key, value] = c.split("=");
617
+ cookies.set(key.trim(), value.trim());
618
+ }
619
+ }
620
+ this.cookies = cookies;
621
+ }
622
+ async parseBody() {
623
+ const inputMap = new Input;
624
+ if (this.rawRequest.headers.get("Content-Type") === "application/json") {
625
+ const body = await this.rawRequest.json();
626
+ for (const [key, value] of Object.entries(body)) {
627
+ inputMap.set(key, value);
628
+ }
629
+ }
630
+ if (this.rawRequest.headers.get("Content-Type") === "application/x-www-form-urlencoded") {
631
+ const body = await this.rawRequest.formData();
632
+ for (const [key, value] of body) {
633
+ console.log(key, value);
634
+ inputMap.set(key, value);
635
+ }
636
+ }
637
+ if (this.rawRequest.headers.get("Content-Type").startsWith("multipart/form-data")) {
638
+ const body = await this.rawRequest.formData();
639
+ for (const [key, value] of body) {
640
+ if (inputMap.has(key)) {
641
+ const currentValue = inputMap.get(key);
642
+ if (Array.isArray(currentValue)) {
643
+ currentValue.push(value);
644
+ inputMap.set(key, currentValue);
645
+ } else {
646
+ inputMap.set(key, [currentValue, value]);
647
+ }
648
+ } else {
649
+ inputMap.set(key, value);
650
+ }
651
+ }
652
+ }
653
+ return inputMap;
654
+ }
655
+ validateInput(input) {
656
+ const errors = {};
657
+ for (const [key, rules] of Object.entries(this.schema)) {
658
+ for (const [rule, message] of Object.entries(rules)) {
659
+ const validator = validate(rule);
660
+ if (!validator(input.get(key))) {
661
+ if (!errors[key]) {
662
+ errors[key] = [];
663
+ }
664
+ errors[key].push(String(message));
665
+ }
666
+ }
667
+ }
668
+ if (Object.keys(errors).length > 0) {
669
+ throw new ValidationError(errors);
670
+ } else {
671
+ return input;
672
+ }
673
+ }
674
+ async input() {
675
+ return this.validateInput(await this.parseBody());
676
+ }
677
+ async safeInput() {
678
+ const input = await this.parseBody();
679
+ try {
680
+ this.validateInput(input);
681
+ return {
682
+ isValid: true,
683
+ errors: {},
684
+ input
685
+ };
686
+ } catch (err) {
687
+ if (!(err instanceof ValidationError)) {
688
+ throw err;
689
+ }
690
+ return {
691
+ isValid: false,
692
+ errors: err.errors,
693
+ input
694
+ };
695
+ }
696
+ }
697
+ }
698
+
699
+ // http/ApiRouter.ts
700
+ var isController = function(controller) {
701
+ return "kind" in controller && controller.kind === "controller";
702
+ };
703
+
704
+ class ApiRouter {
705
+ routes = {};
706
+ middlewares = [];
707
+ constructor() {
708
+ }
709
+ middleware(_req) {
710
+ }
711
+ handleRequest(controller, methodName) {
712
+ return (method) => {
713
+ const prepare = (middleware = []) => {
714
+ return {
715
+ middleware,
716
+ method,
717
+ exec: async (req, params, app) => {
718
+ let handler = (_req, params2) => Promise.resolve({});
719
+ let httpRequest = new HttpRequest(req);
720
+ if (isController(controller)) {
721
+ const controllerInstance = new controller(app);
722
+ const Req = controllerInstance.requests[methodName] ?? HttpRequest;
723
+ httpRequest = new Req(req);
724
+ handler = controllerInstance[methodName].bind(controllerInstance);
725
+ } else if (typeof controller === "function") {
726
+ handler = (req2) => controller(new HttpRequest(req2));
727
+ }
728
+ return await handler(httpRequest, params);
729
+ }
730
+ };
731
+ };
732
+ return {
733
+ prepare,
734
+ middleware: (middlware) => {
735
+ return {
736
+ prepare: () => prepare(middlware)
737
+ };
738
+ }
739
+ };
740
+ };
741
+ }
742
+ get(controller, methodName) {
743
+ const handler = this.handleRequest(controller, methodName);
744
+ return handler("get");
745
+ }
746
+ post(controller, methodName) {
747
+ const handler = this.handleRequest(controller, methodName);
748
+ return handler("post");
749
+ }
750
+ put(controller, methodName) {
751
+ const handler = this.handleRequest(controller, methodName);
752
+ return handler("put");
753
+ }
754
+ delete(controller, methodName) {
755
+ const handler = this.handleRequest(controller, methodName);
756
+ return handler("delete");
757
+ }
758
+ patch(controller, methodName) {
759
+ const handler = this.handleRequest(controller, methodName);
760
+ return handler("patch");
761
+ }
762
+ }
763
+ // http/ViewRouter.ts
764
+ class ViewRouter {
765
+ routes = {};
766
+ middlewares = [];
767
+ middleware(req) {
768
+ }
769
+ layout(viewPath, handler, children = {}) {
770
+ function prepare(middlewares = []) {
771
+ let _children = children;
772
+ if (handler && handler.constructor === Object) {
773
+ _children = handler;
774
+ }
775
+ return {
776
+ exec: async (req, params, app) => {
777
+ let _handler = () => Promise.resolve({
778
+ data: { [viewPath]: {} },
779
+ headers: {},
780
+ head: {}
781
+ });
782
+ if (typeof handler === "function") {
783
+ _handler = handler;
784
+ }
785
+ if (Array.isArray(handler)) {
786
+ const [controller, methodName] = handler;
787
+ const instance = new controller(app);
788
+ _handler = instance[methodName].bind(instance);
789
+ }
790
+ const data = await _handler(req, params);
791
+ return { [viewPath]: data };
792
+ },
793
+ children: _children,
794
+ viewPath,
795
+ middlewares,
796
+ kind: "layout"
797
+ };
798
+ }
799
+ return {
800
+ prepare,
801
+ middleware: (middlewares) => ({
802
+ prepare: () => prepare(middlewares)
803
+ })
804
+ };
805
+ }
806
+ view(viewPath, handler, children = {}) {
807
+ function prepare(middlewares = []) {
808
+ let _children = children;
809
+ if (handler && handler.constructor === Object) {
810
+ _children = handler;
811
+ }
812
+ return {
813
+ exec: async (req, params, app) => {
814
+ let _handler = () => Promise.resolve({
815
+ data: { [viewPath]: {} },
816
+ headers: {},
817
+ head: {}
818
+ });
819
+ if (typeof handler === "function") {
820
+ _handler = handler;
821
+ }
822
+ if (Array.isArray(handler)) {
823
+ const [controller, methodName] = handler;
824
+ const instance = new controller(app);
825
+ _handler = instance[methodName].bind(instance);
826
+ }
827
+ const data = await _handler(req, params);
828
+ return { [viewPath]: data };
829
+ },
830
+ children: _children,
831
+ viewPath,
832
+ middlewares,
833
+ kind: "view"
834
+ };
835
+ }
836
+ return {
837
+ prepare,
838
+ middleware: (middlewares) => ({
839
+ prepare: () => prepare(middlewares)
840
+ })
841
+ };
842
+ }
843
+ }
844
+ // http/Middleware.ts
845
+ class Middleware {
846
+ async run(_req, ctx) {
847
+ return {};
848
+ }
849
+ }
850
+ // http/getCookies.ts
851
+ function getCookies(req) {
852
+ const cookies = req.headers.get("cookie");
853
+ if (!cookies) {
854
+ return new Map;
855
+ }
856
+ const _cookies = new Map;
857
+ const cookieStrings = cookies.split(";");
858
+ for (const cookieString of cookieStrings) {
859
+ const [name, value] = cookieString.split("=");
860
+ _cookies.set(name.trim(), value);
861
+ }
862
+ return _cookies;
863
+ }
492
864
  // ../../node_modules/urlpattern-polyfill/dist/urlpattern.js
493
865
  var Re = function(e, t) {
494
866
  return (t ? /^[\x00-\xFF]*$/ : /^[\x00-\x7F]*$/).test(e);
@@ -1295,18 +1667,10 @@ var v4 = dist.default.v4;
1295
1667
  var v5 = dist.default.v5;
1296
1668
  var NIL = dist.default.NIL;
1297
1669
  var version = dist.default.version;
1298
- var validate = dist.default.validate;
1670
+ var validate2 = dist.default.validate;
1299
1671
  var stringify = dist.default.stringify;
1300
1672
  var parse = dist.default.parse;
1301
1673
 
1302
- // http/Error.ts
1303
- class RequestBreakerError extends Error {
1304
- constructor() {
1305
- super(...arguments);
1306
- }
1307
- payload = { api: {}, view: {} };
1308
- }
1309
-
1310
1674
  // http/requestContext.ts
1311
1675
  import {AsyncLocalStorage} from "async_hooks";
1312
1676
  var requestContext = new AsyncLocalStorage;
@@ -1417,10 +1781,66 @@ function createRouteManifest(routes) {
1417
1781
  return routeManifest;
1418
1782
  }
1419
1783
 
1784
+ // app/createFlatApiRoutes.ts
1785
+ function createFlatApiRoutes(routes) {
1786
+ const flatApiRoutes = {};
1787
+ for (const [rootPath, apiConfigOrApiRouter] of Object.entries(routes)) {
1788
+ if ("prepare" in apiConfigOrApiRouter) {
1789
+ if (!flatApiRoutes[rootPath]) {
1790
+ flatApiRoutes[rootPath] = {};
1791
+ }
1792
+ const { exec, method, middleware } = apiConfigOrApiRouter.prepare();
1793
+ flatApiRoutes[rootPath][method] = {
1794
+ exec,
1795
+ middleware: [...middleware]
1796
+ };
1797
+ } else if (Array.isArray(apiConfigOrApiRouter)) {
1798
+ for (const apiConfig of apiConfigOrApiRouter) {
1799
+ if (!flatApiRoutes[rootPath]) {
1800
+ flatApiRoutes[rootPath] = {};
1801
+ }
1802
+ const { exec, method, middleware } = apiConfig.prepare();
1803
+ flatApiRoutes[rootPath][method] = {
1804
+ exec,
1805
+ middleware
1806
+ };
1807
+ }
1808
+ } else {
1809
+ const router = new apiConfigOrApiRouter;
1810
+ const result = createFlatApiRoutes(router.routes);
1811
+ for (const [path, handlers] of Object.entries(result)) {
1812
+ const subPath = path === "/" ? "" : path;
1813
+ const _rootPath = rootPath === "/" ? "" : rootPath;
1814
+ const finalPath = `${_rootPath}${subPath}` === "" ? "/" : `${_rootPath}${subPath}`;
1815
+ if (!flatApiRoutes[finalPath]) {
1816
+ flatApiRoutes[finalPath] = {};
1817
+ }
1818
+ for (const [method, handler] of Object.entries(handlers)) {
1819
+ flatApiRoutes[finalPath][method] = {
1820
+ exec: handler.exec,
1821
+ middleware: [
1822
+ router.middleware,
1823
+ ...router.middlewares,
1824
+ ...handler.middleware
1825
+ ]
1826
+ };
1827
+ }
1828
+ }
1829
+ }
1830
+ }
1831
+ return flatApiRoutes;
1832
+ }
1833
+
1420
1834
  // app/App.ts
1421
1835
  import {renderToReadableStream} from "react-dom/server.browser";
1422
1836
  import {createElement, Fragment} from "react";
1423
1837
 
1838
+ // internal/isConstructor.ts
1839
+ function isConstructor(value) {
1840
+ return typeof value === "function" && value.prototype !== undefined;
1841
+ }
1842
+
1843
+ // app/App.ts
1424
1844
  class App {
1425
1845
  flatViewRoutes = {};
1426
1846
  flatApiRoutes = {};
@@ -1469,7 +1889,7 @@ class App {
1469
1889
  this.flatViewRoutes = createFlatViewRoutes(viewRouters);
1470
1890
  this.componentTree = createComponentTree(viewRouters);
1471
1891
  this.routeManifest = createRouteManifest(viewRouters);
1472
- this.flatApiRoutes = this.flattenApiRoutes(apiRouters);
1892
+ this.flatApiRoutes = createFlatApiRoutes(apiRouters);
1473
1893
  }
1474
1894
  printName() {
1475
1895
  console.log(this.name);
@@ -1477,58 +1897,6 @@ class App {
1477
1897
  getComponentTree() {
1478
1898
  return this.componentTree;
1479
1899
  }
1480
- flattenApiRoutes(routes) {
1481
- const flatApiRoutes = {};
1482
- for (const [rootPath, apiConfigOrApiRouter] of Object.entries(routes)) {
1483
- if ("exec" in apiConfigOrApiRouter) {
1484
- if (!flatApiRoutes[rootPath]) {
1485
- flatApiRoutes[rootPath] = {};
1486
- }
1487
- flatApiRoutes[rootPath][apiConfigOrApiRouter.method] = {
1488
- exec: apiConfigOrApiRouter.exec,
1489
- middleware: []
1490
- };
1491
- } else if (Array.isArray(apiConfigOrApiRouter)) {
1492
- for (const apiConfig of apiConfigOrApiRouter) {
1493
- if (!flatApiRoutes[rootPath]) {
1494
- flatApiRoutes[rootPath] = {};
1495
- }
1496
- flatApiRoutes[rootPath][apiConfig.method] = {
1497
- exec: apiConfig.exec,
1498
- middleware: []
1499
- };
1500
- }
1501
- } else {
1502
- const router = new apiConfigOrApiRouter(this);
1503
- const middlewares = router.middlewares.map((alias) => {
1504
- if (this.middlewareAliases?.[alias]) {
1505
- const middleware = new this.middlewareAliases[alias];
1506
- return middleware.run;
1507
- }
1508
- }).filter(Boolean);
1509
- const result = this.flattenApiRoutes(router.routes);
1510
- for (const [path, handlers] of Object.entries(result)) {
1511
- const subPath = path === "/" ? "" : path;
1512
- const _rootPath = rootPath === "/" ? "" : rootPath;
1513
- const finalPath = `${_rootPath}${subPath}` === "" ? "/" : `${_rootPath}${subPath}`;
1514
- if (!flatApiRoutes[finalPath]) {
1515
- flatApiRoutes[finalPath] = {};
1516
- }
1517
- for (const [method, handler] of Object.entries(handlers)) {
1518
- flatApiRoutes[finalPath][method] = {
1519
- exec: handler.exec,
1520
- middleware: [
1521
- router.middleware,
1522
- ...middlewares,
1523
- ...handler.middleware
1524
- ]
1525
- };
1526
- }
1527
- }
1528
- }
1529
- }
1530
- return flatApiRoutes;
1531
- }
1532
1900
  async resolvePageData(req) {
1533
1901
  const url = new URL(req.url);
1534
1902
  let handlers = [];
@@ -1560,7 +1928,7 @@ class App {
1560
1928
  }, (_req, _ctx) => Promise.resolve({}));
1561
1929
  const reqCtx = new Map;
1562
1930
  const data = await requestContext.run(reqCtx, async () => {
1563
- await reqWithMiddlewares(req, reqCtx);
1931
+ await reqWithMiddlewares(new HttpRequest(req), reqCtx);
1564
1932
  return await Promise.all(handlers.map((fn) => fn(req, params, this)));
1565
1933
  });
1566
1934
  return {
@@ -1578,9 +1946,28 @@ class App {
1578
1946
  const pattern = new me({ pathname: path });
1579
1947
  if (pattern.test({ pathname: apiPath })) {
1580
1948
  const params = pattern.exec({ pathname: apiPath })?.pathname.groups;
1949
+ if (!handler[req.method.toLowerCase()]) {
1950
+ return {
1951
+ kind: "api_404"
1952
+ };
1953
+ }
1581
1954
  const exec = handler[req.method.toLowerCase()].exec;
1582
1955
  const middlewares = handler[req.method.toLowerCase()].middleware;
1583
- const reqWithMiddlewares = middlewares.reduce((acc, middleware) => {
1956
+ const reqWithMiddlewares = middlewares.map((aliasOrTest) => {
1957
+ if (typeof aliasOrTest === "string") {
1958
+ const alias = aliasOrTest;
1959
+ if (this.middlewareAliases?.[alias]) {
1960
+ const middleware = new this.middlewareAliases[alias];
1961
+ return middleware.run;
1962
+ }
1963
+ } else {
1964
+ if (isConstructor(aliasOrTest)) {
1965
+ const middleware = new aliasOrTest;
1966
+ return middleware.run;
1967
+ }
1968
+ return aliasOrTest;
1969
+ }
1970
+ }).filter(Boolean).reduce((acc, middleware) => {
1584
1971
  return async (req2, ctx) => {
1585
1972
  return {
1586
1973
  ...await acc(req2, ctx),
@@ -1591,7 +1978,7 @@ class App {
1591
1978
  const reqCtx = new Map;
1592
1979
  return await requestContext.run(reqCtx, async () => {
1593
1980
  try {
1594
- await reqWithMiddlewares(req, reqCtx);
1981
+ await reqWithMiddlewares(new HttpRequest(req), reqCtx);
1595
1982
  } catch (err) {
1596
1983
  if (err instanceof RequestBreakerError) {
1597
1984
  return {
@@ -1731,7 +2118,7 @@ class App {
1731
2118
  });
1732
2119
  }
1733
2120
  if (result.kind === "view") {
1734
- const { data, headers, head, status } = result;
2121
+ const { data, headers, status } = result;
1735
2122
  const { styles, views, manifest, serverManifest, ...renderOptions } = renderParams;
1736
2123
  const viewImportMap = {};
1737
2124
  let appDir = null;
@@ -1,6 +1,7 @@
1
1
  import { type PropsWithChildren, type ComponentProps } from "react";
2
2
  interface MutationProps {
3
3
  url: string;
4
+ method?: "POST" | "GET" | "PUT" | "DELETE" | "PATCH";
4
5
  onSuccess?: (result: any) => void;
5
6
  }
6
7
  export declare const Mutation: (props: PropsWithChildren<MutationProps>) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"Mutation.d.ts","sourceRoot":"","sources":["../../client/Mutation.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAItB,KAAK,cAAc,EAGpB,MAAM,OAAO,CAAC;AAcf,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CACnC;AAED,eAAO,MAAM,QAAQ,UAAW,kBAAkB,aAAa,CAAC,4CAqD/D,CAAC;AAEF,wBAAgB,iBAAiB;;EAIhC;AAED,eAAO,MAAM,gBAAgB,UAAW;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,CAAC,KAAK,WAAW,CAAC;CACxD,4CAwBA,CAAC;AAEF,eAAO,MAAM,SAAS,UAAW,eAAe,KAAK,CAAC,4CAQrD,CAAC"}
1
+ {"version":3,"file":"Mutation.d.ts","sourceRoot":"","sources":["../../client/Mutation.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAItB,KAAK,cAAc,EAGpB,MAAM,OAAO,CAAC;AAcf,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CACnC;AAED,eAAO,MAAM,QAAQ,UAAW,kBAAkB,aAAa,CAAC,4CAsD/D,CAAC;AAEF,wBAAgB,iBAAiB;;EAIhC;AAED,eAAO,MAAM,gBAAgB,UAAW;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,CAAC,KAAK,WAAW,CAAC;CACxD,4CAwBA,CAAC;AAEF,eAAO,MAAM,SAAS,UAAW,eAAe,KAAK,CAAC,4CAQrD,CAAC"}
@@ -215,6 +215,7 @@ const MutationContext = createContext({
215
215
  result: null
216
216
  });
217
217
  const Mutation = (props) => {
218
+ const { method = "POST" } = props;
218
219
  const [isPending, setIsPending] = useState(false);
219
220
  const formRef = useRef(null);
220
221
  const [result, setResult] = useState(null);
@@ -227,7 +228,7 @@ const Mutation = (props) => {
227
228
  setResult(null);
228
229
  try {
229
230
  const res = await fetch(`/api${props.url}`, {
230
- method: "POST",
231
+ method,
231
232
  body: formData
232
233
  });
233
234
  const data = await res.json();
@@ -2,6 +2,7 @@ import { Controller } from "./Controller";
2
2
  import { type MiddlewareReturnType } from "./Router";
3
3
  import type { App } from "../app/App";
4
4
  import { HttpRequest } from "./HttpRequest";
5
+ import { Middleware } from "./Middleware";
5
6
  type ControllerMethods<T extends new (app: App) => Controller> = {
6
7
  [K in keyof InstanceType<T>]: InstanceType<T>[K] extends Function ? K : never;
7
8
  }[keyof InstanceType<T>];
@@ -9,22 +10,28 @@ type DataResponse = any;
9
10
  type ErrorResponse = {
10
11
  error: any;
11
12
  };
12
- type ApiHandler<T extends new (app: App) => Controller, U = {}> = {
13
+ type Prepare = (middleware?: (Middleware | string)[]) => {
14
+ middleware: string[];
13
15
  method: string;
14
16
  exec: (req: Request, params: Record<string, any>, app: App) => Promise<Partial<DataResponse> | ErrorResponse>;
15
17
  };
16
- export type ApiRouteExec = (req: Request, params: Record<string, string>) => Promise<DataResponse | ErrorResponse>;
18
+ type ApiHandler<T extends new (app: App) => Controller, U = {}> = {
19
+ prepare: Prepare;
20
+ middleware: (middleware: string[]) => {
21
+ prepare: Prepare;
22
+ };
23
+ };
24
+ export type ApiRouteExec = (req: Request, params: Record<string, string>, app: App) => Promise<DataResponse | ErrorResponse>;
17
25
  type ApiRouteConfig = {
18
- method: string;
19
- exec: ApiRouteExec;
26
+ prepare: Prepare;
20
27
  };
21
28
  type CallbackHandler<T> = (req: HttpRequest) => Promise<T> | T;
22
- export type ApiRouteChildren = Record<string, ApiRouteConfig | ApiRouteConfig[] | (new (app: App) => ApiRouter)>;
29
+ export type ApiRouteChildren = Record<string, ApiRouteConfig | ApiRouteConfig[] | (new () => ApiRouter)>;
23
30
  export declare class ApiRouter {
24
31
  routes: Record<string, any>;
25
32
  middlewares: string[];
26
33
  constructor();
27
- middleware(_req: Request): MiddlewareReturnType;
34
+ middleware(_req: HttpRequest): MiddlewareReturnType;
28
35
  private handleRequest;
29
36
  protected get<T>(controller: CallbackHandler<T>): ApiHandler<any>;
30
37
  protected get<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): ApiHandler<T>;
@@ -1 +1 @@
1
- {"version":3,"file":"ApiRouter.d.ts","sourceRoot":"","sources":["../../http/ApiRouter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ApiRouter.d.ts","sourceRoot":"","sources":["../../http/ApiRouter.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
+ import { HttpRequest } from "./HttpRequest";
1
2
  export declare class Middleware {
2
- run(_req: Request, ctx: Map<string, any>): Promise<{}>;
3
+ run(_req: HttpRequest, ctx: Map<string, any>): Promise<{}>;
3
4
  }
4
5
  //# sourceMappingURL=Middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Middleware.d.ts","sourceRoot":"","sources":["../../http/Middleware.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAU;IACf,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;CAG/C"}
1
+ {"version":3,"file":"Middleware.d.ts","sourceRoot":"","sources":["../../http/Middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,qBAAa,UAAU;IACf,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;CAGnD"}
@@ -1,10 +1,11 @@
1
1
  import { RequestBreakerError } from "./Error";
2
+ import { HttpRequest } from "./HttpRequest";
2
3
  type MiddlewareResult = Partial<{
3
4
  headers: Record<string, string>;
4
5
  cookies: Record<string, string>;
5
6
  }>;
6
7
  export type MiddlewareReturnType = void | Promise<MiddlewareResult> | MiddlewareResult;
7
- export type RouterMiddleware = (req: Request, ctx: any) => MiddlewareReturnType;
8
+ export type RouterMiddleware = (req: HttpRequest, ctx: any) => MiddlewareReturnType;
8
9
  export declare class AuthenticationError extends RequestBreakerError {
9
10
  constructor();
10
11
  payload: {
@@ -1 +1 @@
1
- {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../http/Router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,KAAK,gBAAgB,GAAG,OAAO,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAC5B,IAAI,GACJ,OAAO,CAAC,gBAAgB,CAAC,GACzB,gBAAgB,CAAC;AAErB,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,oBAAoB,CAAC;AAEhF,qBAAa,mBAAoB,SAAQ,mBAAmB;;IAM1D,OAAO;;;;;;;;;;;;;;MAaL;CACH;AAED,qBAAa,eAAgB,SAAQ,mBAAmB;IACtD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAM;gBAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CAuB7C"}
1
+ {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../http/Router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,KAAK,gBAAgB,GAAG,OAAO,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAC5B,IAAI,GACJ,OAAO,CAAC,gBAAgB,CAAC,GACzB,gBAAgB,CAAC;AAErB,MAAM,MAAM,gBAAgB,GAAG,CAC7B,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,GAAG,KACL,oBAAoB,CAAC;AAE1B,qBAAa,mBAAoB,SAAQ,mBAAmB;;IAM1D,OAAO;;;;;;;;;;;;;;MAaL;CACH;AAED,qBAAa,eAAgB,SAAQ,mBAAmB;IACtD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAM;gBAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CAuB7C"}
@@ -239,20 +239,31 @@ class ApiRouter {
239
239
  }
240
240
  handleRequest(controller, methodName) {
241
241
  return (method) => {
242
- return {
243
- method,
244
- exec: async (req, params, app) => {
245
- let handler = (_req, params2) => Promise.resolve({});
246
- let httpRequest = new HttpRequest(req);
247
- if (isController(controller)) {
248
- const controllerInstance = new controller(app);
249
- const Req = controllerInstance.requests[methodName] ?? HttpRequest;
250
- httpRequest = new Req(req);
251
- handler = controllerInstance[methodName].bind(controllerInstance);
252
- } else if (typeof controller === "function") {
253
- handler = (req2) => controller(new HttpRequest(req2));
242
+ const prepare = (middleware = []) => {
243
+ return {
244
+ middleware,
245
+ method,
246
+ exec: async (req, params, app) => {
247
+ let handler = (_req, params2) => Promise.resolve({});
248
+ let httpRequest = new HttpRequest(req);
249
+ if (isController(controller)) {
250
+ const controllerInstance = new controller(app);
251
+ const Req = controllerInstance.requests[methodName] ?? HttpRequest;
252
+ httpRequest = new Req(req);
253
+ handler = controllerInstance[methodName].bind(controllerInstance);
254
+ } else if (typeof controller === "function") {
255
+ handler = (req2) => controller(new HttpRequest(req2));
256
+ }
257
+ return await handler(httpRequest, params);
254
258
  }
255
- return await handler(httpRequest, params);
259
+ };
260
+ };
261
+ return {
262
+ prepare,
263
+ middleware: (middlware) => {
264
+ return {
265
+ prepare: () => prepare(middlware)
266
+ };
256
267
  }
257
268
  };
258
269
  };
@@ -0,0 +1,2 @@
1
+ export declare function isConstructor(value: any): boolean;
2
+ //# sourceMappingURL=isConstructor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isConstructor.d.ts","sourceRoot":"","sources":["../../internal/isConstructor.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,WAEvC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemi",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "devDependencies": {
5
5
  "@repo/eslint-config": "*",
6
6
  "@repo/typescript-config": "*",
@@ -41,7 +41,6 @@
41
41
  "test": "vitest"
42
42
  },
43
43
  "dependencies": {
44
- "@react-email/components": "^0.0.19",
45
44
  "commander": "^12.1.0",
46
45
  "history": "^5.3.0",
47
46
  "react-email": "^2.1.4",