Sign In

@tanstack/start-static-server-functions

Package Overview
Dependencies
Maintainers
2
Versions
372
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tanstack/start-static-server-functions - npm Package Compare versions

Comparing version
1.132.0-alpha.2
to
1.132.0-alpha.3
+22
-31
dist/esm/staticFunctionMiddleware.js

@@ -1,2 +0,5 @@

import { createMiddleware, startSerializer } from "@tanstack/start-client-core";
import fs from "node:fs/promises";
import path from "node:path";
import { createMiddleware, getDefaultSerovalPlugins } from "@tanstack/start-client-core";
import { fromJSON, toJSONAsync } from "seroval";
async function sha1Hash(message) {

@@ -22,22 +25,8 @@ const msgBuffer = new TextEncoder().encode(message);

const staticClientCache = typeof document !== "undefined" ? /* @__PURE__ */ new Map() : null;
const serverFnStaticCache = {
getItem: async (ctx) => {
if (typeof document === "undefined") {
const hash = jsonToFilenameSafeString(ctx.data);
const url = await getStaticCacheUrl({ functionId: ctx.functionId, hash });
const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR;
const { promises: fs } = await import("node:fs");
const path = await import("node:path");
const filePath = path.join(publicUrl, url);
const [cachedResult, readError] = await fs.readFile(filePath, "utf-8").then((c) => [startSerializer.parse(c), null]).catch((e) => [null, e]);
if (readError && readError.code !== "ENOENT") {
throw readError;
}
return cachedResult;
}
return void 0;
},
setItem: async ({ data, functionId, response }) => {
const { promises: fs } = await import("node:fs");
const path = await import("node:path");
async function addItemToCache({
functionId,
data,
response
}) {
{
const hash = jsonToFilenameSafeString(data);

@@ -48,12 +37,14 @@ const url = await getStaticCacheUrl({ functionId, hash });

await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(
filePath,
startSerializer.stringify({
result: response.result,
context: response.context.sendContext
}),
"utf-8"
const stringifiedResult = JSON.stringify(
await toJSONAsync(
{
result: response.result,
context: response.context.sendContext
},
{ plugins: getDefaultSerovalPlugins() }
)
);
await fs.writeFile(filePath, stringifiedResult, "utf-8");
}
};
}
const fetchItem = async ({

@@ -68,3 +59,3 @@ data,

method: "GET"
}).then((r) => r.text()).then((d) => startSerializer.parse(d));
}).then((r) => r.json()).then((d) => fromJSON(d, { plugins: getDefaultSerovalPlugins() }));
return result;

@@ -90,3 +81,3 @@ };

