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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions