import type { Children, Refkey } from "@alloy-js/core"; import { For, List, refkey } from "@alloy-js/core"; import * as ts from "@alloy-js/typescript"; import { useTsp } from "@typespec/emitter-framework"; import { FunctionDeclaration } from "@typespec/emitter-framework/typescript"; import type { HttpAuth } from "@typespec/http"; import { type OAuth2Flow } from "@typespec/http"; import type * as cl from "@typespec/http-client"; import { reportDiagnostic } from "../../lib.js"; import { buildClientParameters } from "../../utils/parameters.jsx"; import { httpRuntimeTemplateLib } from "../external-packages/ts-http-runtime.js"; import { addClientTestOptions } from "../testing/client-options.jsx"; import { getClientcontextDeclarationRef } from "./client-context-declaration.jsx"; import { ParametrizedEndpoint } from "./parametrized-endpoint.jsx"; export interface ClientContextFactoryProps { client: cl.Client; } export function getClientContextFactoryRef(client: cl.Client) { return refkey(client, "contextFactory"); } export function ClientContextFactoryDeclaration(props: ClientContextFactoryProps) { const { $ } = useTsp(); const ref = getClientContextFactoryRef(props.client); const contextDeclarationRef = getClientcontextDeclarationRef(props.client); const namePolicy = ts.useTSNamePolicy(); const factoryFunctionName = namePolicy.getName(`create_${props.client.name}Context`, "function"); const clientConstructor = $.client.getConstructor(props.client); const parameters = buildClientParameters(props.client, refkey()); const urlTemplate = $.client.getUrlTemplate(props.client); const endpointRef = refkey(); const resolvedEndpoint = ( ); let credentialsRef: string | undefined; if (parameters.some((p) => p.name === "credential")) { credentialsRef = "credential"; } // Filter out optional parameters, they will be passed as options const args = ( ); return ( {resolvedEndpoint} return ); } interface ClientFactoryArgumentsProps { client: cl.Client; endpointRef: Refkey; credentialsRef?: string; } function ClientFactoryArguments(props: ClientFactoryArgumentsProps) { const params = [<>{props.endpointRef},]; return [ ...params, props.credentialsRef ? ( {props.credentialsRef} ) : ( ), ]; } interface AuthSchemeOptionsProps { client: cl.Client; } interface AuthSchemeProps { scheme: HttpAuth; client: cl.Client; } function AuthScheme(props: AuthSchemeProps) { const { $ } = useTsp(); switch (props.scheme.type) { case "http": return ( ); case "apiKey": if (props.scheme.in !== "header") { reportDiagnostic($.program, { code: "key-credential-non-header-not-implemented", target: props.client.service, }); } return ( ); case "oauth2": return ( [ {(flow) => } ] ); default: return null; } } interface OAuth2FlowProps { flow: OAuth2Flow; } function OAuth2Flow(props: OAuth2FlowProps) { // rename type to kind and clean up the scopes const { type, ...rewrittenFlow } = { kind: props.flow.type, ...props.flow, // scopes are sometimes duplicated so converting to set and back to dedupe scopes: [...new Set(props.flow.scopes.map((s) => s.value))], }; return ; } function AuthSchemeOptions(props: AuthSchemeOptionsProps) { const { $ } = useTsp(); const clientCredential = $.client.getAuth(props.client); if (clientCredential.schemes.length === 0) { return null; } // Filtering out custom http schemes for "http/custom" spector scenario // TODO: Should typekit allow for arbitrary strings on scheme with http auth type? const supportedSchemes = clientCredential.schemes.filter( (s) => s.type !== "http" || ["Basic", "Bearer"].includes(s.scheme), ); return ( [ {(scheme) => } ] ); } interface ClientOptionsExpressionProps { children?: Children; } function ClientOptionsExpression(props: ClientOptionsExpressionProps) { const options: Children = ["...options"]; // Conditionally add test options // based on the environment variable TYPESPEC_JS_EMITTER_TESTING addClientTestOptions(options); const children = Array.isArray(props.children) ? props.children : [props.children]; if (children.length) { const children = Array.isArray(props.children) ? props.children : [props.children]; options.push(...children); } return ( {(child) => child} ); }