GithubHelp home page GithubHelp logo

rametta / rapini Goto Github PK

View Code? Open in Web Editor NEW
134.0 5.0 13.0 336 KB

:leafy_green: OpenAPI to React Query (or SWR) & Axios

License: Apache License 2.0

JavaScript 1.47% TypeScript 98.53%
axios codegen generator openapi react-query swagger react swr tanstack-react-query typescript

rapini's Introduction

npm License PR Test

๐Ÿฅฌ Rapini - OpenAPI to React Query (or SWR) & Axios

Rapini is a tool that generates React Query (or SWR) hooks, Axios requests and Typescript types, based on an OpenAPI spec file. The generated code is packaged conveniently so that it can be published as a package on any NPM registry.

Features

  • ๐Ÿšด Generates axios calls for every endpoint, with typed payload.
  • ๐ŸŒ๏ธ Generates custom react hooks that use React Query's useQuery and useMutation hooks for each axios call. Optional to generate custom hooks that use SWR's useSWR hook.
  • ๐Ÿšฃ Generates query keys for every hook.
  • ๐Ÿ‹๏ธ Generates strong typescript types for all inputs, outputs, and options.

Getting Started

Rapini is a CLI tool so you can execute the remote npm package directly for convenience

npx rapini [library] [options]

eg:

# For React Query V3
npx rapini react-query -p path/to/openapi.yaml

# For TanStack Query 4
npx rapini react-query v4 -p path/to/openapi.yaml

# For TanStack Query 5
npx rapini react-query v5 -p path/to/openapi.yaml

# For SWR
npx rapini swr -p path/to/openapi.yaml

This will generate the package code based on an OpenAPI file at path/to/openapi.yaml. The outputted code will be packaged in a way to just publish it as your own NPM package and then import it in your React project.

CLI Arguments & Options

rapini help outputs the following:

Usage: rapini [options] [command]

Generate a package based on OpenAPI

Options:
  -V, --version                    output the version number
  -h, --help                       display help for command

Commands:
  react-query [options] [version]  Generate a Package for TanStack Query V4 or React Query V3
  swr [options]                    Generate a Package for SWR (stale-while-revalidate)
  help [command]                   display help for command

rapini help react-query outputs the following:

Usage: rapini react-query [options] [react-query-version]

Generate a Package for TanStack Query V4 or V5, or legacy React Query V3

Options:
  -p, --path <path>                          Path to OpenAPI file
  -n, --name [name]                          Name to use for the generated package (default: "rapini-generated-package")
  -pv, --package-version [version]           Semver version to use for the generated package (default: "1.0.0")
  -o, --output-dir [directory]               Directory to output the generated package (default: "rapini-generated-package")
  -b, --base-url [url]                       Prefix every request with this url
  -r, --replacer [oldString] [newString...]  Replace part(s) of any route's path with simple string replacements. Ex: `-r /api/v1 /api/v2` would replace the v1 with v2 in every route
  -h, --help                                 display help for command

rapini help swr outputs the following:

Usage: rapini swr [options]

Generate a Package for SWR (stale-while-revalidate)

Options:
  -p, --path <path>                          Path to OpenAPI file
  -n, --name [name]                          Name to use for the generated package (default: "rapini-generated-package")
  -pv, --package-version [version]           Semver version to use for the generated package (default: "1.0.0")
  -o, --output-dir [directory]               Directory to output the generated package (default: "rapini-generated-package")
  -b, --base-url [url]                       Prefix every request with this url
  -r, --replacer [oldString] [newString...]  Replace part(s) of any route's path with simple string replacements. Ex: `-r /api/v1 /api/v2` would replace the v1 with v2 in every route
  -h, --help                                 display help for command

Example Usage

Let's say you have an OpenAPI file that looks like this one.

Once you run the CLI tool to generate the React Query code, you can then cd into the generated directory, run npm install && npm run build then npm publish with your own package name to publish it to your own registry, then import and use it like this:

import { initialize } from "your-custom-package";
import { axiosInstance } from "./your-custom-axios-instance";

// Can even import the generated Typescript Types if needed
import type { Pet } from "your-custom-package";

const config = initialize(axiosInstance);

const { usePets } = config.queries;

