@bool-ts/core 1.7.16 → 1.7.17

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.
@@ -25,6 +25,7 @@ export type TBoolFactoryOptions = Required<{
25
25
  path: string;
26
26
  }> & Partial<{
27
27
  headers: Record<string, string>;
28
+ cacheTimeInSeconds: number;
28
29
  }>;
29
30
  cors: Partial<{
30
31
  credentials: boolean;
@@ -2,10 +2,12 @@ import "colors";
2
2
  import "reflect-metadata";
3
3
  import Qs from "qs";
4
4
  import * as Zod from "zod";
5
+ import { ETimeUnit, add as TimeAdd } from "@bool-ts/date-time";
5
6
  import { Router, RouterGroup } from "../entities";
6
7
  import { HttpClientError, HttpServerError, jsonErrorInfer } from "../http";
7
8
  import { argumentsKey, configKey, contextArgsKey, controllerHttpKey, controllerKey, moduleKey, paramArgsKey, paramsArgsKey, queryArgsKey, requestArgsKey, requestBodyArgsKey, requestHeaderArgsKey, requestHeadersArgsKey, responseBodyArgsKey, responseHeadersArgsKey, routeModelArgsKey } from "../keys";
8
9
  import { Injector } from "./injector";
10
+ const DEFAULT_STATIC_CACHE_TIME_IN_SECONDS = 900;
9
11
  export const responseConverter = (response) => {
10
12
  response.headers.set("X-Powered-By", "Bool Typescript");
11
13
  return response;
@@ -567,6 +569,7 @@ const fetcher = async (bun, bool) => {
567
569
  };
568
570
  export const BoolFactory = async (modules, options) => {
569
571
  try {
572
+ const staticMap = new Map();
570
573
  const modulesConverted = !Array.isArray(modules) ? [modules] : modules;
571
574
  const { allowLogsMethods, staticOption, allowOrigins, allowMethods, allowCredentials, allowHeaders } = Object.freeze({
572
575
  allowLogsMethods: options?.log?.methods,
@@ -625,20 +628,52 @@ export const BoolFactory = async (modules, options) => {
625
628
  }));
626
629
  }
627
630
  if (staticOption) {
628
- const file = Bun.file(`${staticOption.path}/${url.pathname}`);
629
- const isFileExists = await file.exists();
630
- if (isFileExists) {
631
- if (staticOption.headers) {
632
- for (const [key, value] of Object.entries(staticOption.headers)) {
633
- responseHeaders.set(key, value);
631
+ const { path, headers, cacheTimeInSeconds } = staticOption;
632
+ const pathname = `${path}/${url.pathname}`;
633
+ const cachedFile = staticMap.get(pathname);
634
+ if (!cachedFile) {
635
+ const file = Bun.file(pathname);
636
+ const isFileExists = await file.exists();
637
+ if (isFileExists) {
638
+ if (headers) {
639
+ for (const [key, value] of Object.entries(headers)) {
640
+ responseHeaders.set(key, value);
641
+ }
634
642
  }
643
+ responseHeaders.set("Content-Type", file.type);
644
+ return responseConverter(new Response(await file.arrayBuffer(), {
645
+ status: 200,
646
+ statusText: "SUCCESS",
647
+ headers: responseHeaders
648
+ }));
649
+ }
650
+ }
651
+ else {
652
+ const isExpired = new Date() > cachedFile.expiredAt;
653
+ if (isExpired) {
654
+ staticMap.delete(pathname);
655
+ }
656
+ const file = !isExpired ? cachedFile.file : Bun.file(pathname);
657
+ const isFileExists = await file.exists();
658
+ if (isFileExists) {
659
+ staticMap.set(pathname, Object.freeze({
660
+ expiredAt: TimeAdd(new Date(), typeof cacheTimeInSeconds !== "number"
661
+ ? DEFAULT_STATIC_CACHE_TIME_IN_SECONDS
662
+ : cacheTimeInSeconds, ETimeUnit.seconds),
663
+ file: file
664
+ }));
665
+ if (headers) {
666
+ for (const [key, value] of Object.entries(headers)) {
667
+ responseHeaders.set(key, value);
668
+ }
669
+ }
670
+ responseHeaders.set("Content-Type", file.type);
671
+ return responseConverter(new Response(await file.arrayBuffer(), {
672
+ status: 200,
673
+ statusText: "SUCCESS",
674
+ headers: responseHeaders
675
+ }));
635
676
  }
636
- responseHeaders.set("Content-Type", file.type);
637
- return responseConverter(new Response(await file.arrayBuffer(), {
638
- status: 200,
639
- statusText: "SUCCESS",
640
- headers: responseHeaders
641
- }));
642
677
  }
643
678
  }
644
679
  let collection;
@@ -657,7 +692,11 @@ export const BoolFactory = async (modules, options) => {
657
692
  httpCode: 404,
658
693
  message: "Route not found",
659
694
  data: undefined
660
- })));
695
+ }), {
696
+ status: 404,
697
+ statusText: "Not found.",
698
+ headers: responseHeaders
699
+ }));
661
700
  }
