import { connectLoopbackRedirectUri, 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 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_LOOPBACK_PORT = 34338;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({ 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; }} const buildTimeRelayUrl = typeof __T3CODE_BUILD_RELAY_URL__ === "undefined" ? "" : (normalizeSecureRelayUrl(__T3CODE_BUILD_RELAY_URL__) ?? "");const buildTimeClerkPublishableKey = readBuildTimeValue( typeof __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__ === "undefined" ? undefined : __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__,);const buildTimeClerkCliOAuthClientId = readBuildTimeValue( typeof __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__ === "undefined" ? undefined : __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__,);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<Record<string, string | undefined>> = 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({ 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()), );} /** * The CLI never calls Clerk's /oauth/authorize itself: the browser leg goes * through the hosted /connect page, which builds the authorize URL after a * Clerk session exists (see CliTokenManager.login). Only the token endpoint * is contacted directly. */export interface CloudCliOAuthConfig { readonly tokenEndpoint: string; readonly clientId: string; readonly loopbackPort: number; 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) => ({ tokenEndpoint: `${clerkFrontendApiUrl}/oauth/token`, clientId, loopbackPort: CLOUD_CLI_OAUTH_LOOPBACK_PORT, redirectUri: connectLoopbackRedirectUri(CLOUD_CLI_OAUTH_LOOPBACK_PORT), 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),);
import {
connectLoopbackRedirectUri,
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 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_LOOPBACK_PORT = 34338;
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({
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;
}
}
const buildTimeRelayUrl =
typeof __T3CODE_BUILD_RELAY_URL__ === "undefined"
? ""
: (normalizeSecureRelayUrl(__T3CODE_BUILD_RELAY_URL__) ?? "");
const buildTimeClerkPublishableKey = readBuildTimeValue(
typeof __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__ === "undefined"
? undefined
: __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__,
);
const buildTimeClerkCliOAuthClientId = readBuildTimeValue(
typeof __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__ === "undefined"
? undefined
: __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__,
);
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<Record<string, string | undefined>> = 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({
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()),
);
}
/**
* The CLI never calls Clerk's /oauth/authorize itself: the browser leg goes
* through the hosted /connect page, which builds the authorize URL after a
* Clerk session exists (see CliTokenManager.login). Only the token endpoint
* is contacted directly.
*/
export interface CloudCliOAuthConfig {
readonly tokenEndpoint: string;
readonly clientId: string;
readonly loopbackPort: number;
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) =>
({
tokenEndpoint: `${clerkFrontendApiUrl}/oauth/token`,
clientId,
loopbackPort: CLOUD_CLI_OAUTH_LOOPBACK_PORT,
redirectUri: connectLoopbackRedirectUri(CLOUD_CLI_OAUTH_LOOPBACK_PORT),
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),
);