From 23db8558e2b939dcbf450bdfd33086e1192d340d Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Thu, 23 Jan 2025 09:29:21 -0800 Subject: [PATCH 01/16] feat: Create shared environment variable retrieval function --- packages/react-router/src/ssr/loadOptions.ts | 3 +- packages/react-router/src/utils/env.ts | 54 +------------------ packages/shared/package.json | 3 +- packages/shared/src/getEnvVariable.ts | 56 ++++++++++++++++++++ packages/shared/src/index.ts | 2 + 5 files changed, 63 insertions(+), 55 deletions(-) create mode 100644 packages/shared/src/getEnvVariable.ts diff --git a/packages/react-router/src/ssr/loadOptions.ts b/packages/react-router/src/ssr/loadOptions.ts index 79a15dd0113..a958a39d9c6 100644 --- a/packages/react-router/src/ssr/loadOptions.ts +++ b/packages/react-router/src/ssr/loadOptions.ts @@ -1,10 +1,11 @@ import { createClerkRequest } from '@clerk/backend/internal'; import { apiUrlFromPublishableKey } from '@clerk/shared/apiUrlFromPublishableKey'; +import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isDevelopmentFromSecretKey } from '@clerk/shared/keys'; import { isHttpOrHttps, isProxyUrlRelative } from '@clerk/shared/proxy'; import { handleValueOrFn } from '@clerk/shared/utils'; -import { getEnvVariable, getPublicEnvVariables } from '../utils/env'; +import { getPublicEnvVariables } from '../utils/env'; import { noSecretKeyError, satelliteAndMissingProxyUrlAndDomain, satelliteAndMissingSignInUrl } from '../utils/errors'; import type { LoaderFunctionArgs, RootAuthLoaderOptions } from './types'; import { patchRequest } from './utils'; diff --git a/packages/react-router/src/utils/env.ts b/packages/react-router/src/utils/env.ts index 078a503a245..d151fbcfb98 100644 --- a/packages/react-router/src/utils/env.ts +++ b/packages/react-router/src/utils/env.ts @@ -1,59 +1,7 @@ +import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isTruthy } from '@clerk/shared/underscore'; import type { AppLoadContext } from 'react-router'; -type CloudflareEnv = { env: Record }; - -const hasCloudflareProxyContext = (context: any): context is { cloudflare: CloudflareEnv } => { - return !!context?.cloudflare?.env; -}; - -const hasCloudflareContext = (context: any): context is CloudflareEnv => { - return !!context?.env; -}; - -/** - * - * Utility function to get env variables across Node and Edge runtimes. - * - * @param name - * @returns string - */ -export const getEnvVariable = (name: string, context: AppLoadContext | undefined): string => { - // Node envs - if (typeof process !== 'undefined' && process.env && typeof process.env[name] === 'string') { - return process.env[name]; - } - - // @ts-expect-error - Vite specific - if (typeof import.meta !== 'undefined' && import.meta.env && typeof import.meta.env[name] === 'string') { - // @ts-expect-error - Vite specific - return import.meta.env[name]; - } - - if (hasCloudflareProxyContext(context)) { - return context.cloudflare.env[name] || ''; - } - - // Cloudflare - if (hasCloudflareContext(context)) { - return context.env[name] || ''; - } - - // Check whether the value exists in the context object directly - if (context && typeof context[name] === 'string') { - return context[name]; - } - - // Cloudflare workers - try { - return globalThis[name as keyof typeof globalThis]; - } catch { - // This will raise an error in Cloudflare Pages - } - - return ''; -}; - export const getPublicEnvVariables = (context: AppLoadContext | undefined) => { return { publishableKey: diff --git a/packages/shared/package.json b/packages/shared/package.json index 2f676f6f912..45b35d44660 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -114,7 +114,8 @@ "devBrowser", "object", "oauth", - "web3" + "web3", + "getEnvVariable" ], "scripts": { "build": "tsup", diff --git a/packages/shared/src/getEnvVariable.ts b/packages/shared/src/getEnvVariable.ts new file mode 100644 index 00000000000..032231f85c6 --- /dev/null +++ b/packages/shared/src/getEnvVariable.ts @@ -0,0 +1,56 @@ +type CloudflareEnv = { env: Record }; + +interface Context { + [key: string]: unknown; + cloudflare?: CloudflareEnv; +} + +const hasCloudflareProxyContext = (context: any): context is { cloudflare: CloudflareEnv } => { + return !!context?.cloudflare?.env; +}; + +const hasCloudflareContext = (context: any): context is CloudflareEnv => { + return !!context?.env; +}; + +/** + * Retrieves an environment variable across runtime environments. + * @param name - The environment variable name to retrieve + * @param context - Optional context object that may contain environment values + * @returns The environment variable value or empty string if not found + */ +export const getEnvVariable = (name: string, context: Context | undefined): string => { + // Node envs + if (typeof process !== 'undefined' && process.env && typeof process.env[name] === 'string') { + return process.env[name]; + } + + // @ts-expect-error - Vite specific + if (typeof import.meta !== 'undefined' && import.meta.env && typeof import.meta.env[name] === 'string') { + // @ts-expect-error - Vite specific + return import.meta.env[name]; + } + + if (hasCloudflareProxyContext(context)) { + return context.cloudflare.env[name] || ''; + } + + // Cloudflare + if (hasCloudflareContext(context)) { + return context.env[name] || ''; + } + + // Check whether the value exists in the context object directly + if (context && typeof context[name] === 'string') { + return context[name]; + } + + // Cloudflare workers + try { + return globalThis[name as keyof typeof globalThis]; + } catch (_) { + // This will raise an error in Cloudflare Pages + } + + return ''; +}; diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index aa98558a41d..dd2adca0f97 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -35,3 +35,5 @@ export * from './object'; export * from './logger'; export { createWorkerTimers } from './workerTimers'; export { DEV_BROWSER_JWT_KEY, extractDevBrowserJWTFromURL, setDevBrowserJWTInURL } from './devBrowser'; +export { fastDeepMergeAndKeep, fastDeepMergeAndReplace } from './utils/fastDeepMerge'; +export { getEnvVariable } from './getEnvVariable'; From f75666288443c01e4cf21a6f32e4949b26dd467c Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Thu, 23 Jan 2025 09:53:59 -0800 Subject: [PATCH 02/16] reuse logic within tanstack-start --- packages/shared/src/getEnvVariable.ts | 11 ++---- .../tanstack-start/src/server/constants.ts | 16 ++++----- .../tanstack-start/src/server/loadOptions.ts | 5 +-- .../tanstack-start/src/server/utils/index.ts | 2 +- packages/tanstack-start/src/utils/env.ts | 34 ++----------------- 5 files changed, 17 insertions(+), 51 deletions(-) diff --git a/packages/shared/src/getEnvVariable.ts b/packages/shared/src/getEnvVariable.ts index 032231f85c6..423495ff239 100644 --- a/packages/shared/src/getEnvVariable.ts +++ b/packages/shared/src/getEnvVariable.ts @@ -1,10 +1,5 @@ type CloudflareEnv = { env: Record }; -interface Context { - [key: string]: unknown; - cloudflare?: CloudflareEnv; -} - const hasCloudflareProxyContext = (context: any): context is { cloudflare: CloudflareEnv } => { return !!context?.cloudflare?.env; }; @@ -19,7 +14,7 @@ const hasCloudflareContext = (context: any): context is CloudflareEnv => { * @param context - Optional context object that may contain environment values * @returns The environment variable value or empty string if not found */ -export const getEnvVariable = (name: string, context: Context | undefined): string => { +export const getEnvVariable = (name: string, context?: T): string => { // Node envs if (typeof process !== 'undefined' && process.env && typeof process.env[name] === 'string') { return process.env[name]; @@ -41,8 +36,8 @@ export const getEnvVariable = (name: string, context: Context | undefined): stri } // Check whether the value exists in the context object directly - if (context && typeof context[name] === 'string') { - return context[name]; + if (context && typeof context[name as keyof typeof context] === 'string') { + return context[name as keyof typeof context] as string; } // Cloudflare workers diff --git a/packages/tanstack-start/src/server/constants.ts b/packages/tanstack-start/src/server/constants.ts index c5e1114cd71..94cc40fc913 100644 --- a/packages/tanstack-start/src/server/constants.ts +++ b/packages/tanstack-start/src/server/constants.ts @@ -1,8 +1,8 @@ import { apiUrlFromPublishableKey } from '@clerk/shared/apiUrlFromPublishableKey'; -// eslint-disable-next-line import/no-unresolved +import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { getEvent } from 'vinxi/http'; -import { getEnvVariable, getPublicEnvVariables } from '../utils/env'; +import { getPublicEnvVariables } from '../utils/env'; export const commonEnvs = () => { const event = getEvent(); @@ -22,16 +22,16 @@ export const commonEnvs = () => { TELEMETRY_DEBUG: publicEnvs.telemetryDebug, // Server-only environment variables - API_VERSION: getEnvVariable('CLERK_API_VERSION', 'v1', event), - SECRET_KEY: getEnvVariable('CLERK_SECRET_KEY', '', event), - ENCRYPTION_KEY: getEnvVariable('CLERK_ENCRYPTION_KEY', '', event), - CLERK_JWT_KEY: getEnvVariable('CLERK_JWT_KEY', '', event), - API_URL: getEnvVariable('CLERK_API_URL', '', event) || apiUrlFromPublishableKey(publicEnvs.publishableKey), + API_VERSION: getEnvVariable('CLERK_API_VERSION', event) || 'v1', + SECRET_KEY: getEnvVariable('CLERK_SECRET_KEY', event), + ENCRYPTION_KEY: getEnvVariable('CLERK_ENCRYPTION_KEY', event), + CLERK_JWT_KEY: getEnvVariable('CLERK_JWT_KEY', event), + API_URL: getEnvVariable('CLERK_API_URL', event) || apiUrlFromPublishableKey(publicEnvs.publishableKey), SDK_METADATA: { name: PACKAGE_NAME, version: PACKAGE_VERSION, - environment: getEnvVariable('NODE_ENV', '', event), + environment: getEnvVariable('NODE_ENV', event), }, } as const; }; diff --git a/packages/tanstack-start/src/server/loadOptions.ts b/packages/tanstack-start/src/server/loadOptions.ts index a0a580763a5..725149aa013 100644 --- a/packages/tanstack-start/src/server/loadOptions.ts +++ b/packages/tanstack-start/src/server/loadOptions.ts @@ -1,5 +1,6 @@ import { createClerkRequest } from '@clerk/backend/internal'; import { apiUrlFromPublishableKey } from '@clerk/shared/apiUrlFromPublishableKey'; +import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isDevelopmentFromSecretKey } from '@clerk/shared/keys'; import { isHttpOrHttps, isProxyUrlRelative } from '@clerk/shared/proxy'; import { handleValueOrFn } from '@clerk/shared/utils'; @@ -7,7 +8,7 @@ import { handleValueOrFn } from '@clerk/shared/utils'; import { getEvent } from 'vinxi/http'; import { errorThrower } from '../utils'; -import { getEnvVariable, getPublicEnvVariables } from '../utils/env'; +import { getPublicEnvVariables } from '../utils/env'; import { commonEnvs } from './constants'; import type { LoaderOptions } from './types'; import { patchRequest } from './utils'; @@ -19,7 +20,7 @@ export const loadOptions = (request: Request, overrides: LoaderOptions = {}) => const secretKey = overrides.secretKey || commonEnv.SECRET_KEY; const publishableKey = overrides.publishableKey || commonEnv.PUBLISHABLE_KEY; const jwtKey = overrides.jwtKey || commonEnv.CLERK_JWT_KEY; - const apiUrl = getEnvVariable('CLERK_API_URL', '', event) || apiUrlFromPublishableKey(publishableKey); + const apiUrl = getEnvVariable('CLERK_API_URL', event) || apiUrlFromPublishableKey(publishableKey); const domain = handleValueOrFn(overrides.domain, new URL(request.url)) || commonEnv.DOMAIN; const isSatellite = handleValueOrFn(overrides.isSatellite, new URL(request.url)) || commonEnv.IS_SATELLITE; const relativeOrAbsoluteProxyUrl = handleValueOrFn(overrides?.proxyUrl, clerkRequest.clerkUrl, commonEnv.PROXY_URL); diff --git a/packages/tanstack-start/src/server/utils/index.ts b/packages/tanstack-start/src/server/utils/index.ts index ae52dff32a1..f7657e12eb5 100644 --- a/packages/tanstack-start/src/server/utils/index.ts +++ b/packages/tanstack-start/src/server/utils/index.ts @@ -1,8 +1,8 @@ import type { RequestState } from '@clerk/backend/internal'; import { debugRequestState } from '@clerk/backend/internal'; +import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isTruthy } from '@clerk/shared/underscore'; -import { getEnvVariable } from '../../utils/env'; import type { AdditionalStateOptions } from '../types'; /** diff --git a/packages/tanstack-start/src/utils/env.ts b/packages/tanstack-start/src/utils/env.ts index c0e677e2ef6..d69dc8579e2 100644 --- a/packages/tanstack-start/src/utils/env.ts +++ b/packages/tanstack-start/src/utils/env.ts @@ -1,40 +1,10 @@ +import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isTruthy } from '@clerk/shared/underscore'; import type { HTTPEvent } from 'vinxi/http'; -/** - * - * Utility function to get env variables. - * - * @param name env variable name - * @param defaultVaue default value to return if the env variable is not set - * @param event - H3Event object for accessing runtime environment variables - * @returns string - * - * @internal - */ -export const getEnvVariable = (name: string, defaultValue: string = '', event?: HTTPEvent) => { - // Cloudflare context check - const cfValue = event?.context?.cloudflare?.env[name]; - if (cfValue) { - return cfValue; - } - - // Node envs - if (typeof process !== 'undefined' && process.env && typeof process.env[name] === 'string') { - return process.env[name]; - } - - // Vite specific envs - if (typeof import.meta !== 'undefined' && import.meta.env && typeof import.meta.env[name] === 'string') { - return import.meta.env[name]; - } - - return defaultValue; -}; - export const getPublicEnvVariables = (event?: HTTPEvent) => { const getValue = (name: string): string => { - return getEnvVariable(`VITE_${name}`, '', event) || getEnvVariable(name, '', event); + return getEnvVariable(`VITE_${name}`, event) || getEnvVariable(name, event); }; return { From f1ce19b87df3afbb66fade0302473fc442664542 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Fri, 24 Jan 2025 13:11:50 -0800 Subject: [PATCH 03/16] chore: pass context directly --- .../tanstack-start/src/server/constants.ts | 14 +++++----- .../tanstack-start/src/server/loadOptions.ts | 6 ++--- .../tanstack-start/src/server/utils/index.ts | 26 +++++++++++++------ packages/tanstack-start/src/utils/env.ts | 6 ++--- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/packages/tanstack-start/src/server/constants.ts b/packages/tanstack-start/src/server/constants.ts index 94cc40fc913..ee90395c551 100644 --- a/packages/tanstack-start/src/server/constants.ts +++ b/packages/tanstack-start/src/server/constants.ts @@ -6,7 +6,7 @@ import { getPublicEnvVariables } from '../utils/env'; export const commonEnvs = () => { const event = getEvent(); - const publicEnvs = getPublicEnvVariables(event); + const publicEnvs = getPublicEnvVariables(event.context); return { // Public environment variables @@ -22,16 +22,16 @@ export const commonEnvs = () => { TELEMETRY_DEBUG: publicEnvs.telemetryDebug, // Server-only environment variables - API_VERSION: getEnvVariable('CLERK_API_VERSION', event) || 'v1', - SECRET_KEY: getEnvVariable('CLERK_SECRET_KEY', event), - ENCRYPTION_KEY: getEnvVariable('CLERK_ENCRYPTION_KEY', event), - CLERK_JWT_KEY: getEnvVariable('CLERK_JWT_KEY', event), - API_URL: getEnvVariable('CLERK_API_URL', event) || apiUrlFromPublishableKey(publicEnvs.publishableKey), + API_VERSION: getEnvVariable('CLERK_API_VERSION', event.context) || 'v1', + SECRET_KEY: getEnvVariable('CLERK_SECRET_KEY', event.context), + ENCRYPTION_KEY: getEnvVariable('CLERK_ENCRYPTION_KEY', event.context), + CLERK_JWT_KEY: getEnvVariable('CLERK_JWT_KEY', event.context), + API_URL: getEnvVariable('CLERK_API_URL', event.context) || apiUrlFromPublishableKey(publicEnvs.publishableKey), SDK_METADATA: { name: PACKAGE_NAME, version: PACKAGE_VERSION, - environment: getEnvVariable('NODE_ENV', event), + environment: getEnvVariable('NODE_ENV', event.context), }, } as const; }; diff --git a/packages/tanstack-start/src/server/loadOptions.ts b/packages/tanstack-start/src/server/loadOptions.ts index 0fa94f2651a..f45128334e1 100644 --- a/packages/tanstack-start/src/server/loadOptions.ts +++ b/packages/tanstack-start/src/server/loadOptions.ts @@ -19,14 +19,14 @@ export const loadOptions = (request: Request, overrides: LoaderOptions = {}) => const secretKey = overrides.secretKey || commonEnv.SECRET_KEY; const publishableKey = overrides.publishableKey || commonEnv.PUBLISHABLE_KEY; const jwtKey = overrides.jwtKey || commonEnv.CLERK_JWT_KEY; - const apiUrl = getEnvVariable('CLERK_API_URL', event) || apiUrlFromPublishableKey(publishableKey); + const apiUrl = getEnvVariable('CLERK_API_URL', event.context) || apiUrlFromPublishableKey(publishableKey); const domain = handleValueOrFn(overrides.domain, new URL(request.url)) || commonEnv.DOMAIN; const isSatellite = handleValueOrFn(overrides.isSatellite, new URL(request.url)) || commonEnv.IS_SATELLITE; const relativeOrAbsoluteProxyUrl = handleValueOrFn(overrides?.proxyUrl, clerkRequest.clerkUrl, commonEnv.PROXY_URL); const signInUrl = overrides.signInUrl || commonEnv.SIGN_IN_URL; const signUpUrl = overrides.signUpUrl || commonEnv.SIGN_UP_URL; - const afterSignInUrl = overrides.afterSignInUrl || getPublicEnvVariables(event).afterSignInUrl; - const afterSignUpUrl = overrides.afterSignUpUrl || getPublicEnvVariables(event).afterSignUpUrl; + const afterSignInUrl = overrides.afterSignInUrl || getPublicEnvVariables(event.context).afterSignInUrl; + const afterSignUpUrl = overrides.afterSignUpUrl || getPublicEnvVariables(event.context).afterSignUpUrl; let proxyUrl; if (!!relativeOrAbsoluteProxyUrl && isProxyUrlRelative(relativeOrAbsoluteProxyUrl)) { diff --git a/packages/tanstack-start/src/server/utils/index.ts b/packages/tanstack-start/src/server/utils/index.ts index f7657e12eb5..e9b431bd644 100644 --- a/packages/tanstack-start/src/server/utils/index.ts +++ b/packages/tanstack-start/src/server/utils/index.ts @@ -2,6 +2,7 @@ import type { RequestState } from '@clerk/backend/internal'; import { debugRequestState } from '@clerk/backend/internal'; import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isTruthy } from '@clerk/shared/underscore'; +import { getEvent } from 'vinxi/http'; import type { AdditionalStateOptions } from '../types'; @@ -22,6 +23,7 @@ export const wrapWithClerkState = (data: any) => { */ export function getResponseClerkState(requestState: RequestState, additionalStateOptions: AdditionalStateOptions = {}) { const { reason, message, isSignedIn, ...rest } = requestState; + const event = getEvent(); const clerkInitialState = wrapWithClerkState({ __clerk_ssr_state: rest.toAuth(), @@ -34,18 +36,26 @@ export function getResponseClerkState(requestState: RequestState, additionalStat __afterSignInUrl: requestState.afterSignInUrl, __afterSignUpUrl: requestState.afterSignUpUrl, __clerk_debug: debugRequestState(requestState), - __clerkJSUrl: getEnvVariable('CLERK_JS'), - __clerkJSVersion: getEnvVariable('CLERK_JS_VERSION'), - __telemetryDisabled: isTruthy(getEnvVariable('CLERK_TELEMETRY_DISABLED')), - __telemetryDebug: isTruthy(getEnvVariable('CLERK_TELEMETRY_DEBUG')), + __clerkJSUrl: getEnvVariable('CLERK_JS', event.context), + __clerkJSVersion: getEnvVariable('CLERK_JS_VERSION', event.context), + __telemetryDisabled: isTruthy(getEnvVariable('CLERK_TELEMETRY_DISABLED', event.context)), + __telemetryDebug: isTruthy(getEnvVariable('CLERK_TELEMETRY_DEBUG', event.context)), __signInForceRedirectUrl: - additionalStateOptions.signInForceRedirectUrl || getEnvVariable('CLERK_SIGN_IN_FORCE_REDIRECT_URL') || '', + additionalStateOptions.signInForceRedirectUrl || + getEnvVariable('CLERK_SIGN_IN_FORCE_REDIRECT_URL', event.context) || + '', __signUpForceRedirectUrl: - additionalStateOptions.signUpForceRedirectUrl || getEnvVariable('CLERK_SIGN_UP_FORCE_REDIRECT_URL') || '', + additionalStateOptions.signUpForceRedirectUrl || + getEnvVariable('CLERK_SIGN_UP_FORCE_REDIRECT_URL', event.context) || + '', __signInFallbackRedirectUrl: - additionalStateOptions.signInFallbackRedirectUrl || getEnvVariable('CLERK_SIGN_IN_FALLBACK_REDIRECT_URL') || '', + additionalStateOptions.signInFallbackRedirectUrl || + getEnvVariable('CLERK_SIGN_IN_FALLBACK_REDIRECT_URL', event.context) || + '', __signUpFallbackRedirectUrl: - additionalStateOptions.signUpFallbackRedirectUrl || getEnvVariable('CLERK_SIGN_UP_FALLBACK_REDIRECT_URL') || '', + additionalStateOptions.signUpFallbackRedirectUrl || + getEnvVariable('CLERK_SIGN_UP_FALLBACK_REDIRECT_URL', event.context) || + '', }); return { diff --git a/packages/tanstack-start/src/utils/env.ts b/packages/tanstack-start/src/utils/env.ts index d69dc8579e2..039a16c99ca 100644 --- a/packages/tanstack-start/src/utils/env.ts +++ b/packages/tanstack-start/src/utils/env.ts @@ -1,10 +1,10 @@ import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isTruthy } from '@clerk/shared/underscore'; -import type { HTTPEvent } from 'vinxi/http'; +import type { H3EventContext } from 'vinxi/http'; -export const getPublicEnvVariables = (event?: HTTPEvent) => { +export const getPublicEnvVariables = (context?: H3EventContext) => { const getValue = (name: string): string => { - return getEnvVariable(`VITE_${name}`, event) || getEnvVariable(name, event); + return getEnvVariable(`VITE_${name}`, context) || getEnvVariable(name, context); }; return { From 2a1bd48dfed2b2c1c8b57cb2d76af9d7ac7f8a96 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Fri, 24 Jan 2025 13:22:14 -0800 Subject: [PATCH 04/16] remove unused catch var --- packages/shared/src/getEnvVariable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/src/getEnvVariable.ts b/packages/shared/src/getEnvVariable.ts index 423495ff239..d74bfe5ff4f 100644 --- a/packages/shared/src/getEnvVariable.ts +++ b/packages/shared/src/getEnvVariable.ts @@ -43,7 +43,7 @@ export const getEnvVariable = (name: string, context?: T): string = // Cloudflare workers try { return globalThis[name as keyof typeof globalThis]; - } catch (_) { + } catch { // This will raise an error in Cloudflare Pages } From d85c375ebc47ee8bf528e61b4d3576d3e29bd6a4 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Wed, 29 Jan 2025 11:32:39 -0800 Subject: [PATCH 05/16] test nextjs env vars --- packages/nextjs/src/server/constants.ts | 33 +++++++++++++------------ 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/packages/nextjs/src/server/constants.ts b/packages/nextjs/src/server/constants.ts index 67c7295bbd5..5d0470b13a5 100644 --- a/packages/nextjs/src/server/constants.ts +++ b/packages/nextjs/src/server/constants.ts @@ -1,25 +1,26 @@ import { apiUrlFromPublishableKey } from '@clerk/shared/apiUrlFromPublishableKey'; +import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isTruthy } from '@clerk/shared/underscore'; -export const CLERK_JS_VERSION = process.env.NEXT_PUBLIC_CLERK_JS_VERSION || ''; -export const CLERK_JS_URL = process.env.NEXT_PUBLIC_CLERK_JS_URL || ''; -export const API_VERSION = process.env.CLERK_API_VERSION || 'v1'; -export const SECRET_KEY = process.env.CLERK_SECRET_KEY || ''; -export const PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY || ''; -export const ENCRYPTION_KEY = process.env.CLERK_ENCRYPTION_KEY || ''; -export const API_URL = process.env.CLERK_API_URL || apiUrlFromPublishableKey(PUBLISHABLE_KEY); -export const DOMAIN = process.env.NEXT_PUBLIC_CLERK_DOMAIN || ''; -export const PROXY_URL = process.env.NEXT_PUBLIC_CLERK_PROXY_URL || ''; -export const IS_SATELLITE = isTruthy(process.env.NEXT_PUBLIC_CLERK_IS_SATELLITE) || false; -export const SIGN_IN_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_IN_URL || ''; -export const SIGN_UP_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_UP_URL || ''; +export const CLERK_JS_VERSION = getEnvVariable('NEXT_PUBLIC_CLERK_JS_VERSION') || ''; +export const CLERK_JS_URL = getEnvVariable('NEXT_PUBLIC_CLERK_JS_URL') || ''; +export const API_VERSION = getEnvVariable('CLERK_API_VERSION') || 'v1'; +export const SECRET_KEY = getEnvVariable('CLERK_SECRET_KEY') || ''; +export const PUBLISHABLE_KEY = getEnvVariable('NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY') || ''; +export const ENCRYPTION_KEY = getEnvVariable('CLERK_ENCRYPTION_KEY') || ''; +export const API_URL = getEnvVariable('CLERK_API_URL') || apiUrlFromPublishableKey(PUBLISHABLE_KEY); +export const DOMAIN = getEnvVariable('NEXT_PUBLIC_CLERK_DOMAIN') || ''; +export const PROXY_URL = getEnvVariable('NEXT_PUBLIC_CLERK_PROXY_URL') || ''; +export const IS_SATELLITE = isTruthy(getEnvVariable('NEXT_PUBLIC_CLERK_IS_SATELLITE')) || false; +export const SIGN_IN_URL = getEnvVariable('NEXT_PUBLIC_CLERK_SIGN_IN_URL') || ''; +export const SIGN_UP_URL = getEnvVariable('NEXT_PUBLIC_CLERK_SIGN_UP_URL') || ''; export const SDK_METADATA = { name: PACKAGE_NAME, version: PACKAGE_VERSION, - environment: process.env.NODE_ENV, + environment: getEnvVariable('NODE_ENV'), }; -export const TELEMETRY_DISABLED = isTruthy(process.env.NEXT_PUBLIC_CLERK_TELEMETRY_DISABLED); -export const TELEMETRY_DEBUG = isTruthy(process.env.NEXT_PUBLIC_CLERK_TELEMETRY_DEBUG); +export const TELEMETRY_DISABLED = isTruthy(getEnvVariable('NEXT_PUBLIC_CLERK_TELEMETRY_DISABLED')); +export const TELEMETRY_DEBUG = isTruthy(getEnvVariable('NEXT_PUBLIC_CLERK_TELEMETRY_DEBUG')); -export const ENABLE_KEYLESS = isTruthy(process.env.NEXT_PUBLIC_CLERK_ENABLE_KEYLESS); +export const ENABLE_KEYLESS = isTruthy(getEnvVariable('NEXT_PUBLIC_CLERK_ENABLE_KEYLESS')); From a7cb5a901ae4d8c4979ee306e9027cc012085d73 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Wed, 29 Jan 2025 13:06:24 -0800 Subject: [PATCH 06/16] revert --- packages/nextjs/src/server/constants.ts | 33 ++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/nextjs/src/server/constants.ts b/packages/nextjs/src/server/constants.ts index 5d0470b13a5..67c7295bbd5 100644 --- a/packages/nextjs/src/server/constants.ts +++ b/packages/nextjs/src/server/constants.ts @@ -1,26 +1,25 @@ import { apiUrlFromPublishableKey } from '@clerk/shared/apiUrlFromPublishableKey'; -import { getEnvVariable } from '@clerk/shared/getEnvVariable'; import { isTruthy } from '@clerk/shared/underscore'; -export const CLERK_JS_VERSION = getEnvVariable('NEXT_PUBLIC_CLERK_JS_VERSION') || ''; -export const CLERK_JS_URL = getEnvVariable('NEXT_PUBLIC_CLERK_JS_URL') || ''; -export const API_VERSION = getEnvVariable('CLERK_API_VERSION') || 'v1'; -export const SECRET_KEY = getEnvVariable('CLERK_SECRET_KEY') || ''; -export const PUBLISHABLE_KEY = getEnvVariable('NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY') || ''; -export const ENCRYPTION_KEY = getEnvVariable('CLERK_ENCRYPTION_KEY') || ''; -export const API_URL = getEnvVariable('CLERK_API_URL') || apiUrlFromPublishableKey(PUBLISHABLE_KEY); -export const DOMAIN = getEnvVariable('NEXT_PUBLIC_CLERK_DOMAIN') || ''; -export const PROXY_URL = getEnvVariable('NEXT_PUBLIC_CLERK_PROXY_URL') || ''; -export const IS_SATELLITE = isTruthy(getEnvVariable('NEXT_PUBLIC_CLERK_IS_SATELLITE')) || false; -export const SIGN_IN_URL = getEnvVariable('NEXT_PUBLIC_CLERK_SIGN_IN_URL') || ''; -export const SIGN_UP_URL = getEnvVariable('NEXT_PUBLIC_CLERK_SIGN_UP_URL') || ''; +export const CLERK_JS_VERSION = process.env.NEXT_PUBLIC_CLERK_JS_VERSION || ''; +export const CLERK_JS_URL = process.env.NEXT_PUBLIC_CLERK_JS_URL || ''; +export const API_VERSION = process.env.CLERK_API_VERSION || 'v1'; +export const SECRET_KEY = process.env.CLERK_SECRET_KEY || ''; +export const PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY || ''; +export const ENCRYPTION_KEY = process.env.CLERK_ENCRYPTION_KEY || ''; +export const API_URL = process.env.CLERK_API_URL || apiUrlFromPublishableKey(PUBLISHABLE_KEY); +export const DOMAIN = process.env.NEXT_PUBLIC_CLERK_DOMAIN || ''; +export const PROXY_URL = process.env.NEXT_PUBLIC_CLERK_PROXY_URL || ''; +export const IS_SATELLITE = isTruthy(process.env.NEXT_PUBLIC_CLERK_IS_SATELLITE) || false; +export const SIGN_IN_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_IN_URL || ''; +export const SIGN_UP_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_UP_URL || ''; export const SDK_METADATA = { name: PACKAGE_NAME, version: PACKAGE_VERSION, - environment: getEnvVariable('NODE_ENV'), + environment: process.env.NODE_ENV, }; -export const TELEMETRY_DISABLED = isTruthy(getEnvVariable('NEXT_PUBLIC_CLERK_TELEMETRY_DISABLED')); -export const TELEMETRY_DEBUG = isTruthy(getEnvVariable('NEXT_PUBLIC_CLERK_TELEMETRY_DEBUG')); +export const TELEMETRY_DISABLED = isTruthy(process.env.NEXT_PUBLIC_CLERK_TELEMETRY_DISABLED); +export const TELEMETRY_DEBUG = isTruthy(process.env.NEXT_PUBLIC_CLERK_TELEMETRY_DEBUG); -export const ENABLE_KEYLESS = isTruthy(getEnvVariable('NEXT_PUBLIC_CLERK_ENABLE_KEYLESS')); +export const ENABLE_KEYLESS = isTruthy(process.env.NEXT_PUBLIC_CLERK_ENABLE_KEYLESS); From 58c1fdd3342ad4c9d9e1a9b0fa23a6ed855d00cd Mon Sep 17 00:00:00 2001 From: Robert Soriano Date: Mon, 3 Feb 2025 12:01:53 -0800 Subject: [PATCH 07/16] chore: add changeset --- .changeset/eleven-cougars-film.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/eleven-cougars-film.md diff --git a/.changeset/eleven-cougars-film.md b/.changeset/eleven-cougars-film.md new file mode 100644 index 00000000000..bc5abecaa74 --- /dev/null +++ b/.changeset/eleven-cougars-film.md @@ -0,0 +1,7 @@ +--- +"@clerk/react-router": patch +"@clerk/shared": patch +"@clerk/tanstack-start": patch +--- + +Create shared isomorphic environment variable retrieval function From df3533b8d30d5c916fb716d7efebf398ec5c36d2 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 3 Feb 2025 12:10:56 -0800 Subject: [PATCH 08/16] add env var manually to tanstack router integration --- integration/templates/tanstack-router/src/routes/__root.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/templates/tanstack-router/src/routes/__root.tsx b/integration/templates/tanstack-router/src/routes/__root.tsx index 7addf20d386..64d4b69bed6 100644 --- a/integration/templates/tanstack-router/src/routes/__root.tsx +++ b/integration/templates/tanstack-router/src/routes/__root.tsx @@ -17,7 +17,7 @@ export const Route = createRootRoute({ function RootComponent() { return ( - + From 5152f7861e4ce7431aa4003c3934178b5e349f9d Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 3 Feb 2025 13:01:38 -0800 Subject: [PATCH 09/16] temporarily add tsup config to ts config --- integration/templates/tanstack-router/src/routes/__root.tsx | 2 +- packages/shared/tsconfig.json | 2 +- packages/shared/tsup.config.ts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/integration/templates/tanstack-router/src/routes/__root.tsx b/integration/templates/tanstack-router/src/routes/__root.tsx index 64d4b69bed6..7addf20d386 100644 --- a/integration/templates/tanstack-router/src/routes/__root.tsx +++ b/integration/templates/tanstack-router/src/routes/__root.tsx @@ -17,7 +17,7 @@ export const Route = createRootRoute({ function RootComponent() { return ( - + diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index f120c796cd0..c26f908c172 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -20,5 +20,5 @@ "allowJs": true }, "exclude": ["node_modules"], - "include": ["src", "global.d.ts"] + "include": ["src", "global.d.ts", "tsup.config.ts"] } diff --git a/packages/shared/tsup.config.ts b/packages/shared/tsup.config.ts index 695703ac940..6515b9da11d 100644 --- a/packages/shared/tsup.config.ts +++ b/packages/shared/tsup.config.ts @@ -24,6 +24,7 @@ export default defineConfig(overrideOptions => { minify: false, sourcemap: true, dts: true, + target: 'es2020', external: ['react', 'react-dom'], esbuildPlugins: [WebWorkerMinifyPlugin as any], define: { From 7b442191dc3e4e4d826419cec867afc5825a18bb Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 3 Feb 2025 13:05:59 -0800 Subject: [PATCH 10/16] remove from tsconfig --- packages/shared/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index c26f908c172..f120c796cd0 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -20,5 +20,5 @@ "allowJs": true }, "exclude": ["node_modules"], - "include": ["src", "global.d.ts", "tsup.config.ts"] + "include": ["src", "global.d.ts"] } From d09261de401d30b5c204854d64e357506eca5c31 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 3 Feb 2025 13:19:39 -0800 Subject: [PATCH 11/16] update changeset --- .changeset/eleven-cougars-film.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eleven-cougars-film.md b/.changeset/eleven-cougars-film.md index bc5abecaa74..5069aa9a06c 100644 --- a/.changeset/eleven-cougars-film.md +++ b/.changeset/eleven-cougars-film.md @@ -1,6 +1,6 @@ --- "@clerk/react-router": patch -"@clerk/shared": patch +"@clerk/shared": minor "@clerk/tanstack-start": patch --- From 2ea0a3e44a80b825125dafd2b2725d825b73936d Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 3 Feb 2025 13:31:21 -0800 Subject: [PATCH 12/16] remove duplicate util export --- packages/shared/src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 89875f32fb8..6c0d63672b1 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -35,6 +35,5 @@ export * from './object'; export * from './logger'; export { createWorkerTimers } from './workerTimers'; export { DEV_BROWSER_JWT_KEY, extractDevBrowserJWTFromURL, setDevBrowserJWTInURL } from './devBrowser'; -export { fastDeepMergeAndKeep, fastDeepMergeAndReplace } from './utils/fastDeepMerge'; export { getEnvVariable } from './getEnvVariable'; export * from './pathMatcher'; From 15b7417656ec478d552500a35adc6f7745995d48 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 3 Feb 2025 15:57:03 -0800 Subject: [PATCH 13/16] improve types --- packages/shared/global.d.ts | 8 ++++++++ packages/shared/src/getEnvVariable.ts | 9 ++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/shared/global.d.ts b/packages/shared/global.d.ts index b91055a700d..5776b61ae17 100644 --- a/packages/shared/global.d.ts +++ b/packages/shared/global.d.ts @@ -2,3 +2,11 @@ declare const PACKAGE_NAME: string; declare const PACKAGE_VERSION: string; declare const JS_PACKAGE_VERSION: string; declare const __DEV__: boolean; + +interface ImportMetaEnv { + readonly [key: string]: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/packages/shared/src/getEnvVariable.ts b/packages/shared/src/getEnvVariable.ts index d74bfe5ff4f..24cd5d5e3fe 100644 --- a/packages/shared/src/getEnvVariable.ts +++ b/packages/shared/src/getEnvVariable.ts @@ -14,15 +14,14 @@ const hasCloudflareContext = (context: any): context is CloudflareEnv => { * @param context - Optional context object that may contain environment values * @returns The environment variable value or empty string if not found */ -export const getEnvVariable = (name: string, context?: T): string => { +export const getEnvVariable = (name: string, context?: Record): string => { // Node envs if (typeof process !== 'undefined' && process.env && typeof process.env[name] === 'string') { return process.env[name]; } - // @ts-expect-error - Vite specific + // Vite specific if (typeof import.meta !== 'undefined' && import.meta.env && typeof import.meta.env[name] === 'string') { - // @ts-expect-error - Vite specific return import.meta.env[name]; } @@ -36,8 +35,8 @@ export const getEnvVariable = (name: string, context?: T): string = } // Check whether the value exists in the context object directly - if (context && typeof context[name as keyof typeof context] === 'string') { - return context[name as keyof typeof context] as string; + if (context && typeof context[name] === 'string') { + return context[name]; } // Cloudflare workers From 8431042be8d525e8c9d2f132418d2be2bb1bcaad Mon Sep 17 00:00:00 2001 From: Robert Soriano Date: Mon, 3 Feb 2025 16:09:20 -0800 Subject: [PATCH 14/16] chore: update changeset --- .changeset/eleven-cougars-film.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eleven-cougars-film.md b/.changeset/eleven-cougars-film.md index 5069aa9a06c..bed3cb9f510 100644 --- a/.changeset/eleven-cougars-film.md +++ b/.changeset/eleven-cougars-film.md @@ -4,4 +4,4 @@ "@clerk/tanstack-start": patch --- -Create shared isomorphic environment variable retrieval function +Introduce unified environment variable handling across all supported platforms From 1f6bff3a9aa6f47c4b1cd4e4ce9f327477b7e885 Mon Sep 17 00:00:00 2001 From: Robert Soriano Date: Mon, 3 Feb 2025 16:11:12 -0800 Subject: [PATCH 15/16] chore: update changeset --- .changeset/eleven-cougars-film.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.changeset/eleven-cougars-film.md b/.changeset/eleven-cougars-film.md index bed3cb9f510..427dcce7bf7 100644 --- a/.changeset/eleven-cougars-film.md +++ b/.changeset/eleven-cougars-film.md @@ -5,3 +5,11 @@ --- Introduce unified environment variable handling across all supported platforms + +Usage: + +```ts +import { getEnvVariable } from '@clerk/shared/getEnvVariable' + +const publishableKey = getEnvVariable('CLERK_PUBLISHABLE_KEY') +``` From db1427ebb2eb249fee8c67ee4712f11d557da6e9 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Tue, 4 Feb 2025 08:53:46 -0800 Subject: [PATCH 16/16] chore: update changesets --- .changeset/eleven-cougars-film.md | 2 -- .changeset/unlucky-gifts-obey.md | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .changeset/unlucky-gifts-obey.md diff --git a/.changeset/eleven-cougars-film.md b/.changeset/eleven-cougars-film.md index 427dcce7bf7..a6cdfb0640b 100644 --- a/.changeset/eleven-cougars-film.md +++ b/.changeset/eleven-cougars-film.md @@ -1,7 +1,5 @@ --- -"@clerk/react-router": patch "@clerk/shared": minor -"@clerk/tanstack-start": patch --- Introduce unified environment variable handling across all supported platforms diff --git a/.changeset/unlucky-gifts-obey.md b/.changeset/unlucky-gifts-obey.md new file mode 100644 index 00000000000..773fffbbc2d --- /dev/null +++ b/.changeset/unlucky-gifts-obey.md @@ -0,0 +1,6 @@ +--- +'@clerk/tanstack-start': patch +'@clerk/react-router': patch +--- + +Internal changes to use new `getEnvVariable` utility from `@clerk/shared`