revojs 0.0.46 → 0.0.48

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.
@@ -11,19 +11,19 @@ export type ClientConfig = {
11
11
  export type ServerConfig = {
12
12
  entry: ServerEntry;
13
13
  };
14
- export type DevelopmentConfig<T> = {
15
- middleware: Array<Middleware<T>>;
14
+ export type DevelopmentConfig = {
15
+ middleware: Array<Middleware>;
16
16
  };
17
- export type Config<T> = {
17
+ export type Config = {
18
18
  client: ClientConfig;
19
19
  server: false | ServerConfig;
20
20
  markdown: Record<string, Template>;
21
- dev: DevelopmentConfig<T>;
21
+ dev: DevelopmentConfig;
22
22
  };
23
- export type App<T> = {
24
- config: Config<T>;
23
+ export type App = {
24
+ config: Config;
25
25
  virtuals: Record<string, (environment: Environment) => string>;
26
26
  };
27
- export declare const createApp: <T>(config?: NestedPartial<Config<T>>) => App<T>;
27
+ export declare const createApp: <T>(config?: NestedPartial<Config>) => App;
28
28
  export declare const SERVER = "ssr";
29
29
  export declare const CLIENT = "client";
@@ -1,3 +1,4 @@
1
+ import { Scope } from "../signals";
1
2
  export type CookieOptions = {
2
3
  domain?: string;
3
4
  expires?: Date;
@@ -12,31 +13,21 @@ export type HttpMethod = "GET" | "HEAD" | "PATCH" | "POST" | "PUT" | "DELETE" |
12
13
  export type Encoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex";
13
14
  export type StatusCode = 100 | 101 | 102 | 103 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 304 | 305 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 444 | 450 | 451 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 506 | 507 | 508 | 509 | 510 | 511 | 521 | 522 | 523 | 525 | 530 | 599;
14
15
  export type MimeType = "text/plain" | "text/css" | "text/html" | "text/csv" | "text/javascript" | "application/json" | "application/xml" | "image/jpeg" | "image/png" | "image/gif" | "image/webp" | "image/svg+xml" | "image/bmp" | "image/x-icon" | "font/ttf" | "font/otf" | "font/woff" | "font/woff2" | "audio/mpeg" | "audio/wav" | "audio/ogg" | "audio/mp4" | "video/mp4" | "video/webm" | "video/ogg" | "video/quicktime" | "video/x-msvideo" | "application/zip" | "application/vnd.rar" | "application/x-tar" | "application/gzip" | "application/x-7z-compressed" | "application/pdf" | "application/msword" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | "application/vnd.ms-excel" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | "application/vnd.ms-powerpoint" | "application/vnd.openxmlformats-officedocument.presentationml.presentation" | "application/vnd.microsoft.portable-executable" | "application/vnd.android.package-archive";
15
- export type Context<T> = {
16
- inputs: Record<string, string>;
17
- variables: T;
18
- };
19
- export type Set = {
16
+ export type ResponseOptions = {
20
17
  status?: StatusCode;
21
18
  message?: string;
22
19
  headers: Headers;
23
20
  };
24
- export type Event<T = Record<string, unknown>> = {
25
- request: Request;
26
- response: Set;
27
- context: Context<T>;
28
- };
29
- export type Handle<T> = (event: Event<T>) => void | Response | Promise<void | Response>;
30
- export type Middleware<T> = (event: Event<T>, next: Handle<T>) => void | Response | Promise<void | Response>;
31
- export declare const createEvent: <T>(request: Request, context: Context<T>) => Event<T>;
32
- export declare const sendText: <T>(event: Event<T>, text: string) => Response;
33
- export declare const sendHtml: <T>(event: Event<T>, text: string) => Response;
34
- export declare const sendJson: <TValue, T>(event: Event<T>, value: TValue) => Response;
35
- export declare const sendRedirect: <T>(event: Event<T>, path: string) => Response;
36
- export declare const sendBadRequest: <T>(event: Event<T>, text: string) => Response;
37
- export declare const sendUnauthorized: <T>(event: Event<T>) => Response;
38
- export declare const getRequestUrl: <T>(event: Event<T> | Request) => URL;
39
- export declare const getCookies: <T>(event: Event<T>) => Record<string, string>;
40
- export declare const getSetCookies: <T>(event: Event<T>) => Record<string, string>;
41
- export declare const setCookie: <T>(event: Event<T>, name: string, value: string, options?: CookieOptions) => void;
21
+ export type Handle = (scope: Scope) => void | Response | Promise<void | Response>;
22
+ export type Middleware = (scope: Scope, next: Handle) => void | Response | Promise<void | Response>;
23
+ export declare const sendText: (scope: Scope, text: string) => Response;
24
+ export declare const sendHtml: (scope: Scope, text: string) => Response;
25
+ export declare const sendJson: <T>(scope: Scope, value: T) => Response;
26
+ export declare const sendRedirect: (scope: Scope, path: string) => Response;
27
+ export declare const sendBadRequest: (scope: Scope, text: string) => Response;
28
+ export declare const sendUnauthorized: (scope: Scope) => Response;
29
+ export declare const getRequestUrl: (scope: Scope, base?: string) => URL;
30
+ export declare const getCookies: (scope: Scope) => Record<string, string>;
31
+ export declare const getSetCookies: (scope: Scope) => Record<string, string>;
32
+ export declare const setCookie: (scope: Scope, name: string, value: string, options?: CookieOptions) => void;
42
33
  export declare const getMimeType: (file: string) => MimeType;
package/dist/index.js CHANGED
@@ -476,121 +476,6 @@ const stopImmediatePropagation = (event) => event.stopImmediatePropagation();
476
476
  const components = new Map();
477
477
  const HOST_CONTEXT = defineContext("HOST_CONTEXT");
478
478
 
479
- //#endregion
480
- //#region src/http/index.ts
481
- const createEvent = (request, context) => {
482
- return {
483
- request,
484
- response: { headers: new Headers() },
485
- context
486
- };
487
- };
488
- const sendText = (event, text) => {
489
- event.response.headers.set("Content-Type", "text/plain");
490
- return new Response(text, event.response);
491
- };
492
- const sendHtml = (event, text) => {
493
- event.response.headers.set("Content-Type", "text/html");
494
- return new Response(text, event.response);
495
- };
496
- const sendJson = (event, value) => {
497
- event.response.headers.set("Content-Type", "application/json");
498
- return new Response(JSON.stringify(value), event.response);
499
- };
500
- const sendRedirect = (event, path) => {
501
- event.response.status = 302;
502
- event.response.headers.set("Location", path);
503
- return new Response(null, event.response);
504
- };
505
- const sendBadRequest = (event, text) => {
506
- event.response.status = 400;
507
- return new Response(text, event.response);
508
- };
509
- const sendUnauthorized = (event) => {
510
- event.response.status = 401;
511
- return new Response(null, event.response);
512
- };
513
- const getRequestUrl = (event) => {
514
- return new URL(event instanceof Request ? event.url : event.request.url);
515
- };
516
- const getCookies = (event) => {
517
- const cookies = event.request.headers.get("Cookie")?.split("; ") ?? [];
518
- return cookies.reduce((result, cookie) => {
519
- const [name, value] = cookie.split("=");
520
- if (name && value) result[name] = decodeURIComponent(value);
521
- return result;
522
- }, {});
523
- };
524
- const getSetCookies = (event) => {
525
- const cookies = event.request.headers.getSetCookie();
526
- return cookies.reduce((result, cookie) => {
527
- const [name, value] = cookie.split("=");
528
- if (name && value) result[name] = decodeURIComponent(value);
529
- return result;
530
- }, {});
531
- };
532
- const setCookie = (event, name, value, options) => {
533
- let cookie = name + "=" + encodeURIComponent(value);
534
- if (options?.domain) cookie += `; Domain=${options.domain}`;
535
- if (options?.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
536
- if (options?.httpOnly) cookie += `; HttpOnly`;
537
- if (options?.maxAge) cookie += `; Max-Age=${options.maxAge}`;
538
- if (options?.path) cookie += `; Path=${options.path}`;
539
- if (options?.priority) cookie += `; Priority=${options.priority}`;
540
- if (options?.sameSite) cookie += `; SameSite=${options.sameSite}`;
541
- if (options?.secure) cookie += `; Secure`;
542
- event.response.headers.append("Set-Cookie", cookie);
543
- };
544
- const getMimeType = (file) => {
545
- const extension = /\.([a-zA-Z0-9]+?)$/.exec(file)?.at(1);
546
- return mimeTypes[extension ?? ""] ?? "text/plain";
547
- };
548
- const mimeTypes = {
549
- txt: "text/plain",
550
- css: "text/css",
551
- html: "text/html",
552
- htm: "text/html",
553
- js: "text/javascript",
554
- json: "application/json",
555
- xml: "application/xml",
556
- csv: "text/csv",
557
- jpg: "image/jpeg",
558
- jpeg: "image/jpeg",
559
- png: "image/png",
560
- gif: "image/gif",
561
- webp: "image/webp",
562
- svg: "image/svg+xml",
563
- bmp: "image/bmp",
564
- ico: "image/x-icon",
565
- ttf: "font/ttf",
566
- otf: "font/otf",
567
- woff: "font/woff",
568
- woff2: "font/woff2",
569
- mp3: "audio/mpeg",
570
- wav: "audio/wav",
571
- ogg: "audio/ogg",
572
- m4a: "audio/mp4",
573
- mp4: "video/mp4",
574
- webm: "video/webm",
575
- ogv: "video/ogg",
576
- mov: "video/quicktime",
577
- avi: "video/x-msvideo",
578
- zip: "application/zip",
579
- rar: "application/vnd.rar",
580
- tar: "application/x-tar",
581
- gz: "application/gzip",
582
- "7z": "application/x-7z-compressed",
583
- pdf: "application/pdf",
584
- doc: "application/msword",
585
- docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
586
- xls: "application/vnd.ms-excel",
587
- xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
588
- ppt: "application/vnd.ms-powerpoint",
589
- pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
590
- exe: "application/vnd.microsoft.portable-executable",
591
- apk: "application/vnd.android.package-archive"
592
- };
593
-
594
479
  //#endregion
595
480
  //#region src/radix/index.ts
596
481
  var Radix = class Radix {
@@ -633,8 +518,11 @@ var Radix = class Radix {
633
518
 
634
519
  //#endregion
635
520
  //#region src/runtime/index.ts
636
- const useRuntime = (scope, context) => {
637
- return scope.getContext(context ?? RUNTIME_CONTEXT);
521
+ const useRuntime = (scope) => {
522
+ return scope.getContext(RUNTIME_CONTEXT);
523
+ };
524
+ const useRoute = (scope) => {
525
+ return scope.getContext(ROUTE_CONTEXT);
638
526
  };
639
527
  const defineRoute = (route) => {
640
528
  return route;
@@ -648,22 +536,28 @@ const toPath = (value) => {
648
536
  const split = route.split(".");
649
537
  return split.length === 3 ? [split.at(0), split.at(1)] : [split.at(0)];
650
538
  };
651
- const $fetch = async (scope, input, init) => {
652
- const { event } = useRuntime(scope);
539
+ const $fetch = async (scope, input, options) => {
540
+ const { request, variables } = useRuntime(scope);
653
541
  let response;
654
- if (event) {
655
- const url = new URL(input.toString(), event.request.url);
656
- response = await (await import("#virtual/runtime")).runtime.fetch(new Request(url, init), event.context);
657
- } else response = await fetch(input, init);
542
+ if (request) {
543
+ const next = new Scope();
544
+ const url = new URL(input.toString(), request.url);
545
+ next.setContext(RUNTIME_CONTEXT, {
546
+ request: new Request(url, options),
547
+ response: { headers: new Headers() },
548
+ variables
549
+ });
550
+ const previous = new URL(request.url);
551
+ if (url.origin === previous.origin) response = await (await import("#virtual/runtime")).runtime.fetch(next);
552
+ }
553
+ response ??= await fetch(input, options);
658
554
  if (response.ok === false) throw response;
659
- switch (response.headers.get("Content-Type")) {
555
+ const contentType = response.headers.get("Content-Type")?.split(";").shift() ?? "";
556
+ switch (contentType) {
660
557
  case "application/json": return response.json();
661
558
  default: return response;
662
559
  }
663
560
  };
664
- const getVariables = (event) => {
665
- return event ? event.context.variables : import.meta.env;
666
- };
667
561
  const createRuntime = async () => {
668
562
  const radix = new Radix();
669
563
  const middlewares = new Array();
@@ -673,41 +567,32 @@ const createRuntime = async () => {
673
567
  radix.insert((method ?? "GET").toUpperCase() + name, defineRoute({ fetch: async (event) => {
674
568
  const route = await routes[path]?.();
675
569
  if (typeof route === "object") return route.fetch(event);
676
- if (route) {
677
- const scope = new Scope();
678
- try {
679
- scope.setContext(RUNTIME_CONTEXT, { event });
680
- return sendHtml(event, await renderToString(scope, await import("#virtual/client").then((module) => module.client)));
681
- } finally {
682
- scope.stop();
683
- }
684
- }
570
+ if (route) return sendHtml(event, await renderToString(event, await import("#virtual/client").then((module) => module.client)));
685
571
  } }));
686
572
  }
687
573
  const assets = await import("#virtual/assets").then((module) => module.assets);
688
- for (const path in assets) radix.insert("GET/" + path, defineRoute({ fetch: async (event) => {
689
- event.response.headers.set("Content-Type", getMimeType(path));
690
- return new Response(await assets[path]?.(), event.response);
574
+ for (const path in assets) radix.insert("GET/" + path, defineRoute({ fetch: async (scope) => {
575
+ const { response } = useRuntime(scope);
576
+ response.headers.set("Content-Type", getMimeType(path));
577
+ return new Response(await assets[path]?.(), response);
691
578
  } }));
692
- const invoke = (event, next, index) => {
693
- return middlewares.at(index)?.(event, () => invoke(event, next, index + 1)) ?? next(event);
579
+ const invoke = (scope, next, index) => {
580
+ return middlewares.at(index)?.(scope, () => invoke(scope, next, index + 1)) ?? next(scope);
694
581
  };
695
582
  return {
696
583
  radix,
697
584
  middlewares,
698
- fetch: async (request, context) => {
699
- const url = getRequestUrl(request);
585
+ fetch: async (scope) => {
586
+ const { request } = useRuntime(scope);
587
+ const url = getRequestUrl(scope);
700
588
  const { value: route, inputs } = radix.match(request.method + url.pathname);
701
- const event = createEvent(request, {
702
- ...context,
703
- inputs
704
- });
705
589
  try {
590
+ scope.setContext(ROUTE_CONTEXT, { inputs: createState(inputs) });
706
591
  if (route) {
707
- const response = await invoke(event, route.fetch, 0);
592
+ const response = await invoke(scope, route.fetch, 0);
708
593
  if (response) return response;
709
594
  }
710
- return sendText(event, "Not found");
595
+ return sendText(scope, "NOT_FOUND");
711
596
  } catch (exception) {
712
597
  if (exception instanceof Response) return exception;
713
598
  throw exception;
@@ -716,6 +601,123 @@ const createRuntime = async () => {
716
601
  };
717
602
  };
718
603
  const RUNTIME_CONTEXT = defineContext("RUNTIME_CONTEXT");
604
+ const ROUTE_CONTEXT = defineContext("ROUTE_CONTEXT");
605
+
606
+ //#endregion
607
+ //#region src/http/index.ts
608
+ const sendText = (scope, text) => {
609
+ const { response } = useRuntime(scope);
610
+ response.headers.set("Content-Type", "text/plain");
611
+ return new Response(text, response);
612
+ };
613
+ const sendHtml = (scope, text) => {
614
+ const { response } = useRuntime(scope);
615
+ response.headers.set("Content-Type", "text/html");
616
+ return new Response(text, response);
617
+ };
618
+ const sendJson = (scope, value) => {
619
+ const { response } = useRuntime(scope);
620
+ response.headers.set("Content-Type", "application/json");
621
+ return new Response(JSON.stringify(value), response);
622
+ };
623
+ const sendRedirect = (scope, path) => {
624
+ const { response } = useRuntime(scope);
625
+ response.status = 302;
626
+ response.headers.set("Location", path);
627
+ return new Response(null, response);
628
+ };
629
+ const sendBadRequest = (scope, text) => {
630
+ const { response } = useRuntime(scope);
631
+ response.status = 400;
632
+ return new Response(text, response);
633
+ };
634
+ const sendUnauthorized = (scope) => {
635
+ const { response } = useRuntime(scope);
636
+ response.status = 401;
637
+ return new Response(null, response);
638
+ };
639
+ const getRequestUrl = (scope, base) => {
640
+ const { request } = useRuntime(scope);
641
+ return new URL(request.url, base);
642
+ };
643
+ const getCookies = (scope) => {
644
+ const { request } = useRuntime(scope);
645
+ return (request.headers.get("Cookie")?.split("; ") ?? []).reduce((result, cookie) => {
646
+ const [name, value] = cookie.split("=");
647
+ if (name && value) result[name] = decodeURIComponent(value);
648
+ return result;
649
+ }, {});
650
+ };
651
+ const getSetCookies = (scope) => {
652
+ const { request } = useRuntime(scope);
653
+ return request.headers.getSetCookie().reduce((result, cookie) => {
654
+ const [name, value] = cookie.split("=");
655
+ if (name && value) result[name] = decodeURIComponent(value);
656
+ return result;
657
+ }, {});
658
+ };
659
+ const setCookie = (scope, name, value, options) => {
660
+ const { response } = useRuntime(scope);
661
+ let cookie = name + "=" + encodeURIComponent(value);
662
+ if (options?.domain) cookie += `; Domain=${options.domain}`;
663
+ if (options?.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
664
+ if (options?.httpOnly) cookie += `; HttpOnly`;
665
+ if (options?.maxAge) cookie += `; Max-Age=${options.maxAge}`;
666
+ if (options?.path) cookie += `; Path=${options.path}`;
667
+ if (options?.priority) cookie += `; Priority=${options.priority}`;
668
+ if (options?.sameSite) cookie += `; SameSite=${options.sameSite}`;
669
+ if (options?.secure) cookie += `; Secure`;
670
+ response.headers.append("Set-Cookie", cookie);
671
+ };
672
+ const getMimeType = (file) => {
673
+ const extension = /\.([a-zA-Z0-9]+?)$/.exec(file)?.at(1);
674
+ return mimeTypes[extension ?? ""] ?? "text/plain";
675
+ };
676
+ const mimeTypes = {
677
+ txt: "text/plain",
678
+ css: "text/css",
679
+ html: "text/html",
680
+ htm: "text/html",
681
+ js: "text/javascript",
682
+ json: "application/json",
683
+ xml: "application/xml",
684
+ csv: "text/csv",
685
+ jpg: "image/jpeg",
686
+ jpeg: "image/jpeg",
687
+ png: "image/png",
688
+ gif: "image/gif",
689
+ webp: "image/webp",
690
+ svg: "image/svg+xml",
691
+ bmp: "image/bmp",
692
+ ico: "image/x-icon",
693
+ ttf: "font/ttf",
694
+ otf: "font/otf",
695
+ woff: "font/woff",
696
+ woff2: "font/woff2",
697
+ mp3: "audio/mpeg",
698
+ wav: "audio/wav",
699
+ ogg: "audio/ogg",
700
+ m4a: "audio/mp4",
701
+ mp4: "video/mp4",
702
+ webm: "video/webm",
703
+ ogv: "video/ogg",
704
+ mov: "video/quicktime",
705
+ avi: "video/x-msvideo",
706
+ zip: "application/zip",
707
+ rar: "application/vnd.rar",
708
+ tar: "application/x-tar",
709
+ gz: "application/gzip",
710
+ "7z": "application/x-7z-compressed",
711
+ pdf: "application/pdf",
712
+ doc: "application/msword",
713
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
714
+ xls: "application/vnd.ms-excel",
715
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
716
+ ppt: "application/vnd.ms-powerpoint",
717
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
718
+ exe: "application/vnd.microsoft.portable-executable",
719
+ apk: "application/vnd.android.package-archive"
720
+ };
719
721
 
720
722
  //#endregion
721
723
  //#region src/router/index.tsx
@@ -730,7 +732,6 @@ const createRouter = (options) => {
730
732
  const radix = new Radix();
731
733
  const url = createState();
732
734
  const route = createState();
733
- const inputs = createState();
734
735
  for (const path in options.routes) {
735
736
  const [name] = toPath(path);
736
737
  if (name) {
@@ -739,24 +740,22 @@ const createRouter = (options) => {
739
740
  }
740
741
  }
741
742
  const registerRouterContext = async (scope) => {
742
- const { event } = useRuntime(scope);
743
743
  const fetch$1 = async () => {
744
- url.value = new URL(event?.request.url ?? window?.location.href);
744
+ const { request } = useRuntime(scope);
745
+ url.value = new URL(request?.url ?? window?.location.href);
745
746
  const match = radix.match(url.value.pathname);
746
- inputs.value = match.inputs;
747
+ scope.setContext(ROUTE_CONTEXT, { inputs: createState(match.inputs) });
747
748
  const Page$1 = await match.value?.();
748
- if (Page$1) route.value = /* @__PURE__ */ h(Page$1, inputs.value);
749
+ if (Page$1) route.value = /* @__PURE__ */ h(Page$1, null);
749
750
  };
750
751
  if (isClient()) useEvent(scope, window, "popstate", () => navigator.dispatchEvent(new NavigateEvent()));
751
- if (event) inputs.value = event.context.inputs;
752
752
  await fetch$1().then(() => useEvent(scope, navigator, "navigate", fetch$1));
753
753
  scope.setContext(ROUTER_CONTEXT, {
754
754
  options,
755
755
  navigator,
756
756
  url,
757
757
  radix,
758
- route,
759
- inputs
758
+ route
760
759
  });
761
760
  return useRouter(scope);
762
761
  };
@@ -766,7 +765,7 @@ const createRouter = (options) => {
766
765
  };
767
766
  };
768
767
  const useRouter = (scope, context) => {
769
- const { url, route, inputs, navigator } = scope.getContext(context ?? ROUTER_CONTEXT);
768
+ const { url, route, navigator } = scope.getContext(context ?? ROUTER_CONTEXT);
770
769
  const navigate = (path) => {
771
770
  if (isClient()) {
772
771
  if (window.location.pathname != path) window.history.pushState(window.history.state, "", path);
@@ -780,7 +779,6 @@ const useRouter = (scope, context) => {
780
779
  return {
781
780
  url,
782
781
  route,
783
- inputs,
784
782
  navigator,
785
783
  navigate,
786
784
  anchorNavigate
@@ -801,10 +799,11 @@ const createLocale = (options) => {
801
799
  const locale = createState(options.defaultLocale);
802
800
  const messages = createState();
803
801
  const registerLocaleContext = async (scope) => {
804
- const { inputs, navigator } = useRouter(scope);
802
+ const { inputs } = useRoute(scope);
803
+ const { navigator } = useRouter(scope);
805
804
  const fetch$1 = async () => {
806
805
  if (options.input) {
807
- const input = inputs.value?.[options.input];
806
+ const input = inputs.value[options.input];
808
807
  if (input && input in options.locales) locale.value = input;
809
808
  }
810
809
  if (locale.value) {
@@ -935,4 +934,4 @@ const markdownToSlot = (input, options) => {
935
934
  };
936
935
 
937
936
  //#endregion
938
- export { $fetch, CLIENT, Compute, HOST_CONTEXT, Handler, LOCALE_CONTEXT, MountedEvent, NavigateEvent, Page, ROUTER_CONTEXT, RUNTIME_CONTEXT, Radix, SERVER, Scope, StopEvent, activeCompute, components, createApp, createCompute, createElement, createEvent, createLocale, createMemo, createRouter, createRuntime, createState, defineComponent, defineContext, defineRoute, fileName, fromValue, getCookies, getCustomElement, getMimeType, getRequestUrl, getSetCookies, getVariables, hydrate, isClient, isServer, isTemplate, markdownToSlot, preventDefault, registerComponent, renderToString, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, stopImmediatePropagation, stopPropagation, targets, toArray, toCustomElement, toFragment, toPath, toRange, toString, useEvent, useHost, useLocale, useRouter, useRuntime };
937
+ export { $fetch, CLIENT, Compute, HOST_CONTEXT, Handler, LOCALE_CONTEXT, MountedEvent, NavigateEvent, Page, ROUTER_CONTEXT, ROUTE_CONTEXT, RUNTIME_CONTEXT, Radix, SERVER, Scope, StopEvent, activeCompute, components, createApp, createCompute, createElement, createLocale, createMemo, createRouter, createRuntime, createState, defineComponent, defineContext, defineRoute, fileName, fromValue, getCookies, getCustomElement, getMimeType, getRequestUrl, getSetCookies, hydrate, isClient, isServer, isTemplate, markdownToSlot, preventDefault, registerComponent, renderToString, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, stopImmediatePropagation, stopPropagation, targets, toArray, toCustomElement, toFragment, toPath, toRange, toString, useEvent, useHost, useLocale, useRoute, useRouter, useRuntime };
@@ -1,12 +1,20 @@
1
+ import { RUNTIME_CONTEXT, Scope } from "./runtime-CnZe26-A.js";
1
2
  import { runtime } from "#virtual/runtime";
2
3
  import { serve } from "bun";
3
4
 
4
5
  //#region src/presets/bun.ts
5
6
  serve({ fetch: (request) => {
6
- return runtime.fetch(request, {
7
- inputs: {},
7
+ const scope = new Scope();
8
+ scope.setContext(RUNTIME_CONTEXT, {
9
+ request,
10
+ response: { headers: new Headers() },
8
11
  variables: process.env
9
12
  });
13
+ try {
14
+ return runtime.fetch(scope);
15
+ } finally {
16
+ scope.stop();
17
+ }
10
18
  } });
11
19
 
12
20
  //#endregion
@@ -1,4 +1,4 @@
1
1
  declare const _default: {
2
- fetch: <T>(request: Request, env: T) => Promise<Response>;
2
+ fetch: (request: Request, variables: Record<string, unknown>) => Promise<Response>;
3
3
  };
4
4
  export default _default;
@@ -1,11 +1,19 @@
1
+ import { RUNTIME_CONTEXT, Scope } from "./runtime-CnZe26-A.js";
1
2
  import { runtime } from "#virtual/runtime";
2
3
 
3
4
  //#region src/presets/cloudflare.ts
4
- var cloudflare_default = { fetch: (request, env) => {
5
- return runtime.fetch(request, {
6
- inputs: {},
7
- variables: env
5
+ var cloudflare_default = { fetch: (request, variables) => {
6
+ const scope = new Scope();
7
+ scope.setContext(RUNTIME_CONTEXT, {
8
+ request,
9
+ response: { headers: new Headers() },
10
+ variables
8
11
  });
12
+ try {
13
+ return runtime.fetch(scope);
14
+ } finally {
15
+ scope.stop();
16
+ }
9
17
  } };
10
18
 
11
19
  //#endregion
@@ -0,0 +1,49 @@
1
+ //#region src/signals/index.ts
2
+ var StopEvent = class extends Event {
3
+ constructor() {
4
+ super("stop");
5
+ }
6
+ };
7
+ var Scope = class extends EventTarget {
8
+ parentScope;
9
+ context;
10
+ constructor(scope) {
11
+ super();
12
+ this.parentScope = scope;
13
+ this.context = new Map();
14
+ }
15
+ getContext(input) {
16
+ let scope = this;
17
+ const seen = new Set();
18
+ while (scope && !seen.has(scope)) {
19
+ seen.add(scope);
20
+ if (scope.context.has(input)) return scope.context.get(input);
21
+ scope = scope.parentScope;
22
+ }
23
+ return {};
24
+ }
25
+ setContext(input, value) {
26
+ this.context.set(input, value);
27
+ }
28
+ onStop(input) {
29
+ this.addEventListener("stop", input, { once: true });
30
+ }
31
+ stop() {
32
+ return this.dispatchEvent(new StopEvent());
33
+ }
34
+ };
35
+ function defineContext(key) {
36
+ return key;
37
+ }
38
+
39
+ //#endregion
40
+ //#region src/html/index.ts
41
+ const HOST_CONTEXT = defineContext("HOST_CONTEXT");
42
+
43
+ //#endregion
44
+ //#region src/runtime/index.ts
45
+ const RUNTIME_CONTEXT = defineContext("RUNTIME_CONTEXT");
46
+ const ROUTE_CONTEXT = defineContext("ROUTE_CONTEXT");
47
+
48
+ //#endregion
49
+ export { RUNTIME_CONTEXT, Scope };
@@ -11,7 +11,6 @@ export type RouterContext<T extends RouterOptions = RouterOptions> = {
11
11
  url: State<URL | undefined>;
12
12
  radix: Radix<() => Promise<ComponentConstructor<Events, Attributes>>>;
13
13
  route: State<Slot | undefined>;
14
- inputs: State<Record<string, string> | undefined>;
15
14
  };
16
15
  export declare class NavigateEvent extends Event {
17
16
  constructor();
@@ -22,7 +21,6 @@ export declare const createRouter: <T extends RouterOptions>(options: T) => {
22
21
  registerRouterContext: (scope: Scope) => Promise<{
23
22
  url: State<URL | undefined>;
24
23
  route: State<unknown>;
25
- inputs: State<Record<string, string> | undefined>;
26
24
  navigator: EventTarget;
27
25
  navigate: (path: string) => void;
28
26
  anchorNavigate: (event: Event) => void;
@@ -31,7 +29,6 @@ export declare const createRouter: <T extends RouterOptions>(options: T) => {
31
29
  export declare const useRouter: <T extends RouterContext>(scope: Scope, context?: Descriptor<T>) => {
32
30
  url: State<URL | undefined>;
33
31
  route: State<unknown>;
34
- inputs: State<Record<string, string> | undefined>;
35
32
  navigator: EventTarget;
36
33
  navigate: (path: string) => void;
37
34
  anchorNavigate: (event: Event) => void;
@@ -1,22 +1,28 @@
1
- import { type Context, type Event, type Handle, type Middleware } from "../http";
1
+ import { type Handle, type Middleware, type ResponseOptions } from "../http";
2
2
  import { Radix } from "../radix";
3
- import { type Descriptor, Scope } from "../signals";
4
- export type Route<T> = {
5
- fetch: Handle<T>;
3
+ import { Scope, type State } from "../signals";
4
+ export type Route = {
5
+ fetch: Handle;
6
6
  };
7
- export type Runtime<T> = {
8
- radix: Radix<Route<T>>;
9
- middlewares: Array<Middleware<T>>;
10
- fetch: (request: Request, context: Context<T>) => Promise<Response>;
7
+ export type Runtime = {
8
+ radix: Radix<Route>;
9
+ middlewares: Array<Middleware>;
10
+ fetch: (scope: Scope) => Promise<Response>;
11
11
  };
12
12
  export type RuntimeContext<T = Record<string, unknown>> = {
13
- event?: Event<T>;
13
+ request: Request;
14
+ response: ResponseOptions;
15
+ variables: T;
14
16
  };
15
- export declare const useRuntime: <T extends RuntimeContext>(scope: Scope, context?: Descriptor<T>) => RuntimeContext<Record<string, unknown>>;
16
- export declare const defineRoute: <T>(route: Route<T>) => Route<T>;
17
+ export type RouteContext = {
18
+ inputs: State<Record<string, string>>;
19
+ };
20
+ export declare const useRuntime: (scope: Scope) => RuntimeContext<Record<string, unknown>>;
21
+ export declare const useRoute: (scope: Scope) => RouteContext;
22
+ export declare const defineRoute: (route: Route) => Route;
17
23
  export declare const fileName: (path: string) => string | undefined;
18
24
  export declare const toPath: (value: string) => (string | undefined)[];
19
- export declare const $fetch: <T>(scope: Scope, input: string | URL, init?: RequestInit) => Promise<T>;
20
- export declare const getVariables: <T>(event?: Event<T>) => T;
21
- export declare const createRuntime: <T>() => Promise<Runtime<T>>;
22
- export declare const RUNTIME_CONTEXT: Descriptor<RuntimeContext<Record<string, unknown>>>;
25
+ export declare const $fetch: <T>(scope: Scope, input: string | URL, options?: RequestInit) => Promise<T>;
26
+ export declare const createRuntime: () => Promise<Runtime>;
27
+ export declare const RUNTIME_CONTEXT: import("..").Descriptor<RuntimeContext<Record<string, unknown>>>;
28
+ export declare const ROUTE_CONTEXT: import("..").Descriptor<RouteContext>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "revojs",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "type": "module",
5
5
  "repository": "coverbase/revojs",
6
6
  "license": "MIT",
@@ -13,11 +13,11 @@ declare module "#virtual/client" {
13
13
  }
14
14
 
15
15
  declare module "#virtual/routes" {
16
- export const routes: Record<string, () => Promise<Route<T> | ComponentConstructor<Events, Attributes>>>;
16
+ export const routes: Record<string, () => Promise<Route | ComponentConstructor<Events, Attributes>>>;
17
17
  }
18
18
 
19
19
  declare module "#virtual/runtime" {
20
20
  import type { Runtime } from "revojs";
21
21
 
22
- export const runtime: Runtime<T>;
22
+ export const runtime: Runtime;
23
23
  }