diff --git a/.changeset/many-ads-smile.md b/.changeset/many-ads-smile.md new file mode 100644 index 00000000000..87c0133fb95 --- /dev/null +++ b/.changeset/many-ads-smile.md @@ -0,0 +1,7 @@ +--- +'@tanstack/start-plugin-core': patch +'@tanstack/router-generator': patch +'@tanstack/router-utils': patch +--- + +Use node crypto.hash instead of crypto.createHash for single string hashes diff --git a/docs/start/framework/react/guide/isr.md b/docs/start/framework/react/guide/isr.md index ad1e3221305..805467eee6d 100644 --- a/docs/start/framework/react/guide/isr.md +++ b/docs/start/framework/react/guide/isr.md @@ -341,10 +341,7 @@ const etagMiddleware = createMiddleware().server(async ({ next }) => { const result = await next() // Generate ETag from response content - const etag = crypto - .createHash('md5') - .update(JSON.stringify(result.data)) - .digest('hex') + const etag = crypto.hash('md5', JSON.stringify(result.data), 'hex') result.response.headers.set('ETag', `"${etag}"`) diff --git a/docs/start/framework/react/guide/server-functions.md b/docs/start/framework/react/guide/server-functions.md index 32a342b8c8f..0bd937c7a85 100644 --- a/docs/start/framework/react/guide/server-functions.md +++ b/docs/start/framework/react/guide/server-functions.md @@ -379,10 +379,7 @@ export default defineConfig({ serverFns: { generateFunctionId: ({ filename, functionName }) => { // Return a custom ID string - return crypto - .createHash('sha1') - .update(`${filename}--${functionName}`) - .digest('hex') + return crypto.hash('sha1', `${filename}--${functionName}`, 'hex') // If you return undefined, the default is used // return undefined diff --git a/packages/router-generator/src/generator.ts b/packages/router-generator/src/generator.ts index f951beb05ba..bd3bd0bbaaf 100644 --- a/packages/router-generator/src/generator.ts +++ b/packages/router-generator/src/generator.ts @@ -3,6 +3,7 @@ import * as fsp from 'node:fs/promises' import { existsSync, mkdirSync } from 'node:fs' import crypto from 'node:crypto' import { rootRouteId } from '@tanstack/router-core' +import { hash as hashString } from '@tanstack/router-utils' import { logging } from './logger' import { isVirtualConfigFile, @@ -1243,7 +1244,7 @@ ${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolved private getTempFileName(filePath: string) { const absPath = path.resolve(filePath) - const hash = crypto.createHash('md5').update(absPath).digest('hex') + const hash = hashString('md5', absPath, 'hex') // lazy initialize sessionId to only create tmpDir when it is first needed if (!this.sessionId) { // ensure the directory exists diff --git a/packages/router-utils/src/hash.ts b/packages/router-utils/src/hash.ts new file mode 100644 index 00000000000..92b0bf92160 --- /dev/null +++ b/packages/router-utils/src/hash.ts @@ -0,0 +1,16 @@ +import crypto from 'node:crypto' +import type { BinaryLike, BinaryToTextEncoding } from 'node:crypto' + +const nativeHashAvailable = typeof crypto.hash === 'function' + +export function hash( + algorithm: string, + data: BinaryLike, + outputEncoding: BinaryToTextEncoding = 'hex', +): string { + if (nativeHashAvailable) { + return crypto.hash(algorithm, data, outputEncoding) + } + + return crypto.createHash(algorithm).update(data).digest(outputEncoding) +} diff --git a/packages/router-utils/src/index.ts b/packages/router-utils/src/index.ts index 3b072ae4199..a47b194b7a7 100644 --- a/packages/router-utils/src/index.ts +++ b/packages/router-utils/src/index.ts @@ -7,5 +7,6 @@ export { } from './ast' export type { ParseAstOptions, ParseAstResult, GeneratorResult } from './ast' export { logDiff } from './logger' +export { hash } from './hash' export { copyFilesPlugin } from './copy-files-plugin' diff --git a/packages/start-plugin-core/src/start-compiler/compiler.ts b/packages/start-plugin-core/src/start-compiler/compiler.ts index ec42547fc2b..ed75e5be06e 100644 --- a/packages/start-plugin-core/src/start-compiler/compiler.ts +++ b/packages/start-plugin-core/src/start-compiler/compiler.ts @@ -1,10 +1,9 @@ -/* eslint-disable import/no-commonjs */ -import crypto from 'node:crypto' import * as t from '@babel/types' import { deadCodeElimination, findReferencedIdentifiers, generateFromAst, + hash, parseAst, } from '@tanstack/router-utils' import babel from '@babel/core' @@ -600,7 +599,7 @@ export class StartCompiler { }) } if (!functionId) { - functionId = crypto.createHash('sha256').update(entryId).digest('hex') + functionId = hash('sha256', entryId, 'hex') } // Deduplicate in case the generated id conflicts with an existing id if (this.functionIds.has(functionId)) {