const MyComponent = () => {
  const { data, isLoading, isError } = usePets();

  return (
    <ul>
      {data.pets.map((pet) => (
        <li key={pet.id}>{pet.name}</li>
      ))}
    </ul>
  );
};

You must call initialize(axiosInstance) with your custom axios instance. The return value from the initialize will give you an object with everything you need, here is the return value with examples:

import { queryKeys } from "generated-package";
// queryKeys = { pets: () => ['pets'] } ...

const rapini = initialize(axiosInstance);
rapini.queries; // { usePets, usePetById } ...
rapini.mutations; // { useUpdatePet, useDeletePet } ... if generated by SWR, there will be no property `mutations`
rapini.requests; // { pets: () => axios.get<Pet[]>(...) } ...

With Global Config

There may be times when you want extra functionality hooked into each hook's callbacks. You can do this normally by passing options to each hook, but if you want something more global - a config can be provided to the initialize function.

import { initialize, type Config } from "your-custom-package";
import type { QueryClient } from "react-query";

const config: Config = {
  mutations: {
    useCreatePet: (queryClient: QueryClient) => ({
      onSuccess: () => showSuccessNotification(),
      onError: () => showErrorNotification(),
    }),
  },
};

const rapini = initialize(axiosInstance, config);

Important Notes

  • Every request must have an operationId defined. The operationId is used in many places in the final generated code.

rapini's People

Contributors

chihabhajji avatar daniel-pulley avatar moetazbrayek1 avatar phlrss avatar rametta avatar tmo207 avatar yuleicul 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  avatar

rapini's Issues

Use `npx` instead of `npm install -g`

This is just a little suggestion. We could simplify the document of the installation part.

Reduce two steps:

npm install -g rapini
rapini [library] [options]

to just one:

npx rapini [library] [options]

And I can open a PR to update the document

Export union types as objects

When generating enums, it would be good to centralise the options for use in select menus etc

When enums are produced at the moment it creates:

export type Payment = 'Debit' | 'Credit';

Preferentially it could be

export enum Payment {
    Debit = 'Debit',
    Credit = 'Credit'
}

Now you can access array of options:

Object.values(Payment)

TypeError: Cannot read properties of undefined (reading 'split')

(spleeter) โžœ  react-native git:(react-native) โœ— npx rapini react-query -p openapi.yaml
Generating React Query v3 package using OpenApi file openapi.yaml
API name: SETFlowAPI, Version: 1.0
DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
DeprecationWarning: 'createParameterDeclaration' has been deprecated since v4.8.0. Decorators have been combined with modifiers. Callers should switch to an overload that does not accept a 'decorators' parameter.
DeprecationWarning: 'createFunctionDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
/Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/common/util.js:253
        .split("-")
         ^

TypeError: Cannot read properties of undefined (reading 'split')
    at normalizeOperationId (/Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/common/util.js:253:10)
    at makeRequest (/Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/common/requests.js:247:150)
    at makeRequestsPropertyAssignment (/Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/common/requests.js:85:23)
    at /Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/common/requests.js:28:16
    at Array.flatMap (<anonymous>)
    at makeRequests (/Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/common/requests.js:26:42)
    at parseOpenApiV3Doc (/Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/react-query/generator.js:91:47)
    at parse (/Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/react-query/generator.js:83:16)
    at /Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/react-query/generator.js:126:28
    at step (/Users/johndpope/.npm/_npx/d88112f5ad5f60bf/node_modules/rapini/dist/react-query/generator.js:33:23)

Node.js v18.14.0


any help would be great.

https://gist.github.com/cn-johndpope/3597fb777ce43041801d661ca4b75ca7

node 10 - also not working.

npx rapini react-query -p openapi.yaml
npx: installed 25 in 4.631s
Generating React Query v3 package using OpenApi file openapi.yaml
API name: SETFlowAPI, Version: 1.0
DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
(node:18087) UnhandledPromiseRejectionWarning: TypeError: operationId.split(...).flatMap is not a function
at normalizeOperationId (/Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/common/util.js:254:10)
at makeQueryId (/Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/common/queryIds.js:87:65)
at /Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/common/queryIds.js:43:16
at Array.map ()
at makeQueryIds (/Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/common/queryIds.js:41:10)
at parseOpenApiV3Doc (/Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/react-query/generator.js:90:47)
at parse (/Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/react-query/generator.js:83:16)
at /Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/react-query/generator.js:126:28
at step (/Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/react-query/generator.js:33:23)
at Object.next (/Users/johndpope/.npm/_npx/18087/lib/node_modules/rapini/dist/react-query/generator.js:14:53)
(node:18087) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:18087) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

