gemi 0.2.2 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/app/App.d.ts CHANGED
@@ -15,8 +15,8 @@ interface RenderParams {
15
15
  serverManifest: Record<string, any>;
16
16
  }
17
17
  interface AppParams {
18
- viewRouter: new (app: App) => ViewRouter;
19
- apiRouter: new (app: App) => ApiRouter;
18
+ viewRouter: new () => ViewRouter;
19
+ apiRouter: new () => ApiRouter;
20
20
  plugins?: (new () => Plugin)[];
21
21
  middlewareAliases?: Record<string, new () => Middleware>;
22
22
  root: ComponentType;
@@ -44,16 +44,16 @@ export declare class App {
44
44
  kind: string;
45
45
  data?: undefined;
46
46
  headers?: undefined;
47
- status?: undefined;
48
47
  } | {
49
48
  kind: string;
50
- data: any;
51
- headers: any;
52
- status: any;
49
+ data: {};
50
+ headers: {
51
+ "Set-Cookie": string;
52
+ };
53
53
  } | {
54
54
  kind: string;
55
55
  data: {
56
- [x: string]: Record<string, any>;
56
+ [x: string]: any;
57
57
  pageData?: undefined;
58
58
  auth?: undefined;
59
59
  routeManifest?: undefined;
@@ -61,14 +61,14 @@ export declare class App {
61
61
  componentTree?: undefined;
62
62
  };
63
63
  meta: any[];
64
- headers: Record<string, any>;
64
+ headers: {};
65
65
  head?: undefined;
66
66
  status?: undefined;
67
67
  } | {
68
68
  kind: string;
69
69
  data: {
70
70
  pageData: {
71
- [x: string]: Record<string, any>;
71
+ [x: string]: any;
72
72
  };
73
73
  auth: {
74
74
  user: any;
@@ -80,11 +80,9 @@ export declare class App {
80
80
  currentPath: string;
81
81
  is404: boolean;
82
82
  };
83
- componentTree: (string[] | {
84
- [x: string]: ComponentTree;
85
- })[];
83
+ componentTree: ([string, [string, [string, [string, [string, [string, [string, [string, [string, [string, [string, any[]][]][]][]][]][]][]][]][]][]][]] | (string | any[])[])[];
86
84
  };
87
- head: Record<string, Record<string, any>[]>;
85
+ head: {};
88
86
  headers: {
89
87
  "Content-Type": string;
90
88
  "Cache-Control": string;
@@ -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;AAM3C,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;AAoCD,UAAU,SAAS;IACjB,UAAU,EAAE,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,CAAC;IACzC,SAAS,EAAE,KAAK,GAAG,EAAE,GAAG,KAAK,SAAS,CAAC;IACvC,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,CAA8B;IAC/C,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,IAAI,CAAgB;gBAEhB,MAAM,EAAE,SAAS;IAU7B,OAAO,CAAC,OAAO;IAqCR,SAAS;IAIT,gBAAgB;IAIvB,OAAO,CAAC,gBAAgB;YA6DV,eAAe;IAyDvB,aAAa,CAAC,GAAG,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAuJ1B,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY;IAyGpD,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;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"}
@@ -0,0 +1,4 @@
1
+ import { ComponentTree } from "../client/types";
2
+ import { ViewChildren } from "../http/ViewRouter";
3
+ export declare function createComponentTree(routes: ViewChildren): ComponentTree;
4
+ //# sourceMappingURL=createComponentTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createComponentTree.d.ts","sourceRoot":"","sources":["../../app/createComponentTree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,aAAa,CAoBvE"}
@@ -0,0 +1,6 @@
1
+ import { ViewChildren, ViewRouteExec } from "../http/ViewRouter";
2
+ export declare function createFlatViewRoutes(routes: ViewChildren): Record<string, {
3
+ exec: ViewRouteExec[];
4
+ middleware: (string | any)[];
5
+ }>;
6
+ //# sourceMappingURL=createFlatViewRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFlatViewRoutes.d.ts","sourceRoot":"","sources":["../../app/createFlatViewRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEjE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY;UAG7C,aAAa,EAAE;gBAAc,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE;GA8CxD"}
@@ -0,0 +1,3 @@
1
+ import { ViewChildren } from "../http/ViewRouter";
2
+ export declare function createRouteManifest(routes: ViewChildren): Record<string, string[]>;
3
+ //# sourceMappingURL=createRouteManifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createRouteManifest.d.ts","sourceRoot":"","sources":["../../app/createRouteManifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,4BAiCvD"}
package/dist/app/index.js CHANGED
@@ -1311,111 +1311,115 @@ class RequestBreakerError extends Error {
1311
1311
  import {AsyncLocalStorage} from "async_hooks";
1312
1312
  var requestContext = new AsyncLocalStorage;
1313
1313
 
1314
- // app/flattenViewRoutes.ts
1315
- function flattenViewRoutes(routes, app) {
1316
- const flatRoutes = {};
1317
- const routeManifest = {};
1314
+ // client/helpers/flattenComponentTree.ts
1315
+ function flattenComponentTree(componentTree) {
1316
+ let out = [];
1317
+ for (const [root, branches] of componentTree) {
1318
+ out.push(root, ...flattenComponentTree(branches).flat());
1319
+ }
1320
+ return Array.from(new Set(out));
1321
+ }
1322
+
1323
+ // app/createComponentTree.ts
1324
+ function createComponentTree(routes) {
1318
1325
  const componentTree = [];
1319
- for (const [rootPath, viewConfigOrViewRouter] of Object.entries(routes)) {
1320
- let children;
1321
- let rootHandler = async () => ({});
1322
- let rootMiddleware = [];
1323
- let layoutViewPath = null;
1324
- if ("prepare" in viewConfigOrViewRouter) {
1325
- const result2 = viewConfigOrViewRouter.prepare();
1326
- children = result2.children;
1327
- rootHandler = result2.exec;
1328
- flatRoutes[rootPath] = {
1329
- exec: [rootHandler],
1330
- middleware: result2.middlewares
1331
- };
1332
- if (Object.keys(children).length > 0) {
1333
- layoutViewPath = result2.viewPath;
1326
+ for (const [_2, routeHandler] of Object.entries(routes)) {
1327
+ if ("prepare" in routeHandler) {
1328
+ const { viewPath, children } = routeHandler.prepare();
1329
+ if (Object.entries(children).length > 0) {
1330
+ const branch = createComponentTree(children);
1331
+ componentTree.push([viewPath, branch]);
1334
1332
  } else {
1335
- routeManifest[rootPath] = [result2.viewPath];
1336
- componentTree.push([result2.viewPath]);
1333
+ componentTree.push([viewPath, []]);
1337
1334
  }
1338
1335
  } else {
1339
- const router = new viewConfigOrViewRouter(app);
1340
- const middlewares = router.middlewares.map((alias) => {
1341
- if (app.middlewareAliases?.[alias]) {
1342
- const middleware = new app.middlewareAliases[alias];
1343
- return middleware.run;
1344
- }
1345
- }).filter(Boolean);
1346
- rootMiddleware.push(router.middleware, ...middlewares);
1347
- children = router.routes;
1336
+ const router = new routeHandler;
1337
+ const branch = createComponentTree(router.routes);
1338
+ componentTree.push(...branch);
1348
1339
  }
1349
- const result = flattenViewRoutes(children, app);
1350
- if (layoutViewPath) {
1351
- componentTree.push({ [layoutViewPath]: result.componentTree });
1352
- } else {
1353
- componentTree.push(...result.componentTree);
1354
- }
1355
- for (const [path, handlers] of Object.entries(result.flatRoutes)) {
1356
- const subPath = path === "/" ? "" : path;
1357
- const _rootPath = rootPath === "/" ? "" : rootPath;
1358
- const finalPath = `${_rootPath}${subPath}` === "" ? "/" : `${_rootPath}${subPath}`;
1359
- flatRoutes[finalPath] = {
1360
- exec: [rootHandler, ...handlers.exec],
1361
- middleware: [...rootMiddleware, ...handlers.middleware]
1362
- };
1363
- if (layoutViewPath) {
1364
- routeManifest[finalPath] = [
1365
- layoutViewPath,
1366
- ...result.routeManifest[path] ?? []
1367
- ];
1340
+ }
1341
+ return componentTree;
1342
+ }
1343
+
1344
+ // app/createFlatViewRoutes.ts
1345
+ function createFlatViewRoutes(routes) {
1346
+ const flatRoutes = {};
1347
+ for (const [routePath, viewConfigOrViewRouter] of Object.entries(routes)) {
1348
+ if ("prepare" in viewConfigOrViewRouter) {
1349
+ const route = viewConfigOrViewRouter.prepare();
1350
+ if (Object.entries(route.children).length > 0) {
1351
+ const result = createFlatViewRoutes(route.children);
1352
+ if (route.kind === "view") {
1353
+ flatRoutes[routePath] = {
1354
+ exec: [route.exec],
1355
+ middleware: route.middlewares
1356
+ };
1357
+ }
1358
+ for (const [path, { exec, middleware }] of Object.entries(result)) {
1359
+ const key = routePath === "/" ? path : `${routePath}${path}`;
1360
+ const _key = path === "/" && routePath !== "/" ? routePath : key;
1361
+ flatRoutes[_key] = {
1362
+ exec,
1363
+ middleware: [...route.middlewares, ...middleware]
1364
+ };
1365
+ }
1368
1366
  } else {
1369
- routeManifest[finalPath] = [...result.routeManifest[path] ?? []];
1367
+ flatRoutes[routePath] = {
1368
+ exec: [route.exec],
1369
+ middleware: route.middlewares
1370
+ };
1371
+ }
1372
+ } else {
1373
+ const router = new viewConfigOrViewRouter;
1374
+ const result = createFlatViewRoutes(router.routes);
1375
+ for (const [path, { exec, middleware }] of Object.entries(result)) {
1376
+ const key = routePath === "/" ? path : `${routePath}${path}`;
1377
+ const _key = path === "/" && routePath !== "/" ? routePath : key;
1378
+ flatRoutes[_key] = {
1379
+ exec,
1380
+ middleware: [...router.middlewares, ...middleware]
1381
+ };
1370
1382
  }
1371
1383
  }
1372
1384
  }
1373
- return {
1374
- flatRoutes,
1375
- routeManifest,
1376
- componentTree
1377
- };
1385
+ return flatRoutes;
1378
1386
  }
1379
1387
 
1380
- // client/helpers/flattenComponentTree.ts
1381
- function flattenComponentTree(componentTree) {
1382
- const out = [];
1383
- for (const section of componentTree.flat()) {
1384
- if (typeof section === "string") {
1385
- out.push(section);
1388
+ // app/createRouteManifest.ts
1389
+ function createRouteManifest(routes) {
1390
+ const routeManifest = {};
1391
+ for (const [routePath, routeHandler] of Object.entries(routes)) {
1392
+ if ("prepare" in routeHandler) {
1393
+ const { viewPath, children, kind } = routeHandler.prepare();
1394
+ if (kind === "view") {
1395
+ routeManifest[routePath] = [viewPath];
1396
+ }
1397
+ if (Object.entries(children).length > 0) {
1398
+ const manifest = createRouteManifest(children);
1399
+ for (const [path, viewPaths] of Object.entries(manifest)) {
1400
+ const key = routePath === "/" ? path : `${routePath}${path}`;
1401
+ const _key = path === "/" && routePath !== "/" ? routePath : key;
1402
+ routeManifest[_key] = [viewPath, ...viewPaths];
1403
+ }
1404
+ } else {
1405
+ routeManifest[routePath] = [viewPath];
1406
+ }
1386
1407
  } else {
1387
- for (const [key, value] of Object.entries(section)) {
1388
- out.push(key);
1389
- out.push(...flattenComponentTree(value));
1408
+ const router = new routeHandler;
1409
+ const manifest = createRouteManifest(router.routes);
1410
+ for (const [path, viewPaths] of Object.entries(manifest)) {
1411
+ const key = routePath === "/" ? path : `${routePath}${path}`;
1412
+ const _key = path === "/" && routePath !== "/" ? routePath : key;
1413
+ routeManifest[_key] = viewPaths;
1390
1414
  }
1391
1415
  }
1392
1416
  }
1393
- return out;
1417
+ return routeManifest;
1394
1418
  }
1395
1419
 
1396
1420
  // app/App.ts
1397
1421
  import {renderToReadableStream} from "react-dom/server.browser";
1398
1422
  import {createElement, Fragment} from "react";
1399
- var prepareViewData = function(result) {
1400
- return result.reduce((acc, next) => {
1401
- return {
1402
- pageData: {
1403
- ...acc.pageData,
1404
- ...next.data
1405
- },
1406
- headers: {
1407
- ...acc.headers,
1408
- ...next.headers
1409
- },
1410
- head: {
1411
- ...acc.head,
1412
- title: next?.head?.title ?? acc.head?.title ?? "Gemi App",
1413
- meta: [...acc.head?.meta ?? [], ...next?.head?.meta ?? []],
1414
- link: [...acc.head?.link ?? [], ...next?.head?.link ?? []]
1415
- }
1416
- };
1417
- }, { pageData: {}, headers: {}, head: {} });
1418
- };
1419
1423
 
1420
1424
  class App {
1421
1425
  flatViewRoutes = {};
@@ -1462,10 +1466,9 @@ class App {
1462
1466
  };
1463
1467
  }
1464
1468
  }
1465
- const { flatRoutes, routeManifest, componentTree } = flattenViewRoutes(viewRouters, this);
1466
- this.componentTree = componentTree;
1467
- this.routeManifest = routeManifest;
1468
- this.flatViewRoutes = flatRoutes;
1469
+ this.flatViewRoutes = createFlatViewRoutes(viewRouters);
1470
+ this.componentTree = createComponentTree(viewRouters);
1471
+ this.routeManifest = createRouteManifest(viewRouters);
1469
1472
  this.flatApiRoutes = this.flattenApiRoutes(apiRouters);
1470
1473
  }
1471
1474
  printName() {
@@ -1542,7 +1545,12 @@ class App {
1542
1545
  middlewares = handler.middleware;
1543
1546
  }
1544
1547
  }
1545
- const reqWithMiddlewares = middlewares.reduce((acc, middleware) => {
1548
+ const reqWithMiddlewares = middlewares.map((middleware) => {
1549
+ if (typeof middleware === "string") {
1550
+ return new this.middlewareAliases[middleware]().run;
1551
+ }
1552
+ return middleware;
1553
+ }).reduce((acc, middleware) => {
1546
1554
  return async (req2, ctx) => {
1547
1555
  return {
1548
1556
  ...await acc(req2, ctx),
@@ -1551,21 +1559,12 @@ class App {
1551
1559
  };
1552
1560
  }, (_req, _ctx) => Promise.resolve({}));
1553
1561
  const reqCtx = new Map;
1554
- const result = await requestContext.run(reqCtx, async () => {
1562
+ const data = await requestContext.run(reqCtx, async () => {
1555
1563
  await reqWithMiddlewares(req, reqCtx);
1556
1564
  return await Promise.all(handlers.map((fn) => fn(req, params, this)));
1557
1565
  });
1558
- let is404 = false;
1559
- for (const res of result) {
1560
- const [data] = Object.values(res.data ?? {});
1561
- if (data?.status === 404) {
1562
- is404 = true;
1563
- break;
1564
- }
1565
- }
1566
1566
  return {
1567
- is404,
1568
- result,
1567
+ data,
1569
1568
  currentPathName,
1570
1569
  params,
1571
1570
  user: reqCtx.get("user") ?? null
@@ -1600,11 +1599,12 @@ class App {
1600
1599
  ...err.payload.api
1601
1600
  };
1602
1601
  }
1602
+ throw err;
1603
1603
  }
1604
1604
  if (exec) {
1605
- let result = {};
1605
+ let data = {};
1606
1606
  try {
1607
- result = await exec(req, params, this);
1607
+ data = await exec(req, params, this);
1608
1608
  } catch (err) {
1609
1609
  if (err instanceof RequestBreakerError) {
1610
1610
  return {
@@ -1612,18 +1612,16 @@ class App {
1612
1612
  ...err.payload.api
1613
1613
  };
1614
1614
  }
1615
+ throw err;
1615
1616
  }
1616
- const { data, cookies = {}, headers, status } = result;
1617
1617
  return {
1618
1618
  kind: "api",
1619
1619
  data,
1620
1620
  headers: {
1621
- ...headers,
1622
- "Set-Cookie": Object.entries(cookies).map(([name, config]) => {
1621
+ "Set-Cookie": Object.entries({}).map(([name, config]) => {
1623
1622
  return `${name}=${config.value}; HttpOnly; SameSite=Strict; Path=/; Max-Age=${config.maxAge}`;
1624
1623
  }).join(", ")
1625
- },
1626
- status
1624
+ }
1627
1625
  };
1628
1626
  }
1629
1627
  });
@@ -1652,16 +1650,21 @@ class App {
1652
1650
  headers: {}
1653
1651
  };
1654
1652
  }
1655
- const { result, params, currentPathName, is404, user } = pageData;
1656
- const data = prepareViewData(result);
1653
+ const { data, params, currentPathName, user } = pageData;
1654
+ const viewData = data.reduce((acc, data2) => {
1655
+ return {
1656
+ ...acc,
1657
+ ...data2
1658
+ };
1659
+ }, {});
1657
1660
  if (url.searchParams.get("json")) {
1658
1661
  return {
1659
1662
  kind: "viewData",
1660
1663
  data: {
1661
- [url.pathname]: data.pageData
1664
+ [url.pathname]: viewData
1662
1665
  },
1663
1666
  meta: [],
1664
- headers: data.headers
1667
+ headers: {}
1665
1668
  };
1666
1669
  }
1667
1670
  let cookieHeaders = {};
@@ -1675,7 +1678,7 @@ class App {
1675
1678
  kind: "view",
1676
1679
  data: {
1677
1680
  pageData: {
1678
- [url.pathname]: data.pageData
1681
+ [url.pathname]: viewData
1679
1682
  },
1680
1683
  auth: { user },
1681
1684
  routeManifest: this.routeManifest,
@@ -1683,19 +1686,18 @@ class App {
1683
1686
  pathname: currentPathName,
1684
1687
  params,
1685
1688
  currentPath: url.pathname,
1686
- is404
1689
+ is404: false
1687
1690
  },
1688
- componentTree: [["404"], ...this.componentTree]
1691
+ componentTree: [["404", []], ...this.componentTree]
1689
1692
  },
1690
- head: data.head,
1693
+ head: {},
1691
1694
  headers: {
1692
- ...data.headers,
1693
1695
  "Content-Type": "text/html",
1694
1696
  "Cache-Control": user ? "private, no-cache, no-store, max-age=0, must-revalidate" : "public, max-age=864000, must-revalidate",
1695
1697
  ETag: this.appId,
1696
1698
  ...cookieHeaders
1697
1699
  },
1698
- status: is404 ? 404 : 200
1700
+ status: 200
1699
1701
  };
1700
1702
  }
1701
1703
  }
@@ -1735,7 +1737,10 @@ class App {
1735
1737
  let appDir = null;
1736
1738
  const template = (viewName, path) => `"${viewName}": () => import("${path}")`;
1737
1739
  const templates = [];
1738
- for (const fileName of flattenComponentTree(this.componentTree)) {
1740
+ for (const fileName of [
1741
+ "404",
1742
+ ...flattenComponentTree(this.componentTree)
1743
+ ]) {
1739
1744
  if (!manifest) {
1740
1745
  appDir = `${process.env.APP_DIR}`;
1741
1746
  const mod = await import(`${appDir}/views/${fileName}.tsx`);
@@ -1756,7 +1761,6 @@ class App {
1756
1761
  children: [
1757
1762
  styles,
1758
1763
  createElement(this.Root, {
1759
- head,
1760
1764
  data,
1761
1765
  viewImportMap
1762
1766
  })
@@ -1774,9 +1778,8 @@ class App {
1774
1778
  });
1775
1779
  }
1776
1780
  if (result.kind === "api") {
1777
- const { data, headers, status } = result;
1781
+ const { data, headers } = result;
1778
1782
  return new Response(JSON.stringify(data), {
1779
- status,
1780
1783
  headers: {
1781
1784
  "Content-Type": "application/json",
1782
1785
  ...headers
package/dist/bin/gemi CHANGED
Binary file
@@ -1 +1 @@
1
- {"version":3,"file":"ClientRouter.d.ts","sourceRoot":"","sources":["../../client/ClientRouter.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAkHf,eAAO,MAAM,YAAY,UAAW;IAClC,aAAa,CAAC,EAAE,OAAO,MAAM,EAAE,GAAG,CAAC,CAAC;IACpC,UAAU,EAAE,cAAc,GAAG,CAAC,CAAC;CAChC,4CA2BA,CAAC"}
1
+ {"version":3,"file":"ClientRouter.d.ts","sourceRoot":"","sources":["../../client/ClientRouter.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAkFf,eAAO,MAAM,YAAY,UAAW;IAClC,aAAa,CAAC,EAAE,OAAO,MAAM,EAAE,GAAG,CAAC,CAAC;IACpC,UAAU,EAAE,cAAc,GAAG,CAAC,CAAC;CAChC,4CA2BA,CAAC"}
@@ -22,6 +22,7 @@ interface ClientRouterProviderProps {
22
22
  export declare const ClientRouterProvider: (props: PropsWithChildren<ClientRouterProviderProps>) => import("react/jsx-runtime").JSX.Element;
23
23
  export declare function useLocation(): Location;
24
24
  export declare function useParams(): Record<string, string>;
25
+ export declare function useViewData(): void;
25
26
  export declare function useRouter(): {
26
27
  push: (to: To, state?: any) => Promise<void>;
27
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ClientRouterContext.d.ts","sourceRoot":"","sources":["../../client/ClientRouterContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,EAAE,EACP,KAAK,QAAQ,EAEd,MAAM,SAAS,CAAC;AACjB,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACvB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,UAAU,wBAAwB;IAChC,kBAAkB,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACxD,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,eAAO,MAAM,mBAAmB,mDAE/B,CAAC;AAEF,UAAU,yBAAyB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,oBAAoB,UACxB,kBAAkB,yBAAyB,CAAC,4CA2GpD,CAAC;AAUF,wBAAgB,WAAW,aAU1B;AAED,wBAAgB,SAAS,2BAGxB;AAED,wBAAgB,SAAS;eAGJ,EAAE,UAAU,GAAG;EAsBnC;AAED,eAAO,MAAM,IAAI,UACR,KAAK,eAAe,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,EAAE,EAAE,CAAA;CAAE,4CA0BxD,CAAC"}
1
+ {"version":3,"file":"ClientRouterContext.d.ts","sourceRoot":"","sources":["../../client/ClientRouterContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,EAAE,EACP,KAAK,QAAQ,EAEd,MAAM,SAAS,CAAC;AACjB,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACvB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,UAAU,wBAAwB;IAChC,kBAAkB,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACxD,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,eAAO,MAAM,mBAAmB,mDAE/B,CAAC;AAEF,UAAU,yBAAyB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,oBAAoB,UACxB,kBAAkB,yBAAyB,CAAC,4CA2GpD,CAAC;AAUF,wBAAgB,WAAW,aAU1B;AAED,wBAAgB,SAAS,2BAGxB;AAED,wBAAgB,WAAW,SAAK;AAEhC,wBAAgB,SAAS;eAGJ,EAAE,UAAU,GAAG;EAsBnC;AAED,eAAO,MAAM,IAAI,UACR,KAAK,eAAe,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,EAAE,EAAE,CAAA;CAAE,4CA0BxD,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import type { ComponentTree } from "../types";
2
- export declare function flattenComponentTree(componentTree: ComponentTree): any[];
2
+ export declare function flattenComponentTree(componentTree: ComponentTree): string[];
3
3
  //# sourceMappingURL=flattenComponentTree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"flattenComponentTree.d.ts","sourceRoot":"","sources":["../../../client/helpers/flattenComponentTree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,aAAa,SAahE"}
1
+ {"version":3,"file":"flattenComponentTree.d.ts","sourceRoot":"","sources":["../../../client/helpers/flattenComponentTree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,aAAa,GAAG,MAAM,EAAE,CAM3E"}
@@ -573,7 +573,7 @@ const ClientRouterProvider = (props) => {
573
573
  params
574
574
  } = props;
575
575
  const [parameters, setParameters] = useState(params);
576
- const pageDataRef = useRef(pageData);
576
+ const pageDataRef = useRef(structuredClone(pageData));
577
577
  const scrollHistoryRef = useRef(/* @__PURE__ */ new Map());
578
578
  const initalViewEntries = is404 ? ["404"] : routeManifest[pathname] ?? ["404"];
579
579
  const viewEntriesSubject = useRef(new Subject(initalViewEntries));
@@ -29364,18 +29364,11 @@ if (process.env.NODE_ENV === "production") {
29364
29364
  }
29365
29365
  var clientExports = client.exports;
29366
29366
  function flattenComponentTree(componentTree) {
29367
- const out = [];
29368
- for (const section of componentTree.flat()) {
29369
- if (typeof section === "string") {
29370
- out.push(section);
29371
- } else {
29372
- for (const [key, value] of Object.entries(section)) {
29373
- out.push(key);
29374
- out.push(...flattenComponentTree(value));
29375
- }
29376
- }
29367
+ let out = [];
29368
+ for (const [root, branches] of componentTree) {
29369
+ out.push(root, ...flattenComponentTree(branches).flat());
29377
29370
  }
29378
- return out;
29371
+ return Array.from(new Set(out));
29379
29372
  }
29380
29373
  let viewImportMap = null;
29381
29374
  if (typeof window !== "undefined") {
@@ -29413,26 +29406,12 @@ const Route = (props) => {
29413
29406
  };
29414
29407
  const Routes = (props) => {
29415
29408
  const { componentTree } = props;
29416
- return /* @__PURE__ */ jsx(Suspense, { children: componentTree.map((node, i) => {
29417
- if (typeof node === "undefined") {
29418
- return null;
29419
- }
29420
- if (typeof node === "string") {
29421
- return /* @__PURE__ */ jsx(Route, { componentPath: node }, node);
29422
- }
29423
- if (Array.isArray(node)) {
29424
- const [path, subtree2] = node;
29425
- if (subtree2) {
29426
- return /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(Route, { componentPath: path, children: /* @__PURE__ */ jsx(Routes, { componentTree: subtree2 }) }, i) }, path);
29427
- } else {
29428
- return /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(Route, { componentPath: path }, i) }, path);
29429
- }
29430
- }
29431
- const [[first, subtree]] = Object.entries(node);
29432
- if (subtree) {
29433
- return /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(Route, { componentPath: String(first), children: /* @__PURE__ */ jsx(Routes, { componentTree: subtree }) }, i) }, first);
29409
+ return /* @__PURE__ */ jsx(Suspense, { children: componentTree.map((node) => {
29410
+ const [path, subtree] = node;
29411
+ if (subtree.length > 0) {
29412
+ return /* @__PURE__ */ jsx(Route, { componentPath: path, children: /* @__PURE__ */ jsx(Routes, { componentTree: subtree }) }, path);
29434
29413
  }
29435
- return /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(Route, { componentPath: String(first) }, i) }, first);
29414
+ return /* @__PURE__ */ jsx(Route, { componentPath: path }, path);
29436
29415
  }) });
29437
29416
  };
29438
29417
  const ClientRouter = (props) => {
@@ -1,4 +1,4 @@
1
- type ComponentTreeBranch = Record<string, ComponentTree>;
2
- export type ComponentTree = (string[] | ComponentTreeBranch)[];
1
+ type ComponentBranch = [string, ComponentBranch[]];
2
+ export type ComponentTree = ComponentBranch[];
3
3
  export {};
4
4
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../client/types.ts"],"names":[],"mappings":"AAAA,KAAK,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AACzD,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,GAAG,mBAAmB,CAAC,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../client/types.ts"],"names":[],"mappings":"AAAA,KAAK,eAAe,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;AACnD,MAAM,MAAM,aAAa,GAAG,eAAe,EAAE,CAAC"}
@@ -1,53 +1,41 @@
1
- import type { Controller } from "./Controller";
1
+ import { Controller } from "./Controller";
2
2
  import { type MiddlewareReturnType } from "./Router";
3
3
  import type { App } from "../app/App";
4
+ import { HttpRequest } from "./HttpRequest";
4
5
  type ControllerMethods<T extends new (app: App) => Controller> = {
5
6
  [K in keyof InstanceType<T>]: InstanceType<T>[K] extends Function ? K : never;
6
7
  }[keyof InstanceType<T>];
7
- type DataResponse = {
8
- data: any;
9
- status: number;
10
- headers: Record<string, string>;
11
- cookies: Record<string, string>;
12
- };
8
+ type DataResponse = any;
13
9
  type ErrorResponse = {
14
10
  error: any;
15
- status: number;
16
- headers: Record<string, string>;
17
- cookies: Record<string, string>;
11
+ };
12
+ type ApiHandler<T extends new (app: App) => Controller, U = {}> = {
13
+ method: string;
14
+ exec: (req: Request, params: Record<string, any>, app: App) => Promise<Partial<DataResponse> | ErrorResponse>;
18
15
  };
19
16
  export type ApiRouteExec = (req: Request, params: Record<string, string>) => Promise<DataResponse | ErrorResponse>;
20
17
  type ApiRouteConfig = {
21
18
  method: string;
22
19
  exec: ApiRouteExec;
23
20
  };
21
+ type CallbackHandler<T> = (req: HttpRequest) => Promise<T> | T;
24
22
  export type ApiRouteChildren = Record<string, ApiRouteConfig | ApiRouteConfig[] | (new (app: App) => ApiRouter)>;
25
23
  export declare class ApiRouter {
26
24
  routes: Record<string, any>;
27
25
  middlewares: string[];
28
26
  constructor();
29
- middleware(req: Request): MiddlewareReturnType;
27
+ middleware(_req: Request): MiddlewareReturnType;
30
28
  private handleRequest;
31
- protected get<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): {
32
- method: string;
33
- exec: (req: Request, params: Record<string, string>, app: App) => Promise<DataResponse | ErrorResponse>;
34
- };
35
- protected post<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): {
36
- method: string;
37
- exec: (req: Request, params: Record<string, string>, app: App) => Promise<DataResponse | ErrorResponse>;
38
- };
39
- protected patch<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): {
40
- method: string;
41
- exec: (req: Request, params: Record<string, string>, app: App) => Promise<DataResponse | ErrorResponse>;
42
- };
43
- protected put<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): {
44
- method: string;
45
- exec: (req: Request, params: Record<string, string>, app: App) => Promise<DataResponse | ErrorResponse>;
46
- };
47
- protected delete<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): {
48
- method: string;
49
- exec: (req: Request, params: Record<string, string>, app: App) => Promise<DataResponse | ErrorResponse>;
50
- };
29
+ protected get<T>(controller: CallbackHandler<T>): ApiHandler<any>;
30
+ protected get<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): ApiHandler<T>;
31
+ protected post<T>(controller: CallbackHandler<T>): ApiHandler<any>;
32
+ protected post<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): ApiHandler<T>;
33
+ protected put<T>(controller: CallbackHandler<T>): ApiHandler<any>;
34
+ protected put<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): ApiHandler<T>;
35
+ protected delete<T>(controller: CallbackHandler<T>): ApiHandler<any>;
36
+ protected delete<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): ApiHandler<T>;
37
+ protected patch<T>(controller: CallbackHandler<T>): ApiHandler<any>;
38
+ protected patch<T extends new (app: App) => Controller>(controller: T, methodName: ControllerMethods<T>): ApiHandler<T>;
51
39
  }
52
40
  export {};
53
41
  //# sourceMappingURL=ApiRouter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApiRouter.d.ts","sourceRoot":"","sources":["../../http/ApiRouter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAGtC,KAAK,iBAAiB,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,IAAI;KAC9D,CAAC,IAAI,MAAM,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,GAAG,CAAC,GAAG,KAAK;CAC9E,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzB,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,GAAG,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AACF,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,GAAG,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AAYF,MAAM,MAAM,YAAY,GAAG,CACzB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC3B,OAAO,CAAC,YAAY,GAAG,aAAa,CAAC,CAAC;AAE3C,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,MAAM,CACnC,MAAM,EACN,cAAc,GAAG,cAAc,EAAE,GAAG,CAAC,KAAK,GAAG,EAAE,GAAG,KAAK,SAAS,CAAC,CAClE,CAAC;AAEF,qBAAa,SAAS;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAM;IACjC,WAAW,EAAE,MAAM,EAAE,CAAM;;IAI3B,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB;IAErD,OAAO,CAAC,aAAa;IAkCrB,SAAS,CAAC,GAAG,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EAClD,UAAU,EAAE,CAAC,EACb,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;;;;IAMlC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACnD,UAAU,EAAE,CAAC,EACb,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;;;;IAMlC,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACpD,UAAU,EAAE,CAAC,EACb,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;;;;IAMlC,SAAS,CAAC,GAAG,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EAClD,UAAU,EAAE,CAAC,EACb,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;;;;IAMlC,SAAS,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACrD,UAAU,EAAE,CAAC,EACb,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;;;;CAKnC"}
1
+ {"version":3,"file":"ApiRouter.d.ts","sourceRoot":"","sources":["../../http/ApiRouter.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { App } from "../app/App";
2
2
  import type { HttpRequest } from "./HttpRequest";
3
3
  export declare class Controller {
4
- app: App;
4
+ private app;
5
5
  requests: Record<string, typeof HttpRequest<any>>;
6
+ static kind: "controller";
6
7
  constructor(app: App);
7
8
  }
8
9
  //# sourceMappingURL=Controller.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Controller.d.ts","sourceRoot":"","sources":["../../http/Controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,qBAAa,UAAU;IAGF,GAAG,EAAE,GAAG;IAF3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAM;gBAEpC,GAAG,EAAE,GAAG;CAC5B"}
1
+ {"version":3,"file":"Controller.d.ts","sourceRoot":"","sources":["../../http/Controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,qBAAa,UAAU;IAKT,OAAO,CAAC,GAAG;IAJvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAM;IAEvD,MAAM,CAAC,IAAI,eAAyB;gBAEhB,GAAG,EAAE,GAAG;CAC7B"}
@@ -4,30 +4,30 @@ import type { App } from "../app/App";
4
4
  type ControllerMethods<T extends new () => Controller> = {
5
5
  [K in keyof InstanceType<T>]: InstanceType<T>[K] extends Function ? K : never;
6
6
  }[keyof InstanceType<T>];
7
- type ViewHandler<T extends new () => Controller> = [
8
- controller: T,
9
- method: ControllerMethods<T>
10
- ];
7
+ type ViewHandler<T extends new () => Controller> = [controller: T, method: ControllerMethods<T>] | ((req: Request) => Promise<any> | any);
11
8
  type ViewPrepare = {
12
9
  exec: (req: Request, params: Record<string, string>) => any;
13
10
  viewPath: string;
14
11
  children: ViewChildren;
15
12
  middlewares: any[];
13
+ kind: "view" | "layout";
16
14
  };
17
15
  type ViewConfig = {
18
16
  prepare: (_middlewares?: any[]) => ViewPrepare;
19
- middlewares: (middlewares: any[]) => {
20
- prepare: () => ViewPrepare;
21
- };
17
+ middleware: (middlewares: any[]) => ViewConfig;
22
18
  };
23
- export type ViewChildren = Record<string, ViewConfig | (new (app: App) => ViewRouter)>;
19
+ export type ViewChildren = Record<string, ViewConfig | (new () => ViewRouter)>;
24
20
  export type ViewRouteExec = (req: Request, params: Record<string, string>, app: App) => any;
25
21
  export declare class ViewRouter {
26
22
  routes: ViewChildren;
27
23
  middlewares: string[];
28
- constructor();
29
24
  middleware(req: Request): MiddlewareReturnType;
30
- protected view<T extends new (app: App) => Controller>(viewPath: string, handler?: ViewHandler<T>, children?: ViewChildren): ViewConfig;
25
+ protected layout<T extends new (app: App) => Controller>(viewPath: string): ViewConfig;
26
+ protected layout<T extends new (app: App) => Controller>(viewPath: string, children?: ViewChildren): ViewConfig;
27
+ protected layout<T extends new (app: App) => Controller>(viewPath: string, handler: ViewHandler<T>): ViewConfig;
28
+ protected view<T extends new (app: App) => Controller>(viewPath: string): ViewConfig;
29
+ protected view<T extends new (app: App) => Controller>(viewPath: string, children?: ViewChildren): ViewConfig;
30
+ protected view<T extends new (app: App) => Controller>(viewPath: string, handler: ViewHandler<T>): ViewConfig;
31
31
  }
32
32
  export {};
33
33
  //# sourceMappingURL=ViewRouter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ViewRouter.d.ts","sourceRoot":"","sources":["../../http/ViewRouter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,KAAK,iBAAiB,CAAC,CAAC,SAAS,UAAU,UAAU,IAAI;KACtD,CAAC,IAAI,MAAM,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,GAAG,CAAC,GAAG,KAAK;CAC9E,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzB,KAAK,WAAW,CAAC,CAAC,SAAS,UAAU,UAAU,IAAI;IACjD,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;CAC7B,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,EAAE,GAAG,EAAE,CAAC;CACpB,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,KAAK,WAAW,CAAC;IAC/C,WAAW,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK;QACnC,OAAO,EAAE,MAAM,WAAW,CAAC;KAC5B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,CAC/B,MAAM,EACN,UAAU,GAAG,CAAC,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,CAAC,CAC5C,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,GAAG,EAAE,GAAG,KACL,GAAG,CAAC;AAET,qBAAa,UAAU;IACd,MAAM,EAAE,YAAY,CAAM;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAM;;IAG3B,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB;IAErD,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACnD,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACxB,QAAQ,GAAE,YAAiB,GAC1B,UAAU;CA8Bd"}
1
+ {"version":3,"file":"ViewRouter.d.ts","sourceRoot":"","sources":["../../http/ViewRouter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,KAAK,iBAAiB,CAAC,CAAC,SAAS,UAAU,UAAU,IAAI;KACtD,CAAC,IAAI,MAAM,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,GAAG,CAAC,GAAG,KAAK;CAC9E,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzB,KAAK,WAAW,CAAC,CAAC,SAAS,UAAU,UAAU,IAC3C,CAAC,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,GAC7C,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;AAE3C,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,EAAE,GAAG,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CACzB,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,KAAK,WAAW,CAAC;IAC/C,UAAU,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,UAAU,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,UAAU,UAAU,CAAC,CAAC,CAAC;AAE/E,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,GAAG,EAAE,GAAG,KACL,GAAG,CAAC;AAET,qBAAa,UAAU;IACd,MAAM,EAAE,YAAY,CAAM;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAM;IAE3B,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB;IAErD,SAAS,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACrD,QAAQ,EAAE,MAAM,GACf,UAAU;IACb,SAAS,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACrD,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,YAAiB,GAC1B,UAAU;IACb,SAAS,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACrD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GACtB,UAAU;IAmDb,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACnD,QAAQ,EAAE,MAAM,GACf,UAAU;IACb,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACnD,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,YAAiB,GAC1B,UAAU;IACb,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,KAAK,UAAU,EACnD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GACtB,UAAU;CAkDd"}
@@ -22,6 +22,7 @@ var __require = createRequire(import.meta.url);
22
22
  class Controller {
23
23
  app;
24
24
  requests = {};
25
+ static kind = "controller";
25
26
  constructor(app) {
26
27
  this.app = app;
27
28
  }
@@ -225,34 +226,33 @@ class HttpRequest {
225
226
  }
226
227
 
227
228
  // http/ApiRouter.ts
229
+ var isController = function(controller) {
230
+ return "kind" in controller && controller.kind === "controller";
231
+ };
232
+
228
233
  class ApiRouter {
229
234
  routes = {};
230
235
  middlewares = [];
231
236
  constructor() {
232
237
  }
233
- middleware(req) {
238
+ middleware(_req) {
234
239
  }
235
240
  handleRequest(controller, methodName) {
236
241
  return (method) => {
237
242
  return {
238
243
  method,
239
244
  exec: async (req, params, app) => {
240
- const controllerInstance = new controller(app);
241
- const handler = controllerInstance[methodName].bind(controllerInstance);
242
- const Req = controllerInstance.requests[methodName] ?? HttpRequest;
243
- const httpRequest = new Req(req);
244
- const {
245
- data,
246
- status = method === "post" ? 201 : 200,
247
- headers = {},
248
- cookies = {}
249
- } = await handler(httpRequest, params);
250
- return {
251
- data,
252
- status,
253
- headers,
254
- cookies
255
- };
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));
254
+ }
255
+ return await handler(httpRequest, params);
256
256
  }
257
257
  };
258
258
  };
@@ -265,10 +265,6 @@ class ApiRouter {
265
265
  const handler = this.handleRequest(controller, methodName);
266
266
  return handler("post");
267
267
  }
268
- patch(controller, methodName) {
269
- const handler = this.handleRequest(controller, methodName);
270
- return handler("patch");
271
- }
272
268
  put(controller, methodName) {
273
269
  const handler = this.handleRequest(controller, methodName);
274
270
  return handler("put");
@@ -277,39 +273,89 @@ class ApiRouter {
277
273
  const handler = this.handleRequest(controller, methodName);
278
274
  return handler("delete");
279
275
  }
276
+ patch(controller, methodName) {
277
+ const handler = this.handleRequest(controller, methodName);
278
+ return handler("patch");
279
+ }
280
280
  }
281
281
  // http/ViewRouter.ts
282
282
  class ViewRouter {
283
283
  routes = {};
284
284
  middlewares = [];
285
- constructor() {
286
- }
287
285
  middleware(req) {
288
286
  }
289
- view(viewPath, handler, children = {}) {
287
+ layout(viewPath, handler, children = {}) {
290
288
  function prepare(middlewares = []) {
289
+ let _children = children;
290
+ if (handler && handler.constructor === Object) {
291
+ _children = handler;
292
+ }
291
293
  return {
292
294
  exec: async (req, params, app) => {
293
- if (!handler) {
294
- return { data: { [viewPath]: {} }, headers: {}, head: {} };
295
+ let _handler = () => Promise.resolve({
296
+ data: { [viewPath]: {} },
297
+ headers: {},
298
+ head: {}
299
+ });
300
+ if (typeof handler === "function") {
301
+ _handler = handler;
295
302
  }
296
- const [controller, methodName] = handler;
297
- const instance = new controller(app);
298
- const method = instance[methodName].bind(instance);
299
- const { data, headers = {}, head = {} } = await method(req, params);
300
- return { data: { [viewPath]: data }, headers, head };
303
+ if (Array.isArray(handler)) {
304
+ const [controller, methodName] = handler;
305
+ const instance = new controller(app);
306
+ _handler = instance[methodName].bind(instance);
307
+ }
308
+ const data = await _handler(req, params);
309
+ return { [viewPath]: data };
301
310
  },
302
- children,
311
+ children: _children,
303
312
  viewPath,
304
- middlewares
313
+ middlewares,
314
+ kind: "layout"
305
315
  };
306
316
  }
307
317
  return {
308
318
  prepare,
309
- middlewares: (middlewares) => {
310
- prepare:
311
- ;
319
+ middleware: (middlewares) => ({
320
+ prepare: () => prepare(middlewares)
321
+ })
322
+ };
323
+ }
324
+ view(viewPath, handler, children = {}) {
325
+ function prepare(middlewares = []) {
326
+ let _children = children;
327
+ if (handler && handler.constructor === Object) {
328
+ _children = handler;
312
329
  }
330
+ return {
331
+ exec: async (req, params, app) => {
332
+ let _handler = () => Promise.resolve({
333
+ data: { [viewPath]: {} },
334
+ headers: {},
335
+ head: {}
336
+ });
337
+ if (typeof handler === "function") {
338
+ _handler = handler;
339
+ }
340
+ if (Array.isArray(handler)) {
341
+ const [controller, methodName] = handler;
342
+ const instance = new controller(app);
343
+ _handler = instance[methodName].bind(instance);
344
+ }
345
+ const data = await _handler(req, params);
346
+ return { [viewPath]: data };
347
+ },
348
+ children: _children,
349
+ viewPath,
350
+ middlewares,
351
+ kind: "view"
352
+ };
353
+ }
354
+ return {
355
+ prepare,
356
+ middleware: (middlewares) => ({
357
+ prepare: () => prepare(middlewares)
358
+ })
313
359
  };
314
360
  }
315
361
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemi",
3
- "version": "0.2.2",
3
+ "version": "0.3.2",
4
4
  "devDependencies": {
5
5
  "@repo/eslint-config": "*",
6
6
  "@repo/typescript-config": "*",
@@ -10,7 +10,8 @@
10
10
  "@types/react": "^18.2.61",
11
11
  "@types/react-dom": "^18.2.19",
12
12
  "eslint": "^8.57.0",
13
- "typescript": "^5.3.3"
13
+ "typescript": "^5.3.3",
14
+ "vitest": "^1.6.0"
14
15
  },
15
16
  "bin": {
16
17
  "gemi": "./dist/bin/gemi"
@@ -36,7 +37,8 @@
36
37
  "build:bin": "bun build --compile ./bin/gemi.ts --external vite --external react-dom --external react/jsx-runtime --outfile ./dist/bin/gemi",
37
38
  "build:client": "vite build",
38
39
  "build:types": "tsc",
39
- "build:client-types": "tsc -p tsconfig.browser.json"
40
+ "build:client-types": "tsc -p tsconfig.browser.json",
41
+ "test": "vitest"
40
42
  },
41
43
  "dependencies": {
42
44
  "@react-email/components": "^0.0.19",