662
701
  return await fetcher({
663
702
  request,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bool-ts/core",
3
- "version": "1.7.16",
3
+ "version": "1.7.17",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "homepage": "https://github.com/BoolTS/core#readme",
20
20
  "dependencies": {
21
+ "@bool-ts/date-time": "^1.0.0",
21
22
  "colors": "^1.4.0",
22
23
  "qs": "^6.13.0",
23
24
  "reflect-metadata": "^0.2.2",
@@ -8,7 +8,8 @@ import "reflect-metadata";
8
8
  import Qs from "qs";
9
9
  import * as Zod from "zod";
10
10
 
11
- import type { Server } from "bun";
11
+ import { ETimeUnit, add as TimeAdd } from "@bool-ts/date-time";
12
+ import type { BunFile, Server } from "bun";
12
13
  import { Router, RouterGroup } from "../entities";
13
14
  import { HttpClientError, HttpServerError, jsonErrorInfer, type THttpMethods } from "../http";
14
15
  import {
@@ -57,6 +58,7 @@ export type TBoolFactoryOptions = Required<{
57
58
  }> &
58
59
  Partial<{
59
60
  headers: Record<string, string>;
61
+ cacheTimeInSeconds: number;
60
62
  }>;
61
63
  cors: Partial<{
62
64
  credentials: boolean;
@@ -66,6 +68,8 @@ export type TBoolFactoryOptions = Required<{
66
68
  }>;
67
69
  }>;
68
70
 
71
+ const DEFAULT_STATIC_CACHE_TIME_IN_SECONDS = 900;
72
+
69
73
  export const responseConverter = (response: Response) => {
70
74
  response.headers.set("X-Powered-By", "Bool Typescript");
71
75
 
@@ -926,7 +930,16 @@ const fetcher = async (
926
930
 
927
931
  export const BoolFactory = async (modules: Object | Array<Object>, options: TBoolFactoryOptions) => {
928
932
  try {
933
+ const staticMap: Map<
934
+ string,
935
+ Readonly<{
936
+ expiredAt: Date;
937
+ file: BunFile;
938
+ }>
939
+ > = new Map();
940
+
929
941
  const modulesConverted = !Array.isArray(modules) ? [modules] : modules;
942
+
930
943
  const { allowLogsMethods, staticOption, allowOrigins, allowMethods, allowCredentials, allowHeaders } = Object.freeze({
931
944
  allowLogsMethods: options?.log?.methods,
932
945
  staticOption: options.static,
@@ -1005,25 +1018,72 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
1005
1018
  }
1006
1019
 
1007
1020
  if (staticOption) {
1008
- const file = Bun.file(`${staticOption.path}/${url.pathname}`);
1009
- const isFileExists = await file.exists();
1010
-
1011
- if (isFileExists) {
1012
- if (staticOption.headers) {
1013
- for (const [key, value] of Object.entries(staticOption.headers)) {
1014
- responseHeaders.set(key, value);
1021
+ const { path, headers, cacheTimeInSeconds } = staticOption;
1022
+ const pathname = `${path}/${url.pathname}`;
1023
+ const cachedFile = staticMap.get(pathname);
1024
+
1025
+ if (!cachedFile) {
1026
+ const file = Bun.file(pathname);
1027
+ const isFileExists = await file.exists();
1028
+
1029
+ if (isFileExists) {
1030
+ if (headers) {
1031
+ for (const [key, value] of Object.entries(headers)) {
1032
+ responseHeaders.set(key, value);
1033
+ }
1015
1034
  }
1035
+
1036
+ responseHeaders.set("Content-Type", file.type);
1037
+
1038
+ return responseConverter(
1039
+ new Response(await file.arrayBuffer(), {
1040
+ status: 200,
1041
+ statusText: "SUCCESS",
1042
+ headers: responseHeaders
1043
+ })
1044
+ );
1016
1045
  }
1046
+ } else {
1047
+ const isExpired = new Date() > cachedFile.expiredAt;
1017
1048
 
1018
- responseHeaders.set("Content-Type", file.type);
1049
+ if (isExpired) {
1050
+ staticMap.delete(pathname);
1051
+ }
1019
1052
 
1020
- return responseConverter(
1021
- new Response(await file.arrayBuffer(), {
1022
- status: 200,
1023
- statusText: "SUCCESS",
1024
- headers: responseHeaders
1025
- })
1026
- );
1053
+ const file = !isExpired ? cachedFile.file : Bun.file(pathname);
1054
+ const isFileExists = await file.exists();
1055
+
1056
+ if (isFileExists) {
1057
+ staticMap.set(
1058
+ pathname,
1059
+ Object.freeze({
1060
+ expiredAt: TimeAdd(
1061
+ new Date(),
1062
+ typeof cacheTimeInSeconds !== "number"
1063
+ ? DEFAULT_STATIC_CACHE_TIME_IN_SECONDS
1064
+ : cacheTimeInSeconds,
1065
+ ETimeUnit.seconds
1066
+ ),
1067
+ file: file
1068
+ })
1069
+ );
1070
+
1071
+ if (headers) {
1072
+ for (const [key, value] of Object.entries(headers)) {
1073
+ responseHeaders.set(key, value);
1074
+ }
1075
+ }
1076
+
1077
+ responseHeaders.set("Content-Type", file.type);
1078
+
1079
+ return responseConverter(
1080
+ new Response(await file.arrayBuffer(), {
1081
+ status: 200,
1082
+ statusText: "SUCCESS",
1083
+ headers: responseHeaders
1084
+ })
1085
+ );
1086
+ }
1027
1087
  }
1028
1088
  }
1029
1089
 
@@ -1056,7 +1116,12 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
1056
1116
  httpCode: 404,
1057
1117
  message: "Route not found",
1058
1118
  data: undefined
1059
- })
1119
+ }),
1120
+ {
1121
+ status: 404,
1122
+ statusText: "Not found.",
1123
+ headers: responseHeaders
1124
+ }
1060
1125
  )
1061
1126
  );
1062
1127
  }
package/bun.lockb DELETED
Binary file