if (process.env.NODE_ENV === "production") {
await serverFnStaticCache.setItem({
await addItemToCache({
functionId: ctx.functionId,

@@ -93,0 +84,0 @@ response: { result: response.result, context: ctx },

@@ -1,1 +0,1 @@

{"version":3,"file":"staticFunctionMiddleware.js","sources":["../../src/staticFunctionMiddleware.ts"],"sourcesContent":["import { createMiddleware, startSerializer } from '@tanstack/start-client-core'\n\ntype StaticCachedResult = {\n result: any\n context: any\n}\n\ntype ServerFnStaticCache = {\n getItem: (opts: {\n functionId: string\n data: any\n }) => StaticCachedResult | Promise<StaticCachedResult | undefined>\n setItem: (opts: {\n functionId: string\n data: any\n response: StaticCachedResult\n }) => Promise<void>\n}\n\n/**\n * This is a simple hash function for generating a hash from a string to make the filenames shorter.\n *\n * It is not cryptographically secure (as its using SHA-1) and should not be used for any security purposes.\n *\n * It is only used to generate a hash for the static cache filenames.\n *\n * @param message - The input string to hash.\n * @returns A promise that resolves to the SHA-1 hash of the input string in hexadecimal format.\n *\n * @example\n * ```typescript\n * const hash = await sha1Hash(\"hello\");\n * console.log(hash); // Outputs the SHA-1 hash of \"hello\" -> \"aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d\"\n * ```\n */\nasync function sha1Hash(message: string): Promise<string> {\n // Encode the string as UTF-8\n const msgBuffer = new TextEncoder().encode(message)\n\n // Hash the message\n const hashBuffer = await crypto.subtle.digest('SHA-1', msgBuffer)\n\n // Convert the ArrayBuffer to a string\n const hashArray = Array.from(new Uint8Array(hashBuffer))\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')\n return hashHex\n}\n\nconst getStaticCacheUrl = async (opts: {\n functionId: string\n hash: string\n}) => {\n const filename = await sha1Hash(`${opts.functionId}__${opts.hash}`)\n return `/__tsr/staticServerFnCache/${filename}.json`\n}\n\nconst jsonToFilenameSafeString = (json: any) => {\n // Custom replacer to sort keys\n const sortedKeysReplacer = (key: string, value: any) =>\n value && typeof value === 'object' && !Array.isArray(value)\n ? Object.keys(value)\n .sort()\n .reduce((acc: any, curr: string) => {\n acc[curr] = value[curr]\n return acc\n }, {})\n : value\n\n // Convert JSON to string with sorted keys\n const jsonString = JSON.stringify(json ?? '', sortedKeysReplacer)\n\n // Replace characters invalid in filenames\n return jsonString\n .replace(/[/\\\\?%*:|\"<>]/g, '-') // Replace invalid characters with a dash\n .replace(/\\s+/g, '_') // Optionally replace whitespace with underscores\n}\n\nconst staticClientCache =\n typeof document !== 'undefined' ? new Map<string, any>() : null\n\nconst serverFnStaticCache: ServerFnStaticCache = {\n getItem: async (ctx) => {\n if (typeof document === 'undefined') {\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = await getStaticCacheUrl({ functionId: ctx.functionId, hash })\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n\n // Use fs instead of fetch to read from filesystem\n const { promises: fs } = await import('node:fs')\n const path = await import('node:path')\n const filePath = path.join(publicUrl, url)\n\n const [cachedResult, readError] = await fs\n .readFile(filePath, 'utf-8')\n .then((c) => [startSerializer.parse(c), null])\n .catch((e) => [null, e])\n\n if (readError && readError.code !== 'ENOENT') {\n throw readError\n }\n\n return cachedResult as StaticCachedResult\n }\n\n return undefined\n },\n setItem: async ({ data, functionId, response }) => {\n const { promises: fs } = await import('node:fs')\n const path = await import('node:path')\n\n const hash = jsonToFilenameSafeString(data)\n const url = await getStaticCacheUrl({ functionId, hash })\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n const filePath = path.join(publicUrl, url)\n\n // Ensure the directory exists\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n\n // Store the result with fs\n await fs.writeFile(\n filePath,\n startSerializer.stringify({\n result: response.result,\n context: response.context.sendContext,\n }),\n 'utf-8',\n )\n },\n}\n\nconst fetchItem = async ({\n data,\n functionId,\n}: {\n data: any\n functionId: string\n}) => {\n const hash = jsonToFilenameSafeString(data)\n const url = await getStaticCacheUrl({ functionId, hash })\n\n let result: any = staticClientCache?.get(url)\n\n result = await fetch(url, {\n method: 'GET',\n })\n .then((r) => r.text())\n .then((d) => startSerializer.parse(d))\n\n return result\n}\n\nexport const staticFunctionMiddleware = createMiddleware({ type: 'function' })\n .client(async (ctx) => {\n if (\n process.env.NODE_ENV === 'production' &&\n // do not run this during SSR on the server\n typeof document !== 'undefined'\n ) {\n const response = await fetchItem({\n functionId: ctx.functionId,\n data: ctx.data,\n })\n\n if (response) {\n return {\n result: response.result,\n context: { ...(ctx as any).context, ...response.context },\n } as any\n }\n }\n return ctx.next()\n })\n .server(async (ctx) => {\n const response = await ctx.next()\n\n if (process.env.NODE_ENV === 'production') {\n await serverFnStaticCache.setItem({\n functionId: ctx.functionId,\n response: { result: (response as any).result, context: ctx },\n data: ctx.data,\n })\n }\n\n return response\n })\n"],"names":[],"mappings":"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"}
{"version":3,"file":"staticFunctionMiddleware.js","sources":["../../src/staticFunctionMiddleware.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {\n createMiddleware,\n getDefaultSerovalPlugins,\n} from '@tanstack/start-client-core'\nimport { fromJSON, toJSONAsync } from 'seroval'\n\ntype StaticCachedResult = {\n result: any\n context: any\n}\n\n/**\n * This is a simple hash function for generating a hash from a string to make the filenames shorter.\n *\n * It is not cryptographically secure (as its using SHA-1) and should not be used for any security purposes.\n *\n * It is only used to generate a hash for the static cache filenames.\n *\n * @param message - The input string to hash.\n * @returns A promise that resolves to the SHA-1 hash of the input string in hexadecimal format.\n *\n * @example\n * ```typescript\n * const hash = await sha1Hash(\"hello\");\n * console.log(hash); // Outputs the SHA-1 hash of \"hello\" -> \"aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d\"\n * ```\n */\nasync function sha1Hash(message: string): Promise<string> {\n // Encode the string as UTF-8\n const msgBuffer = new TextEncoder().encode(message)\n\n // Hash the message\n const hashBuffer = await crypto.subtle.digest('SHA-1', msgBuffer)\n\n // Convert the ArrayBuffer to a string\n const hashArray = Array.from(new Uint8Array(hashBuffer))\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')\n return hashHex\n}\n\nconst getStaticCacheUrl = async (opts: {\n functionId: string\n hash: string\n}) => {\n const filename = await sha1Hash(`${opts.functionId}__${opts.hash}`)\n return `/__tsr/staticServerFnCache/${filename}.json`\n}\n\nconst jsonToFilenameSafeString = (json: any) => {\n // Custom replacer to sort keys\n const sortedKeysReplacer = (key: string, value: any) =>\n value && typeof value === 'object' && !Array.isArray(value)\n ? Object.keys(value)\n .sort()\n .reduce((acc: any, curr: string) => {\n acc[curr] = value[curr]\n return acc\n }, {})\n : value\n\n // Convert JSON to string with sorted keys\n const jsonString = JSON.stringify(json ?? '', sortedKeysReplacer)\n\n // Replace characters invalid in filenames\n return jsonString\n .replace(/[/\\\\?%*:|\"<>]/g, '-') // Replace invalid characters with a dash\n .replace(/\\s+/g, '_') // Optionally replace whitespace with underscores\n}\n\nconst staticClientCache =\n typeof document !== 'undefined' ? new Map<string, any>() : null\n\nasync function addItemToCache({\n functionId,\n data,\n response,\n}: {\n functionId: string\n data: any\n response: StaticCachedResult\n}): Promise<void> {\n {\n const hash = jsonToFilenameSafeString(data)\n const url = await getStaticCacheUrl({ functionId, hash })\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n const filePath = path.join(publicUrl, url)\n\n // Ensure the directory exists\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n\n // Store the result with fs\n const stringifiedResult = JSON.stringify(\n await toJSONAsync(\n {\n result: response.result,\n context: response.context.sendContext,\n },\n { plugins: getDefaultSerovalPlugins() },\n ),\n )\n await fs.writeFile(filePath, stringifiedResult, 'utf-8')\n }\n}\n\nconst fetchItem = async ({\n data,\n functionId,\n}: {\n data: any\n functionId: string\n}) => {\n const hash = jsonToFilenameSafeString(data)\n const url = await getStaticCacheUrl({ functionId, hash })\n\n let result: any = staticClientCache?.get(url)\n\n result = await fetch(url, {\n method: 'GET',\n })\n .then((r) => r.json())\n .then((d) => fromJSON(d, { plugins: getDefaultSerovalPlugins() }))\n\n return result\n}\n\nexport const staticFunctionMiddleware = createMiddleware({ type: 'function' })\n .client(async (ctx) => {\n if (\n process.env.NODE_ENV === 'production' &&\n // do not run this during SSR on the server\n typeof document !== 'undefined'\n ) {\n const response = await fetchItem({\n functionId: ctx.functionId,\n data: ctx.data,\n })\n\n if (response) {\n return {\n result: response.result,\n context: { ...(ctx as any).context, ...response.context },\n } as any\n }\n }\n return ctx.next()\n })\n .server(async (ctx) => {\n const response = await ctx.next()\n if (process.env.NODE_ENV === 'production') {\n await addItemToCache({\n functionId: ctx.functionId,\n response: { result: (response as any).result, context: ctx },\n data: ctx.data,\n })\n }\n\n return response\n })\n"],"names":[],"mappings":"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"}
{
"name": "@tanstack/start-static-server-functions",
"version": "1.132.0-alpha.2",
"version": "1.132.0-alpha.3",
"description": "Modern and scalable routing for React applications",

@@ -46,5 +46,6 @@ "author": "Tanner Linsley",

"dependencies": {
"@tanstack/start-client-core": "1.132.0-alpha.2"
"seroval": "^1.3.2",
"@tanstack/start-client-core": "1.132.0-alpha.3"
},
"scripts": {}
}

@@ -1,2 +0,8 @@

import { createMiddleware, startSerializer } from '@tanstack/start-client-core'
import fs from 'node:fs/promises'
import path from 'node:path'
import {
createMiddleware,
getDefaultSerovalPlugins,
} from '@tanstack/start-client-core'
import { fromJSON, toJSONAsync } from 'seroval'

@@ -8,14 +14,2 @@ type StaticCachedResult = {

type ServerFnStaticCache = {
getItem: (opts: {
functionId: string
data: any
}) => StaticCachedResult | Promise<StaticCachedResult | undefined>
setItem: (opts: {
functionId: string
data: any
response: StaticCachedResult
}) => Promise<void>
}
/**

@@ -82,32 +76,12 @@ * This is a simple hash function for generating a hash from a string to make the filenames shorter.

const serverFnStaticCache: ServerFnStaticCache = {
getItem: async (ctx) => {
if (typeof document === 'undefined') {
const hash = jsonToFilenameSafeString(ctx.data)
const url = await getStaticCacheUrl({ functionId: ctx.functionId, hash })
const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!
// Use fs instead of fetch to read from filesystem
const { promises: fs } = await import('node:fs')
const path = await import('node:path')
const filePath = path.join(publicUrl, url)
const [cachedResult, readError] = await fs
.readFile(filePath, 'utf-8')
.then((c) => [startSerializer.parse(c), null])
.catch((e) => [null, e])
if (readError && readError.code !== 'ENOENT') {
throw readError
}
return cachedResult as StaticCachedResult
}
return undefined
},
setItem: async ({ data, functionId, response }) => {
const { promises: fs } = await import('node:fs')
const path = await import('node:path')
async function addItemToCache({
functionId,
data,
response,
}: {
functionId: string
data: any
response: StaticCachedResult
}): Promise<void> {
{
const hash = jsonToFilenameSafeString(data)

@@ -122,11 +96,13 @@ const url = await getStaticCacheUrl({ functionId, hash })

// Store the result with fs
await fs.writeFile(
filePath,
startSerializer.stringify({
result: response.result,
context: response.context.sendContext,
}),
'utf-8',
const stringifiedResult = JSON.stringify(
await toJSONAsync(
{
result: response.result,
context: response.context.sendContext,
},
{ plugins: getDefaultSerovalPlugins() },
),
)
},
await fs.writeFile(filePath, stringifiedResult, 'utf-8')
}
}

@@ -149,4 +125,4 @@

})
.then((r) => r.text())
.then((d) => startSerializer.parse(d))
.then((r) => r.json())
.then((d) => fromJSON(d, { plugins: getDefaultSerovalPlugins() }))

@@ -179,5 +155,4 @@ return result

const response = await ctx.next()
if (process.env.NODE_ENV === 'production') {
await serverFnStaticCache.setItem({
await addItemToCache({
functionId: ctx.functionId,

@@ -184,0 +159,0 @@ response: { result: (response as any).result, context: ctx },