Add error logs for server functions. Add cache dynamic function.

This commit is contained in:
Benjamin Toby 2026-03-27 05:22:31 +01:00
parent 572f739b5c
commit 950bdc3dca
10 changed files with 157 additions and 32 deletions

View File

@ -0,0 +1,10 @@
import type { BunextPageModule, BunextPageModuleServerReturn, BunxRouteParams } from "../../../types";
type Params = {
html: string;
module: BunextPageModule;
root_module?: BunextPageModule;
routeParams?: BunxRouteParams;
serverRes?: BunextPageModuleServerReturn<any, any>;
};
export default function generateWebPageGetCachePage({ module, routeParams, serverRes, root_module, html, }: Params): Promise<boolean>;
export {};

View File

@ -0,0 +1,29 @@
import _ from "lodash";
import { log } from "../../../utils/log";
import writeCache from "../../cache/write-cache";
export default async function generateWebPageGetCachePage({ module, routeParams, serverRes, root_module, html, }) {
const config = _.merge(root_module?.config, module.config);
const cache_page = config?.cachePage || serverRes?.cachePage || false;
const expiry_seconds = config?.cacheExpiry || serverRes?.cacheExpiry;
if (cache_page && routeParams?.url) {
try {
const is_cache = typeof cache_page == "boolean"
? cache_page
: await cache_page({ ctx: routeParams, serverRes });
if (!is_cache) {
return false;
}
const key = routeParams.url.pathname + (routeParams.url.search || "");
writeCache({
key,
value: html,
paradigm: "html",
expiry_seconds,
});
}
catch (error) {
log.error(`Error writing Cache => ${error.message}\n`, error);
}
}
return true;
}

View File