TError = unknown

Hi,
thank you very much for this great library.

I noticed that you're defining all generics by React-Query but didn't provide AxiosError as TError.

Feature request: optionally generate MSW mocks too

In my opinion it would be a great addition for this library to generate MSW mocks too alongside the queries. Mocking API responses is a common use-case while working with an openapi specification when the backend side of the API is not ready yet or we want to use mocks for tests. The handlers would look like this for example. Combined with faker it could be very powerful.
Thank you

Anyof doesn't generate correct response

For example following openapi spec would generate results with any instead of ModeA | ModeB for react-query v4

{"openapi":"3.0.2","info":{"title":"Test","version":"0.1.0"},"paths":{"/":{"get":{"summary":"Read Root","operationId":"read_root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Read Root Get","anyOf":[{"$ref":"#/components/schemas/ModeA"},{"$ref":"#/components/schemas/ModeB"}]}}}}}}}},"components":{"schemas":{"ModeA":{"title":"ModeA","required":["val"],"type":"object","properties":{"val":{"title":"Val","type":"number"}}},"ModeB":{"title":"ModeB","required":["config"],"type":"object","properties":{"config":{"title":"Config","type":"string"}}}}}}

Generated client (truncated):
function makeRequests(axios: AxiosInstance, config?: AxiosConfig) { return { readRootGet: () => axios.request<**any**>({ method: "get", url: / }).then(res => res.data) } as const; }

Clarification on how to use onSuccess / onError with mutation

is it possible to pass this into the given mutations?

wanting to do something like this.... at client level - without rewriting sdk

https://github.com/c121914yu/FastGPT/blob/8c70205940138c75e48fa648b927fafeea1f0e5a/src/hooks/useRequest.tsx

this runs / authenticates fine - but I need to save the token to add to auth header.

           var model:UserLoginModel = {}
            model.userName = username
            model.password = password
            await postMutation.mutate(model)

this code compiles and runs - but I don't see any onSuccess callback.

           var model:UserLoginModel = {}
            model.userName = username
            model.password = password
            await postMutation.mutate(model,{
                onError: (error:any, variables:any, context:any) => {
                    // An error happened!
                    console.log(`๐Ÿ”ฅ error ${error}`)
                  },
                  onSuccess: (data:any, variables:any, context:any) => {
                    console.log("๐ŸŽธ  data:",data)
                    console.log("variables:",variables)
                    console.log("context:",context)
        
                    // let token = data.token
                    // axiosInstance.defaults.headers.common.Authorization = `Bearer ${token}`;
                    // Boom baby!
                  },
            })

// here we are authenticated - but in the body of response - there's a token
the body - is by default undefined - so there's no token - auto populated...
console.log("๐ŸŒฑ success result:",postMutation)
console.log("๐ŸŒฑ success result:",postMutation.result.token ?? "") // FAILS - as the postMutation . data = undefined

๐ŸŒฑ success result: {"context": undefined, "data": undefined, "error": null, "failureCount": 0, "failureReason": null, "isError": false, "isIdle": true, "isLoading": false, "isPaused": false, "isSuccess": false, "mutate": [Function anonymous], "mutateAsync": [Function bound mutate], "reset": [Function bound reset], "status": "idle", "variables": undefined}

can tanstack be made to default to any - instead of undefined?

error trying to run

Have run through the commands in the readme only i get an error when trying to run against react query 4

running node 16.17.0
npm 8.15.0

px rapini react-query -p openapi.yaml -n VC

DeprecationWarning: 'createParameterDeclaration' has been deprecated since v4.8.0. Decorators have been combined with modifiers. Callers should switch to an overload that does not accept a 'decorators' parameter.
DeprecationWarning: 'createFunctionDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
/Users//node_modules/rapini/dist/common/util.js:253
        .split("-")
         ^

