@qwik.dev/router 2.0.0-alpha.8 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/lib/adapters/azure-swa/vite/index.cjs +3 -3
  3. package/lib/adapters/azure-swa/vite/index.d.ts +13 -13
  4. package/lib/adapters/bun-server/vite/index.cjs +3 -3
  5. package/lib/adapters/bun-server/vite/index.d.ts +14 -14
  6. package/lib/adapters/cloud-run/vite/index.cjs +3 -3
  7. package/lib/adapters/cloud-run/vite/index.d.ts +13 -13
  8. package/lib/adapters/cloudflare-pages/vite/index.cjs +3 -3
  9. package/lib/adapters/cloudflare-pages/vite/index.d.ts +27 -27
  10. package/lib/adapters/deno-server/vite/index.cjs +3 -3
  11. package/lib/adapters/deno-server/vite/index.d.ts +14 -14
  12. package/lib/adapters/netlify-edge/vite/index.cjs +3 -3
  13. package/lib/adapters/netlify-edge/vite/index.d.ts +44 -44
  14. package/lib/adapters/node-server/vite/index.cjs +3 -3
  15. package/lib/adapters/node-server/vite/index.d.ts +14 -14
  16. package/lib/adapters/shared/vite/index.cjs +10 -3
  17. package/lib/adapters/shared/vite/index.d.ts +114 -114
  18. package/lib/adapters/shared/vite/index.mjs +7 -0
  19. package/lib/adapters/static/vite/index.cjs +10 -3
  20. package/lib/adapters/static/vite/index.d.ts +10 -10
  21. package/lib/adapters/static/vite/index.mjs +7 -0
  22. package/lib/adapters/vercel-edge/vite/index.cjs +3 -3
  23. package/lib/adapters/vercel-edge/vite/index.d.ts +45 -45
  24. package/lib/index.d.ts +878 -801
  25. package/lib/index.qwik.cjs +127 -51
  26. package/lib/index.qwik.mjs +130 -54
  27. package/lib/middleware/aws-lambda/index.d.ts +48 -50
  28. package/lib/middleware/azure-swa/index.d.ts +28 -28
  29. package/lib/middleware/bun/index.d.ts +35 -35
  30. package/lib/middleware/cloudflare-pages/index.d.ts +35 -35
  31. package/lib/middleware/deno/index.d.ts +47 -47
  32. package/lib/middleware/firebase/index.d.ts +26 -26
  33. package/lib/middleware/netlify-edge/index.d.ts +27 -27
  34. package/lib/middleware/node/index.cjs +3 -3
  35. package/lib/middleware/node/index.d.ts +64 -66
  36. package/lib/middleware/request-handler/index.cjs +133 -75
  37. package/lib/middleware/request-handler/index.d.ts +710 -681
  38. package/lib/middleware/request-handler/index.mjs +129 -72
  39. package/lib/middleware/vercel-edge/index.d.ts +26 -26
  40. package/lib/service-worker.cjs +13 -263
  41. package/lib/service-worker.d.ts +15 -4
  42. package/lib/service-worker.mjs +13 -263
  43. package/lib/static/index.cjs +3 -3
  44. package/lib/static/index.d.ts +96 -98
  45. package/lib/static/node.cjs +3 -3
  46. package/lib/vite/index.cjs +199 -262
  47. package/lib/vite/index.d.ts +154 -154
  48. package/lib/vite/index.mjs +197 -260
  49. package/package.json +8 -8
@@ -1,17 +1,11 @@
1
1
  // packages/qwik-router/src/middleware/request-handler/error-handler.ts
2
2
  var ServerError = class extends Error {
3
3
  constructor(status, data) {
4
- super();
4
+ super(typeof data === "string" ? data : void 0);
5
5
  this.status = status;
6
6
  this.data = data;
7
7
  }
8
8
  };