@ -1,9 +1,10 @@
import _ from "lodash"; import _ from "lodash";
import isDevelopment from "../../../utils/is-development"; import isDevelopment from "../../../utils/is-development";
import { log } from "../../../utils/log"; import { log } from "../../../utils/log";
import writeCache from "../../cache/write-cache";
import genWebHTML from "./generate-web-html"; import genWebHTML from "./generate-web-html";
import generateWebPageGetCachePage from "./generate-web-page-get-cache-page";
export default async function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, routeParams, serverRes, debug, root_module, }) { export default async function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, routeParams, serverRes, debug, root_module, }) {
const is_dev = isDevelopment();
const html = await genWebHTML({ const html = await genWebHTML({
component, component,
pageProps: serverRes, pageProps: serverRes,
@ -28,7 +29,7 @@ export default async function generateWebPageResponseFromComponentReturn({ compo
...serverRes?.responseOptions?.headers, ...serverRes?.responseOptions?.headers,
}, },
}; };
if (isDevelopment()) { if (is_dev) {
res_opts.headers = { res_opts.headers = {
...res_opts.headers, ...res_opts.headers,
"Cache-Control": "no-cache, no-store, must-revalidate", "Cache-Control": "no-cache, no-store, must-revalidate",
@ -36,16 +37,13 @@ export default async function generateWebPageResponseFromComponentReturn({ compo
Expires: "0", Expires: "0",
}; };
} }
const config = _.merge(root_module?.config, module.config); if (!is_dev) {
const cache_page = config?.cachePage || serverRes?.cachePage || false; await generateWebPageGetCachePage({
const expiry_seconds = config?.cacheExpiry || serverRes?.cacheExpiry; html,
if (cache_page && routeParams?.url) { module,
const key = routeParams.url.pathname + (routeParams.url.search || ""); root_module,
writeCache({ routeParams,
key, serverRes,
value: html,
paradigm: "html",
expiry_seconds,
}); });
} }
const res = new Response(html, res_opts); const res = new Response(html, res_opts);

View File

@ -1,4 +1,5 @@
import _ from "lodash"; import _ from "lodash";
import { log } from "../../../utils/log";
export default async function grabPageServerRes({ url, query, routeParams, server_function, }) { export default async function grabPageServerRes({ url, query, routeParams, server_function, }) {
const default_props = { const default_props = {
url: url url: url
@ -37,8 +38,10 @@ export default async function grabPageServerRes({ url, query, routeParams, serve
}; };
} }
catch (error) { catch (error) {
log.error(`Page ${url?.pathname} Server Error => ${error.message}\n`, error);
return { return {
...default_props, ...default_props,
error: error.message,
}; };
} }
} }

15
dist/types/index.d.ts vendored
View File

@ -188,7 +188,10 @@ export type BunextPageServerFn<T extends {
[k: string]: any; [k: string]: any;
}> = (ctx: Omit<BunxRouteParams, "body">) => Promise<BunextPageModuleServerReturn<T>>; }> = (ctx: Omit<BunxRouteParams, "body">) => Promise<BunextPageModuleServerReturn<T>>;
export type BunextRouteConfig = { export type BunextRouteConfig = {
cachePage?: boolean; /**
* Whether to cache the current page
*/
cachePage?: BunextCachePageType;
/** /**
* Expiry time of the cache in seconds * Expiry time of the cache in seconds
*/ */
@ -207,13 +210,21 @@ export type BunextPageModuleServerReturn<T extends {
query?: Q; query?: Q;
redirect?: BunextPageModuleServerRedirect; redirect?: BunextPageModuleServerRedirect;
responseOptions?: ResponseInit; responseOptions?: ResponseInit;
cachePage?: boolean; /**
* Whether to cache the current page
*/
cachePage?: BunextCachePageType;
/** /**
* Expiry time of the cache in seconds * Expiry time of the cache in seconds
*/ */
cacheExpiry?: number; cacheExpiry?: number;
url?: BunextPageModuleServerReturnURLObject; url?: BunextPageModuleServerReturnURLObject;
error?: string;
}; };
export type BunextCachePageType = boolean | ((params: {
ctx: Omit<BunxRouteParams, "body">;
serverRes?: BunextPageModuleServerReturn;
}) => Promise<boolean> | boolean);
export type BunextPageProps<T extends { export type BunextPageProps<T extends {
[k: string]: any; [k: string]: any;
} = { } = {

View File

@ -2,7 +2,7 @@
"name": "@moduletrace/bunext", "name": "@moduletrace/bunext",
"module": "index.ts", "module": "index.ts",
"type": "module", "type": "module",
"version": "1.0.39", "version": "1.0.40",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"exports": { "exports": {

View File

@ -0,0 +1,56 @@
import _ from "lodash";
import type {
BunextPageModule,
BunextPageModuleServerReturn,
BunxRouteParams,
} from "../../../types";
import { log } from "../../../utils/log";
import writeCache from "../../cache/write-cache";
type Params = {
html: string;
module: BunextPageModule;
root_module?: BunextPageModule;
routeParams?: BunxRouteParams;
serverRes?: BunextPageModuleServerReturn<any, any>;
};
export default async function generateWebPageGetCachePage({
module,
routeParams,
serverRes,
root_module,
html,
}: Params) {
const config = _.merge(root_module?.config, module.config);
const cache_page = config?.cachePage || serverRes?.cachePage || false;
const expiry_seconds = config?.cacheExpiry || serverRes?.cacheExpiry;
if (cache_page && routeParams?.url) {
try {
const is_cache =
typeof cache_page == "boolean"
? cache_page
: await cache_page({ ctx: routeParams, serverRes });
if (!is_cache) {
return false;
}
const key =
routeParams.url.pathname + (routeParams.url.search || "");
writeCache({
key,
value: html,
paradigm: "html",
expiry_seconds,
});
} catch (error: any) {
log.error(`Error writing Cache => ${error.message}\n`, error);
}
}
return true;
}

View File

@ -2,8 +2,8 @@ import _ from "lodash";
import type { GrabPageComponentRes } from "../../../types"; import type { GrabPageComponentRes } from "../../../types";
import isDevelopment from "../../../utils/is-development"; import isDevelopment from "../../../utils/is-development";
import { log } from "../../../utils/log"; import { log } from "../../../utils/log";
import writeCache from "../../cache/write-cache";
import genWebHTML from "./generate-web-html"; import genWebHTML from "./generate-web-html";
import generateWebPageGetCachePage from "./generate-web-page-get-cache-page";
export default async function generateWebPageResponseFromComponentReturn({ export default async function generateWebPageResponseFromComponentReturn({
component, component,
@ -14,6 +14,8 @@ export default async function generateWebPageResponseFromComponentReturn({
debug, debug,
root_module, root_module,
}: GrabPageComponentRes) { }: GrabPageComponentRes) {
const is_dev = isDevelopment();
const html = await genWebHTML({ const html = await genWebHTML({
component, component,
pageProps: serverRes, pageProps: serverRes,
@ -45,7 +47,7 @@ export default async function generateWebPageResponseFromComponentReturn({
}, },
}; };
if (isDevelopment()) { if (is_dev) {
res_opts.headers = { res_opts.headers = {
...res_opts.headers, ...res_opts.headers,
"Cache-Control": "no-cache, no-store, must-revalidate", "Cache-Control": "no-cache, no-store, must-revalidate",
@ -54,18 +56,13 @@ export default async function generateWebPageResponseFromComponentReturn({
}; };
} }
const config = _.merge(root_module?.config, module.config); if (!is_dev) {
await generateWebPageGetCachePage({
const cache_page = config?.cachePage || serverRes?.cachePage || false; html,
const expiry_seconds = config?.cacheExpiry || serverRes?.cacheExpiry; module,
root_module,
if (cache_page && routeParams?.url) { routeParams,
const key = routeParams.url.pathname + (routeParams.url.search || ""); serverRes,
writeCache({
key,
value: html,
paradigm: "html",
expiry_seconds,
}); });
} }

View File

@ -6,6 +6,7 @@ import type {
GrabPageComponentRes, GrabPageComponentRes,
} from "../../../types"; } from "../../../types";
import _ from "lodash"; import _ from "lodash";
import { log } from "../../../utils/log";
type Params = { type Params = {
url?: URL; url?: URL;
@ -56,9 +57,15 @@ export default async function grabPageServerRes({
return { return {
...default_props, ...default_props,
}; };
} catch (error) { } catch (error: any) {
log.error(
`Page ${url?.pathname} Server Error => ${error.message}\n`,
error,
);
return { return {
...default_props, ...default_props,
error: error.message,
}; };
} }
} }

View File

@ -222,7 +222,10 @@ export type BunextPageServerFn<
) => Promise<BunextPageModuleServerReturn<T>>; ) => Promise<BunextPageModuleServerReturn<T>>;
export type BunextRouteConfig = { export type BunextRouteConfig = {
cachePage?: boolean; /**
* Whether to cache the current page
*/
cachePage?: BunextCachePageType;
/** /**
* Expiry time of the cache in seconds * Expiry time of the cache in seconds
*/ */
@ -237,14 +240,25 @@ export type BunextPageModuleServerReturn<
query?: Q; query?: Q;
redirect?: BunextPageModuleServerRedirect; redirect?: BunextPageModuleServerRedirect;
responseOptions?: ResponseInit; responseOptions?: ResponseInit;
cachePage?: boolean; /**
* Whether to cache the current page
*/
cachePage?: BunextCachePageType;
/** /**
* Expiry time of the cache in seconds * Expiry time of the cache in seconds
*/ */
cacheExpiry?: number; cacheExpiry?: number;
url?: BunextPageModuleServerReturnURLObject; url?: BunextPageModuleServerReturnURLObject;
error?: string;
}; };
export type BunextCachePageType =
| boolean
| ((params: {
ctx: Omit<BunxRouteParams, "body">;
serverRes?: BunextPageModuleServerReturn;
}) => Promise<boolean> | boolean);
export type BunextPageProps< export type BunextPageProps<
T extends { [k: string]: any } = { [k: string]: any }, T extends { [k: string]: any } = { [k: string]: any },
Q extends { [k: string]: any } = { [k: string]: any }, Q extends { [k: string]: any } = { [k: string]: any },