import { CONNECT_OAUTH_SCOPES, DEFAULT_HOSTED_APP_URL } from "@t3tools/shared/connectAuth"; import { clerkFrontendApiUrlFromPublishableKey } from "@t3tools/shared/relayAuth"; import { normalizeSecureRelayUrl } from "@t3tools/shared/relayUrl"; import * as Config from "effect/Config"; import * as ConfigProvider from "effect/ConfigProvider"; import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as SchemaIssue from "effect/SchemaIssue"; declare const __T3CODE_BUILD_RELAY_URL__: string | undefined; declare const __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__: string | undefined; declare const __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__: string | undefined; declare const __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_URL__: string | undefined; declare const __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_DATASET__: string | undefined; declare const __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_TOKEN__: string | undefined; const CLOUD_CLI_OAUTH_REDIRECT_URI = "http://127.0.0.1:34338/callback"; const CLOUD_CLI_OAUTH_SCOPES = CONNECT_OAUTH_SCOPES; function validateRelayUrl(value: string) { const relayUrl = normalizeSecureRelayUrl(value); return relayUrl === null ? Effect.fail( new Config.ConfigError( new Schema.SchemaError( new SchemaIssue.InvalidValue(Option.some(value), { message: "Relay URL must be a secure absolute HTTPS origin.", }), ), ), ) : Effect.succeed(relayUrl); } function readBuildTimeValue(value: string | undefined): string { return typeof value === "undefined" ? "" : value.trim(); } function normalizeSecureUrl(value: string): string | null { try { const url = new URL(value); return url.protocol === "https:" ? url.toString() : null; } catch { return null; } } export const buildTimeRelayUrl = typeof __T3CODE_BUILD_RELAY_URL__ === "undefined" ? "" : (normalizeSecureRelayUrl(__T3CODE_BUILD_RELAY_URL__) ?? ""); export const buildTimeClerkPublishableKey = readBuildTimeValue( typeof __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__ === "undefined" ? undefined : __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__, ); export const buildTimeClerkCliOAuthClientId = readBuildTimeValue( typeof __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__ === "undefined" ? undefined : __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__, ); export const buildTimeRelayClientTracing = { tracesUrl: readBuildTimeValue( typeof __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_URL__ === "undefined" ? undefined : __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_URL__, ), tracesDataset: readBuildTimeValue( typeof __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_DATASET__ === "undefined" ? undefined : __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_DATASET__, ), tracesToken: readBuildTimeValue( typeof __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_TOKEN__ === "undefined" ? undefined : __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_TOKEN__, ), } as const; export function resolveRelayClientTracingConfig( env: Readonly> = process.env, fallback = buildTimeRelayClientTracing, ) { const tracesUrl = env.T3CODE_RELAY_CLIENT_OTLP_TRACES_URL?.trim() || fallback.tracesUrl; const tracesDataset = env.T3CODE_RELAY_CLIENT_OTLP_TRACES_DATASET?.trim() || fallback.tracesDataset; const tracesToken = env.T3CODE_RELAY_CLIENT_OTLP_TRACES_TOKEN?.trim() || fallback.tracesToken; const normalizedTracesUrl = normalizeSecureUrl(tracesUrl); return normalizedTracesUrl && tracesDataset && tracesToken ? { tracesUrl: normalizedTracesUrl, tracesDataset, tracesToken } : null; } export function makeRelayUrlConfig(fallback = buildTimeRelayUrl) { const runtimeConfig = Config.nonEmptyString("T3CODE_RELAY_URL"); return (fallback ? runtimeConfig.pipe(Config.withDefault(fallback)) : runtimeConfig).pipe( Config.mapOrFail(validateRelayUrl), ); } export const relayUrlConfig = makeRelayUrlConfig(); /** * Hosted app origin used for out-of-band OAuth on headless * machines. Overridable so staging/nightly builds can point their CLIs at a * matching hosted deployment. */ export const hostedAppUrlConfig = makePublicValueConfig( "T3CODE_HOSTED_APP_URL", DEFAULT_HOSTED_APP_URL, ).pipe(Config.mapOrFail(validateHostedAppUrl)); function validateHostedAppUrl(value: string) { try { const url = new URL(value); const isLoopbackHttp = url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]"); if ( (url.protocol !== "https:" && !isLoopbackHttp) || url.pathname !== "/" || url.search !== "" || url.hash !== "" ) { throw new Error("invalid hosted app origin"); } return Effect.succeed(url.origin); } catch { return Effect.fail( new Config.ConfigError( new Schema.SchemaError( new SchemaIssue.InvalidValue(Option.some(value), { message: "Hosted app URL must be an absolute HTTPS origin (or HTTP loopback origin).", }), ), ), ); } } function makePublicValueConfig(name: string, fallback: string) { const runtimeConfig = Config.nonEmptyString(name); return (fallback ? runtimeConfig.pipe(Config.withDefault(fallback)) : runtimeConfig).pipe( Config.map((value) => value.trim()), ); } export interface CloudCliOAuthConfig { readonly authorizationEndpoint: string; readonly tokenEndpoint: string; readonly clientId: string; readonly redirectUri: string; readonly scopes: typeof CLOUD_CLI_OAUTH_SCOPES; } export function makeCloudCliOAuthConfig({ clerkPublishableKeyFallback = buildTimeClerkPublishableKey, clerkCliOAuthClientIdFallback = buildTimeClerkCliOAuthClientId, }: { readonly clerkPublishableKeyFallback?: string; readonly clerkCliOAuthClientIdFallback?: string; } = {}) { return Config.all({ clerkPublishableKey: makePublicValueConfig( "T3CODE_CLERK_PUBLISHABLE_KEY", clerkPublishableKeyFallback, ), clientId: makePublicValueConfig( "T3CODE_CLERK_CLI_OAUTH_CLIENT_ID", clerkCliOAuthClientIdFallback, ), }).pipe( Config.mapOrFail(({ clerkPublishableKey, clientId }) => Effect.try({ try: () => clerkFrontendApiUrlFromPublishableKey(clerkPublishableKey), catch: (cause) => new Config.ConfigError( new ConfigProvider.SourceError({ message: "Failed to derive Clerk Frontend API URL from the publishable key.", cause, }), ), }).pipe( Effect.map( (clerkFrontendApiUrl) => ({ authorizationEndpoint: `${clerkFrontendApiUrl}/oauth/authorize`, tokenEndpoint: `${clerkFrontendApiUrl}/oauth/token`, clientId, redirectUri: CLOUD_CLI_OAUTH_REDIRECT_URI, scopes: CLOUD_CLI_OAUTH_SCOPES, }) satisfies CloudCliOAuthConfig, ), ), ), ); } export const cloudCliOAuthConfig = makeCloudCliOAuthConfig(); export const hasCloudPublicConfig = Boolean( (normalizeSecureRelayUrl(process.env.T3CODE_RELAY_URL ?? "") ?? buildTimeRelayUrl) && (process.env.T3CODE_CLERK_PUBLISHABLE_KEY?.trim() || buildTimeClerkPublishableKey) && (process.env.T3CODE_CLERK_CLI_OAUTH_CLIENT_ID?.trim() || buildTimeClerkCliOAuthClientId), );