9
- var ErrorResponse = class extends Error {
10
- constructor(status, message) {
11
- super(message);
12
- this.status = status;
13
- }
14
- };
15
9
  function getErrorHtml(status, e) {
16
10
  let message = "Server Error";
17
11
  if (e != null) {
@@ -224,6 +218,14 @@ var AbortMessage = class {
224
218
  var RedirectMessage = class extends AbortMessage {
225
219
  };
226
220
 
221
+ // packages/qwik-router/src/middleware/request-handler/rewrite-handler.ts
222
+ var RewriteMessage = class extends AbortMessage {
223
+ constructor(pathname) {
224
+ super();
225
+ this.pathname = pathname;
226
+ }
227
+ };
228
+
227
229
  // packages/qwik-router/src/runtime/src/constants.ts
228
230
  var MODULE_CACHE = /* @__PURE__ */ new WeakMap();
229
231
  var QACTION_KEY = "qaction";
@@ -459,8 +461,7 @@ function createCacheControl(cacheControl) {
459
461
  cacheControl = {
460
462
  public: true,
461
463
  immutable: true,
462
- maxAge: 60 * 60 * 24 * 365,
463
- staleWhileRevalidate: 60 * 60 * 24 * 365
464
+ maxAge: 60 * 60 * 24 * 365
464
465
  };
465
466
  } else if (cacheControl === "no-cache") {
466
467
  cacheControl = {
@@ -470,8 +471,7 @@ function createCacheControl(cacheControl) {
470
471
  if (typeof cacheControl === "number") {
471
472
  cacheControl = {
472
473
  maxAge: cacheControl,
473
- sMaxAge: cacheControl,
474
- staleWhileRevalidate: cacheControl
474
+ sMaxAge: cacheControl
475
475
  };
476
476
  }
477
477
  if (cacheControl.immutable) {
@@ -516,14 +516,13 @@ import("node:async_hooks").then((module) => {
516
516
  err
517
517
  );
518
518
  });
519
- function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, manifest, trailingSlash = true, basePathname = "/", qwikSerializer) {
519
+ function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, trailingSlash = true, basePathname = "/", qwikSerializer) {
520
520
  let resolve;
521
521
  const responsePromise = new Promise((r) => resolve = r);
522
522
  const requestEv = createRequestEvent(
523
523
  serverRequestEv,
524
524
  loadedRoute,
525
525
  requestHandlers,
526
- manifest,
527
526
  trailingSlash,
528
527
  basePathname,
529
528
  qwikSerializer,
@@ -532,49 +531,71 @@ function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, manifest,
532
531
  return {
533
532
  response: responsePromise,
534
533
  requestEv,
535
- completion: asyncStore ? asyncStore.run(requestEv, runNext, requestEv, resolve) : runNext(requestEv, resolve)
534
+ completion: asyncStore ? asyncStore.run(requestEv, runNext, requestEv, rebuildRouteInfo, resolve) : runNext(requestEv, rebuildRouteInfo, resolve)
536
535
  };
537
536
  }
538
- async function runNext(requestEv, resolve) {
539
- try {
540
- await requestEv.next();
541
- } catch (e) {
542
- if (e instanceof RedirectMessage) {
543
- const stream = requestEv.getWritableStream();
544
- await stream.close();
545
- } else if (e instanceof ErrorResponse) {
546
- console.error(e);
547
- if (!requestEv.headersSent) {
548
- const html = getErrorHtml(e.status, e);
549
- const status = e.status;
550
- requestEv.html(status, html);
551
- }
552
- } else if (!(e instanceof AbortMessage)) {
553
- if (getRequestMode(requestEv) !== "dev") {
554
- try {
555
- if (!requestEv.headersSent) {
556
- requestEv.headers.set("content-type", "text/html; charset=utf-8");
557
- requestEv.cacheControl({ noCache: true });
558
- requestEv.status(500);
537
+ async function runNext(requestEv, rebuildRouteInfo, resolve) {
538
+ let rewriteAttempt = 1;
539
+ async function _runNext() {
540
+ try {
541
+ await requestEv.next();
542
+ } catch (e) {
543
+ if (e instanceof RedirectMessage) {
544
+ const stream = requestEv.getWritableStream();
545
+ await stream.close();
546
+ } else if (e instanceof RewriteMessage) {
547
+ if (rewriteAttempt > 50) {
548
+ throw new Error(`Infinite rewrite loop`);
549
+ }
550
+ rewriteAttempt += 1;
551
+ const url = new URL(requestEv.url);
552
+ url.pathname = e.pathname;
553
+ const { loadedRoute, requestHandlers } = await rebuildRouteInfo(url);
554
+ requestEv.resetRoute(loadedRoute, requestHandlers, url);
555
+ return await _runNext();
556
+ } else if (e instanceof ServerError) {
557
+ if (!requestEv.headersSent) {
558
+ const status = e.status;
559
+ const accept = requestEv.request.headers.get("Accept");
560
+ if (accept && !accept.includes("text/html")) {
561
+ const qwikSerializer = requestEv[RequestEvQwikSerializer];
562
+ requestEv.headers.set("Content-Type", "application/qwik-json");
563
+ requestEv.send(status, await qwikSerializer._serialize([e.data]));
564
+ } else {
565
+ const html = getErrorHtml(e.status, e.data);
566
+ requestEv.html(status, html);
559
567
  }
560
- const stream = requestEv.getWritableStream();
561
- if (!stream.locked) {
562
- const writer = stream.getWriter();
563
- await writer.write(encoder.encode(minimalHtmlResponse(500, "Internal Server Error")));
564
- await writer.close();
568
+ }
569
+ } else if (!(e instanceof AbortMessage)) {
570
+ if (getRequestMode(requestEv) !== "dev") {
571
+ try {
572
+ if (!requestEv.headersSent) {
573
+ requestEv.headers.set("content-type", "text/html; charset=utf-8");
574
+ requestEv.cacheControl({ noCache: true });
575
+ requestEv.status(500);
576
+ }
577
+ const stream = requestEv.getWritableStream();
578
+ if (!stream.locked) {
579
+ const writer = stream.getWriter();
580
+ await writer.write(encoder.encode(minimalHtmlResponse(500, "Internal Server Error")));
581
+ await writer.close();
582
+ }
583
+ } catch {
584
+ console.error("Unable to render error page");
565
585
  }
566
- } catch {
567
- console.error("Unable to render error page");
568
586
  }
587
+ return e;
569
588
  }
570
- return e;
571
589
  }
590
+ return void 0;
591
+ }
592
+ try {
593
+ return await _runNext();
572
594
  } finally {
573
595
  if (!requestEv.isDirty()) {
574
596
  resolve(null);
575
597
  }
576
598
  }
577
- return void 0;
578
599
  }
579
600
  function getRouteMatchPathname(pathname, trailingSlash) {
580
601
  if (pathname.endsWith(QDATA_JSON)) {
@@ -600,7 +621,8 @@ var RequestRouteName = "@routeName";
600
621
  var RequestEvSharedActionId = "@actionId";
601
622
  var RequestEvSharedActionFormData = "@actionFormData";
602
623
  var RequestEvSharedNonce = "@nonce";
603
- function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manifest, trailingSlash, basePathname, qwikSerializer, resolved) {
624
+ var RequestEvIsRewrite = "@rewrite";
625
+ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trailingSlash, basePathname, qwikSerializer, resolved) {
604
626
  const { request, platform, env } = serverRequestEv;
605
627
  const sharedMap = /* @__PURE__ */ new Map();
606
628
  const cookie = new Cookie(request.headers.get("cookie"));
@@ -613,7 +635,6 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
613
635
  }
614
636
  sharedMap.set(IsQData, true);
615
637
  }
616
- sharedMap.set("@manifest", manifest);
617
638
  let routeModuleIndex = -1;
618
639
  let writableStream = null;
619
640
  let requestData = void 0;
@@ -631,6 +652,13 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
631
652
  routeModuleIndex++;
632
653
  }
633
654
  };
655
+ const resetRoute = (_loadedRoute, _requestHandlers, _url = url) => {
656
+ loadedRoute = _loadedRoute;
657
+ requestHandlers = _requestHandlers;
658
+ url.pathname = _url.pathname;
659
+ url.search = _url.search;
660
+ routeModuleIndex = -1;
661
+ };
634
662
  const check = () => {
635
663
  if (writableStream !== null) {
636
664
  throw new Error("Response already sent");
@@ -665,11 +693,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
665
693
  const writableStream2 = requestEv.getWritableStream();
666
694
  statusOrResponse.body.pipeTo(writableStream2);
667
695
  } else {
668
- if (status >= 300 && status < 400) {
669
- return new RedirectMessage();
670
- } else {
671
- requestEv.getWritableStream().getWriter().close();
672
- }
696
+ requestEv.getWritableStream().getWriter().close();
673
697
  }
674
698
  }
675
699
  return exit();
@@ -683,17 +707,26 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
683
707
  [RequestEvLoaders]: loaders,
684
708
  [RequestEvMode]: serverRequestEv.mode,
685
709
  [RequestEvTrailingSlash]: trailingSlash,
686
- [RequestEvRoute]: loadedRoute,
710
+ get [RequestEvRoute]() {
711
+ return loadedRoute;
712
+ },
687
713
  [RequestEvQwikSerializer]: qwikSerializer,
688
714
  cookie,
689
715
  headers,
690
716
  env,
691
717
  method: request.method,
692
718
  signal: request.signal,
693
- params: (loadedRoute == null ? void 0 : loadedRoute[1]) ?? {},
694
- pathname: url.pathname,
719
+ originalUrl: new URL(url),
720
+ get params() {
721
+ return (loadedRoute == null ? void 0 : loadedRoute[1]) ?? {};
722
+ },
723
+ get pathname() {
724
+ return url.pathname;
725
+ },
695
726
  platform,
696
- query: url.searchParams,
727
+ get query() {
728
+ return url.searchParams;
729
+ },
697
730
  request,
698
731
  url,
699
732
  basePathname,
@@ -708,6 +741,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
708
741
  return serverRequestEv.getClientConn();
709
742
  },
710
743
  next,
744
+ resetRoute,
711
745
  exit,
712
746
  cacheControl: (cacheControl, target = "Cache-Control") => {
713
747
  check();
@@ -740,7 +774,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
740
774
  },
741
775
  error: (statusCode, message) => {
742
776
  status = statusCode;
743
- return new ErrorResponse(statusCode, message);
777
+ return new ServerError(statusCode, message);
744
778
  },
745
779
  redirect: (statusCode, url2) => {
746
780
  check();
@@ -758,6 +792,14 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
758
792
  exit();
759
793
  return new RedirectMessage();
760
794
  },
795
+ rewrite: (pathname) => {
796
+ check();
797
+ if (pathname.startsWith("http")) {
798
+ throw new Error("Rewrite does not support absolute urls");
799
+ }
800
+ sharedMap.set(RequestEvIsRewrite, true);
801
+ return new RewriteMessage(pathname.replace(/\/+/g, "/"));
802
+ },
761
803
  defer: (returnData) => {
762
804
  return typeof returnData === "function" ? returnData : () => returnData;
763
805
  },
@@ -841,7 +883,7 @@ var parseRequest = async ({ request, method, query }, sharedMap, qwikSerializer)
841
883
  if (data) {
842
884
  try {
843
885
  return qwikSerializer._deserialize(decodeURIComponent(data));
844
- } catch (err) {
886
+ } catch {
845
887
  }
846
888
  }
847
889
  }
@@ -869,7 +911,7 @@ var formToObj = (formData) => {
869
911
 
870
912
  // packages/qwik-router/src/middleware/request-handler/response-page.ts
871
913
  function getQwikRouterServerData(requestEv) {
872
- const { url, params, request, status, locale } = requestEv;
914
+ const { params, request, status, locale, originalUrl } = requestEv;
873
915
  const requestHeaders = {};
874
916
  request.headers.forEach((value, key) => requestHeaders[key] = value);
875
917
  const action = requestEv.sharedMap.get(RequestEvSharedActionId);
@@ -877,7 +919,7 @@ function getQwikRouterServerData(requestEv) {
877
919
  const routeName = requestEv.sharedMap.get(RequestRouteName);
878
920
  const nonce = requestEv.sharedMap.get(RequestEvSharedNonce);
879
921
  const headers = requestEv.request.headers;
880
- const reconstructedUrl = new URL(url.pathname + url.search, url);
922
+ const reconstructedUrl = new URL(originalUrl.pathname + originalUrl.search, originalUrl);
881
923
  const host = headers.get("X-Forwarded-Host");
882
924
  const protocol = headers.get("X-Forwarded-Proto");
883
925
  if (host) {
@@ -1152,13 +1194,9 @@ async function pureServerFunction(ev) {
1152
1194
  }
1153
1195
  } catch (err) {
1154
1196
  if (err instanceof ServerError) {
1155
- ev.headers.set("Content-Type", "application/qwik-json");
1156
- ev.send(err.status, await qwikSerializer._serialize([err.data]));
1157
- return;
1197
+ throw ev.error(err.status, err.data);
1158
1198
  }
1159
- ev.headers.set("Content-Type", "application/qwik-json");
1160
- ev.send(500, await qwikSerializer._serialize([err]));
1161
- return;
1199
+ throw ev.error(500, "Invalid request");
1162
1200
  }
1163
1201
  if (isAsyncIterator(result)) {
1164
1202
  ev.headers.set("Content-Type", "text/qwik-json-stream");
@@ -1190,18 +1228,19 @@ async function pureServerFunction(ev) {
1190
1228
  }
1191
1229
  function fixTrailingSlash(ev) {
1192
1230
  const trailingSlash = getRequestTrailingSlash(ev);
1193
- const { basePathname, pathname, url, sharedMap } = ev;
1231
+ const { basePathname, originalUrl, sharedMap } = ev;
1232
+ const { pathname, search } = originalUrl;
1194
1233
  const isQData = sharedMap.has(IsQData);
1195
1234
  if (!isQData && pathname !== basePathname && !pathname.endsWith(".html")) {
1196
1235
  if (trailingSlash) {
1197
1236
  if (!pathname.endsWith("/")) {
1198
- throw ev.redirect(301 /* MovedPermanently */, pathname + "/" + url.search);
1237
+ throw ev.redirect(301 /* MovedPermanently */, pathname + "/" + search);
1199
1238
  }
1200
1239
  } else {
1201
1240
  if (pathname.endsWith("/")) {
1202
1241
  throw ev.redirect(
1203
1242
  301 /* MovedPermanently */,
1204
- pathname.slice(0, pathname.length - 1) + url.search
1243
+ pathname.slice(0, pathname.length - 1) + search
1205
1244
  );
1206
1245
  }
1207
1246
  }
@@ -1353,7 +1392,7 @@ async function renderQData(requestEv) {
1353
1392
  return;
1354
1393
  }
1355
1394
  const status = requestEv.status();
1356
- const location = requestEv.headers.get("Location");
1395
+ const redirectLocation = requestEv.headers.get("Location");
1357
1396
  const trailingSlash = getRequestTrailingSlash(requestEv);
1358
1397
  const requestHeaders = {};
1359
1398
  requestEv.request.headers.forEach((value, key) => requestHeaders[key] = value);
@@ -1363,7 +1402,8 @@ async function renderQData(requestEv) {
1363
1402
  action: requestEv.sharedMap.get(RequestEvSharedActionId),
1364
1403
  status: status !== 200 ? status : 200,
1365
1404
  href: getPathname(requestEv.url, trailingSlash),
1366
- redirect: location ?? void 0
1405
+ redirect: redirectLocation ?? void 0,
1406
+ isRewrite: requestEv.sharedMap.get(RequestEvIsRewrite)
1367
1407
  };
1368
1408
  const writer = requestEv.getWritableStream().getWriter();
1369
1409
  const qwikSerializer = requestEv[RequestEvQwikSerializer];
@@ -1406,7 +1446,7 @@ function isContentType(headers, ...types) {
1406
1446
 
1407
1447
  // packages/qwik-router/src/middleware/request-handler/request-handler.ts
1408
1448
  async function requestHandler(serverRequestEv, opts, qwikSerializer) {
1409
- const { render, qwikRouterConfig, manifest, checkOrigin } = opts;
1449
+ const { render, qwikRouterConfig, checkOrigin } = opts;
1410
1450
  if (!qwikRouterConfig) {
1411
1451
  throw new Error("qwikRouterConfig is required.");
1412
1452
  }
@@ -1421,11 +1461,27 @@ async function requestHandler(serverRequestEv, opts, qwikSerializer) {
1421
1461
  );
1422
1462
  if (routeAndHandlers) {
1423
1463
  const [route, requestHandlers] = routeAndHandlers;
1464
+ const rebuildRouteInfo = async (url) => {
1465
+ const matchPathname2 = getRouteMatchPathname(url.pathname, qwikRouterConfig.trailingSlash);
1466
+ const routeAndHandlers2 = await loadRequestHandlers(
1467
+ qwikRouterConfig,
1468
+ matchPathname2,
1469
+ serverRequestEv.request.method,
1470
+ checkOrigin ?? true,
1471
+ render
1472
+ );
1473
+ if (routeAndHandlers2) {
1474
+ const [loadedRoute, requestHandlers2] = routeAndHandlers2;
1475
+ return { loadedRoute, requestHandlers: requestHandlers2 };
1476
+ } else {
1477
+ return { loadedRoute: null, requestHandlers: [] };
1478
+ }
1479
+ };
1424
1480
  return runQwikRouter(
1425
1481
  serverRequestEv,
1426
1482
  route,
1427
1483
  requestHandlers,
1428
- manifest,
1484
+ rebuildRouteInfo,
1429
1485
  qwikRouterConfig.trailingSlash,
1430
1486
  qwikRouterConfig.basePathname,
1431
1487
  qwikSerializer
@@ -1505,6 +1561,7 @@ var _TextEncoderStream_polyfill = class {
1505
1561
  export {
1506
1562
  AbortMessage,
1507
1563
  RedirectMessage,
1564
+ RewriteMessage,
1508
1565
  ServerError,
1509
1566
  _TextEncoderStream_polyfill,
1510
1567
  getErrorHtml,
@@ -1,26 +1,26 @@
1
- import type { ServerRenderOptions } from '@qwik.dev/router/middleware/request-handler';
2
-
3
- /**
4
- * @deprecated Use `createQwikRouter` instead. Will be removed in V3
5
- * @public
6
- */
7
- export declare const createQwikCity: typeof createQwikRouter;
8
-
9
- /** @public */
10
- export declare function createQwikRouter(opts: QwikRouterVercelEdgeOptions): (request: Request) => Promise<Response>;
11
-
12
- /** @public */
13
- export declare interface PlatformVercel {
14
- }
15
-
16
- /**
17
- * @deprecated Use `QwikRouterVercelEdgeOptions` instead. Will be removed in V3
18
- * @public
19
- */
20
- export declare type QwikCityVercelEdgeOptions = QwikRouterVercelEdgeOptions;
21
-
22
- /** @public */
23
- export declare interface QwikRouterVercelEdgeOptions extends ServerRenderOptions {
24
- }
25
-
26
- export { }
1
+ import type { ServerRenderOptions } from '@qwik.dev/router/middleware/request-handler';
2
+
3
+ /**
4
+ * @deprecated Use `createQwikRouter` instead. Will be removed in V3
5
+ * @public
6
+ */
7
+ export declare const createQwikCity: typeof createQwikRouter;
8
+
9
+ /** @public */
10
+ export declare function createQwikRouter(opts: QwikRouterVercelEdgeOptions): (request: Request) => Promise<Response>;
11
+
12
+ /** @public */
13
+ export declare interface PlatformVercel {
14
+ }
15
+
16
+ /**
17
+ * @deprecated Use `QwikRouterVercelEdgeOptions` instead. Will be removed in V3
18
+ * @public
19
+ */
20
+ export declare type QwikCityVercelEdgeOptions = QwikRouterVercelEdgeOptions;
21
+
22
+ /** @public */
23
+ export declare interface QwikRouterVercelEdgeOptions extends ServerRenderOptions {
24
+ }
25
+
26
+ export { }