├── .gitignore ├── README.md ├── examples ├── config.js ├── generated │ ├── example.d.ts │ ├── example.js │ ├── pix.d.ts │ └── pix.js └── openapi.json ├── package.json ├── src ├── generator.js ├── generatorApi.js ├── generatorApiTypes.js ├── generatorHook.js ├── generatorHookTypes.js ├── generatorTypes.js ├── index.js └── utils.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # builds 7 | build 8 | dist 9 | artifacts 10 | .rpt2_cache 11 | coverage 12 | 13 | # misc 14 | .DS_Store 15 | .env 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | .next 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | .history 26 | size-plugin.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # swagger-to-react-query WIP 2 | 3 | ## Try 4 | 5 | ```bash 6 | $ git clone https://github.com/elsangedy/swagger-to-react-query.git 7 | $ cd swagger-to-react-query/examples 8 | $ node ../src/index config.js 9 | $ // or 10 | $ npx swagger-to-react-query config.js 11 | ``` 12 | 13 | 14 | ```js 15 | const addToken = (request) => { 16 | const token = authService.getToken() 17 | if (token) { 18 | request.headers.set('authorization', `Bearer ${token}`) 19 | } 20 | } 21 | const refreshToken = async ({ request }) => { 22 | try { 23 | await authService.refreshToken() 24 | addToken(request) 25 | } catch (e) { 26 | authService.logout() 27 | } 28 | } 29 | 30 | // https://github.com/sindresorhus/ky 31 | extendApi({ 32 | prefixUrl: API_URL, 33 | hooks: { 34 | beforeRequest: [addToken], 35 | beforeRetry: [refreshToken], 36 | }, 37 | }) 38 | ``` 39 | -------------------------------------------------------------------------------- /examples/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | apis: [ 3 | { 4 | name: 'Nestjs Example API', 5 | input: { 6 | url: 'https://nestjs-example.now.sh/json', 7 | }, 8 | output: { 9 | path: 'generated', 10 | file: 'example', 11 | }, 12 | kyOptions: { 13 | prefixUrl: 'https://nestjs-example.now.sh', 14 | throwHttpErrors: false, 15 | }, 16 | }, 17 | { 18 | name: 'PIX', 19 | input: { 20 | json: require('./openapi.json'), 21 | }, 22 | output: { 23 | path: 'generated', 24 | file: 'pix', 25 | }, 26 | kyOptions: { 27 | prefixUrl: 'https://pix.com', 28 | throwHttpErrors: false, 29 | retry: { 30 | statusCodes: [401], 31 | }, 32 | }, 33 | }, 34 | ], 35 | } 36 | -------------------------------------------------------------------------------- /examples/generated/example.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | import ky, { Options } from 'ky' 4 | import { QueryOptions, QueryResult, MutationOptions, MutateFunction, MutationResult } from 'react-query' 5 | 6 | export const getApi: { (): typeof ky } 7 | 8 | export const setApi: { (newApi: typeof ky ): void } 9 | 10 | export const extendApi: { (options: Options ): void } 11 | 12 | export type User = { id: string; name: string } 13 | 14 | export type CreateUserDto = { name: string } 15 | 16 | export type UpdateUserDto = { name: string } 17 | 18 | export type Post = { id: string; title: string } 19 | 20 | export type CreatePostDto = { title: string } 21 | 22 | export type UpdatePostDto = { title: string } 23 | 24 | export const queryUsersControllerFindMany: { (options?: Options): Promise } 25 | export const useQueryUsersControllerFindMany: { (config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 26 | 27 | export const mutationUsersControllerCreate: { (options?: Options): { (body?: CreateUserDto | [void, void, CreateUserDto, Options]): Promise } } 28 | export const useMutationUsersControllerCreate: { (config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 29 | 30 | export type UsersControllerFindByIdPathParams = { id: string } 31 | export const queryUsersControllerFindById: { (pathParams?: UsersControllerFindByIdPathParams, options?: Options): Promise } 32 | export const useQueryUsersControllerFindById: { (pathParams?: UsersControllerFindByIdPathParams, config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 33 | 34 | export type UsersControllerUpdatePathParams = { id: string } 35 | export const mutationUsersControllerUpdate: { (pathParams?: UsersControllerUpdatePathParams, options?: Options): { (body?: UpdateUserDto | [UsersControllerUpdatePathParams, void, UpdateUserDto, Options]): Promise } } 36 | export const useMutationUsersControllerUpdate: { (pathParams?: UsersControllerUpdatePathParams, config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 37 | 38 | export type UsersControllerDeletePathParams = { id: string } 39 | export const mutationUsersControllerDelete: { (pathParams?: UsersControllerDeletePathParams, options?: Options): { (body?: void | [UsersControllerDeletePathParams, void, void, Options]): Promise } } 40 | export const useMutationUsersControllerDelete: { (pathParams?: UsersControllerDeletePathParams, config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 41 | 42 | export const queryPostsControllerFindMany: { (options?: Options): Promise } 43 | export const useQueryPostsControllerFindMany: { (config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 44 | 45 | export const mutationPostsControllerCreate: { (options?: Options): { (body?: CreatePostDto | [void, void, CreatePostDto, Options]): Promise } } 46 | export const useMutationPostsControllerCreate: { (config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 47 | 48 | export type PostsControllerFindByIdPathParams = { id: string } 49 | export const queryPostsControllerFindById: { (pathParams?: PostsControllerFindByIdPathParams, options?: Options): Promise } 50 | export const useQueryPostsControllerFindById: { (pathParams?: PostsControllerFindByIdPathParams, config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 51 | 52 | export type PostsControllerUpdatePathParams = { id: string } 53 | export const mutationPostsControllerUpdate: { (pathParams?: PostsControllerUpdatePathParams, options?: Options): { (body?: UpdatePostDto | [PostsControllerUpdatePathParams, void, UpdatePostDto, Options]): Promise } } 54 | export const useMutationPostsControllerUpdate: { (pathParams?: PostsControllerUpdatePathParams, config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 55 | 56 | export type PostsControllerDeletePathParams = { id: string } 57 | export const mutationPostsControllerDelete: { (pathParams?: PostsControllerDeletePathParams, options?: Options): { (body?: void | [PostsControllerDeletePathParams, void, void, Options]): Promise } } 58 | export const useMutationPostsControllerDelete: { (pathParams?: PostsControllerDeletePathParams, config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 59 | 60 | -------------------------------------------------------------------------------- /examples/generated/example.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | import ky from 'ky' 4 | import { useQuery, useMutation } from 'react-query' 5 | 6 | let api = ky.create({ 7 | "prefixUrl": "https://nestjs-example.now.sh", 8 | "throwHttpErrors": false 9 | }) 10 | 11 | export const getApi = () => api 12 | 13 | export const setApi = (newApi) => { 14 | api = newApi 15 | } 16 | 17 | export const extendApi = (options) => { 18 | api = getApi().extend(options) 19 | } 20 | 21 | const requestFn = async ({ url, method, pathParams, queryParams, ...rest }) => { 22 | const urlPathParams = url.match(/{([^}]+)}/g) 23 | 24 | if (urlPathParams) { 25 | url = urlPathParams.reduce((acc, param) => acc.replace(param, pathParams[param.replace(/{|}/g, '')]), url) 26 | } else { 27 | queryParams = pathParams 28 | } 29 | 30 | if (url.charAt(0) === '/') { 31 | url = url.replace('/', '') 32 | } 33 | 34 | const response = await api(url, { 35 | method, 36 | ...rest, 37 | searchParams: { 38 | ...(rest.searchParams || {}), 39 | ...queryParams 40 | } 41 | }) 42 | 43 | let data 44 | 45 | try { 46 | const contentType = (response.headers.get('content-type') || '').split('; ')[0] 47 | 48 | const responseType = 49 | { 50 | 'application/json': 'json', 51 | 'application/pdf': 'blob' 52 | }[contentType] || 'text' 53 | 54 | data = await response[responseType]() 55 | } catch (e) { 56 | data = e.message 57 | } 58 | 59 | if (!response.ok) { 60 | const error = { 61 | data, 62 | status: response.status, 63 | message: `Failed to fetch: ${response.status} ${response.statusText}` 64 | } 65 | 66 | throw error 67 | } 68 | 69 | return data 70 | } 71 | 72 | const queryFn = (options = {}) => (url, pathParams = {}, queryParams = {}) => { 73 | const controller = new AbortController() 74 | const { signal } = controller 75 | 76 | const promise = requestFn({ 77 | url, 78 | method: 'get', 79 | pathParams, 80 | queryParams, 81 | signal, 82 | ...options 83 | }) 84 | 85 | // cancel the request if React Query calls the 'promise.cancel' method 86 | promise.cancel = () => { 87 | controller.abort('Query was cancelled by React Query') 88 | } 89 | 90 | return promise 91 | } 92 | 93 | const mutationFn = ( 94 | method, 95 | url, 96 | pathParams = {}, 97 | queryParams = {}, 98 | options = {} 99 | ) => (body = {}) => { 100 | if (Array.isArray(body)) { 101 | pathParams = { ...pathParams, ...(body[0] || {}) } 102 | queryParams = { ...queryParams, ...(body[1] || {}) } 103 | options = { ...options, ...(body[3] || {}) } 104 | body = body[2] 105 | } 106 | 107 | const request = { 108 | url, 109 | method, 110 | pathParams, 111 | queryParams, 112 | ...options 113 | } 114 | 115 | if (method !== 'delete') { 116 | try { 117 | request[body.toString() === '[object FormData]' ? 'body' : 'json'] = body 118 | } catch(e) { 119 | } 120 | } 121 | 122 | return requestFn(request) 123 | } 124 | 125 | export const queryUsersControllerFindMany = (options) => queryFn(options)('/users') 126 | export const useQueryUsersControllerFindMany = (config, options) => useQuery({ 127 | queryKey: ['/users'], 128 | queryFn: queryFn(options), 129 | config 130 | }) 131 | useQueryUsersControllerFindMany.queryKey = '/users' 132 | 133 | export const mutationUsersControllerCreate = (options) => mutationFn('post', '/users', {}, {}, options) 134 | export const useMutationUsersControllerCreate = (config, options) => useMutation(mutationFn('post', '/users', {}, {}, options), config) 135 | 136 | export const queryUsersControllerFindById = (pathParams, options) => queryFn(options)('/user/{id}', pathParams) 137 | export const useQueryUsersControllerFindById = (pathParams, config, options) => useQuery({ 138 | queryKey: pathParams && pathParams.id && ['/user/{id}', pathParams], 139 | queryFn: queryFn(options), 140 | config 141 | }) 142 | useQueryUsersControllerFindById.queryKey = '/user/{id}' 143 | 144 | export const mutationUsersControllerUpdate = (pathParams, options) => mutationFn('put', '/user/{id}', pathParams, {}, options) 145 | export const useMutationUsersControllerUpdate = (pathParams, config, options) => useMutation(mutationFn('put', '/user/{id}', pathParams, {}, options), config) 146 | 147 | export const mutationUsersControllerDelete = (pathParams, options) => mutationFn('delete', '/user/{id}', pathParams, {}, options) 148 | export const useMutationUsersControllerDelete = (pathParams, config, options) => useMutation(mutationFn('delete', '/user/{id}', pathParams, {}, options), config) 149 | 150 | export const queryPostsControllerFindMany = (options) => queryFn(options)('/posts') 151 | export const useQueryPostsControllerFindMany = (config, options) => useQuery({ 152 | queryKey: ['/posts'], 153 | queryFn: queryFn(options), 154 | config 155 | }) 156 | useQueryPostsControllerFindMany.queryKey = '/posts' 157 | 158 | export const mutationPostsControllerCreate = (options) => mutationFn('post', '/posts', {}, {}, options) 159 | export const useMutationPostsControllerCreate = (config, options) => useMutation(mutationFn('post', '/posts', {}, {}, options), config) 160 | 161 | export const queryPostsControllerFindById = (pathParams, options) => queryFn(options)('/post/{id}', pathParams) 162 | export const useQueryPostsControllerFindById = (pathParams, config, options) => useQuery({ 163 | queryKey: pathParams && pathParams.id && ['/post/{id}', pathParams], 164 | queryFn: queryFn(options), 165 | config 166 | }) 167 | useQueryPostsControllerFindById.queryKey = '/post/{id}' 168 | 169 | export const mutationPostsControllerUpdate = (pathParams, options) => mutationFn('put', '/post/{id}', pathParams, {}, options) 170 | export const useMutationPostsControllerUpdate = (pathParams, config, options) => useMutation(mutationFn('put', '/post/{id}', pathParams, {}, options), config) 171 | 172 | export const mutationPostsControllerDelete = (pathParams, options) => mutationFn('delete', '/post/{id}', pathParams, {}, options) 173 | export const useMutationPostsControllerDelete = (pathParams, config, options) => useMutation(mutationFn('delete', '/post/{id}', pathParams, {}, options), config) 174 | 175 | -------------------------------------------------------------------------------- /examples/generated/pix.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | import ky, { Options } from 'ky' 4 | import { QueryOptions, QueryResult, MutationOptions, MutateFunction, MutationResult } from 'react-query' 5 | 6 | export const getApi: { (): typeof ky } 7 | 8 | export const setApi: { (newApi: typeof ky ): void } 9 | 10 | export const extendApi: { (options: Options ): void } 11 | 12 | export type TxId = string 13 | 14 | export type EndToEndId = string 15 | 16 | export type DevolucaoId = string 17 | 18 | export type CobStatus = "ATIVA" | "CONCLUIDA" | "REMOVIDA_PELO_USUARIO_RECEBEDOR" | "REMOVIDA_PELO_PSP" 19 | 20 | export type CPF = string 21 | 22 | export type CNPJ = string 23 | 24 | export type Revisao = number 25 | 26 | export type Location = string 27 | 28 | export type PessoaFisica = { cpf: CPF & any; nome: string } 29 | 30 | export type PessoaJuridica = { cnpj: CNPJ & any; nome: string } 31 | 32 | export type Webhook = { webhookUrl: string } 33 | 34 | export type CobExpiracao = { expiracao?: number } 35 | 36 | export type CobApresentacao = { apresentacao: string } 37 | 38 | export type CobCriacao = { criacao: string } 39 | 40 | export type Valor = string 41 | 42 | export type CobBase = { devedor?: PessoaFisica | PessoaJuridica; valor?: { original: Valor & any }; chave?: string; solicitacaoPagador?: string; infoAdicionais?: { nome: string; valor: string }[] } 43 | 44 | export type CobSolicitada = { calendario?: CobExpiracao } & CobBase 45 | 46 | export type CobRevisada = { calendario?: CobExpiracao; status?: CobStatus } & CobBase 47 | 48 | export type CobGerada = { calendario?: CobCriacao & CobExpiracao; status?: CobStatus; txid?: TxId; revisao?: Revisao; location?: Location } & CobBase 49 | 50 | export type CobCompleta = CobGerada & CobSolicitada & { pix?: Pix[] } 51 | 52 | export type CobPayload = { txid?: TxId; revisao?: Revisao; calendario?: CobCriacao & CobApresentacao & CobExpiracao; status?: CobStatus } & CobBase 53 | 54 | export type ParametrosConsultaCob = { inicio: string; fim: string; cpf?: CPF & any; cnpj?: CNPJ & any; status?: CobStatus & any; paginacao: Paginacao } 55 | 56 | export type CobsConsultadas = { parametros: ParametrosConsultaCob; cobs: (CobCompleta & any)[] } 57 | 58 | export type Pix = { endToEndId: EndToEndId; txid?: TxId; valor: Valor & any; horario: string; pagador?: PessoaFisica | PessoaJuridica; infoPagador?: string; devolucoes?: Devolucao[] } 59 | 60 | export type Devolucao = { id: DevolucaoId; rtrId: string; valor: Valor & any; horario: { solicitacao: string; liquidacao?: string }; status: "EM_PROCESSAMENTO" | "DEVOLVIDO" | "NAO_REALIZADO" } 61 | 62 | export type ParametrosConsultaPix = { inicio: string; fim: string; cpf?: CPF & any; cnpj?: CNPJ & any; txId?: TxId; paginacao: Paginacao } 63 | 64 | export type PixConsultados = { parametros: ParametrosConsultaPix; pix?: (Pix)[] } 65 | 66 | export type Paginacao = { paginaAtual: number; itensPorPagina: number; quantidadeDePaginas: number; quantidadeTotalDeItens: number } 67 | 68 | export type CriarCobrancaPathParams = { txid: TxId } 69 | export const mutationCriarCobranca: { (pathParams?: CriarCobrancaPathParams, options?: Options): { (body?: CobBodyRequestBody | [CriarCobrancaPathParams, void, CobBodyRequestBody, Options]): Promise } } 70 | export const useMutationCriarCobranca: { (pathParams?: CriarCobrancaPathParams, config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 71 | 72 | export type RevisarCobrancaPathParams = { txid: TxId } 73 | export const mutationRevisarCobranca: { (pathParams?: RevisarCobrancaPathParams, options?: Options): { (body?: CobBodyRevisadaRequestBody | [RevisarCobrancaPathParams, void, CobBodyRevisadaRequestBody, Options]): Promise } } 74 | export const useMutationRevisarCobranca: { (pathParams?: RevisarCobrancaPathParams, config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 75 | 76 | export type ConsultarCobrancaPathParams = { txid: TxId } 77 | export type ConsultarCobrancaQueryParams = { revisao?: Revisao } 78 | export const queryConsultarCobranca: { (pathParams?: ConsultarCobrancaPathParams, queryParams?: ConsultarCobrancaQueryParams, options?: Options): Promise } 79 | export const useQueryConsultarCobranca: { (pathParams?: ConsultarCobrancaPathParams, queryParams?: ConsultarCobrancaQueryParams, config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 80 | 81 | export type ConsultarListaDeCobrancasQueryParams = { cpf?: CPF & any; cnpj?: CNPJ & any; status?: CobStatus & any } 82 | export const queryConsultarListaDeCobrancas: { (queryParams?: ConsultarListaDeCobrancasQueryParams, options?: Options): Promise } 83 | export const useQueryConsultarListaDeCobrancas: { (queryParams?: ConsultarListaDeCobrancasQueryParams, config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 84 | 85 | export type SolicitarDevolucaoPathParams = { e2eid: EndToEndId; id: DevolucaoId } 86 | export const mutationSolicitarDevolucao: { (pathParams?: SolicitarDevolucaoPathParams, options?: Options): { (body?: { valor?: Valor & any } | [SolicitarDevolucaoPathParams, void, { valor?: Valor & any }, Options]): Promise } } 87 | export const useMutationSolicitarDevolucao: { (pathParams?: SolicitarDevolucaoPathParams, config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 88 | 89 | export type ConsultarDevolucaoPathParams = { e2eid: EndToEndId; id: DevolucaoId } 90 | export const queryConsultarDevolucao: { (pathParams?: ConsultarDevolucaoPathParams, options?: Options): Promise } 91 | export const useQueryConsultarDevolucao: { (pathParams?: ConsultarDevolucaoPathParams, config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 92 | 93 | export type ConsultarPixPathParams = { e2eid: EndToEndId } 94 | export const queryConsultarPix: { (pathParams?: ConsultarPixPathParams, options?: Options): Promise } 95 | export const useQueryConsultarPix: { (pathParams?: ConsultarPixPathParams, config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 96 | 97 | export type ConsultarPixRecebidosQueryParams = { txId?: TxId; cpf?: CPF & any; cnpj?: CNPJ & any } 98 | export const queryConsultarPixRecebidos: { (queryParams?: ConsultarPixRecebidosQueryParams, options?: Options): Promise } 99 | export const useQueryConsultarPixRecebidos: { (queryParams?: ConsultarPixRecebidosQueryParams, config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 100 | 101 | export type RecuperarOPayloadJsonQueRepresentaACobrancaPathParams = { pixUrlAcessToken: string } 102 | export const queryRecuperarOPayloadJsonQueRepresentaACobranca: { (pathParams?: RecuperarOPayloadJsonQueRepresentaACobrancaPathParams, options?: Options): Promise } 103 | export const useQueryRecuperarOPayloadJsonQueRepresentaACobranca: { (pathParams?: RecuperarOPayloadJsonQueRepresentaACobrancaPathParams, config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 104 | 105 | export const mutationConfigurarOWebhookPix: { (options?: Options): { (body?: Webhook | [void, void, Webhook, Options]): Promise } } 106 | export const useMutationConfigurarOWebhookPix: { (config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 107 | 108 | export const queryExibirInformacoesAcercaDoWebookPix: { (options?: Options): Promise } 109 | export const useQueryExibirInformacoesAcercaDoWebookPix: { (config?: QueryOptions, options?: Options): QueryResult; queryKey: string } 110 | 111 | export const mutationCancelarOWebhookPix: { (options?: Options): { (body?: void | [void, void, void, Options]): Promise } } 112 | export const useMutationCancelarOWebhookPix: { (config?: MutationOptions, options?: Options): [MutateFunction, MutationResult] } 113 | 114 | -------------------------------------------------------------------------------- /examples/generated/pix.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | import ky from 'ky' 4 | import { useQuery, useMutation } from 'react-query' 5 | 6 | let api = ky.create({ 7 | "prefixUrl": "https://pix.com", 8 | "throwHttpErrors": false, 9 | "retry": { 10 | "statusCodes": [ 11 | 401 12 | ] 13 | } 14 | }) 15 | 16 | export const getApi = () => api 17 | 18 | export const setApi = (newApi) => { 19 | api = newApi 20 | } 21 | 22 | export const extendApi = (options) => { 23 | api = getApi().extend(options) 24 | } 25 | 26 | const requestFn = async ({ url, method, pathParams, queryParams, ...rest }) => { 27 | const urlPathParams = url.match(/{([^}]+)}/g) 28 | 29 | if (urlPathParams) { 30 | url = urlPathParams.reduce((acc, param) => acc.replace(param, pathParams[param.replace(/{|}/g, '')]), url) 31 | } else { 32 | queryParams = pathParams 33 | } 34 | 35 | if (url.charAt(0) === '/') { 36 | url = url.replace('/', '') 37 | } 38 | 39 | const response = await api(url, { 40 | method, 41 | ...rest, 42 | searchParams: { 43 | ...(rest.searchParams || {}), 44 | ...queryParams 45 | } 46 | }) 47 | 48 | let data 49 | 50 | try { 51 | const contentType = (response.headers.get('content-type') || '').split('; ')[0] 52 | 53 | const responseType = 54 | { 55 | 'application/json': 'json', 56 | 'application/pdf': 'blob' 57 | }[contentType] || 'text' 58 | 59 | data = await response[responseType]() 60 | } catch (e) { 61 | data = e.message 62 | } 63 | 64 | if (!response.ok) { 65 | const error = { 66 | data, 67 | status: response.status, 68 | message: `Failed to fetch: ${response.status} ${response.statusText}` 69 | } 70 | 71 | throw error 72 | } 73 | 74 | return data 75 | } 76 | 77 | const queryFn = (options = {}) => (url, pathParams = {}, queryParams = {}) => { 78 | const controller = new AbortController() 79 | const { signal } = controller 80 | 81 | const promise = requestFn({ 82 | url, 83 | method: 'get', 84 | pathParams, 85 | queryParams, 86 | signal, 87 | ...options 88 | }) 89 | 90 | // cancel the request if React Query calls the 'promise.cancel' method 91 | promise.cancel = () => { 92 | controller.abort('Query was cancelled by React Query') 93 | } 94 | 95 | return promise 96 | } 97 | 98 | const mutationFn = ( 99 | method, 100 | url, 101 | pathParams = {}, 102 | queryParams = {}, 103 | options = {} 104 | ) => (body = {}) => { 105 | if (Array.isArray(body)) { 106 | pathParams = { ...pathParams, ...(body[0] || {}) } 107 | queryParams = { ...queryParams, ...(body[1] || {}) } 108 | options = { ...options, ...(body[3] || {}) } 109 | body = body[2] 110 | } 111 | 112 | const request = { 113 | url, 114 | method, 115 | pathParams, 116 | queryParams, 117 | ...options 118 | } 119 | 120 | if (method !== 'delete') { 121 | try { 122 | request[body.toString() === '[object FormData]' ? 'body' : 'json'] = body 123 | } catch(e) { 124 | } 125 | } 126 | 127 | return requestFn(request) 128 | } 129 | 130 | export const mutationCriarCobranca = (pathParams, options) => mutationFn('put', '/cob/{txid}', pathParams, {}, options) 131 | export const useMutationCriarCobranca = (pathParams, config, options) => useMutation(mutationFn('put', '/cob/{txid}', pathParams, {}, options), config) 132 | 133 | export const mutationRevisarCobranca = (pathParams, options) => mutationFn('patch', '/cob/{txid}', pathParams, {}, options) 134 | export const useMutationRevisarCobranca = (pathParams, config, options) => useMutation(mutationFn('patch', '/cob/{txid}', pathParams, {}, options), config) 135 | 136 | export const queryConsultarCobranca = (pathParams, queryParams, options) => queryFn(options)('/cob/{txid}', pathParams, queryParams) 137 | export const useQueryConsultarCobranca = (pathParams, queryParams, config, options) => useQuery({ 138 | queryKey: pathParams && pathParams.txid && ['/cob/{txid}', pathParams, queryParams], 139 | queryFn: queryFn(options), 140 | config 141 | }) 142 | useQueryConsultarCobranca.queryKey = '/cob/{txid}' 143 | 144 | export const queryConsultarListaDeCobrancas = (queryParams, options) => queryFn(options)('/cob/', queryParams) 145 | export const useQueryConsultarListaDeCobrancas = (queryParams, config, options) => useQuery({ 146 | queryKey: ['/cob/', queryParams], 147 | queryFn: queryFn(options), 148 | config 149 | }) 150 | useQueryConsultarListaDeCobrancas.queryKey = '/cob/' 151 | 152 | export const mutationSolicitarDevolucao = (pathParams, options) => mutationFn('put', '/pix/{e2eid}/devolucao/{id}', pathParams, {}, options) 153 | export const useMutationSolicitarDevolucao = (pathParams, config, options) => useMutation(mutationFn('put', '/pix/{e2eid}/devolucao/{id}', pathParams, {}, options), config) 154 | 155 | export const queryConsultarDevolucao = (pathParams, options) => queryFn(options)('/pix/{e2eid}/devolucao/{id}', pathParams) 156 | export const useQueryConsultarDevolucao = (pathParams, config, options) => useQuery({ 157 | queryKey: pathParams && pathParams.e2eid && pathParams.id && ['/pix/{e2eid}/devolucao/{id}', pathParams], 158 | queryFn: queryFn(options), 159 | config 160 | }) 161 | useQueryConsultarDevolucao.queryKey = '/pix/{e2eid}/devolucao/{id}' 162 | 163 | export const queryConsultarPix = (pathParams, options) => queryFn(options)('/pix/{e2eid}', pathParams) 164 | export const useQueryConsultarPix = (pathParams, config, options) => useQuery({ 165 | queryKey: pathParams && pathParams.e2eid && ['/pix/{e2eid}', pathParams], 166 | queryFn: queryFn(options), 167 | config 168 | }) 169 | useQueryConsultarPix.queryKey = '/pix/{e2eid}' 170 | 171 | export const queryConsultarPixRecebidos = (queryParams, options) => queryFn(options)('/pix', queryParams) 172 | export const useQueryConsultarPixRecebidos = (queryParams, config, options) => useQuery({ 173 | queryKey: ['/pix', queryParams], 174 | queryFn: queryFn(options), 175 | config 176 | }) 177 | useQueryConsultarPixRecebidos.queryKey = '/pix' 178 | 179 | export const queryRecuperarOPayloadJsonQueRepresentaACobranca = (pathParams, options) => queryFn(options)('/{pixUrlAcessToken}', pathParams) 180 | export const useQueryRecuperarOPayloadJsonQueRepresentaACobranca = (pathParams, config, options) => useQuery({ 181 | queryKey: pathParams && pathParams.pixUrlAcessToken && ['/{pixUrlAcessToken}', pathParams], 182 | queryFn: queryFn(options), 183 | config 184 | }) 185 | useQueryRecuperarOPayloadJsonQueRepresentaACobranca.queryKey = '/{pixUrlAcessToken}' 186 | 187 | export const mutationConfigurarOWebhookPix = (options) => mutationFn('put', '/webhook', {}, {}, options) 188 | export const useMutationConfigurarOWebhookPix = (config, options) => useMutation(mutationFn('put', '/webhook', {}, {}, options), config) 189 | 190 | export const queryExibirInformacoesAcercaDoWebookPix = (options) => queryFn(options)('/webhook') 191 | export const useQueryExibirInformacoesAcercaDoWebookPix = (config, options) => useQuery({ 192 | queryKey: ['/webhook'], 193 | queryFn: queryFn(options), 194 | config 195 | }) 196 | useQueryExibirInformacoesAcercaDoWebookPix.queryKey = '/webhook' 197 | 198 | export const mutationCancelarOWebhookPix = (options) => mutationFn('delete', '/webhook', {}, {}, options) 199 | export const useMutationCancelarOWebhookPix = (config, options) => useMutation(mutationFn('delete', '/webhook', {}, {}, options), config) 200 | 201 | -------------------------------------------------------------------------------- /examples/openapi.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.0", 3 | "info": { 4 | "title": "API Pix", 5 | "version": "2.0.0", 6 | "license": { 7 | "name": "Apache 2.0", 8 | "url": "http://www.apache.org/licenses/LICENSE-2.0" 9 | }, 10 | "contact": { 11 | "name": "Suporte TI BCB", 12 | "email": "suporte.ti@bcb.gov.br", 13 | "url": "https://www.bcb.gov.br/estabilidadefinanceira/pagamentosinstantaneos" 14 | }, 15 | "description": "A API Pix padroniza serviços oferecidos pelo PSP recebedor no contexto do arranjo Pix, como criação de cobrança,\nverificação de Pix recebidos, devolução e conciliação. Os serviços expostos pelo PSP recebedor permitem ao usuário\nrecebedor estabelecer integração de sua automação com os serviços PIX do PSP.\n\n# Evolução da API Pix\nAs seguintes mudanças são esperadas e consideradas retro-compatíveis (_backwards-compatibility_):\n\n- Adição de novos recursos na API Pix.\n- Adição de novos parâmetros opcionais a cobranças.\n- Adição de novos campos em respostas da API Pix.\n- Alteração da ordem de campos.\n- Adição de novos elementos em enumerações\n\nMudanças compatíveis não geram nova versão da API Pix.\nClientes devem estar preparados para lidar com essas mudanças sem quebrar.\n\nMudanças incompatíveis geram nova versão da API Pix." 16 | }, 17 | "servers": [ 18 | { 19 | "url": "https://pix.example.com/api/v1/", 20 | "description": "Servidor de Produção" 21 | }, 22 | { 23 | "url": "https://pix-h.example.com/api/v1/", 24 | "description": "Servidor de Homologação" 25 | } 26 | ], 27 | "security": [ 28 | { 29 | "OAuth2": [ 30 | "cob.write", 31 | "cob.read", 32 | "pix.write", 33 | "pix.read", 34 | "webhook.read", 35 | "webhook.write" 36 | ] 37 | } 38 | ], 39 | "tags": [ 40 | { 41 | "name": "CobPayload", 42 | "x-displayName": "Payload JSON que representa uma Cobrança.", 43 | "description": "Endpoint (location) utilizado pelo usuário pagador para recuperar o payload JSON que representa uma cobrança." 44 | }, 45 | { 46 | "name": "Cob", 47 | "x-displayName": "Gerenciamento de cobranças", 48 | "description": "Reune endpoints destinados a lidar com gerenciamento de cobranças." 49 | }, 50 | { 51 | "name": "Pix", 52 | "x-displayName": "Gerenciamento de Pix recebidos", 53 | "description": "Reune endpoints destinados a lidar com gerenciamento de Pix recebidos." 54 | }, 55 | { 56 | "name": "Webhook", 57 | "x-displayName": "Gerenciamento de notificações", 58 | "description": "Reune endpoints para gerenciamento de notificações por parte do PSP recebedor ao usuário recebedor." 59 | } 60 | ], 61 | "paths": { 62 | "/cob/{txid}": { 63 | "parameters": [ 64 | { 65 | "name": "txid", 66 | "in": "path", 67 | "required": true, 68 | "schema": { 69 | "$ref": "#/components/schemas/TxId" 70 | } 71 | } 72 | ], 73 | "put": { 74 | "tags": [ 75 | "Cob" 76 | ], 77 | "summary": "Criar cobrança.", 78 | "security": [ 79 | { 80 | "OAuth2": [ 81 | "cob.write" 82 | ] 83 | } 84 | ], 85 | "description": "Endpoint para criar uma cobrança.", 86 | "requestBody": { 87 | "$ref": "#/components/requestBodies/CobBody" 88 | }, 89 | "responses": { 90 | "200": { 91 | "description": "Cobrança criada", 92 | "content": { 93 | "application/json": { 94 | "schema": { 95 | "$ref": "#/components/schemas/CobGerada" 96 | }, 97 | "examples": { 98 | "retorno1": { 99 | "$ref": "#/components/examples/retorno1" 100 | } 101 | } 102 | } 103 | } 104 | } 105 | } 106 | }, 107 | "patch": { 108 | "tags": [ 109 | "Cob" 110 | ], 111 | "summary": "Revisar cobrança.", 112 | "security": [ 113 | { 114 | "OAuth2": [ 115 | "cob.write" 116 | ] 117 | } 118 | ], 119 | "requestBody": { 120 | "$ref": "#/components/requestBodies/CobBodyRevisada" 121 | }, 122 | "responses": { 123 | "200": { 124 | "description": "Cobrança revisada. A revisão deve ser incrementada em 1.", 125 | "content": { 126 | "application/json": { 127 | "schema": { 128 | "$ref": "#/components/schemas/CobGerada" 129 | }, 130 | "examples": { 131 | "retorno1": { 132 | "$ref": "#/components/examples/retorno1" 133 | } 134 | } 135 | } 136 | } 137 | } 138 | } 139 | }, 140 | "get": { 141 | "parameters": [ 142 | { 143 | "name": "revisao", 144 | "in": "query", 145 | "required": false, 146 | "description": " Permite recuperar revisões anteriores de uma cobrança. Na ausência desse parâmetro, sempre será retornada a cobrança conforme consta em sua última revisão.", 147 | "schema": { 148 | "$ref": "#/components/schemas/Revisao" 149 | } 150 | } 151 | ], 152 | "tags": [ 153 | "Cob" 154 | ], 155 | "summary": "Consultar cobrança.", 156 | "security": [ 157 | { 158 | "OAuth2": [ 159 | "cob.read" 160 | ] 161 | } 162 | ], 163 | "description": "Endpoint para consultar uma cobrança através de um determinado TxID.", 164 | "responses": { 165 | "200": { 166 | "description": "Dados da cobrança.", 167 | "content": { 168 | "application/json": { 169 | "schema": { 170 | "$ref": "#/components/schemas/CobCompleta" 171 | }, 172 | "examples": { 173 | "retorno1": { 174 | "$ref": "#/components/examples/retorno1" 175 | }, 176 | "retorno2": { 177 | "$ref": "#/components/examples/retorno2" 178 | } 179 | } 180 | } 181 | } 182 | } 183 | } 184 | } 185 | }, 186 | "/cob/": { 187 | "get": { 188 | "parameters": [ 189 | { 190 | "$ref": "#/components/parameters/inicio" 191 | }, 192 | { 193 | "$ref": "#/components/parameters/fim" 194 | }, 195 | { 196 | "name": "cpf", 197 | "in": "query", 198 | "schema": { 199 | "allOf": [ 200 | { 201 | "$ref": "#/components/schemas/CPF" 202 | }, 203 | { 204 | "description": "Filtro pelo CPF do pagador. Não pode ser utilizado ao mesmo tempo que o CNPJ." 205 | } 206 | ] 207 | } 208 | }, 209 | { 210 | "name": "cnpj", 211 | "in": "query", 212 | "schema": { 213 | "allOf": [ 214 | { 215 | "$ref": "#/components/schemas/CNPJ" 216 | }, 217 | { 218 | "description": "Filtro pelo CNPJ do pagador. Não pode ser utilizado ao mesmo tempo que o CPF." 219 | } 220 | ] 221 | } 222 | }, 223 | { 224 | "name": "status", 225 | "in": "query", 226 | "schema": { 227 | "allOf": [ 228 | { 229 | "$ref": "#/components/schemas/CobStatus" 230 | }, 231 | { 232 | "description": "Filtro pelo status da cobrança." 233 | } 234 | ] 235 | } 236 | }, 237 | { 238 | "$ref": "#/components/parameters/paginaAtual" 239 | }, 240 | { 241 | "$ref": "#/components/parameters/itensPorPagina" 242 | } 243 | ], 244 | "tags": [ 245 | "Cob" 246 | ], 247 | "summary": "Consultar lista de cobranças.", 248 | "security": [ 249 | { 250 | "OAuth2": [ 251 | "cob.read" 252 | ] 253 | } 254 | ], 255 | "description": "Endpoint para consultar cobranças através de parâmetros como início, fim, cpf, cnpj e status.", 256 | "responses": { 257 | "200": { 258 | "description": "Lista de cobranças.", 259 | "content": { 260 | "application/json": { 261 | "schema": { 262 | "$ref": "#/components/schemas/CobsConsultadas" 263 | }, 264 | "examples": { 265 | "getCobs1": { 266 | "$ref": "#/components/examples/getCobs1" 267 | }, 268 | "getCobs2": { 269 | "$ref": "#/components/examples/getCobs2" 270 | } 271 | } 272 | } 273 | } 274 | } 275 | } 276 | } 277 | }, 278 | "/pix/{e2eid}/devolucao/{id}": { 279 | "parameters": [ 280 | { 281 | "name": "e2eid", 282 | "in": "path", 283 | "required": true, 284 | "schema": { 285 | "$ref": "#/components/schemas/EndToEndId" 286 | } 287 | }, 288 | { 289 | "name": "id", 290 | "in": "path", 291 | "required": true, 292 | "schema": { 293 | "$ref": "#/components/schemas/DevolucaoId" 294 | } 295 | } 296 | ], 297 | "put": { 298 | "tags": [ 299 | "Pix" 300 | ], 301 | "summary": "Solicitar devolução.", 302 | "security": [ 303 | { 304 | "OAuth2": [ 305 | "pix.write" 306 | ] 307 | } 308 | ], 309 | "description": "Endpoint para solicitar uma devolução através de um e2eid do Pix e do ID da devolução.", 310 | "requestBody": { 311 | "description": "Dados para pedido de devolução.", 312 | "required": true, 313 | "content": { 314 | "application/json": { 315 | "schema": { 316 | "type": "object", 317 | "properties": { 318 | "valor": { 319 | "allOf": [ 320 | { 321 | "$ref": "#/components/schemas/Valor" 322 | }, 323 | { 324 | "description": "Valor solicitado para devolução. A soma dos valores de todas as devolucões não podem ultrapassar o valor total da cobrança." 325 | } 326 | ] 327 | } 328 | } 329 | }, 330 | "example": { 331 | "valor": "7.89" 332 | } 333 | } 334 | } 335 | }, 336 | "responses": { 337 | "200": { 338 | "description": "Dados da devolução.", 339 | "content": { 340 | "application/json": { 341 | "schema": { 342 | "$ref": "#/components/schemas/Devolucao" 343 | }, 344 | "examples": { 345 | "retorno1": { 346 | "$ref": "#/components/examples/retorno7" 347 | } 348 | } 349 | } 350 | } 351 | } 352 | } 353 | }, 354 | "get": { 355 | "tags": [ 356 | "Pix" 357 | ], 358 | "summary": "Consultar devolução.", 359 | "security": [ 360 | { 361 | "OAuth2": [ 362 | "pix.read" 363 | ] 364 | } 365 | ], 366 | "description": "Endpoint para consultar uma devolução através de um End To End ID do Pix e do ID da devolução", 367 | "responses": { 368 | "200": { 369 | "description": "Dados da devolução.", 370 | "content": { 371 | "application/json": { 372 | "schema": { 373 | "$ref": "#/components/schemas/Devolucao" 374 | }, 375 | "examples": { 376 | "retorno1": { 377 | "$ref": "#/components/examples/retorno7" 378 | } 379 | } 380 | } 381 | } 382 | } 383 | } 384 | } 385 | }, 386 | "/pix/{e2eid}": { 387 | "parameters": [ 388 | { 389 | "name": "e2eid", 390 | "in": "path", 391 | "required": true, 392 | "schema": { 393 | "$ref": "#/components/schemas/EndToEndId" 394 | } 395 | } 396 | ], 397 | "get": { 398 | "tags": [ 399 | "Pix" 400 | ], 401 | "summary": "Consultar Pix.", 402 | "security": [ 403 | { 404 | "OAuth2": [ 405 | "pix.read" 406 | ] 407 | } 408 | ], 409 | "description": "Endpoint para consultar um Pix através de um e2eid.", 410 | "responses": { 411 | "200": { 412 | "description": "Dados do Pix efetuado.", 413 | "content": { 414 | "application/json": { 415 | "schema": { 416 | "$ref": "#/components/schemas/Pix" 417 | }, 418 | "examples": { 419 | "retorno1": { 420 | "$ref": "#/components/examples/retorno3" 421 | }, 422 | "retorno2": { 423 | "$ref": "#/components/examples/retorno4" 424 | } 425 | } 426 | } 427 | } 428 | } 429 | } 430 | } 431 | }, 432 | "/pix": { 433 | "get": { 434 | "parameters": [ 435 | { 436 | "$ref": "#/components/parameters/inicio" 437 | }, 438 | { 439 | "$ref": "#/components/parameters/fim" 440 | }, 441 | { 442 | "name": "txId", 443 | "in": "query", 444 | "schema": { 445 | "$ref": "#/components/schemas/TxId" 446 | } 447 | }, 448 | { 449 | "name": "cpf", 450 | "in": "query", 451 | "schema": { 452 | "allOf": [ 453 | { 454 | "$ref": "#/components/schemas/CPF" 455 | }, 456 | { 457 | "description": "Filtro pelo CPF do pagador. Não pode ser utilizado ao mesmo tempo que o CNPJ." 458 | } 459 | ] 460 | } 461 | }, 462 | { 463 | "name": "cnpj", 464 | "in": "query", 465 | "schema": { 466 | "allOf": [ 467 | { 468 | "$ref": "#/components/schemas/CNPJ" 469 | }, 470 | { 471 | "description": "Filtro pelo CNPJ do pagador. Não pode ser utilizado ao mesmo tempo que o CPF." 472 | } 473 | ] 474 | } 475 | }, 476 | { 477 | "$ref": "#/components/parameters/paginaAtual" 478 | }, 479 | { 480 | "$ref": "#/components/parameters/itensPorPagina" 481 | } 482 | ], 483 | "tags": [ 484 | "Pix" 485 | ], 486 | "summary": "Consultar Pix recebidos.", 487 | "security": [ 488 | { 489 | "OAuth2": [ 490 | "pix.read" 491 | ] 492 | } 493 | ], 494 | "description": "Endpoint para consultar Pix recebidos", 495 | "responses": { 496 | "200": { 497 | "description": "lista dos Pix recebidos de acordo com o critério de busca.", 498 | "content": { 499 | "application/json": { 500 | "schema": { 501 | "$ref": "#/components/schemas/PixConsultados" 502 | }, 503 | "examples": { 504 | "getCobs1": { 505 | "$ref": "#/components/examples/getPix1" 506 | } 507 | } 508 | } 509 | } 510 | } 511 | } 512 | } 513 | }, 514 | "/{pixUrlAcessToken}": { 515 | "parameters": [ 516 | { 517 | "name": "pixUrlAcessToken", 518 | "in": "path", 519 | "required": true, 520 | "schema": { 521 | "type": "string" 522 | } 523 | } 524 | ], 525 | "get": { 526 | "tags": [ 527 | "CobPayload" 528 | ], 529 | "servers": [ 530 | { 531 | "url": "https://{fdqnPSPRecebedor}/{pixEndpoint}/v1", 532 | "variables": { 533 | "fdqnPSPRecebedor": { 534 | "default": "example.com", 535 | "description": "Endpoint base para que os usuário pagadores possam acessar o payload JSON que representa a cobrança." 536 | } 537 | } 538 | } 539 | ], 540 | "summary": "Recuperar o payload JSON que representa a cobrança.", 541 | "description": "## Endpoint (location) que serve um payload que representa uma cobrança.\n\nNo momento que o usuário pagador efetua a leitura de um QR Code dinâmico gerado pelo recebedor, esta URL será acessada e seu conteúdo consiste em uma estrutura JWS.\nAs informações sobre a segurança no acesso às urls encontram-se no Manual de Segurança do Pix disponível em nesse __[link](https://www.bcb.gov.br/estabilidadefinanceira/comunicacaodados)__.\n", 542 | "security": [], 543 | "responses": { 544 | "200": { 545 | "description": "# Descrição do Retorno\nO retorno desse endpoint é um objeto que apresenta estrutura JWS, conforme especificado no manual de segurança. Segue um exemplo:\n\n```jws\neyJhbGciOiJQUzI1NiIsInR5cCI6IkpXUyJ9.eyJ0eElkIjoiNTJjNDMzNjEtY2FhMS00ZGRiLTkxNTItNzA4NDI2YTI1ZGIzIiwicmV2aXNhbyI6IjMiLCJjYWxlbmRhcmlvIjp7ImNyaWFjYW8iOiIyMDIwLTA5LTE1VDE5OjM5OjU0LjAxM1oiLCJhcHJlc2VudGFjYW8iOiIyMDIwLTA0LTAxVDE4OjAwOjAwWiIsImV4cGlyYWNhbyI6IjEyMDAifSwidmFsb3IiOnsib3JpZ2luYWwiOiI1MDAuMDAifSwiY2hhdmUiOiI3NDA3YzljOC1mNzhiLTExZWEtYWRjMS0wMjQyYWMxMjAwMDIiLCJzb2xpY2l0YWNhb1BhZ2Fkb3IiOiJJbmZvcm1hciBjYXJ0w6NvIGZpZGVsaWRhZGUiLCJpbmZvQWRpY2lvbmFpcyI6W3sibm9tZSI6InF1YW50aWRhZGUiLCJ2YWxvciI6IjIifV19.khlLEW4Q4W6zIYlacIaSHzwg_q9JrIkeinmvRDcUUD3120oXXew_xqSEAWsefY28g4MhUmK-RuaZgn1_rR22ZVM1pDbblw7Sk6dlHGxEc8PbMzMgEJPLdOZRumzMLx6YBYLAYsxT-HZp_vmBT713biN3jJf3V55z9RK6Xyo1CeWvemt81_O4kyGZ9lbp7p0VhmdJ9u6_EquEyP2n0uWy2ikbe7AFobkAdBRoF8gtp891WG5-gZmk4ZzATORNQOTrytQYMyprWV7o_prVjwT308RUo9Si-FRPTvYRGqyKo-voGoQVaZgCMUjc0jLr9WqYCRMyeCJZHTJmpaCFSNQnhw\n```\n\nEste objeto JWS assinado deve ser validado pelo pagador. Maiores detalhes técnicos a respeito da especificação\nde segurança encontram-se no __[Manual de Segurança do Pix](https://www.bcb.gov.br/estabilidadefinanceira/pagamentosinstantaneos)__.\n\nConforme pode-se verificar no exemplo acima, o objeto JWS apresenta três fragmentos separados pelo caractere `.` (ponto). São eles: `header`, `payload` e `signature`.\n\nEm termos de funcionalidade, o fragmento que interessa ao pagador é o `payload`, que apresenta estrutura conforme especificada pelo `schema` do presente endpoint, contendo detalhes concernentes à cobrança.\n", 546 | "content": { 547 | "application/jose": { 548 | "schema": { 549 | "$ref": "#/components/schemas/CobPayload" 550 | }, 551 | "examples": { 552 | "retorno1": { 553 | "$ref": "#/components/examples/retorno8" 554 | } 555 | } 556 | } 557 | } 558 | } 559 | } 560 | } 561 | }, 562 | "/webhook": { 563 | "put": { 564 | "tags": [ 565 | "Webhook" 566 | ], 567 | "summary": "Configurar o Webhook Pix.", 568 | "description": "Endpoint para configuração do serviço de notificações acerca de Pix recebidos.\nSomente PIX associados a um txid serão notificados.\n", 569 | "security": [ 570 | { 571 | "OAuth2": [ 572 | "webhook.write" 573 | ] 574 | } 575 | ], 576 | "requestBody": { 577 | "required": true, 578 | "content": { 579 | "application/json": { 580 | "schema": { 581 | "$ref": "#/components/schemas/Webhook" 582 | } 583 | } 584 | } 585 | }, 586 | "responses": { 587 | "201": { 588 | "description": "Webhook para notificações acerca de Pix recebidos associados a um txid." 589 | } 590 | }, 591 | "callbacks": { 592 | "listaPix": { 593 | "{$request.body#/webhookUrl}/pix": { 594 | "post": { 595 | "description": "Esse serviço está protegido por uma camada de autenticação mTLS.\n", 596 | "security": [], 597 | "requestBody": { 598 | "$ref": "#/components/requestBodies/WebhookPixBody" 599 | }, 600 | "responses": { 601 | "200": { 602 | "description": "Notificação recebida com sucesso" 603 | } 604 | } 605 | } 606 | } 607 | } 608 | } 609 | }, 610 | "get": { 611 | "tags": [ 612 | "Webhook" 613 | ], 614 | "summary": "Exibir informações acerca do Webook Pix.", 615 | "description": "Endpoint para recuperação de informações sobre o webhook pix.\n", 616 | "security": [ 617 | { 618 | "OAuth2": [ 619 | "webhook.read" 620 | ] 621 | } 622 | ], 623 | "responses": { 624 | "200": { 625 | "description": "Dados da location do Payload.", 626 | "content": { 627 | "application/json": { 628 | "schema": { 629 | "$ref": "#/components/schemas/Webhook" 630 | } 631 | } 632 | } 633 | } 634 | } 635 | }, 636 | "delete": { 637 | "tags": [ 638 | "Webhook" 639 | ], 640 | "summary": "Cancelar o webhook Pix.", 641 | "description": "Endpoint para cancelamento do webhook.\n", 642 | "security": [ 643 | { 644 | "OAuth2": [ 645 | "webhook.write" 646 | ] 647 | } 648 | ], 649 | "responses": { 650 | "204": { 651 | "description": "Webhook para notificações Pix foi cancelado." 652 | } 653 | } 654 | } 655 | } 656 | }, 657 | "components": { 658 | "securitySchemes": { 659 | "OAuth2": { 660 | "type": "oauth2", 661 | "flows": { 662 | "clientCredentials": { 663 | "refreshUrl": "https://pix.example.com/oauth/refresh", 664 | "tokenUrl": "https://pix.example.com/oauth/token", 665 | "scopes": { 666 | "cob.write": "Permissão para alteração de cobranças", 667 | "cob.read": "Permissão para consulta de cobranças", 668 | "pix.write": "Permissão para alteração de Pix", 669 | "pix.read": "Permissão para consulta de Pix", 670 | "webhook.read": "Permissão para consulta do webhook", 671 | "webhook.write": "Permissão para alteração do webhook" 672 | } 673 | } 674 | } 675 | } 676 | }, 677 | "examples": { 678 | "corpo1": { 679 | "summary": "Exemplo 1", 680 | "value": { 681 | "calendario": { 682 | "expiracao": "3600" 683 | }, 684 | "devedor": { 685 | "cpf": "12345678909", 686 | "nome": "Francisco da Silva" 687 | }, 688 | "valor": { 689 | "original": "123.45" 690 | }, 691 | "chave": "71cdf9ba-c695-4e3c-b010-abb521a3f1be", 692 | "solicitacaoPagador": "Cobrança dos serviços prestados." 693 | } 694 | }, 695 | "corpo2": { 696 | "summary": "Exemplo 2", 697 | "value": { 698 | "calendario": { 699 | "expiracao": "3600" 700 | }, 701 | "devedor": { 702 | "cnpj": "12345678000195", 703 | "nome": "Empresa de Serviços SA" 704 | }, 705 | "valor": { 706 | "original": "37.00" 707 | }, 708 | "chave": "ac107ed7-97cd-4fe7-8df5-a5f5659bf2f3", 709 | "solicitacaoPagador": "Serviço realizado.", 710 | "infoAdicionais": [ 711 | { 712 | "nome": "Campo 1", 713 | "valor": "Informação Adicional1 do PSP-Recebedor" 714 | }, 715 | { 716 | "nome": "Campo 2", 717 | "valor": "Informação Adicional2 do PSP-Recebedor" 718 | } 719 | ] 720 | } 721 | }, 722 | "corpo4": { 723 | "summary": "Exemplo 1", 724 | "value": { 725 | "status": "EM_USO" 726 | } 727 | }, 728 | "corpo5": { 729 | "summary": "Exemplo 1", 730 | "value": { 731 | "status": "REMOVIDA_PELO_USUARIO_RECEBEDOR" 732 | } 733 | }, 734 | "retorno1": { 735 | "summary": "Exemplo 1", 736 | "value": { 737 | "status": "ATIVA", 738 | "calendario": { 739 | "criacao": "2020-09-09T20:15:00.358Z", 740 | "expiracao": "3600" 741 | }, 742 | "location": "pix.example.com/qr/9d36b84f-c70b-478f-b95c-12729b90ca25", 743 | "txid": "7978c0c9-7ea8-47e7-8e88-49634473c1f1", 744 | "revisao": 1, 745 | "devedor": { 746 | "cnpj": "12345678000195", 747 | "nome": "Empresa de Serviços SA" 748 | }, 749 | "valor": { 750 | "original": "567.89" 751 | }, 752 | "chave": "a1f4102e-a446-4a57-bcce-6fa48899c1d1", 753 | "solicitacaoPagador": "Informar cartão fidelidade" 754 | } 755 | }, 756 | "retorno2": { 757 | "summary": "Exemplo 2", 758 | "value": { 759 | "status": "CONCLUIDA", 760 | "calendario": { 761 | "criacao": "2020-09-09T20:15:00.358Z", 762 | "expiracao": "3600" 763 | }, 764 | "location": "pix.example.com/qr/1dd7f893-a58e-4172-8702-8dc33e21a403", 765 | "txid": "655dfdb1-a451-4b8f-bb58-254b958913fb", 766 | "revisao": 1, 767 | "devedor": { 768 | "cnpj": "12345678000195", 769 | "nome": "Empresa de Serviços SA" 770 | }, 771 | "valor": { 772 | "original": "100.00" 773 | }, 774 | "chave": "40a0932d-1918-4eee-845d-35a2da1690dc", 775 | "solicitacaoPagador": "Informar cartão fidelidade", 776 | "pix": [ 777 | { 778 | "endToEndId": "E12345678202009091221kkkkkkkkkkk", 779 | "txid": "655dfdb1-a451-4b8f-bb58-254b958913fb", 780 | "valor": "110.00", 781 | "horario": "2020-09-09T20:15:00.358Z", 782 | "pagador": { 783 | "cnpj": "12345678000195", 784 | "nome": "Empresa de Serviços SA" 785 | }, 786 | "infoPagador": "0123456789", 787 | "devolucoes": [ 788 | { 789 | "id": "123ABC", 790 | "rtrId": "Dxxxxxxxx202009091221kkkkkkkkkkk", 791 | "valor": "10.00", 792 | "horario": { 793 | "solicitacao": "2020-09-09T20:15:00.358Z" 794 | }, 795 | "status": "EM_PROCESSAMENTO" 796 | } 797 | ] 798 | } 799 | ] 800 | } 801 | }, 802 | "retorno3": { 803 | "summary": "Exemplo 1", 804 | "value": { 805 | "endToEndId": "E12345678202009091221abcdef12345", 806 | "txid": "cd1fe328-c875-4812-85a6-f233ae41b662", 807 | "valor": "100.00", 808 | "horario": "2020-09-10T13:03:33.902Z", 809 | "pagador": { 810 | "cnpj": "12345678000195", 811 | "nome": "Empresa de Serviços SA" 812 | }, 813 | "infoPagador": "Reforma da casa", 814 | "devolucoes": [ 815 | { 816 | "id": "000AAA111", 817 | "rtrId": "D12345678202009091000abcde123456", 818 | "valor": "11.00", 819 | "horario": { 820 | "solicitacao": "2020-09-10T13:03:33.902Z" 821 | }, 822 | "status": "EM_PROCESSAMENTO" 823 | } 824 | ] 825 | } 826 | }, 827 | "retorno4": { 828 | "summary": "Exemplo 2", 829 | "value": { 830 | "endToEndId": "E12345678202009091221ghijk78901234", 831 | "txid": "5b933948-f322-4266-b105-0ac54319e775", 832 | "valor": "200.00", 833 | "horario": "2020-09-10T13:03:33.902Z", 834 | "pagador": { 835 | "cpf": "12345678909", 836 | "nome": "Francisco da Silva" 837 | }, 838 | "infoPagador": "Revisão do carro" 839 | } 840 | }, 841 | "retorno5": { 842 | "summary": "Exemplo 1", 843 | "value": { 844 | "endToEndId": "E12345678202009091221kkkkkkkkkkk", 845 | "txid": "c3e0e7a4-e7f1-469a-9f78-2d3d4999343c", 846 | "valor": "110.00", 847 | "horario": "2020-09-09T20:15:00.358Z", 848 | "infoPagador": "0123456789", 849 | "devolucoes": { 850 | "id": "123ABC", 851 | "rtrId": "D12345678202009091221abcdf098765", 852 | "valor": "10.00", 853 | "horario": { 854 | "solicitacao": "2020-09-09T20:15:00.358Z" 855 | }, 856 | "status": "EM_PROCESSAMENTO" 857 | } 858 | } 859 | }, 860 | "retorno6": { 861 | "summary": "Exemplo 2", 862 | "value": { 863 | "endToEndId": "E87654321202009091221dfghi123456", 864 | "txid": "971122d8-f372-11ea-adc1-0242ac120002", 865 | "valor": "110.00", 866 | "horario": "2020-09-09T20:15:00.358Z", 867 | "infoPagador": "0123456789" 868 | } 869 | }, 870 | "retorno7": { 871 | "summary": "Exemplo 1", 872 | "value": { 873 | "id": "123456", 874 | "rtrId": "D12345678202009091000abcde123456", 875 | "valor": "7.89", 876 | "horario": { 877 | "solicitacao": "2020-09-11T15:25:59.411Z" 878 | }, 879 | "status": "EM_PROCESSAMENTO" 880 | } 881 | }, 882 | "retorno8": { 883 | "summary": "Exemplo 1", 884 | "value": { 885 | "txId": "fc9a4366-ff3d-4964-b5db-c6c91a8722d3", 886 | "revisao": "3", 887 | "calendario": { 888 | "criacao": "2020-09-15T19:39:54.013Z", 889 | "apresentacao": "2020-04-01T18:00:00Z", 890 | "expiracao": "3600" 891 | }, 892 | "status": "ATIVA", 893 | "valor": { 894 | "original": "500.00" 895 | }, 896 | "chave": "7407c9c8-f78b-11ea-adc1-0242ac120002", 897 | "solicitacaoPagador": "Informar cartão fidelidade", 898 | "infoAdicionais": [ 899 | { 900 | "nome": "quantidade", 901 | "valor": "2" 902 | } 903 | ] 904 | } 905 | }, 906 | "getCobs1": { 907 | "summary": "Exemplo 1", 908 | "value": { 909 | "parametros": { 910 | "inicio": "2020-04-01T00:00:00Z", 911 | "fim": "2020-04-02T10:00:00Z", 912 | "paginacao": { 913 | "paginaAtual": 0, 914 | "itensPorPagina": 100, 915 | "quantidadeDePaginas": 1, 916 | "quantidadeTotalDeItens": 2 917 | } 918 | }, 919 | "cobs": [ 920 | { 921 | "allOf": [ 922 | { 923 | "$ref": "#/components/examples/retorno1/value" 924 | } 925 | ] 926 | }, 927 | { 928 | "allOf": [ 929 | { 930 | "$ref": "#/components/examples/retorno2/value" 931 | } 932 | ] 933 | } 934 | ] 935 | } 936 | }, 937 | "getCobs2": { 938 | "summary": "Exemplo 2", 939 | "value": { 940 | "parametros": { 941 | "inicio": "2020-04-01T00:00:00Z", 942 | "fim": "2020-04-01T23:59:59Z", 943 | "paginacao": { 944 | "paginaAtual": 0, 945 | "itensPorPagina": 100, 946 | "quantidadeDePaginas": 1, 947 | "quantidadeTotalDeItens": 1 948 | } 949 | }, 950 | "cobs": [ 951 | { 952 | "allOf": [ 953 | { 954 | "$ref": "#/components/examples/retorno1/value" 955 | } 956 | ] 957 | } 958 | ] 959 | } 960 | }, 961 | "getPix1": { 962 | "summary": "Exemplo 1", 963 | "value": { 964 | "parametros": { 965 | "inicio": "2020-04-01T00:00:00Z", 966 | "fim": "2020-04-01T23:59:59Z", 967 | "paginacao": { 968 | "paginaAtual": 0, 969 | "itensPorPagina": 100, 970 | "quantidadeDePaginas": 1, 971 | "quantidadeTotalDeItens": 2 972 | } 973 | }, 974 | "pix": [ 975 | { 976 | "allOf": [ 977 | { 978 | "$ref": "#/components/examples/retorno3/value" 979 | } 980 | ] 981 | }, 982 | { 983 | "allOf": [ 984 | { 985 | "$ref": "#/components/examples/retorno4/value" 986 | } 987 | ] 988 | } 989 | ] 990 | } 991 | } 992 | }, 993 | "requestBodies": { 994 | "CobBody": { 995 | "description": "Dados para geração da cobrança.", 996 | "required": true, 997 | "content": { 998 | "application/json": { 999 | "schema": { 1000 | "$ref": "#/components/schemas/CobSolicitada" 1001 | }, 1002 | "examples": { 1003 | "exemplo1": { 1004 | "$ref": "#/components/examples/corpo1" 1005 | }, 1006 | "exemplo2": { 1007 | "$ref": "#/components/examples/corpo2" 1008 | } 1009 | } 1010 | } 1011 | } 1012 | }, 1013 | "CobBodyRevisada": { 1014 | "description": "Dados para geração da cobrança.", 1015 | "required": true, 1016 | "content": { 1017 | "application/json": { 1018 | "schema": { 1019 | "$ref": "#/components/schemas/CobRevisada" 1020 | }, 1021 | "examples": { 1022 | "exemplo1": { 1023 | "$ref": "#/components/examples/corpo5" 1024 | } 1025 | } 1026 | } 1027 | } 1028 | }, 1029 | "WebhookPixBody": { 1030 | "description": "Dados para notificação dos Pix.", 1031 | "required": true, 1032 | "content": { 1033 | "application/json": { 1034 | "schema": { 1035 | "properties": { 1036 | "pix": { 1037 | "type": "array", 1038 | "items": { 1039 | "$ref": "#/components/schemas/Pix" 1040 | }, 1041 | "example": [ 1042 | { 1043 | "allOf": [ 1044 | { 1045 | "$ref": "#/components/examples/retorno5/value" 1046 | } 1047 | ] 1048 | }, 1049 | { 1050 | "allOf": [ 1051 | { 1052 | "$ref": "#/components/examples/retorno6/value" 1053 | } 1054 | ] 1055 | } 1056 | ] 1057 | } 1058 | } 1059 | } 1060 | } 1061 | } 1062 | } 1063 | }, 1064 | "schemas": { 1065 | "TxId": { 1066 | "type": "string", 1067 | "title": "Id da Transação", 1068 | "description": "# Identificador da transação\n\nO campo txid, obrigatório, determina o identificador da transação.\nO objetivo desse campo é ser um elemento que possibilite ao PSP do recebedor apresentar ao usuário recebedor a funcionalidade de conciliação de pagamentos.\n\nNa pacs.008, é referenciado como `TransactionIdentification ` ou `idConciliacaoRecebedor`.\nO preenchimento do campo txid é limitado a 35 caracteres na pacs.008.\n\nEm termos de fluxo de funcionamento, o txid é lido pelo aplicativo do PSP do pagador e, \ndepois de confirmado o pagamento, é enviado para o SPI via pacs.008. \nUma pacs.008 também é enviada ao PSP do recebedor, contendo, além de todas as informações usuais \ndo pagamento, o txid.\nAo perceber um recebimento dotado de txid, o PSP do recebedor está apto a se comunicar com o usuário recebedor, \ninformando que um pagamento específico foi liquidado.\n\nO txid é criado exclusivamente pelo usuário recebedor e está sob sua responsabilidade.\nO txid, no contexto de representação de uma cobrança, é único por CPF/CNPJ do usuário recebedor. Cabe ao \nPSP recebedor validar essa regra na API PIX.\n", 1069 | "pattern": "[A-Z0-9-]{1,35}" 1070 | }, 1071 | "EndToEndId": { 1072 | "type": "string", 1073 | "title": "Id fim a fim da transação", 1074 | "description": "EndToEndIdentification que transita na PACS002, PACS004 e PACS008", 1075 | "pattern": "[A-Z0-9-]{1,35}" 1076 | }, 1077 | "DevolucaoId": { 1078 | "type": "string", 1079 | "title": "Id da Devolução", 1080 | "description": "Id gerado pelo cliente para representar unicamente uma devolução.", 1081 | "pattern": "[A-Z0-9-]{1,35}" 1082 | }, 1083 | "CobStatus": { 1084 | "type": "string", 1085 | "title": "Status da Cobrança", 1086 | "enum": [ 1087 | "ATIVA", 1088 | "CONCLUIDA", 1089 | "REMOVIDA_PELO_USUARIO_RECEBEDOR", 1090 | "REMOVIDA_PELO_PSP" 1091 | ] 1092 | }, 1093 | "CPF": { 1094 | "type": "string", 1095 | "title": "CPF", 1096 | "pattern": "/^\\d{11}$/" 1097 | }, 1098 | "CNPJ": { 1099 | "type": "string", 1100 | "title": "CNPJ", 1101 | "pattern": "/^\\d{14}$/" 1102 | }, 1103 | "Revisao": { 1104 | "type": "integer", 1105 | "format": "int32", 1106 | "title": "Revisão", 1107 | "description": "Revisão da cobrança. Sempre começa em zero. Sempre varia em acréscimos de 1." 1108 | }, 1109 | "Location": { 1110 | "type": "string", 1111 | "title": "Localização do payload", 1112 | "description": "Localização do Payload a ser informada na criação da cobrança.", 1113 | "maxLength": 77, 1114 | "format": "uri", 1115 | "example": "pix.example.com/qr/2353c790-eefb-11ea-adc1-0242ac120002" 1116 | }, 1117 | "PessoaFisica": { 1118 | "type": "object", 1119 | "required": [ 1120 | "cpf", 1121 | "nome" 1122 | ], 1123 | "title": "Pessoa Física", 1124 | "properties": { 1125 | "cpf": { 1126 | "allOf": [ 1127 | { 1128 | "$ref": "#/components/schemas/CPF" 1129 | }, 1130 | { 1131 | "description": "CPF do usuário pagador." 1132 | } 1133 | ] 1134 | }, 1135 | "nome": { 1136 | "type": "string", 1137 | "title": "Nome", 1138 | "description": "Nome do usuário pagador.", 1139 | "maxLength": 200 1140 | } 1141 | } 1142 | }, 1143 | "PessoaJuridica": { 1144 | "type": "object", 1145 | "required": [ 1146 | "cnpj", 1147 | "nome" 1148 | ], 1149 | "title": "Pessoa Jurídica", 1150 | "properties": { 1151 | "cnpj": { 1152 | "allOf": [ 1153 | { 1154 | "$ref": "#/components/schemas/CNPJ" 1155 | }, 1156 | { 1157 | "description": "CNPJ do usuário pagador." 1158 | } 1159 | ] 1160 | }, 1161 | "nome": { 1162 | "type": "string", 1163 | "title": "Nome", 1164 | "description": "Nome do usuário pagador.", 1165 | "maxLength": 200 1166 | } 1167 | } 1168 | }, 1169 | "Webhook": { 1170 | "type": "object", 1171 | "required": [ 1172 | "webhookUrl" 1173 | ], 1174 | "title": "Webhook", 1175 | "properties": { 1176 | "webhookUrl": { 1177 | "type": "string", 1178 | "format": "uri", 1179 | "example": "https://pix.example.com/api/webhook/" 1180 | } 1181 | } 1182 | }, 1183 | "CobExpiracao": { 1184 | "type": "object", 1185 | "title": "Expiração", 1186 | "properties": { 1187 | "expiracao": { 1188 | "type": "integer", 1189 | "format": "int32", 1190 | "title": "Tempo de vida da cobrança, especificado em segundos.", 1191 | "description": "Tempo de vida da cobrança, especificado em segundos a partir da data de criação (Calendario.criacao)\n", 1192 | "example": "3600" 1193 | } 1194 | } 1195 | }, 1196 | "CobApresentacao": { 1197 | "type": "object", 1198 | "title": "Apresentação", 1199 | "required": [ 1200 | "apresentacao" 1201 | ], 1202 | "properties": { 1203 | "apresentacao": { 1204 | "type": "string", 1205 | "format": "date-time", 1206 | "title": "Timestamp de apresentação do QR Code", 1207 | "description": "Timestamp que indica o momento em que o payload JSON que representa a cobrança foi recuperado. Ou seja, idealmente, é o momento em que o usuário realizou a captura do QR Code para verificar os dados de pagamento. Respeita o formato definido na RFC 3339." 1208 | } 1209 | } 1210 | }, 1211 | "CobCriacao": { 1212 | "type": "object", 1213 | "title": "Criação", 1214 | "required": [ 1215 | "criacao" 1216 | ], 1217 | "properties": { 1218 | "criacao": { 1219 | "type": "string", 1220 | "format": "date-time", 1221 | "title": "Data de Criação", 1222 | "description": "Timestamp que indica o momento em que foi criada a cobrança. Respeita o formato definido na RFC 3339." 1223 | } 1224 | } 1225 | }, 1226 | "Valor": { 1227 | "type": "string", 1228 | "title": "Valor", 1229 | "pattern": "\\d{1,10}\\.\\d{2}" 1230 | }, 1231 | "CobBase": { 1232 | "type": "object", 1233 | "title": "Cobrança Base", 1234 | "description": "Atributos comuns a todas entidades de Cobrança", 1235 | "properties": { 1236 | "devedor": { 1237 | "description": "Os campos aninhados sob o objeto devedor são opcionais e identificam o devedor, ou seja, a pessoa ou a instituição a quem a cobrança está endereçada. Não identifica, necessariamente, quem irá efetivamente realizar o pagamento. Um CPF pode ser o devedor de uma cobrança, mas pode acontecer de outro CPF realizar, efetivamente, o pagamento do documento. Não é permitido que o campo pagador.cpf e campo pagador.cnpj estejam preenchidos ao mesmo tempo. Se o campo pagador.cnpj está preenchido, então o campo pagador.cpf não pode estar preenchido, e vice-versa. Se o campo pagador.nome está preenchido, então deve existir ou um pagador.cpf ou um campo pagador.cnpj preenchido.", 1238 | "oneOf": [ 1239 | { 1240 | "$ref": "#/components/schemas/PessoaFisica" 1241 | }, 1242 | { 1243 | "$ref": "#/components/schemas/PessoaJuridica" 1244 | } 1245 | ] 1246 | }, 1247 | "valor": { 1248 | "type": "object", 1249 | "description": "Todos os campos que indicam valores monetários obedecem ao formato do ID 54 da especificação EMV/BR Code para QR Codes. O separador decimal é o caractere ponto. Não é aplicável utilizar separador de milhar. Exemplos de valores aderentes ao padrão: “0.00”, “1.00”, “123.99”, “123456789.23”", 1250 | "required": [ 1251 | "original" 1252 | ], 1253 | "properties": { 1254 | "original": { 1255 | "allOf": [ 1256 | { 1257 | "$ref": "#/components/schemas/Valor" 1258 | }, 1259 | { 1260 | "title": "Valor", 1261 | "description": "Valor original da cobrança." 1262 | } 1263 | ] 1264 | } 1265 | } 1266 | }, 1267 | "chave": { 1268 | "type": "string", 1269 | "title": "Chave DICT do recebedor", 1270 | "description": "O campo chave, obrigatório, determina a chave Pix registrada no DICT que será utilizada para a cobrança. Essa chave será lida pelo aplicativo do PSP do pagador para consulta ao DICT, que retornará a informação que identificará o recebedor da cobrança.", 1271 | "maxLength": 77 1272 | }, 1273 | "solicitacaoPagador": { 1274 | "type": "string", 1275 | "title": "Solicitação ao pagador", 1276 | "description": "O campo solicitacaoPagador, opcional, determina um texto a ser apresentado ao pagador para que ele possa digitar uma informação correlata, em formato livre, a ser enviada ao recebedor. Esse texto será preenchido, na pacs.008, pelo PSP do pagador, no campo RemittanceInformation . O tamanho do campo na pacs.008 está limitado a 140 caracteres.", 1277 | "maxLength": 140 1278 | }, 1279 | "infoAdicionais": { 1280 | "type": "array", 1281 | "title": "Informações adicionais", 1282 | "description": "Cada respectiva informação adicional contida na lista (nome e valor) deve ser apresentada ao pagador.", 1283 | "maximum": 50, 1284 | "items": { 1285 | "type": "object", 1286 | "required": [ 1287 | "nome", 1288 | "valor" 1289 | ], 1290 | "properties": { 1291 | "nome": { 1292 | "type": "string", 1293 | "title": "Nome", 1294 | "description": "Nome do campo.", 1295 | "maxLength": 50 1296 | }, 1297 | "valor": { 1298 | "type": "string", 1299 | "title": "Valor", 1300 | "description": "Dados do campo.", 1301 | "maxLength": 200 1302 | } 1303 | } 1304 | } 1305 | } 1306 | } 1307 | }, 1308 | "CobSolicitada": { 1309 | "type": "object", 1310 | "title": "Cobrança Solicitada", 1311 | "description": "Dados enviados para criação ou alteração da cobrança via API Pix", 1312 | "required": [ 1313 | "valor", 1314 | "chave" 1315 | ], 1316 | "allOf": [ 1317 | { 1318 | "type": "object", 1319 | "properties": { 1320 | "calendario": { 1321 | "title": "Calendário", 1322 | "description": "Os campos aninhados sob o identificador calendário organizam informações a respeito de controle de tempo da cobrança.", 1323 | "allOf": [ 1324 | { 1325 | "$ref": "#/components/schemas/CobExpiracao" 1326 | } 1327 | ] 1328 | } 1329 | } 1330 | }, 1331 | { 1332 | "$ref": "#/components/schemas/CobBase" 1333 | } 1334 | ] 1335 | }, 1336 | "CobRevisada": { 1337 | "type": "object", 1338 | "title": "Cobrança Revisada", 1339 | "description": "Dados enviados para revisão da cobrança via API Pix", 1340 | "allOf": [ 1341 | { 1342 | "type": "object", 1343 | "properties": { 1344 | "calendario": { 1345 | "title": "Calendário", 1346 | "description": "Os campos aninhados sob o identificador calendário organizam informações a respeito de controle de tempo da cobrança.", 1347 | "allOf": [ 1348 | { 1349 | "$ref": "#/components/schemas/CobExpiracao" 1350 | } 1351 | ] 1352 | }, 1353 | "status": { 1354 | "title": "Novo status da cobrança", 1355 | "description": "O único status que pode ser informado na revisão da Cobrança é o REMOVIDA_PELO_USUARIO_RECEBEDOR", 1356 | "allOf": [ 1357 | { 1358 | "$ref": "#/components/schemas/CobStatus" 1359 | } 1360 | ] 1361 | } 1362 | } 1363 | }, 1364 | { 1365 | "$ref": "#/components/schemas/CobBase" 1366 | } 1367 | ] 1368 | }, 1369 | "CobGerada": { 1370 | "type": "object", 1371 | "title": "Cobrança Gerada", 1372 | "description": "Dados criados ou alterados da cobrança via API Pix", 1373 | "required": [ 1374 | "location", 1375 | "txid", 1376 | "calendario", 1377 | "revisao", 1378 | "status", 1379 | "valor", 1380 | "chave" 1381 | ], 1382 | "allOf": [ 1383 | { 1384 | "type": "object", 1385 | "properties": { 1386 | "calendario": { 1387 | "title": "Calendário", 1388 | "description": "Os campos aninhados sob o identificador calendário organizam informações a respeito de controle de tempo da cobrança.", 1389 | "allOf": [ 1390 | { 1391 | "$ref": "#/components/schemas/CobCriacao" 1392 | }, 1393 | { 1394 | "$ref": "#/components/schemas/CobExpiracao" 1395 | } 1396 | ] 1397 | }, 1398 | "status": { 1399 | "$ref": "#/components/schemas/CobStatus" 1400 | }, 1401 | "txid": { 1402 | "$ref": "#/components/schemas/TxId" 1403 | }, 1404 | "revisao": { 1405 | "$ref": "#/components/schemas/Revisao" 1406 | }, 1407 | "location": { 1408 | "$ref": "#/components/schemas/Location" 1409 | } 1410 | } 1411 | }, 1412 | { 1413 | "$ref": "#/components/schemas/CobBase" 1414 | } 1415 | ] 1416 | }, 1417 | "CobCompleta": { 1418 | "title": "Cobrança Completa", 1419 | "allOf": [ 1420 | { 1421 | "$ref": "#/components/schemas/CobGerada" 1422 | }, 1423 | { 1424 | "$ref": "#/components/schemas/CobSolicitada" 1425 | }, 1426 | { 1427 | "type": "object", 1428 | "title": "Cob", 1429 | "required": [ 1430 | "status" 1431 | ], 1432 | "properties": { 1433 | "pix": { 1434 | "type": "array", 1435 | "title": "Pix recebidos", 1436 | "items": { 1437 | "$ref": "#/components/schemas/Pix" 1438 | } 1439 | } 1440 | } 1441 | } 1442 | ] 1443 | }, 1444 | "CobPayload": { 1445 | "type": "object", 1446 | "title": "Payload JSON da cobrança", 1447 | "description": "Dados da cobrança acessados pelo payload JSON", 1448 | "required": [ 1449 | "txid", 1450 | "calendario", 1451 | "revisao", 1452 | "status", 1453 | "valor", 1454 | "chave" 1455 | ], 1456 | "allOf": [ 1457 | { 1458 | "type": "object", 1459 | "properties": { 1460 | "txid": { 1461 | "$ref": "#/components/schemas/TxId" 1462 | }, 1463 | "revisao": { 1464 | "$ref": "#/components/schemas/Revisao" 1465 | }, 1466 | "calendario": { 1467 | "title": "Calendário", 1468 | "description": "Os campos aninhados sob o identificador calendário organizam informações a respeito de controle de tempo da cobrança.", 1469 | "allOf": [ 1470 | { 1471 | "$ref": "#/components/schemas/CobCriacao" 1472 | }, 1473 | { 1474 | "$ref": "#/components/schemas/CobApresentacao" 1475 | }, 1476 | { 1477 | "$ref": "#/components/schemas/CobExpiracao" 1478 | } 1479 | ] 1480 | }, 1481 | "status": { 1482 | "$ref": "#/components/schemas/CobStatus" 1483 | } 1484 | } 1485 | }, 1486 | { 1487 | "$ref": "#/components/schemas/CobBase" 1488 | } 1489 | ] 1490 | }, 1491 | "ParametrosConsultaCob": { 1492 | "type": "object", 1493 | "title": "Parâmetros de Consulta de Cobrança", 1494 | "description": "Parâmetros utilizados para a realização de uma consulta de cobranças.", 1495 | "required": [ 1496 | "inicio", 1497 | "fim", 1498 | "paginacao" 1499 | ], 1500 | "properties": { 1501 | "inicio": { 1502 | "type": "string", 1503 | "format": "date-time", 1504 | "title": "Data de Início", 1505 | "description": "Data inicial utilizada na consulta. Respeita RFC 3339.", 1506 | "example": "2020-04-01T00:00:00Z" 1507 | }, 1508 | "fim": { 1509 | "type": "string", 1510 | "format": "date-time", 1511 | "title": "Data de Fim", 1512 | "description": "Data de fim utilizada na consulta. Respeita RFC 3339.", 1513 | "example": "2020-04-01T17:00:00Z" 1514 | }, 1515 | "cpf": { 1516 | "allOf": [ 1517 | { 1518 | "$ref": "#/components/schemas/CPF" 1519 | }, 1520 | { 1521 | "description": "Filtro pelo CPF do devedor. Não pode ser utilizado ao mesmo tempo que o CNPJ." 1522 | } 1523 | ] 1524 | }, 1525 | "cnpj": { 1526 | "allOf": [ 1527 | { 1528 | "$ref": "#/components/schemas/CNPJ" 1529 | }, 1530 | { 1531 | "description": "Filtro pelo CNPJ do devedor. Não pode ser utilizado ao mesmo tempo que o CPF." 1532 | } 1533 | ] 1534 | }, 1535 | "status": { 1536 | "allOf": [ 1537 | { 1538 | "$ref": "#/components/schemas/CobStatus" 1539 | }, 1540 | { 1541 | "description": "Filtro pelo status das cobranças." 1542 | } 1543 | ] 1544 | }, 1545 | "paginacao": { 1546 | "$ref": "#/components/schemas/Paginacao" 1547 | } 1548 | } 1549 | }, 1550 | "CobsConsultadas": { 1551 | "type": "object", 1552 | "title": "Cobranças Consultadas", 1553 | "required": [ 1554 | "parametros", 1555 | "cobs" 1556 | ], 1557 | "properties": { 1558 | "parametros": { 1559 | "$ref": "#/components/schemas/ParametrosConsultaCob" 1560 | }, 1561 | "cobs": { 1562 | "type": "array", 1563 | "title": "Lista de cobranças", 1564 | "items": { 1565 | "allOf": [ 1566 | { 1567 | "$ref": "#/components/schemas/CobCompleta" 1568 | }, 1569 | { 1570 | "required": [ 1571 | "status", 1572 | "txid", 1573 | "idCob" 1574 | ] 1575 | } 1576 | ] 1577 | } 1578 | } 1579 | } 1580 | }, 1581 | "Pix": { 1582 | "type": "object", 1583 | "title": "Pix", 1584 | "required": [ 1585 | "endToEndId", 1586 | "valor", 1587 | "horario" 1588 | ], 1589 | "properties": { 1590 | "endToEndId": { 1591 | "$ref": "#/components/schemas/EndToEndId" 1592 | }, 1593 | "txid": { 1594 | "$ref": "#/components/schemas/TxId" 1595 | }, 1596 | "valor": { 1597 | "allOf": [ 1598 | { 1599 | "$ref": "#/components/schemas/Valor" 1600 | }, 1601 | { 1602 | "description": "Valor do Pix." 1603 | } 1604 | ] 1605 | }, 1606 | "horario": { 1607 | "type": "string", 1608 | "format": "date-time", 1609 | "title": "Horário", 1610 | "description": "Horário em que o Pix foi processado no PSP." 1611 | }, 1612 | "pagador": { 1613 | "oneOf": [ 1614 | { 1615 | "$ref": "#/components/schemas/PessoaFisica" 1616 | }, 1617 | { 1618 | "$ref": "#/components/schemas/PessoaJuridica" 1619 | } 1620 | ] 1621 | }, 1622 | "infoPagador": { 1623 | "type": "string", 1624 | "title": "Informação livre do pagador", 1625 | "maxLength": 140 1626 | }, 1627 | "devolucoes": { 1628 | "type": "array", 1629 | "title": "Devoluções", 1630 | "items": { 1631 | "$ref": "#/components/schemas/Devolucao" 1632 | } 1633 | } 1634 | } 1635 | }, 1636 | "Devolucao": { 1637 | "type": "object", 1638 | "title": "Devolução", 1639 | "required": [ 1640 | "id", 1641 | "rtrId", 1642 | "valor", 1643 | "horario", 1644 | "status" 1645 | ], 1646 | "properties": { 1647 | "id": { 1648 | "$ref": "#/components/schemas/DevolucaoId" 1649 | }, 1650 | "rtrId": { 1651 | "type": "string", 1652 | "title": "RtrId", 1653 | "description": "ReturnIdentification que transita na PACS004.", 1654 | "example": "D12345678202009091000abcde123456", 1655 | "minLength": 32, 1656 | "maxLength": 32 1657 | }, 1658 | "valor": { 1659 | "allOf": [ 1660 | { 1661 | "$ref": "#/components/schemas/Valor" 1662 | }, 1663 | { 1664 | "description": "Valor a devolver." 1665 | } 1666 | ] 1667 | }, 1668 | "horario": { 1669 | "type": "object", 1670 | "required": [ 1671 | "solicitacao" 1672 | ], 1673 | "properties": { 1674 | "solicitacao": { 1675 | "type": "string", 1676 | "format": "date-time", 1677 | "title": "Horário de solicitação", 1678 | "description": "Horário no qual a devolução foi solicitada no PSP." 1679 | }, 1680 | "liquidacao": { 1681 | "type": "string", 1682 | "format": "date-time", 1683 | "title": "Horário de liquidacao", 1684 | "description": "Horário no qual a devolução foi liquidada no PSP." 1685 | } 1686 | } 1687 | }, 1688 | "status": { 1689 | "type": "string", 1690 | "title": "Status", 1691 | "description": "Status da devolução.", 1692 | "enum": [ 1693 | "EM_PROCESSAMENTO", 1694 | "DEVOLVIDO", 1695 | "NAO_REALIZADO" 1696 | ] 1697 | } 1698 | } 1699 | }, 1700 | "ParametrosConsultaPix": { 1701 | "type": "object", 1702 | "title": "Parâmetros de Consulta Pix", 1703 | "description": "Parâmetros utilizados para a realização de uma consulta de cobranças.", 1704 | "required": [ 1705 | "inicio", 1706 | "fim", 1707 | "paginacao" 1708 | ], 1709 | "properties": { 1710 | "inicio": { 1711 | "type": "string", 1712 | "format": "date-time", 1713 | "title": "Data de Início", 1714 | "description": "Data inicial utilizada na consulta. Respeita RFC 3339.", 1715 | "example": "2020-04-01T00:00:00Z" 1716 | }, 1717 | "fim": { 1718 | "type": "string", 1719 | "format": "date-time", 1720 | "title": "Data de Fim", 1721 | "description": "Data de fim utilizada na consulta. Respeita RFC 3339.", 1722 | "example": "2020-04-01T17:00:00Z" 1723 | }, 1724 | "cpf": { 1725 | "allOf": [ 1726 | { 1727 | "$ref": "#/components/schemas/CPF" 1728 | }, 1729 | { 1730 | "description": "Filtro pelo CPF do pagador. Não pode ser utilizado ao mesmo tempo que o CNPJ." 1731 | } 1732 | ] 1733 | }, 1734 | "cnpj": { 1735 | "allOf": [ 1736 | { 1737 | "$ref": "#/components/schemas/CNPJ" 1738 | }, 1739 | { 1740 | "description": "Filtro pelo CNPJ do pagador. Não pode ser utilizado ao mesmo tempo que o CPF." 1741 | } 1742 | ] 1743 | }, 1744 | "txId": { 1745 | "$ref": "#/components/schemas/TxId" 1746 | }, 1747 | "paginacao": { 1748 | "$ref": "#/components/schemas/Paginacao" 1749 | } 1750 | } 1751 | }, 1752 | "PixConsultados": { 1753 | "type": "object", 1754 | "title": "Pix Consultados", 1755 | "required": [ 1756 | "parametros", 1757 | "cobs" 1758 | ], 1759 | "properties": { 1760 | "parametros": { 1761 | "$ref": "#/components/schemas/ParametrosConsultaPix" 1762 | }, 1763 | "pix": { 1764 | "type": "array", 1765 | "title": "Lista de Pix recebidos", 1766 | "items": { 1767 | "allOf": [ 1768 | { 1769 | "$ref": "#/components/schemas/Pix" 1770 | } 1771 | ] 1772 | } 1773 | } 1774 | } 1775 | }, 1776 | "Paginacao": { 1777 | "type": "object", 1778 | "title": "Paginação", 1779 | "required": [ 1780 | "paginaAtual", 1781 | "itensPorPagina", 1782 | "quantidadeDePaginas", 1783 | "quantidadeTotalDeItens" 1784 | ], 1785 | "properties": { 1786 | "paginaAtual": { 1787 | "type": "integer", 1788 | "title": "Página atual", 1789 | "description": "Número da página recuperada.", 1790 | "minimum": 0 1791 | }, 1792 | "itensPorPagina": { 1793 | "type": "integer", 1794 | "title": "Itens por página", 1795 | "description": "Quantidade de registros retornado na página.", 1796 | "minimum": 1 1797 | }, 1798 | "quantidadeDePaginas": { 1799 | "type": "integer", 1800 | "title": "Quantidade de páginas", 1801 | "description": "Quantidade de páginas disponíveis para consulta.", 1802 | "minimum": 1 1803 | }, 1804 | "quantidadeTotalDeItens": { 1805 | "type": "integer", 1806 | "title": "Quantidade total de itens", 1807 | "description": "Quantidade total de itens disponíveis de acordo com os parâmetros informados.", 1808 | "minimum": 0 1809 | } 1810 | } 1811 | } 1812 | }, 1813 | "parameters": { 1814 | "inicio": { 1815 | "in": "query", 1816 | "name": "inicio", 1817 | "required": true, 1818 | "schema": { 1819 | "type": "string", 1820 | "format": "date-time", 1821 | "title": "Data de início", 1822 | "description": "Filtra os registros cuja data de criação seja maior ou igual que a data de início. Respeita RFC 3339." 1823 | } 1824 | }, 1825 | "fim": { 1826 | "in": "query", 1827 | "name": "fim", 1828 | "required": true, 1829 | "schema": { 1830 | "type": "string", 1831 | "format": "date-time", 1832 | "title": "Data de início", 1833 | "description": "Filtra os registros cuja data de criação seja maior ou igual que a data de início. Respeita RFC 3339." 1834 | } 1835 | }, 1836 | "paginaAtual": { 1837 | "in": "query", 1838 | "name": "paginacao.paginaAtual", 1839 | "required": false, 1840 | "schema": { 1841 | "type": "integer", 1842 | "format": "int32", 1843 | "title": "Página atual", 1844 | "minimum": 0, 1845 | "default": 0, 1846 | "description": "Página a ser retornada pela consulta. Se não for informada, o PSP assumirá que será 0." 1847 | } 1848 | }, 1849 | "itensPorPagina": { 1850 | "in": "query", 1851 | "name": "paginacao.itensPorPagina", 1852 | "required": false, 1853 | "schema": { 1854 | "type": "integer", 1855 | "format": "int32", 1856 | "title": "Itens por Página", 1857 | "minimum": 1, 1858 | "maximum": 1000, 1859 | "default": 100, 1860 | "description": "Quantidade máxima de registros retornados em cada página. Apenas a última página pode conter uma quantidade menor de registros." 1861 | } 1862 | } 1863 | } 1864 | } 1865 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "swagger-to-react-query", 3 | "version": "0.1.9", 4 | "license": "MIT", 5 | "keywords": [ 6 | "react", 7 | "react-query", 8 | "swagger", 9 | "open-api", 10 | "code-generation", 11 | "fetch" 12 | ], 13 | "author": { 14 | "name": "Munir Ahmed Elsangedy", 15 | "email": "elsangedy@gmail.com", 16 | "url": "https://github.com/elsangedy" 17 | }, 18 | "main": "src/index.js", 19 | "files": [ 20 | "src" 21 | ], 22 | "bin": { 23 | "swagger-to-react-query": "src/index.js" 24 | }, 25 | "scripts": { 26 | "generate": "node ./src/index.js" 27 | }, 28 | "dependencies": { 29 | "chalk": "^4.1.0", 30 | "ky": "^0.23.0", 31 | "ky-universal": "^0.8.2", 32 | "meow": "^7.1.1", 33 | "swagger2openapi": "^7.0.2" 34 | }, 35 | "peerDependencies": {}, 36 | "devDependencies": {} 37 | } 38 | -------------------------------------------------------------------------------- /src/generator.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk') 2 | const swagger2openapi = require('swagger2openapi') 3 | 4 | const { pascalCase, camelCase } = require('./utils') 5 | const generatorApi = require('./generatorApi') 6 | const generatorHook = require('./generatorHook') 7 | const generatorApiTypes = require('./generatorApiTypes') 8 | const generatorHookTypes = require('./generatorHookTypes') 9 | const { generatorGlobalTypes, generatorTypes } = require('./generatorTypes') 10 | 11 | const log = console.log 12 | 13 | function convertToOpenApiSchema(data) { 14 | return new Promise((resolve, reject) => { 15 | if (!data.openapi || !data.openapi.startsWith('3.0')) { 16 | swagger2openapi.convertObj(data, {}, (err, convertedObj) => { 17 | if (err) { 18 | reject(err) 19 | } else { 20 | resolve(convertedObj.openapi) 21 | } 22 | }) 23 | } else { 24 | resolve(data) 25 | } 26 | }) 27 | } 28 | 29 | function validateSchema(schema) { 30 | const operationIds = [] 31 | 32 | Object.entries(schema.paths).forEach(([route, verbs]) => { 33 | Object.entries(verbs).forEach(([verb, operation]) => { 34 | if (['get', 'post', 'patch', 'put', 'delete'].includes(verb)) { 35 | if (!operation.operationId && !!operation.summary) { 36 | operation.operationId = camelCase(operation.summary) 37 | } 38 | 39 | if (!operation.operationId) { 40 | throw new Error( 41 | `Every path must have a operationId or summary - No operationId or summary set for ${verb} ${route}` 42 | ) 43 | } 44 | 45 | if (operationIds.includes(operation.operationId)) { 46 | throw new Error(`"${operation.operationId}" is duplicated in your schema definition!`) 47 | } 48 | 49 | operationIds.push(operation.operationId) 50 | } 51 | }) 52 | }) 53 | } 54 | 55 | async function generator({ specs, config }) { 56 | const schema = await convertToOpenApiSchema(specs) 57 | 58 | let outputCode = '' 59 | let outputTypes = generatorGlobalTypes(schema) 60 | 61 | validateSchema(schema) 62 | 63 | Object.entries(schema.paths).forEach(([route, verbs]) => { 64 | Object.entries(verbs).forEach(([verb, operation]) => { 65 | if (['get', 'post', 'patch', 'put', 'delete'].includes(verb)) { 66 | const operationName = pascalCase(operation.operationId) 67 | const operationType = verb === 'get' ? 'Query' : 'Mutation' 68 | const isOperationQuery = operationType === 'Query' 69 | 70 | const allParams = [...(verbs.parameters || []), ...(operation.parameters || [])] 71 | const pathParamsBase = allParams.filter((param) => param.in === 'path') 72 | const pathParams = pathParamsBase.map((param) => param.name) 73 | const queryParamsBase = allParams.filter((param) => param.in === 'query') 74 | const queryParams = queryParamsBase.map((param) => param.name) 75 | const hasPathParams = pathParams.length > 0 76 | const hasQueryParams = queryParams.length > 0 77 | const hasQueryParamsOrPathParams = hasPathParams || hasQueryParams 78 | 79 | const params = { 80 | route, 81 | verb: verb.toLowerCase(), 82 | operation, 83 | operationName, 84 | operationType, 85 | isOperationQuery, 86 | allParams, 87 | pathParams, 88 | queryParams, 89 | pathParamsBase, 90 | queryParamsBase, 91 | hasPathParams, 92 | hasQueryParams, 93 | hasQueryParamsOrPathParams, 94 | } 95 | 96 | outputCode += generatorApi(params) 97 | outputCode += generatorHook(params) 98 | outputCode += ` 99 | ` 100 | outputTypes += generatorTypes(params) 101 | outputTypes += generatorApiTypes(params) 102 | outputTypes += generatorHookTypes(params) 103 | outputTypes += ` 104 | ` 105 | } 106 | }) 107 | }) 108 | 109 | const hasQuery = Boolean(outputCode.match(/useQuery/)) 110 | const hasMutation = Boolean(outputCode.match(/useMutation/)) 111 | 112 | const codeReactQueryImports = [] 113 | const typesReactQueryImports = [] 114 | 115 | if (hasQuery) { 116 | codeReactQueryImports.push('useQuery') 117 | typesReactQueryImports.push('QueryConfig', 'QueryResult') 118 | } 119 | 120 | if (hasMutation) { 121 | codeReactQueryImports.push('useMutation') 122 | typesReactQueryImports.push('MutationConfig', 'MutateFunction', 'MutationResult') 123 | } 124 | 125 | // imports 126 | outputCode = `/* eslint-disable */ 127 | /* tslint:disable */ 128 | import ky from 'ky' 129 | import { ${codeReactQueryImports.join(', ')} } from 'react-query' 130 | 131 | let api = ky.create(${JSON.stringify(config.kyOptions || {}, null, 2)}) 132 | 133 | export const getApi = () => api 134 | 135 | export const setApi = (newApi) => { 136 | api = newApi 137 | } 138 | 139 | export const extendApi = (options) => { 140 | api = getApi().extend(options) 141 | } 142 | 143 | const requestFn = async ({ url, method, pathParams, queryParams, ...rest }) => { 144 | const urlPathParams = url.match(/{([^}]+)}/g) 145 | 146 | if (urlPathParams) { 147 | url = urlPathParams.reduce((acc, param) => acc.replace(param, pathParams[param.replace(/{|}/g, '')]), url) 148 | } else { 149 | queryParams = { ...queryParams, ...pathParams } 150 | } 151 | 152 | if (url.charAt(0) === '/') { 153 | url = url.replace('/', '') 154 | } 155 | 156 | const response = await api(url, { 157 | method, 158 | ...rest, 159 | searchParams: { 160 | ...(rest.searchParams || {}), 161 | ...queryParams 162 | } 163 | }) 164 | 165 | let data 166 | 167 | try { 168 | const contentType = (response.headers.get('content-type') || '').split(';')[0] 169 | 170 | const responseType = 171 | { 172 | 'application/json': 'json', 173 | 'application/pdf': 'blob' 174 | }[contentType] || 'text' 175 | 176 | data = await response[responseType]() 177 | } catch (e) { 178 | data = e.message 179 | } 180 | 181 | if (!response || !response.ok) { 182 | const error = { 183 | data, 184 | status: response.status, 185 | message: \`Failed to fetch: \${response.status} \${response.statusText}\` 186 | } 187 | 188 | throw error 189 | } 190 | 191 | return data 192 | } 193 | 194 | const queryFn = (options = {}) => (url, pathParams = {}, queryParams = {}) => { 195 | const controller = new AbortController() 196 | const { signal } = controller 197 | 198 | const promise = requestFn({ 199 | url, 200 | method: 'get', 201 | pathParams, 202 | queryParams, 203 | signal, 204 | ...options 205 | }) 206 | 207 | // cancel the request if React Query calls the 'promise.cancel' method 208 | promise.cancel = () => { 209 | controller.abort('Query was cancelled by React Query') 210 | } 211 | 212 | return promise 213 | } 214 | 215 | const mutationFn = ( 216 | method, 217 | url, 218 | pathParams = {}, 219 | queryParams = {}, 220 | options = {} 221 | ) => (body = {}) => { 222 | if (Array.isArray(body)) { 223 | pathParams = { ...pathParams, ...(body[0] || {}) } 224 | queryParams = { ...queryParams, ...(body[1] || {}) } 225 | options = { ...options, ...(body[3] || {}) } 226 | body = body[2] 227 | } 228 | 229 | const request = { 230 | url, 231 | method, 232 | pathParams, 233 | queryParams, 234 | ...options 235 | } 236 | 237 | if (method !== 'delete') { 238 | try { 239 | request[body.toString() === '[object FormData]' ? 'body' : 'json'] = body 240 | } catch(e) { 241 | } 242 | } 243 | 244 | return requestFn(request) 245 | } 246 | 247 | ${outputCode}` 248 | 249 | outputTypes = `/* eslint-disable */ 250 | /* tslint:disable */ 251 | import ky, { Options } from 'ky' 252 | import { ${typesReactQueryImports.join(', ')} } from 'react-query' 253 | 254 | export const getApi: { (): typeof ky } 255 | 256 | export const setApi: { (newApi: typeof ky ): void } 257 | 258 | export const extendApi: { (options: Options ): void } 259 | 260 | ${outputTypes}` 261 | 262 | log(chalk.green(`Finish ${config.name} code generation`)) 263 | 264 | return Promise.resolve({ 265 | code: outputCode, 266 | types: outputTypes, 267 | }) 268 | } 269 | 270 | module.exports = generator 271 | -------------------------------------------------------------------------------- /src/generatorApi.js: -------------------------------------------------------------------------------- 1 | const { ifElse } = require('./utils') 2 | 3 | function generatorApiTypes({ 4 | verb, 5 | route, 6 | operationName, 7 | operationType, 8 | hasPathParams, 9 | hasQueryParams, 10 | isOperationQuery, 11 | }) { 12 | let output = '' 13 | 14 | const methodName = `${operationType.toLowerCase()}${operationName}` 15 | 16 | if (isOperationQuery) { 17 | output += `export const ${methodName} = (${ifElse(hasPathParams, 'pathParams, ')}${ifElse( 18 | hasQueryParams, 19 | 'queryParams, ' 20 | )}options) => queryFn(options)('${route}'${ifElse(hasPathParams, ', pathParams')}${ifElse( 21 | hasQueryParams, 22 | ', queryParams' 23 | )})` 24 | } else { 25 | output += `export const ${methodName} = (${ifElse(hasPathParams, 'pathParams, ')}${ifElse( 26 | hasQueryParams, 27 | 'queryParams, ' 28 | )}options) => mutationFn('${verb}', '${route}', ${ifElse(hasPathParams, 'pathParams', '{}')}, ${ifElse( 29 | hasQueryParams, 30 | 'queryParams', 31 | '{}' 32 | )}, options)` 33 | } 34 | 35 | return `${output} 36 | ` 37 | } 38 | 39 | module.exports = generatorApiTypes 40 | -------------------------------------------------------------------------------- /src/generatorApiTypes.js: -------------------------------------------------------------------------------- 1 | const { ifElse } = require('./utils') 2 | const { getResReqTypes } = require('./generatorTypes') 3 | 4 | function generatorHookTypes({ 5 | hasPathParams, 6 | hasQueryParams, 7 | operation, 8 | operationType, 9 | operationName, 10 | isOperationQuery, 11 | }) { 12 | let output = '' 13 | 14 | const methodName = `${operationType.toLowerCase()}${operationName}` 15 | 16 | const isOk = ([statusCode]) => statusCode.toString().startsWith('2') 17 | const responseTypes = getResReqTypes(Object.entries(operation.responses).filter(isOk)) || 'void' 18 | 19 | if (isOperationQuery) { 20 | output += `export const ${methodName}: { (${ifElse( 21 | hasPathParams, 22 | `pathParams?: ${operationName}PathParams, ` 23 | )}${ifElse( 24 | hasQueryParams, 25 | `queryParams?: ${operationName}QueryParams, ` 26 | )}options?: Options): Promise<${responseTypes}> }` 27 | } else { 28 | const requestBodyTypes = getResReqTypes([['body', operation.requestBody]]) 29 | 30 | const requestBodyTypesOptional = `[${ifElse(hasPathParams, `${operationName}PathParams`, 'void')}?, ${ifElse( 31 | hasQueryParams, 32 | `${operationName}QueryParams`, 33 | 'void' 34 | )}?, ${requestBodyTypes}?, Options?]` 35 | 36 | output += `export const ${methodName}: { (${ifElse( 37 | hasPathParams, 38 | `pathParams?: ${operationName}PathParams, ` 39 | )}${ifElse( 40 | hasQueryParams, 41 | `queryParams?: ${operationName}QueryParams, ` 42 | )}options?: Options): { (body?: ${requestBodyTypes} | ${requestBodyTypesOptional}): Promise<${responseTypes}> } }` 43 | } 44 | 45 | return `${output} 46 | ` 47 | } 48 | 49 | module.exports = generatorHookTypes 50 | -------------------------------------------------------------------------------- /src/generatorHook.js: -------------------------------------------------------------------------------- 1 | const { ifElse } = require('./utils') 2 | 3 | function generatorHook({ 4 | verb, 5 | route, 6 | operationName, 7 | operationType, 8 | isOperationQuery, 9 | pathParams, 10 | hasPathParams, 11 | hasQueryParams, 12 | }) { 13 | let output = '' 14 | 15 | const hookName = `use${operationType}${operationName}` 16 | 17 | if (isOperationQuery) { 18 | output += `export const ${hookName} = (${ifElse(hasPathParams, 'pathParams, ')}${ifElse( 19 | hasQueryParams, 20 | 'queryParams, ' 21 | )}config, options) => useQuery({ 22 | queryKey: ${ifElse( 23 | hasPathParams, 24 | 'pathParams && ' + pathParams.map((param) => `pathParams.${param}`).join(' && ') + ' && ' 25 | )}['${route}'${ifElse(hasPathParams, ', pathParams')}${ifElse(hasQueryParams, ', queryParams')}], 26 | queryFn: queryFn(options), 27 | config 28 | }) 29 | ${hookName}.queryKey = '${route}'` 30 | } 31 | // mutation hook 32 | else { 33 | output += `export const ${hookName} = (${ifElse(hasPathParams, 'pathParams, ')}${ifElse( 34 | hasQueryParams, 35 | 'queryParams, ' 36 | )}config, options) => useMutation(mutationFn('${verb}', '${route}', ${ifElse( 37 | hasPathParams, 38 | 'pathParams', 39 | '{}' 40 | )}, ${ifElse(hasQueryParams, 'queryParams', '{}')}, options), config)` 41 | } 42 | 43 | return `${output} 44 | ` 45 | } 46 | 47 | module.exports = generatorHook 48 | -------------------------------------------------------------------------------- /src/generatorHookTypes.js: -------------------------------------------------------------------------------- 1 | const { ifElse } = require('./utils') 2 | const { getResReqTypes } = require('./generatorTypes') 3 | 4 | function generatorHookTypes({ 5 | hasPathParams, 6 | hasQueryParams, 7 | operation, 8 | operationType, 9 | operationName, 10 | isOperationQuery, 11 | }) { 12 | let output = '' 13 | 14 | const hookName = `use${operationType}${operationName}` 15 | 16 | const isOk = ([statusCode]) => statusCode.toString().startsWith('2') 17 | const responseTypes = getResReqTypes(Object.entries(operation.responses).filter(isOk)) || 'void' 18 | 19 | if (isOperationQuery) { 20 | output += `export const ${hookName}: { (${ifElse( 21 | hasPathParams, 22 | `pathParams?: ${operationName}PathParams, ` 23 | )}${ifElse( 24 | hasQueryParams, 25 | `queryParams?: ${operationName}QueryParams, ` 26 | )}config?: QueryConfig<${responseTypes}>, options?: Options): QueryResult<${responseTypes}>; queryKey: string }` 27 | } else { 28 | const requestBodyTypes = getResReqTypes([['body', operation.requestBody]]) 29 | 30 | const requestBodyTypesOptional = `[${ifElse(hasPathParams, `${operationName}PathParams`, 'void')}?, ${ifElse( 31 | hasQueryParams, 32 | `${operationName}QueryParams`, 33 | 'void' 34 | )}?, ${requestBodyTypes}?, Options?]` 35 | 36 | output += `export const ${hookName}: { (${ifElse( 37 | hasPathParams, 38 | `pathParams?: ${operationName}PathParams, ` 39 | )}${ifElse( 40 | hasQueryParams, 41 | `queryParams?: ${operationName}QueryParams, ` 42 | )}config?: MutationConfig<${responseTypes}, unknown, ${requestBodyTypes}>, options?: Options): [MutateFunction<${responseTypes}, unknown, ${requestBodyTypes} | ${requestBodyTypesOptional}>, MutationResult<${responseTypes}>] }` 43 | } 44 | 45 | return `${output} 46 | ` 47 | } 48 | 49 | module.exports = generatorHookTypes 50 | -------------------------------------------------------------------------------- /src/generatorTypes.js: -------------------------------------------------------------------------------- 1 | const { pascalCase, ifElse, fixTypeWhenHaveHyphen } = require('./utils') 2 | 3 | const isReference = (property) => Boolean(property.$ref) 4 | 5 | const getRef = ($ref) => { 6 | if ($ref.startsWith('#/components/schemas')) { 7 | return pascalCase($ref.replace('#/components/schemas/', '')) 8 | } else if ($ref.startsWith('#/components/responses')) { 9 | return pascalCase($ref.replace('#/components/responses/', '')) + 'Response' 10 | } else if ($ref.startsWith('#/components/parameters')) { 11 | return pascalCase($ref.replace('#/components/parameters/', '')) + 'Parameter' 12 | } else if ($ref.startsWith('#/components/requestBodies')) { 13 | return pascalCase($ref.replace('#/components/requestBodies/', '')) + 'RequestBody' 14 | } else { 15 | throw new Error('This library only resolve $ref that are include into `#/components/*` for now') 16 | } 17 | } 18 | 19 | const resolveTypeValue = (schema) => (isReference(schema) ? getRef(schema.$ref) : getScalar(schema)) 20 | 21 | const getArray = (item) => { 22 | if (item.items) { 23 | if (!isReference(item.items) && (item.items.oneOf || item.items.allOf)) { 24 | return `(${resolveTypeValue(item.items)})[]` 25 | } else { 26 | return `${resolveTypeValue(item.items)}[]` 27 | } 28 | } else { 29 | throw new Error('All arrays must have an `items` key define') 30 | } 31 | } 32 | 33 | const getObject = (item) => { 34 | if (isReference(item)) { 35 | return getRef(item.$ref) 36 | } 37 | 38 | if (item.allOf) { 39 | return item.allOf.map(resolveTypeValue).join(' & ') 40 | } 41 | 42 | if (item.oneOf) { 43 | return item.oneOf.map(resolveTypeValue).join(' | ') 44 | } 45 | 46 | if (item.properties) { 47 | return ( 48 | '{ ' + 49 | Object.entries(item.properties) 50 | .filter(([_, prop]) => !prop.readOnly) 51 | .map(([key, prop]) => `${key}${(item.required || []).includes(key) ? '' : '?'}: ${resolveTypeValue(prop)}`) 52 | .join('; ') + 53 | ' }' 54 | ) 55 | } 56 | 57 | return item.type === 'object' ? '{}' : 'any' 58 | } 59 | 60 | const getScalar = (item) => { 61 | const nullable = item.nullable ? ' | null' : '' 62 | 63 | switch (item.type) { 64 | case 'int32': 65 | case 'int64': 66 | case 'number': 67 | case 'integer': 68 | case 'long': 69 | case 'float': 70 | case 'double': 71 | return 'number' + nullable 72 | 73 | case 'boolean': 74 | return 'boolean' + nullable 75 | 76 | case 'array': 77 | return getArray(item) + nullable 78 | 79 | case 'string': 80 | case 'byte': 81 | case 'binary': 82 | case 'date': 83 | case 'dateTime': 84 | case 'date-time': 85 | case 'password': 86 | return (item.enum ? `"${item.enum.join(`" | "`)}"` : 'string') + nullable 87 | 88 | case 'object': 89 | default: 90 | return getObject(item) + nullable 91 | } 92 | } 93 | 94 | const generateSchemasDefinition = (schemas = {}) => { 95 | if (Object.keys(schemas).length === 0) { 96 | return '' 97 | } 98 | 99 | return ( 100 | Object.entries(schemas) 101 | .map(([name, schema]) => 102 | (!schema.type || schema.type === 'object') && 103 | !schema.allOf && 104 | !schema.oneOf && 105 | !isReference(schema) && 106 | !schema.nullable 107 | ? `export type ${pascalCase(name)} = ${getScalar(schema)}` 108 | : `export type ${pascalCase(name)} = ${resolveTypeValue(schema)}` 109 | ) 110 | .join('\n\n') + '\n' 111 | ) 112 | } 113 | 114 | const getResReqTypes = (responsesOrRequests) => 115 | responsesOrRequests 116 | .map(([_, res]) => { 117 | if (!res) { 118 | return 'void' 119 | } 120 | 121 | if (isReference(res)) { 122 | return getRef(res.$ref) 123 | } else { 124 | if (res.content && res.content['application/json']) { 125 | const schema = res.content['application/json'].schema 126 | return resolveTypeValue(schema) 127 | } else if (res.content && res.content['application/octet-stream']) { 128 | const schema = res.content['application/octet-stream'].schema 129 | return resolveTypeValue(schema) 130 | } else { 131 | return 'void' 132 | } 133 | } 134 | }) 135 | .join(' | ') 136 | 137 | const generateResponsesDefinition = (responses = {}) => { 138 | if (Object.keys(responses).length === 0) { 139 | return '' 140 | } 141 | 142 | return ( 143 | '\n' + 144 | Object.entries(responses) 145 | .map(([name, response]) => { 146 | const type = getResReqTypes([['', response]]) 147 | 148 | if (type.includes('{') && !type.includes('|') && !type.includes('&')) { 149 | return `export interface ${pascalCase(name)}Response ${type}` 150 | } else { 151 | return `export type ${pascalCase(name)}Response = ${type}` 152 | } 153 | }) 154 | .join('\n\n') + 155 | '\n' 156 | ) 157 | } 158 | 159 | function generatorGlobalTypes(schema) { 160 | let output = '' 161 | 162 | output += generateSchemasDefinition(schema.components && schema.components.schemas) 163 | output += generateResponsesDefinition(schema.components && schema.components.responses) 164 | 165 | return `${output} 166 | ` 167 | } 168 | 169 | function generatorTypes({ pathParamsBase, queryParamsBase, hasPathParams, hasQueryParams, operationName }) { 170 | let output = '' 171 | 172 | output += ifElse( 173 | hasPathParams, 174 | `export type ${operationName}PathParams = { ${pathParamsBase 175 | .map((p) => `${p.name}${p.required ? '' : '?'}: ${resolveTypeValue(p.schema)}`) 176 | .join('; ')} } 177 | ` 178 | ) 179 | 180 | output += ifElse( 181 | hasQueryParams, 182 | `export type ${operationName}QueryParams = { ${queryParamsBase 183 | .map((p) => `${fixTypeWhenHaveHyphen(p.name)}${p.required ? '' : '?'}: ${resolveTypeValue(p.schema)}`) 184 | .join('; ')} } 185 | ` 186 | ) 187 | 188 | return output 189 | } 190 | 191 | module.exports = { 192 | generatorTypes, 193 | getResReqTypes, 194 | resolveTypeValue, 195 | generatorGlobalTypes, 196 | } 197 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict' 4 | 5 | const { join } = require('path') 6 | const { writeFileSync, mkdirSync, existsSync } = require('fs') 7 | const meow = require('meow') 8 | const chalk = require('chalk') 9 | const ky = require('ky-universal') 10 | 11 | const generator = require('./generator') 12 | 13 | const log = console.log 14 | 15 | const cli = meow( 16 | ` 17 | Usage 18 | $ swagger-to-react-query 19 | 20 | Options 21 | --hooks, -hk Include hooks 22 | 23 | Examples 24 | $ swagger-to-react-query config.js --hooks 25 | `, 26 | { 27 | flags: { 28 | hooks: { 29 | type: 'boolean', 30 | alias: 'hk', 31 | }, 32 | }, 33 | } 34 | ) 35 | 36 | const [configFile] = cli.input 37 | 38 | if (!configFile) { 39 | throw new Error('Config file is required') 40 | } 41 | 42 | const configs = require(join(process.cwd(), configFile)) 43 | 44 | async function importSpecs({ url, headers = {}, json }) { 45 | if (url) { 46 | log(chalk.green(`Start import specs from "${url}"`)) 47 | 48 | try { 49 | const req = await ky(url, { headers, timeout: false }) 50 | const data = await req.json() 51 | 52 | return data 53 | } catch (err) { 54 | throw new Error(`Fail to import specs from "${url}"`) 55 | } 56 | } 57 | 58 | if (json) { 59 | return json 60 | } 61 | 62 | throw new Error(`Fail to import specs from "${url || json}"`) 63 | } 64 | 65 | Promise.all( 66 | configs.apis.map(async (config) => { 67 | log(chalk.green(`Start ${config.name}`)) 68 | 69 | if (!config.input || (!config.input.url && !config.input.json)) { 70 | throw new Error(`"input.url" or "input.json" is required`) 71 | } 72 | 73 | if (!config.output) { 74 | throw new Error(`"output" is required`) 75 | } 76 | 77 | if (!config.output.path) { 78 | throw new Error(`"output.path" is required`) 79 | } 80 | 81 | if (!config.output.file) { 82 | throw new Error(`"output.file" is required`) 83 | } 84 | 85 | const specs = await importSpecs(config.input) 86 | 87 | const { code, types } = await generator({ specs, config }) 88 | 89 | const path = join(process.cwd(), config.output.path) 90 | 91 | if (!existsSync(path)) { 92 | mkdirSync(path) 93 | } 94 | 95 | writeFileSync(join(path, `${config.output.file}.js`), code) 96 | writeFileSync(join(path, `${config.output.file}.d.ts`), types) 97 | }) 98 | ) 99 | .then(() => { 100 | log(chalk.green('Finish!')) 101 | }) 102 | .catch((err) => { 103 | log(chalk.red(err.message)) 104 | process.exit(1) 105 | }) 106 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | function camelCase(str) { 2 | return str 3 | .toString() // Cast to string 4 | .toLowerCase() // Convert the string to lowercase letters 5 | .normalize('NFD') // The normalize() method returns the Unicode Normalization Form of a given string. 6 | .trim() // Remove whitespace from both sides of a string 7 | .replace(/\s+/g, '-') // Replace spaces with - 8 | .replace(/[^\w\-]+/g, '') // Remove all non-word chars 9 | .replace(/\-\-+/g, '-') // Replace multiple - with single - 10 | .replace(/-([a-z])/g, (g) => g[1].toUpperCase()) // convert to camel case 11 | } 12 | 13 | function pascalCase(str) { 14 | return str 15 | .split(/(?=[A-Z])/) 16 | .join('_') 17 | .match(/[a-z,0-9]+/gi) 18 | .map((s) => s.charAt(0).toUpperCase() + s.substr(1).toLowerCase()) 19 | .join('') 20 | } 21 | 22 | function ifElse(condition, whenTrue = '', whenFalse = '') { 23 | return condition ? whenTrue : whenFalse 24 | } 25 | 26 | const hasHyphen = (str) => { 27 | return str.indexOf('-') > -1 28 | } 29 | 30 | const fixTypeWhenHaveHyphen = (name) => { 31 | if (hasHyphen(name)) { 32 | return `"${name}"` 33 | } 34 | 35 | return name 36 | } 37 | 38 | const hyphenToCamelCase = (str) => { 39 | return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase()) 40 | } 41 | 42 | module.exports = { 43 | ifElse, 44 | camelCase, 45 | pascalCase, 46 | hasHyphen, 47 | fixTypeWhenHaveHyphen, 48 | hyphenToCamelCase, 49 | } 50 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.8.3" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" 8 | integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== 9 | dependencies: 10 | "@babel/highlight" "^7.8.3" 11 | 12 | "@babel/helper-validator-identifier@^7.9.0": 13 | version "7.9.0" 14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" 15 | integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== 16 | 17 | "@babel/highlight@^7.8.3": 18 | version "7.9.0" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" 20 | integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.9.0" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@exodus/schemasafe@^1.0.0-rc.2": 27 | version "1.0.0-rc.2" 28 | resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.0.0-rc.2.tgz#3a0214ce90709f4d4c19d526890ed2e42b286a66" 29 | integrity sha512-W98NvvOe/Med3o66xTO03pd7a2omZebH79PV64gSE+ceDdU8uxQhFTa7ISiD1kseyqyOrMyW5/MNdsGEU02i3Q== 30 | 31 | "@types/color-name@^1.1.1": 32 | version "1.1.1" 33 | resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" 34 | integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== 35 | 36 | "@types/minimist@^1.2.0": 37 | version "1.2.0" 38 | resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" 39 | integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= 40 | 41 | "@types/normalize-package-data@^2.4.0": 42 | version "2.4.0" 43 | resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" 44 | integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== 45 | 46 | abort-controller@^3.0.0: 47 | version "3.0.0" 48 | resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" 49 | integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== 50 | dependencies: 51 | event-target-shim "^5.0.0" 52 | 53 | ansi-regex@^5.0.0: 54 | version "5.0.0" 55 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 56 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 57 | 58 | ansi-styles@^3.2.1: 59 | version "3.2.1" 60 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 61 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 62 | dependencies: 63 | color-convert "^1.9.0" 64 | 65 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 66 | version "4.2.1" 67 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" 68 | integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== 69 | dependencies: 70 | "@types/color-name" "^1.1.1" 71 | color-convert "^2.0.1" 72 | 73 | arrify@^1.0.1: 74 | version "1.0.1" 75 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 76 | integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= 77 | 78 | call-me-maybe@^1.0.1: 79 | version "1.0.1" 80 | resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" 81 | integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= 82 | 83 | camelcase-keys@^6.2.2: 84 | version "6.2.2" 85 | resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" 86 | integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== 87 | dependencies: 88 | camelcase "^5.3.1" 89 | map-obj "^4.0.0" 90 | quick-lru "^4.0.1" 91 | 92 | camelcase@^5.0.0, camelcase@^5.3.1: 93 | version "5.3.1" 94 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 95 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 96 | 97 | chalk@^2.0.0: 98 | version "2.4.2" 99 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 100 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 101 | dependencies: 102 | ansi-styles "^3.2.1" 103 | escape-string-regexp "^1.0.5" 104 | supports-color "^5.3.0" 105 | 106 | chalk@^4.1.0: 107 | version "4.1.0" 108 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" 109 | integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== 110 | dependencies: 111 | ansi-styles "^4.1.0" 112 | supports-color "^7.1.0" 113 | 114 | cliui@^6.0.0: 115 | version "6.0.0" 116 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" 117 | integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== 118 | dependencies: 119 | string-width "^4.2.0" 120 | strip-ansi "^6.0.0" 121 | wrap-ansi "^6.2.0" 122 | 123 | color-convert@^1.9.0: 124 | version "1.9.3" 125 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 126 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 127 | dependencies: 128 | color-name "1.1.3" 129 | 130 | color-convert@^2.0.1: 131 | version "2.0.1" 132 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 133 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 134 | dependencies: 135 | color-name "~1.1.4" 136 | 137 | color-name@1.1.3: 138 | version "1.1.3" 139 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 140 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 141 | 142 | color-name@~1.1.4: 143 | version "1.1.4" 144 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 145 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 146 | 147 | data-uri-to-buffer@^3.0.1: 148 | version "3.0.1" 149 | resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" 150 | integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== 151 | 152 | decamelize-keys@^1.1.0: 153 | version "1.1.0" 154 | resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" 155 | integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= 156 | dependencies: 157 | decamelize "^1.1.0" 158 | map-obj "^1.0.0" 159 | 160 | decamelize@^1.1.0, decamelize@^1.2.0: 161 | version "1.2.0" 162 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 163 | integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= 164 | 165 | emoji-regex@^8.0.0: 166 | version "8.0.0" 167 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 168 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 169 | 170 | error-ex@^1.3.1: 171 | version "1.3.2" 172 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 173 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 174 | dependencies: 175 | is-arrayish "^0.2.1" 176 | 177 | es6-promise@^3.2.1: 178 | version "3.3.1" 179 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" 180 | integrity sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM= 181 | 182 | escape-string-regexp@^1.0.5: 183 | version "1.0.5" 184 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 185 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 186 | 187 | event-target-shim@^5.0.0: 188 | version "5.0.1" 189 | resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" 190 | integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== 191 | 192 | fast-safe-stringify@^2.0.7: 193 | version "2.0.7" 194 | resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" 195 | integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== 196 | 197 | fetch-blob@^2.1.1: 198 | version "2.1.1" 199 | resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-2.1.1.tgz#a54ab0d5ed7ccdb0691db77b6674308b23fb2237" 200 | integrity sha512-Uf+gxPCe1hTOFXwkxYyckn8iUSk6CFXGy5VENZKifovUTZC9eUODWSBhOBS7zICGrAetKzdwLMr85KhIcePMAQ== 201 | 202 | find-up@^4.1.0: 203 | version "4.1.0" 204 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 205 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 206 | dependencies: 207 | locate-path "^5.0.0" 208 | path-exists "^4.0.0" 209 | 210 | get-caller-file@^2.0.1: 211 | version "2.0.5" 212 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 213 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 214 | 215 | hard-rejection@^2.1.0: 216 | version "2.1.0" 217 | resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" 218 | integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== 219 | 220 | has-flag@^3.0.0: 221 | version "3.0.0" 222 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 223 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 224 | 225 | has-flag@^4.0.0: 226 | version "4.0.0" 227 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 228 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 229 | 230 | hosted-git-info@^2.1.4: 231 | version "2.8.8" 232 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" 233 | integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== 234 | 235 | http2-client@^1.2.5: 236 | version "1.3.3" 237 | resolved "https://registry.yarnpkg.com/http2-client/-/http2-client-1.3.3.tgz#90fc15d646cca86956b156d07c83947d57d659a9" 238 | integrity sha512-nUxLymWQ9pzkzTmir24p2RtsgruLmhje7lH3hLX1IpwvyTg77fW+1brenPPP3USAR+rQ36p5sTA/x7sjCJVkAA== 239 | 240 | indent-string@^4.0.0: 241 | version "4.0.0" 242 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" 243 | integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== 244 | 245 | is-arrayish@^0.2.1: 246 | version "0.2.1" 247 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 248 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 249 | 250 | is-fullwidth-code-point@^3.0.0: 251 | version "3.0.0" 252 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 253 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 254 | 255 | is-plain-obj@^1.1.0: 256 | version "1.1.0" 257 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" 258 | integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= 259 | 260 | js-tokens@^4.0.0: 261 | version "4.0.0" 262 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 263 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 264 | 265 | json-parse-better-errors@^1.0.1: 266 | version "1.0.2" 267 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 268 | integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 269 | 270 | kind-of@^6.0.3: 271 | version "6.0.3" 272 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" 273 | integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== 274 | 275 | ky-universal@^0.8.2: 276 | version "0.8.2" 277 | resolved "https://registry.yarnpkg.com/ky-universal/-/ky-universal-0.8.2.tgz#edc398d54cf495d7d6830aa1ab69559a3cc7f824" 278 | integrity sha512-xe0JaOH9QeYxdyGLnzUOVGK4Z6FGvDVzcXFTdrYA1f33MZdEa45sUDaMBy98xQMcsd2XIBrTXRrRYnegcSdgVQ== 279 | dependencies: 280 | abort-controller "^3.0.0" 281 | node-fetch "3.0.0-beta.9" 282 | 283 | ky@^0.23.0: 284 | version "0.23.0" 285 | resolved "https://registry.yarnpkg.com/ky/-/ky-0.23.0.tgz#54c2f3fa9003d591cb2f368384e6c84795a92e64" 286 | integrity sha512-+t2CbQsLmpN3HeYPBxN+VbZqBOd86njF3cvnueC77pJKVHRjiMI0Ac+pfkB8e17Bw1dGHbMk9hrHst9Bw7ndgw== 287 | 288 | lines-and-columns@^1.1.6: 289 | version "1.1.6" 290 | resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" 291 | integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= 292 | 293 | locate-path@^5.0.0: 294 | version "5.0.0" 295 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 296 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 297 | dependencies: 298 | p-locate "^4.1.0" 299 | 300 | map-obj@^1.0.0: 301 | version "1.0.1" 302 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" 303 | integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= 304 | 305 | map-obj@^4.0.0: 306 | version "4.1.0" 307 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" 308 | integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g== 309 | 310 | meow@^7.1.1: 311 | version "7.1.1" 312 | resolved "https://registry.yarnpkg.com/meow/-/meow-7.1.1.tgz#7c01595e3d337fcb0ec4e8eed1666ea95903d306" 313 | integrity sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA== 314 | dependencies: 315 | "@types/minimist" "^1.2.0" 316 | camelcase-keys "^6.2.2" 317 | decamelize-keys "^1.1.0" 318 | hard-rejection "^2.1.0" 319 | minimist-options "4.1.0" 320 | normalize-package-data "^2.5.0" 321 | read-pkg-up "^7.0.1" 322 | redent "^3.0.0" 323 | trim-newlines "^3.0.0" 324 | type-fest "^0.13.1" 325 | yargs-parser "^18.1.3" 326 | 327 | min-indent@^1.0.0: 328 | version "1.0.0" 329 | resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" 330 | integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= 331 | 332 | minimist-options@4.1.0: 333 | version "4.1.0" 334 | resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" 335 | integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== 336 | dependencies: 337 | arrify "^1.0.1" 338 | is-plain-obj "^1.1.0" 339 | kind-of "^6.0.3" 340 | 341 | node-fetch-h2@^2.3.0: 342 | version "2.3.0" 343 | resolved "https://registry.yarnpkg.com/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz#c6188325f9bd3d834020bf0f2d6dc17ced2241ac" 344 | integrity sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg== 345 | dependencies: 346 | http2-client "^1.2.5" 347 | 348 | node-fetch@3.0.0-beta.9: 349 | version "3.0.0-beta.9" 350 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.0.0-beta.9.tgz#0a7554cfb824380dd6812864389923c783c80d9b" 351 | integrity sha512-RdbZCEynH2tH46+tj0ua9caUHVWrd/RHnRfvly2EVdqGmI3ndS1Vn/xjm5KuGejDt2RNDQsVRLPNd2QPwcewVg== 352 | dependencies: 353 | data-uri-to-buffer "^3.0.1" 354 | fetch-blob "^2.1.1" 355 | 356 | node-readfiles@^0.2.0: 357 | version "0.2.0" 358 | resolved "https://registry.yarnpkg.com/node-readfiles/-/node-readfiles-0.2.0.tgz#dbbd4af12134e2e635c245ef93ffcf6f60673a5d" 359 | integrity sha1-271K8SE04uY1wkXvk//Pb2BnOl0= 360 | dependencies: 361 | es6-promise "^3.2.1" 362 | 363 | normalize-package-data@^2.5.0: 364 | version "2.5.0" 365 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 366 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 367 | dependencies: 368 | hosted-git-info "^2.1.4" 369 | resolve "^1.10.0" 370 | semver "2 || 3 || 4 || 5" 371 | validate-npm-package-license "^3.0.1" 372 | 373 | oas-kit-common@^1.0.8: 374 | version "1.0.8" 375 | resolved "https://registry.yarnpkg.com/oas-kit-common/-/oas-kit-common-1.0.8.tgz#6d8cacf6e9097967a4c7ea8bcbcbd77018e1f535" 376 | integrity sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ== 377 | dependencies: 378 | fast-safe-stringify "^2.0.7" 379 | 380 | oas-linter@^3.2.0: 381 | version "3.2.0" 382 | resolved "https://registry.yarnpkg.com/oas-linter/-/oas-linter-3.2.0.tgz#82d2e586da00adc24c44e44de4b31a6f6ba5cc7e" 383 | integrity sha512-LP5F1dhjULEJV5oGRg6ROztH2FddzttrrUEwq5J2GB2Zy938mg0vwt1+Rthn/qqDHtj4Qgq21duNGHh+Ew1wUg== 384 | dependencies: 385 | "@exodus/schemasafe" "^1.0.0-rc.2" 386 | should "^13.2.1" 387 | yaml "^1.10.0" 388 | 389 | oas-resolver@^2.5.1: 390 | version "2.5.1" 391 | resolved "https://registry.yarnpkg.com/oas-resolver/-/oas-resolver-2.5.1.tgz#d129b4f62bd21021184d765747b72d559e864c62" 392 | integrity sha512-MdMY8YAnCdFTAt5+CTC/aYEOSIFt+ICOWxQvKKxsIHjc0/0tG6V4DzbkHW9SWWqUmDPiHDxJsi79kjsE/1PJ5g== 393 | dependencies: 394 | node-fetch-h2 "^2.3.0" 395 | oas-kit-common "^1.0.8" 396 | reftools "^1.1.6" 397 | yaml "^1.10.0" 398 | yargs "^15.3.1" 399 | 400 | oas-schema-walker@^1.1.5: 401 | version "1.1.5" 402 | resolved "https://registry.yarnpkg.com/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz#74c3cd47b70ff8e0b19adada14455b5d3ac38a22" 403 | integrity sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ== 404 | 405 | oas-validator@^5.0.2: 406 | version "5.0.2" 407 | resolved "https://registry.yarnpkg.com/oas-validator/-/oas-validator-5.0.2.tgz#6c7d405fa0b1b144414c6319140e987d6d7dc683" 408 | integrity sha512-KVyNNWtZut1sZVBy4mBt1Iq6vQt0km+vJvaPanx4xV33ylpWpuQnMsb9UNQ6MuZVmOzBLl9SbNyvlNjzicty9Q== 409 | dependencies: 410 | call-me-maybe "^1.0.1" 411 | oas-kit-common "^1.0.8" 412 | oas-linter "^3.2.0" 413 | oas-resolver "^2.5.1" 414 | oas-schema-walker "^1.1.5" 415 | reftools "^1.1.6" 416 | should "^13.2.1" 417 | yaml "^1.10.0" 418 | 419 | p-limit@^2.2.0: 420 | version "2.2.2" 421 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" 422 | integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== 423 | dependencies: 424 | p-try "^2.0.0" 425 | 426 | p-locate@^4.1.0: 427 | version "4.1.0" 428 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 429 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 430 | dependencies: 431 | p-limit "^2.2.0" 432 | 433 | p-try@^2.0.0: 434 | version "2.2.0" 435 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 436 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 437 | 438 | parse-json@^5.0.0: 439 | version "5.0.0" 440 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" 441 | integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== 442 | dependencies: 443 | "@babel/code-frame" "^7.0.0" 444 | error-ex "^1.3.1" 445 | json-parse-better-errors "^1.0.1" 446 | lines-and-columns "^1.1.6" 447 | 448 | path-exists@^4.0.0: 449 | version "4.0.0" 450 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 451 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 452 | 453 | path-parse@^1.0.6: 454 | version "1.0.6" 455 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 456 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 457 | 458 | quick-lru@^4.0.1: 459 | version "4.0.1" 460 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" 461 | integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== 462 | 463 | read-pkg-up@^7.0.1: 464 | version "7.0.1" 465 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" 466 | integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== 467 | dependencies: 468 | find-up "^4.1.0" 469 | read-pkg "^5.2.0" 470 | type-fest "^0.8.1" 471 | 472 | read-pkg@^5.2.0: 473 | version "5.2.0" 474 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" 475 | integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== 476 | dependencies: 477 | "@types/normalize-package-data" "^2.4.0" 478 | normalize-package-data "^2.5.0" 479 | parse-json "^5.0.0" 480 | type-fest "^0.6.0" 481 | 482 | redent@^3.0.0: 483 | version "3.0.0" 484 | resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" 485 | integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== 486 | dependencies: 487 | indent-string "^4.0.0" 488 | strip-indent "^3.0.0" 489 | 490 | reftools@^1.1.6: 491 | version "1.1.6" 492 | resolved "https://registry.yarnpkg.com/reftools/-/reftools-1.1.6.tgz#841b1ac241259632d63167bf708eccfbfbbba5b5" 493 | integrity sha512-rQfJ025lvPjw9qyQuNPqE+cRs5qVs7BMrZwgRJnmuMcX/8r/eJE8f5/RCunJWViXKHmN5K2DFafYzglLOHE/tw== 494 | 495 | require-directory@^2.1.1: 496 | version "2.1.1" 497 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 498 | integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= 499 | 500 | require-main-filename@^2.0.0: 501 | version "2.0.0" 502 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" 503 | integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== 504 | 505 | resolve@^1.10.0: 506 | version "1.15.1" 507 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" 508 | integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== 509 | dependencies: 510 | path-parse "^1.0.6" 511 | 512 | "semver@2 || 3 || 4 || 5": 513 | version "5.7.1" 514 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 515 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 516 | 517 | set-blocking@^2.0.0: 518 | version "2.0.0" 519 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 520 | integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= 521 | 522 | should-equal@^2.0.0: 523 | version "2.0.0" 524 | resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" 525 | integrity sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA== 526 | dependencies: 527 | should-type "^1.4.0" 528 | 529 | should-format@^3.0.3: 530 | version "3.0.3" 531 | resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" 532 | integrity sha1-m/yPdPo5IFxT04w01xcwPidxJPE= 533 | dependencies: 534 | should-type "^1.3.0" 535 | should-type-adaptors "^1.0.1" 536 | 537 | should-type-adaptors@^1.0.1: 538 | version "1.1.0" 539 | resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" 540 | integrity sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA== 541 | dependencies: 542 | should-type "^1.3.0" 543 | should-util "^1.0.0" 544 | 545 | should-type@^1.3.0, should-type@^1.4.0: 546 | version "1.4.0" 547 | resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" 548 | integrity sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM= 549 | 550 | should-util@^1.0.0: 551 | version "1.0.1" 552 | resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.1.tgz#fb0d71338f532a3a149213639e2d32cbea8bcb28" 553 | integrity sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g== 554 | 555 | should@^13.2.1: 556 | version "13.2.3" 557 | resolved "https://registry.yarnpkg.com/should/-/should-13.2.3.tgz#96d8e5acf3e97b49d89b51feaa5ae8d07ef58f10" 558 | integrity sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ== 559 | dependencies: 560 | should-equal "^2.0.0" 561 | should-format "^3.0.3" 562 | should-type "^1.4.0" 563 | should-type-adaptors "^1.0.1" 564 | should-util "^1.0.0" 565 | 566 | spdx-correct@^3.0.0: 567 | version "3.1.0" 568 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" 569 | integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== 570 | dependencies: 571 | spdx-expression-parse "^3.0.0" 572 | spdx-license-ids "^3.0.0" 573 | 574 | spdx-exceptions@^2.1.0: 575 | version "2.2.0" 576 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" 577 | integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== 578 | 579 | spdx-expression-parse@^3.0.0: 580 | version "3.0.0" 581 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 582 | integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== 583 | dependencies: 584 | spdx-exceptions "^2.1.0" 585 | spdx-license-ids "^3.0.0" 586 | 587 | spdx-license-ids@^3.0.0: 588 | version "3.0.5" 589 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" 590 | integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== 591 | 592 | string-width@^4.1.0, string-width@^4.2.0: 593 | version "4.2.0" 594 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" 595 | integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== 596 | dependencies: 597 | emoji-regex "^8.0.0" 598 | is-fullwidth-code-point "^3.0.0" 599 | strip-ansi "^6.0.0" 600 | 601 | strip-ansi@^6.0.0: 602 | version "6.0.0" 603 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" 604 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== 605 | dependencies: 606 | ansi-regex "^5.0.0" 607 | 608 | strip-indent@^3.0.0: 609 | version "3.0.0" 610 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" 611 | integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== 612 | dependencies: 613 | min-indent "^1.0.0" 614 | 615 | supports-color@^5.3.0: 616 | version "5.5.0" 617 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 618 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 619 | dependencies: 620 | has-flag "^3.0.0" 621 | 622 | supports-color@^7.1.0: 623 | version "7.1.0" 624 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" 625 | integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== 626 | dependencies: 627 | has-flag "^4.0.0" 628 | 629 | swagger2openapi@^7.0.2: 630 | version "7.0.2" 631 | resolved "https://registry.yarnpkg.com/swagger2openapi/-/swagger2openapi-7.0.2.tgz#598079039f025dd4a92f7128368e8b0ab65fad6a" 632 | integrity sha512-EG9h+hq+mX4S6mh0IHf/K4Bd8cLFVvRFxt6YiuoQCKycbCoa8Cjr8hbzy1oDNpGYwjT29js/PrHffgJDuDlgQw== 633 | dependencies: 634 | call-me-maybe "^1.0.1" 635 | node-fetch-h2 "^2.3.0" 636 | node-readfiles "^0.2.0" 637 | oas-kit-common "^1.0.8" 638 | oas-resolver "^2.5.1" 639 | oas-schema-walker "^1.1.5" 640 | oas-validator "^5.0.2" 641 | reftools "^1.1.6" 642 | yaml "^1.10.0" 643 | yargs "^15.3.1" 644 | 645 | trim-newlines@^3.0.0: 646 | version "3.0.0" 647 | resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" 648 | integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== 649 | 650 | type-fest@^0.13.1: 651 | version "0.13.1" 652 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" 653 | integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== 654 | 655 | type-fest@^0.6.0: 656 | version "0.6.0" 657 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" 658 | integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== 659 | 660 | type-fest@^0.8.1: 661 | version "0.8.1" 662 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" 663 | integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== 664 | 665 | validate-npm-package-license@^3.0.1: 666 | version "3.0.4" 667 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 668 | integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 669 | dependencies: 670 | spdx-correct "^3.0.0" 671 | spdx-expression-parse "^3.0.0" 672 | 673 | which-module@^2.0.0: 674 | version "2.0.0" 675 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 676 | integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= 677 | 678 | wrap-ansi@^6.2.0: 679 | version "6.2.0" 680 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" 681 | integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== 682 | dependencies: 683 | ansi-styles "^4.0.0" 684 | string-width "^4.1.0" 685 | strip-ansi "^6.0.0" 686 | 687 | y18n@^4.0.0: 688 | version "4.0.0" 689 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" 690 | integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== 691 | 692 | yaml@^1.10.0: 693 | version "1.10.0" 694 | resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" 695 | integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== 696 | 697 | yargs-parser@^18.1.2, yargs-parser@^18.1.3: 698 | version "18.1.3" 699 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" 700 | integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== 701 | dependencies: 702 | camelcase "^5.0.0" 703 | decamelize "^1.2.0" 704 | 705 | yargs@^15.3.1: 706 | version "15.4.1" 707 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" 708 | integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== 709 | dependencies: 710 | cliui "^6.0.0" 711 | decamelize "^1.2.0" 712 | find-up "^4.1.0" 713 | get-caller-file "^2.0.1" 714 | require-directory "^2.1.1" 715 | require-main-filename "^2.0.0" 716 | set-blocking "^2.0.0" 717 | string-width "^4.2.0" 718 | which-module "^2.0.0" 719 | y18n "^4.0.0" 720 | yargs-parser "^18.1.2" 721 | --------------------------------------------------------------------------------