├── website ├── static │ ├── .nojekyll │ └── img │ │ ├── favicon.ico │ │ ├── docusaurus.png │ │ └── docusaurus-social-card.jpg ├── .prettierignore ├── versions.json ├── .remarkignore ├── linkcheck-ignore.txt ├── .prettierrc.json ├── babel.config.js ├── docs │ ├── codegen │ │ ├── CLI │ │ │ └── _category_.json │ │ └── _category_.json │ ├── hooks │ │ └── _category_.json │ ├── core │ │ └── _category_.json │ ├── eslint │ │ └── _category_.json │ ├── query-client │ │ ├── _category_.json │ │ ├── getQueryState.mdx │ │ ├── getInfiniteQueryState.mdx │ │ ├── resetQueries.mdx │ │ ├── setInfiniteQueryData.mdx │ │ ├── prefetchInfiniteQuery.mdx │ │ ├── prefetchQuery.mdx │ │ └── getInfiniteQueryKey.mdx │ ├── getting-started │ │ └── _category_.json │ └── authorization │ │ └── _category_.json ├── versioned_sidebars │ └── version-1.x-sidebars.json ├── versioned_docs │ └── version-1.x │ │ ├── core │ │ └── _category_.json │ │ ├── hooks │ │ └── _category_.json │ │ ├── codegen │ │ └── _category_.json │ │ ├── query-client │ │ ├── _category_.json │ │ ├── getQueryState.mdx │ │ ├── getQueriesData.mdx │ │ ├── getInfiniteQueryState.mdx │ │ ├── resetQueries.mdx │ │ ├── setInfiniteQueryData.mdx │ │ ├── prefetchInfiniteQuery.mdx │ │ ├── prefetchQuery.mdx │ │ └── getInfiniteQueryData.mdx │ │ ├── getting-started │ │ ├── _category_.json │ │ └── installation.mdx │ │ └── authorization │ │ └── _category_.json ├── src │ ├── components │ │ └── HomepageFeatures │ │ │ └── styles.module.css │ ├── pages │ │ ├── index.module.css │ │ └── index.js │ └── css │ │ └── custom.css ├── .gitignore ├── tools │ └── algolia │ │ └── config.json ├── .editorconfig ├── sidebars.js └── README.md ├── packages ├── plugin │ ├── README.md │ ├── .gitignore │ ├── src │ │ ├── lib │ │ │ ├── OutputOptions.ts │ │ │ ├── GeneratorFile.ts │ │ │ ├── fileHeader.ts │ │ │ ├── formatFileHeader.ts │ │ │ ├── maybeEscapeShellArg.ts │ │ │ ├── open-api │ │ │ │ ├── getContent.ts │ │ │ │ ├── getServiceName.ts │ │ │ │ ├── getServiceNamesByOperationTags.ts │ │ │ │ ├── readSchema.ts │ │ │ │ ├── getServiceNamesByOperationTags.spec.ts │ │ │ │ ├── replaceRefParametersWithComponent.ts │ │ │ │ ├── openapi-typescript-redoc.d.ts │ │ │ │ ├── resolveDocumentLocalRef.ts │ │ │ │ ├── OpenAPISchemaType.ts │ │ │ │ └── getServices.spec.ts │ │ │ ├── QraftCommandPlugin.ts │ │ │ ├── isReadOnlyOperation.ts │ │ │ ├── vitestFsMock.ts │ │ │ ├── parseOperationGlobs.test.ts │ │ │ ├── createServicePathMatch.ts │ │ │ ├── filterDocumentPaths.ts │ │ │ ├── splitCommaSeparatedGlobs.ts │ │ │ ├── filterDocumentPaths.spec.ts │ │ │ └── shouldQuoteCommandLineArg.ts │ │ └── index.ts │ ├── eslint.config.js │ ├── tsconfig.build.json │ └── tsconfig.json ├── rollup-config │ ├── .gitignore │ ├── tsconfig.json │ ├── CHANGELOG.md │ └── package.json ├── tanstack-query-react-types │ ├── .gitignore │ ├── src │ │ ├── shared │ │ │ ├── OperationError.ts │ │ │ ├── WithOptional.ts │ │ │ ├── AreAllOptional.ts │ │ │ ├── DeepReadonly.ts │ │ │ ├── OperationInfiniteData.ts │ │ │ ├── PartialParameters.ts │ │ │ ├── QraftServiceOperationsToken.ts │ │ │ ├── InvalidateQueryFilters.ts │ │ │ ├── ServiceOperationKey.ts │ │ │ ├── UseQueryOptionsForUseSuspenseQuery.ts │ │ │ ├── index.ts │ │ │ ├── UseQueryOptionsForUseQueries.ts │ │ │ └── ServiceOperationQuery.ts │ │ ├── index.ts │ │ └── service-operation │ │ │ ├── ServiceOperationGetQueryData.ts │ │ │ ├── ServiceOperationInvalidateQueries.ts │ │ │ ├── ServiceOperationGetInfiniteQueryData.ts │ │ │ ├── ServiceOperationRemoveQueries.ts │ │ │ ├── ServiceOperationIsFetchingQueries.ts │ │ │ ├── ServiceOperationUseIsFetchingQueries.ts │ │ │ ├── ServiceOperationUseQueries.ts │ │ │ ├── ServiceOperationIsMutatingQueries.ts │ │ │ ├── ServiceOperationUseIsMutating.ts │ │ │ ├── ServiceOperationResetQueries.ts │ │ │ ├── ServiceOperationCancelQueries.ts │ │ │ ├── ServiceOperationSetQueryData.ts │ │ │ ├── ServiceOperationRefetchQueries.ts │ │ │ ├── ServiceOperationMutationFn.ts │ │ │ ├── ServiceOperationUseSuspenseQueries.ts │ │ │ ├── ServiceOperationUseSuspenseQuery.ts │ │ │ ├── ServiceOperationQueryFn.ts │ │ │ ├── ServiceOperationSetQueriesData.ts │ │ │ ├── ServiceOperationSetInfiniteQueryData.ts │ │ │ └── ServiceOperationGetQueryState.ts │ ├── tsconfig.build.json │ ├── eslint.config.js │ ├── turbo.json │ ├── tsconfig.json │ └── rollup.config.mjs ├── test-fixtures │ ├── README.md │ ├── package.json │ ├── redocly.yaml │ └── CHANGELOG.md ├── openapi-typescript-plugin │ ├── .prettierignore │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── createOpenapiTypesImportPath.test.ts │ │ │ ├── createExportsForComponentSchemas.test.ts │ │ │ └── createOpenapiTypesImportPath.ts │ ├── eslint.config.js │ ├── tsconfig.json │ └── tsconfig.build.json ├── tanstack-query-react-plugin │ ├── .prettierignore │ ├── README.md │ ├── src │ │ ├── ts-factory │ │ │ ├── service-operation.generated │ │ │ │ └── .gitignore │ │ │ ├── tsdoc │ │ │ │ └── lib │ │ │ │ │ ├── createOperationMethodBodyParametersExampleNode.ts │ │ │ │ │ └── createOperationMethodCallExpressionExampleNode.ts │ │ │ ├── OverrideImportType.ts │ │ │ ├── astToString.ts │ │ │ └── filterUnusedTypes.spec.ts │ │ ├── index.ts │ │ ├── __snapshots__ │ │ │ ├── no-export-openapi-types │ │ │ │ └── index.ts.snapshot.ts │ │ │ ├── openapi-types-import-path-d-ts │ │ │ │ └── index.ts.snapshot.ts │ │ │ ├── openapi-types-import-path-ts │ │ │ │ └── index.ts.snapshot.ts │ │ │ ├── explicit-import-extensions │ │ │ │ ├── index.ts.snapshot.ts │ │ │ │ └── services │ │ │ │ │ └── index.ts.snapshot.ts │ │ │ └── explicit-import-extensions-d-ts-imports │ │ │ │ └── index.ts.snapshot.ts │ │ └── lib │ │ │ ├── createOperationCommonTSDoc.ts │ │ │ ├── maybeResolveImport.ts │ │ │ └── maybeResolveImport.spec.ts │ ├── tsconfig.json │ ├── turbo.json │ ├── tsconfig.build.json │ └── eslint.config.js ├── ts-factory-code-generator │ ├── .gitignore │ ├── src │ │ ├── index.ts │ │ └── generateSourceFileFactoryCode.ts │ ├── generate-factory-code-generator.mjs │ ├── eslint.config.mjs │ ├── tsconfig.json │ ├── turbo.json │ ├── CHANGELOG.md │ └── package.json ├── eslint-plugin-query │ ├── src │ │ ├── types.ts │ │ ├── utils │ │ │ ├── get-docs-url.ts │ │ │ ├── get-root-identifier.ts │ │ │ └── create-client-name-regex.ts │ │ ├── rules │ │ │ └── no-rest-destructuring │ │ │ │ └── no-rest-destructuring.utils.ts │ │ └── rules.ts │ ├── eslint.config.js │ ├── CHANGELOG.md │ ├── tsconfig.json │ ├── tsconfig.build.json │ ├── rollup.config.mjs │ └── vitest.config.ts ├── react-client │ ├── src │ │ ├── unstable__responseUtils.ts │ │ ├── tests │ │ │ ├── fixtures │ │ │ │ ├── type-overrides │ │ │ │ │ ├── use-infinite-query-result.ts │ │ │ │ │ ├── create-query-client-options.ts │ │ │ │ │ ├── operation-error.ts │ │ │ │ │ ├── suspense-query.ts │ │ │ │ │ └── qraft-predefined-parameters.ts │ │ │ │ ├── .gitignore │ │ │ │ └── migrate-to-v2.6.0-codemod │ │ │ │ │ ├── custom-package.tsx │ │ │ │ │ ├── other-imports.tsx │ │ │ │ │ ├── mixed-imports.tsx │ │ │ │ │ └── generics.tsx │ │ │ ├── msw │ │ │ │ └── node.ts │ │ │ ├── setupTests.ts │ │ │ ├── createTestJwt.test.ts │ │ │ ├── createTestJwt.ts │ │ │ ├── shallowEqualObjects.test.ts │ │ │ └── composeMutationKey.test.ts │ │ ├── lib │ │ │ ├── requestFnResponseResolver.ts │ │ │ ├── composeQueryKey.ts │ │ │ ├── requestFnResponseRejecter.ts │ │ │ ├── composeInfiniteQueryKey.ts │ │ │ ├── shelfMerge.ts │ │ │ ├── composeBaseQueryKey.ts │ │ │ └── callQueryClientMethodWithMutationFilters.ts │ │ ├── callbacks │ │ │ ├── getQueryKey.ts │ │ │ ├── getMutationKey.ts │ │ │ ├── getInfiniteQueryKey.ts │ │ │ ├── getQueryData.ts │ │ │ ├── setQueryData.ts │ │ │ ├── resetQueries.ts │ │ │ ├── cancelQueries.ts │ │ │ ├── isFetching.ts │ │ │ ├── removeQueries.ts │ │ │ ├── getQueriesData.ts │ │ │ ├── refetchQueries.ts │ │ │ ├── setQueriesData.ts │ │ │ ├── invalidateQueries.ts │ │ │ ├── isMutating.ts │ │ │ ├── getQueryState.ts │ │ │ ├── fetchQuery.ts │ │ │ ├── getInfiniteQueryData.ts │ │ │ ├── getInfiniteQueryState.ts │ │ │ ├── setInfiniteQueryData.ts │ │ │ ├── prefetchQuery.ts │ │ │ ├── ensureQueryData.ts │ │ │ ├── fetchInfiniteQuery.ts │ │ │ ├── useIsFetching.ts │ │ │ ├── prefetchInfiniteQuery.ts │ │ │ ├── ensureInfiniteQueryData.ts │ │ │ ├── useQuery.ts │ │ │ ├── getMutationCache.ts │ │ │ ├── useSuspenseQuery.ts │ │ │ ├── useInfiniteQuery.ts │ │ │ ├── useIsMutating.ts │ │ │ ├── useSuspenseInfiniteQuery.ts │ │ │ └── useMutationState.ts │ │ └── index.ts │ ├── turbo.json │ ├── tsconfig.build.json │ ├── rollup.config.mjs │ └── tsconfig.json ├── cli │ ├── tsconfig.json │ ├── eslint.config.js │ ├── src │ │ ├── builtInPlugins.ts │ │ ├── handleDeprecatedOptions.ts │ │ └── bin.spec.ts │ ├── bin.mjs │ └── tsconfig.build.json └── eslint-config │ ├── CHANGELOG.md │ └── package.json ├── playground ├── src │ ├── vite-env.d.ts │ └── main.tsx ├── .env.local.example ├── vite.config.ts ├── tsconfig.node.json ├── index.html ├── .gitignore ├── tsconfig.json └── eslint.config.js ├── e2e ├── projects │ ├── typescript-commonjs-node │ │ ├── .gitignore │ │ ├── tsconfig.json │ │ └── package.json │ ├── typescript-es2015-bundler │ │ ├── .gitignore │ │ ├── tsconfig.json │ │ ├── my-redocly.yaml │ │ └── package.json │ └── typescript-nodenext-nodenext │ │ ├── .gitignore │ │ ├── tsconfig.json │ │ └── package.json ├── CHANGELOG.md ├── .gitignore ├── bin │ ├── build-projects.sh │ ├── lib │ │ └── find-monorepo-root.mjs │ ├── update-projects-from-private-registry.sh │ └── unpublish-from-private-registry.sh └── package.json ├── .github ├── actions │ └── spelling │ │ ├── allow.txt │ │ └── patterns.txt └── workflows │ ├── lint-pr-title.yml │ ├── update-search-engines.yml │ ├── versioning.yml │ ├── ci.yml │ ├── docs-validation.yml │ └── deploy-gh-pages.yml ├── .yarnrc.yml ├── tsconfig.json ├── .gitignore ├── .prettierrc.json ├── .yarn └── patches │ └── ts-morph-npm-17.0.1-6097358fba.patch ├── .changeset ├── config.json ├── version.sh ├── remove-dist-tag.sh └── deprecate-version.sh ├── write-package-version-file.sh ├── package.json ├── LICENSE.txt └── README.md /website/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/plugin/README.md: -------------------------------------------------------------------------------- 1 | # shared 2 | -------------------------------------------------------------------------------- /website/.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.mdx 2 | **/*.md 3 | -------------------------------------------------------------------------------- /website/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "1.x" 3 | ] 4 | -------------------------------------------------------------------------------- /packages/plugin/.gitignore: -------------------------------------------------------------------------------- 1 | /src/packageVersion.ts 2 | -------------------------------------------------------------------------------- /packages/rollup-config/.gitignore: -------------------------------------------------------------------------------- 1 | types 2 | dist 3 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/.gitignore: -------------------------------------------------------------------------------- 1 | /dist -------------------------------------------------------------------------------- /packages/test-fixtures/README.md: -------------------------------------------------------------------------------- 1 | # test-fixtures 2 | -------------------------------------------------------------------------------- /website/.remarkignore: -------------------------------------------------------------------------------- 1 | /versioned_docs/version-1.x 2 | -------------------------------------------------------------------------------- /playground/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/openapi-typescript-plugin/.prettierignore: -------------------------------------------------------------------------------- 1 | /src/__snapshots__/** 2 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/.prettierignore: -------------------------------------------------------------------------------- 1 | /src/__snapshots__/** 2 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/README.md: -------------------------------------------------------------------------------- 1 | # tanstack-react-plugin 2 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/.gitignore: -------------------------------------------------------------------------------- 1 | /src/generateFactoryCode.ts 2 | -------------------------------------------------------------------------------- /website/linkcheck-ignore.txt: -------------------------------------------------------------------------------- 1 | http://localhost:\d{4} 2 | https://.*.algolia.net 3 | -------------------------------------------------------------------------------- /e2e/projects/typescript-commonjs-node/.gitignore: -------------------------------------------------------------------------------- 1 | /package-lock.json 2 | node_modules 3 | /src/api 4 | -------------------------------------------------------------------------------- /e2e/projects/typescript-es2015-bundler/.gitignore: -------------------------------------------------------------------------------- 1 | /package-lock.json 2 | node_modules 3 | /src/api 4 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/ts-factory/service-operation.generated/.gitignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | -------------------------------------------------------------------------------- /e2e/projects/typescript-nodenext-nodenext/.gitignore: -------------------------------------------------------------------------------- 1 | /package-lock.json 2 | node_modules 3 | /src/api 4 | -------------------------------------------------------------------------------- /.github/actions/spelling/allow.txt: -------------------------------------------------------------------------------- 1 | github 2 | https 3 | ssh 4 | ubuntu 5 | workarounds 6 | createapiclient 7 | -------------------------------------------------------------------------------- /packages/openapi-typescript-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | import { plugin } from './plugin.js'; 2 | 3 | export default plugin; 4 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | import { plugin } from './plugin.js'; 2 | 3 | export default plugin; 4 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/OperationError.ts: -------------------------------------------------------------------------------- 1 | export type OperationError = TError | Error; 2 | -------------------------------------------------------------------------------- /website/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "bracketSpacing": true, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenAPI-Qraft/openapi-qraft/HEAD/website/static/img/favicon.ico -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /website/docs/codegen/CLI/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "CLI", 3 | "collapsible": false, 4 | "collapsed": false 5 | } 6 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/src/types.ts: -------------------------------------------------------------------------------- 1 | export type ExtraRuleDocs = { 2 | recommended: 'strict' | 'error' | 'warn'; 3 | }; 4 | -------------------------------------------------------------------------------- /packages/react-client/src/unstable__responseUtils.ts: -------------------------------------------------------------------------------- 1 | export { resolveResponse, processResponse } from './lib/responseUtils.js'; 2 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/src/index.ts: -------------------------------------------------------------------------------- 1 | export { generateSourceFileFactoryCode } from './generateSourceFileFactoryCode'; 2 | -------------------------------------------------------------------------------- /website/static/img/docusaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenAPI-Qraft/openapi-qraft/HEAD/website/static/img/docusaurus.png -------------------------------------------------------------------------------- /playground/.env.local.example: -------------------------------------------------------------------------------- 1 | VITE_CLIENT_ID=c59964ce-... 2 | VITE_CLIENT_SECRET=49b55da0-... 3 | VITE_ENTITY_USER_ID=8ee9e41c-... 4 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | npmPublishRegistry: "https://registry.npmjs.org/" 4 | 5 | yarnPath: .yarn/releases/yarn-4.9.1.cjs 6 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './service-operation/index.js'; 2 | export type * from './shared/index.js'; 3 | -------------------------------------------------------------------------------- /website/static/img/docusaurus-social-card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenAPI-Qraft/openapi-qraft/HEAD/website/static/img/docusaurus-social-card.jpg -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/type-overrides/use-infinite-query-result.ts: -------------------------------------------------------------------------------- 1 | export type { UseInfiniteQueryResult } from '@tanstack/react-query'; 2 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/WithOptional.ts: -------------------------------------------------------------------------------- 1 | export type WithOptional = Omit & 2 | Partial>; 3 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/OutputOptions.ts: -------------------------------------------------------------------------------- 1 | import { URL } from 'node:url'; 2 | 3 | export interface OutputOptions { 4 | dir: URL; 5 | clean: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/type-overrides/create-query-client-options.ts: -------------------------------------------------------------------------------- 1 | export type { CreateAPIQueryClientOptions } from '@openapi-qraft/react'; 2 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/type-overrides/operation-error.ts: -------------------------------------------------------------------------------- 1 | export type { OperationError } from '@openapi-qraft/tanstack-query-react-types'; 2 | -------------------------------------------------------------------------------- /website/docs/hooks/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "React", 3 | "position": 50, 4 | "collapsible": true, 5 | "collapsed": true, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated 2 | /openapi.ts 3 | /api 4 | /queryable-write-operations-api 5 | /internal-api 6 | /files-api 7 | 8 | -------------------------------------------------------------------------------- /website/docs/codegen/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Codegen", 3 | "position": 3, 4 | "collapsible": false, 5 | "collapsed": false, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /website/docs/core/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Fetch", 3 | "position": 40, 4 | "collapsible": false, 5 | "collapsed": false, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /website/docs/eslint/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "ESLint Plugin", 3 | "position": 120, 4 | "collapsible": true, 5 | "collapsed": true, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /website/docs/query-client/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "QueryClient", 3 | "position": 60, 4 | "collapsible": true, 5 | "collapsed": true, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /website/versioned_sidebars/version-1.x-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "mainDocsSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/type-overrides/suspense-query.ts: -------------------------------------------------------------------------------- 1 | export type { 2 | UseSuspenseQueryOptions, 3 | UseSuspenseQueryResult, 4 | } from '@tanstack/react-query'; 5 | -------------------------------------------------------------------------------- /website/docs/getting-started/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Getting Started", 3 | "position": 2, 4 | "collapsible": false, 5 | "collapsed": false, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/core/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Fetch", 3 | "position": 40, 4 | "collapsible": false, 5 | "collapsed": false, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/hooks/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "React", 3 | "position": 50, 4 | "collapsible": true, 5 | "collapsed": true, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/src/utils/get-docs-url.ts: -------------------------------------------------------------------------------- 1 | export const getDocsUrl = (ruleName: string): string => 2 | `https://openapi-qraft.github.io/openapi-qraft/docs/eslint/${ruleName}`; 3 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/msw/node.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node'; 2 | import { handlers } from './handlers.js'; 3 | 4 | export const server = setupServer(...handlers); 5 | -------------------------------------------------------------------------------- /website/docs/authorization/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Authentication \uD83E\uDDEA", 3 | "position": 45, 4 | "collapsible": true, 5 | "collapsed": true, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/codegen/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Codegen", 3 | "position": 3, 4 | "collapsible": false, 5 | "collapsed": false, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/GeneratorFile.ts: -------------------------------------------------------------------------------- 1 | import type { URL } from 'node:url'; 2 | 3 | export type GeneratorFile = 4 | | { file: URL; code: string } 5 | | { directory: URL; clean: boolean }; 6 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/fileHeader.ts: -------------------------------------------------------------------------------- 1 | export const fileHeader = `/** 2 | * This file was auto-generated by @openapi-qraft/cli. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | `; 7 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "QueryClient", 3 | "position": 60, 4 | "collapsible": true, 5 | "collapsed": true, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/getting-started/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Getting Started", 3 | "position": 2, 4 | "collapsible": false, 5 | "collapsed": false, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /playground/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react-swc' 3 | 4 | // https://vite.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/authorization/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Authentication \uD83E\uDDEA", 3 | "position": 45, 4 | "collapsible": true, 5 | "collapsed": true, 6 | "link": null 7 | } 8 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/formatFileHeader.ts: -------------------------------------------------------------------------------- 1 | export const formatFileHeader = (fileHeader: string | undefined) => { 2 | if (!fileHeader) return ''; 3 | return `${fileHeader}${fileHeader.endsWith('\n') ? '' : '\n'}`; 4 | }; 5 | -------------------------------------------------------------------------------- /packages/plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | export { getContentMediaType } from './lib/open-api/getContent.js'; 2 | export { QraftCommand } from './lib/QraftCommand.js'; 3 | export { type QraftCommandPlugin } from './lib/QraftCommandPlugin.js'; 4 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/type-overrides/qraft-predefined-parameters.ts: -------------------------------------------------------------------------------- 1 | export type { RequestFn } from '@openapi-qraft/react'; 2 | export type { QraftPredefinedParameterValue } from '@openapi-qraft/react/qraftPredefinedParametersRequestFn'; 3 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "resolveJsonModule": true, 8 | }, 9 | "include": ["src/**/*"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/cli/eslint.config.js: -------------------------------------------------------------------------------- 1 | import openAPIQraftConfig from '@openapi-qraft/eslint-config/eslint.vanilla.config'; 2 | import globals from 'globals'; 3 | 4 | export default [ 5 | { languageOptions: { globals: globals.node } }, 6 | ...openAPIQraftConfig, 7 | ]; 8 | -------------------------------------------------------------------------------- /packages/plugin/eslint.config.js: -------------------------------------------------------------------------------- 1 | import openAPIQraftConfig from '@openapi-qraft/eslint-config/eslint.vanilla.config'; 2 | import globals from 'globals'; 3 | 4 | export default [ 5 | { languageOptions: { globals: globals.node } }, 6 | ...openAPIQraftConfig, 7 | ]; 8 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "declarationDir": "dist/types", 6 | "declaration": true, 7 | "declarationMap": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/cli/src/builtInPlugins.ts: -------------------------------------------------------------------------------- 1 | export const builtInPlugins = { 2 | 'tanstack-query-react': () => 3 | import('@openapi-qraft/tanstack-query-react-plugin'), 4 | 'openapi-typescript': () => 5 | import('@openapi-qraft/openapi-typescript-plugin'), 6 | } as const; 7 | -------------------------------------------------------------------------------- /packages/cli/bin.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | /** 5 | * Workaround to allow `rimraf dist/` on rebuilds and keep `bin` executable 6 | * without a need `yarn install` 7 | */ 8 | import { main } from './dist/bin.js'; 9 | 10 | main(process.argv); 11 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "declaration": true, 6 | "declarationMap": true 7 | }, 8 | "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/tmp/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/eslint.config.js: -------------------------------------------------------------------------------- 1 | import openAPIQraftConfig from '@openapi-qraft/eslint-config/eslint.vanilla.config'; 2 | import globals from 'globals'; 3 | 4 | export default [ 5 | { languageOptions: { globals: globals.node } }, 6 | ...openAPIQraftConfig, 7 | ]; 8 | -------------------------------------------------------------------------------- /packages/plugin/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "declaration": true, 6 | "declarationMap": true 7 | }, 8 | "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/tmp/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/openapi-typescript-plugin/eslint.config.js: -------------------------------------------------------------------------------- 1 | import openAPIQraftConfig from '@openapi-qraft/eslint-config/eslint.vanilla.config'; 2 | import globals from 'globals'; 3 | 4 | export default [ 5 | { languageOptions: { globals: globals.node } }, 6 | ...openAPIQraftConfig, 7 | ]; 8 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/eslint.config.js: -------------------------------------------------------------------------------- 1 | import openAPIQraftConfig from '@openapi-qraft/eslint-config/eslint.vanilla.config'; 2 | import globals from 'globals'; 3 | 4 | export default [ 5 | { languageOptions: { globals: globals.node } }, 6 | ...openAPIQraftConfig, 7 | ]; 8 | -------------------------------------------------------------------------------- /playground/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | 4 | import App from './App.tsx'; 5 | 6 | ReactDOM.createRoot(document.getElementById('root')!).render( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /playground/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "declaration": true, 8 | "resolveJsonModule": true 9 | }, 10 | "include": ["src/**/*"] 11 | } 12 | -------------------------------------------------------------------------------- /e2e/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @openapi-qraft/e2e 2 | 3 | ## 1.0.0 4 | 5 | ### Major Changes 6 | 7 | - c545cb2: chore: First release of the `@openapi-qraft/*` packages. 8 | 9 | ## 1.0.0-beta.1 10 | 11 | ### Major Changes 12 | 13 | - 2034eba: First release of the `@openapi-qraft/*` packages. 14 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/AreAllOptional.ts: -------------------------------------------------------------------------------- 1 | export type AreAllOptional = 2 | NonNullable extends never 3 | ? true 4 | : { 5 | [K in keyof T]-?: undefined extends T[K] ? never : K; 6 | }[keyof T] extends never 7 | ? true 8 | : false; 9 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "extends": ["//"], 4 | "tasks": { 5 | "typecheck": { 6 | "cache": true, 7 | "dependsOn": [ 8 | "^build", 9 | "build" 10 | ] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/DeepReadonly.ts: -------------------------------------------------------------------------------- 1 | export type DeepReadonly = T extends (...args: any[]) => any 2 | ? T 3 | : T extends Array 4 | ? ReadonlyArray> 5 | : T extends object 6 | ? { readonly [P in keyof T]: DeepReadonly } 7 | : T; 8 | -------------------------------------------------------------------------------- /packages/openapi-typescript-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "resolveJsonModule": true 8 | }, 9 | "include": ["src/**/*"], 10 | "exclude": ["src/__snapshots__/**/*"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/OperationInfiniteData.ts: -------------------------------------------------------------------------------- 1 | import type { InfiniteData } from '@tanstack/react-query'; 2 | import type { PartialParameters } from './PartialParameters.js'; 3 | 4 | export type OperationInfiniteData = InfiniteData< 5 | TData, 6 | PartialParameters 7 | >; 8 | -------------------------------------------------------------------------------- /website/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureEmoji { 9 | display: inline-block; 10 | height: 1em; 11 | width: 1em; 12 | margin-bottom: 0.6em; 13 | font-size: 70px; 14 | } 15 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @openapi-qraft/eslint-plugin-query 2 | 3 | ## 2.13.0 4 | 5 | ## 2.12.0 6 | 7 | ### Minor Changes 8 | 9 | - 8dcc7c1: Added `@openapi-qraft/eslint-plugin-query` 10 | 11 | An ESLint plugin to enforce best practices and prevent common mistakes with Qraft-generated hooks has been added. 12 | -------------------------------------------------------------------------------- /packages/openapi-typescript-plugin/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "declaration": true, 6 | "declarationMap": true, 7 | "resolveJsonModule": false 8 | }, 9 | "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/tmp/**", "src/__snapshots__/**/*"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "declaration": true, 8 | "resolveJsonModule": true, 9 | }, 10 | "include": ["src/**/*"], 11 | "exclude": ["src/__snapshots__/**/*"] 12 | } 13 | -------------------------------------------------------------------------------- /e2e/.gitignore: -------------------------------------------------------------------------------- 1 | # verdaccio 2 | /verdaccio-storage 3 | /htpasswd 4 | 5 | # misc 6 | .DS_Store 7 | *.pem 8 | 9 | # debug 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # typescript 15 | *.tsbuildinfo 16 | 17 | # yarn 18 | .yarn/* 19 | !.yarn/patches 20 | !.yarn/plugins 21 | !.yarn/releases 22 | !.yarn/sdks 23 | !.yarn/versions 24 | -------------------------------------------------------------------------------- /packages/react-client/turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "extends": ["//"], 4 | "tasks": { 5 | "typecheck": { 6 | "cache": true, 7 | "dependsOn": ["build"] 8 | }, 9 | "test": { 10 | "cache": true, 11 | "dependsOn": ["build"], 12 | "outputs": ["coverage/**"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "declaration": true, 8 | "resolveJsonModule": true, 9 | "module": "ES2022", 10 | "moduleResolution": "Bundler" 11 | }, 12 | "include": ["src/**/*"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/maybeEscapeShellArg.ts: -------------------------------------------------------------------------------- 1 | import { shouldQuoteCommandLineArg } from './shouldQuoteCommandLineArg.js'; 2 | 3 | export function maybeEscapeShellArg(arg: string): string { 4 | if (shouldQuoteCommandLineArg(arg)) { 5 | // bash-safe single-quote escaping 6 | return `'${arg.replace(/'/g, `'\\''`)}'`; 7 | } 8 | 9 | return arg; 10 | } 11 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/getContent.ts: -------------------------------------------------------------------------------- 1 | export const getContentMediaType = ( 2 | content: 3 | | { 4 | [contentType: string]: { schema: unknown } | { type: unknown }; 5 | } 6 | | undefined 7 | ) => { 8 | const mediaTypes = Object.keys(content || {}); 9 | 10 | if (!mediaTypes.length) return null; 11 | 12 | return mediaTypes; 13 | }; 14 | -------------------------------------------------------------------------------- /packages/react-client/src/lib/requestFnResponseResolver.ts: -------------------------------------------------------------------------------- 1 | import type { RequestFnResponse } from './requestFn.js'; 2 | 3 | export function requestFnResponseResolver( 4 | requestFnResponse: RequestFnResponse 5 | ): TData | undefined { 6 | if ('error' in requestFnResponse) throw requestFnResponse.error; 7 | return requestFnResponse.data; 8 | } 9 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/__snapshots__/no-export-openapi-types/index.ts.snapshot.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by @openapi-qraft/cli. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | export { services } from "./services/index"; 7 | export type { Services } from "./services/index"; 8 | export { createAPIClient } from "./create-api-client"; 9 | -------------------------------------------------------------------------------- /playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Qraft Playground 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /website/docs/query-client/getQueryState.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: getQueryState() 3 | --- 4 | 5 | # getQueryState(...) 6 | 7 | See the TanStack 8 | [_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate) 9 | documentation. 10 | 11 | :::info 12 | Documentation is actively being updated 🚧 13 | ::: 14 | -------------------------------------------------------------------------------- /e2e/projects/typescript-commonjs-node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "rootDir": "./src", 5 | "target": "es2016", 6 | "module": "CommonJS", 7 | "moduleResolution": "Node", 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "strict": true, 11 | "skipLibCheck": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "declarationDir": "dist/types", 6 | "declaration": true, 7 | "declarationMap": true 8 | }, 9 | "exclude": [ 10 | "src/**/*.spec.ts", 11 | "src/__tests__/**", 12 | "src/**/*.test.ts", 13 | "src/tmp/**" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # editorconfig-checker bin 8 | /bin/latest 9 | 10 | # Generated files 11 | .docusaurus 12 | .cache-loader 13 | 14 | # Misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/getQueryState.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: getQueryState() 3 | --- 4 | 5 | # getQueryState(...) 6 | 7 | See the TanStack 8 | [_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate) 9 | documentation. 10 | 11 | :::info 12 | Documentation is actively being updated 🚧 13 | ::: 14 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/getQueriesData.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: getQueriesData() 3 | --- 4 | 5 | # getQueriesData(...) 6 | 7 | See the TanStack 8 | [_queryClient.getQueriesData(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetqueriesdata) 9 | documentation. 10 | 11 | :::info 12 | Documentation is actively being updated 🚧 13 | ::: 14 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/setupTests.ts: -------------------------------------------------------------------------------- 1 | import { cleanup } from '@testing-library/react'; 2 | import { afterAll, afterEach, beforeAll } from 'vitest'; 3 | import { server } from './msw/node.js'; 4 | 5 | beforeAll(() => { 6 | server.listen(); 7 | }); 8 | 9 | afterEach(() => { 10 | server.resetHandlers(); 11 | cleanup(); 12 | }); 13 | 14 | afterAll(() => { 15 | server.close(); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/react-client/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "declarationDir": "dist/types", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "paths": {} 9 | }, 10 | "include": ["src/**/*"], 11 | "exclude": [ 12 | "**/node_modules", 13 | "**/.*/", 14 | "src/tests/**/*" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "extends": ["//"], 4 | "tasks": { 5 | "codegen": { 6 | "cache": true, 7 | "dependsOn": ["^build"], 8 | "outputs": [ 9 | "src/ts-factory/service-operation.generated/**/*.ts" 10 | ], 11 | "inputs": ["generate-ts-factory.mjs"] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /playground/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | src/api 27 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/QraftCommandPlugin.ts: -------------------------------------------------------------------------------- 1 | import { QraftCommand } from './QraftCommand.js'; 2 | 3 | export interface QraftCommandPlugin { 4 | setupCommand(command: QraftCommand): void | Promise; 5 | 6 | /** 7 | * Called after all plugins have been set up 8 | */ 9 | postSetupCommand?( 10 | command: QraftCommand, 11 | plugins: string[] 12 | ): void | Promise; 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "NodeNext", 5 | "lib": ["ES2019", "ESNext.Array", "ES2022.Array"], 6 | "moduleResolution": "NodeNext", 7 | "sourceMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "strict": true, 11 | "skipLibCheck": true, 12 | "noEmit": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /website/tools/algolia/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_name": "openapi-qraftio", 3 | "start_urls": ["https://openapi-qraft.github.io/openapi-qraft/"], 4 | "sitemap_urls": ["https://openapi-qraft.github.io/openapi-qraft/sitemap.xml"], 5 | "stop_urls": [], 6 | "strip_chars": "#", 7 | "custom_settings": { 8 | "attributesForFaceting": ["language", "version", "type", "docusaurus_tag"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "lib": ["ES2019", "DOM", "DOM.Iterable"], 8 | "jsx": "react", 9 | "verbatimModuleSyntax": true 10 | }, 11 | "include": ["src/**/*"], 12 | "exclude": [ 13 | "**/node_modules" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/generate-factory-code-generator.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import * as fs from 'fs'; 3 | import { generateCode } from 'ts-factory-code-generator-generator'; 4 | 5 | console.log('🏗️ Generating code for TypeScript Factory Generator...'); 6 | 7 | fs.writeFileSync( 8 | './src/generateFactoryCode.ts', 9 | generateCode('typescript-5.5.4'), 10 | { encoding: 'utf-8' } 11 | ); 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log* 2 | yarn-debug.log* 3 | yarn-error.log* 4 | stats.html* 5 | build-storybook.log 6 | 7 | .firebase 8 | .DS_Store 9 | .idea 10 | 11 | node_modules 12 | dist 13 | build 14 | coverage 15 | 16 | .yarn/* 17 | !.yarn/patches 18 | !.yarn/plugins 19 | !.yarn/releases 20 | !.yarn/sdks 21 | !.yarn/versions 22 | 23 | .swc/ 24 | .turbo/ 25 | 26 | # Used as dummy placeholder during CI/CD 27 | /.npmrc 28 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "declaration": true, 6 | "declarationMap": true 7 | }, 8 | "exclude": [ 9 | "src/**/*.spec.ts", 10 | "src/**/*.test.ts", 11 | "src/tmp/**", 12 | "src/__snapshots__/**/*", 13 | "src/ts-factory-source/service-operation/**/*" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import openAPIQraftConfig from '@openapi-qraft/eslint-config/eslint.vanilla.config'; 2 | import { defineConfig, globalIgnores } from 'eslint/config'; 3 | import globals from 'globals'; 4 | 5 | export default defineConfig([ 6 | { languageOptions: { globals: globals.node } }, 7 | ...openAPIQraftConfig, 8 | globalIgnores(['src/generateFactoryCode.ts']), 9 | ]); 10 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "bracketSpacing": true, 4 | "trailingComma": "es5", 5 | "importOrder": [ 6 | "^(node:)", 7 | "", 8 | "^[.]", 9 | "", 10 | "", 11 | "^[.]" 12 | ], 13 | "importOrderParserPlugins": ["importAssertions", "typescript", "jsx"], 14 | "plugins": ["@ianvs/prettier-plugin-sort-imports"] 15 | } 16 | -------------------------------------------------------------------------------- /e2e/projects/typescript-es2015-bundler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "rootDir": "./src", 5 | "target": "es2016", 6 | "module": "es2015", 7 | "moduleResolution": "Bundler", 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "strict": true, 11 | "skipLibCheck": true, 12 | "verbatimModuleSyntax": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /e2e/projects/typescript-nodenext-nodenext/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "rootDir": "./src", 5 | "target": "es2016", 6 | "module": "NodeNext", 7 | "moduleResolution": "NodeNext", 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "strict": true, 11 | "skipLibCheck": true, 12 | "verbatimModuleSyntax": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import { rollupConfig } from '@openapi-qraft/rollup-config'; 2 | import packageJson from './package.json' with { type: 'json' }; 3 | 4 | const moduleDist = { 5 | import: packageJson['exports']['.']['import'], 6 | require: packageJson['exports']['.']['require'], 7 | }; 8 | 9 | const config = [rollupConfig(moduleDist, { input: 'src/index.ts' })]; 10 | 11 | export default config; 12 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-title.yml: -------------------------------------------------------------------------------- 1 | name: Lint PR Title 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - reopened 8 | - edited 9 | - synchronize 10 | 11 | jobs: 12 | main: 13 | name: Lint PR Title 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: amannn/action-semantic-pull-request@v5 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | -------------------------------------------------------------------------------- /e2e/bin/build-projects.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -o errexit 4 | 5 | BASE_DIR=$(dirname "$(readlink -f "$0")") 6 | 7 | PROJECTS=$(find "${TEST_PROJECTS_DIR:-"$BASE_DIR/../projects"}" -maxdepth 1 -mindepth 1 -type d) 8 | 9 | for project in $PROJECTS; do 10 | echo "Building $project..." 11 | (cd "$project" && npm run e2e:pre-build) 12 | (cd "$project" && npm run build) 13 | (cd "$project" && npm run e2e:post-build) 14 | done 15 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import { rollupConfig } from '@openapi-qraft/rollup-config'; 2 | import packageJson from './package.json' with { type: 'json' }; 3 | 4 | const moduleDist = { 5 | import: packageJson['exports']['.']['import'], 6 | require: packageJson['exports']['.']['require'], 7 | }; 8 | 9 | const config = [rollupConfig(moduleDist, { input: 'src/index.ts' })]; 10 | 11 | export default config; 12 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/PartialParameters.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Shallow partial 'parameters'. 3 | * @example 4 | * ```ts 5 | * {query?: {page: number, nested: {still: 'not_partial'}}} 6 | * // => 7 | * {query?: {page?: number, nested?: {still: 'not_partial'}}} 8 | * ``` 9 | */ 10 | export type PartialParameters = T extends object 11 | ? { [K in keyof T]?: T[K] extends object ? Partial : T[K] } 12 | : T; 13 | -------------------------------------------------------------------------------- /website/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | 8 | [*.{js,jsx,mjs,ts,tsx,css,md}] 9 | indent_style = space 10 | indent_size = 2 11 | max_line_length = 160 12 | 13 | [*.mdx] 14 | indent_style = space 15 | indent_size = 2 16 | 17 | [*.{yml,yaml}] 18 | indent_style = space 19 | indent_size = 2 20 | 21 | [*.{bat,cmd,ps1}] 22 | end_of_line = crlf 23 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/createTestJwt.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { jwtDecode } from '../lib/jwt-decode/index.js'; 3 | import { createTestJwt } from './createTestJwt.js'; 4 | 5 | describe('createTestJwt', () => { 6 | it('creates valid jwt', () => { 7 | expect(jwtDecode(createTestJwt({ exp: 123, iat: 100 }))).toEqual({ 8 | exp: 123, 9 | iat: 100, 10 | }); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "rootDir": "src", 5 | "strict": true, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "target": "es2016", 9 | "module": "CommonJS", 10 | "esModuleInterop": false, 11 | "forceConsistentCasingInFileNames": true, 12 | "skipLibCheck": true 13 | }, 14 | "include": [ 15 | "src/**/*" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | globals: true, 6 | environment: 'node', 7 | css: false, 8 | coverage: { 9 | include: ['src/**/*'], 10 | exclude: [ 11 | 'src/__tests__/**', 12 | 'src/index.ts', 13 | 'src/rules.ts', 14 | 'src/**/*.d.ts', 15 | ], 16 | }, 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /packages/rollup-config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "baseUrl": ".", 5 | "declaration": true, 6 | "outDir": "dist", 7 | "module": "ESNext", 8 | "target": "ES2019", 9 | "moduleResolution": "Node", 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "skipLibCheck": true 14 | }, 15 | "exclude": ["node_modules", "dist"] 16 | } 17 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/isReadOnlyOperation.ts: -------------------------------------------------------------------------------- 1 | export function isReadOnlyOperation(operation: { 2 | readonly method: 3 | | 'get' 4 | | 'put' 5 | | 'post' 6 | | 'patch' 7 | | 'delete' 8 | | 'options' 9 | | 'head' 10 | | 'trace'; 11 | }) { 12 | return ( 13 | operation.method === 'get' || 14 | operation.method === 'head' || 15 | operation.method === 'trace' || 16 | operation.method === 'options' 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/getServiceName.ts: -------------------------------------------------------------------------------- 1 | import camelCase from 'camelcase'; 2 | 3 | /** 4 | * Convert the input value to the correct service name. This converts 5 | * the input string to PascalCase. 6 | */ 7 | export const getServiceName = (value: string): string => { 8 | const clean = value 9 | .replace(/^[^a-zA-Z]+/g, '') 10 | .replace(/[^\w-]+/g, '-') 11 | .trim(); 12 | 13 | return camelCase(clean, { pascalCase: true }); 14 | }; 15 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "extends": ["//"], 4 | "tasks": { 5 | "codegen": { 6 | "cache": true, 7 | "dependsOn": [], 8 | "inputs": [], 9 | "outputs": ["src/generateFactoryCode.ts"] 10 | }, 11 | "build": { 12 | "cache": true, 13 | "dependsOn": ["codegen"], 14 | "inputs": ["src/**"], 15 | "outputs": ["dist/**"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/__snapshots__/openapi-types-import-path-d-ts/index.ts.snapshot.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by @openapi-qraft/cli. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | export type { $defs, paths, components, operations, webhooks } from "./../openapi.d.ts"; 7 | export { services } from "./services/index"; 8 | export type { Services } from "./services/index"; 9 | export { createAPIClient } from "./create-api-client"; 10 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/__snapshots__/openapi-types-import-path-ts/index.ts.snapshot.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by @openapi-qraft/cli. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | export type { $defs, paths, components, operations, webhooks } from "./../openapi.ts"; 7 | export { services } from "./services/index"; 8 | export type { Services } from "./services/index"; 9 | export { createAPIClient } from "./create-api-client"; 10 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/index.ts.snapshot.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by @openapi-qraft/cli. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | export type { $defs, paths, components, operations, webhooks } from "./../openapi.js"; 7 | export { services } from "./services/index.js"; 8 | export type { Services } from "./services/index.js"; 9 | export { createAPIClient } from "./create-api-client.js"; 10 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions-d-ts-imports/index.ts.snapshot.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by @openapi-qraft/cli. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | export type { $defs, paths, components, operations, webhooks } from "./../openapi.d.ts"; 7 | export { services } from "./services/index.ts"; 8 | export type { Services } from "./services/index.ts"; 9 | export { createAPIClient } from "./create-api-client.ts"; 10 | -------------------------------------------------------------------------------- /website/docs/query-client/getInfiniteQueryState.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: getInfiniteQueryState() 3 | --- 4 | 5 | # getInfiniteQueryState(...) 6 | 7 | The method is the same as the [`getQueryState`](getQueryState.mdx) method, but for infinite queries. 8 | See the TanStack 9 | [_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate) 10 | documentation. 11 | 12 | :::info 13 | Documentation is actively being updated 🚧 14 | ::: 15 | -------------------------------------------------------------------------------- /website/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /website/docs/query-client/resetQueries.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: resetQueries() 3 | --- 4 | 5 | # resetQueries(...) 6 | 7 | The function is used to refetch a list of queries by their keys. 8 | The API is the same as [_cancelQueries(...)_](cancelQueries.mdx) Hook. 9 | See also the TanStack [_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries) documentation. 10 | 11 | :::info 12 | Documentation is actively being updated 🚧 13 | ::: 14 | -------------------------------------------------------------------------------- /packages/eslint-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @openapi-qraft/eslint-config 2 | 3 | ## 1.0.1 4 | 5 | ### Patch Changes 6 | 7 | - 37fbcd3: Enabled provenance support in GitHub Actions for npm publishing. 8 | 9 | Special thanks to [GauBen](https://github.com/GauBen) for implementing provenance publishing support in Yarn — this work 10 | inspired this change. 11 | 12 | ## 1.0.1-provenance-test.0 13 | 14 | ### Patch Changes 15 | 16 | - 37fbcd3: Enabled provenance support in GitHub Actions for npm publishing. 17 | -------------------------------------------------------------------------------- /packages/test-fixtures/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openapi-qraft/test-fixtures", 3 | "version": "1.1.1", 4 | "private": true, 5 | "packageManager": "yarn@4.0.2", 6 | "exports": { 7 | "./openapi.json": "./openapi.json", 8 | "./package.json": "./package.json" 9 | }, 10 | "files": [ 11 | "openapi.json" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/OpenAPI-Qraft/openapi-qraft.git", 16 | "directory": "packages/cli" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/src/rules/no-rest-destructuring/no-rest-destructuring.utils.ts: -------------------------------------------------------------------------------- 1 | import type { TSESTree } from '@typescript-eslint/utils'; 2 | import { AST_NODE_TYPES } from '@typescript-eslint/utils'; 3 | 4 | export const NoRestDestructuringUtils = { 5 | isObjectRestDestructuring(node: TSESTree.Node): boolean { 6 | if (node.type !== AST_NODE_TYPES.ObjectPattern) { 7 | return false; 8 | } 9 | return node.properties.some((p) => p.type === AST_NODE_TYPES.RestElement); 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/getInfiniteQueryState.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: getInfiniteQueryState() 3 | --- 4 | 5 | # getInfiniteQueryState(...) 6 | 7 | The method is the same as the [`getQueryState`](getQueryState.mdx) method, but for infinite queries. 8 | See the TanStack 9 | [_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate) 10 | documentation. 11 | 12 | :::info 13 | Documentation is actively being updated 🚧 14 | ::: 15 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/resetQueries.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: resetQueries() 3 | --- 4 | 5 | # resetQueries(...) 6 | 7 | The function is used to refetch a list of queries by their keys. 8 | The API is the same as [_cancelQueries(...)_](cancelQueries.mdx) Hook. 9 | See also the TanStack [_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries) documentation. 10 | 11 | :::info 12 | Documentation is actively being updated 🚧 13 | ::: 14 | -------------------------------------------------------------------------------- /packages/react-client/src/lib/composeQueryKey.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationQueryKey } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { OperationSchema } from './requestFn.js'; 3 | import { composeBaseQueryKey } from './composeBaseQueryKey.js'; 4 | 5 | export function composeQueryKey( 6 | schema: TSchema, 7 | parameters: TParams | undefined 8 | ): ServiceOperationQueryKey { 9 | return composeBaseQueryKey(schema, parameters, false); 10 | } 11 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/getServiceNamesByOperationTags.ts: -------------------------------------------------------------------------------- 1 | import { getServiceName } from './getServiceName.js'; 2 | 3 | export const getServiceNamesByOperationTags = ( 4 | tags: (string | number | null | undefined)[] | undefined, 5 | fallbackBaseName: string 6 | ): string[] => { 7 | const filteredTags = tags 8 | ?.filter((tag): tag is string => typeof tag === 'string') 9 | .map(getServiceName) 10 | .filter(Boolean); 11 | 12 | return filteredTags?.length 13 | ? filteredTags 14 | : [getServiceName(fallbackBaseName)]; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/react-client/src/lib/requestFnResponseRejecter.ts: -------------------------------------------------------------------------------- 1 | import type { RequestFnResponse } from './requestFn.js'; 2 | 3 | export function requestFnResponseRejecter( 4 | requestFnResponseOrError: RequestFnResponse | Error 5 | ): TData | undefined { 6 | if (requestFnResponseOrError instanceof Error) throw requestFnResponseOrError; 7 | if ('error' in requestFnResponseOrError) throw requestFnResponseOrError.error; 8 | throw new Error('Unhandled `requestFn` response', { 9 | cause: requestFnResponseOrError, 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/readSchema.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'node:stream'; 2 | import type { Config } from '@redocly/openapi-core'; 3 | import type { OpenAPI3 } from 'openapi-typescript'; 4 | import { validateAndBundle } from 'openapi-typescript/dist/lib/redoc.js'; 5 | 6 | export const readSchema = async ( 7 | source: string | URL | OpenAPI3 | Readable | Buffer, 8 | redoc: Config 9 | ) => { 10 | const parsed = await validateAndBundle(source, { 11 | redoc, 12 | silent: false, 13 | }); 14 | 15 | return parsed as OpenAPI3; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/lib/createOperationCommonTSDoc.ts: -------------------------------------------------------------------------------- 1 | import { ServiceOperation } from '@openapi-qraft/plugin/lib/open-api/OpenAPIService'; 2 | 3 | export const createOperationCommonTSDoc = (operation: ServiceOperation) => { 4 | return [ 5 | operation.deprecated ? '@deprecated' : null, 6 | operation.summary ? `@summary ${operation.summary}` : null, 7 | operation.description ? `@description ${operation.description}` : null, 8 | ].filter((comment): comment is NonNullable => 9 | Boolean(comment) 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /e2e/projects/typescript-es2015-bundler/my-redocly.yaml: -------------------------------------------------------------------------------- 1 | rules: 2 | operation-operationId-unique: 3 | severity: 'error' 4 | 5 | apis: 6 | main: 7 | root: https://raw.githubusercontent.com/swagger-api/swagger-petstore/7767363b841961221a38c0be9c6b1066a5120051/src/main/resources/openapi.yaml 8 | x-openapi-qraft: 9 | output-dir: src/api 10 | clean: true 11 | openapi-types-import-path: '../schema.d.ts' 12 | openapi-types-file-name: schema.d.ts 13 | plugin: 14 | tanstack-query-react: true 15 | openapi-typescript: true 16 | -------------------------------------------------------------------------------- /packages/react-client/src/lib/composeInfiniteQueryKey.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationInfiniteQueryKey } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { OperationSchema } from './requestFn.js'; 3 | import { composeBaseQueryKey } from './composeBaseQueryKey.js'; 4 | 5 | export function composeInfiniteQueryKey< 6 | TSchema extends OperationSchema, 7 | TParams, 8 | >( 9 | schema: TSchema, 10 | parameters: TParams | undefined 11 | ): ServiceOperationInfiniteQueryKey { 12 | return composeBaseQueryKey(schema, parameters, true); 13 | } 14 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/QraftServiceOperationsToken.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A unique symbol that exists only at type-level and is used for type inference of services. 3 | * This symbol does not exist at runtime and cannot be accessed or used for data operations. 4 | * It serves purely as a TypeScript type mechanism to infer and enforce correct service types 5 | * when services are passed as variables in the type system. 6 | */ 7 | export declare const QraftServiceOperationsToken: unique symbol; 8 | export type QraftServiceOperationsToken = typeof QraftServiceOperationsToken; 9 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/eslint.config.js: -------------------------------------------------------------------------------- 1 | import openAPIQraftConfig from '@openapi-qraft/eslint-config/eslint.vanilla.config'; 2 | import globals from 'globals'; 3 | 4 | export default [ 5 | { languageOptions: { globals: globals.node } }, 6 | ...openAPIQraftConfig, 7 | { 8 | files: ['src/ts-factory/service-operation.generated/**'], 9 | rules: { 10 | 'prettier/prettier': 'off', 11 | }, 12 | }, 13 | { 14 | files: ['generate-ts-factory.mjs'], 15 | rules: { 16 | 'import-x/no-extraneous-dependencies': ['off'], 17 | }, 18 | }, 19 | ]; 20 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/ts-factory/tsdoc/lib/createOperationMethodBodyParametersExampleNode.ts: -------------------------------------------------------------------------------- 1 | import { ServiceOperation } from '@openapi-qraft/plugin/lib/open-api/OpenAPIService'; 2 | import { factory } from 'typescript'; 3 | 4 | export const createOperationMethodBodyParametersExampleNode = ( 5 | operation: ServiceOperation, 6 | bodyVariableName = 'queryBody' 7 | ) => 8 | operation.requestBody 9 | ? factory.createPropertyAssignment( 10 | factory.createIdentifier('body'), 11 | factory.createIdentifier(bodyVariableName) 12 | ) 13 | : undefined; 14 | -------------------------------------------------------------------------------- /website/docs/query-client/setInfiniteQueryData.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: setInfiniteQueryData() 3 | --- 4 | 5 | # setInfiniteQueryData(...) 6 | 7 | The method enables direct access to the `QueryClient` cache to set the data for a specific _Infinite Query_. 8 | The method API is the same as the [`setQueryData`](setQueryData.mdx) method, but it is specifically for _Infinite Queries_. 9 | 10 | See the TanStack [_queryClient.setQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata) documentation. 11 | 12 | :::info 13 | Documentation is actively being updated 🚧 14 | ::: 15 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/setInfiniteQueryData.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: setInfiniteQueryData() 3 | --- 4 | 5 | # setInfiniteQueryData(...) 6 | 7 | The method enables direct access to the `QueryClient` cache to set the data for a specific _Infinite Query_. 8 | The method API is the same as the [`setQueryData`](setQueryData.mdx) method, but it is specifically for _Infinite Queries_. 9 | 10 | See the TanStack [_queryClient.setQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata) documentation. 11 | 12 | :::info 13 | Documentation is actively being updated 🚧 14 | ::: 15 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/src/rules.ts: -------------------------------------------------------------------------------- 1 | import type { ESLintUtils } from '@typescript-eslint/utils'; 2 | import type { ExtraRuleDocs } from './types'; 3 | import * as noRestDestructuring from './rules/no-rest-destructuring/no-rest-destructuring.rule'; 4 | import * as noUnstableDeps from './rules/no-unstable-deps/no-unstable-deps.rule'; 5 | 6 | export const rules: Record< 7 | string, 8 | ESLintUtils.RuleModule< 9 | string, 10 | ReadonlyArray, 11 | ExtraRuleDocs, 12 | ESLintUtils.RuleListener 13 | > 14 | > = { 15 | [noRestDestructuring.name]: noRestDestructuring.rule, 16 | [noUnstableDeps.name]: noUnstableDeps.rule, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/cli/src/handleDeprecatedOptions.ts: -------------------------------------------------------------------------------- 1 | import c from 'ansi-colors'; 2 | 3 | const deprecatedOptionsMap: Record = { 4 | '-rm': { replacement: '-c' }, 5 | }; 6 | 7 | export function handleDeprecatedOptions(argv: string[]): string[] { 8 | return argv.map((arg) => { 9 | const deprecated = deprecatedOptionsMap[arg]; 10 | if (deprecated) { 11 | console.warn( 12 | c.yellow( 13 | `⚠ Option '${arg}' is deprecated and will be removed in v3.0. Please use '${deprecated.replacement}' instead.` 14 | ) 15 | ); 16 | return deprecated.replacement; 17 | } 18 | return arg; 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /.yarn/patches/ts-morph-npm-17.0.1-6097358fba.patch: -------------------------------------------------------------------------------- 1 | diff --git a/dist/ts-morph.js b/dist/ts-morph.js 2 | index a0dddc39797ba9f3db9b21b689195bd2b59e4ae2..50e0970b06842f7bcf0a49114cbb08a7197505f9 100644 3 | --- a/dist/ts-morph.js 4 | +++ b/dist/ts-morph.js 5 | @@ -20200,6 +20200,8 @@ class Project { 6 | }); 7 | } 8 | addSourceFileAtPath(filePath) { 9 | + if (filePath.startsWith('node_modules/typescript')) 10 | + filePath = `../../${filePath}` 11 | return this._context.directoryCoordinator.addSourceFileAtPath(this._context.fileSystemWrapper.getStandardizedAbsolutePath(filePath), { 12 | markInProject: true, 13 | }); 14 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/vitestFsMock.ts: -------------------------------------------------------------------------------- 1 | import { vi } from 'vitest'; 2 | 3 | const createMemFs = vi.hoisted( 4 | () => async (_fsOriginal: typeof import('node:fs')) => { 5 | const { Volume, createFsFromVolume } = await import('memfs'); 6 | 7 | return createFsFromVolume(Volume.fromJSON({})); 8 | } 9 | ); 10 | 11 | vi.mock('node:fs', async (importOriginal) => { 12 | return { 13 | default: await createMemFs( 14 | await importOriginal() 15 | ), 16 | }; 17 | }); 18 | 19 | vi.mock('fs', async (importOriginal) => { 20 | return { 21 | default: await createMemFs(await importOriginal()), 22 | }; 23 | }); 24 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openapi-qraft/eslint-config", 3 | "version": "1.0.1", 4 | "packageManager": "yarn@4.0.2", 5 | "private": true, 6 | "type": "module", 7 | "dependencies": { 8 | "@eslint/js": "^9.39.1", 9 | "eslint-config-prettier": "^10.1.8", 10 | "eslint-plugin-prettier": "^5.5.4", 11 | "globals": "^15.15.0", 12 | "typescript-eslint": "^8.24.0" 13 | }, 14 | "devDependencies": { 15 | "eslint": "^9.39.1", 16 | "eslint-import-resolver-typescript": "^4.4.4", 17 | "eslint-plugin-import-x": "^4.16.1" 18 | }, 19 | "exports": { 20 | "./package.json": "./package.json", 21 | "./*": "./*.js" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationGetQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AreAllOptional, 3 | DeepReadonly, 4 | ServiceOperationQueryKey, 5 | } from '@openapi-qraft/tanstack-query-react-types'; 6 | 7 | export interface ServiceOperationGetQueryData< 8 | TSchema extends { url: string; method: string }, 9 | TOperationQueryFnData, 10 | TQueryParams, 11 | > { 12 | getQueryData( 13 | parameters: 14 | | ServiceOperationQueryKey 15 | | (AreAllOptional extends true 16 | ? DeepReadonly | void 17 | : DeepReadonly) 18 | ): TOperationQueryFnData | undefined; 19 | } 20 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/InvalidateQueryFilters.ts: -------------------------------------------------------------------------------- 1 | import type { DefaultError } from '@tanstack/react-query'; 2 | import type { 3 | QueryFiltersByParameters, 4 | QueryFiltersByQueryKey, 5 | QueryTypeFilter, 6 | } from './QueryFilters.js'; 7 | 8 | export type InvalidateQueryFilters< 9 | TSchema extends { url: string; method: string }, 10 | TQueryFnData, 11 | TInfinite extends boolean, 12 | TParams = {}, 13 | TError = DefaultError, 14 | > = ( 15 | | QueryFiltersByParameters 16 | | QueryFiltersByQueryKey 17 | ) & { 18 | refetchType?: QueryTypeFilter | 'none'; 19 | }; 20 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @openapi-qraft/ts-factory-code-generator 2 | 3 | ## 1.0.2 4 | 5 | ### Patch Changes 6 | 7 | - 37fbcd3: Enabled provenance support in GitHub Actions for npm publishing. 8 | 9 | Special thanks to [GauBen](https://github.com/GauBen) for implementing provenance publishing support in Yarn — this work 10 | inspired this change. 11 | 12 | ## 1.0.2-provenance-test.0 13 | 14 | ### Patch Changes 15 | 16 | - 37fbcd3: Enabled provenance support in GitHub Actions for npm publishing. 17 | 18 | ## 1.0.1 19 | 20 | ### Patch Changes 21 | 22 | - 05b734b: Reorganized the internal file structure of `ts-factory-code-generator` for better maintainability and consistency. 23 | -------------------------------------------------------------------------------- /e2e/projects/typescript-es2015-bundler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-es2015-bundler", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "", 6 | "type": "module", 7 | "scripts": { 8 | "build": "tsc", 9 | "codegen": "openapi-qraft --redocly my-redocly.yaml", 10 | "e2e:pre-build": "npm run codegen", 11 | "e2e:post-build": "echo 'No post-build action'" 12 | }, 13 | "dependencies": { 14 | "@openapi-qraft/cli": "latest", 15 | "@openapi-qraft/react": "latest", 16 | "@types/node": "latest", 17 | "typescript": "latest" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/OpenAPI-Qraft/openapi-qraft.git" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/rollup-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @openapi-qraft/rollup-config 2 | 3 | ## 1.1.1 4 | 5 | ### Patch Changes 6 | 7 | - 37fbcd3: Enabled provenance support in GitHub Actions for npm publishing. 8 | 9 | Special thanks to [GauBen](https://github.com/GauBen) for implementing provenance publishing support in Yarn — this work 10 | inspired this change. 11 | 12 | ## 1.1.1-provenance-test.0 13 | 14 | ### Patch Changes 15 | 16 | - 37fbcd3: Enabled provenance support in GitHub Actions for npm publishing. 17 | 18 | ## 1.1.0 19 | 20 | ### Minor Changes 21 | 22 | - 2a53608: Updated TypeScript to version 5.5.4 23 | 24 | ## 1.1.0-next.0 25 | 26 | ### Minor Changes 27 | 28 | - 2a53608: Updated TypeScript to version 5.5.4 29 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/ServiceOperationKey.ts: -------------------------------------------------------------------------------- 1 | export type ServiceOperationBaseQueryKey< 2 | S extends { url: string; method: string }, 3 | Infinite extends boolean, 4 | T, 5 | > = [S & { infinite: Infinite }, T]; 6 | 7 | export type ServiceOperationQueryKey< 8 | S extends { url: string; method: string }, 9 | T, 10 | > = ServiceOperationBaseQueryKey; 11 | 12 | export type ServiceOperationInfiniteQueryKey< 13 | S extends { url: string; method: string }, 14 | T, 15 | > = ServiceOperationBaseQueryKey; 16 | 17 | export type ServiceOperationMutationKey< 18 | S extends Record<'url' | 'method', string>, 19 | T, 20 | > = NonNullable extends never ? [S] : [S, T]; 21 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/lib/maybeResolveImport.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Prepend the import path if it's a relative path. 3 | * Normally,`openapiTypesImportPath` is a relative path to the services' directory. 4 | */ 5 | export function maybeResolveImport({ 6 | openapiTypesImportPath, 7 | servicesDirName, 8 | }: { 9 | openapiTypesImportPath: T; 10 | servicesDirName: string; 11 | }) { 12 | if (openapiTypesImportPath?.startsWith('../')) { 13 | return `./${openapiTypesImportPath.slice(3)}`; 14 | } else if (openapiTypesImportPath?.startsWith('./')) { 15 | return `./${servicesDirName}/${openapiTypesImportPath.slice(2)}`; 16 | } 17 | 18 | return openapiTypesImportPath; 19 | } 20 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationInvalidateQueries.ts: -------------------------------------------------------------------------------- 1 | import type { InvalidateQueryFilters } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { InvalidateOptions } from '@tanstack/react-query'; 3 | 4 | export interface ServiceOperationInvalidateQueries< 5 | TSchema extends { url: string; method: string }, 6 | TOperationQueryFnData, 7 | TQueryParams, 8 | TError, 9 | > { 10 | invalidateQueries( 11 | filters?: InvalidateQueryFilters< 12 | TSchema, 13 | TOperationQueryFnData, 14 | TInfinite, 15 | TQueryParams, 16 | TError 17 | >, 18 | options?: InvalidateOptions 19 | ): Promise; 20 | } 21 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/migrate-to-v2.6.0-codemod/custom-package.tsx: -------------------------------------------------------------------------------- 1 | // Import from custom package (not standard '@openapi-qraft/react-client') 2 | import { qraftAPIClient } from '@custom/package'; 3 | 4 | // This call should be modified when correct package name is specified in options 5 | const api = qraftAPIClient(services, callbacks, options); 6 | 7 | // Additional call 8 | const api2 = qraftAPIClient(services, callbacks, { 9 | requestFn, 10 | baseUrl, 11 | queryClient, 12 | }); 13 | 14 | interface Services { 15 | service1: { 16 | operation1: { 17 | schema: any; 18 | }; 19 | }; 20 | } 21 | 22 | interface Callbacks { 23 | operation1: () => void; 24 | } 25 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getQueryKey.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationUseQuery, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIBasicClientOptions } from '../qraftAPIClient.js'; 7 | import { composeQueryKey } from '../lib/composeQueryKey.js'; 8 | 9 | export const getQueryKey = ( 10 | _qraftOptions: CreateAPIBasicClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationUseQuery< 14 | OperationSchema, 15 | unknown, 16 | unknown, 17 | DefaultError 18 | >['getQueryKey'] 19 | > 20 | ) => { 21 | return composeQueryKey(schema, args[0]); 22 | }; 23 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/getServiceNamesByOperationTags.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { getServiceNamesByOperationTags } from './getServiceNamesByOperationTags.js'; 3 | 4 | describe('getServiceNamesByOperationTags(...)', () => { 5 | it('should return all tags', () => { 6 | expect(getServiceNamesByOperationTags(['foo', 'bar'], 'fallback')).toEqual([ 7 | 'Foo', 8 | 'Bar', 9 | ]); 10 | }); 11 | 12 | it('should return fallback tags', () => { 13 | expect(getServiceNamesByOperationTags([], 'fallback')).toEqual([ 14 | 'Fallback', 15 | ]); 16 | expect(getServiceNamesByOperationTags(['--', '__'], 'fallback')).toEqual([ 17 | 'Fallback', 18 | ]); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /.github/workflows/update-search-engines.yml: -------------------------------------------------------------------------------- 1 | name: Update Algolia Index 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | workflow_run: 7 | workflows: ["pages build and deployment"] 8 | types: 9 | - completed 10 | 11 | jobs: 12 | update_algolia: 13 | runs-on: ubuntu-latest 14 | if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} 15 | environment: github-pages 16 | steps: 17 | - name: Update Algolia index 18 | uses: darrenjennings/algolia-docsearch-action@v0.2.0 19 | with: 20 | algolia_application_id: ${{ vars.ALGOLIA_APP_ID }} 21 | algolia_api_key: ${{ secrets.ALGOLIA_WRITE_API_KEY }} 22 | file: 'website/tools/algolia/config.json' 23 | -------------------------------------------------------------------------------- /packages/react-client/rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import { rollupConfig } from '@openapi-qraft/rollup-config'; 2 | import packageJson from './package.json' with { type: 'json' }; 3 | 4 | const moduleDist = { 5 | import: packageJson['exports']['.']['import'], 6 | require: packageJson['exports']['.']['require'], 7 | }; 8 | 9 | const config = [ 10 | rollupConfig(moduleDist, { input: 'src/index.ts' }), 11 | rollupConfig(moduleDist, { input: 'src/callbacks/index.ts' }), 12 | rollupConfig(moduleDist, { input: 'src/Unstable_QraftSecureRequestFn.ts' }), 13 | rollupConfig(moduleDist, { 14 | input: 'src/qraftPredefinedParametersRequestFn.ts', 15 | }), 16 | rollupConfig(moduleDist, { input: 'src/unstable__responseUtils.ts' }), 17 | ]; 18 | 19 | export default config; 20 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/migrate-to-v2.6.0-codemod/other-imports.tsx: -------------------------------------------------------------------------------- 1 | // Import from another package, should not be modified 2 | import { qraftAPIClient } from 'other-library'; 3 | 4 | // Same identifier but different source 5 | const api = qraftAPIClient(services, callbacks, options); 6 | 7 | // Local function with the same name 8 | function qraftAPIClient(a: T, b: K, c: any) { 9 | return { a, b, c }; 10 | } 11 | 12 | // Local function call should not be modified 13 | const localApi = qraftAPIClient(1, "test", {}); 14 | 15 | interface Services { 16 | service1: { 17 | operation1: { 18 | schema: any; 19 | }; 20 | }; 21 | } 22 | 23 | interface Callbacks { 24 | operation1: () => void; 25 | } -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": ["@changesets/cli/commit", { "skipCI": false }], 5 | "fixed": [ 6 | [ 7 | "@openapi-qraft/cli", 8 | "@openapi-qraft/plugin", 9 | "@openapi-qraft/tanstack-query-react-plugin", 10 | "@openapi-qraft/openapi-typescript-plugin", 11 | "@openapi-qraft/react", 12 | "@openapi-qraft/tanstack-query-react-types", 13 | "@openapi-qraft/eslint-plugin-query" 14 | ] 15 | ], 16 | "linked": [], 17 | "access": "public", 18 | "baseBranch": "origin/main", 19 | "updateInternalDependencies": "patch", 20 | "ignore": ["@openapi-qraft/e2e", "playground", "openapi-qraft-website"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getMutationKey.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationUseMutation, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIBasicClientOptions } from '../qraftAPIClient.js'; 7 | import { composeMutationKey } from '../lib/composeMutationKey.js'; 8 | 9 | export const getMutationKey = ( 10 | _qraftOptions: CreateAPIBasicClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationUseMutation< 14 | OperationSchema, 15 | unknown, 16 | unknown, 17 | unknown, 18 | DefaultError 19 | >['getMutationKey'] 20 | > 21 | ) => { 22 | return composeMutationKey(schema, args[0]); 23 | }; 24 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/parseOperationGlobs.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { parseOperationGlobs } from './parseOperationGlobs.js'; 3 | 4 | describe('parseOperationGlobs(...)', () => { 5 | it('parses valid operation methods', () => { 6 | expect(parseOperationGlobs('post /**')).toEqual({ 7 | methods: ['post'], 8 | pathGlobs: '/**', 9 | }); 10 | expect(parseOperationGlobs('get,post, put /**,/foo/bar')).toEqual({ 11 | methods: ['get', 'post', 'put'], 12 | pathGlobs: '/**,/foo/bar', 13 | }); 14 | }); 15 | 16 | it('skips invalid operation methods', () => { 17 | expect(parseOperationGlobs('post,fetch??,foo?? /**')).toEqual({ 18 | methods: ['post'], 19 | pathGlobs: '/**', 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/createServicePathMatch.ts: -------------------------------------------------------------------------------- 1 | import micromatch from 'micromatch'; 2 | 3 | /** 4 | * Create a function to match service paths 5 | * @param servicesGlob 6 | */ 7 | export const createServicePathMatch = (servicesGlob: string[]) => { 8 | const servicePathGlobs = servicesGlob.reduce< 9 | Record<'match' | 'ignore', string[]> 10 | >( 11 | (acc, glob) => { 12 | if (glob.startsWith('!')) acc.ignore.push(glob.slice(1)); 13 | else acc.match.push(glob); 14 | return acc; 15 | }, 16 | { 17 | match: [], 18 | ignore: [], 19 | } 20 | ); 21 | 22 | return function isServicePatchMatch(path: string) { 23 | return micromatch.isMatch(path, servicePathGlobs.match, { 24 | ignore: servicePathGlobs.ignore, 25 | }); 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "exclude": ["src/api/**/*", "src/kubb/**/*", "src/orval/**/*"], 25 | "references": [{ "path": "./tsconfig.node.json" }] 26 | } 27 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationGetInfiniteQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AreAllOptional, 3 | DeepReadonly, 4 | OperationInfiniteData, 5 | ServiceOperationInfiniteQueryKey, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | 8 | export interface ServiceOperationGetInfiniteQueryData< 9 | TSchema extends { url: string; method: string }, 10 | TOperationQueryFnData, 11 | TQueryParams, 12 | > { 13 | getInfiniteQueryData( 14 | parameters: 15 | | ServiceOperationInfiniteQueryKey 16 | | (AreAllOptional extends true 17 | ? DeepReadonly | void 18 | : DeepReadonly) 19 | ): OperationInfiniteData | undefined; 20 | } 21 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getInfiniteQueryKey.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationUseInfiniteQuery, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIBasicClientOptions } from '../qraftAPIClient.js'; 7 | import { composeInfiniteQueryKey } from '../lib/composeInfiniteQueryKey.js'; 8 | 9 | export const getInfiniteQueryKey = ( 10 | _qraftOptions: CreateAPIBasicClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationUseInfiniteQuery< 14 | OperationSchema, 15 | unknown, 16 | unknown, 17 | DefaultError 18 | >['getInfiniteQueryKey'] 19 | > 20 | ) => { 21 | return composeInfiniteQueryKey(schema, args[0]); 22 | }; 23 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/replaceRefParametersWithComponent.ts: -------------------------------------------------------------------------------- 1 | import type { OpenAPI3, ReferenceObject } from 'openapi-typescript'; 2 | import { ParameterObject } from 'openapi-typescript'; 3 | import { resolveDocumentLocalRef } from './resolveDocumentLocalRef.js'; 4 | 5 | export function replaceRefParametersWithComponent( 6 | parameters: ParameterObject | ReferenceObject | undefined, 7 | openApiJson: OpenAPI3 8 | ) { 9 | if (!Array.isArray(parameters)) return undefined; 10 | 11 | const definedParameters = parameters 12 | .map((parameter) => 13 | parameter.$ref 14 | ? resolveDocumentLocalRef(parameter.$ref, openApiJson) 15 | : parameter 16 | ) 17 | .filter(Boolean); 18 | 19 | if (!definedParameters.length) return undefined; 20 | 21 | return definedParameters; 22 | } 23 | -------------------------------------------------------------------------------- /packages/react-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "lib": ["ES2019", "DOM", "DOM.Iterable", "ES2022.Error", "ES2022.Array"], 8 | "jsx": "react", 9 | "verbatimModuleSyntax": true, 10 | "paths": { 11 | "@openapi-qraft/react": ["./src/index.ts"], 12 | "@openapi-qraft/react/callbacks/index": ["./src/callbacks/index.ts"], 13 | "@openapi-qraft/react/Unstable_QraftSecureRequestFn": ["./src/Unstable_QraftSecureRequestFn.ts"] 14 | } 15 | }, 16 | "include": ["src/**/*"], 17 | "exclude": [ 18 | "**/node_modules", 19 | "**/.*/", 20 | "src/tests/fixtures/migrate-to-v2-codemod/**/*", 21 | "src/tests/fixtures/migrate-to-v2.6.0-codemod/**/*" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /website/docs/query-client/prefetchInfiniteQuery.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: prefetchInfiniteQuery() 3 | --- 4 | 5 | # prefetchInfiniteQuery(...) 6 | 7 | The method facilitates the fetching of paginated data. 8 | See TanStack [_queryClient.prefetchInfiniteQuery 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientprefetchinfinitequery) 9 | documentation for more details. 10 | 11 | ```ts 12 | const result = qraft...prefetchInfiniteQuery( 13 | { 14 | parameters, 15 | requestFn, 16 | baseUrl, 17 | ...prefetchInfiniteQueryOptions, 18 | } 19 | ); 20 | ``` 21 | 22 | ### Arguments 23 | 24 | See [fetchInfiniteQuery](fetchInfiniteQuery.mdx) for the list of arguments. 25 | 26 | ### Returns 27 | 28 | `Promise` - a promise that resolves when the query is successfully fetched 29 | -------------------------------------------------------------------------------- /website/docs/query-client/prefetchQuery.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: prefetchQuery() 3 | --- 4 | 5 | # prefetchQuery(...) 6 | 7 | The method allows you to fetch data and cache it before it's needed. 8 | To understand how `prefetchQuery` handles data and cache management, 9 | refer to the TanStack [_queryClient.prefetchQuery 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientprefetchquery) documentation. 10 | 11 | ```ts 12 | const result = qraft...prefetchQuery( 13 | { 14 | parameters, 15 | requestFn, 16 | baseUrl, 17 | ...prefetchQueryOptions, 18 | } 19 | ); 20 | ``` 21 | 22 | ### Arguments 23 | 24 | See [_fetchQuery(...)_](fetchQuery.mdx) for the full list of arguments. 25 | 26 | ### Returns 27 | 28 | `Promise` - a promise that resolves when the query is successfully cached 29 | -------------------------------------------------------------------------------- /packages/react-client/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | qraftAPIClient, 3 | type CreateAPIClientOptions, 4 | type CreateAPIBasicQueryClientOptions, 5 | type CreateAPIBasicClientOptions, 6 | type CreateAPIQueryClientOptions, 7 | type APIQueryClientServices, 8 | type APIDefaultQueryClientServices, 9 | type APIBasicQueryClientServices, 10 | type APIBasicClientServices, 11 | type APIUtilityClientServices, 12 | type UnionServiceOperationsDeclaration, 13 | type QraftClientOptions, 14 | } from './qraftAPIClient.js'; 15 | export { 16 | requestFn, 17 | baseRequestFn, 18 | urlSerializer, 19 | bodySerializer, 20 | mergeHeaders, 21 | type RequestFn, 22 | type RequestFnResponse, 23 | type HeadersOptions, 24 | type RequestFnOptions, 25 | type RequestFnInfo, 26 | type OperationSchema, 27 | type RequestFnPayload, 28 | } from './lib/requestFn.js'; 29 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/ts-factory/OverrideImportType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Allows you to override standard type imports by specifying custom paths for them. 3 | * 4 | * @example 5 | * ```ts 6 | * { 7 | * services: { 8 | * '@openapi-qraft/tanstack-query-react-types': { 9 | * OperationError: '../custom/types/ErrorType.js', 10 | * RequestFn: '../custom/types/ApiClient.js', 11 | * }, 12 | * '@openapi-qraft/react': { 13 | * Result: '../custom/types/ApiResult.js', 14 | * }, 15 | * }, 16 | * 'create-api-client': { 17 | * '@openapi-qraft/react': { 18 | * CreateAPIQueryClientOptions: 19 | * '../custom/types/CreateAPIQueryClientOptions', 20 | * }, 21 | * }, 22 | * } 23 | **/ 24 | export type OverrideImportType = Record< 25 | string, 26 | Record> 27 | >; 28 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationRemoveQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | QueryFiltersByParameters, 3 | QueryFiltersByQueryKey, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | 6 | export interface ServiceOperationRemoveQueries< 7 | TSchema extends { url: string; method: string }, 8 | TOperationQueryFnData, 9 | TQueryParams, 10 | TError, 11 | > { 12 | removeQueries( 13 | filters?: 14 | | QueryFiltersByParameters< 15 | TSchema, 16 | TOperationQueryFnData, 17 | TInfinite, 18 | TQueryParams, 19 | TError 20 | > 21 | | QueryFiltersByQueryKey< 22 | TSchema, 23 | TOperationQueryFnData, 24 | TInfinite, 25 | TQueryParams, 26 | TError 27 | > 28 | ): void; 29 | } 30 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/prefetchInfiniteQuery.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: prefetchInfiniteQuery() 3 | --- 4 | 5 | # prefetchInfiniteQuery(...) 6 | 7 | The method facilitates the fetching of paginated data. 8 | See TanStack [_queryClient.prefetchInfiniteQuery 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientprefetchinfinitequery) 9 | documentation for more details. 10 | 11 | ```ts 12 | const result = qraft...prefetchInfiniteQuery( 13 | { 14 | parameters, 15 | requestFn, 16 | baseUrl, 17 | ...prefetchInfiniteQueryOptions, 18 | }, 19 | queryClient 20 | ); 21 | ``` 22 | 23 | ### Arguments 24 | 25 | See [fetchInfiniteQuery](fetchInfiniteQuery.mdx) for the list of arguments. 26 | 27 | ### Returns 28 | 29 | `Promise` - a promise that resolves when the query is successfully fetched 30 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationGetQueryData, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 6 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientMethodWithQueryKey.js'; 7 | 8 | export function getQueryData( 9 | qraftOptions: CreateAPIQueryClientOptions, 10 | schema: OperationSchema, 11 | args: Parameters< 12 | ServiceOperationGetQueryData< 13 | OperationSchema, 14 | unknown, 15 | TData 16 | >['getQueryData'] 17 | > 18 | ): TData | undefined { 19 | return callQueryClientMethodWithQueryKey( 20 | qraftOptions, 21 | 'getQueryData', 22 | schema, 23 | false, 24 | // @ts-expect-error - Too complex to type 25 | args 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/setQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationSetQueryData, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 6 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientMethodWithQueryKey.js'; 7 | 8 | export function setQueryData( 9 | qraftOptions: CreateAPIQueryClientOptions, 10 | schema: OperationSchema, 11 | args: Parameters< 12 | ServiceOperationSetQueryData< 13 | OperationSchema, 14 | unknown, 15 | TData 16 | >['setQueryData'] 17 | > 18 | ): TData | undefined { 19 | return callQueryClientMethodWithQueryKey( 20 | qraftOptions, 21 | 'setQueryData', 22 | schema, 23 | false, 24 | // @ts-expect-error - Too complex to type 25 | args 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationIsFetchingQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | QueryFiltersByParameters, 3 | QueryFiltersByQueryKey, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | 6 | export interface ServiceOperationIsFetchingQueries< 7 | TSchema extends { url: string; method: string }, 8 | TOperationQueryFnData, 9 | TQueryParams, 10 | TError, 11 | > { 12 | isFetching( 13 | filters?: 14 | | QueryFiltersByParameters< 15 | TSchema, 16 | TOperationQueryFnData, 17 | TInfinite, 18 | TQueryParams, 19 | TError 20 | > 21 | | QueryFiltersByQueryKey< 22 | TSchema, 23 | TOperationQueryFnData, 24 | TInfinite, 25 | TQueryParams, 26 | TError 27 | > 28 | ): number; 29 | } 30 | -------------------------------------------------------------------------------- /playground/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js'; 2 | import reactHooks from 'eslint-plugin-react-hooks'; 3 | import reactRefresh from 'eslint-plugin-react-refresh'; 4 | import globals from 'globals'; 5 | import tseslint from 'typescript-eslint'; 6 | 7 | export default tseslint.config( 8 | { ignores: ['dist', 'src/api'] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ['**/*.{ts,tsx}'], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | 'react-hooks': reactHooks, 18 | 'react-refresh': reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | 'react-refresh/only-export-components': [ 23 | 'warn', 24 | { allowConstantExport: true }, 25 | ], 26 | }, 27 | } 28 | ); 29 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/prefetchQuery.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: prefetchQuery() 3 | --- 4 | 5 | # prefetchQuery(...) 6 | 7 | The method allows you to fetch data and cache it before it's needed. 8 | To understand how `prefetchQuery` handles data and cache management, 9 | refer to the TanStack [_queryClient.prefetchQuery 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientprefetchquery) documentation. 10 | 11 | ```ts 12 | const result = qraft...prefetchQuery( 13 | { 14 | parameters, 15 | requestFn, 16 | baseUrl, 17 | ...prefetchQueryOptions, 18 | }, 19 | queryClient 20 | ); 21 | ``` 22 | 23 | ### Arguments 24 | 25 | See [_fetchQuery(...)_](fetchQuery.mdx) for the full list of arguments. 26 | 27 | ### Returns 28 | 29 | `Promise` - a promise that resolves when the query is successfully cached 30 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationUseIsFetchingQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | QueryFiltersByParameters, 3 | QueryFiltersByQueryKey, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | 6 | export interface ServiceOperationUseIsFetchingQueries< 7 | TSchema extends { url: string; method: string }, 8 | TOperationQueryFnData, 9 | TQueryParams, 10 | TError, 11 | > { 12 | useIsFetching( 13 | filters?: 14 | | QueryFiltersByParameters< 15 | TSchema, 16 | TOperationQueryFnData, 17 | TInfinite, 18 | TQueryParams, 19 | TError 20 | > 21 | | QueryFiltersByQueryKey< 22 | TSchema, 23 | TOperationQueryFnData, 24 | TInfinite, 25 | TQueryParams, 26 | TError 27 | > 28 | ): number; 29 | } 30 | -------------------------------------------------------------------------------- /.github/workflows/versioning.yml: -------------------------------------------------------------------------------- 1 | name: Versioning 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | release: 10 | name: Changesets Versioning 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: write 14 | pull-requests: write 15 | steps: 16 | - name: Checkout Repo 17 | uses: actions/checkout@v4 18 | 19 | - name: Setup Node.js 20.x 20 | uses: actions/setup-node@v4 21 | with: 22 | cache: 'yarn' 23 | node-version: 20.12.2 24 | 25 | - name: Install Dependencies 26 | run: yarn install --immutable 27 | 28 | - name: Create Version Packages Pull Request 29 | id: changesets 30 | uses: changesets/action@v1 31 | with: 32 | version: yarn exec .changeset/version.sh 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationUseQueries.ts: -------------------------------------------------------------------------------- 1 | import type { UseQueryOptionsForUseQueries } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { UseQueryResult } from '@tanstack/react-query'; 3 | 4 | export interface ServiceOperationUseQueries< 5 | TSchema extends { url: string; method: string }, 6 | TOperationQueryFnData, 7 | TQueryParams, 8 | TError, 9 | > { 10 | useQueries< 11 | T extends Array< 12 | UseQueryOptionsForUseQueries< 13 | TSchema, 14 | TQueryParams, 15 | TOperationQueryFnData, 16 | TError 17 | > 18 | >, 19 | TCombinedResult = Array>, 20 | >(options: { 21 | queries: T; 22 | combine?: ( 23 | results: Array> 24 | ) => TCombinedResult; 25 | }): TCombinedResult; 26 | } 27 | -------------------------------------------------------------------------------- /e2e/bin/lib/find-monorepo-root.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs'; 2 | import { resolve } from 'node:path'; 3 | import process from 'node:process'; 4 | 5 | /** 6 | * Find the root of the monorepo by looking for package.json with "workspaces" 7 | * 8 | * @param baseDir 9 | * @return {string|undefined} 10 | */ 11 | export function findMonorepoRoot(baseDir = process.cwd()) { 12 | const packageJsonPath = resolve(baseDir, 'package.json'); 13 | if (fs.existsSync(packageJsonPath)) { 14 | const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString()); 15 | if (packageJson.workspaces) { 16 | return baseDir; 17 | } 18 | } 19 | 20 | const parentDir = resolve(baseDir, '..'); 21 | if (baseDir === parentDir) { 22 | throw new Error( 23 | 'Reached the root of the disk or path, but package.json was not found' 24 | ); 25 | } 26 | 27 | return findMonorepoRoot(parentDir); 28 | } 29 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/createTestJwt.ts: -------------------------------------------------------------------------------- 1 | export function createTestJwt(payload: { exp: number; iat: number }) { 2 | function base64url(source: string) { 3 | // Encode in base64 4 | let encodedSource = Buffer.from(source).toString('base64'); 5 | 6 | // Replace characters to get base64url 7 | encodedSource = encodedSource.replace(/=+$/, ''); 8 | encodedSource = encodedSource.replace(/\+/g, '-'); 9 | encodedSource = encodedSource.replace(/\//g, '_'); 10 | 11 | return encodedSource; 12 | } 13 | 14 | // Token header 15 | const header = { 16 | alg: 'none', 17 | typ: 'JWT', 18 | }; 19 | 20 | // Encode header and payload in base64url 21 | const encodedHeader = base64url(JSON.stringify(header)); 22 | const encodedPayload = base64url(JSON.stringify(payload)); 23 | 24 | // Create token without signature 25 | return `${encodedHeader}.${encodedPayload}.`; 26 | } 27 | -------------------------------------------------------------------------------- /write-package-version-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Creates a file with the package version 4 | # Package version is read from `package.json` and written to `src/packageVersion.ts` 5 | # relative to the package. `packageVersion.ts` could be used to retrieve the package version 6 | # without need to read `package.json` and include it in the build output. 7 | # Usage example (run from the root of the monorepo): 8 | # ```bash 9 | # (cd packages/sdk-api && yarn exec ../../write-package-version-file.sh) 10 | # ``` 11 | 12 | if [ ! -f ./package.json ]; then 13 | echo "package.json not found" >&2 14 | exit 1 15 | fi 16 | 17 | PACKAGE_VERSION=$(node -p 'require("./package.json").version') 18 | OUTPUT_FILE="./src/packageVersion.ts" 19 | 20 | # Write package version to file 21 | echo "// This file was generated automatically" > "$OUTPUT_FILE" 22 | echo "export const packageVersion = '$PACKAGE_VERSION';" >> "$OUTPUT_FILE" 23 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/resetQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationResetQueries, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js'; 8 | 9 | export function resetQueries( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationResetQueries< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['resetQueries'] 19 | > 20 | ): Promise { 21 | return callQueryClientMethodWithQueryFilters( 22 | qraftOptions, 23 | 'resetQueries', 24 | schema, 25 | args as never 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/cancelQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationCancelQueries, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js'; 8 | 9 | export function cancelQueries( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationCancelQueries< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['cancelQueries'] 19 | > 20 | ): Promise { 21 | return callQueryClientMethodWithQueryFilters( 22 | qraftOptions, 23 | 'cancelQueries', 24 | schema, 25 | args as never 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/isFetching.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationIsFetchingQueries, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js'; 8 | 9 | export function isFetching( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationIsFetchingQueries< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['isFetching'] 19 | > 20 | ): Promise { 21 | return callQueryClientMethodWithQueryFilters( 22 | qraftOptions, 23 | 'isFetching', 24 | schema, 25 | args as never 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/removeQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationRemoveQueries, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js'; 8 | 9 | export function removeQueries( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationRemoveQueries< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['removeQueries'] 19 | > 20 | ): Promise { 21 | return callQueryClientMethodWithQueryFilters( 22 | qraftOptions, 23 | 'removeQueries', 24 | schema, 25 | args as never 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getQueriesData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationGetQueriesData, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js'; 8 | 9 | export function getQueriesData( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationGetQueriesData< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['getQueriesData'] 19 | > 20 | ): TData | undefined { 21 | return callQueryClientMethodWithQueryFilters( 22 | qraftOptions, 23 | 'getQueriesData', 24 | schema, 25 | args as never 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/refetchQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationRefetchQueries, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js'; 8 | 9 | export function refetchQueries( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationRefetchQueries< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['refetchQueries'] 19 | > 20 | ): Promise { 21 | return callQueryClientMethodWithQueryFilters( 22 | qraftOptions, 23 | 'refetchQueries', 24 | schema, 25 | args as never 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/setQueriesData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationSetQueriesData, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js'; 8 | 9 | export function setQueriesData( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationSetQueriesData< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['setQueriesData'] 19 | > 20 | ): TData | undefined { 21 | return callQueryClientMethodWithQueryFilters( 22 | qraftOptions, 23 | 'setQueriesData', 24 | schema, 25 | args as never 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/lib/shelfMerge.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Merges objects with provided depth 3 | * @param depth 4 | * @param args 5 | */ 6 | export function shelfMerge(depth = 2, ...args: T[]): T { 7 | return args.reduce((acc, arg) => { 8 | if (!arg || typeof arg !== 'object') return acc; 9 | 10 | Object.entries(arg).forEach(([key, value]) => { 11 | if (typeof value !== 'object') { 12 | acc[key as never] = value as never; 13 | return; 14 | } 15 | 16 | if (Array.isArray(value)) { 17 | acc[key as never] = value as never; 18 | return; 19 | } 20 | 21 | if (depth > 1) { 22 | acc[key as never] = shelfMerge( 23 | depth - 1, 24 | acc[key as never], 25 | value 26 | ) as never; 27 | return; 28 | } 29 | 30 | acc[key as never] = value as never; 31 | }); 32 | 33 | return acc; 34 | }, {} as T); 35 | } 36 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/index.ts.snapshot.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by @openapi-qraft/cli. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | import type { EntitiesService } from "./EntitiesService.js"; 7 | import { entitiesService } from "./EntitiesService.js"; 8 | import type { ApprovalPoliciesService } from "./ApprovalPoliciesService.js"; 9 | import { approvalPoliciesService } from "./ApprovalPoliciesService.js"; 10 | import type { FilesService } from "./FilesService.js"; 11 | import { filesService } from "./FilesService.js"; 12 | export type Services = { 13 | entities: EntitiesService; 14 | approvalPolicies: ApprovalPoliciesService; 15 | files: FilesService; 16 | }; 17 | export const services = { 18 | entities: entitiesService, 19 | approvalPolicies: approvalPoliciesService, 20 | files: filesService 21 | } as const; 22 | -------------------------------------------------------------------------------- /e2e/bin/update-projects-from-private-registry.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -o errexit 4 | 5 | BASE_DIR=$(dirname "$(readlink -f "$0")") 6 | 7 | # Include shared functions 8 | . "$BASE_DIR/lib/private-registry-functions.sh" 9 | 10 | # Update projects with workspace packages 11 | # Usage: update_projects_with_workspace_packages 12 | update_projects_with_workspace_packages() { 13 | projects_dir="$1" 14 | node -e "import('$BASE_DIR/lib/update-projects-with-workspace-packages.mjs').then(({updateProjectsWithWorkspacePackages}) => updateProjectsWithWorkspacePackages('$projects_dir'))" 15 | echo "Projects updated with workspace packages." 16 | } 17 | 18 | # Cleanup on exit or interrupt 19 | trap 'stop_private_registry' INT EXIT 20 | 21 | start_private_registry 22 | NPM_PUBLISH_REGISTRY="${NPM_PUBLISH_REGISTRY:-http://localhost:4873/}" update_projects_with_workspace_packages "${TEST_PROJECTS_DIR:-"$BASE_DIR/../projects"}" 23 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/UseQueryOptionsForUseSuspenseQuery.ts: -------------------------------------------------------------------------------- 1 | import type { UseQueryOptions } from '@tanstack/react-query'; 2 | import type { DeepReadonly } from './DeepReadonly.js'; 3 | import type { ServiceOperationQueryKey } from './ServiceOperationKey.js'; 4 | 5 | export type UseQueryOptionsForUseSuspenseQuery< 6 | TSchema extends { url: string; method: string }, 7 | TParams, 8 | TQueryFnData, 9 | TError, 10 | TData = TQueryFnData, 11 | > = Omit< 12 | UseQueryOptions< 13 | TQueryFnData, 14 | TError, 15 | TData, 16 | ServiceOperationQueryKey 17 | >, 18 | 'enabled' | 'throwOnError' | 'placeholderData' | 'queryKey' 19 | > & 20 | ( 21 | | { 22 | parameters: DeepReadonly; 23 | queryKey?: never; 24 | } 25 | | { 26 | queryKey: ServiceOperationQueryKey; 27 | parameters?: never; 28 | } 29 | ); 30 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationIsMutatingQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | MutationFiltersByMutationKey, 3 | MutationFiltersByParameters, 4 | OperationError, 5 | } from '@openapi-qraft/tanstack-query-react-types'; 6 | 7 | export interface ServiceOperationIsMutatingQueries< 8 | TSchema extends { url: string; method: string }, 9 | TBody, 10 | TMutationData, 11 | TMutationParams, 12 | TError, 13 | > { 14 | isMutating( 15 | filters?: 16 | | MutationFiltersByParameters< 17 | TBody, 18 | TMutationData, 19 | TMutationParams, 20 | OperationError, 21 | TContext 22 | > 23 | | MutationFiltersByMutationKey< 24 | TSchema, 25 | TBody, 26 | TMutationData, 27 | TMutationParams, 28 | OperationError, 29 | TContext 30 | > 31 | ): number; 32 | } 33 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/src/utils/get-root-identifier.ts: -------------------------------------------------------------------------------- 1 | import type { TSESTree } from '@typescript-eslint/utils'; 2 | import { AST_NODE_TYPES } from '@typescript-eslint/utils'; 3 | 4 | export function getRootIdentifier( 5 | node: TSESTree.Node 6 | ): TSESTree.Identifier | undefined { 7 | let current: TSESTree.Node | undefined = node; 8 | while ( 9 | current.type === AST_NODE_TYPES.MemberExpression || 10 | current.type === AST_NODE_TYPES.TSNonNullExpression || 11 | current.type === AST_NODE_TYPES.ChainExpression 12 | ) { 13 | if (current.type === AST_NODE_TYPES.MemberExpression) { 14 | current = current.object; 15 | continue; 16 | } 17 | if (current.type === AST_NODE_TYPES.TSNonNullExpression) { 18 | current = current.expression; 19 | continue; 20 | } 21 | 22 | current = current.expression; 23 | } 24 | return current.type === AST_NODE_TYPES.Identifier ? current : undefined; 25 | } 26 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/invalidateQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationInvalidateQueries, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js'; 8 | 9 | export function invalidateQueries( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationInvalidateQueries< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['invalidateQueries'] 19 | > 20 | ): Promise { 21 | return callQueryClientMethodWithQueryFilters( 22 | qraftOptions, 23 | 'invalidateQueries', 24 | schema, 25 | args as never 26 | ) as never; 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/isMutating.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationIsMutatingQueries, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithMutationFilters } from '../lib/callQueryClientMethodWithMutationFilters.js'; 8 | 9 | export function isMutating( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationIsMutatingQueries< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | unknown, 18 | DefaultError 19 | >['isMutating'] 20 | > 21 | ): Promise { 22 | return callQueryClientMethodWithMutationFilters( 23 | qraftOptions, 24 | 'isMutating', 25 | schema, 26 | args as never 27 | ) as never; 28 | } 29 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationUseIsMutating.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | MutationFiltersByMutationKey, 3 | MutationFiltersByParameters, 4 | OperationError, 5 | } from '@openapi-qraft/tanstack-query-react-types'; 6 | 7 | export interface ServiceOperationUseIsMutating< 8 | TSchema extends { url: string; method: string }, 9 | TBody, 10 | TMutationData, 11 | TMutationParams, 12 | TError, 13 | > { 14 | useIsMutating( 15 | filters?: 16 | | MutationFiltersByParameters< 17 | TBody, 18 | TMutationData, 19 | TMutationParams, 20 | OperationError, 21 | TContext 22 | > 23 | | MutationFiltersByMutationKey< 24 | TSchema, 25 | TBody, 26 | TMutationData, 27 | TMutationParams, 28 | OperationError, 29 | TContext 30 | > 31 | ): number; 32 | } 33 | -------------------------------------------------------------------------------- /.changeset/version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -o errexit 3 | 4 | yarn changeset version 5 | 6 | # Check if the .changeset/pre.json file exists, then add it to the staged files 7 | if [ -f ".changeset/pre.json" ]; then 8 | echo "Found '.changeset/pre.json' file..." 9 | git add ".changeset/pre.json" >> /dev/null 10 | # Check if the .changeset/pre.json file has been deleted but not staged 11 | elif git ls-files --deleted | grep -q ".changeset/pre.json"; then 12 | echo "Found deletion of '.changeset/pre.json' file..." 13 | git add ".changeset/pre.json" >> /dev/null 14 | else 15 | echo "No '.changeset/pre.json' file found." 16 | fi 17 | 18 | # Check if the .changeset/pre.json is present in the staged files (it could be also deleted) 19 | if git diff --staged --name-only | grep -q ".changeset/pre.json"; then 20 | git commit --amend --no-edit --no-verify >> /dev/null 21 | echo "Changes to '.changeset/pre.json' amended to the previous commit!" 22 | fi 23 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/openapi-typescript-redoc.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'openapi-typescript/dist/lib/redoc.js' { 2 | import type { 3 | Document, 4 | Config as RedoclyConfig, 5 | } from '@redocly/openapi-core'; 6 | import type { OpenAPI3 } from 'openapi-typescript'; 7 | import { Readable } from 'node:stream'; 8 | import { BaseResolver } from '@redocly/openapi-core'; 9 | 10 | export interface ValidateAndBundleOptions { 11 | redoc: RedoclyConfig; 12 | silent: boolean; 13 | cwd?: URL; 14 | } 15 | interface ParseSchemaOptions { 16 | absoluteRef: string; 17 | resolver: BaseResolver; 18 | } 19 | export declare function parseSchema( 20 | schema: unknown, 21 | { absoluteRef, resolver }: ParseSchemaOptions 22 | ): Promise; 23 | export declare function validateAndBundle( 24 | source: string | URL | OpenAPI3 | Readable | Buffer, 25 | options: ValidateAndBundleOptions 26 | ): Promise; 27 | } 28 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | mainDocsSidebar: [{ type: 'autogenerated', dirName: '.' }], 18 | 19 | // But you can create a sidebar manually 20 | /** 21 | * tutorialSidebar: [ 22 | * 'intro', 23 | * 'hello', 24 | * { 25 | * type: 'category', 26 | * label: 'Tutorial', 27 | * items: ['tutorial-basics/create-a-document'], 28 | * }, 29 | * ], 30 | */ 31 | }; 32 | 33 | export default sidebars; 34 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ```bash 8 | yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ```bash 14 | yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ```bash 22 | yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ```bash 32 | USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ```bash 38 | GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getQueryState.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationGetQueryState, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientMethodWithQueryKey.js'; 8 | 9 | export function getQueryState( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationGetQueryState< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['getQueryState'] 19 | > 20 | ): TData | undefined { 21 | return callQueryClientMethodWithQueryKey( 22 | qraftOptions, 23 | 'getQueryState', 24 | schema, 25 | false, 26 | // @ts-expect-error - Too complex to type 27 | args 28 | ) as never; 29 | } 30 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationResetQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | QueryFiltersByParameters, 3 | QueryFiltersByQueryKey, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { ResetOptions } from '@tanstack/react-query'; 6 | 7 | export interface ServiceOperationResetQueries< 8 | TSchema extends { url: string; method: string }, 9 | TOperationQueryFnData, 10 | TQueryParams, 11 | TError, 12 | > { 13 | resetQueries( 14 | filters?: 15 | | QueryFiltersByParameters< 16 | TSchema, 17 | TOperationQueryFnData, 18 | TInfinite, 19 | TQueryParams, 20 | TError 21 | > 22 | | QueryFiltersByQueryKey< 23 | TSchema, 24 | TOperationQueryFnData, 25 | TInfinite, 26 | TQueryParams, 27 | TError 28 | >, 29 | options?: ResetOptions 30 | ): Promise; 31 | } 32 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Main Suite 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - '*' 7 | push: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | validate: 13 | timeout-minutes: 10 14 | runs-on: ubuntu-latest 15 | name: Validate Build 16 | steps: 17 | - name: Checkout Repo 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Setup Node.js 20.x 23 | uses: actions/setup-node@v4 24 | with: 25 | cache: 'yarn' 26 | node-version: 20.12.2 27 | 28 | - name: Install Dependencies 29 | run: yarn install --immutable 30 | 31 | - name: Build 32 | run: yarn build 33 | 34 | - name: Unit Testing 35 | run: yarn test 36 | 37 | - name: Linting 38 | run: yarn lint 39 | 40 | - name: Type Checking 41 | run: yarn typecheck 42 | 43 | - name: Run Knip 44 | run: yarn knip 45 | -------------------------------------------------------------------------------- /.github/workflows/docs-validation.yml: -------------------------------------------------------------------------------- 1 | name: Docs Validation 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | # Review gh actions docs if you want to further define triggers, paths, etc 8 | # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on 9 | 10 | jobs: 11 | install: 12 | name: Lint and Build Docs 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout Repo 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Setup Node.js 20.x 21 | uses: actions/setup-node@v4 22 | with: 23 | cache: 'yarn' 24 | node-version: 20.12.2 25 | 26 | - name: Install dependencies 27 | run: yarn install --immutable 28 | 29 | - name: Lint 30 | run: yarn workspace openapi-qraft-website run lint 31 | 32 | - name: Build 33 | run: yarn workspace openapi-qraft-website run build 34 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationCancelQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | QueryFiltersByParameters, 3 | QueryFiltersByQueryKey, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { CancelOptions } from '@tanstack/react-query'; 6 | 7 | export interface ServiceOperationCancelQueries< 8 | TSchema extends { url: string; method: string }, 9 | TOperationQueryFnData, 10 | TQueryParams, 11 | TError, 12 | > { 13 | cancelQueries( 14 | filters?: 15 | | QueryFiltersByParameters< 16 | TSchema, 17 | TOperationQueryFnData, 18 | TInfinite, 19 | TQueryParams, 20 | TError 21 | > 22 | | QueryFiltersByQueryKey< 23 | TSchema, 24 | TOperationQueryFnData, 25 | TInfinite, 26 | TQueryParams, 27 | TError 28 | >, 29 | options?: CancelOptions 30 | ): Promise; 31 | } 32 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationSetQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AreAllOptional, 3 | DeepReadonly, 4 | ServiceOperationQueryKey, 5 | } from '@openapi-qraft/tanstack-query-react-types'; 6 | import type { NoInfer, SetDataOptions, Updater } from '@tanstack/react-query'; 7 | 8 | export interface ServiceOperationSetQueryData< 9 | TSchema extends { url: string; method: string }, 10 | TOperationQueryFnData, 11 | TQueryParams, 12 | > { 13 | setQueryData( 14 | parameters: 15 | | (AreAllOptional extends true 16 | ? DeepReadonly | undefined 17 | : DeepReadonly) 18 | | ServiceOperationQueryKey, 19 | updater: Updater< 20 | NoInfer | undefined, 21 | NoInfer> | undefined 22 | >, 23 | options?: SetDataOptions 24 | ): TOperationQueryFnData | undefined; 25 | } 26 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationRefetchQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | QueryFiltersByParameters, 3 | QueryFiltersByQueryKey, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { RefetchOptions } from '@tanstack/react-query'; 6 | 7 | export interface ServiceOperationRefetchQueries< 8 | TSchema extends { url: string; method: string }, 9 | TOperationQueryFnData, 10 | TQueryParams, 11 | TError, 12 | > { 13 | refetchQueries( 14 | filters?: 15 | | QueryFiltersByParameters< 16 | TSchema, 17 | TOperationQueryFnData, 18 | TInfinite, 19 | TQueryParams, 20 | TError 21 | > 22 | | QueryFiltersByQueryKey< 23 | TSchema, 24 | TOperationQueryFnData, 25 | TInfinite, 26 | TQueryParams, 27 | TError 28 | >, 29 | options?: RefetchOptions 30 | ): Promise; 31 | } 32 | -------------------------------------------------------------------------------- /e2e/bin/unpublish-from-private-registry.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -o errexit 4 | 5 | BASE_DIR=$(dirname "$(readlink -f "$0")") 6 | 7 | # Include shared functions 8 | . "$BASE_DIR/lib/private-registry-functions.sh" 9 | 10 | # Publish packages to Verdaccio 11 | unpublish_from_registry() { 12 | echo "Unpublishing packages from private registry..." 13 | 14 | if [ -z "$NPM_PUBLISH_SCOPES" ]; then 15 | echo "Error: NPM_PUBLISH_SCOPES is not set." 16 | exit 1 17 | fi 18 | 19 | for scope in $NPM_PUBLISH_SCOPES; do 20 | from_flags="$from_flags --from '@${scope}/*'" 21 | done 22 | 23 | sh -c "(cd '$(monorepo_root)' && yarn workspaces foreach --recursive -t --no-private \ 24 | $from_flags \ 25 | exec npm unpublish --force --registry '${NPM_PUBLISH_REGISTRY:-http://localhost:4873/}')" 26 | } 27 | 28 | # Cleanup on exit or interrupt 29 | trap 'stop_private_registry' INT EXIT 30 | 31 | start_private_registry 32 | unpublish_from_registry 33 | stop_private_registry 34 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/fetchQuery.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationFetchQuery } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { DefaultError } from '@tanstack/react-query'; 3 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 4 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientFetchMethod.js'; 5 | 6 | export const fetchQuery: < 7 | TSchema extends { url: string; method: 'get' | 'head' | 'options' }, 8 | TData, 9 | TParams, 10 | >( 11 | qraftOptions: CreateAPIQueryClientOptions, 12 | schema: TSchema, 13 | args: Parameters< 14 | ServiceOperationFetchQuery< 15 | TSchema, 16 | TData, 17 | TParams, 18 | DefaultError 19 | >['fetchQuery'] 20 | > 21 | ) => Promise = (qraftOptions, schema, args) => { 22 | return callQueryClientMethodWithQueryKey( 23 | qraftOptions, 24 | 'fetchQuery', 25 | schema, 26 | false, 27 | args as never 28 | ) as never; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './AreAllOptional.js'; 2 | export type * from './DeepReadonly.js'; 3 | export type * from './InvalidateQueryFilters.js'; 4 | export type * from './MutationFilters.js'; 5 | export type * from './OperationInfiniteData.js'; 6 | export type * from './PartialParameters.js'; 7 | export type * from './QueryFilters.js'; 8 | export type * from './RequestFn.js'; 9 | export type * from './ServiceOperationFetchInfiniteQueryOptions.js'; 10 | export type * from './ServiceOperationFetchQueryOptions.js'; 11 | export type * from './ServiceOperationKey.js'; 12 | export type * from './ServiceOperationMutation.js'; 13 | export type * from './ServiceOperationQuery.js'; 14 | export type * from './UseQueryOptionsForUseQueries.js'; 15 | export type * from './UseQueryOptionsForUseSuspenseQuery.js'; 16 | export type * from './WithOptional.js'; 17 | export type * from './QraftServiceOperationsToken.js'; 18 | export type * from './OperationError.js'; 19 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getInfiniteQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationGetInfiniteQueryData, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { InfiniteData } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientMethodWithQueryKey.js'; 8 | 9 | export function getInfiniteQueryData( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationGetInfiniteQueryData< 14 | OperationSchema, 15 | unknown, 16 | TData 17 | >['getInfiniteQueryData'] 18 | > 19 | ): InfiniteData | undefined { 20 | return callQueryClientMethodWithQueryKey( 21 | qraftOptions, 22 | 'getQueryData', 23 | schema, 24 | true, 25 | // @ts-expect-error - Too complex to type 26 | args 27 | ) as never; 28 | } 29 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getInfiniteQueryState.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationGetQueryState, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { DefaultError } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientMethodWithQueryKey.js'; 8 | 9 | export function getInfiniteQueryState( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationGetQueryState< 14 | OperationSchema, 15 | unknown, 16 | TData, 17 | DefaultError 18 | >['getInfiniteQueryState'] 19 | > 20 | ): TData | undefined { 21 | return callQueryClientMethodWithQueryKey( 22 | qraftOptions, 23 | 'getQueryState', 24 | schema, 25 | true, 26 | // @ts-expect-error - Too complex to type 27 | args 28 | ) as never; 29 | } 30 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/setInfiniteQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | OperationSchema, 3 | ServiceOperationSetInfiniteQueryData, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { InfiniteData } from '@tanstack/react-query'; 6 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 7 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientMethodWithQueryKey.js'; 8 | 9 | export function setInfiniteQueryData( 10 | qraftOptions: CreateAPIQueryClientOptions, 11 | schema: OperationSchema, 12 | args: Parameters< 13 | ServiceOperationSetInfiniteQueryData< 14 | OperationSchema, 15 | unknown, 16 | TData 17 | >['setInfiniteQueryData'] 18 | > 19 | ): InfiniteData | undefined { 20 | return callQueryClientMethodWithQueryKey( 21 | qraftOptions, 22 | 'setQueryData', 23 | schema, 24 | true, 25 | // @ts-expect-error - Too complex to type 26 | args 27 | ) as never; 28 | } 29 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationMutationFn.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | RequestFnResponse, 3 | ServiceOperationMutationFnOptions, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | 6 | export interface ServiceOperationMutationFn< 7 | TSchema extends { url: string; method: string }, 8 | TBody, 9 | TMutationData, 10 | TMutationParams, 11 | TError, 12 | > { 13 | < 14 | TMeta extends Record, 15 | TSignal extends AbortSignal = AbortSignal, 16 | >( 17 | options: ServiceOperationMutationFnOptions< 18 | TBody, 19 | TMutationParams, 20 | TMeta, 21 | TSignal 22 | >, 23 | client?: ( 24 | schema: TSchema, 25 | options: ServiceOperationMutationFnOptions< 26 | TBody, 27 | TMutationParams, 28 | TMeta, 29 | TSignal 30 | > 31 | ) => Promise> 32 | ): Promise>; 33 | } 34 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/prefetchQuery.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationFetchQuery } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { DefaultError } from '@tanstack/react-query'; 3 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 4 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientFetchMethod.js'; 5 | 6 | export const prefetchQuery: < 7 | TSchema extends { url: string; method: 'get' | 'head' | 'options' }, 8 | TData, 9 | TParams, 10 | >( 11 | qraftOptions: CreateAPIQueryClientOptions, 12 | schema: TSchema, 13 | args: Parameters< 14 | ServiceOperationFetchQuery< 15 | TSchema, 16 | TData, 17 | TParams, 18 | DefaultError 19 | >['prefetchQuery'] 20 | > 21 | ) => Promise = (qraftOptions, schema, args) => { 22 | return callQueryClientMethodWithQueryKey( 23 | qraftOptions, 24 | 'prefetchQuery', 25 | schema, 26 | false, 27 | args as never 28 | ) as never; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/ensureQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationFetchQuery } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { DefaultError } from '@tanstack/react-query'; 3 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 4 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientFetchMethod.js'; 5 | 6 | export const ensureQueryData: < 7 | TSchema extends { url: string; method: 'get' | 'head' | 'options' }, 8 | TData, 9 | TParams, 10 | >( 11 | qraftOptions: CreateAPIQueryClientOptions, 12 | schema: TSchema, 13 | args: Parameters< 14 | ServiceOperationFetchQuery< 15 | TSchema, 16 | TData, 17 | TParams, 18 | DefaultError 19 | >['ensureQueryData'] 20 | > 21 | ) => Promise = (qraftOptions, schema, args) => { 22 | return callQueryClientMethodWithQueryKey( 23 | qraftOptions, 24 | 'ensureQueryData', 25 | schema, 26 | false, 27 | args as never 28 | ) as never; 29 | }; 30 | -------------------------------------------------------------------------------- /e2e/projects/typescript-nodenext-nodenext/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-nodenext-nodenext", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "", 6 | "main": "dist/index.js", 7 | "type": "module", 8 | "scripts": { 9 | "build": "tsc", 10 | "codegen": "openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript https://raw.githubusercontent.com/swagger-api/swagger-petstore/7767363b841961221a38c0be9c6b1066a5120051/src/main/resources/openapi.yaml --clean -o src/api --openapi-types-import-path '../schema.js' --explicit-import-extensions --openapi-types-file-name schema.ts", 11 | "e2e:pre-build": "npm run codegen", 12 | "e2e:post-build": "node ./dist/index.js" 13 | }, 14 | "dependencies": { 15 | "@openapi-qraft/cli": "latest", 16 | "@openapi-qraft/react": "latest", 17 | "@types/node": "latest", 18 | "typescript": "latest" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/OpenAPI-Qraft/openapi-qraft.git" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/getting-started/installation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Installation 6 | 7 | Before you start using OpenAPI Qraft, you need to install the CLI tool to generate the API client. 8 | You also need to install the Qraft Client React package to use the generated API client. 9 | 10 | ```bash npm2yarn 11 | npm install -D @openapi-qraft/cli 12 | npm install @openapi-qraft/react 13 | ``` 14 | 15 | :::info Peer Dependency 16 | 17 | If you are not already using **TanStack Query v5**, you need to 18 | [install](https://tanstack.com/query/latest/docs/framework/react/installation) it as well: 19 | 20 | ```bash npm2yarn 21 | npm install @tanstack/react-query 22 | ``` 23 | 24 | ::: 25 | 26 | ## Requirements 🌴 27 | 28 | OpenAPI Qraft is compatible with React v18+ and works with ReactDOM and React Native. 29 | Browser support is consistent with TanStack Query: 30 | 31 | ```text 32 | Chrome >= 91 33 | Firefox >= 90 34 | Edge >= 91 35 | Safari >= 15 36 | iOS >= 15 37 | Opera >= 77 38 | ``` 39 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/fetchInfiniteQuery.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationFetchInfiniteQuery } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { DefaultError } from '@tanstack/react-query'; 3 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 4 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientFetchMethod.js'; 5 | 6 | export const fetchInfiniteQuery: < 7 | TSchema extends { url: string; method: 'get' | 'head' | 'options' }, 8 | TData, 9 | TParams, 10 | >( 11 | qraftOptions: CreateAPIQueryClientOptions, 12 | schema: TSchema, 13 | args: Parameters< 14 | ServiceOperationFetchInfiniteQuery< 15 | TSchema, 16 | TData, 17 | TParams, 18 | DefaultError 19 | >['fetchInfiniteQuery'] 20 | > 21 | ) => Promise = (qraftOptions, schema, args) => { 22 | return callQueryClientMethodWithQueryKey( 23 | qraftOptions, 24 | 'fetchInfiniteQuery', 25 | schema, 26 | true, 27 | args as never 28 | ) as never; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/filterDocumentPaths.ts: -------------------------------------------------------------------------------- 1 | import { type OpenAPI3 } from 'openapi-typescript'; 2 | import { createServicePathMatch } from './createServicePathMatch.js'; 3 | 4 | /** 5 | * Filter the schema to only include paths that match the servicesGlob 6 | * @param schema OpenAPI schema 7 | * @param servicesGlob Glob pattern to match services. E.g.: `['**']` 8 | * 9 | * @example 10 | * ```ts 11 | * filterDocumentPaths(schema, ['/user/**', '/post/**', '!/user/internal']) 12 | * ``` 13 | */ 14 | export const filterDocumentPaths = ( 15 | schema: OpenAPI3, 16 | servicesGlob: string[] 17 | ): OpenAPI3 => { 18 | if (!servicesGlob.length) return schema; 19 | 20 | const isPathMatch = createServicePathMatch(servicesGlob); 21 | const paths: typeof schema.paths = {}; 22 | 23 | for (const path in schema.paths) { 24 | if (!Object.prototype.hasOwnProperty.call(schema.paths, path)) continue; 25 | if (!isPathMatch(path)) continue; 26 | paths[path] = schema.paths[path]; 27 | } 28 | 29 | return { ...schema, paths }; 30 | }; 31 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/useIsFetching.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { 4 | OperationSchema, 5 | ServiceOperationUseIsFetchingQueries, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 8 | import { useIsFetching as useIsFetchingTanstack } from '@tanstack/react-query'; 9 | import { composeQueryFilters } from '../lib/composeQueryFilters.js'; 10 | 11 | export const useIsFetching: ( 12 | qraftOptions: CreateAPIQueryClientOptions | undefined, 13 | schema: OperationSchema, 14 | args: Parameters< 15 | ServiceOperationUseIsFetchingQueries< 16 | OperationSchema, 17 | object | undefined, 18 | TVariables, 19 | unknown 20 | >['useIsFetching'] 21 | > 22 | ) => number = (qraftOptions, schema, args) => { 23 | const [filters] = args; 24 | 25 | return useIsFetchingTanstack( 26 | composeQueryFilters(schema, filters as never) as never, 27 | qraftOptions?.queryClient 28 | ) as never; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/prefetchInfiniteQuery.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationFetchInfiniteQuery } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { DefaultError } from '@tanstack/react-query'; 3 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 4 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientFetchMethod.js'; 5 | 6 | export const prefetchInfiniteQuery: < 7 | TSchema extends { url: string; method: 'get' | 'head' | 'options' }, 8 | TData, 9 | TParams, 10 | >( 11 | qraftOptions: CreateAPIQueryClientOptions, 12 | schema: TSchema, 13 | args: Parameters< 14 | ServiceOperationFetchInfiniteQuery< 15 | TSchema, 16 | TData, 17 | TParams, 18 | DefaultError 19 | >['prefetchInfiniteQuery'] 20 | > 21 | ) => Promise = (qraftOptions, schema, args) => { 22 | return callQueryClientMethodWithQueryKey( 23 | qraftOptions, 24 | 'prefetchInfiniteQuery', 25 | schema, 26 | true, 27 | args as never 28 | ) as never; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/shallowEqualObjects.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { shallowEqualObjects } from '../Unstable_QraftSecureRequestFn.js'; 3 | 4 | describe('shallowCompare', () => { 5 | it('should return true if the objects are the same', () => { 6 | expect(shallowEqualObjects({ foo: 'bar' }, { foo: 'bar' })).toBe(true); 7 | }); 8 | 9 | it('should return true if the types are the same', () => { 10 | expect(shallowEqualObjects('new', 'new')).toBe(true); 11 | }); 12 | 13 | it('should return false if the types are different', () => { 14 | expect(shallowEqualObjects('baz', { foo: 'bar' })).toBe(false); 15 | }); 16 | 17 | it('should return false object are not the same', () => { 18 | expect(shallowEqualObjects({ foo: 'bar' }, { bar: 'foo' })).toBe(false); 19 | }); 20 | 21 | it('should return false if the objects are not the same length', () => { 22 | expect( 23 | shallowEqualObjects({ foo: 'bar' }, { foo: 'bar', bar: 'foo' }) 24 | ).toBe(false); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/ts-factory/astToString.ts: -------------------------------------------------------------------------------- 1 | import ts from 'typescript'; 2 | 3 | export interface AstToStringOptions { 4 | fileName?: string; 5 | sourceText?: string; 6 | formatOptions?: ts.PrinterOptions; 7 | } 8 | 9 | /** Convert TypeScript AST to string */ 10 | export function astToString( 11 | ast: ts.Node | ts.Node[] | ts.TypeElement | ts.TypeElement[], 12 | options?: AstToStringOptions 13 | ): string { 14 | const sourceFile = ts.createSourceFile( 15 | options?.fileName ?? 'openapi-ts.ts', 16 | options?.sourceText ?? '', 17 | ts.ScriptTarget.ESNext, 18 | false, 19 | ts.ScriptKind.TS 20 | ); 21 | 22 | // @ts-expect-error it’s OK to overwrite statements once 23 | sourceFile.statements = ts.factory.createNodeArray( 24 | Array.isArray(ast) ? ast : [ast] 25 | ); 26 | 27 | const printer = ts.createPrinter({ 28 | newLine: ts.NewLineKind.LineFeed, 29 | removeComments: false, 30 | ...options?.formatOptions, 31 | }); 32 | 33 | return printer.printFile(sourceFile); 34 | } 35 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/ensureInfiniteQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationFetchInfiniteQuery } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { DefaultError } from '@tanstack/react-query'; 3 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 4 | import { callQueryClientMethodWithQueryKey } from '../lib/callQueryClientFetchMethod.js'; 5 | 6 | export const ensureInfiniteQueryData: < 7 | TSchema extends { url: string; method: 'get' | 'head' | 'options' }, 8 | TData, 9 | TParams, 10 | >( 11 | qraftOptions: CreateAPIQueryClientOptions, 12 | schema: TSchema, 13 | args: Parameters< 14 | ServiceOperationFetchInfiniteQuery< 15 | TSchema, 16 | TData, 17 | TParams, 18 | DefaultError 19 | >['ensureInfiniteQueryData'] 20 | > 21 | ) => Promise = (qraftOptions, schema, args) => { 22 | return callQueryClientMethodWithQueryKey( 23 | qraftOptions, 24 | 'ensureInfiniteQueryData', 25 | schema, 26 | true, 27 | args as never 28 | ) as never; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/ts-factory/tsdoc/lib/createOperationMethodCallExpressionExampleNode.ts: -------------------------------------------------------------------------------- 1 | import { ServiceOperation } from '@openapi-qraft/plugin/lib/open-api/OpenAPIService'; 2 | import ts from 'typescript'; 3 | 4 | export const createOperationMethodCallExpressionExampleNode = ( 5 | operation: ServiceOperation, 6 | { 7 | serviceVariableName, 8 | operationMethodName, 9 | }: { serviceVariableName: string; operationMethodName: string }, 10 | nodes: ts.Expression[] | undefined 11 | ) => { 12 | const factory = ts.factory; 13 | 14 | return factory.createCallExpression( 15 | factory.createPropertyAccessExpression( 16 | factory.createPropertyAccessExpression( 17 | factory.createPropertyAccessExpression( 18 | factory.createIdentifier('qraft'), 19 | factory.createIdentifier(serviceVariableName) 20 | ), 21 | factory.createIdentifier(operation.name) 22 | ), 23 | factory.createIdentifier(operationMethodName) 24 | ), 25 | undefined, 26 | nodes 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /e2e/projects/typescript-commonjs-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-commonjs-node", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "", 6 | "main": "dist/index.js", 7 | "type": "commonjs", 8 | "scripts": { 9 | "build": "tsc", 10 | "codegen": "openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript https://raw.githubusercontent.com/swagger-api/swagger-petstore/7767363b841961221a38c0be9c6b1066a5120051/src/main/resources/openapi.yaml --clean -o src/api --openapi-types-import-path '../schema.d.ts' --openapi-types-file-name schema.d.ts --operation-predefined-parameters /pet/findByStatus:query.status", 11 | "e2e:pre-build": "npm run codegen", 12 | "e2e:post-build": "node ./dist/index.js" 13 | }, 14 | "dependencies": { 15 | "@openapi-qraft/cli": "latest", 16 | "@openapi-qraft/react": "latest", 17 | "@types/node": "latest", 18 | "typescript": "latest" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/OpenAPI-Qraft/openapi-qraft.git" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/migrate-to-v2.6.0-codemod/mixed-imports.tsx: -------------------------------------------------------------------------------- 1 | // Import from our package 2 | import { qraftAPIClient } from '@openapi-qraft/react-client'; 3 | // Import another function with the same name from another package 4 | import { qraftAPIClient as otherClient } from 'other-library'; 5 | 6 | // This call should be modified (it uses our import) 7 | const api = qraftAPIClient(services, callbacks, options); 8 | 9 | // This call should NOT be modified (it uses another import) 10 | const otherApi = otherClient( 11 | otherServices, 12 | otherCallbacks, 13 | otherOptions 14 | ); 15 | 16 | interface Services { 17 | service1: { 18 | operation1: { 19 | schema: any; 20 | }; 21 | }; 22 | } 23 | 24 | interface Callbacks { 25 | operation1: () => void; 26 | } 27 | 28 | interface OtherServices { 29 | otherService: { 30 | otherOperation: { 31 | schema: any; 32 | }; 33 | }; 34 | } 35 | 36 | interface OtherCallbacks { 37 | otherOperation: () => void; 38 | } 39 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/src/generateSourceFileFactoryCode.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'node:fs'; 2 | import * as ts from 'typescript-5.5.4'; 3 | import { generateFactoryCode } from './generateFactoryCode'; 4 | 5 | /** 6 | * Generates the factory code for a given source file 7 | * @param sourceFilePath - The path to the source file 8 | * @returns The factory code for the source file 9 | * 10 | * @example 11 | * ```ts 12 | * const sourceFilePath = '/path/to/file.ts'; 13 | * const factoryCode = getSourceFileFactoryCode(sourceFilePath); 14 | * ``` 15 | */ 16 | export function generateSourceFileFactoryCode(sourceFilePath: string): string { 17 | if (!fs.existsSync(sourceFilePath)) { 18 | throw new Error(`File "${sourceFilePath}" does not exist`); 19 | } 20 | 21 | // get ast 22 | const sourceFile = ts.createSourceFile( 23 | sourceFilePath, 24 | fs.readFileSync(sourceFilePath).toString('utf-8'), 25 | ts.ScriptTarget.Latest 26 | ); 27 | 28 | // get the generated factory code 29 | return generateFactoryCode(ts, sourceFile); 30 | } 31 | -------------------------------------------------------------------------------- /e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openapi-qraft/e2e", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "verdaccio": "VERDACCIO_STORAGE_PATH=./verdaccio-storage verdaccio --config ./verdaccio-config.yaml", 7 | "remove-verdaccio-storage": "rimraf ./verdaccio-storage", 8 | "e2e:publish-to-private-registry": "NPM_PUBLISH_SCOPES='openapi-qraft' yarn exec bin/publish-to-private-registry.sh", 9 | "e2e:unpublish-from-private-registry": "NPM_PUBLISH_SCOPES='openapi-qraft' yarn exec bin/unpublish-from-private-registry.sh", 10 | "e2e:update-projects-from-private-registry": "NPM_PUBLISH_SCOPES='openapi-qraft' yarn exec bin/update-projects-from-private-registry.sh", 11 | "e2e:build-projects": "yarn exec bin/build-projects.sh", 12 | "e2e:test": "yarn e2e:publish-to-private-registry && yarn e2e:update-projects-from-private-registry && yarn e2e:build-projects && yarn e2e:unpublish-from-private-registry" 13 | }, 14 | "packageManager": "yarn@3.5.0", 15 | "devDependencies": { 16 | "rimraf": "^6.1.2", 17 | "verdaccio": "^5.33.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/useQuery.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { 4 | OperationSchema, 5 | ServiceOperationUseQuery, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { DefaultError, UseQueryResult } from '@tanstack/react-query'; 8 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 9 | import { useQuery as useQueryTanstack } from '@tanstack/react-query'; 10 | import { useComposeUseQueryOptions } from '../lib/useComposeUseQueryOptions.js'; 11 | 12 | export const useQuery: ( 13 | qraftOptions: CreateAPIQueryClientOptions, 14 | schema: OperationSchema, 15 | args: Parameters< 16 | ServiceOperationUseQuery< 17 | OperationSchema, 18 | unknown, 19 | unknown, 20 | DefaultError 21 | >['useQuery'] 22 | > 23 | ) => UseQueryResult = (qraftOptions, schema, args) => { 24 | return useQueryTanstack( 25 | // @ts-expect-error - Too complex to type 26 | ...useComposeUseQueryOptions(qraftOptions, schema, args, false) 27 | ) as never; 28 | }; 29 | -------------------------------------------------------------------------------- /packages/test-fixtures/redocly.yaml: -------------------------------------------------------------------------------- 1 | apis: 2 | main: 3 | root: ./openapi.json 4 | x-openapi-qraft: 5 | plugin: 6 | tanstack-query-react: true 7 | openapi-typescript: true 8 | output-dir: src/api 9 | clean: true 10 | explicit-import-extensions: true 11 | openapi-types-file-name: openapi.ts 12 | filter-services: 13 | - '/approval_policies/**' 14 | - '/entities/**' 15 | - '/files/**' 16 | - '!/internal/**' 17 | operation-predefined-parameters: 18 | '/approval_policies/{approval_policy_id}/**': 'header.x-monite-entity-id' 19 | '/entities/{entity_id}/documents': 'header.x-monite-version' 20 | operation-name-modifier: 21 | - '/files/list:[a-zA-Z]+List ==> findAll' 22 | main@internal: 23 | root: ./openapi.json 24 | x-openapi-qraft: 25 | plugin: 26 | tanstack-query-react: true 27 | openapi-typescript: true 28 | output-dir: src/internal-api 29 | filter-services: 30 | - '/internal/**' 31 | 32 | not-gen: 33 | root: ./openapi.json 34 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationUseSuspenseQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | UseQueryOptionsForUseSuspenseQuery, 3 | WithOptional, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { UseSuspenseQueryResult } from '@tanstack/react-query'; 6 | 7 | export interface ServiceOperationUseSuspenseQueries< 8 | TSchema extends { url: string; method: string }, 9 | TOperationQueryFnData, 10 | TQueryParams, 11 | TError, 12 | > { 13 | useSuspenseQueries< 14 | T extends Array< 15 | UseQueryOptionsForUseSuspenseQuery< 16 | TSchema, 17 | TQueryParams, 18 | TOperationQueryFnData, 19 | TError 20 | > 21 | >, 22 | TCombinedResult = Array< 23 | UseSuspenseQueryResult 24 | >, 25 | >(options: { 26 | queries: T; 27 | combine?: ( 28 | results: Array< 29 | WithOptional< 30 | UseSuspenseQueryResult, 31 | 'data' 32 | > 33 | > 34 | ) => TCombinedResult; 35 | }): TCombinedResult; 36 | } 37 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/splitCommaSeparatedGlobs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Normalize a comma-separated list of globs 3 | * @param commaSeparatedGlobs - Example: `/foo , /bar/**, ,` 4 | * @returns Example: `/foo,/bar/**` 5 | * @throws {Error} if input is invalid: not a `string` or `undefined` is provided 6 | */ 7 | export function splitCommaSeparatedGlobs( 8 | commaSeparatedGlobs: Array | string | undefined 9 | ): string[] { 10 | const flattenCommaSeparatedGlobs = Array.isArray(commaSeparatedGlobs) 11 | ? commaSeparatedGlobs 12 | : [commaSeparatedGlobs].filter((glob) => { 13 | if (typeof glob !== 'string' && typeof glob !== 'undefined') 14 | throw new Error('Invalid input'); 15 | return Boolean(glob); 16 | }); 17 | 18 | if (!flattenCommaSeparatedGlobs.length) return []; 19 | 20 | return flattenCommaSeparatedGlobs 21 | .flatMap((path) => path?.split(',')) 22 | .map((path) => path?.trim()) 23 | .filter((path, index, array): path is NonNullable => { 24 | return Boolean(path) && array.lastIndexOf(path) === index; 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qraft", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "build": "turbo run build", 7 | "dev": "turbo run dev", 8 | "dev:qraft": "turbo run dev --filter '@openapi-qraft/*'", 9 | "test": "turbo run test --continue --output-logs=new-only", 10 | "lint": "turbo run lint --continue --output-logs=new-only", 11 | "typecheck": "turbo run typecheck --output-logs=new-only" 12 | }, 13 | "devDependencies": { 14 | "@changesets/cli": "^2.29.8", 15 | "@ianvs/prettier-plugin-sort-imports": "^4.3.1", 16 | "knip": "^5.62.0", 17 | "prettier": "^3.7.3", 18 | "turbo": "^2.6.1", 19 | "typescript": "^5.6.2" 20 | }, 21 | "workspaces": [ 22 | "packages/*", 23 | "playground", 24 | "e2e", 25 | "website" 26 | ], 27 | "packageManager": "yarn@4.9.1", 28 | "resolutions": { 29 | "ts-morph@npm:^17.0.1": "patch:ts-morph@npm%3A17.0.1#~/.yarn/patches/ts-morph-npm-17.0.1-6097358fba.patch", 30 | "verdaccio/js-yaml": "4.1.1", 31 | "@verdaccio/config/js-yaml": "4.1.1", 32 | "compression/on-headers": "1.1.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/eslint-plugin-query/src/utils/create-client-name-regex.ts: -------------------------------------------------------------------------------- 1 | export function createClientNameRegex(clientNamePattern: string | undefined) { 2 | clientNamePattern = clientNamePattern?.trim(); 3 | 4 | if (clientNamePattern) { 5 | // Check if pattern is in regex format: /pattern/flags 6 | const regexMatch = clientNamePattern.match(/^\/(.*)\/([gimuy]*)$/); 7 | 8 | if (regexMatch) { 9 | const regexPattern = regexMatch[1].trim(); 10 | const flags = regexMatch[2]; 11 | 12 | // Validate that regex pattern is not empty or whitespace-only 13 | if (regexPattern === '') { 14 | throw new Error( 15 | 'clientNamePattern cannot be empty or contain only whitespace' 16 | ); 17 | } 18 | 19 | return new RegExp(regexPattern, flags); 20 | } 21 | 22 | // Fallback to treating as plain string pattern 23 | return new RegExp(clientNamePattern); 24 | } else if (clientNamePattern === '') { 25 | throw new Error( 26 | 'clientNamePattern cannot be empty or contain only whitespace' 27 | ); 28 | } 29 | 30 | // Default if no pattern provided 31 | return /qraft|api/i; 32 | } 33 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/fixtures/migrate-to-v2.6.0-codemod/generics.tsx: -------------------------------------------------------------------------------- 1 | import { qraftAPIClient } from '@openapi-qraft/react-client'; 2 | 3 | const services: Services = { 4 | service1: { 5 | operation1: { 6 | schema: {}, 7 | }, 8 | }, 9 | }; 10 | 11 | const callbacks: Callbacks = { 12 | operation1: () => {}, 13 | }; 14 | 15 | const options = { 16 | requestFn: () => Promise.resolve({}), 17 | baseUrl: 'https://api.example.com', 18 | queryClient: {}, 19 | }; 20 | 21 | const requestFn = () => Promise.resolve({}); 22 | const baseUrl = 'https://api.example.com'; 23 | const queryClient = {}; 24 | 25 | const api = qraftAPIClient(services, callbacks, options); 26 | 27 | const api2 = qraftAPIClient(services, callbacks, { 28 | requestFn, 29 | baseUrl, 30 | queryClient, 31 | }); 32 | 33 | const api3 = qraftAPIClient(services, callbacks, { 34 | queryClient, 35 | }); 36 | 37 | interface Services { 38 | service1: { 39 | operation1: { 40 | schema: any; 41 | }; 42 | }; 43 | } 44 | 45 | interface Callbacks { 46 | operation1: () => void; 47 | } 48 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationUseSuspenseQuery.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AreAllOptional, 3 | DeepReadonly, 4 | OperationError, 5 | ServiceOperationQueryKey, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { 8 | UseSuspenseQueryOptions, 9 | UseSuspenseQueryResult, 10 | } from '@tanstack/react-query'; 11 | 12 | export interface ServiceOperationUseSuspenseQuery< 13 | TSchema extends { url: string; method: string }, 14 | TOperationQueryFnData, 15 | TQueryParams, 16 | TError, 17 | > { 18 | useSuspenseQuery( 19 | parameters: 20 | | ServiceOperationQueryKey 21 | | (AreAllOptional extends true 22 | ? DeepReadonly | void 23 | : DeepReadonly), 24 | options?: Omit< 25 | UseSuspenseQueryOptions< 26 | TOperationQueryFnData, 27 | TError, 28 | TData, 29 | ServiceOperationQueryKey 30 | >, 31 | 'queryKey' 32 | > 33 | ): UseSuspenseQueryResult>; 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024-present Alex Batalov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/ts-factory/filterUnusedTypes.spec.ts: -------------------------------------------------------------------------------- 1 | import ts from 'typescript'; 2 | import { describe, expect, test } from 'vitest'; 3 | import { filterUnusedTypes } from './filterUnusedTypes.js'; 4 | 5 | describe('filterUnusedTypes(...)', () => { 6 | const sourceFile = ts.createSourceFile( 7 | 'test.ts', 8 | ` 9 | type Foo = ExternalBar; 10 | type Bar = string; 11 | `, 12 | ts.ScriptTarget.Latest, 13 | true, 14 | ts.ScriptKind.TS 15 | ); 16 | 17 | test('return only used external types', () => { 18 | const typeImports = { 19 | 'other-module': ['ExternalBar'], 20 | 'some-module': ['Foo', 'Bar'], 21 | }; 22 | 23 | expect( 24 | filterUnusedTypes(typeImports, Array.from(sourceFile.statements)) 25 | ).toEqual({ 26 | 'other-module': ['ExternalBar'], 27 | }); 28 | }); 29 | 30 | test('return empty record if no types are used', () => { 31 | const typeImports = { 32 | 'some-module': ['Foo', 'Bar'], 33 | }; 34 | 35 | expect( 36 | filterUnusedTypes(typeImports, Array.from(sourceFile.statements)) 37 | ).toEqual({}); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationQueryFn.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AreAllOptional, 3 | QueryFnOptionsByParameters, 4 | QueryFnOptionsByQueryKey, 5 | RequestFnResponse, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | 8 | export interface ServiceOperationQueryFn< 9 | TSchema extends { url: string; method: string }, 10 | TOperationQueryFnData, 11 | TQueryParams, 12 | TError, 13 | > { 14 | < 15 | TMeta extends Record, 16 | TSignal extends AbortSignal = AbortSignal, 17 | >( 18 | options: 19 | | QueryFnOptionsByQueryKey 20 | | (AreAllOptional extends true 21 | ? QueryFnOptionsByParameters | void 22 | : QueryFnOptionsByParameters), 23 | client?: ( 24 | schema: TSchema, 25 | options: { 26 | parameters: TQueryParams; 27 | signal?: TSignal; 28 | meta?: TMeta; 29 | } 30 | ) => Promise> 31 | ): Promise>; 32 | } 33 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationSetQueriesData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | QueryFiltersByParameters, 3 | QueryFiltersByQueryKey, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { NoInfer, SetDataOptions, Updater } from '@tanstack/react-query'; 6 | 7 | export interface ServiceOperationSetQueriesData< 8 | TSchema extends { url: string; method: string }, 9 | TOperationQueryFnData, 10 | TQueryParams, 11 | TError, 12 | > { 13 | setQueriesData( 14 | filters: 15 | | QueryFiltersByParameters< 16 | TSchema, 17 | TOperationQueryFnData, 18 | TInfinite, 19 | TQueryParams, 20 | TError 21 | > 22 | | QueryFiltersByQueryKey< 23 | TSchema, 24 | TOperationQueryFnData, 25 | TInfinite, 26 | TQueryParams, 27 | TError 28 | >, 29 | updater: Updater< 30 | NoInfer | undefined, 31 | NoInfer | undefined 32 | >, 33 | options?: SetDataOptions 34 | ): Array; 35 | } 36 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/resolveDocumentLocalRef.ts: -------------------------------------------------------------------------------- 1 | import type { OpenAPI3 } from 'openapi-typescript'; 2 | import type { OpenAPISchemaType } from './OpenAPISchemaType.js'; 3 | import { unescapePointer } from '@redocly/openapi-core'; 4 | 5 | /** 6 | * Resolves a local reference to a value in the OpenAPI schema. 7 | * 8 | * @param ref - The reference to resolve. 9 | * @param openApiJson - The OpenAPI schema to resolve the reference in. 10 | */ 11 | export function resolveDocumentLocalRef( 12 | ref: string, 13 | openApiJson: OpenAPISchemaType | OpenAPI3 14 | ) { 15 | const refParts = parseLocalRef(ref); 16 | 17 | let result: unknown = openApiJson; 18 | for (const part of refParts) { 19 | if (result && typeof result === 'object' && part in result) { 20 | result = result[part as keyof typeof result]; 21 | } else { 22 | throw new Error(`Reference ${ref} not found`); 23 | } 24 | } 25 | 26 | return result; 27 | } 28 | 29 | function parseLocalRef(ref: string): string[] { 30 | const [, pointer = ''] = ref.split('#/'); 31 | 32 | return pointer 33 | .split('/') 34 | .map(unescapePointer) 35 | .filter((path) => !!path); 36 | } 37 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/filterDocumentPaths.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { createServicePathMatch } from './createServicePathMatch.js'; 3 | 4 | describe('createServicePathMatch', () => { 5 | it('should match with multiple include glob', () => { 6 | const isPathMatch = createServicePathMatch(['/user/**', '/post/**']); 7 | expect(isPathMatch('/user/1')).toBe(true); 8 | expect(isPathMatch('/user/1/approve')).toBe(true); 9 | expect(isPathMatch('/post/1')).toBe(true); 10 | expect(isPathMatch('/profile/1')).toBe(false); 11 | }); 12 | 13 | it('should not match with inclusion pattern', () => { 14 | const isPathMatch = createServicePathMatch([ 15 | '/user/**', 16 | '/post/**', 17 | '!/user/1', 18 | ]); 19 | expect(isPathMatch('/user/1')).toBe(false); 20 | expect(isPathMatch('/user/1/approve')).toBe(true); 21 | expect(isPathMatch('/post/1')).toBe(true); 22 | expect(isPathMatch('/profile/1')).toBe(false); 23 | }); 24 | 25 | it('should not match if nothing is specified', () => { 26 | const isPathMatch = createServicePathMatch([]); 27 | expect(isPathMatch('/user/1')).toBe(false); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/UseQueryOptionsForUseQueries.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | QueriesPlaceholderDataFunction, 3 | UseQueryOptions, 4 | } from '@tanstack/react-query'; 5 | import type { DeepReadonly } from './DeepReadonly.js'; 6 | import type { ServiceOperationQueryKey } from './ServiceOperationKey.js'; 7 | 8 | export type UseQueryOptionsForUseQueries< 9 | TSchema extends { url: string; method: string }, 10 | TParams, 11 | TQueryFnData, 12 | TError, 13 | TData = TQueryFnData, 14 | > = Omit< 15 | UseQueryOptions< 16 | TQueryFnData, 17 | TError, 18 | TData, 19 | ServiceOperationQueryKey 20 | >, 21 | 'placeholderData' | 'suspense' | 'queryKey' 22 | > & 23 | ( 24 | | { 25 | parameters: DeepReadonly; 26 | placeholderData?: 27 | | TQueryFnData 28 | | QueriesPlaceholderDataFunction; 29 | queryKey?: never; 30 | } 31 | | { 32 | queryKey: ServiceOperationQueryKey; 33 | placeholderData?: 34 | | TQueryFnData 35 | | QueriesPlaceholderDataFunction; 36 | parameters?: never; 37 | } 38 | ); 39 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/getMutationCache.ts: -------------------------------------------------------------------------------- 1 | import type { OperationSchema } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 3 | import { composeMutationFilters } from '../lib/composeMutationFilters.js'; 4 | 5 | export function getMutationCache( 6 | qraftOptions: CreateAPIQueryClientOptions, 7 | schema: OperationSchema 8 | ) { 9 | const mutationCache = qraftOptions.queryClient.getMutationCache(); 10 | 11 | return wrapMutationCacheMethods(schema, mutationCache); 12 | } 13 | 14 | function wrapMutationCacheMethods< 15 | T extends Record<'find' | 'findAll', (...args: any[]) => any>, 16 | >(schema: OperationSchema, original: T): T { 17 | return new Proxy(original, { 18 | get(target, prop, receiver) { 19 | if (prop === 'find' || prop === 'findAll') { 20 | return function (...args: any[]) { 21 | return Reflect.apply(target[prop], target, [ 22 | composeMutationFilters(schema, args[0] as never), 23 | ...args.slice(1, args.length), 24 | ]); 25 | }; 26 | } 27 | 28 | return Reflect.get(target, prop, receiver); 29 | }, 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/useSuspenseQuery.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { 4 | OperationSchema, 5 | ServiceOperationUseSuspenseQuery, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { DefaultError, UseQueryResult } from '@tanstack/react-query'; 8 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 9 | import { useSuspenseQuery as useSuspenseQueryTanstack } from '@tanstack/react-query'; 10 | import { useComposeUseQueryOptions } from '../lib/useComposeUseQueryOptions.js'; 11 | 12 | export const useSuspenseQuery: < 13 | TQueryFnData = unknown, 14 | TError = DefaultError, 15 | TData = TQueryFnData, 16 | >( 17 | qraftOptions: CreateAPIQueryClientOptions, 18 | schema: OperationSchema, 19 | args: Parameters< 20 | ServiceOperationUseSuspenseQuery< 21 | OperationSchema, 22 | unknown, 23 | unknown, 24 | DefaultError 25 | >['useSuspenseQuery'] 26 | > 27 | ) => UseQueryResult = (qraftOptions, schema, args) => { 28 | return useSuspenseQueryTanstack( 29 | // @ts-expect-error - Too complex to type 30 | ...useComposeUseQueryOptions(qraftOptions, schema, args, false) 31 | ) as never; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/react-client/src/tests/composeMutationKey.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { composeMutationKey } from '../lib/composeMutationKey.js'; 3 | 4 | describe('composeMutationKey', () => { 5 | it('should return mutation key with parameters', () => { 6 | const schema = { 7 | url: 'https://example.com', 8 | method: 'get', 9 | } as const; 10 | 11 | const parameters = { 12 | body: 'body', 13 | requestBody: 'requestBody', 14 | other: 'other', 15 | }; 16 | const result = composeMutationKey(schema, parameters); 17 | 18 | expect(result).toEqual([ 19 | { 20 | url: schema.url, 21 | method: schema.method, 22 | }, 23 | { 24 | other: 'other', 25 | }, 26 | ]); 27 | }); 28 | 29 | it('should return mutation key without parameters', () => { 30 | const schema = { 31 | url: 'https://example.com', 32 | method: 'get', 33 | } as const; 34 | 35 | const result = composeMutationKey(schema, undefined); 36 | 37 | expect(result).toEqual([ 38 | { 39 | url: schema.url, 40 | method: schema.method, 41 | }, 42 | {}, 43 | ]); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationSetInfiniteQueryData.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AreAllOptional, 3 | DeepReadonly, 4 | OperationInfiniteData, 5 | ServiceOperationInfiniteQueryKey, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { NoInfer, SetDataOptions, Updater } from '@tanstack/react-query'; 8 | 9 | export interface ServiceOperationSetInfiniteQueryData< 10 | TSchema extends { url: string; method: string }, 11 | TOperationQueryFnData, 12 | TQueryParams, 13 | > { 14 | setInfiniteQueryData( 15 | parameters: 16 | | (AreAllOptional extends true 17 | ? DeepReadonly | undefined 18 | : DeepReadonly) 19 | | ServiceOperationInfiniteQueryKey, 20 | updater: Updater< 21 | | NoInfer> 22 | | undefined, 23 | | NoInfer< 24 | DeepReadonly< 25 | OperationInfiniteData 26 | > 27 | > 28 | | undefined 29 | >, 30 | options?: SetDataOptions 31 | ): OperationInfiniteData | undefined; 32 | } 33 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/useInfiniteQuery.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { 4 | OperationSchema, 5 | ServiceOperationUseInfiniteQuery, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { 8 | DefaultError, 9 | InfiniteData, 10 | UseInfiniteQueryResult, 11 | } from '@tanstack/react-query'; 12 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 13 | import { useInfiniteQuery as useInfiniteQueryBase } from '@tanstack/react-query'; 14 | import { useComposeUseQueryOptions } from '../lib/useComposeUseQueryOptions.js'; 15 | 16 | export const useInfiniteQuery: < 17 | TQueryFnData, 18 | TError = DefaultError, 19 | TData = InfiniteData, 20 | >( 21 | qraftOptions: CreateAPIQueryClientOptions, 22 | schema: OperationSchema, 23 | args: Parameters< 24 | ServiceOperationUseInfiniteQuery< 25 | OperationSchema, 26 | unknown, 27 | unknown, 28 | DefaultError 29 | >['useInfiniteQuery'] 30 | > 31 | ) => UseInfiniteQueryResult = (qraftOptions, schema, args) => { 32 | return useInfiniteQueryBase( 33 | // @ts-expect-error - Too complex to type... 34 | ...useComposeUseQueryOptions(qraftOptions, schema, args, true) 35 | ) as never; 36 | }; 37 | -------------------------------------------------------------------------------- /packages/rollup-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openapi-qraft/rollup-config", 3 | "version": "1.1.1", 4 | "private": true, 5 | "scripts": { 6 | "build": "tsc", 7 | "dev": "tsc --watch --noEmitOnError false", 8 | "lint": "echo 'No linting configured'", 9 | "typecheck": "tsc --noEmit --emitDeclarationOnly false", 10 | "clean": "rimraf dist/" 11 | }, 12 | "dependencies": { 13 | "@swc/core": "1.7.26", 14 | "rollup-plugin-swc3": "~0.12.1", 15 | "rollup-preserve-directives": "~1.1.3" 16 | }, 17 | "devDependencies": { 18 | "rimraf": "^6.1.2", 19 | "typescript": "^5.6.2" 20 | }, 21 | "peerDependencies": { 22 | "rollup": "~4.18.0" 23 | }, 24 | "peerDependenciesMeta": { 25 | "rollup": { 26 | "optional": false 27 | } 28 | }, 29 | "type": "module", 30 | "module": "dist/rollup.config.js", 31 | "types": "dist/rollup.config.d.ts", 32 | "exports": { 33 | ".": { 34 | "types": "./dist/rollup.config.d.ts", 35 | "import": "./dist/rollup.config.js" 36 | }, 37 | "./package.json": "./package.json" 38 | }, 39 | "repository": { 40 | "type": "git", 41 | "url": "git+https://github.com/OpenAPI-Qraft/openapi-qraft.git", 42 | "directory": "packages/cli" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/OpenAPISchemaType.ts: -------------------------------------------------------------------------------- 1 | export type OpenAPISchemaType = { 2 | openapi: string; 3 | info: { 4 | title: string; 5 | version: string; 6 | }; 7 | paths: { 8 | [path: string]: { 9 | [method: string]: { 10 | tags?: string[]; 11 | description?: string; 12 | summary?: string; 13 | operationId?: string; 14 | parameters?: Array; 15 | deprecated?: boolean; 16 | requestBody?: { 17 | content?: { 18 | [contentType: string]: { 19 | schema: any; 20 | }; 21 | }; 22 | $ref?: string; 23 | required?: boolean; 24 | }; 25 | responses: { 26 | [statusCode in number | 'default']: { 27 | $ref?: string; 28 | description?: string; 29 | content?: { 30 | [contentType: string]: 31 | | { 32 | schema: any; 33 | } 34 | | { type: string }; 35 | }; 36 | }; 37 | }; 38 | security?: Array>; 39 | }; 40 | }; 41 | }; 42 | components: { 43 | parameters: Record | undefined; 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /.changeset/remove-dist-tag.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if [ $# -ne 1 ]; then 4 | echo "Usage: $0 " 5 | echo "Example: $0 provenance-test" 6 | exit 1 7 | fi 8 | 9 | TAG_TO_REMOVE=$1 10 | 11 | confirm() { 12 | if [ -z "$CI" ] && [ -z "$GITHUB_ACTIONS" ] && [ -z "$GITLAB_CI" ]; then 13 | echo "You are about to remove tag '$TAG_TO_REMOVE' from all packages in the packages directory" 14 | echo "This will remove the tag from npm registry. Do you want to continue? (y/n)" 15 | read ans 16 | case $ans in 17 | [Yy]* ) ;; 18 | * ) echo "Operation cancelled"; exit 1 ;; 19 | esac 20 | fi 21 | } 22 | 23 | confirm 24 | 25 | cd packages 26 | 27 | for dir in */; do 28 | if [ -f "${dir}package.json" ]; then 29 | package_name=$(node -p "require('./${dir}package.json').name") 30 | 31 | if [ -n "$package_name" ]; then 32 | echo "Processing package: $package_name" 33 | 34 | echo "Removing tag '$TAG_TO_REMOVE' from $package_name..." 35 | npm dist-tag rm "$package_name" "$TAG_TO_REMOVE" || true 36 | 37 | echo "Processed $package_name" 38 | echo "------------------------" 39 | fi 40 | fi 41 | done -------------------------------------------------------------------------------- /packages/tanstack-query-react-plugin/src/lib/maybeResolveImport.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from 'vitest'; 2 | import { maybeResolveImport } from './maybeResolveImport.js'; 3 | 4 | describe('maybeResolveImport', () => { 5 | test('should prepend services directory to services relative path', () => { 6 | expect( 7 | maybeResolveImport({ 8 | openapiTypesImportPath: './openapi.ts', 9 | servicesDirName: 'services', 10 | }) 11 | ).toBe('./services/openapi.ts'); 12 | }); 13 | 14 | test('should remove one level from path', () => { 15 | expect( 16 | maybeResolveImport({ 17 | openapiTypesImportPath: '../openapi.ts', 18 | servicesDirName: 'services', 19 | }) 20 | ).toBe('./openapi.ts'); 21 | }); 22 | 23 | test('should not modify module path', () => { 24 | expect( 25 | maybeResolveImport({ 26 | openapiTypesImportPath: '@my-openapi', 27 | servicesDirName: 'services', 28 | }) 29 | ).toBe('@my-openapi'); 30 | }); 31 | 32 | test('should not modify absolute path', () => { 33 | expect( 34 | maybeResolveImport({ 35 | openapiTypesImportPath: '/openapi.ts', 36 | servicesDirName: 'services', 37 | }) 38 | ).toBe('/openapi.ts'); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /.github/workflows/deploy-gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | workflow_run: 7 | workflows: ["Release"] 8 | types: 9 | - completed 10 | 11 | permissions: 12 | contents: write 13 | 14 | jobs: 15 | deploy: 16 | name: Deploy to GitHub Pages 17 | runs-on: ubuntu-latest 18 | if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} 19 | environment: github-pages 20 | steps: 21 | - name: Checkout Repo 22 | uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Setup Node.js 20.x 27 | uses: actions/setup-node@v4 28 | with: 29 | cache: 'yarn' 30 | node-version: 20.12.2 31 | 32 | - name: Install dependencies 33 | run: yarn install --immutable 34 | 35 | - name: Lint Documentation 36 | run: yarn workspace openapi-qraft-website run lint 37 | 38 | - name: Build website 39 | run: yarn workspace openapi-qraft-website run build 40 | 41 | - name: Deploy to GitHub Pages 42 | uses: peaceiris/actions-gh-pages@v3 43 | with: 44 | github_token: ${{ secrets.GITHUB_TOKEN }} 45 | publish_dir: ./website/build 46 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/shouldQuoteCommandLineArg.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if a command-line argument needs to be quoted when used in a command line. 3 | * 4 | * Arguments containing special characters like spaces, quotes, or shell metacharacters 5 | * need to be wrapped in quotes to be properly interpreted by the shell. 6 | * 7 | * @param arg The command-line argument to check 8 | * @returns True if the argument needs quotes, false otherwise 9 | */ 10 | export function shouldQuoteCommandLineArg(arg: string): boolean { 11 | if (!arg) return false; 12 | 13 | // Check for spaces 14 | if (arg.includes(' ')) return true; 15 | 16 | // Check for quotes 17 | if (arg.includes('"') || arg.includes("'")) return true; 18 | 19 | // Check for shell metacharacters and special characters 20 | const shellSpecialChars = /[&|<>(){}[\]$;!*?~`\n\r\t#]/; 21 | if (shellSpecialChars.test(arg)) return true; 22 | 23 | // Check for control characters 24 | // eslint-disable-next-line no-control-regex 25 | if (/[\x00-\x1F\x7F]/.test(arg)) return true; 26 | 27 | // Check if argument starts with a dash (to avoid confusion with options) 28 | if (arg.startsWith('-') && !arg.startsWith('--')) return true; 29 | 30 | // Check for wildcards 31 | return arg.includes('*') || arg.includes('?'); 32 | } 33 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/shared/ServiceOperationQuery.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceOperationQueryKey } from '@openapi-qraft/tanstack-query-react-types'; 2 | import type { DeepReadonly } from './DeepReadonly.js'; 3 | 4 | interface QueryFnOptionsBase< 5 | TMeta extends Record, 6 | TSignal extends AbortSignal = AbortSignal, 7 | > { 8 | signal?: TSignal; 9 | meta?: TMeta; 10 | } 11 | 12 | export interface QueryFnOptionsByParameters< 13 | TParams, 14 | TMeta extends Record, 15 | TSignal extends AbortSignal = AbortSignal, 16 | > 17 | extends QueryFnOptionsBase, QueryFnBaseUrlOptions { 18 | parameters: DeepReadonly; 19 | 20 | queryKey?: never; 21 | } 22 | 23 | export interface QueryFnOptionsByQueryKey< 24 | TSchema extends { url: string; method: string }, 25 | TParams, 26 | TMeta extends Record, 27 | TSignal extends AbortSignal = AbortSignal, 28 | > 29 | extends QueryFnOptionsBase, QueryFnBaseUrlOptions { 30 | queryKey: ServiceOperationQueryKey; 31 | 32 | parameters?: never; 33 | } 34 | 35 | interface QueryFnBaseUrlOptions { 36 | /** 37 | * Base URL to use for the request 38 | * @example 'https://api.example.com' 39 | */ 40 | baseUrl?: string; 41 | } 42 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/useIsMutating.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { 4 | OperationSchema, 5 | ServiceOperationUseIsMutating, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { DefaultError, UseMutationResult } from '@tanstack/react-query'; 8 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 9 | import { useIsMutating as useIsMutatingStateTanstack } from '@tanstack/react-query'; 10 | import { composeMutationFilters } from '../lib/composeMutationFilters.js'; 11 | 12 | export const useIsMutating: < 13 | TData = unknown, 14 | TError = DefaultError, 15 | TVariables = unknown, 16 | TContext = unknown, 17 | >( 18 | qraftOptions: CreateAPIQueryClientOptions | undefined, 19 | schema: OperationSchema, 20 | args: Parameters< 21 | ServiceOperationUseIsMutating< 22 | OperationSchema, 23 | object | undefined, 24 | TVariables, 25 | TData, 26 | DefaultError 27 | >['useIsMutating'] 28 | > 29 | ) => UseMutationResult = ( 30 | qraftOptions, 31 | schema, 32 | args 33 | ) => { 34 | const [filters] = args; 35 | 36 | return useIsMutatingStateTanstack( 37 | composeMutationFilters(schema, filters) as never, 38 | qraftOptions?.queryClient 39 | ) as never; 40 | }; 41 | -------------------------------------------------------------------------------- /website/docs/query-client/getInfiniteQueryKey.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: getInfiniteQueryKey() 3 | --- 4 | 5 | # getInfiniteQueryKey(...) 6 | 7 | The method provides a standardized way to generate `QueryKey` the _Infinite Queries_. 8 | See TanStack [_Query Keys 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) 9 | guide for more information. 10 | 11 | ```ts 12 | const queryKey = api...getInfiniteQueryKey(parameters); 13 | ``` 14 | 15 | ### Arguments 16 | 17 | 1. - `parameters: { path, query, header } | QueryKey | void` 18 | - **Required**, OpenAPI request parameters for the query, strictly-typed ✨ 19 | - `parameters` will be used to generate the `QueryKey` 20 | 21 | ### Returns 22 | 23 | `QueryKey` - a query key for the _Infinite Queries_ 24 | 25 | ### Example 26 | 27 | ```tsx 28 | const queryKey = api.files.getFiles.getInfiniteQueryKey({ 29 | header: { 'x-monite-version': '1.0.0' }, 30 | query: { id__in: ['1', '2'] }, 31 | }); 32 | 33 | expect(queryKey).toEqual([ 34 | { 35 | method: 'get', 36 | url: '/files', 37 | infinite: true // ⬅︎ this is the only difference from the `getQueryKey` method result 38 | }, 39 | { 40 | header: { 'x-monite-version': '1.0.0' }, 41 | query: { id__in: ['1', '2'] } 42 | } 43 | ]); 44 | ``` 45 | -------------------------------------------------------------------------------- /packages/ts-factory-code-generator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openapi-qraft/ts-factory-code-generator", 3 | "version": "1.0.2", 4 | "private": true, 5 | "type": "commonjs", 6 | "scripts": { 7 | "build": "yarn clean && tsc --build", 8 | "codegen": "yarn exec ./generate-factory-code-generator.mjs", 9 | "clean": "rimraf dist/", 10 | "lint": "eslint" 11 | }, 12 | "main": "dist/index.js", 13 | "types": "dist/index.d.ts", 14 | "exports": { 15 | ".": { 16 | "types": "./dist/index.d.ts", 17 | "import": "./dist/index.js" 18 | }, 19 | "./*": { 20 | "types": "./dist/*.d.ts", 21 | "import": "./dist/*.js" 22 | }, 23 | "./package.json": "./package.json" 24 | }, 25 | "typesVersions": { 26 | "*": { 27 | "*": [ 28 | "dist/*" 29 | ] 30 | } 31 | }, 32 | "dependencies": { 33 | "ts-factory-code-generator-generator": "^0.7.0", 34 | "typescript-5.5.4": "npm:typescript@5.5.4" 35 | }, 36 | "devDependencies": { 37 | "@openapi-qraft/eslint-config": "workspace:*", 38 | "@types/node": "^22.5.5", 39 | "eslint": "^9.39.1", 40 | "rimraf": "^6.1.2" 41 | }, 42 | "repository": { 43 | "type": "git", 44 | "url": "git+https://github.com/OpenAPI-Qraft/openapi-qraft.git", 45 | "directory": "packages/cli" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.github/actions/spelling/patterns.txt: -------------------------------------------------------------------------------- 1 | # See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns 2 | 3 | # Questionably acceptable forms of `in to` 4 | # Personally, I prefer `log into`, but people object 5 | # https://www.tprteaching.com/log-into-log-in-to-login/ 6 | \b(?:[Ll]og|[Ss]ign) in to\b 7 | 8 | # to opt in 9 | \bto opt in\b 10 | 11 | # acceptable duplicates 12 | # ls directory listings 13 | [-bcdlpsw](?:[-r][-w][-Ssx]){3}\s+\d+\s+\S+\s+\S+\s+\d+\s+ 14 | # mount 15 | \bmount\s+-t\s+(\w+)\s+\g{-1}\b 16 | # C types and repeated CSS values 17 | \s(auto|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?: \g{-1})+\s 18 | # C struct 19 | \bstruct\s+(\w+)\s+\g{-1}\b 20 | # go templates 21 | \s(\w+)\s+\g{-1}\s+\`(?:graphql|inject|json|yaml): 22 | # doxygen / javadoc / .net 23 | (?:[\\@](?:brief|groupname|t?param|return|retval)|(?:public|private)(?:\s+static|\s+readonly)*)(?:\s+\{\w+\}|)\s+(\w+)\s+\g{-1}\s 24 | 25 | # Commit message -- Signed-off-by and friends 26 | ^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$ 27 | 28 | # Autogenerated revert commit message 29 | ^This reverts commit [0-9a-f]{40}\.$ 30 | 31 | # ignore long runs of a single character: 32 | \b([A-Za-z])\g{-1}{3,}\b 33 | 34 | \b(?:queryclient)[\w]+ 35 | -------------------------------------------------------------------------------- /packages/cli/src/bin.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { extractArgvPluginOptions } from './bin.js'; 3 | 4 | describe('bin', () => { 5 | describe('extractArgvPluginOptions(...)', () => { 6 | it('returns single plugin', () => { 7 | expect( 8 | extractArgvPluginOptions(['--plugin', 'tanstack-query-react']) 9 | ).toEqual({ 10 | argv: [], 11 | plugins: ['tanstack-query-react'], 12 | }); 13 | }); 14 | 15 | it('filters out plugin options', () => { 16 | expect( 17 | extractArgvPluginOptions([ 18 | '--fake-boolean', 19 | '--plugin', 20 | 'tanstack-query-react', 21 | '--input', 22 | 'openapi.json', 23 | ]) 24 | ).toEqual({ 25 | argv: ['--fake-boolean', '--input', 'openapi.json'], 26 | plugins: ['tanstack-query-react'], 27 | }); 28 | }); 29 | 30 | it('extracts multiple plugins if specified', () => { 31 | expect( 32 | extractArgvPluginOptions([ 33 | '--plugin', 34 | 'tanstack-query-react', 35 | '--plugin', 36 | 'tanstack-query-react-2', 37 | ]) 38 | ).toEqual({ 39 | argv: [], 40 | plugins: ['tanstack-query-react', 'tanstack-query-react-2'], 41 | }); 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /packages/openapi-typescript-plugin/src/lib/createOpenapiTypesImportPath.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { createOpenapiTypesImportPath } from './createOpenapiTypesImportPath.js'; 3 | 4 | describe('createOpenapiTypesImportPath', () => { 5 | it('should create import path with explicit extensions ".js" and ".d.ts"', () => { 6 | expect(createOpenapiTypesImportPath('schema.d.ts', '.js')).toBe( 7 | '../schema.d.ts' 8 | ); 9 | }); 10 | 11 | it('should create import path with explicit extensions "undefined" and ".d.ts"', () => { 12 | expect(createOpenapiTypesImportPath('schema.d.ts', undefined)).toBe( 13 | '../schema.d.ts' 14 | ); 15 | }); 16 | 17 | it('should create import path with explicit extensions "undefined" from ".ts"', () => { 18 | expect(createOpenapiTypesImportPath('schema.ts', undefined)).toBe( 19 | '../schema.ts' 20 | ); 21 | }); 22 | 23 | it('should create import path with explicit extensions ".js" from ".ts"', () => { 24 | expect(createOpenapiTypesImportPath('schema.ts', '.js')).toBe( 25 | '../schema.js' 26 | ); 27 | }); 28 | 29 | it('should create import path with explicit extensions ".ts" from ".ts"', () => { 30 | expect(createOpenapiTypesImportPath('schema.ts', '.ts')).toBe( 31 | '../schema.ts' 32 | ); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/react-client/src/lib/composeBaseQueryKey.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | ServiceOperationInfiniteQueryKey, 3 | ServiceOperationQueryKey, 4 | } from '@openapi-qraft/tanstack-query-react-types'; 5 | import type { OperationSchema } from './requestFn.js'; 6 | 7 | export function composeBaseQueryKey( 8 | schema: TSchema, 9 | parameters: TParams | undefined, 10 | infinite: undefined 11 | ): [TSchema, TParams]; 12 | export function composeBaseQueryKey( 13 | schema: TSchema, 14 | parameters: TParams | undefined, 15 | infinite: true 16 | ): ServiceOperationInfiniteQueryKey; 17 | export function composeBaseQueryKey( 18 | schema: TSchema, 19 | parameters: TParams | undefined, 20 | infinite: false 21 | ): ServiceOperationQueryKey; 22 | export function composeBaseQueryKey( 23 | schema: TSchema, 24 | parameters: TParams | undefined, 25 | infinite: boolean | undefined 26 | ): 27 | | ServiceOperationQueryKey 28 | | ServiceOperationInfiniteQueryKey 29 | | [TSchema, TParams] { 30 | return [ 31 | typeof infinite === 'boolean' ? { ...schema, infinite } : schema, 32 | parameters ?? ({} as TParams), 33 | ]; 34 | } 35 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/useSuspenseInfiniteQuery.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { 4 | OperationSchema, 5 | ServiceOperationUseSuspenseInfiniteQuery, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { 8 | DefaultError, 9 | InfiniteData, 10 | UseSuspenseInfiniteQueryResult, 11 | } from '@tanstack/react-query'; 12 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 13 | import { useSuspenseInfiniteQuery as useSuspenseInfiniteQueryTanstack } from '@tanstack/react-query'; 14 | import { useComposeUseQueryOptions } from '../lib/useComposeUseQueryOptions.js'; 15 | 16 | export const useSuspenseInfiniteQuery: < 17 | TQueryFnData, 18 | TError = DefaultError, 19 | TData = InfiniteData, 20 | >( 21 | qraftOptions: CreateAPIQueryClientOptions, 22 | schema: OperationSchema, 23 | args: Parameters< 24 | ServiceOperationUseSuspenseInfiniteQuery< 25 | OperationSchema, 26 | unknown, 27 | unknown, 28 | DefaultError 29 | >['useSuspenseInfiniteQuery'] 30 | > 31 | ) => UseSuspenseInfiniteQueryResult = ( 32 | qraftOptions, 33 | schema, 34 | args 35 | ) => { 36 | return useSuspenseInfiniteQueryTanstack( 37 | // @ts-expect-error - Too complex to type 38 | ...useComposeUseQueryOptions(qraftOptions, schema, args, true) 39 | ) as never; 40 | }; 41 | -------------------------------------------------------------------------------- /packages/plugin/src/lib/open-api/getServices.spec.ts: -------------------------------------------------------------------------------- 1 | import openAPI from '@openapi-qraft/test-fixtures/openapi.json' with { type: 'json' }; 2 | import { describe, expect, it } from 'vitest'; 3 | import { filterDocumentPaths } from '../filterDocumentPaths.js'; 4 | import { getServices } from './getServices.js'; 5 | 6 | describe('getServices', () => { 7 | it('matches snapshot with default options', () => { 8 | expect(getServices(openAPI)).toMatchSnapshot(); 9 | }); 10 | 11 | it('matches snapshot with custom `postfixServices`', () => { 12 | expect(getServices(openAPI, { postfixServices: 'Srv' })).toMatchSnapshot(); 13 | }); 14 | 15 | it('matches snapshot with custom `servicesGlob`', () => { 16 | expect( 17 | // @ts-expect-error - JSON OpenAPI schema does not match to OpenAPI3 18 | getServices(filterDocumentPaths(openAPI, ['/files/**']), { 19 | serviceNameBase: 'endpoint[0]', 20 | postfixServices: 'Service', 21 | }) 22 | ).toMatchSnapshot(); 23 | }); 24 | 25 | it('matches snapshot with "serviceNameBase: endpoint"', () => { 26 | expect( 27 | getServices(openAPI, { serviceNameBase: 'endpoint[0]' }) 28 | ).toMatchSnapshot(); 29 | }); 30 | 31 | it('matches snapshot with "serviceNameBase: tags"', () => { 32 | expect(getServices(openAPI, { serviceNameBase: 'tags' })).toMatchSnapshot(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/test-fixtures/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @openapi-qraft/test-fixtures 2 | 3 | ## 1.1.1 4 | 5 | ### Patch Changes 6 | 7 | - 8f90621: Add support for responses with `$ref` specification. 8 | 9 | ## 1.1.0 10 | 11 | ### Minor Changes 12 | 13 | - c9afb3b: Generate `null` type and return `null` data for the empty (204) responses instead of an empty object `{}`. 14 | 15 | ## 1.1.0-beta.1 16 | 17 | ### Minor Changes 18 | 19 | - c9afb3b: Generate `null` type and return `null` data for the empty (204) responses instead of an empty object `{}`. 20 | 21 | ## 1.0.2-beta.0 22 | 23 | ### Patch Changes 24 | 25 | - ece9c58: Generate types for empty responses 26 | 27 | Now, for both successful and error responses, we generate types for all possible response outcomes. 28 | For instance, if a 204 (No Content) response is possible, we now explicitly generate a type for it 29 | (represented as `undefined` in the generated code) instead of omitting it. 30 | 31 | ## 1.0.1 32 | 33 | ### Patch Changes 34 | 35 | - 37fbcd3: Enabled provenance support in GitHub Actions for npm publishing. 36 | 37 | Special thanks to [GauBen](https://github.com/GauBen) for implementing provenance publishing support in Yarn — this work 38 | inspired this change. 39 | 40 | ## 1.0.1-provenance-test.0 41 | 42 | ### Patch Changes 43 | 44 | - 37fbcd3: Enabled provenance support in GitHub Actions for npm publishing. 45 | -------------------------------------------------------------------------------- /packages/react-client/src/callbacks/useMutationState.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { 4 | OperationSchema, 5 | ServiceOperationUseMutationState, 6 | } from '@openapi-qraft/tanstack-query-react-types'; 7 | import type { DefaultError, UseMutationResult } from '@tanstack/react-query'; 8 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 9 | import { useMutationState as useMutationStateTanstack } from '@tanstack/react-query'; 10 | import { composeMutationFilters } from '../lib/composeMutationFilters.js'; 11 | 12 | export const useMutationState: < 13 | TData = unknown, 14 | TError = DefaultError, 15 | TVariables = unknown, 16 | TContext = unknown, 17 | >( 18 | qraftOptions: CreateAPIQueryClientOptions | undefined, 19 | schema: OperationSchema, 20 | args: Parameters< 21 | ServiceOperationUseMutationState< 22 | OperationSchema, 23 | object | undefined, 24 | TVariables, 25 | TData, 26 | DefaultError 27 | >['useMutationState'] 28 | > 29 | ) => UseMutationResult = ( 30 | qraftOptions, 31 | schema, 32 | args 33 | ) => { 34 | const [options] = args; 35 | 36 | return useMutationStateTanstack( 37 | { 38 | ...options, 39 | filters: composeMutationFilters(schema, options?.filters), 40 | } as never, 41 | qraftOptions?.queryClient 42 | ) as never; 43 | }; 44 | -------------------------------------------------------------------------------- /packages/tanstack-query-react-types/src/service-operation/ServiceOperationGetQueryState.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AreAllOptional, 3 | DeepReadonly, 4 | OperationInfiniteData, 5 | ServiceOperationInfiniteQueryKey, 6 | ServiceOperationQueryKey, 7 | } from '@openapi-qraft/tanstack-query-react-types'; 8 | import type { QueryState } from '@tanstack/react-query'; 9 | 10 | export interface ServiceOperationGetQueryState< 11 | TSchema extends { url: string; method: string }, 12 | TOperationQueryFnData, 13 | TQueryParams, 14 | TError, 15 | > { 16 | getQueryState( 17 | parameters: 18 | | ServiceOperationQueryKey 19 | | (AreAllOptional extends true 20 | ? DeepReadonly | void 21 | : DeepReadonly) 22 | ): QueryState | undefined; 23 | 24 | getInfiniteQueryState( 25 | parameters: AreAllOptional extends true 26 | ? 27 | | DeepReadonly 28 | | ServiceOperationInfiniteQueryKey 29 | | void 30 | : 31 | | DeepReadonly 32 | | ServiceOperationInfiniteQueryKey 33 | ): 34 | | QueryState< 35 | OperationInfiniteData, 36 | TError 37 | > 38 | | undefined; 39 | } 40 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.x/query-client/getInfiniteQueryData.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: getInfiniteQueryData() 3 | --- 4 | 5 | # getInfiniteQueryData(...) 6 | 7 | The method enables direct access to the `QueryClient` cache to retrieve the data for a specific _InfiniteQuery_. 8 | See the TanStack [_queryClient.getQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerydata) documentation. 9 | 10 | ```ts 11 | const data = qraft...getInfiniteQueryData( 12 | parameters, 13 | queryClient 14 | ); 15 | ``` 16 | 17 | ### Arguments 18 | 19 | 1. `parameters: { path, query, header } | {} | QueryKey` 20 | - **Required** parameters to retrieve the data from the cache. 21 | - Instead of an object with `{path, query, header}`, you can pass a `QueryKey` as an array 22 | which is also strictly-typed ✨ 23 | 2. `queryClient: QueryClient` 24 | - **Required** `QueryClient` instance to use 25 | 26 | ### Returns 27 | 28 | The data from the _Query Cache_ for the specific query, strictly-typed ✨ 29 | 30 | ### Example 31 | 32 | ```tsx 33 | const fileListPages = qraft.files.getFiles.getInfiniteQueryData({}, queryClient); 34 | 35 | expect(fileListPages).toEqual({ 36 | pageParams: [ 37 | { page: 1 }, 38 | { page: 2 }, 39 | ], 40 | pages: [ 41 | [file1, file2], 42 | [file3, file4] 43 | ], 44 | }); 45 | ``` 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenAPI Qraft 2 | 3 | This repository houses the OpenAPI Qraft tools, designed to enhance the development experience by providing 4 | generated typesafe TanStack Query wrapper. 5 | 6 | ## 📦 Packages 7 | 8 | ### [`@openapi-qraft/cli` 🔗](./packages/cli/README.md) 9 | 10 | A powerful command-line utility for generating service declarations and typed **TanStack Query** interfaces directly from an 11 | **OpenAPI Schema**. 12 | 13 | [Read More](./packages/cli/README.md) 14 | 15 | ### [`@openapi-qraft/react` 🔗](./packages/react-client/README.md) 16 | 17 | A modular **TypeScript** client that facilitates type-safe API requests in React applications, leveraging **TanStack Query**. It 18 | uses a Proxy-based architecture to dynamically call **React Hooks with typed parameters**. 19 | 20 | **Main Features:** 21 | 22 | - Type-safe API Requests 23 | - Dynamic Proxy-Based Hooks for TanStack React Query 24 | - Safe and compatible integration with TanStack Query 25 | 26 | [Read More](./packages/react-client/README.md) 27 | 28 | ## 🤝 Contributing 29 | 30 | Contributions to the OpenAPI Qraft are highly appreciated. Whether it's improving documentation, adding new 31 | features, or reporting issues, your help makes a big difference in making these tools better for everyone. 32 | 33 | ## 📄 License 34 | 35 | All packages within this repository are licensed under the [MIT License](./LICENSE.txt). 36 | -------------------------------------------------------------------------------- /.changeset/deprecate-version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if [ $# -ne 1 ]; then 4 | echo "Usage: $0 " 5 | echo "Example: $0 2.1.0-beta.0" 6 | exit 1 7 | fi 8 | 9 | VERSION_TO_DEPRECATE=$1 10 | 11 | confirm() { 12 | if [ -z "$CI" ] && [ -z "$GITHUB_ACTIONS" ] && [ -z "$GITLAB_CI" ]; then 13 | echo "You are about to deprecate version $VERSION_TO_DEPRECATE for all packages in the packages directory" 14 | echo "This will mark the version as deprecated in npm registry. Do you want to continue? (y/n)" 15 | read ans 16 | case $ans in 17 | [Yy]* ) ;; 18 | * ) echo "Operation cancelled"; exit 1 ;; 19 | esac 20 | fi 21 | } 22 | 23 | confirm 24 | 25 | cd packages 26 | 27 | for dir in */; do 28 | if [ -f "${dir}package.json" ]; then 29 | package_name=$(node -p "require('./${dir}package.json').name") 30 | 31 | if [ -n "$package_name" ]; then 32 | echo "Processing package: $package_name" 33 | 34 | echo "Deprecating $package_name@$VERSION_TO_DEPRECATE..." 35 | npm deprecate "$package_name@$VERSION_TO_DEPRECATE" "This version is deprecated. Please use the latest stable version instead" || true 36 | 37 | echo "Processed $package_name" 38 | echo "------------------------" 39 | fi 40 | fi 41 | done -------------------------------------------------------------------------------- /packages/openapi-typescript-plugin/src/lib/createExportsForComponentSchemas.test.ts: -------------------------------------------------------------------------------- 1 | import schema from '@openapi-qraft/test-fixtures/openapi.json' with { type: 'json' }; 2 | import openapiTS, { OpenAPI3 } from 'openapi-typescript'; 3 | import { describe, expect, it } from 'vitest'; 4 | import { getExportedNames } from './createExportsForComponentSchemas.js'; 5 | 6 | describe('getExportedNames(...)', () => { 7 | it('returns exported names without enums', async () => { 8 | const ast = await openapiTS(schema as OpenAPI3, { 9 | silent: true, 10 | }); 11 | 12 | expect(getExportedNames(ast)).toEqual([ 13 | 'paths', 14 | 'webhooks', 15 | 'components', 16 | '$defs', 17 | 'operations', 18 | ]); 19 | }); 20 | 21 | it('returns exported names with enums', async () => { 22 | const ast = await openapiTS(schema as OpenAPI3, { 23 | silent: true, 24 | enum: true, 25 | }); 26 | 27 | expect(getExportedNames(ast)).toEqual([ 28 | 'paths', 29 | 'webhooks', 30 | 'components', 31 | '$defs', 32 | 'operations', 33 | 'ApprovalPolicyStatus', 34 | 'OrderEnum', 35 | ]); 36 | }); 37 | 38 | it('return an empty array if no components', async () => { 39 | expect( 40 | getExportedNames( 41 | // @ts-expect-error - invalid AST 42 | [{}, []] 43 | ) 44 | ).toEqual([]); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /packages/react-client/src/lib/callQueryClientMethodWithMutationFilters.ts: -------------------------------------------------------------------------------- 1 | import type { QueryClient } from '@tanstack/react-query'; 2 | import type { CreateAPIQueryClientOptions } from '../qraftAPIClient.js'; 3 | import type { OperationSchema } from './requestFn.js'; 4 | import { composeMutationFilters } from './composeMutationFilters.js'; 5 | 6 | /** 7 | * Calls a query client method with mutation filters and options, 8 | * and automatically composes the `MutationKey` based on the schema and parameters. 9 | */ 10 | export function callQueryClientMethodWithMutationFilters< 11 | QFMethod extends QueryFilterMethods, 12 | >( 13 | qraftOptions: CreateAPIQueryClientOptions, 14 | queryFilterMethod: QFMethod, 15 | schema: OperationSchema, 16 | args: [...Parameters<(typeof QueryClient.prototype)[QFMethod]>, QueryClient] 17 | ): ReturnType<(typeof QueryClient.prototype)[QFMethod]> { 18 | const filters = args[0]; 19 | const queryClient = qraftOptions.queryClient; 20 | 21 | // @ts-expect-error - Too complex to type 22 | return queryClient[queryFilterMethod]( 23 | composeMutationFilters(schema, filters as never), 24 | // @ts-expect-error - Argument types are too complex 25 | ...args.slice(1, args.length) 26 | ); 27 | } 28 | 29 | type QueryFiltersMethod = 30 | QFMethod; 31 | 32 | type QueryFilterMethods = QueryFiltersMethod<'isMutating'>; 33 | -------------------------------------------------------------------------------- /website/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import Link from '@docusaurus/Link'; 3 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 4 | import Layout from '@theme/Layout'; 5 | import HomepageFeatures from '@site/src/components/HomepageFeatures'; 6 | 7 | import Heading from '@theme/Heading'; 8 | import styles from './index.module.css'; 9 | 10 | function HomepageHeader() { 11 | const { siteConfig } = useDocusaurusContext(); 12 | return ( 13 |
14 |
15 | 16 | {siteConfig.title} 17 | 18 |

{siteConfig.tagline}

19 |
20 | 21 | Get Started 22 | 23 |
24 |
25 |
26 | ); 27 | } 28 | 29 | export default function Home() { 30 | const { siteConfig } = useDocusaurusContext(); 31 | return ( 32 | 33 | 34 |
35 | 36 |
37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /packages/openapi-typescript-plugin/src/lib/createOpenapiTypesImportPath.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Create the import path for the OpenAPI types file. 3 | * @param openapiTypesFileName The file name of the OpenAPI types file. Eg: `schema.d.ts` 4 | * @param explicitImportExtensions Whether to include explicit `.js` extensions in the import path. 5 | */ 6 | export function createOpenapiTypesImportPath( 7 | openapiTypesFileName: string, 8 | explicitImportExtensions: '.ts' | '.js' | undefined 9 | ) { 10 | if (openapiTypesFileName.endsWith('.d.ts')) 11 | return `../${getTypeScriptFileBaseName(openapiTypesFileName)}.d.ts`; 12 | 13 | return explicitImportExtensions 14 | ? `../${getTypeScriptFileBaseName(openapiTypesFileName)}${explicitImportExtensions}` 15 | : `../${openapiTypesFileName}`; 16 | } 17 | 18 | /** 19 | * Get the base name of the TypeScript file without the extension. 20 | * Removes `.d.ts` or `.ts` from the file name. 21 | */ 22 | function getTypeScriptFileBaseName(openapiTypesFileName: string) { 23 | return openapiTypesFileName.replace(getTsExtensionRegexp(), ''); 24 | } 25 | 26 | /** 27 | * Check if the file name is a valid TypeScript file name. 28 | * Eg: `schema.d.ts`, `schema.ts` 29 | */ 30 | export function isValidTypeScriptFileName(fileName: string) { 31 | return getTsExtensionRegexp().test(fileName); 32 | } 33 | 34 | function getTsExtensionRegexp() { 35 | return /\.(d\.)?ts$/; 36 | } 37 | --------------------------------------------------------------------------------