Skip to content

Attach additional metadata information on the sdk method #3446

@SukkaW

Description

@SukkaW

Problem

We have been building our own SWR solution on top of the Hey API that looks like this:

import { addPet, findPetsByStatus } from 'sdk';

// our wrapped version of useSWR and useSWRMutation that accepts sdk method and sdk method arg
import { useData, useMutation } from './data';

export default function Example() {
  const { isMutating: isAdding, trigger: triggerAddPet } = useMutation(addPet);
  const { data, error, isLoading } = useData(findPetsByStatus, { query: { status: ['available'] } });

  return (
    <div>
      <button type="button" onClick={() => trigger({ body: { id: 1, name: 'Kitty', photoUrls: [] } })}>
        Add Pet
      </button>
      <ul>
        {data?.map((pet) => (
          <li key={pet.id}>{pet.name}</li>
        ))}
      </ul>
    </div>
  );
}

We are using SWR's React provider to do global error handling:

<SWRConfig
  value={{
    onError(error, swrKey, swrOptions) {
      const [sdkMethodFn, sdkMethodArg, someOtherOptions] = swrKey;
      // logging, error reporting, maybe an error toast, etc.
      console.error({ error, sdkMethodFn, sdkMethodArg, someOtherOptions });
    }
  }}
/>

With global error handling, we only have access to what SDK method function and what parameter are producing the issue, we don't have a human-readable name (sdkMethodFn.name can and will be broken by bundler and minifier) and other metadata (like the API path endpoint or the HTTP request method).

Proposal

What I am proposing is to expose some of the metadata field onto the generated method function. I am proposing:

Flat Mode

/**
 * Finds Pets by status
 *
 * Multiple status values can be provided with comma separated strings
 */
export const findPetsByStatus = <ThrowOnError extends boolean = true>(options: Options<FindPetsByStatusData, ThrowOnError>) => (options.client ?? client).get<FindPetsByStatusResponses, FindPetsByStatusErrors, ThrowOnError>({
    requestValidator: async (data) => await zFindPetsByStatusData.parseAsync(data),
    responseValidator: async (data) => await zFindPetsByStatusResponse.parseAsync(data),
    url: '/pet/findByStatus/MultipleExamples',
    ...options
});

findPetsByStatus.metadata = {
  name: 'findPetsByStatus',
  method: 'GET',
  url: '/pet/findByStatus/MultipleExamples',
  requestSchema: zFindPetsByStatusData,
  responseSchema: zFindPetsByStatusResponse
};

Instance Mode

class Sdk extends HetAPIClient {
    /**
     * Finds Pets by status
     *
     * Multiple status values can be provided with comma separated strings
     */
    public findPetsByStatus<ThrowOnError extends boolean = true>(options: Options<FindPetsByStatusData, ThrowOnError>) {
        return (options.client ?? this.client).get<FindPetsByStatusResponses, FindPetsByStatusErrors, ThrowOnError>({
            requestValidator: async (data) => await zFindPetsByStatusData.parseAsync(data),
            responseValidator: async (data) => await zFindPetsByStatusResponse.parseAsync(data),
            url: '/pet/findByStatus/MultipleExamples',
            ...options
        });
    }
}

Sdk.prototype.findPetsByStatus.metadata = {
  name: 'findPetsByStatus',
  method: 'GET',
  url: '/pet/findByStatus/MultipleExamples',
  requestSchema: zFindPetsByStatusData
  responseSchema: zFindPetsByStatusResponse
};

Alternative

A way to tap into the Hey API's client/client.gen.ts so we can attach metadata ourselves.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions