Giter Club home page Giter Club logo

openapi-typescript-fetch's People

Contributors

ajaishankar avatar hpohlmeyer avatar smaspe avatar xmlhexagram avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

openapi-typescript-fetch's Issues

Problem with Get Method when i send complexe object

Hello,

Primary, thank you for you excellente library,

I have a problem when i send an object with an Array of Object, this library converted my array into the string "Object Object"

My object
{ "levelExperience.skill": [ { "id": "018e3d92-389f-70bc-bcfa-5629ca7c4d4c", "levelExperience": null } ], }

This conversation to query string
image

I think for fix this problem, i need to replace the query encoder of library by my self encoder.

It's possible of replace encoder ?

`response.ok` is always true

👋 thank you for this great module.

I noticed, that an APIError is thrown if response.ok is falsy:

if (result.ok) {
return result
}
throw new ApiError(result)

ok is omitted in ApiError constructor:

constructor(response: Omit<ApiResponse, 'ok'>) {

This means, that you always have true for ok, because it is not part of the error response.

It's not a real issue, but I expected that I could check for ok by myself to separate abnormal HTTP-statuses (4xx, 5xx) from network problems.
I suggest removing ok from the result, or do not throw an error if the response is not ok.

Inaccessible unique symbol error when using `FetchErrorType`

When I attempt to use FetchErrorType<F>, TypeScript emits the following error:

The inferred type of makeHook1 references an inaccessible 'unique symbol' type. A type annotation is necessary.
ts(2527)

I investigated this and discovered that the following const declaration (on line 65) is the cause of the problem.

// private symbol to prevent narrowing on "default" error status
const never: unique symbol = Symbol()
type _OpErrorType<T> = {
[S in Exclude<keyof T, 200 | 201>]: {
status: S extends 'default' ? typeof never : S
data: T[S]
}
}[Exclude<keyof T, 200 | 201>]

If I modify that source code to export the type, the error I mentioned disappears with no further modifications needed in my own code:

// private symbol to prevent narrowing on "default" error status
-const never: unique symbol = Symbol()
+export const never: unique symbol = Symbol()

type _OpErrorType<T> = {
  [S in Exclude<keyof T, 200 | 201>]: {
    status: S extends 'default' ? typeof never : S
    data: T[S]
  }
}[Exclude<keyof T, 200 | 201>]

Would it be feasible to add an export to this constant to resolve the "inaccessible unique symbol" error here?

Footnotes

  1. makeHook is the name of the calling function in my code.

CreateFetch query param types incorrect

Hi, given some parameters in the query, the types in the parameters seem to be incorrect:

Given the following types:

createX: {
    parameters: {
      query: {
        includeTags?: true | false;
      };      

When we try to create the fetch command:

fetcher
    .path('/api/v1/x')
    .method('post')     
    .create({
      includeTags: true, // The type is true | 1, when it should be a boolean
    })

I suspect it has something to do with this line here:

? _CreateFetch<OP, { [K in keyof Q]: true | 1 }>

Is anyone else seeing this issue?

OpArgType is Record<string, never> if operation has header parameters and requestBody

OpArgType returns Record<string, never>under specific conditions:

  • parameters contains none of path / query / body props
  • requestBody is present

Suggested fix:

export declare type OpArgType<OP> = OP extends {
    parameters?: {
        path?: infer P;
        query?: infer Q;
        body?: infer B;
+       header?: unknown;
    };
    requestBody?: {
        content: {
            'application/json': infer RB;
        };
    };
} ? P & Q & (B extends Record<string, unknown> ? B[keyof B] : unknown) & RB : Record<string, never>;

Below is an example of code that is affected by this bug.

const example = Fetcher.for<{
  '/hello/world': {
    get: {
      parameters: {
        // only header parameters
        header: {
          foo: string;
        };
      };
      requestBody: {
        content: {
          'application/json': {
            // non-empty request body
            bar: boolean;
          };
        };
      };
    };
  };
}>();
const helloWorld = example.path('/hello/world').method('get').create();

helloWorld({ bar: false }); // Record<string, never>

OpenApi3 and "application/json;charset=UTF-8"

Thanks for you nice work!

We use application/json;charset=UTF-8 and not just application/json as it is assumed in types.d.ts and hence the response data type becomes unknown.

I wonder if it's possible to extend

Fetcher.for<paths>();
to optional
Fetcher.for<paths, 'application/json;charset=UTF-8'>();

and/or

fetcher.path('/xzy').method('get').create();
to optional
fetcher.path('/xyz').method<'application/json;charset=UTF-8'>('get').create();

Running in Jest tests React-Testing-Library?

Has anybody got this to successfully work in a jest test with RTL or anything else for unit tests? I tried using the node-fetch polyfill, but I cannot seem to get it to work. Maybe I am doing something wrong? Was wondering if anybody else has figured it out and had any tips?

Optional args instead of Record<string, never>

Hi, thank you for your cool library.

I was wondering if it is possible to make arg parameter optional when there are no arguments (or there may be none) instead of Record<string, never>.

Right now we have to write

const getMe = fetcher
    .path('/my')
    .method('get')
    .create();

getMe({}); // note {}

for typescript to not yell the error

Missing responses interfaces

I have an openapi spec for authentification with few responses types:

"/authentication": {
  "post": {
    "tags": [
      "authenticate_user"
    ],
    "operationId": "authenticate",
    "requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Auth"
          }
        }
      },
      "required": true
    },
    "responses": {
      "200": {
        "description": "Returns current authentication state.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/AuthResponse"
            }
          }
        }
      },
      "4XX": {
        "description": "",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseObject"
            }
          }
        }
      },
      "5XX": {
        "description": "",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseObject"
            }
          }
        }
      }
    }
  }
}