TypeError: Cannot read properties of undefined (reading 'split')
    at normalizeOperationId (/Users/node_modules/rapini/dist/common/util.js:253:10)```

The promise rejected with the reason "Missing "operationId" from "get" request with pattern /api/configuration/{orgId}/meterType".]

npx rapini react-query v4 -p openapi.yaml
Generating React Query v4 package using OpenApi file openapi.yaml
API name: SETFlowAPI, Version: 1.0
DeprecationWarning: 'createImportDeclaration' has been deprecated since v4.8.0. Decorators are no longer supported for this function. Callers should switch to an overload that does not accept a 'decorators' parameter.
node:internal/process/promises:279
triggerUncaughtException(err, true /* fromPromise */);
^

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "Missing "operationId" from "get" request with pattern /api/configuration/{orgId}/meterType".] {

I use this yaml
https://gist.github.com/cn-johndpope/3597fb777ce43041801d661ca4b75ca7

I added operationId: to each get /post but no joy.

Typescript support

How can i get the types when using a query?
const { data, isLoading, isError } = useSomeQuery(param1,param2 );

The data always shows as:
const data: UseQueryResult<any, unknown>

newbie help

basically need an example where I can post the body

eg. passing a model in a post.
because you're using the definitions as a hook - it's not clear that I can use this dynamically.
eg.

// REACT HOOKS
here I want to pass in {username,password}
const { data, isLoading, isError } = useLogin({username,password});

it seems trivial example - but I need this dynamic - not set once component is instantiated.
I'm going to have to revert until I can get clarity here.

Generated code incompatible from 5.14.6 to 5.17.9 of @tanstack/react-query

Today when i have updated the @tanstack/react-query depenency, i found out that the latest compatible version is 5.13.4.

Changing the generated local code from:

ts function useRapiniMutation<TData = unknown, TError = unknown, TVariables = void, TContext = unknown>(mutationFn: MutationFunction<TData, TVariables>, config?: (queryClient: QueryClient) => Pick<UseMutationOptions<TData, TError, TVariables, TContext>, "onSuccess" | "onSettled" | "onError">, options?: Omit<UseMutationOptions<TData, TError, TVariables, TContext>, "mutationFn">): UseMutationResult<TData, TError, TVariables, TContext> { const { onSuccess, onError, onSettled, ...rest } = options ?? {}; const queryClient = useQueryClient(); const conf = config?.(queryClient); const mutationOptions: typeof options = { onSuccess: (data: TData, variables: TVariables, context?: TContext) => { conf?.onSuccess?.(data, variables, context); onSuccess?.(data, variables, context); }, onError: (error: TError, variables: TVariables, context?: TContext) => { conf?.onError?.(error, variables, context); onError?.(error, variables, context); }, onSettled: (data: TData | undefined, error: TError | null, variables: TVariables, context?: TContext) => { conf?.onSettled?.(data, error, variables, context); onSettled?.(data, error, variables, context); }, ...rest }; return useMutation({ mutationFn, ...mutationOptions }); }

to

ts function useRapiniMutation<TData = unknown, TError = unknown, TVariables = void, TContext = unknown>(mutationFn: MutationFunction<TData, TVariables>, config?: (queryClient: QueryClient) => Pick<UseMutationOptions<TData, TError, TVariables, TContext>, "onSuccess" | "onSettled" | "onError">, options?: Omit<UseMutationOptions<TData, TError, TVariables, TContext>, "mutationFn">): UseMutationResult<TData, TError, TVariables, TContext> { const { onSuccess, onError, onSettled, ...rest } = options ?? {}; const queryClient = useQueryClient(); const conf = config?.(queryClient); const mutationOptions: typeof options = { onSuccess: (data: TData, variables: TVariables, context: TContext) => { conf?.onSuccess?.(data, variables, context); onSuccess?.(data, variables, context); }, onError: (error: TError, variables: TVariables, context?: TContext) => { conf?.onError?.(error, variables, context); onError?.(error, variables, context); }, onSettled: (data: TData | undefined, error: TError | null, variables: TVariables, context?: TContext) => { conf?.onSettled?.(data, error, variables, context); onSettled?.(data, error, variables, context); }, ...rest }; return useMutation({ mutationFn, ...mutationOptions }); }

makes it compile again:

onSuccess: (data: TData, variables: TVariables, context: TContext) => {
conf?.onSuccess?.(data, variables, context);
onSuccess?.(data, variables, context);
},

Can rapini generate code with responseType: 'blob' for file GET requests?

Hello,
This is a bit similar to issue #31, but I am trying to generate request code for a GET request which returns a PDF file, based on the following OpenAPI 3.0.1 path:

"/api/v1/publisering/vedtakelsesnotat": {
	"get": {
		"tags": [
			"Publisering"
		],
		"summary": "Hent vedtakelsesnotat",
		"operationId": "getVedtakelsesnotat",
		"responses": {
			"200": {
				"description": "OK",
				"content": {
					"application/pdf": {
						"schema": {
							"$ref": "#/components/schemas/StreamingResponseBody"
						}
					}
				}
			}
		},
		"security": [
			{
				"bearerAuth": []
			}
		]
	}
},

This generates the following code:

getVedtakelsesnotat: () =>
	axios
		.request<StreamingResponseBody>({
			method: 'get',
			url: `/api/v1/publisering/vedtakelsesnotat`
		})
		.then((res) => res.data),

However, since this returns a PDF file I would think the generated code should include responseType: 'blob', producing this code instead:

getVedtakelsesnotat: () =>
    axios
        .request<StreamingResponseBody>({
			method: 'get',
			url: `/api/v1/publisering/vedtakelsesnotat`,
			responseType: 'blob'
        })
        .then((res) => res.data),

Or is there a way to add responseType: 'blob' manually when calling this generated request?

clarity on what is needed to correctly create react hook

To be upfront - I'm not sure if my react-native code is faulty - or the yaml or index code generated....

I have this method -

  /api/health/ping:
   
    get:
      operationId: "getPing"
      tags:
      - Health
      responses:
        200:
          description: Success
          content: {}

it declares stuff as unknown

I get the impression - that we should warn users when they get this unknown model returened to bring attention to fix things first.

readonly getPing: () => Promise<unknown>;

readonly useGetPing: (options?: Omit<UseQueryOptions<unknown, unknown, unknown, readonly ["getPing"]>, "queryKey" | "queryFn">) => UseQueryResult<unknown, unknown>;

const axiosInstance:AxiosInstance = axios.create({
  baseURL: "https://api.setflow.com/",
  timeout: 3000,
  timeoutErrorMessage: 'Server down.. Please try after sometime.',
});
console.log("axiosInstance:",axiosInstance);
console.log("initialize:",initialize);
const config = initialize(axiosInstance);
const { useGetPing } = config.queries;
console.log("useGetPing:",useGetPing);

when I implement


function Ping() {
  const { data:any, isLoading, isError } = useGetPing();

  return (
    <div>
      <h1>Ping</h1>

      <div

      >
        {isLoading ? (
          <span>Loading...</span>
        ) : isError ? (
       "error"
        ) : (
         "ok"
        )}
      </div>
    </div>
  )
}

Screenshot 2023-04-01 at 1 50 08 am

then I end up here....
Screenshot 2023-04-01 at 1 50 41 am

is it the unknown return type -

I'll have to cross reference the pets yaml.

react-query cache

When Rapini is generating the hooks with react-query, is cache used? Can i config the cache?
Great package by the way:)

Type imports are not quite right

Hello! I was testing out rapini but noticed that in the exported code, the type imports for TypeScript are just a little off:

import type { AxiosInstance, AxiosRequestConfig } from "axios";
import { useQuery, useMutation, useQueryClient, type QueryClient, type UseMutationOptions, type UseQueryOptions, type MutationFunction, type UseMutationResult, type UseQueryResult } from "react-query";

You can see how it's not handling theimport type syntax probably. I think should probably be

import type { AxiosInstance, AxiosRequestConfig } from "axios";
import { useQuery, useMutation, useQueryClient } from "react-query";
import type { QueryClient, UseMutationOptions, UseQueryOptions, MutationFunction, UseMutationResult, UseQueryResult } from "react-query";

Is that right?

(Suggestion) - Conditional support for UseInfiniteQuery

ts.factory.createIdentifier("useQuery"),

First of all, thank you so much for the awesome life and time saving lib, as the "DX guy" in my team, this is my bread and butter.

So as the title suggests, adding support for the use of paginatable or on scroll infninite query based on either a config file, for example
"infiniteQueryRoutes": ['OperationId(bad idea since not unique / or route'....]

i know this will require the backend to follow some rules, both for hashing the query key (so either the pagination relies on the path params or specific tokens in the query like skip sort limit ....)

Does Rapini generate code which is able to handle files download where the content-type=application/octet-stream?

Hello,
I was wondering if the code that rapini generates is able to handle files served with a content-type of application/octet-stream? When I use insomnia the file is downloaded correctly, however, when using the function created by rapini and a blob it generates a corrupt file.

  return useExportPpt(
    searchCriteria.search || '',
    true,
    {
      enabled: false,
      onSuccess: (response) => {
        const fileName = exportFilename('pptx');
        const data = new Blob([response as BlobPart], {
          type: 'application/octet-stream'
        });
        const url = window.URL.createObjectURL(data);
        const link = document.createElement('a');
        document.body.appendChild(link);
        link.href = url;
        link.setAttribute('download', fileName);
        link.click();
        document.body.removeChild(link);
      }
    }
  );

After executing this code a file corrupt file is produced, it is double the size and contains characters when opened in a text editor which do not exist if you download it by insomnia. Also, the response variable has type unknown.

Any assistance, would be helpful. Thanks!

$ref: ./file.yaml: can't resolve components defined in a different file

Hey,

I want to use components that are defined in different file, but it's impossible to share let's say enum (or any other component).
This makes $ref: files unusable (except to few top level fields like paths or componetns)

package.json

{
  "devDependencies": {
    "rapini": "^1.7.0"
  }
}

spec.yaml

openapi: 3.0.0
info:
  title: 'api'
  version: 0.0.1

paths:
  /a:
    get:
      operationId: getA
      responses:
        '200':
          description: '200'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TypeA'

components:
  schemas:
    # I want to store component type per file
    # but it's impossible to use a component defined
    # in different file
    SharedEnumType:
      type: string
      enum: ['PENDING', 'DONE']

    TypeA:
      $ref: './type_a.yaml'

    TypeB:
      type: object
      properties:
        b:
          $ref: '#/components/schemas/SharedEnumType'

type_a.yaml

type: object
properties:
  a:
    $ref: '#/components/schemas/SharedEnumType' # works with type: string or if this is include in spec.yaml directly

cmd to run:

npx rapini -p spec.yaml -o gen -b /v3

result index.js (see #1):

import type { AxiosInstance, AxiosRequestConfig } from "axios";
import { useQuery, useMutation, useQueryClient, type QueryClient, type UseMutationOptions, type UseQueryOptions, type MutationFunction, type UseMutationResult, type UseQueryResult } from "react-query";
export type SharedEnumType = "PENDING" | "DONE";
export type TypeA = ./type_a.yaml; // #1 HERE
export type TypeB = {
    b?: SharedEnumType;
};

React Query v4 plans?

Hi @rametta !

We just started to use rapini which seems to be a real nice fit in our stack. The installation/setup experience was pretty much plugnplay. Do you have any plans bumping up to react-query v4? Noticed some fork with that but have not investigated myself if there is more to it than these small changes: https://github.com/tawandachiteshe/rapini/commits/main

Or any other plans for the project would ofc also be interesting to hear.

Thanks for sharing your work!

Br,
Oscar

Evaluation report (with Vue 3 + Vue Query)

I've tried to use this library for my Vue 3 app.
With minor tweaks, it's possible to use (change a few imports and that's it).
However it has all the same reactivity issues out of the box as the ones mentioned in anymaniax/orval#852

Kind of an advantage over ovral that I've noticed is that rapini does .then((res) => res.data), for axios requests, so you don't have to type .data every time. Same can be disadvantageous as it limits rare use-cases when you might need response headers.

On the topic of headers, we have "X-Api-Key" header required for each request, but rapini doesn't seem to pass it, yet requires it to be passed which is a bit annoyuing. Orval seems to ignore it altogether so I set it in the global axios interceptors.

Also, on the topic of the same header - it was producing invalid TS, failing to transform X-Api-Key into a valid argument name like XApiKey.

Other disadvantages would be less customization and not as complete of a solution IMO at first glance.

I hope this helps maintainers to improve and helps users in their research, cheers!

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.