private recursiveAdaptClient()

in packages/typespec-go/src/tcgcadapter/clients.ts [45:166]


  private recursiveAdaptClient(sdkClient: tcgc.SdkClientType<tcgc.SdkHttpOperation>, parent?: go.Client): go.Client | undefined {
    if (sdkClient.methods.length === 0 && (sdkClient.children === undefined || sdkClient.children.length === 0)) {
      // skip generating empty clients
      return undefined;
    }

    let clientName = ensureNameCase(sdkClient.name);

    // to keep compat with existing ARM packages, don't use hierarchically named clients
    if (parent && this.ta.codeModel.type !== 'azure-arm') {
      // for hierarchical clients, the child client names are built
      // from the parent client name. this is because tsp allows subclients
      // with the same name. consider the following example.
      //
      // namespace Chat {
      //   interface Completions {
      //     ...
      //   }
      // }
      // interface Completions { ... }
      //
      // we want to generate two clients from this,
      // one name ChatCompletions and the other Completions

      // strip off the Client suffix from the parent client name
      clientName = parent.name.substring(0, parent.name.length - 6) + clientName;
    }

    if (!clientName.match(/Client$/)) {
      clientName += 'Client';
    }

    const docs: go.Docs = {
      summary: sdkClient.summary,
      description: sdkClient.doc,
    };

    if (docs.summary) {
      docs.summary = `${clientName} - ${docs.summary}`;
    } else if (docs.description) {
      docs.description = `${clientName} - ${docs.description}`;
    } else {
      // strip clientName's "Client" suffix
      const groupName = clientName.substring(0, clientName.length - 6);
      docs.summary = `${clientName} contains the methods for the ${groupName} group.`;
    }

    const goClient = new go.Client(clientName, docs, go.newClientOptions(this.ta.codeModel.type, clientName));
    goClient.parent = parent;

    // anything other than public means non-instantiable client
    if (sdkClient.clientInitialization.initializedBy & tcgc.InitializedByFlags.Individually) {
      for (const param of sdkClient.clientInitialization.parameters) {
        if (param.kind === 'credential') {
          // skip this for now as we don't generate client constructors
          continue;
        } else if (param.kind === 'endpoint') {
          const paramType = getEndpointType(param);
          // this will either be a fixed or templated host
          // don't set the fixed host for ARM as it isn't used
          if (this.ta.codeModel.type !== 'azure-arm') {
            goClient.host = paramType.serverUrl;
          }
          if (paramType.templateArguments.length === 0) {
            // this is the param for the fixed host, don't create a param for it
            if (!this.ta.codeModel.host) {
              this.ta.codeModel.host = goClient.host;
            } else if (this.ta.codeModel.host !== goClient.host) {
              throw new AdapterError('InternalError', `client ${goClient.name} has a conflicting host ${goClient.host}`, NoTarget);
            }
          } else {
            goClient.templatedHost = true;
            for (const templateArg of paramType.templateArguments) {
              goClient.parameters.push(this.adaptURIParam(templateArg));
            }
          }
          continue;
        } else if (param.kind === 'method') {
          // some client params, notably api-version, can be explicitly
          // defined in the operation signature:
          // e.g. op withQueryApiVersion(@query("api-version") apiVersion: string)
          // these get propagated to sdkMethod.operation.parameters thus they
          // will be adapted in adaptMethodParameters()
          continue;
        }

        goClient.parameters.push(this.adaptURIParam(param));
      }
    } else if (parent) {
      // this is a sub-client. it will share the client/host params of the parent.
      // NOTE: we must propagate parant params before a potential recursive call
      // to create a child client that will need to inherit our client params.
      goClient.templatedHost = parent.templatedHost;
      goClient.host = parent.host;
      // make a copy of the client params. this is to prevent
      // client method params from being shared across clients
      // as not all client method params might be uniform.
      goClient.parameters = new Array<go.Parameter>(...parent.parameters);
    } else {
      throw new AdapterError('InternalError', `uninstantiable client ${sdkClient.name} has no parent`, NoTarget);
    }
    if (sdkClient.children && sdkClient.children.length > 0) {
      for (const child of sdkClient.children) {
        const subClient = this.recursiveAdaptClient(child, goClient);
        if (subClient) {
          goClient.clientAccessors.push(new go.ClientAccessor(`New${subClient.name}`, subClient));
        }
      }
    }
    for (const sdkMethod of sdkClient.methods) {
      this.adaptMethod(sdkMethod, goClient);
    }

    if (this.ta.codeModel.type === 'azure-arm' && goClient.clientAccessors.length > 0 && goClient.methods.length === 0) {
      // this is the service client. to keep compat with existing
      // ARM SDKs we skip adding it to the code model in favor of
      // the synthesized client factory.
    } else {
      this.ta.codeModel.clients.push(goClient);
    }
    return goClient;
  }