The AuthResponse & ErrorResponseObject are correctly created, but ErrorResponseObject is not used in case of 4XX or 5XX errors.

This is the generated file:

import * as runtime from '../runtime';
import type {
  Auth,
  AuthResponse,
  ErrorResponseObject,
} from '../models';
import {
    AuthFromJSON,
    AuthToJSON,
    AuthResponseFromJSON,
    AuthResponseToJSON,
    ErrorResponseObjectFromJSON,
    ErrorResponseObjectToJSON,
} from '../models';

export interface AuthenticateRequest {
    auth: Auth;
}

/**
 * 
 */
export class AuthenticateUserApi extends runtime.BaseAPI {

    /**
     */
    async authenticateRaw(requestParameters: AuthenticateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AuthResponseErrorResponseObject>> {
        if (requestParameters.auth === null || requestParameters.auth === undefined) {
            throw new runtime.RequiredError('auth','Required parameter requestParameters.auth was null or undefined when calling authenticate.');
        }

        const queryParameters: any = {};

        const headerParameters: runtime.HTTPHeaders = {};

        headerParameters['Content-Type'] = 'application/json';

        const response = await this.request({
            path: `/authentication`,
            method: 'POST',
            headers: headerParameters,
            query: queryParameters,
            body: AuthToJSON(requestParameters.auth),
        }, initOverrides);

        return new runtime.JSONApiResponse(response, (jsonValue) => AuthResponseFromJSON(jsonValue));
    }

    /**
     */
    async authenticate(requestParameters: AuthenticateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AuthResponse> {
        const response = await this.authenticateRaw(requestParameters, initOverrides);
        return await response.value();
    }

}

As you can see ErrorResponseObject is imported but never used.

This creates multiple issues down the line. The main one is that I cannot use the ErrorResponseObject attributes to let the user know what the error actually is.

Generating warnings around source maps on packaged versions:

WARNING in ./node_modules/openapi-typescript-fetch/dist/esm/types.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/var/app/node_modules/openapi-typescript-fetch/src/types.ts' file: Error: ENOENT: no such file or directory, open '/var/app/node_modules/openapi-typescript-fetch/src/types.ts'
  @ ./node_modules/openapi-typescript-fetch/dist/esm/index.js 2:0-35 3:0-29

Not sure if the solution is just to add sourceMap: false to the package-level tsconfigs, or if there's a reason to keep them, for production for some reason, otherwise I'd guess you'd have to add src/ to the package, which inflates package size.

Thanks for the awesome library!

Variable baseUrl

I'm working on a project where we talk to many different instances of the same API that live on different hosts. Currently, it seems like I have to create separate Fetcher for each host, which ends up making our code pretty awkward. I'm not sure the best way to handle this, but I have two ideas.

  1. Expose an option to pass in the baseUrl somehow in the fetch
  2. Provide an alternative api that doesn't require you to create a Fetcher before calling an endpoint

Remove coalescing of OpErrorType with unknown.

Firstly, thank you for creating this library, it's fantastic.

The code in question:

export type OpErrorType<OP> = Coalesce<
  _OpErrorType<OpResponseTypes<OP>>,
  unknown
>

If there are no error types defined for an operation, OpErrorType is coalesced to unknown. I think this should remain as never because the error type is known, it's just empty. In our codebase we end up taking the union of FetchErrorType with ApiError to create a union type of all known error types an operation can throw. If FetchErrorType is unknown, the resulting union is unknown instead of just ApiError, which is not desirable in our case.

type Undesirable = unknown | ApiError; // unknown
type Desirable = never | ApiError; // ApiError

CommonJS and ESM lack appropriate extensions

Using this library with vite and pre-render, produces the following error:

[vite-plugin-ssr:autoFullBuild] Named export 'Fetcher' not found. The requested module 'openapi-typescript-fetch' is a CommonJS module, which may not support all module.exports as named exports.

The reason is that both CommonJS and ESM exports are using the .js extension. If package.json#type is commonjs (default), .js can be used for CommonJS but .mjs should be used for ESM. And if package.json#type is module, .js can be used for ESM output, but .cjs should be used for CommonJS.

I think "type": "module" is better because the .js extension can be used for NodeJS modules and browsers alike, making mandatory .cjs only for CommonJS files.

Invalid Typescript schema requested for POST

Hi, love this initiative. It's allowed me to remove hundreds of lines of code.

I've got a strange problem trying to wire up a POST request using the standard approach:

export const submitForm = fetcher.path('/form/{formId}/submit').method('post').create();

The Swagger API definition requests formId as a parameter and formFields as the post body, but the returned function requests the following input, a intersection between an object and an array, which is impossible to provide:

image

I might be doing something wrong, but it seems like a potential bug. Here's the type for the request:

"/form/{formId}/submit": {
    post: {
      parameters: {
        path: {
          formId: string;
        };
      };
      responses: {
        /** Success */
        200: {
          content: {
            "text/plain": components["schemas"]["FormModel"];
            "application/json": components["schemas"]["FormModel"];
            "text/json": components["schemas"]["FormModel"];
          };
        };
      };
      requestBody: {
        content: {
          "application/json":
            | components["schemas"]["FormFieldInputModel"][]
            | null;
          "text/json": components["schemas"]["FormFieldInputModel"][] | null;
          "application/*+json":
            | components["schemas"]["FormFieldInputModel"][]
            | null;
        };
      };
    };
  };


Question: Return all operations

Hi!

I'm trying to create some code that will generate all the available operations based on the paths automatically, so you don't need to create another fetch.path("route").method("method").create() every time you add another path in your api spec.

Anyone who had any luck with this?

I tried something like the below and couldn't really think it to the end

import { ApiPaths, paths } from "./schema"

const fetch = Fetcher.for<paths>();

const createAll = () => {
  const allPaths = Object.keys(ApiPaths);

  const all = {};

  for (const route of allPaths) {
    all[route] = fetch.path(route).method("get").create();
  }

  return all;
};

Typescript 5 compatibility

With Typescript 4.6.2 everything works as intended.
When updating to Typescript 5.0.4, this error appeared for method():

Argument type "get" is not assignable to parameter type M

image

Cheers,
Para

feature request: replace url context while generating

Hi in toolings like Orval and Rapini you can replace the paths context. This is handy for clients who use a specific context in their frontend to point to that api. So example my service swagger tells endpoint is /profile but in our application we use /api/profile to internally forward to that service container.

Is this a feature you think adds value for your library? At the moment i can't use this library because of it but im first checking.

Allow responses other that json (or plain text)

Atm, other formats are not allowed. To be backwards compatible, one option could be to always also return the original response

async function getResponseData(response: Response) {
// ...
const text = await response.clone().text()
//...
}
async function fetchJson(url: string, init: RequestInit): Promise<ApiResponse> {
//...
 const result = {
	...response,
    data,
  }
//...
}

Can't modify message of `ApiError` in middleware

I wanted to do some quick handling to set the err.message of ApiErrors to something in my body, so I whipped up a quick middleware that looks like this:

fetcher.use(async (url, init, next) => {
  try {
    return await next(url, init);
  } catch (err) {
    if (err instanceof ApiError && err.data?.message) {
      err.message = err.data.message;
    }
    throw err;
  }
});

However, I found that the error would still use the default message. I noticed that this is because of this bit: https://github.com/ajaishankar/openapi-typescript-fetch/blob/main/src/fetcher.ts#L207-L209. While I can make my own class that wraps errors to work around this, I would lose that nice getActualType typing. Would you be open to changing the ApiError constructor to respect an existing message if one has been set?

If you have a suggestion of a more "correct" way to do this, I'm all ears, but I use err.message as kind of a generic fallback in a lot of places in my code, and I don't want to have to make everything fetcher response body-aware to display better error messages.

String request payload is incorrectly serialized

Relevant part of api.yml:

      requestBody:
        content:
          application/json:
            schema:
              type: string

The generated function has correct signature: myFunc(arg: string).
However, fetcher.ts only handles objects and arrays. The string "foo" is this serialized as {"0":"f","1":o","2":"o"}

Is there any workaround atm?

.create() incorrectly expects single argument

🗣 Discussion

Defining and OpenAPI3 operation with both a requestBody and query causes the .create() signature to expect an argument for the query portion.

export type paths = {
  '/openapiv3/body': {
    post: {
      parameters: {
        path: { id: number }
        query: { name: string }
      }
      requestBody: {
        content: {
          'application/json': { 200: { schema: Data } }
        }
      }
    }
  }
}

const fetcher = Fetcher.for<paths>()
fetcher.path('/openapiv3/body').method('post').create()
// Expected 1 arguments, but got 0.

image

License Question

Thanks again for creating this incredibly useful library. I would love to incorporate it into a project I am working on although I wanted to check the licensing terms. I noticed that the package.json says a license type is ISC although there wasn't a separate license file in the repo. Just to clarify, are others free to use this software in their own projects (i.e. MIT / ISC license)?

Kind regards,
Aidan

Do not parse the response, let the user do it manually

To better stick to fetch or node-fetch specs, the responsability to parse the JSON response should be left to the user...
(In fetch specs, this is done by calling the async API response.json())

The problem in openapi-typescript-fetch code is that the corresponding async getResponseData API is always called, no matter what the returned HTTP code is.

This is causing issues, for example when an endpoint returns the HTTP code 204 (no content) with a zero bytes response body, which is totally valid. In this case this line will throw an exception (actually thrown by node-fetch implementation).

A simple (but breaking) fix is to return a json() async function in the returned result of fetchJson :

async function fetchJson(url: string, init: RequestInit): Promise<ApiResponse> {
  const response = await fetch(url, init)

  if (response.ok) {
    return {
      headers: response.headers,
      url: response.url,
      ok: response.ok,
      status: response.status,
      statusText: response.statusText,
      json: async (): Promise<any> => await getResponseData(response)
    };
  }

  throw new ApiError(result)
}

And --from looking at the above code-- why not simply returning the response object if response.ok is true ?
(IMHO, getResponseData should disappear)

Your feedback is welcome!
Apart from that, thank you very much for this very useful library!

Don't send `application\json` content-type header with empty body on GET requests

This library works great, but I have noticed issues with GET requests that have no request body on our backend API. The getFetchParams() always sends the Content-Type header as application\json, which throws the following error because the server expects a json body whenever that header is present:

"400 BadRequest: Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)"

We can manually override this by setting Content-Type to */* but it would be nice if it would check if there is body data before setting the content type header.

Suggested Fix:

function getFetchParams(request: Request) {
  const payload = { ...request.payload } // clone payload

  const path = getPath(request.path, payload)
  const query = getQuery(request.method, payload, request.queryParams)
- const headers = getHeaders(request.init?.headers)
+ const headers = sendBody(request.method) ? getHeaders(request.init?.headers): new Headers(request.init?.headers)
  const url = request.baseUrl + path + query

  const init = {
    ...request.init,
    method: request.method.toUpperCase(),
    headers,
    body: getBody(request.method, payload),
  }

  return { url, init }
}

Deleted payload when repeated in body

We have the {id} of the rest api's path also included in the body of the request. That might be a questionable choice, but is as it is.

Unfortunately, atm all values of the path and the query get deleted from the body payload. I must admit I'm not entirely sold on mixing path, query and body into a single object, but if so, deleting values which are specified in the api schema as needed for the request body is a problem (for me).

Can that be solved with like

function getPath(path: string, payload: Record<string, any>) {
  return path.replace(/\{([^}]+)\}/g, (_, key) => {
    const value = encodeURIComponent(payload[key])
    if ( (payload as RequestBody)[key] === undefined ) {
		delete payload[key]
	}
    return value
  })
}

Add config link

Hi, guys!

After reading the README.md, it is not clear what settings can be used for configuration openapi-typescript-fetch.

These settings are in openapi-generator repository.

Can I add a link to the configuration in the README.md?

Array that contains another objects being serialized to [Object]

Hi! I don't know if this should be supported, I don't know openAPI well yet. But I'm getting an error when it tries to serialize an array of objects, like using this spec:

{

    "/transactions/{transaction_id}/capture": {
      "post": {
        "summary": "Capturando uma transação posteriormente",
        "description": "Essa rota é utilizada para capturar uma transação, após aprovada, utilizando o token ou o ID da transação.",
        "operationId": "capturando-uma-transacao-posteriormente",
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "description": "Id ou o token da transação a ser capturada",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "name": "amount",
            "in": "query",
            "description": "Valor a ser capturado. Deve ser passado em centavos. Ex: R$ 10.00 = 1000.",
            "required": true,
            "schema": { "type": "integer", "format": "int32" }
          },
          {
            "name": "split_rules",
            "in": "query",
            "description": "Regras de divisão da transação",
            "schema": {
              "items": {
                "properties": {
                  "recipient_id": {
                    "type": "string",
                    "description": "Id do recebedor"
                  },
                  "liable": {
                    "type": "boolean",
                    "description": "Se o recebedor é responsável ou não pelo chargeback. Default `true` para todos os recebedores da transação."
                  },
                  "charge_processing_fee": {
                    "type": "boolean",
                    "description": "Se o recebedor será cobrado das taxas da criação da transação. Default `true` para todos os recebedores da transação."
                  },
                  "percentage": {
                    "type": "integer",
                    "description": "Qual a porcentagem que o recebedor receberá. Deve estar entre 0 e 100. Se amount já está preenchido, não é obrigatório",
                    "format": "int32"
                  },
                  "amount": {
                    "type": "integer",
                    "description": "Qual o valor da transação o recebedor receberá. Se percentage já está preenchido, não é obrigatório",
                    "format": "int32"
                  },
                  "charge_remainder": {
                    "type": "boolean",
                    "description": "Se o recebedor deverá pagar os eventuais restos das taxas, calculadas em porcentagem. Sendo que o default vai para o primeiro recebedor definido na regra."
                  }
                },
                "required": ["recipient_id"],
                "type": "object"
              },
              "type": "array"
            }
          },
          {
            "name": "metadata",
            "in": "query",
            "description": "Metadata de informações adicionais, caso queira incluir, i.e: Id do pedido, nome do produto, etc.",
            "schema": { "type": "string", "format": "json" }
          }
        ],
        "responses": {
          "200": {
            "description": "200",
          }
        },
        "deprecated": false
      }
    }
  }
}

the split_rules item get in query string as:

{
    "url": "/transactions/18929604/capture?amount=10695&split_rules=%5Bobject+Object%5D&split_rules=%5Bobject+Object%5D",
}

Is the schema wrong, misusage or a nasty bug?

Unknown response types with OpenApi v3

Hi,

I use OpenApi3 and I noticed that when loading my types into Fetcher.for<paths>() it doesn't shows my response data types properly. All responses types becomes as unknown.

But when generating types from swagger v2 all response types are shown correctly and everything works perfectly fine.

Is it a matter of not fully suport for OpenApi3 or am I doing something wrong ?

POST with same property name in path as well as in body gets removed

As an example, say you have a POST endpoint defined as:

POST /api/notes/id/{id}
that expects a body that looks like:

{
  id: 1,
  text: 'xyz'
}

Because the path and the body have a property with the same name, it ends up breaking. In this example, "id" gets put in the path, but then gets removed from the body payload that gets sent in the request.

I narrowed this down to being a problem in getFetchParams(), where the getPath() function ends up deleting keys from the payload. The way the code is written, I see why this is a necessity. I am wondering if there are any suggestions?

One thought I had was to add a third optional parameter to the function that create() returns that can be an array of strings for "keys to persist into body payload"

delete payload[key]

Typing fetch errors

First of all thanks for this library, it's really useful 👍

I'm not sure how it is suppose to work but I'm assuming to get a type on error in the .catch(error => {}) callback one should do something like this if (error instanceof ApiError)? Is that right?

Additionally, would it be possible to take into account the defined return type for certain HTTP error statuses from schema.ts?
Like these: https://github.com/drwpow/openapi-typescript/blob/main/tests/v3/expected/petstore.ts#L423-L426
Here it is unknown but it is possible to return a custom JSON object on 400 as well.
Would be really nice to have that type on error.data. Not sure yet how it could be typed conditional on the status code defined in the OA spec.

(I'm dealing with OpenAPI 3.0 in my case)

Issue with post middleware when it clones the response

Hi all,

First of all, thank you for you excellent library.

I wanted to let you know I found an issue while using a custom post middleware in my autogenerated client. It seems that the autogenerated runtime.ts file is passing a cloned response, which can lead to timeout issues when dealing with large responses.

This is part of the code of the autogenerated runtime.ts file that I updated:

for (const middleware of this.middleware) {
  if (middleware.post) {
      response = await middleware.post({
          fetch: this.fetchApi,
          url: fetchParams.url,
          init: fetchParams.init,
          response: response, // response.clone() method was deleted because it doesn't support large responses
      }) || response;
  }
}

I'm wondering if this change may cause unexpected problems and if you have found any better approach for this.

Thank you for your attention to this matter. Looking forward to your insights.

🚩 Unmaintained?

@ajaishankar if you are maintaining this repo please close this.

Since weekly downloads of openapi-typescript are on the rise and this repo is consuming its output a word or two about the future of this repo would be appreciated - I guess by others too.

Thanks in advance!

[Feature Request] Expose `TypedFetch` type

Exposing the existing TypedFetch type from the package would allow for easier creation of wrapper functions.

My use case is using openapi-typescript-fetch in combination with react-query. Every API calls needs to be wrapped with a useQuery call. To reduce boilerplate code, I have written a small function that does that for me. It currently looks like this:

// Definition
function generateQueryHook<P extends keyof paths, M extends keyof paths[P]>(
  queryKey: string,
  path: P,
  method: M
) {
  const apiCall = api.path(path).method(method).create();
  // ...
}

// Usage
const useUser = generateQueryHook("User", "/user/{id}", "post");

This works, but is very limiting, since I am forced to build the API call inside the function. My preferred way to do it would be:

// Definition
function generateQueryHook<T>(queryKey: string, apiCall: TypedFetch<T>) {
  // ...
}

// Usage
const useUser = generateQueryHook("User", api.path("/user/{id}").method("post").create())

By exposing TypedFetch from the package, building wrappers like this would be way easier.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.