Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export interface ParametrizedHostContext extends Client {
/** The API version to use for this operation. */
/** Known values of {@link KnownVersions} that the service accepts. */
apiVersion: string;
host?: string;
subdomain?: string;
sufix?: string;
}

/** Optional parameters for the client. */
Expand Down Expand Up @@ -61,5 +64,5 @@ export function createParametrizedHost(
return next(req);
},
});
return { ...clientContext, apiVersion } as ParametrizedHostContext;
return { ...clientContext, apiVersion, host, subdomain, sufix } as ParametrizedHostContext;
}
119 changes: 88 additions & 31 deletions packages/typespec-ts/src/modular/buildClientContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,31 +78,60 @@ export function buildClientContext(
getClientContextPath(clientMap, emitterOptions)
);

// Get all client parameters (both required and optional) for the interface
const requiredInterfaceProperties = getClientParameters(client, dpgContext, {
onClientOnly: false,
requiredOnly: true,
apiVersionAsRequired: true
})
.filter((p) => {
const clientParamName = getClientParameterName(p);
return (
clientParamName !== "endpointParam" && clientParamName !== "credential"
);
})
.map((p) => {
return {
name: getClientParameterName(p),
type: getTypeExpression(dpgContext, p.type),
hasQuestionToken: false,
docs: getDocsWithKnownVersion(dpgContext, p)
};
});

// Collect names of required properties to avoid duplicates
const requiredPropertyNames = new Set(
requiredInterfaceProperties.map((p) => p.name)
);

const optionalInterfaceProperties = getClientParameters(client, dpgContext, {
onClientOnly: false,
optionalOnly: true
})
.filter((p) => {
const clientParamName = getClientParameterName(p);
return (
clientParamName !== "endpointParam" &&
clientParamName !== "credential" &&
clientParamName !== "endpoint" &&
!requiredPropertyNames.has(clientParamName) // Avoid duplicating required properties
);
})
.map((p) => {
return {
name: getClientParameterName(p),
type: getTypeExpression(dpgContext, p.type),
hasQuestionToken: true,
docs: getDocsWithKnownVersion(dpgContext, p)
};
});

clientContextFile.addInterface({
isExported: true,
name: `${rlcClientName}`,
extends: [resolveReference(dependencies.Client)],
docs: getDocsFromDescription(client.doc),
properties: getClientParameters(client, dpgContext, {
onClientOnly: false,
requiredOnly: true,
apiVersionAsRequired: true
})
.filter((p) => {
const clientParamName = getClientParameterName(p);
return (
clientParamName !== "endpointParam" &&
clientParamName !== "credential"
);
})
.map((p) => {
return {
name: getClientParameterName(p),
type: getTypeExpression(dpgContext, p.type),
hasQuestionToken: false,
docs: getDocsWithKnownVersion(dpgContext, p)
};
})
properties: [...requiredInterfaceProperties, ...optionalInterfaceProperties]
});

const propertiesInOptions = getClientParameters(client, dpgContext, {
Expand Down Expand Up @@ -168,11 +197,8 @@ export function buildClientContext(
isExported: true
});

const endpointParam = buildGetClientEndpointParam(
factoryFunction,
dpgContext,
client
);
const { endpointParamName: endpointParam, assignedOptionalParams } =
buildGetClientEndpointParam(factoryFunction, dpgContext, client);
const credentialParam = buildGetClientCredentialParam(client, emitterOptions);
const optionsParam = buildGetClientOptionsParam(
factoryFunction,
Expand Down Expand Up @@ -262,13 +288,44 @@ export function buildClientContext(
p.name !== "credential" &&
p.name !== "options"
);
if (contextRequiredParam.length) {

// Collect names of required parameters to avoid duplicates
const requiredParamNames = new Set(contextRequiredParam.map((p) => p.name));

// Also include optional parameters from clientInitialization that should be passed through
const contextOptionalParams = getClientParameters(client, dpgContext, {
optionalOnly: true,
onClientOnly: false
}).filter((p) => {
const clientParamName = getClientParameterName(p);
return (
clientParamName !== "endpointParam" &&
clientParamName !== "credential" &&
clientParamName !== "endpoint" &&
!requiredParamNames.has(clientParamName) // Avoid duplicating required parameters
);
});

// Build context params, checking if param was already assigned as a required param
const allContextParams = [
...contextRequiredParam.map((p) => p.name),
...contextOptionalParams.map((p) => {
const clientParamName = getClientParameterName(p);
// If this param was already assigned (e.g., as a required param or in endpoint building), use the value directly
// Otherwise, get it from options
if (
requiredParamNames.has(clientParamName) ||
(assignedOptionalParams && assignedOptionalParams.has(clientParamName))
) {
return clientParamName;
}
return `${clientParamName}: options.${clientParamName}`;
})
];

if (allContextParams.length) {
factoryFunction.addStatements(
`return { ...clientContext, ${contextRequiredParam
.map((p) => {
return p.name;
})
.join(", ")}} as ${rlcClientName};`
`return { ...clientContext, ${allContextParams.join(", ")}} as ${rlcClientName};`
);
} else {
factoryFunction.addStatements(`return clientContext;`);
Expand Down
13 changes: 8 additions & 5 deletions packages/typespec-ts/src/modular/helpers/clientHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ export function buildGetClientEndpointParam(
context: StatementedNode,
dpgContext: SdkContext,
client: SdkClientType<SdkServiceOperation>
): string {
): { endpointParamName: string; assignedOptionalParams?: Set<string> } {
const assignedOptionalParams = new Set<string>();
let coreEndpointParam = "";
if (dpgContext.rlcOptions?.flavor === "azure") {
const cloudSettingSuffix = dpgContext.arm
Expand Down Expand Up @@ -209,8 +210,10 @@ export function buildGetClientEndpointParam(
context.addStatements(
`const ${paramName} = options.${paramName} ?? ${defaultValue};`
);
assignedOptionalParams.add(paramName);
} else if (templateParam.optional) {
context.addStatements(`const ${paramName} = options.${paramName};`);
assignedOptionalParams.add(paramName);
}
parameterizedEndpointUrl = parameterizedEndpointUrl.replace(
`{${templateParam.name}}`,
Expand All @@ -219,7 +222,7 @@ export function buildGetClientEndpointParam(
}
const endpointUrl = `const endpointUrl = ${coreEndpointParam} ?? \`${parameterizedEndpointUrl}\`;`;
context.addStatements(endpointUrl);
return "endpointUrl";
return { endpointParamName: "endpointUrl", assignedOptionalParams };
} else if (endpointParam.type.kind === "endpoint") {
const clientDefaultValue =
endpointParam.type.templateArguments[0]?.clientDefaultValue;
Expand All @@ -231,14 +234,14 @@ export function buildGetClientEndpointParam(
: `String(${getClientParameterName(endpointParam)})`;
const endpointUrl = `const endpointUrl = ${coreEndpointParam} ?? ${defaultValueStr};`;
context.addStatements(endpointUrl);
return "endpointUrl";
return { endpointParamName: "endpointUrl" };
}
const endpointUrl = `const endpointUrl = ${coreEndpointParam} ?? String(${getClientParameterName(endpointParam)});`;
context.addStatements(endpointUrl);
return "endpointUrl";
return { endpointParamName: "endpointUrl" };
}

return "endpointUrl";
return { endpointParamName: "endpointUrl" };
}

/**
Expand Down
Loading
Loading