@bool-ts/core 1.7.15 → 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;
@@ -66,5 +67,5 @@ export declare const moduleResolution: (module: new (...args: any[]) => unknown,
66
67
  }>[];
67
68
  routerGroup: RouterGroup;
68
69
  }> | undefined>;
69
- export declare const BoolFactory: (modules: new (...args: any[]) => unknown | Array<new (...args: any[]) => unknown>, options: TBoolFactoryOptions) => Promise<void>;
70
+ export declare const BoolFactory: (modules: Object | Array<Object>, options: TBoolFactoryOptions) => Promise<void>;
70
71
  export default BoolFactory;
@@ -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.15",
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
 
@@ -924,12 +928,18 @@ const fetcher = async (
924
928
  );
925
929
  };
926
930
 
927
- export const BoolFactory = async (
928
- modules: new (...args: any[]) => unknown | Array<new (...args: any[]) => unknown>,
929
- options: TBoolFactoryOptions
930
- ) => {
931
+ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoolFactoryOptions) => {
931
932
  try {
933
+ const staticMap: Map<
934
+ string,
935
+ Readonly<{
936
+ expiredAt: Date;
937
+ file: BunFile;
938
+ }>
939
+ > = new Map();
940
+
932
941
  const modulesConverted = !Array.isArray(modules) ? [modules] : modules;
942
+
933
943
  const { allowLogsMethods, staticOption, allowOrigins, allowMethods, allowCredentials, allowHeaders } = Object.freeze({
934
944
  allowLogsMethods: options?.log?.methods,
935
945
  staticOption: options.static,
@@ -1008,25 +1018,72 @@ export const BoolFactory = async (
1008
1018
  }
1009
1019
 
1010
1020
  if (staticOption) {
1011
- const file = Bun.file(`${staticOption.path}/${url.pathname}`);
1012
- const isFileExists = await file.exists();
1013
-
1014
- if (isFileExists) {
1015
- if (staticOption.headers) {
1016
- for (const [key, value] of Object.entries(staticOption.headers)) {
1017
- 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
+ }
1018
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
+ );
1045
+ }
1046
+ } else {
1047
+ const isExpired = new Date() > cachedFile.expiredAt;
1048
+
1049
+ if (isExpired) {
1050
+ staticMap.delete(pathname);
1019
1051
  }
1020
1052
 
1021
- responseHeaders.set("Content-Type", file.type);
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
+ }
1022
1076
 
1023
- return responseConverter(
1024
- new Response(await file.arrayBuffer(), {
1025
- status: 200,
1026
- statusText: "SUCCESS",
1027
- headers: responseHeaders
1028
- })
1029
- );
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
+ }
1030
1087
  }
1031
1088
  }
1032
1089
 
@@ -1059,7 +1116,12 @@ export const BoolFactory = async (
1059
1116
  httpCode: 404,
1060
1117
  message: "Route not found",
1061
1118
  data: undefined
1062
- })
1119
+ }),
1120
+ {
1121
+ status: 404,
1122
+ statusText: "Not found.",
1123
+ headers: responseHeaders
1124
+ }
1063
1125
  )
1064
1126
  );
1065
1127
  }
package/bun.lockb DELETED
Binary file