createIsomorphicFn

Create a function with different implementations for server and client environments. At runtime, the correct implementation is chosen based on the environment. The Vite plugin may also tree-shake the unused implementation at build time.

Import

import { createIsomorphicFn } from 'catmint/server'

Signature

function createIsomorphicFn<TInput, TOutput>(
  config: IsomorphicFnConfig<TInput, TOutput>,
): (input: TInput) => Promise<TOutput>

Parameters

ParameterTypeRequiredDescription
configIsomorphicFnConfig<TInput, TOutput>YesObject with server and client implementations.

IsomorphicFnConfig<TInput, TOutput>

interface IsomorphicFnConfig<TInput, TOutput> {
  server: (input: TInput) => Promise<TOutput> | TOutput
  client: (input: TInput) => Promise<TOutput> | TOutput
}
FieldTypeRequiredDescription
server(input: TInput) => Promise<TOutput> | TOutputYesImplementation that runs on the server.
client(input: TInput) => Promise<TOutput> | TOutputYesImplementation that runs in the browser.

Return Value

Returns an async function (input: TInput) => Promise<TOutput> that delegates to the appropriate implementation based on the current environment.

Environment detection uses typeof document === 'undefined' to distinguish server from client.

Examples

import { createIsomorphicFn } from 'catmint/server'

export const trackEvent = createIsomorphicFn({
  server: async (event: string) => {
    await serverAnalytics.track(event)
  },
  client: async (event: string) => {
    window.analytics?.track(event)
  },
})
import { createIsomorphicFn } from 'catmint/server'

export const getTimezone = createIsomorphicFn({
  server: (input: void) => {
    return process.env.TZ ?? 'UTC'
  },
  client: (input: void) => {
    return Intl.DateTimeFormat().resolvedOptions().timeZone
  },
})
import { createIsomorphicFn } from 'catmint/server'

// Different storage strategies per environment
export const cacheValue = createIsomorphicFn({
  server: async ({ key, value }: { key: string; value: string }) => {
    await redis.set(key, value)
  },
  client: async ({ key, value }: { key: string; value: string }) => {
    localStorage.setItem(key, value)
  },
})

See Also