├── .changeset ├── README.md └── config.json ├── .github ├── FUNDING.yml └── workflows │ ├── release.yaml │ └── tests.yaml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── CONTRIBUTING.md ├── README.md ├── dev-react.mjs ├── dev.mjs ├── docs ├── cli │ ├── codegen.mdx │ ├── config.mdx │ ├── javascript.mdx │ └── programmatic.mdx ├── client │ ├── api │ │ ├── classes │ │ │ ├── eventhandler.md │ │ │ ├── gqlesserror.md │ │ │ └── selection.md │ │ ├── enums │ │ │ └── selectiontype.md │ │ ├── index.md │ │ ├── interfaces │ │ │ ├── accessorcache.md │ │ │ ├── assignselections.md │ │ │ ├── buildandfetchselections.md │ │ │ ├── buildselection.md │ │ │ ├── clientoptions.md │ │ │ ├── gqlessclient.md │ │ │ ├── hydratecache.md │ │ │ ├── hydratecacheoptions.md │ │ │ ├── inlineresolved.md │ │ │ ├── inlineresolveoptions.md │ │ │ ├── innerclientstate.md │ │ │ ├── interceptormanager.md │ │ │ ├── mutate.md │ │ │ ├── mutatehelpers.md │ │ │ ├── parseschematypeinfo.md │ │ │ ├── prefetch.md │ │ │ ├── preparerender.md │ │ │ ├── prepassobjkey.md │ │ │ ├── refetch.md │ │ │ ├── resolved.md │ │ │ ├── resolveoptions.md │ │ │ ├── resolvers.md │ │ │ ├── retryconfigstate.md │ │ │ ├── scalars.md │ │ │ ├── scheduler.md │ │ │ ├── schema.md │ │ │ ├── selectionmanager.md │ │ │ ├── setcache.md │ │ │ ├── subscribeevents.md │ │ │ ├── subscriptionsclient.md │ │ │ └── type.md │ │ └── modules.md │ ├── config.mdx │ ├── fetching-data.mdx │ ├── helper-functions.mdx │ ├── mutations.mdx │ ├── persistence.mdx │ ├── subscriptions.mdx │ └── upload.mdx ├── contributing.mdx ├── development │ └── logger.mdx ├── getting-started.mdx ├── intro.mdx ├── intro │ ├── features.mdx │ ├── how-it-works.mdx │ └── new-in-2.mdx └── react │ ├── api │ ├── index.md │ ├── interfaces │ │ ├── corehelpers.md │ │ ├── createreactclientoptions.md │ │ ├── fetchmorecallbackargs.md │ │ ├── graphqlhoc.md │ │ ├── graphqlhocoptions.md │ │ ├── metastate.md │ │ ├── preparedquery.md │ │ ├── preparequery.md │ │ ├── preparereactrender.md │ │ ├── reactclient.md │ │ ├── reactclientdefaults.md │ │ ├── usehydratecache.md │ │ ├── usehydratecacheoptions.md │ │ ├── uselazyquery.md │ │ ├── uselazyqueryoptions.md │ │ ├── uselazyquerystate.md │ │ ├── usemetastate.md │ │ ├── usemetastateoptions.md │ │ ├── usemutation.md │ │ ├── usemutationoptions.md │ │ ├── usemutationstate.md │ │ ├── usepaginatedquery.md │ │ ├── usepaginatedquerydata.md │ │ ├── usepaginatedquerymergeparams.md │ │ ├── usepaginatedqueryoptions.md │ │ ├── usepreparedqueryoptions.md │ │ ├── usequery.md │ │ ├── usequeryoptions.md │ │ ├── usequerystate.md │ │ ├── userefetch.md │ │ ├── userefetchoptions.md │ │ ├── userefetchstate.md │ │ ├── usesubscription.md │ │ ├── usetransactionquery.md │ │ └── usetransactionquerystate.md │ └── modules.md │ ├── config.mdx │ ├── fetching-data.mdx │ ├── meta.mdx │ ├── mutations.mdx │ ├── ssr.mdx │ ├── subscriptions.mdx │ └── suspense.mdx ├── examples ├── cra │ ├── .env.local │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── gqless.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── sandbox.config.json │ ├── src │ │ ├── components │ │ │ ├── CreatePost.tsx │ │ │ ├── Hello.tsx │ │ │ ├── Login.tsx │ │ │ ├── MyPosts.tsx │ │ │ └── Register.tsx │ │ ├── gqless │ │ │ ├── index.ts │ │ │ └── schema.generated.ts │ │ ├── hooks │ │ │ └── currentUser.ts │ │ ├── index.css │ │ ├── index.tsx │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ └── setupTests.ts │ └── tsconfig.json ├── github │ ├── gqless.config.cjs │ ├── jest.config.js │ ├── package.json │ ├── src │ │ └── gqless │ │ │ ├── index.ts │ │ │ └── schema.generated.ts │ └── test │ │ └── index.test.ts ├── mercurius │ ├── .browserslistrc │ ├── .gitignore │ ├── LICENSE.md │ ├── README.md │ ├── generate.ts │ ├── gqless.config.cjs │ ├── jest.config.js │ ├── listen.js │ ├── package.json │ ├── src │ │ ├── generated │ │ │ ├── gqless.ts │ │ │ ├── mercurius.ts │ │ │ └── schema.generated.ts │ │ ├── graphql │ │ │ └── operations.gql │ │ └── index.ts │ ├── test │ │ ├── example.test.ts │ │ └── tsconfig.json │ └── tsconfig.json └── react │ ├── api │ ├── graphql.ts │ └── server.ts │ ├── gqless.config.cjs │ ├── next-env.d.ts │ ├── next.config.js │ ├── open-browser.mjs │ ├── package.json │ ├── src │ ├── components │ │ ├── NoSSR.tsx │ │ ├── client.ts │ │ ├── common.ts │ │ └── meta.tsx │ ├── graphql │ │ ├── gqless.ts │ │ ├── mercurius.ts │ │ └── schema.generated.ts │ └── pages │ │ ├── _app.tsx │ │ ├── cache.tsx │ │ ├── emptyArrays.tsx │ │ ├── error.tsx │ │ ├── index.tsx │ │ ├── normalized.tsx │ │ ├── pagination.tsx │ │ ├── pagination_infinite_scroll.tsx │ │ ├── playground.tsx │ │ ├── polling.tsx │ │ ├── preparedQuery.tsx │ │ ├── prepass.tsx │ │ ├── refetch.tsx │ │ ├── ssr.tsx │ │ ├── stringArray.tsx │ │ ├── subscriptions.tsx │ │ ├── transactionQuery1.tsx │ │ ├── transactionQuery2.tsx │ │ ├── uploadFile.tsx │ │ └── useQueryTest.tsx │ └── tsconfig.json ├── internal ├── build-utils │ ├── bin │ │ ├── build.js │ │ ├── github-release.js │ │ └── watch.js │ ├── package.json │ ├── src │ │ ├── buildWriteTypes.js │ │ ├── config.js │ │ ├── index.js │ │ ├── rollup-watch-worker.mjs │ │ └── writeIndex.js │ └── tsconfig.json ├── gqless.sketch ├── test-utils │ ├── .gitignore │ ├── LICENSE.md │ ├── README.md │ ├── bin │ │ └── jest-test.js │ ├── jest.config.js │ ├── jest.config.ts │ ├── package.json │ ├── src │ │ ├── app.d.ts │ │ ├── app.ts │ │ ├── index.d.ts │ │ └── index.ts │ ├── test │ │ ├── _generated.ts │ │ ├── index.test.ts │ │ └── tsconfig.json │ ├── tsconfig.json │ └── types │ │ ├── app.d.ts │ │ └── index.d.ts └── website │ ├── .prettierrc │ ├── docusaurus.config.js │ ├── fix-typedoc-plugin.js │ ├── fix-typedoc.js │ ├── package-lock.json │ ├── package.json │ ├── sidebars.js │ ├── sidebars │ ├── client.js │ └── react.js │ ├── src │ ├── components │ │ ├── Arrow.tsx │ │ ├── Example.tsx │ │ ├── Examples │ │ │ ├── App.tsx │ │ │ ├── Embed.tsx │ │ │ ├── NavLink.tsx │ │ │ └── Sidebar.tsx │ │ ├── Feature.tsx │ │ ├── Overflow.tsx │ │ └── index.tsx │ ├── pages │ │ ├── examples │ │ │ ├── index.tsx │ │ │ └── suspense │ │ │ │ ├── auth.tsx │ │ │ │ └── query.tsx │ │ └── index.tsx │ ├── plugins │ │ └── remark-yarn2npm.js │ ├── style.css │ └── theme │ │ └── Root.tsx │ ├── static │ ├── favicon.ico │ ├── fonts.css │ ├── fonts │ │ ├── ColfaxWebBold.woff2 │ │ ├── ColfaxWebLight.woff2 │ │ ├── ColfaxWebMedium.woff2 │ │ ├── ColfaxWebRegular.woff2 │ │ └── OperatorMono.otf │ ├── icon │ │ ├── android-icon-144x144.png │ │ ├── android-icon-192x192.png │ │ ├── android-icon-36x36.png │ │ ├── android-icon-48x48.png │ │ ├── android-icon-72x72.png │ │ ├── android-icon-96x96.png │ │ ├── apple-icon-114x114.png │ │ ├── apple-icon-120x120.png │ │ ├── apple-icon-144x144.png │ │ ├── apple-icon-152x152.png │ │ ├── apple-icon-180x180.png │ │ ├── apple-icon-57x57.png │ │ ├── apple-icon-60x60.png │ │ ├── apple-icon-72x72.png │ │ ├── apple-icon-76x76.png │ │ ├── apple-icon-precomposed.png │ │ ├── apple-icon.png │ │ ├── browserconfig.xml │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── manifest.json │ │ ├── ms-icon-144x144.png │ │ ├── ms-icon-150x150.png │ │ ├── ms-icon-310x310.png │ │ └── ms-icon-70x70.png │ ├── img │ │ ├── gqless-logo.square.png │ │ ├── graphql.svg │ │ ├── intro │ │ │ ├── client-only_fields.png │ │ │ └── intellisense.png │ │ ├── javascript-output-type-error.png │ │ ├── logger.png │ │ ├── logger │ │ │ ├── devtools_query.png │ │ │ └── devtools_verbose.png │ │ ├── logo-1080p.png │ │ ├── logo-200x85.png │ │ ├── logo-436p.png │ │ ├── logo-full-size.png │ │ ├── logo-sm.svg │ │ ├── logo.png │ │ ├── logo.svg │ │ ├── production_ready.png │ │ ├── react-key-warning.png │ │ ├── react.svg │ │ ├── suspense-ssr.png │ │ └── typescript.png │ ├── powered-by-vercel.svg │ └── video │ │ └── invisible-data-fetching.mp4 │ └── tsconfig.json ├── nodemon.json ├── package.json ├── packages ├── cli │ ├── .browserslistrc │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── bin │ │ └── gqless.js │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── config.ts │ │ ├── generate.ts │ │ ├── index.ts │ │ ├── innerState.ts │ │ ├── inspectWriteGenerate.ts │ │ ├── introspection.ts │ │ ├── prettier.ts │ │ └── writeGenerate.ts │ ├── test │ │ ├── config.test.ts │ │ ├── generate.test.ts │ │ ├── inspectWriteGenerate.test.ts │ │ ├── introspection.test.ts │ │ ├── tsconfig.json │ │ ├── utils.ts │ │ └── writeGenerate.test.ts │ └── tsconfig.json ├── gqless │ ├── .browserslistrc │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── Accessor │ │ │ └── index.ts │ │ ├── Cache │ │ │ ├── accessorCache.ts │ │ │ ├── dataCache.ts │ │ │ ├── index.ts │ │ │ └── persistence.ts │ │ ├── Client │ │ │ ├── client.ts │ │ │ ├── index.ts │ │ │ └── resolvers.ts │ │ ├── Error │ │ │ ├── index.ts │ │ │ └── retry.ts │ │ ├── Events │ │ │ └── index.ts │ │ ├── Helpers │ │ │ ├── casters.ts │ │ │ ├── getFields.ts │ │ │ ├── index.ts │ │ │ ├── prefetch.ts │ │ │ ├── prepass.ts │ │ │ ├── refetch.ts │ │ │ ├── selectFields.ts │ │ │ └── ssr.ts │ │ ├── Interceptor │ │ │ └── index.ts │ │ ├── Normalization │ │ │ └── index.ts │ │ ├── QueryBuilder │ │ │ ├── buildQuery.ts │ │ │ └── index.ts │ │ ├── Scheduler │ │ │ └── index.ts │ │ ├── Schema │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── Selection │ │ │ ├── SelectionBuilder.ts │ │ │ ├── SelectionManager.ts │ │ │ ├── index.ts │ │ │ └── selection.ts │ │ ├── Utils │ │ │ ├── cachedJSON.ts │ │ │ ├── cycle.ts │ │ │ ├── debounce.ts │ │ │ ├── index.ts │ │ │ └── object.ts │ │ └── index.ts │ ├── test │ │ ├── accessor.test.ts │ │ ├── buildQuery.test.ts │ │ ├── cache.test.ts │ │ ├── client.test.ts │ │ ├── error.test.ts │ │ ├── events.test.ts │ │ ├── helpers.test.ts │ │ ├── interceptor.test.ts │ │ ├── persistence.test.ts │ │ ├── playground.test.ts │ │ ├── scheduler.test.ts │ │ ├── schema.test.ts │ │ ├── selection.test.ts │ │ ├── ssr.test.tsx │ │ ├── subscriptions.test.ts │ │ ├── tsconfig.json │ │ └── utils.ts │ └── tsconfig.json ├── logger │ ├── .browserslistrc │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ └── index.ts │ ├── test │ │ └── index.test.ts │ └── tsconfig.json ├── react │ ├── .browserslistrc │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── client.ts │ │ ├── common.ts │ │ ├── index.tsx │ │ ├── meta │ │ │ └── useMetaState.ts │ │ ├── mutation │ │ │ └── useMutation.ts │ │ ├── query │ │ │ ├── hoc.tsx │ │ │ ├── preparedQuery.ts │ │ │ ├── useLazyQuery.ts │ │ │ ├── usePaginatedQuery.ts │ │ │ ├── useQuery.ts │ │ │ ├── useRefetch.ts │ │ │ └── useTransactionQuery.ts │ │ ├── ssr │ │ │ └── ssr.ts │ │ ├── subscription │ │ │ └── useSubscription.ts │ │ └── utils.ts │ ├── test │ │ ├── graphqlHOC.test.tsx │ │ ├── useQuery.test.tsx │ │ └── utils.ts │ └── tsconfig.json └── subscriptions │ ├── .browserslistrc │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── index.ts │ ├── subscription │ │ ├── client.ts │ │ └── protocol.ts │ └── utils.ts │ ├── test │ └── index.test.ts │ ├── tsconfig.dev.json │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── tsconfig.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.5.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "public", 7 | "baseBranch": "master", 8 | "updateInternalDependencies": "patch", 9 | "ignore": [ 10 | "mercurius-example", 11 | "react-example", 12 | "website", 13 | "github-example", 14 | "cra-example" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: gqless 2 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - 'docs/**' 7 | - 'internal/website/**' 8 | - '.vscode/**' 9 | - '.husky/**' 10 | branches: 11 | - master 12 | jobs: 13 | release: 14 | name: Release 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout Repo 18 | uses: actions/checkout@master 19 | with: 20 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 21 | fetch-depth: 0 22 | 23 | - name: Setup Node.js 14.x 24 | uses: actions/setup-node@master 25 | with: 26 | node-version: 14.x 27 | 28 | - name: install pnpm 29 | run: npm i pnpm@latest -g 30 | 31 | - name: Install Dependencies 32 | run: pnpm i --frozen-lockfile 33 | 34 | - name: Test everything 35 | run: pnpm test 36 | 37 | - name: Create Release Pull Request or Publish to npm 38 | id: changesets 39 | uses: changesets/action@master 40 | with: 41 | # This expects you to have a script called release which does a build for your packages and calls changeset publish 42 | publish: pnpm ci:release 43 | version: pnpm ci:version 44 | env: 45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 47 | -------------------------------------------------------------------------------- /.github/workflows/tests.yaml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | pull_request: 5 | paths-ignore: 6 | - 'docs/**' 7 | - 'internal/website/**' 8 | - '.vscode/**' 9 | - '.husky/**' 10 | push: 11 | paths-ignore: 12 | - 'docs/**' 13 | - 'internal/website/**' 14 | - '.vscode/**' 15 | - '.husky/**' 16 | 17 | env: 18 | CI: true 19 | PNPM_CACHE_FOLDER: .pnpm-store 20 | 21 | jobs: 22 | build: 23 | name: Install, Build and Test 24 | runs-on: ${{ matrix.os }} 25 | strategy: 26 | matrix: 27 | node: [12, 14, 16] 28 | os: [ubuntu-latest, windows-latest, macOS-latest] 29 | steps: 30 | - name: Checkout code 31 | uses: actions/checkout@v2 32 | - name: Setup node 33 | uses: actions/setup-node@v2-beta 34 | with: 35 | node-version: ${{ matrix.node }} 36 | - name: Cache pnpm modules 37 | uses: actions/cache@v2 38 | env: 39 | cache-name: cache-pnpm-modules 40 | with: 41 | path: ~/.pnpm-store 42 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node }}-${{ hashFiles('./pnpm-lock.yaml') }} 43 | restore-keys: | 44 | ${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node }}- 45 | 46 | - run: npm install -g pnpm@latest 47 | - name: Node version 48 | run: node --version 49 | - name: pnpm version 50 | run: pnpm --version 51 | - name: Install dependencies and build 52 | run: pnpm install 53 | - name: Test everything 54 | run: pnpm test --workspace-concurrency 1 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .nyc_output 4 | coverage 5 | .next 6 | examples/react/db.json 7 | examples/react/last-browser-open 8 | *.tsbuildinfo 9 | .docusaurus 10 | build 11 | .env -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | pnpx pretty-quick --staged 5 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | workspace-concurrency=4 2 | public-hoist-pattern[]=@types/* 3 | public-hoist-pattern[]=esbuild 4 | public-hoist-pattern[]=typescript 5 | public-hoist-pattern[]=prettier 6 | public-hoist-pattern[]=ts-jest 7 | public-hoist-pattern[]=jest 8 | public-hoist-pattern[]=rollup* 9 | public-hoist-pattern[]=@rollup* 10 | prefer-workspace-packages=true -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | pnpm-lock.yaml -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "semi": true, 4 | "singleQuote": true, 5 | "trailingComma": "es5" 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["silvenon.mdx", "esbenp.prettier-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Check [https://gqless.com/contributing](https://gqless.com/contributing) 4 | -------------------------------------------------------------------------------- /dev.mjs: -------------------------------------------------------------------------------- 1 | import { spawn, execSync } from 'child_process'; 2 | import fkill from 'fkill'; 3 | 4 | execSync('pnpm -r exec --filter gqless -- tsc -m commonjs', { 5 | stdio: 'inherit', 6 | }); 7 | 8 | execSync('pnpm -r --filter test-utils build', { 9 | stdio: 'inherit', 10 | }); 11 | 12 | const processes = ['pnpm dev:start', 'pnpm dev:test'].map((script) => { 13 | return spawn(script, { 14 | detached: true, 15 | shell: true, 16 | }).pid; 17 | }); 18 | 19 | process.on('SIGINT', () => { 20 | fkill(processes, { 21 | force: true, 22 | }).catch(() => {}); 23 | }); 24 | 25 | process.on('exit', () => { 26 | fkill(processes, { 27 | force: true, 28 | }).catch(() => {}); 29 | }); 30 | -------------------------------------------------------------------------------- /docs/client/api/enums/selectiontype.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'selectiontype' 3 | title: 'Enumeration: SelectionType' 4 | sidebar_label: 'SelectionType' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Enumeration: SelectionType 10 | 11 | ## Enumeration members 12 | 13 | ### Mutation 14 | 15 | • **Mutation**: = 1 16 | 17 | Defined in: [packages/gqless/src/Selection/selection.ts:3](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Selection/selection.ts#L3) 18 | 19 | --- 20 | 21 | ### Query 22 | 23 | • **Query**: = 0 24 | 25 | Defined in: [packages/gqless/src/Selection/selection.ts:2](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Selection/selection.ts#L2) 26 | 27 | --- 28 | 29 | ### Subscription 30 | 31 | • **Subscription**: = 2 32 | 33 | Defined in: [packages/gqless/src/Selection/selection.ts:4](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Selection/selection.ts#L4) 34 | -------------------------------------------------------------------------------- /docs/client/api/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'index' 3 | title: 'gqless' 4 | slug: '/client/api' 5 | sidebar_label: 'Readme' 6 | custom_edit_url: null 7 | hide_title: true 8 | --- 9 | 10 | # [GQless](https://gqless.com/getting-started) [![Documentation](https://img.shields.io/badge/documentation-documentation?color=C00B84)](https://gqless.com) [![Twitter](https://img.shields.io/twitter/follow/gqlessdev?label=%40gqlessdev&style=flat&logo=twitter&color=00acee)](https://twitter.com/gqlessdev) 11 | 12 | > GQless is a fully-featured GraphQL client, which lowers the barrier of entry towards using GraphQL. 13 | 14 | Data requirements within your application are picked up automatically, freeing you from having to maintain GraphQL queries by-hand. It offers a first-class TypeScript experience. See API documentation at all times within autocomplete. 15 | 16 | Make breaking changes to your API, and see type-errors exactly where things are breaking, in realtime. No more running a separate validation step. 17 | 18 | **More documentation is available at [gqless.com/getting-started](https://gqless.com/getting-started).** 19 | 20 | 21 | Example usage 22 | 23 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/assignselections.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'assignselections' 3 | title: 'Interface: AssignSelections' 4 | sidebar_label: 'AssignSelections' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: AssignSelections 10 | 11 | ## Callable 12 | 13 | ▸ **AssignSelections**(`source`: _undefined_ \| `null` \| A, `target`: _undefined_ \| `null` \| B): _void_ 14 | 15 | #### Type parameters: 16 | 17 | | Name | Type | 18 | | :--- | :------- | 19 | | `A` | _object_ | 20 | | `B` | _object_ | 21 | 22 | #### Parameters: 23 | 24 | | Name | Type | 25 | | :------- | :------------------------- | 26 | | `source` | _undefined_ \| `null` \| A | 27 | | `target` | _undefined_ \| `null` \| B | 28 | 29 | **Returns:** _void_ 30 | 31 | Defined in: [packages/gqless/src/Accessor/index.ts:132](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Accessor/index.ts#L132) 32 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/buildandfetchselections.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'buildandfetchselections' 3 | title: 'Interface: BuildAndFetchSelections' 4 | sidebar_label: 'BuildAndFetchSelections' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: BuildAndFetchSelections 10 | 11 | ## Callable 12 | 13 | ▸ **BuildAndFetchSelections**(`selections`: _undefined_ \| [_Selection_](../classes/selection.md)[], `type`: `"query"` \| `"mutation"`, `cache?`: CacheInstance, `options?`: FetchResolveOptions, `lastTryParam?`: _boolean_): _Promise_ 14 | 15 | #### Type parameters: 16 | 17 | | Name | Default | 18 | | :------ | :-------- | 19 | | `TData` | _unknown_ | 20 | 21 | #### Parameters: 22 | 23 | | Name | Type | 24 | | :-------------- | :------------------------------------------------------ | 25 | | `selections` | _undefined_ \| [_Selection_](../classes/selection.md)[] | 26 | | `type` | `"query"` \| `"mutation"` | 27 | | `cache?` | CacheInstance | 28 | | `options?` | FetchResolveOptions | 29 | | `lastTryParam?` | _boolean_ | 30 | 31 | **Returns:** _Promise_ 32 | 33 | Defined in: [packages/gqless/src/Client/resolvers.ts:171](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/resolvers.ts#L171) 34 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/buildselection.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'buildselection' 3 | title: 'Interface: BuildSelection' 4 | sidebar_label: 'BuildSelection' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: BuildSelection 10 | 11 | ## Callable 12 | 13 | ▸ **BuildSelection**(`type`: `"query"` \| `"mutation"` \| `"subscription"`, ...`values`: [_BuildSelectionValue_](../modules.md#buildselectionvalue)[]): [_Selection_](../classes/selection.md) 14 | 15 | #### Parameters: 16 | 17 | | Name | Type | 18 | | :---------- | :----------------------------------------------------------- | 19 | | `type` | `"query"` \| `"mutation"` \| `"subscription"` | 20 | | `...values` | [_BuildSelectionValue_](../modules.md#buildselectionvalue)[] | 21 | 22 | **Returns:** [_Selection_](../classes/selection.md) 23 | 24 | Defined in: [packages/gqless/src/Selection/SelectionBuilder.ts:17](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Selection/SelectionBuilder.ts#L17) 25 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/hydratecache.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'hydratecache' 3 | title: 'Interface: HydrateCache' 4 | sidebar_label: 'HydrateCache' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: HydrateCache 10 | 11 | ## Callable 12 | 13 | ▸ **HydrateCache**(`__namedParameters`: [_HydrateCacheOptions_](hydratecacheoptions.md)): _void_ 14 | 15 | #### Parameters: 16 | 17 | | Name | Type | 18 | | :------------------ | :---------------------------------------------- | 19 | | `__namedParameters` | [_HydrateCacheOptions_](hydratecacheoptions.md) | 20 | 21 | **Returns:** _void_ 22 | 23 | Defined in: [packages/gqless/src/Helpers/ssr.ts:22](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Helpers/ssr.ts#L22) 24 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/hydratecacheoptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'hydratecacheoptions' 3 | title: 'Interface: HydrateCacheOptions' 4 | sidebar_label: 'HydrateCacheOptions' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: HydrateCacheOptions 10 | 11 | ## Properties 12 | 13 | ### cacheSnapshot 14 | 15 | • **cacheSnapshot**: _string_ 16 | 17 | Cache snapshot, returned from `prepareRender` 18 | 19 | Defined in: [packages/gqless/src/Helpers/ssr.ts:10](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Helpers/ssr.ts#L10) 20 | 21 | --- 22 | 23 | ### shouldRefetch 24 | 25 | • `Optional` **shouldRefetch**: _number_ \| _boolean_ 26 | 27 | If it should refetch everything after 28 | 29 | Specify a number greater than `0` to delay the refetch that amount in ms 30 | 31 | **`default`** 32 | false 33 | 34 | Defined in: [packages/gqless/src/Helpers/ssr.ts:19](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Helpers/ssr.ts#L19) 35 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/inlineresolved.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'inlineresolved' 3 | title: 'Interface: InlineResolved' 4 | sidebar_label: 'InlineResolved' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: InlineResolved 10 | 11 | ## Callable 12 | 13 | ▸ **InlineResolved**(`fn`: () => TData, `options?`: [_InlineResolveOptions_](inlineresolveoptions.md)): TData \| _Promise_ 14 | 15 | #### Type parameters: 16 | 17 | | Name | Default | 18 | | :------ | :-------- | 19 | | `TData` | _unknown_ | 20 | 21 | #### Parameters: 22 | 23 | | Name | Type | 24 | | :--------- | :-------------------------------------------------------- | 25 | | `fn` | () => TData | 26 | | `options?` | [_InlineResolveOptions_](inlineresolveoptions.md) | 27 | 28 | **Returns:** TData \| _Promise_ 29 | 30 | Defined in: [packages/gqless/src/Client/resolvers.ts:196](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/resolvers.ts#L196) 31 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/mutatehelpers.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'mutatehelpers' 3 | title: 'Interface: MutateHelpers' 4 | sidebar_label: 'MutateHelpers' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: MutateHelpers 10 | 11 | ## Type parameters 12 | 13 | | Name | Type | 14 | | :---------------------- | :------- | 15 | | `GeneratedSchema` | _object_ | 16 | | `GeneratedSchema.query` | _object_ | 17 | 18 | ## Properties 19 | 20 | ### assignSelections 21 | 22 | • **assignSelections**: [_AssignSelections_](assignselections.md) 23 | 24 | Defined in: [packages/gqless/src/Client/client.ts:132](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/client.ts#L132) 25 | 26 | --- 27 | 28 | ### query 29 | 30 | • **query**: GeneratedSchema[``"query"``] 31 | 32 | Defined in: [packages/gqless/src/Client/client.ts:130](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/client.ts#L130) 33 | 34 | --- 35 | 36 | ### setCache 37 | 38 | • **setCache**: [_SetCache_](setcache.md) 39 | 40 | Defined in: [packages/gqless/src/Client/client.ts:131](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/client.ts#L131) 41 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/parseschematypeinfo.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'parseschematypeinfo' 3 | title: 'Interface: ParseSchemaTypeInfo' 4 | sidebar_label: 'ParseSchemaTypeInfo' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: ParseSchemaTypeInfo 10 | 11 | ## Properties 12 | 13 | ### isArray 14 | 15 | • **isArray**: _boolean_ 16 | 17 | Defined in: [packages/gqless/src/Schema/types.ts:33](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L33) 18 | 19 | --- 20 | 21 | ### isNullable 22 | 23 | • **isNullable**: _boolean_ 24 | 25 | Defined in: [packages/gqless/src/Schema/types.ts:32](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L32) 26 | 27 | --- 28 | 29 | ### nullableItems 30 | 31 | • **nullableItems**: _boolean_ 32 | 33 | Defined in: [packages/gqless/src/Schema/types.ts:34](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L34) 34 | 35 | --- 36 | 37 | ### pureType 38 | 39 | • **pureType**: _string_ 40 | 41 | Defined in: [packages/gqless/src/Schema/types.ts:31](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L31) 42 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/prefetch.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'prefetch' 3 | title: 'Interface: Prefetch' 4 | sidebar_label: 'Prefetch' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: Prefetch 10 | 11 | ## Type parameters 12 | 13 | | Name | Type | 14 | | :---------------------- | :------- | 15 | | `GeneratedSchema` | _object_ | 16 | | `GeneratedSchema.query` | _object_ | 17 | 18 | ## Callable 19 | 20 | ▸ **Prefetch**(`fn`: (`query`: GeneratedSchema[``"query"``]) => TData): TData \| _Promise_ & { `schedulerPromise`: _Promise_ } 21 | 22 | #### Type parameters: 23 | 24 | | Name | 25 | | :------ | 26 | | `TData` | 27 | 28 | #### Parameters: 29 | 30 | | Name | Type | 31 | | :--- | :----------------------------------------------- | 32 | | `fn` | (`query`: GeneratedSchema[``"query"``]) => TData | 33 | 34 | **Returns:** TData \| _Promise_ & { `schedulerPromise`: _Promise_ } 35 | 36 | Defined in: [packages/gqless/src/Helpers/prefetch.ts:8](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Helpers/prefetch.ts#L8) 37 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/preparerender.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'preparerender' 3 | title: 'Interface: PrepareRender' 4 | sidebar_label: 'PrepareRender' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: PrepareRender 10 | 11 | ## Callable 12 | 13 | ▸ **PrepareRender**(`render`: () => _void_ \| _Promise_): _Promise_<{ `cacheSnapshot`: _string_ }\> 14 | 15 | #### Parameters: 16 | 17 | | Name | Type | 18 | | :------- | :------------------------------- | 19 | | `render` | () => _void_ \| _Promise_ | 20 | 21 | **Returns:** _Promise_<{ `cacheSnapshot`: _string_ }\> 22 | 23 | Defined in: [packages/gqless/src/Helpers/ssr.ts:26](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Helpers/ssr.ts#L26) 24 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/prepassobjkey.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'prepassobjkey' 3 | title: 'Interface: PrepassObjKey' 4 | sidebar_label: 'PrepassObjKey' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: PrepassObjKey 10 | 11 | ## Properties 12 | 13 | ### field 14 | 15 | • **field**: _string_ 16 | 17 | Defined in: [packages/gqless/src/Helpers/prepass.ts:8](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Helpers/prepass.ts#L8) 18 | 19 | --- 20 | 21 | ### variables 22 | 23 | • `Optional` **variables**: _Record_ 24 | 25 | Defined in: [packages/gqless/src/Helpers/prepass.ts:9](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Helpers/prepass.ts#L9) 26 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/refetch.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'refetch' 3 | title: 'Interface: Refetch' 4 | sidebar_label: 'Refetch' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: Refetch 10 | 11 | ## Callable 12 | 13 | ▸ **Refetch**(`refetchArg`: T \| () => T): _Promise_ 14 | 15 | #### Type parameters: 16 | 17 | | Name | Default | 18 | | :--- | :-------------------- | 19 | | `T` | _undefined_ \| _void_ | 20 | 21 | #### Parameters: 22 | 23 | | Name | Type | 24 | | :----------- | :----------- | 25 | | `refetchArg` | T \| () => T | 26 | 27 | **Returns:** _Promise_ 28 | 29 | Defined in: [packages/gqless/src/Helpers/refetch.ts:8](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Helpers/refetch.ts#L8) 30 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/resolved.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'resolved' 3 | title: 'Interface: Resolved' 4 | sidebar_label: 'Resolved' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: Resolved 10 | 11 | ## Callable 12 | 13 | ▸ **Resolved**(`dataFn`: () => T, `opts?`: [_ResolveOptions_](resolveoptions.md)): _Promise_ 14 | 15 | #### Type parameters: 16 | 17 | | Name | Default | 18 | | :--- | :-------- | 19 | | `T` | _unknown_ | 20 | 21 | #### Parameters: 22 | 23 | | Name | Type | 24 | | :------- | :---------------------------------------- | 25 | | `dataFn` | () => T | 26 | | `opts?` | [_ResolveOptions_](resolveoptions.md) | 27 | 28 | **Returns:** _Promise_ 29 | 30 | Defined in: [packages/gqless/src/Client/resolvers.ts:167](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/resolvers.ts#L167) 31 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/resolvers.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'resolvers' 3 | title: 'Interface: Resolvers' 4 | sidebar_label: 'Resolvers' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: Resolvers 10 | 11 | ## Properties 12 | 13 | ### buildAndFetchSelections 14 | 15 | • **buildAndFetchSelections**: [_BuildAndFetchSelections_](buildandfetchselections.md) 16 | 17 | Defined in: [packages/gqless/src/Client/resolvers.ts:191](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/resolvers.ts#L191) 18 | 19 | --- 20 | 21 | ### inlineResolved 22 | 23 | • **inlineResolved**: [_InlineResolved_](inlineresolved.md) 24 | 25 | Defined in: [packages/gqless/src/Client/resolvers.ts:193](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/resolvers.ts#L193) 26 | 27 | --- 28 | 29 | ### resolveSelections 30 | 31 | • **resolveSelections**: ResolveSelections 32 | 33 | Defined in: [packages/gqless/src/Client/resolvers.ts:190](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/resolvers.ts#L190) 34 | 35 | --- 36 | 37 | ### resolved 38 | 39 | • **resolved**: [_Resolved_](resolved.md) 40 | 41 | Defined in: [packages/gqless/src/Client/resolvers.ts:192](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Client/resolvers.ts#L192) 42 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/retryconfigstate.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'retryconfigstate' 3 | title: 'Interface: RetryConfigState' 4 | sidebar_label: 'RetryConfigState' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: RetryConfigState 10 | 11 | ## Properties 12 | 13 | ### attemptIndex 14 | 15 | • `Optional` `Private` **attemptIndex**: _number_ 16 | 17 | Error incremental attempt index 18 | 19 | You shouldn't set it manually 20 | 21 | **`default`** 0 22 | 23 | Defined in: [packages/gqless/src/Error/retry.ts:43](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Error/retry.ts#L43) 24 | 25 | --- 26 | 27 | ### onLastTry 28 | 29 | • `Optional` **onLastTry**: (`attemptIndex`: _number_) => _Promise_ 30 | 31 | Function to be executed on the last try 32 | 33 | #### Type declaration: 34 | 35 | ▸ (`attemptIndex`: _number_): _Promise_ 36 | 37 | #### Parameters: 38 | 39 | | Name | Type | 40 | | :------------- | :------- | 41 | | `attemptIndex` | _number_ | 42 | 43 | **Returns:** _Promise_ 44 | 45 | Defined in: [packages/gqless/src/Error/retry.ts:51](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Error/retry.ts#L51) 46 | 47 | --- 48 | 49 | ### onRetry 50 | 51 | • **onRetry**: (`attemptIndex`: _number_) => _Promise_ 52 | 53 | Function to be executed on approved retry attempt 54 | 55 | #### Type declaration: 56 | 57 | ▸ (`attemptIndex`: _number_): _Promise_ 58 | 59 | #### Parameters: 60 | 61 | | Name | Type | 62 | | :------------- | :------- | 63 | | `attemptIndex` | _number_ | 64 | 65 | **Returns:** _Promise_ 66 | 67 | Defined in: [packages/gqless/src/Error/retry.ts:47](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Error/retry.ts#L47) 68 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/scalars.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'scalars' 3 | title: 'Interface: Scalars' 4 | sidebar_label: 'Scalars' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: Scalars 10 | 11 | ## Properties 12 | 13 | ### Float 14 | 15 | • **Float**: _number_ 16 | 17 | Defined in: [packages/gqless/src/Schema/types.ts:19](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L19) 18 | 19 | --- 20 | 21 | ### ID 22 | 23 | • **ID**: _string_ 24 | 25 | Defined in: [packages/gqless/src/Schema/types.ts:20](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L20) 26 | 27 | --- 28 | 29 | ### Int 30 | 31 | • **Int**: _number_ 32 | 33 | Defined in: [packages/gqless/src/Schema/types.ts:18](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L18) 34 | 35 | --- 36 | 37 | ### String 38 | 39 | • **String**: _string_ 40 | 41 | Defined in: [packages/gqless/src/Schema/types.ts:17](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L17) 42 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/schema.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'schema' 3 | title: 'Interface: Schema' 4 | sidebar_label: 'Schema' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: Schema 10 | 11 | ## Hierarchy 12 | 13 | - _Record_\> 14 | 15 | ↳ **Schema** 16 | 17 | ## Properties 18 | 19 | ### [SchemaUnionsKey] 20 | 21 | • `Optional` **[SchemaUnionsKey]**: _Record_ 22 | 23 | Defined in: [packages/gqless/src/Schema/types.ts:13](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L13) 24 | 25 | --- 26 | 27 | ### mutation 28 | 29 | • **mutation**: _Record_ 30 | 31 | Defined in: [packages/gqless/src/Schema/types.ts:11](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L11) 32 | 33 | --- 34 | 35 | ### query 36 | 37 | • **query**: _Record_ 38 | 39 | Defined in: [packages/gqless/src/Schema/types.ts:10](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L10) 40 | 41 | --- 42 | 43 | ### subscription 44 | 45 | • **subscription**: _Record_ 46 | 47 | Defined in: [packages/gqless/src/Schema/types.ts:12](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L12) 48 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/selectionmanager.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'selectionmanager' 3 | title: 'Interface: SelectionManager' 4 | sidebar_label: 'SelectionManager' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: SelectionManager 10 | 11 | ## Properties 12 | 13 | ### getSelection 14 | 15 | • **getSelection**: GetSelection 16 | 17 | Defined in: [packages/gqless/src/Selection/SelectionManager.ts:57](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Selection/SelectionManager.ts#L57) 18 | 19 | ## Methods 20 | 21 | ### backup 22 | 23 | ▸ **backup**(): SelectionsBackup 24 | 25 | **Returns:** SelectionsBackup 26 | 27 | Defined in: [packages/gqless/src/Selection/SelectionManager.ts:59](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Selection/SelectionManager.ts#L59) 28 | 29 | --- 30 | 31 | ### restore 32 | 33 | ▸ **restore**(`backup`: _unknown_): _void_ 34 | 35 | #### Parameters: 36 | 37 | | Name | Type | 38 | | :------- | :-------- | 39 | | `backup` | _unknown_ | 40 | 41 | **Returns:** _void_ 42 | 43 | Defined in: [packages/gqless/src/Selection/SelectionManager.ts:58](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Selection/SelectionManager.ts#L58) 44 | -------------------------------------------------------------------------------- /docs/client/api/interfaces/type.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'type' 3 | title: 'Interface: Type' 4 | sidebar_label: 'Type' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: Type 10 | 11 | ## Properties 12 | 13 | ### \_\_args 14 | 15 | • `Optional` **\_\_args**: _Record_ 16 | 17 | Defined in: [packages/gqless/src/Schema/types.ts:4](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L4) 18 | 19 | --- 20 | 21 | ### \_\_type 22 | 23 | • **\_\_type**: _string_ 24 | 25 | Defined in: [packages/gqless/src/Schema/types.ts:5](https://github.com/gqless/gqless/blob/master/packages/gqless/src/Schema/types.ts#L5) 26 | -------------------------------------------------------------------------------- /docs/client/mutations.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: mutations 3 | title: Core Mutations 4 | sidebar_label: Mutations 5 | --- 6 | 7 | Mutations greatly follow the format of queries (see [fetching data with `resolved`](/client/fetching-data#resolved)). 8 | 9 | ## Example 10 | 11 | ```ts 12 | import { resolved, mutation } from '../gqless'; 13 | 14 | resolved(() => { 15 | const { email, name } = mutation.createUser({ 16 | email: 'xx@xx.com', 17 | name: 'XX', 18 | }); 19 | 20 | return { 21 | email, 22 | name, 23 | }; 24 | }) 25 | .then((data) => { 26 | console.log('User created!', data); 27 | }) 28 | .catch((err) => { 29 | console.error(err); 30 | }); 31 | ``` 32 | 33 | ## See also 34 | 35 | - [Mutations with React](/react/mutations) 36 | -------------------------------------------------------------------------------- /docs/development/logger.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: logger 3 | title: Logger 4 | --- 5 | 6 | You can improve the development experience using a `Logger` of your GQless usage, which will print relevant information about the requests made to your GraphQL API Server. 7 | 8 | ![Logger screenshot](/img/logger.png) 9 | 10 | ## Installation 11 | 12 | ```bash yarn2npm 13 | yarn add @gqless/logger 14 | ``` 15 | 16 | ## Usage 17 | 18 | ```ts 19 | import { client } from '../gqless'; 20 | 21 | if (process.env.NODE_ENV === 'development') { 22 | import('@gqless/logger').then(({ createLogger }) => { 23 | const logger = createLogger(client, { 24 | // Custom options... 25 | }); 26 | logger.start(); 27 | }); 28 | } 29 | ``` 30 | 31 | ### Options 32 | 33 | | Name | Type | Default Value | Description | 34 | | -------------- | --------- | ------------- | --------------------------------- | 35 | | showSelections | `boolean` | `true` | Show "selections" in logs | 36 | | showCache | `boolean` | `true` | Show cache snapshots in logs | 37 | | stringifyJSON | `boolean` | `false` | Stringify JSON before printing it | 38 | -------------------------------------------------------------------------------- /docs/intro/features.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: features 3 | title: Features 4 | --- 5 | 6 | ## Invisible data fetching 7 | 8 | Simply access data and it will magically appear. Queries are generated automatically, so you never need to write another line of GraphQL again. 9 | 10 | 11 | 12 | ## Typescript 13 | 14 | Typescript support is **built-in** and enabled by default. Run code-generation _only when your API changes_. 15 | 16 | ## Editor intellisense 17 | 18 | You get awesome DX out the box, with docs displayed inline (no extensions required) 19 | 20 | ![VSCode suggestions screenshot](/img/intro/intellisense.png) 21 | 22 | ## Server-side Rendering 23 | 24 | We fully support Server-Side rendering (**SSR**), with focused support for [Next.js](https://nextjs.org/) 25 | 26 | ## Cache 27 | 28 | The built-in [normalized cache](/client/config#normalization) automatically caches everything for you 29 | 30 | ## Subscriptions 31 | 32 | Subscriptions support. [More info here](/client/subscriptions) 33 | -------------------------------------------------------------------------------- /docs/react/api/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'index' 3 | title: '@gqless/react' 4 | slug: '/react/api' 5 | sidebar_label: 'Readme' 6 | custom_edit_url: null 7 | hide_title: true 8 | --- 9 | 10 | # @gqless/react 11 | 12 | ## Visit [https://gqless.com/react/fetching-data](https://gqless.com/react/fetching-data) 13 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/createreactclientoptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'createreactclientoptions' 3 | title: 'Interface: CreateReactClientOptions' 4 | sidebar_label: 'CreateReactClientOptions' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: CreateReactClientOptions 10 | 11 | ## Properties 12 | 13 | ### defaults 14 | 15 | • `Optional` **defaults**: [_ReactClientDefaults_](reactclientdefaults.md) 16 | 17 | Default behaviour values 18 | 19 | Defined in: [react/src/client.ts:160](https://github.com/gqless/gqless/blob/master/packages/react/src/client.ts#L160) 20 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/fetchmorecallbackargs.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'fetchmorecallbackargs' 3 | title: 'Interface: FetchMoreCallbackArgs' 4 | sidebar_label: 'FetchMoreCallbackArgs' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: FetchMoreCallbackArgs 10 | 11 | ## Type parameters 12 | 13 | | Name | 14 | | :------ | 15 | | `TData` | 16 | | `TArgs` | 17 | 18 | ## Properties 19 | 20 | ### existingArgs 21 | 22 | • **existingArgs**: TArgs 23 | 24 | Defined in: [react/src/query/usePaginatedQuery.ts:167](https://github.com/gqless/gqless/blob/master/packages/react/src/query/usePaginatedQuery.ts#L167) 25 | 26 | --- 27 | 28 | ### existingData 29 | 30 | • **existingData**: _undefined_ \| TData 31 | 32 | Defined in: [react/src/query/usePaginatedQuery.ts:166](https://github.com/gqless/gqless/blob/master/packages/react/src/query/usePaginatedQuery.ts#L166) 33 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/graphqlhoc.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'graphqlhoc' 3 | title: 'Interface: GraphQLHOC' 4 | sidebar_label: 'GraphQLHOC' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: GraphQLHOC 10 | 11 | ## Callable 12 | 13 | ▸ **GraphQLHOC**(`component`: (`props`: P) => `null` \| _ReactElement_\>, `options?`: [_GraphQLHOCOptions_](graphqlhocoptions.md)): _function_ 14 | 15 | #### Type parameters: 16 | 17 | | Name | 18 | | :--- | 19 | | `P` | 20 | 21 | #### Parameters: 22 | 23 | | Name | Type | 24 | | :---------- | :------------------------------------------------------------------------------------ | 25 | | `component` | (`props`: P) => `null` \| _ReactElement_\> | 26 | | `options?` | [_GraphQLHOCOptions_](graphqlhocoptions.md) | 27 | 28 | **Returns:** (`props`: P) => `null` \| _ReactElement_\> 29 | 30 | Defined in: [react/src/query/hoc.tsx:18](https://github.com/gqless/gqless/blob/master/packages/react/src/query/hoc.tsx#L18) 31 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/graphqlhocoptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'graphqlhocoptions' 3 | title: 'Interface: GraphQLHOCOptions' 4 | sidebar_label: 'GraphQLHOCOptions' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: GraphQLHOCOptions 10 | 11 | ## Properties 12 | 13 | ### onError 14 | 15 | • `Optional` **onError**: [_OnErrorHandler_](../modules.md#onerrorhandler) 16 | 17 | Defined in: [react/src/query/hoc.tsx:15](https://github.com/gqless/gqless/blob/master/packages/react/src/query/hoc.tsx#L15) 18 | 19 | --- 20 | 21 | ### staleWhileRevalidate 22 | 23 | • `Optional` **staleWhileRevalidate**: _boolean_ 24 | 25 | Defined in: [react/src/query/hoc.tsx:14](https://github.com/gqless/gqless/blob/master/packages/react/src/query/hoc.tsx#L14) 26 | 27 | --- 28 | 29 | ### suspense 30 | 31 | • `Optional` **suspense**: _boolean_ \| { `fallback`: `null` \| _boolean_ \| ReactChild \| ReactFragment \| _ReactPortal_ } 32 | 33 | Defined in: [react/src/query/hoc.tsx:9](https://github.com/gqless/gqless/blob/master/packages/react/src/query/hoc.tsx#L9) 34 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/metastate.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'metastate' 3 | title: 'Interface: MetaState' 4 | sidebar_label: 'MetaState' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: MetaState 10 | 11 | ## Properties 12 | 13 | ### errors 14 | 15 | • `Optional` **errors**: _GQlessError_[] 16 | 17 | Defined in: [react/src/meta/useMetaState.ts:32](https://github.com/gqless/gqless/blob/master/packages/react/src/meta/useMetaState.ts#L32) 18 | 19 | --- 20 | 21 | ### isFetching 22 | 23 | • **isFetching**: _boolean_ 24 | 25 | Defined in: [react/src/meta/useMetaState.ts:31](https://github.com/gqless/gqless/blob/master/packages/react/src/meta/useMetaState.ts#L31) 26 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/preparequery.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'preparequery' 3 | title: 'Interface: PrepareQuery' 4 | sidebar_label: 'PrepareQuery' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: PrepareQuery 10 | 11 | ## Type parameters 12 | 13 | | Name | Type | 14 | | :---------------------- | :------- | 15 | | `GeneratedSchema` | _object_ | 16 | | `GeneratedSchema.query` | _object_ | 17 | 18 | ## Callable 19 | 20 | ▸ **PrepareQuery**(`fn`: TFunction): [_PreparedQuery_](preparedquery.md) 21 | 22 | #### Type parameters: 23 | 24 | | Name | Type | 25 | | :---------- | :-------------------------------------------------------------- | 26 | | `TFunction` | (`query`: GeneratedSchema[``"query"``], `args`: _any_) => _any_ | 27 | 28 | #### Parameters: 29 | 30 | | Name | Type | 31 | | :--- | :-------- | 32 | | `fn` | TFunction | 33 | 34 | **Returns:** [_PreparedQuery_](preparedquery.md) 35 | 36 | Defined in: [react/src/query/preparedQuery.ts:47](https://github.com/gqless/gqless/blob/master/packages/react/src/query/preparedQuery.ts#L47) 37 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/preparereactrender.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'preparereactrender' 3 | title: 'Interface: PrepareReactRender' 4 | sidebar_label: 'PrepareReactRender' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: PrepareReactRender 10 | 11 | ## Callable 12 | 13 | ▸ **PrepareReactRender**(`element`: ReactNode): _Promise_<{ `cacheSnapshot`: _string_ }\> 14 | 15 | #### Parameters: 16 | 17 | | Name | Type | 18 | | :-------- | :-------- | 19 | | `element` | ReactNode | 20 | 21 | **Returns:** _Promise_<{ `cacheSnapshot`: _string_ }\> 22 | 23 | Defined in: [react/src/ssr/ssr.ts:38](https://github.com/gqless/gqless/blob/master/packages/react/src/ssr/ssr.ts#L38) 24 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usehydratecache.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usehydratecache' 3 | title: 'Interface: UseHydrateCache' 4 | sidebar_label: 'UseHydrateCache' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseHydrateCache 10 | 11 | ## Callable 12 | 13 | ▸ **UseHydrateCache**(`__namedParameters`: [_UseHydrateCacheOptions_](usehydratecacheoptions.md)): _void_ 14 | 15 | #### Parameters: 16 | 17 | | Name | Type | 18 | | :------------------ | :---------------------------------------------------- | 19 | | `__namedParameters` | [_UseHydrateCacheOptions_](usehydratecacheoptions.md) | 20 | 21 | **Returns:** _void_ 22 | 23 | Defined in: [react/src/ssr/ssr.ts:34](https://github.com/gqless/gqless/blob/master/packages/react/src/ssr/ssr.ts#L34) 24 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usehydratecacheoptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usehydratecacheoptions' 3 | title: 'Interface: UseHydrateCacheOptions' 4 | sidebar_label: 'UseHydrateCacheOptions' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseHydrateCacheOptions 10 | 11 | ## Hierarchy 12 | 13 | - _Partial_ 14 | 15 | ↳ **UseHydrateCacheOptions** 16 | 17 | ## Properties 18 | 19 | ### cacheSnapshot 20 | 21 | • **cacheSnapshot**: _undefined_ \| _string_ 22 | 23 | Cache snapshot, returned from `prepareReactRender` 24 | 25 | Overrides: Partial.cacheSnapshot 26 | 27 | Defined in: [react/src/ssr/ssr.ts:12](https://github.com/gqless/gqless/blob/master/packages/react/src/ssr/ssr.ts#L12) 28 | 29 | --- 30 | 31 | ### shouldRefetch 32 | 33 | • `Optional` **shouldRefetch**: _boolean_ 34 | 35 | If it should refetch everything after the component is mounted 36 | 37 | **`default`** 38 | false 39 | 40 | Overrides: Partial.shouldRefetch 41 | 42 | Defined in: [react/src/ssr/ssr.ts:19](https://github.com/gqless/gqless/blob/master/packages/react/src/ssr/ssr.ts#L19) 43 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/uselazyqueryoptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'uselazyqueryoptions' 3 | title: 'Interface: UseLazyQueryOptions' 4 | sidebar_label: 'UseLazyQueryOptions' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseLazyQueryOptions 10 | 11 | ## Type parameters 12 | 13 | | Name | 14 | | :------ | 15 | | `TData` | 16 | 17 | ## Properties 18 | 19 | ### fetchPolicy 20 | 21 | • `Optional` **fetchPolicy**: [_LazyFetchPolicy_](../modules.md#lazyfetchpolicy) 22 | 23 | Defined in: [react/src/query/useLazyQuery.ts:18](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L18) 24 | 25 | --- 26 | 27 | ### onCompleted 28 | 29 | • `Optional` **onCompleted**: (`data`: TData) => _void_ 30 | 31 | #### Type declaration: 32 | 33 | ▸ (`data`: TData): _void_ 34 | 35 | #### Parameters: 36 | 37 | | Name | Type | 38 | | :----- | :---- | 39 | | `data` | TData | 40 | 41 | **Returns:** _void_ 42 | 43 | Defined in: [react/src/query/useLazyQuery.ts:16](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L16) 44 | 45 | --- 46 | 47 | ### onError 48 | 49 | • `Optional` **onError**: [_OnErrorHandler_](../modules.md#onerrorhandler) 50 | 51 | Defined in: [react/src/query/useLazyQuery.ts:17](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L17) 52 | 53 | --- 54 | 55 | ### retry 56 | 57 | • `Optional` **retry**: RetryOptions 58 | 59 | Defined in: [react/src/query/useLazyQuery.ts:19](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L19) 60 | 61 | --- 62 | 63 | ### suspense 64 | 65 | • `Optional` **suspense**: _boolean_ 66 | 67 | Defined in: [react/src/query/useLazyQuery.ts:20](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L20) 68 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/uselazyquerystate.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'uselazyquerystate' 3 | title: 'Interface: UseLazyQueryState' 4 | sidebar_label: 'UseLazyQueryState' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseLazyQueryState 10 | 11 | ## Type parameters 12 | 13 | | Name | 14 | | :------ | 15 | | `TData` | 16 | 17 | ## Properties 18 | 19 | ### data 20 | 21 | • **data**: _undefined_ \| TData 22 | 23 | Defined in: [react/src/query/useLazyQuery.ts:24](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L24) 24 | 25 | --- 26 | 27 | ### error 28 | 29 | • `Optional` **error**: _GQlessError_ 30 | 31 | Defined in: [react/src/query/useLazyQuery.ts:25](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L25) 32 | 33 | --- 34 | 35 | ### isCalled 36 | 37 | • **isCalled**: _boolean_ 38 | 39 | Defined in: [react/src/query/useLazyQuery.ts:27](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L27) 40 | 41 | --- 42 | 43 | ### isLoading 44 | 45 | • **isLoading**: _boolean_ 46 | 47 | Defined in: [react/src/query/useLazyQuery.ts:26](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useLazyQuery.ts#L26) 48 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usemetastate.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usemetastate' 3 | title: 'Interface: UseMetaState' 4 | sidebar_label: 'UseMetaState' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseMetaState 10 | 11 | ## Callable 12 | 13 | ▸ **UseMetaState**(`opts?`: [_UseMetaStateOptions_](usemetastateoptions.md)): [_MetaState_](metastate.md) 14 | 15 | #### Type parameters: 16 | 17 | | Name | 18 | | :--- | 19 | | `T` | 20 | 21 | #### Parameters: 22 | 23 | | Name | Type | 24 | | :------ | :-------------------------------------------------- | 25 | | `opts?` | [_UseMetaStateOptions_](usemetastateoptions.md) | 26 | 27 | **Returns:** [_MetaState_](metastate.md) 28 | 29 | Defined in: [react/src/meta/useMetaState.ts:35](https://github.com/gqless/gqless/blob/master/packages/react/src/meta/useMetaState.ts#L35) 30 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usemutation.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usemutation' 3 | title: 'Interface: UseMutation' 4 | sidebar_label: 'UseMutation' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseMutation 10 | 11 | ## Type parameters 12 | 13 | | Name | Type | 14 | | :------------------------- | :------- | 15 | | `GeneratedSchema` | _object_ | 16 | | `GeneratedSchema.mutation` | _object_ | 17 | 18 | ## Callable 19 | 20 | ▸ **UseMutation**(`mutationFn?`: (`mutation`: GeneratedSchema[``"mutation"``], `args`: TArgs) => TData, `options?`: [_UseMutationOptions_](usemutationoptions.md)): readonly [(...`opts`: _undefined_ _extends_ TArgs ? [object?] : [{ `args`: TArgs ; `fn?`: (`mutation`: GeneratedSchema[``"mutation"``], `args`: TArgs) => TData }]) => _Promise_, [_UseMutationState_](usemutationstate.md)] 21 | 22 | #### Type parameters: 23 | 24 | | Name | Default | 25 | | :------ | :---------- | 26 | | `TData` | _unknown_ | 27 | | `TArgs` | _undefined_ | 28 | 29 | #### Parameters: 30 | 31 | | Name | Type | 32 | | :------------ | :-------------------------------------------------------------------- | 33 | | `mutationFn?` | (`mutation`: GeneratedSchema[``"mutation"``], `args`: TArgs) => TData | 34 | | `options?` | [_UseMutationOptions_](usemutationoptions.md) | 35 | 36 | **Returns:** readonly [(...`opts`: _undefined_ _extends_ TArgs ? [object?] : [{ `args`: TArgs ; `fn?`: (`mutation`: GeneratedSchema[``"mutation"``], `args`: TArgs) => TData }]) => _Promise_, [_UseMutationState_](usemutationstate.md)] 37 | 38 | Defined in: [react/src/mutation/useMutation.ts:94](https://github.com/gqless/gqless/blob/master/packages/react/src/mutation/useMutation.ts#L94) 39 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usemutationstate.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usemutationstate' 3 | title: 'Interface: UseMutationState' 4 | sidebar_label: 'UseMutationState' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseMutationState 10 | 11 | ## Type parameters 12 | 13 | | Name | 14 | | :------ | 15 | | `TData` | 16 | 17 | ## Properties 18 | 19 | ### data 20 | 21 | • **data**: _undefined_ \| TData 22 | 23 | Defined in: [react/src/mutation/useMutation.ts:45](https://github.com/gqless/gqless/blob/master/packages/react/src/mutation/useMutation.ts#L45) 24 | 25 | --- 26 | 27 | ### error 28 | 29 | • `Optional` **error**: _GQlessError_ 30 | 31 | Defined in: [react/src/mutation/useMutation.ts:46](https://github.com/gqless/gqless/blob/master/packages/react/src/mutation/useMutation.ts#L46) 32 | 33 | --- 34 | 35 | ### isLoading 36 | 37 | • **isLoading**: _boolean_ 38 | 39 | Defined in: [react/src/mutation/useMutation.ts:47](https://github.com/gqless/gqless/blob/master/packages/react/src/mutation/useMutation.ts#L47) 40 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usepreparedqueryoptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usepreparedqueryoptions' 3 | title: 'Interface: UsePreparedQueryOptions' 4 | sidebar_label: 'UsePreparedQueryOptions' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UsePreparedQueryOptions 10 | 11 | ## Properties 12 | 13 | ### suspense 14 | 15 | • `Optional` **suspense**: _boolean_ 16 | 17 | Defined in: [react/src/query/preparedQuery.ts:12](https://github.com/gqless/gqless/blob/master/packages/react/src/query/preparedQuery.ts#L12) 18 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usequery.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usequery' 3 | title: 'Interface: UseQuery' 4 | sidebar_label: 'UseQuery' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseQuery 10 | 11 | ## Type parameters 12 | 13 | | Name | Type | 14 | | :---------------------- | :------- | 15 | | `GeneratedSchema` | _object_ | 16 | | `GeneratedSchema.query` | _object_ | 17 | 18 | ## Callable 19 | 20 | ▸ **UseQuery**(`options?`: [_UseQueryOptions_](usequeryoptions.md)): [_UseQueryReturnValue_](../modules.md#usequeryreturnvalue) 21 | 22 | #### Parameters: 23 | 24 | | Name | Type | 25 | | :--------- | :-------------------------------------------------------- | 26 | | `options?` | [_UseQueryOptions_](usequeryoptions.md) | 27 | 28 | **Returns:** [_UseQueryReturnValue_](../modules.md#usequeryreturnvalue) 29 | 30 | Defined in: [react/src/query/useQuery.ts:42](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useQuery.ts#L42) 31 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usequeryoptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usequeryoptions' 3 | title: 'Interface: UseQueryOptions' 4 | sidebar_label: 'UseQueryOptions' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseQueryOptions 10 | 11 | ## Type parameters 12 | 13 | | Name | Type | Default | 14 | | :---------------------- | :------- | :------ | 15 | | `GeneratedSchema` | _object_ | _never_ | 16 | | `GeneratedSchema.query` | _object_ | - | 17 | 18 | ## Properties 19 | 20 | ### onError 21 | 22 | • `Optional` **onError**: [_OnErrorHandler_](../modules.md#onerrorhandler) 23 | 24 | Defined in: [react/src/query/useQuery.ts:26](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useQuery.ts#L26) 25 | 26 | --- 27 | 28 | ### prepare 29 | 30 | • `Optional` **prepare**: (`helpers`: _UseQueryPrepareHelpers_) => _void_ 31 | 32 | #### Type declaration: 33 | 34 | ▸ (`helpers`: _UseQueryPrepareHelpers_): _void_ 35 | 36 | #### Parameters: 37 | 38 | | Name | Type | 39 | | :-------- | :----------------------------------------- | 40 | | `helpers` | _UseQueryPrepareHelpers_ | 41 | 42 | **Returns:** _void_ 43 | 44 | Defined in: [react/src/query/useQuery.ts:27](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useQuery.ts#L27) 45 | 46 | --- 47 | 48 | ### staleWhileRevalidate 49 | 50 | • `Optional` **staleWhileRevalidate**: `null` \| _string_ \| _number_ \| _boolean_ \| _object_ 51 | 52 | Defined in: [react/src/query/useQuery.ts:25](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useQuery.ts#L25) 53 | 54 | --- 55 | 56 | ### suspense 57 | 58 | • `Optional` **suspense**: _boolean_ 59 | 60 | Defined in: [react/src/query/useQuery.ts:24](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useQuery.ts#L24) 61 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usequerystate.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usequerystate' 3 | title: 'Interface: UseQueryState' 4 | sidebar_label: 'UseQueryState' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseQueryState 10 | 11 | ## Properties 12 | 13 | ### isLoading 14 | 15 | • `Readonly` **isLoading**: _boolean_ 16 | 17 | Useful for `Non-Suspense` usage. 18 | 19 | Defined in: [react/src/query/useQuery.ts:34](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useQuery.ts#L34) 20 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/userefetch.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'userefetch' 3 | title: 'Interface: UseRefetch' 4 | sidebar_label: 'UseRefetch' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseRefetch 10 | 11 | ## Callable 12 | 13 | ▸ **UseRefetch**(`refetchOptions?`: [_UseRefetchOptions_](userefetchoptions.md)): (`refetchArg?`: T \| () => T) => _Promise_ & [_UseRefetchState_](userefetchstate.md) 14 | 15 | #### Parameters: 16 | 17 | | Name | Type | 18 | | :---------------- | :------------------------------------------ | 19 | | `refetchOptions?` | [_UseRefetchOptions_](userefetchoptions.md) | 20 | 21 | **Returns:** (`refetchArg?`: T \| () => T) => _Promise_ & [_UseRefetchState_](userefetchstate.md) 22 | 23 | Defined in: [react/src/query/useRefetch.ts:77](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useRefetch.ts#L77) 24 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/userefetchoptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'userefetchoptions' 3 | title: 'Interface: UseRefetchOptions' 4 | sidebar_label: 'UseRefetchOptions' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseRefetchOptions 10 | 11 | ## Properties 12 | 13 | ### notifyOnNetworkStatusChange 14 | 15 | • `Optional` **notifyOnNetworkStatusChange**: _boolean_ 16 | 17 | Defined in: [react/src/query/useRefetch.ts:72](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useRefetch.ts#L72) 18 | 19 | --- 20 | 21 | ### retry 22 | 23 | • `Optional` **retry**: RetryOptions 24 | 25 | Defined in: [react/src/query/useRefetch.ts:74](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useRefetch.ts#L74) 26 | 27 | --- 28 | 29 | ### startWatching 30 | 31 | • `Optional` **startWatching**: _boolean_ 32 | 33 | Defined in: [react/src/query/useRefetch.ts:73](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useRefetch.ts#L73) 34 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/userefetchstate.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'userefetchstate' 3 | title: 'Interface: UseRefetchState' 4 | sidebar_label: 'UseRefetchState' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseRefetchState 10 | 11 | ## Hierarchy 12 | 13 | - _UseRefetchReducerState_ 14 | 15 | ↳ **UseRefetchState** 16 | 17 | ## Properties 18 | 19 | ### error 20 | 21 | • `Optional` **error**: _GQlessError_ 22 | 23 | Inherited from: UseRefetchReducerState.error 24 | 25 | Defined in: [react/src/query/useRefetch.ts:20](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useRefetch.ts#L20) 26 | 27 | --- 28 | 29 | ### isLoading 30 | 31 | • **isLoading**: _boolean_ 32 | 33 | Inherited from: UseRefetchReducerState.isLoading 34 | 35 | Defined in: [react/src/query/useRefetch.ts:19](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useRefetch.ts#L19) 36 | 37 | --- 38 | 39 | ### startWatching 40 | 41 | • **startWatching**: () => _void_ 42 | 43 | #### Type declaration: 44 | 45 | ▸ (): _void_ 46 | 47 | **Returns:** _void_ 48 | 49 | Defined in: [react/src/query/useRefetch.ts:67](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useRefetch.ts#L67) 50 | 51 | --- 52 | 53 | ### stopWatching 54 | 55 | • **stopWatching**: () => _void_ 56 | 57 | #### Type declaration: 58 | 59 | ▸ (): _void_ 60 | 61 | **Returns:** _void_ 62 | 63 | Defined in: [react/src/query/useRefetch.ts:68](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useRefetch.ts#L68) 64 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usesubscription.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usesubscription' 3 | title: 'Interface: UseSubscription' 4 | sidebar_label: 'UseSubscription' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseSubscription 10 | 11 | ## Type parameters 12 | 13 | | Name | Type | 14 | | :----------------------------- | :------- | 15 | | `GeneratedSchema` | _object_ | 16 | | `GeneratedSchema.subscription` | _object_ | 17 | 18 | ## Callable 19 | 20 | ▸ **UseSubscription**(): GeneratedSchema[``"subscription"``] 21 | 22 | **Returns:** GeneratedSchema[``"subscription"``] 23 | 24 | Defined in: [react/src/subscription/useSubscription.ts:15](https://github.com/gqless/gqless/blob/master/packages/react/src/subscription/useSubscription.ts#L15) 25 | -------------------------------------------------------------------------------- /docs/react/api/interfaces/usetransactionquerystate.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 'usetransactionquerystate' 3 | title: 'Interface: UseTransactionQueryState' 4 | sidebar_label: 'UseTransactionQueryState' 5 | custom_edit_url: null 6 | hide_title: true 7 | --- 8 | 9 | # Interface: UseTransactionQueryState 10 | 11 | ## Type parameters 12 | 13 | | Name | 14 | | :------ | 15 | | `TData` | 16 | 17 | ## Properties 18 | 19 | ### data 20 | 21 | • **data**: _undefined_ \| TData 22 | 23 | Defined in: [react/src/query/useTransactionQuery.ts:30](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useTransactionQuery.ts#L30) 24 | 25 | --- 26 | 27 | ### error 28 | 29 | • `Optional` **error**: _GQlessError_ 30 | 31 | Defined in: [react/src/query/useTransactionQuery.ts:31](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useTransactionQuery.ts#L31) 32 | 33 | --- 34 | 35 | ### isCalled 36 | 37 | • **isCalled**: _boolean_ 38 | 39 | Defined in: [react/src/query/useTransactionQuery.ts:33](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useTransactionQuery.ts#L33) 40 | 41 | --- 42 | 43 | ### isLoading 44 | 45 | • **isLoading**: _boolean_ 46 | 47 | Defined in: [react/src/query/useTransactionQuery.ts:32](https://github.com/gqless/gqless/blob/master/packages/react/src/query/useTransactionQuery.ts#L32) 48 | -------------------------------------------------------------------------------- /docs/react/subscriptions.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: subscriptions 3 | title: Using Subscriptions with React 4 | sidebar_label: Subscriptions 5 | --- 6 | 7 | ## `useSubscription` 8 | 9 | Hook designed to be used for [GraphQL Subscriptions](https://github.com/graphql/graphql-spec/blob/main/rfcs/Subscriptions.md). 10 | 11 | For more configuration of Subscriptions [check here](/client/subscriptions). 12 | 13 | ### Features: 14 | 15 | - Subscribe on-demand 16 | - Automatic unsubscribe on component unmount 17 | - Automatic updates on cache changes 18 | 19 | ### Example 20 | 21 | ```tsx 22 | import { useSubscription } from '../gqless'; 23 | 24 | export function Example() { 25 | const { newNotification } = useSubscription(); 26 | 27 | if (newNotification) { 28 | return ( 29 |

30 | New Notification: {newNotification} 31 |

32 | ); 33 | } 34 | return

Waiting for new notifications...

; 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/react/suspense.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: suspense 3 | title: Using React Suspense 4 | sidebar_label: Suspense & usage without 5 | --- 6 | 7 | ## How to enable it 8 | 9 | One of the goals of GQless is to embrace React [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html) & [Concurrent Mode](https://reactjs.org/docs/concurrent-mode-intro.html), however these features are still in development by the React team. 10 | 11 | Until these features become widespread enough, you will need to **opt-in** for Suspense support via configuration. This can be done directly in hook, or via the [defaults of the client](/react/config#defaults). 12 | 13 | ```ts 14 | // Enabling support with hooks 15 | const query = useQuery({ suspense: true }); 16 | 17 | // Enabling support with HoC 18 | const Component = graphql(() =>
, { suspense: true }); 19 | ``` 20 | 21 | ## Usage without Suspense 22 | 23 | All hooks return a `$state` object, when suspense support is not enabled. 24 | 25 | ```tsx 26 | function Example() { 27 | const query = useQuery({ suspense: false }); 28 | 29 | if (query.$state.isLoading) return

Loading...

; 30 | 31 | return

{helloWorld}

; 32 | } 33 | ``` 34 | 35 | ## Suspense & SSR 36 | 37 | React doesn't yet support suspense whilst rendering on the server, so [react-ssr-prepass](https://github.com/FormidableLabs/react-ssr-prepass) is used in our SSR functions: 38 | 39 | ![React Error with Suspense in SSR](/img/suspense-ssr.png) 40 | 41 | And for that, reason we suggest using a slighty modified `Suspense` component: 42 | 43 | ```tsx 44 | import { Suspense as ReactSuspense, SuspenseProps } from 'react'; 45 | 46 | export const Suspense = 47 | typeof window !== 'undefined' 48 | ? ReactSuspense 49 | : function SuspenseSSR({ children }: SuspenseProps) { 50 | return <>{children}; 51 | }; 52 | ``` 53 | 54 | And everything should work as you might expect. 55 | -------------------------------------------------------------------------------- /examples/cra/.env.local: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true -------------------------------------------------------------------------------- /examples/cra/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /examples/cra/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false 3 | } 4 | -------------------------------------------------------------------------------- /examples/cra/gqless.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import("@gqless/cli").GQlessConfig} 3 | */ 4 | const config = { 5 | enumsAsStrings: true, 6 | react: true, 7 | scalarTypes: { 8 | DateTime: "string", 9 | NonNegativeInt: "number", 10 | NonEmptyString: "string", 11 | EmailAddress: "string", 12 | }, 13 | preImport: "", 14 | introspection: { 15 | endpoint: "https://examples-api.gqless.com/graphql", 16 | headers: {}, 17 | }, 18 | destination: "./src/gqless/index.ts", 19 | subscriptions: true, 20 | javascriptOutput: false, 21 | }; 22 | 23 | module.exports = config; 24 | -------------------------------------------------------------------------------- /examples/cra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cra-example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "react-scripts build", 7 | "dev": "react-scripts start", 8 | "eject": "react-scripts eject", 9 | "generate": "gqless generate", 10 | "prepare": "react-scripts build", 11 | "prepare-lock": "npm install --package-lock-only", 12 | "start": "react-scripts start" 13 | }, 14 | "browserslist": { 15 | "production": [ 16 | ">0.2%", 17 | "not dead", 18 | "not op_mini all" 19 | ], 20 | "development": [ 21 | "last 1 chrome version", 22 | "last 1 firefox version", 23 | "last 1 safari version" 24 | ] 25 | }, 26 | "eslintConfig": { 27 | "extends": [ 28 | "react-app", 29 | "react-app/jest" 30 | ] 31 | }, 32 | "dependencies": { 33 | "@babel/core": "^7.13.15", 34 | "@emotion/css": "^11.1.3", 35 | "@emotion/react": "^11.1.5", 36 | "@emotion/styled": "^11.3.0", 37 | "@gqless/cli": "workspace:^2.0.16", 38 | "@gqless/logger": "workspace:^2.0.11", 39 | "@gqless/react": "workspace:^2.0.15", 40 | "@gqless/subscriptions": "workspace:^1.0.11", 41 | "@testing-library/jest-dom": "^5.11.10", 42 | "@testing-library/react": "^11.2.6", 43 | "@testing-library/user-event": "^13.1.5", 44 | "@types/jest": "^26.0.22", 45 | "@types/node": "^14.14.41", 46 | "@types/react": "^17.0.3", 47 | "@types/react-dom": "^17.0.3", 48 | "@types/react-router-dom": "^5.1.7", 49 | "framer-motion": "^4.1.5", 50 | "gqless": "workspace:^2.0.14", 51 | "graphql": "^15.5.0", 52 | "prop-types": "^15.7.2", 53 | "react": "^17.0.2", 54 | "react-dom": "^17.0.2", 55 | "react-router-dom": "^5.2.0", 56 | "react-scripts": "^4.0.3", 57 | "react-use": "^17.2.3", 58 | "typescript": "^4.2.4", 59 | "web-vitals": "^1.1.1" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/cra/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/examples/cra/public/favicon.ico -------------------------------------------------------------------------------- /examples/cra/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/cra/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/examples/cra/public/logo192.png -------------------------------------------------------------------------------- /examples/cra/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/examples/cra/public/logo512.png -------------------------------------------------------------------------------- /examples/cra/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/cra/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/cra/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "infiniteLoopProtection": true, 3 | "hardReloadOnChange": false, 4 | "view": "browser" 5 | } 6 | -------------------------------------------------------------------------------- /examples/cra/src/components/CreatePost.tsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource @emotion/react */ 2 | 3 | import { getFields } from "gqless"; 4 | import { useRef } from "react"; 5 | 6 | import { CursorConnectionArgs, useMutation } from "../gqless"; 7 | 8 | export function CreatePost({ 9 | fetchMore, 10 | }: { 11 | fetchMore: (args: CursorConnectionArgs) => void; 12 | }) { 13 | const inputRef = useRef(null); 14 | const [createPost, { isLoading }] = useMutation( 15 | (mutation, title: string) => { 16 | return getFields( 17 | mutation.createPost({ 18 | post: { 19 | title, 20 | }, 21 | }) 22 | ); 23 | }, 24 | { 25 | onCompleted(_data) { 26 | fetchMore({ 27 | first: 5, 28 | }); 29 | }, 30 | } 31 | ); 32 | 33 | return ( 34 |
35 | 36 | 37 | 53 |
54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /examples/cra/src/components/Hello.tsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource @emotion/react */ 2 | 3 | import { Fragment, Suspense, useState } from "react"; 4 | 5 | import { useQuery, graphql, query } from "../gqless"; 6 | 7 | function NamesList({ n }: { n: number }) { 8 | const { namesList } = useQuery(); 9 | 10 | return ( 11 |
    12 | {namesList({ 13 | n, 14 | }).map((name, index) => { 15 | return
  1. {name}
  2. ; 16 | })} 17 |
18 | ); 19 | } 20 | 21 | function Names() { 22 | const [n, setN] = useState(10); 23 | return ( 24 | 25 | 26 | setN(Math.max(ev.target.valueAsNumber, 0))} 29 | css={{ 30 | width: "100px", 31 | }} 32 | type="number" 33 | /> 34 | 35 | Names Loading...

}> 36 | 37 |
38 |
39 | ); 40 | } 41 | 42 | const HelloWorld = graphql( 43 | function HelloWorld() { 44 | return ( 45 |

50 | {query.hello} 51 |

52 | ); 53 | }, 54 | { 55 | suspense: { 56 | fallback:

Hello Loading...

, 57 | }, 58 | } 59 | ); 60 | 61 | export function Hello() { 62 | return ( 63 | 64 | 65 | 66 | 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /examples/cra/src/components/Login.tsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource @emotion/react */ 2 | 3 | import { prepass } from "gqless"; 4 | import { useRef } from "react"; 5 | 6 | import { useMutation } from "../gqless"; 7 | import { useCurrentUser } from "../hooks/currentUser"; 8 | 9 | export function Login() { 10 | const { currentUser } = useCurrentUser(); 11 | const [login, { data, isLoading, error }] = useMutation( 12 | ({ login }, email: string) => { 13 | return prepass( 14 | login({ 15 | input: { 16 | email, 17 | }, 18 | }), 19 | "user.email", 20 | "error", 21 | "token" 22 | ); 23 | } 24 | ); 25 | const inputRef = useRef(null); 26 | 27 | if (currentUser.user) return

Already Logged in

; 28 | 29 | const errorMessage = (data && data.error) || (error && error.message); 30 | 31 | return ( 32 |
33 | {errorMessage ?

{errorMessage}

: null} 34 |
37 | 38 | 43 | 44 | 63 |
64 |
65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /examples/cra/src/components/Register.tsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource @emotion/react */ 2 | 3 | import { prepass } from "gqless"; 4 | import { useRef } from "react"; 5 | 6 | import { useMutation } from "../gqless"; 7 | import { useCurrentUser } from "../hooks/currentUser"; 8 | 9 | export function Register() { 10 | const { currentUser } = useCurrentUser(); 11 | const [register, { data, isLoading, error }] = useMutation( 12 | ({ register }, email: string) => { 13 | return prepass( 14 | register({ 15 | input: { 16 | email, 17 | }, 18 | }), 19 | "user.email", 20 | "error", 21 | "token" 22 | ); 23 | } 24 | ); 25 | const inputRef = useRef(null); 26 | 27 | if (currentUser.user) return

Already Logged in

; 28 | 29 | const errorMessage = (data && data.error) || (error && error.message); 30 | 31 | return ( 32 |
33 | {errorMessage ?

{errorMessage}

: null} 34 |
37 | 38 | 43 | 44 | 63 |
64 |
65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /examples/cra/src/hooks/currentUser.ts: -------------------------------------------------------------------------------- 1 | import { setAuthorizationToken, useQuery } from "../gqless"; 2 | import { useEffect } from "react"; 3 | 4 | export function useCurrentUser(suspense = true) { 5 | const { currentUser } = useQuery({ 6 | prepare({ prepass, query: { currentUser } }) { 7 | prepass(currentUser, "error", "token", "user.email"); 8 | }, 9 | suspense, 10 | }); 11 | 12 | const token = currentUser.token; 13 | useEffect(() => { 14 | if (token !== undefined) setAuthorizationToken(token); 15 | }, [token]); 16 | 17 | return { 18 | currentUser, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /examples/cra/src/index.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Lato&display=swap"); 2 | 3 | body { 4 | font-family: "Lato", sans-serif; 5 | /* Used to prevent CodeSandbox embed buttons */ 6 | padding-bottom: 50px; 7 | } 8 | 9 | a:link { 10 | text-decoration: inherit; 11 | color: inherit; 12 | font-weight: bold; 13 | box-shadow: 1px 1px 1px 1px; 14 | border-radius: 3px; 15 | padding: 2px; 16 | } 17 | 18 | a:visited { 19 | text-decoration: inherit; 20 | color: inherit; 21 | font-weight: bold; 22 | } 23 | 24 | a:hover { 25 | color: rgb(52, 52, 170); 26 | } 27 | -------------------------------------------------------------------------------- /examples/cra/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/cra/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from "web-vitals"; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/cra/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import "@testing-library/jest-dom"; 6 | -------------------------------------------------------------------------------- /examples/cra/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/github/gqless.config.cjs: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | 3 | /** 4 | * @type {import("@gqless/cli").GQlessConfig} 5 | */ 6 | const config = { 7 | enumsAsStrings: false, 8 | react: false, 9 | scalarTypes: { 10 | DateTime: 'string', 11 | Date: 'string', 12 | GitObjectID: 'string', 13 | GitSSHRemote: 'string', 14 | GitTimestamp: 'string', 15 | HTML: 'string', 16 | PreciseDateTime: 'string', 17 | URI: 'string', 18 | X509Certificate: 'string', 19 | }, 20 | preImport: '', 21 | introspection: { 22 | endpoint: 'https://api.github.com/graphql', 23 | headers: { 24 | authorization: `bearer ${process.env.GITHUB_TOKEN}`, 25 | }, 26 | }, 27 | destination: './src/gqless/index.ts', 28 | subscriptions: false, 29 | javascriptOutput: false, 30 | }; 31 | 32 | module.exports = config; 33 | -------------------------------------------------------------------------------- /examples/github/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('test-utils/jest.config.js').default; 2 | -------------------------------------------------------------------------------- /examples/github/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "", 6 | "license": "MIT", 7 | "author": "GQless ", 8 | "scripts": { 9 | "generate": "gqless generate", 10 | "test:manual": "jest -u" 11 | }, 12 | "dependencies": { 13 | "@gqless/cli": "workspace:^2.0.16", 14 | "dotenv": "^8.2.0", 15 | "gqless": "workspace:^2.0.14", 16 | "test-utils": "workspace:^0.1.0" 17 | }, 18 | "devDependencies": { 19 | "isomorphic-unfetch": "^3.1.0", 20 | "jest": "^26.6.3" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/github/src/gqless/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * GQLESS: You can safely modify this file and Query Fetcher based on your needs 3 | */ 4 | 5 | import 'isomorphic-unfetch'; 6 | import 'dotenv/config'; 7 | 8 | import { createClient, QueryFetcher } from 'gqless'; 9 | 10 | import { 11 | generatedSchema, 12 | GeneratedSchema, 13 | scalarsEnumsHash, 14 | SchemaObjectTypes, 15 | SchemaObjectTypesNames, 16 | } from './schema.generated'; 17 | 18 | if (!process.env.GITHUB_TOKEN) { 19 | console.error( 20 | 'You have to create a .env file with a Github Personal Access token, like this: \nGITHUB_TOKEN=your_token_here' 21 | ); 22 | process.exit(1); 23 | } 24 | 25 | const queryFetcher: QueryFetcher = async function (query, variables) { 26 | const response = await fetch('https://api.github.com/graphql', { 27 | method: 'POST', 28 | headers: { 29 | 'Content-Type': 'application/json', 30 | authorization: `bearer ${process.env.GITHUB_TOKEN}`, 31 | }, 32 | body: JSON.stringify({ 33 | query, 34 | variables, 35 | }), 36 | mode: 'cors', 37 | }); 38 | 39 | const json = await response.json(); 40 | 41 | return json; 42 | }; 43 | 44 | export const client = createClient< 45 | GeneratedSchema, 46 | SchemaObjectTypesNames, 47 | SchemaObjectTypes 48 | >({ 49 | schema: generatedSchema, 50 | scalarsEnumsHash, 51 | queryFetcher, 52 | }); 53 | 54 | export const { 55 | query, 56 | mutation, 57 | mutate, 58 | subscription, 59 | resolved, 60 | refetch, 61 | } = client; 62 | 63 | export * from './schema.generated'; 64 | -------------------------------------------------------------------------------- /examples/mercurius/.browserslistrc: -------------------------------------------------------------------------------- 1 | node 10 -------------------------------------------------------------------------------- /examples/mercurius/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | dist 5 | -------------------------------------------------------------------------------- /examples/mercurius/LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright © `2021` `GQless` 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the “Software”), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /examples/mercurius/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/examples/mercurius/README.md -------------------------------------------------------------------------------- /examples/mercurius/generate.ts: -------------------------------------------------------------------------------- 1 | import { writeGenerate } from '@gqless/cli'; 2 | import { app } from './src'; 3 | 4 | (async () => { 5 | await app.ready(); 6 | 7 | const destinationPath = await writeGenerate( 8 | app.graphql.schema, 9 | './src/generated/gqless.ts', 10 | { 11 | scalarTypes: { 12 | ExampleScalar: 'string', 13 | }, 14 | } 15 | ); 16 | 17 | console.log(`gqless schema generated at ${destinationPath}`); 18 | })(); 19 | -------------------------------------------------------------------------------- /examples/mercurius/gqless.config.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import("@gqless/cli").GQlessConfig} 3 | */ 4 | const config = { 5 | enumsAsStrings: false, 6 | react: false, 7 | scalarTypes: { DateTime: 'string' }, 8 | preImport: '', 9 | introspection: { endpoint: 'SPECIFY_ENDPOINT_OR_SCHEMA_FILE_PATH_HERE' }, 10 | destination: './src/generated/graphql.ts', 11 | subscriptions: false, 12 | }; 13 | 14 | module.exports = config; 15 | -------------------------------------------------------------------------------- /examples/mercurius/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('test-utils/jest.config.js').getConfig({ 2 | testTimeout: 20000, 3 | }); 4 | -------------------------------------------------------------------------------- /examples/mercurius/listen.js: -------------------------------------------------------------------------------- 1 | const { app } = require('./'); 2 | 3 | app.listen(3000, (err) => { 4 | if (err) { 5 | console.error(err); 6 | process.exit(1); 7 | } 8 | console.log('Listening on http://localhost:3000'); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/mercurius/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mercurius-example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "license": "MIT", 6 | "author": "GQless ", 7 | "main": "dist/index.js", 8 | "module": "dist/mercurius-example.esm.js", 9 | "typings": "dist/index.d.ts", 10 | "files": [ 11 | "dist", 12 | "src" 13 | ], 14 | "scripts": { 15 | "analyze": "size-limit --why", 16 | "build": "build mercurius", 17 | "generate": "ts-node --skip-project generate.ts", 18 | "listen": "node listen.js", 19 | "prepare": "build mercurius", 20 | "size": "size-limit", 21 | "start": "watch mercurius", 22 | "test": "jest", 23 | "test:watch": "watch mercurius" 24 | }, 25 | "dependencies": { 26 | "@gqless/cli": "workspace:^2.0.16", 27 | "@graphql-typed-document-node/core": "^3.1.0", 28 | "fastify": "^3.14.2", 29 | "gqless": "workspace:^2.0.14", 30 | "graphql": "^15.5.0", 31 | "lodash": "^4.17.21", 32 | "mercurius": "^7.4.0", 33 | "mercurius-codegen": "^1.4.3", 34 | "randomstring": "^1.1.5", 35 | "test-utils": "workspace:^0.1.0" 36 | }, 37 | "devDependencies": { 38 | "@size-limit/preset-small-lib": "^4.10.2", 39 | "@types/lodash": "^4.14.168", 40 | "@types/randomstring": "^1.1.6", 41 | "build-utils": "workspace:*", 42 | "jest": "^26.6.3", 43 | "mercurius-integration-testing": "^3.1.3", 44 | "size-limit": "^4.10.2", 45 | "ts-node": "^9.1.1", 46 | "tslib": "^2.2.0", 47 | "typescript": "^4.2.4" 48 | }, 49 | "engines": { 50 | "node": ">=10" 51 | }, 52 | "size-limit": [ 53 | { 54 | "path": "dist/mercurius-example.cjs.production.min.js", 55 | "limit": "10 KB" 56 | }, 57 | { 58 | "path": "dist/mercurius-example.esm.js", 59 | "limit": "10 KB" 60 | } 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /examples/mercurius/src/generated/gqless.ts: -------------------------------------------------------------------------------- 1 | import { createMercuriusTestClient } from 'mercurius-integration-testing'; 2 | 3 | import { createClient, QueryFetcher } from 'gqless'; 4 | 5 | import { app } from '../'; 6 | import { 7 | GeneratedSchema, 8 | generatedSchema, 9 | scalarsEnumsHash, 10 | SchemaObjectTypes, 11 | SchemaObjectTypesNames, 12 | } from './schema.generated'; 13 | 14 | const testClient = createMercuriusTestClient(app); 15 | const queryFetcher: QueryFetcher = function (query, variables) { 16 | return testClient.query(query, { 17 | variables, 18 | }); 19 | }; 20 | 21 | export const client = createClient< 22 | GeneratedSchema, 23 | SchemaObjectTypesNames, 24 | SchemaObjectTypes 25 | >({ 26 | schema: generatedSchema, 27 | scalarsEnumsHash, 28 | queryFetcher, 29 | normalization: { 30 | identifier(obj) { 31 | switch (obj.__typename) { 32 | case 'A': { 33 | return obj.a; 34 | } 35 | default: { 36 | return; 37 | } 38 | } 39 | }, 40 | keyFields: {}, 41 | }, 42 | }); 43 | 44 | export const { 45 | query, 46 | mutation, 47 | mutate, 48 | subscription, 49 | resolved, 50 | refetch, 51 | } = client; 52 | 53 | export * from './schema.generated'; 54 | -------------------------------------------------------------------------------- /examples/mercurius/src/graphql/operations.gql: -------------------------------------------------------------------------------- 1 | query simpleString { 2 | simpleString 3 | union { 4 | __typename 5 | ... on A { 6 | a 7 | } 8 | ... on B { 9 | b 10 | } 11 | ... on C { 12 | c 13 | } 14 | } 15 | } 16 | 17 | query arrayObjectArgs { 18 | arrayObjectArgs(limit: 2) { 19 | name 20 | father { 21 | name 22 | father { 23 | name 24 | } 25 | } 26 | } 27 | } 28 | 29 | query multipleArgs { 30 | a1: objectWithArgs(who: "hello") { 31 | zxc: name 32 | abc: name 33 | } 34 | a2: objectWithArgs(who: "hello2") { 35 | name 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/mercurius/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": ["**/*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/mercurius/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "module": "esnext", 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | // output .d.ts declaration files for consumers 9 | "declaration": true, 10 | // output .js.map sourcemap files for consumers 11 | "sourceMap": true, 12 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 13 | "rootDir": "./src", 14 | // stricter type-checking for stronger correctness. Recommended by TS 15 | "strict": true, 16 | // linter checks for common issues 17 | "noImplicitReturns": true, 18 | "noFallthroughCasesInSwitch": true, 19 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | // use Node's module resolution algorithm, instead of the legacy TS one 23 | "moduleResolution": "node", 24 | // transpile JSX to React.createElement 25 | "jsx": "react", 26 | // interop between ESM and CJS modules. Recommended by TS 27 | "esModuleInterop": true, 28 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 29 | "skipLibCheck": true, 30 | // error out if import and file system have a casing mismatch. Recommended by TS 31 | "forceConsistentCasingInFileNames": true, 32 | "noEmit": true, 33 | "preserveWatchOutput": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/react/api/server.ts: -------------------------------------------------------------------------------- 1 | import Fastify from 'fastify'; 2 | import ms from 'ms'; 3 | import FastifyNext from 'fastify-nextjs'; 4 | import { resolve } from 'path'; 5 | import mercuriusUpload from 'mercurius-upload'; 6 | import AltairFastify from 'altair-fastify-plugin'; 7 | 8 | import { register } from './graphql'; 9 | 10 | const app = Fastify({ 11 | logger: true, 12 | pluginTimeout: ms('60 seconds'), 13 | }); 14 | 15 | app.register(AltairFastify); 16 | 17 | app.register(mercuriusUpload, {}); 18 | 19 | register(app).catch(console.error); 20 | 21 | console.log('> React example API server started.'); 22 | 23 | app 24 | .register(FastifyNext, { 25 | logLevel: 'error', 26 | dir: resolve(__dirname, '../'), 27 | }) 28 | .after(() => { 29 | try { 30 | app.next('/*'); 31 | } catch (err) { 32 | console.error(err); 33 | } 34 | }); 35 | 36 | app.listen(4141, '0.0.0.0', (err) => { 37 | if (err) throw err; 38 | }); 39 | -------------------------------------------------------------------------------- /examples/react/gqless.config.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import("@gqless/cli").GQlessConfig} 3 | */ 4 | const config = { 5 | enumsAsStrings: false, 6 | react: false, 7 | scalarTypes: { DateTime: 'string', Upload: 'File' }, 8 | preImport: '', 9 | introspection: { endpoint: 'SPECIFY_ENDPOINT_OR_SCHEMA_FILE_PATH_HERE' }, 10 | destination: './src/generated/graphql.ts', 11 | }; 12 | 13 | module.exports = config; 14 | -------------------------------------------------------------------------------- /examples/react/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /examples/react/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // experimental: { 3 | // reactMode: 'concurrent', 4 | // }, 5 | 6 | // Set to `true` to test consistency. 7 | // Set to `false` to test minimal renders possible. 8 | reactStrictMode: false, 9 | 10 | future: { 11 | webpack5: true, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /examples/react/open-browser.mjs: -------------------------------------------------------------------------------- 1 | import { differenceInMinutes } from 'date-fns'; 2 | import { existsSync, readFileSync, writeFileSync } from 'fs'; 3 | import open from 'open'; 4 | 5 | const lastOpenBrowserDateFile = './last-browser-open'; 6 | 7 | if (existsSync(lastOpenBrowserDateFile)) { 8 | const date = new Date( 9 | readFileSync(lastOpenBrowserDateFile, { 10 | encoding: 'utf-8', 11 | }) 12 | ); 13 | 14 | if (Math.abs(differenceInMinutes(date, new Date())) > 30) { 15 | open('http://localhost:4141', {}).catch(console.error); 16 | } 17 | } else { 18 | open('http://localhost:4141', {}).catch(console.error); 19 | } 20 | 21 | writeFileSync(lastOpenBrowserDateFile, new Date().toISOString(), { 22 | encoding: 'utf-8', 23 | }); 24 | -------------------------------------------------------------------------------- /examples/react/src/components/NoSSR.tsx: -------------------------------------------------------------------------------- 1 | import dynamic from 'next/dynamic'; 2 | import { ReactNode } from 'react'; 3 | 4 | export const NoSSR = dynamic( 5 | () => 6 | Promise.resolve(function NoSSR({ children }: { children: ReactNode }) { 7 | return <>{children}; 8 | }), 9 | { 10 | ssr: false, 11 | } 12 | ); 13 | -------------------------------------------------------------------------------- /examples/react/src/components/client.ts: -------------------------------------------------------------------------------- 1 | import { createLogger } from '@gqless/logger'; 2 | 3 | import { createReactClient } from '@gqless/react'; 4 | import { client, GeneratedSchema } from '../graphql/gqless'; 5 | 6 | export const { 7 | useTransactionQuery, 8 | useQuery, 9 | state, 10 | graphql, 11 | useRefetch, 12 | useLazyQuery, 13 | prepareReactRender, 14 | useHydrateCache, 15 | useMutation, 16 | useMetaState, 17 | useSubscription, 18 | prepareQuery, 19 | usePaginatedQuery, 20 | } = createReactClient(client, { 21 | defaults: { 22 | suspense: true, 23 | staleWhileRevalidate: false, 24 | transactionQuerySuspense: false, 25 | }, 26 | }); 27 | 28 | if (typeof window !== 'undefined') { 29 | const logger = createLogger(client, {}); 30 | logger.start(); 31 | } 32 | 33 | export const { refetch, buildSelection } = client; 34 | -------------------------------------------------------------------------------- /examples/react/src/components/common.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MutableRefObject, 3 | useCallback, 4 | useEffect, 5 | useLayoutEffect, 6 | useReducer, 7 | useRef, 8 | } from 'react'; 9 | 10 | export const useIsomorphicLayoutEffect = 11 | typeof window !== 'undefined' ? useLayoutEffect : useEffect; 12 | 13 | const updateReducer = (num: number): number => (num + 1) % 1_000_000; 14 | 15 | export const useBatchUpdate = () => { 16 | const isMounted = useIsMounted(); 17 | 18 | const isRendering = useRef(true); 19 | isRendering.current = true; 20 | 21 | const [, update] = useReducer(updateReducer, 0); 22 | 23 | useEffect(() => { 24 | isRendering.current = false; 25 | }); 26 | 27 | return useCallback(() => { 28 | if (!isMounted.current) return; 29 | 30 | if (isRendering.current) { 31 | setTimeout(() => { 32 | if (isMounted.current) update(); 33 | }, 0); 34 | } else { 35 | update(); 36 | } 37 | }, [update, isRendering, isMounted]); 38 | }; 39 | 40 | export const useIsMounted = () => { 41 | const isMounted = useRef(true); 42 | 43 | useIsomorphicLayoutEffect(() => { 44 | isMounted.current = true; 45 | return () => { 46 | isMounted.current = false; 47 | }; 48 | }, []); 49 | 50 | return isMounted; 51 | }; 52 | 53 | const InitSymbol: any = Symbol(); 54 | 55 | export const useLazyRef = (initialValFunc: () => T) => { 56 | const ref: MutableRefObject = useRef(InitSymbol); 57 | if (ref.current === InitSymbol) { 58 | ref.current = initialValFunc(); 59 | } 60 | return ref; 61 | }; 62 | -------------------------------------------------------------------------------- /examples/react/src/components/meta.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | import { Button, Stack, Text } from '@chakra-ui/react'; 4 | 5 | import { useMetaState } from './client'; 6 | 7 | const NavigationList = [ 8 | '/', 9 | '/normalized', 10 | '/refetch', 11 | '/stringArray', 12 | '/ssr', 13 | '/polling', 14 | '/error', 15 | '/playground', 16 | '/pagination', 17 | '/pagination_infinite_scroll', 18 | '/cache', 19 | '/emptyArrays', 20 | '/subscriptions', 21 | '/preparedQuery', 22 | '/useQueryTest', 23 | '/prepass', 24 | '/uploadFile', 25 | '/transactionQuery1', 26 | '/transactionQuery2', 27 | ]; 28 | 29 | export const MetaClient = () => { 30 | const { isFetching, errors } = useMetaState({ 31 | onStartFetching() {}, 32 | onDoneFetching() {}, 33 | onError() {}, 34 | }); 35 | 36 | return ( 37 | 46 | 47 | {isFetching ? 'Fetching...' : 'Done'} 48 | 49 | {errors && ( 50 | {JSON.stringify(errors, null, 2)} 51 | )} 52 | 53 | 54 | {NavigationList.map((href, key) => { 55 | return ( 56 | 57 | 60 | 61 | ); 62 | })} 63 | 64 | 65 | ); 66 | }; 67 | -------------------------------------------------------------------------------- /examples/react/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import type { AppProps } from 'next/app'; 2 | import { Suspense } from 'react'; 3 | 4 | import { ChakraProvider, Stack } from '@chakra-ui/react'; 5 | 6 | import { MetaClient } from '../components/meta'; 7 | import { NoSSR } from '../components/NoSSR'; 8 | import SSRPage from './ssr'; 9 | 10 | function MyApp({ Component, pageProps }: AppProps) { 11 | const commonComponents = ( 12 | 13 | 14 | 15 | 16 | ); 17 | if (Component === SSRPage) { 18 | return {commonComponents}; 19 | } 20 | return ( 21 | 22 | 23 | {commonComponents} 24 | 25 | 26 | ); 27 | } 28 | 29 | export default MyApp; 30 | -------------------------------------------------------------------------------- /examples/react/src/pages/emptyArrays.tsx: -------------------------------------------------------------------------------- 1 | import { ListItem, OrderedList, Stack } from '@chakra-ui/react'; 2 | import { graphql } from '../components/client'; 3 | import { query } from '../graphql/gqless'; 4 | 5 | export default graphql( 6 | function EmptyArrays() { 7 | query.time; 8 | return ( 9 | 10 | 11 | {query.emptyScalarArray.map((value = 0) => { 12 | return {value}; 13 | })} 14 | 15 | 16 | {query.emptyHumanArray.map(({ id = 0, name }) => { 17 | return ( 18 | 19 | ID: {id} 20 |
21 | Name: {name} 22 |
23 | ); 24 | })} 25 |
26 |
27 | ); 28 | }, 29 | { 30 | suspense: { 31 | fallback: 'Loadingasd...', 32 | }, 33 | } 34 | ); 35 | -------------------------------------------------------------------------------- /examples/react/src/pages/error.tsx: -------------------------------------------------------------------------------- 1 | import { useQuery, useTransactionQuery } from '../components/client'; 2 | import { NoSSR } from '../components/NoSSR'; 3 | import { Suspense, useState } from 'react'; 4 | import { serializeError } from 'serialize-error'; 5 | import { GQlessError } from 'gqless'; 6 | import { Stack, Text } from '@chakra-ui/react'; 7 | 8 | const ExpectedErrorComponent = () => { 9 | const { data, error } = useTransactionQuery( 10 | (query) => { 11 | return { 12 | a: query.thirdTry, 13 | b: query.__typename, 14 | }; 15 | }, 16 | { 17 | suspense: true, 18 | retry: true, 19 | fetchPolicy: 'no-cache', 20 | } 21 | ); 22 | 23 | const [inlineError, setError] = useState(); 24 | 25 | const query = useQuery({ 26 | suspense: true, 27 | onError: setError, 28 | }); 29 | 30 | return ( 31 | <> 32 | 33 | {HOOK DATA:{JSON.stringify(data)}} 34 | {error && ( 35 | HOOK ERROR: {JSON.stringify(serializeError(error))} 36 | )} 37 | 38 | 39 | INLINE DATA:{' '} 40 | {JSON.stringify({ 41 | a: query.expectedError, 42 | b: query.__typename, 43 | })} 44 | {inlineError && ( 45 | 46 | INLINE ERROR: {JSON.stringify(serializeError(inlineError))} 47 | 48 | )} 49 | 50 | 51 | ); 52 | }; 53 | 54 | export default function ErrorPage() { 55 | return ( 56 | 57 | Loading Here...}> 58 | 59 | 60 | 61 | ); 62 | } 63 | -------------------------------------------------------------------------------- /examples/react/src/pages/normalized.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Stack, Text } from '@chakra-ui/react'; 2 | import { selectFields } from 'gqless'; 3 | import { useMutation, useQuery } from '../components/client'; 4 | 5 | export default function NormalizedPage() { 6 | const query = useQuery({ 7 | suspense: true, 8 | staleWhileRevalidate: true, 9 | }); 10 | 11 | const [renameDog] = useMutation((mutation) => { 12 | const dog = mutation.renameDog({ 13 | id: '1', 14 | name: 'z', 15 | }); 16 | 17 | dog?.id; 18 | dog?.name; 19 | }); 20 | 21 | const [renameHuman] = useMutation((mutation) => { 22 | const human = mutation.renameHuman({ 23 | id: '1', 24 | name: 'x', 25 | }); 26 | 27 | human?.id; 28 | human?.name; 29 | }); 30 | 31 | return ( 32 | 33 | {query.time} 34 | 35 | 36 | 37 | {JSON.stringify(selectFields(query.humans, '*', 2), null, 2)} 38 | 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /examples/react/src/pages/preparedQuery.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Stack, Text } from '@chakra-ui/react'; 2 | import { useState } from 'react'; 3 | import { prepareQuery } from '../components/client'; 4 | 5 | const { usePrepared, preload, refetch } = prepareQuery((query) => { 6 | return query.time!; 7 | }); 8 | 9 | function TimeComponent() { 10 | const { data, isRefetching } = usePrepared({ 11 | suspense: true, 12 | }); 13 | 14 | return ( 15 | 16 | Time: {data} 17 | 20 | 21 | ); 22 | } 23 | 24 | export default function PreparedQueryPage() { 25 | const [showTimeComponent, setShowTimeComponent] = useState(false); 26 | const [isLoading, setIsLoading] = useState(false); 27 | 28 | return ( 29 | 30 | 43 | {showTimeComponent && } 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /examples/react/src/pages/prepass.tsx: -------------------------------------------------------------------------------- 1 | import { ListItem, OrderedList, Stack, Text } from '@chakra-ui/react'; 2 | import { useQuery } from '../components/client'; 3 | 4 | let renderCount = 0; 5 | export default function PrepassPage() { 6 | const query = useQuery({ 7 | suspense: false, 8 | prepare({ prepass, query }) { 9 | prepass(query, 'dogs.name'); 10 | }, 11 | }); 12 | 13 | renderCount++; 14 | 15 | if (query.$state.isLoading) { 16 | console.log('IS LOADING'); 17 | } else { 18 | console.log("IT'S NOT LOADING"); 19 | } 20 | 21 | if (query.$state.isLoading) return Loading...; 22 | 23 | return ( 24 | 25 | Render Count: {renderCount} 26 | {query.dogs.map((dog) => { 27 | return ( 28 | 29 | 30 | 31 | ID: {dog.id} 32 | 33 | 34 | Name: {dog.name} 35 | 36 | 37 | 38 | 39 | ); 40 | })} 41 | 42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /examples/react/src/pages/refetch.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Stack, Text } from '@chakra-ui/react'; 2 | import { useQuery, useRefetch } from '../components/client'; 3 | 4 | export default function RefetchPage() { 5 | const query = useQuery(); 6 | 7 | const refetchTime = useRefetch(); 8 | 9 | const time = query.time; 10 | 11 | refetchTime.stopWatching(); 12 | 13 | const refetchQueryTypename = useRefetch(); 14 | 15 | const queryTypename = query.__typename; 16 | 17 | return ( 18 | 19 | {time} 20 | 23 | 24 | {queryTypename} 25 | 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /examples/react/src/pages/ssr.tsx: -------------------------------------------------------------------------------- 1 | import { RouterContext } from 'next/dist/next-server/lib/router-context'; 2 | 3 | import { PropsWithServerCache } from '@gqless/react'; 4 | 5 | import { 6 | graphql, 7 | prepareReactRender, 8 | useHydrateCache, 9 | } from '../components/client'; 10 | import { default as RefetchPage } from './refetch'; 11 | 12 | import type { GetServerSideProps } from 'next'; 13 | 14 | export const getServerSideProps: GetServerSideProps = async ({}) => { 15 | const { cacheSnapshot } = await prepareReactRender( 16 | 17 | 18 | 19 | ); 20 | 21 | return { 22 | props: { 23 | cacheSnapshot, 24 | }, 25 | }; 26 | }; 27 | 28 | export default graphql( 29 | function SSRPage({ cacheSnapshot }: PropsWithServerCache) { 30 | useHydrateCache({ 31 | cacheSnapshot, 32 | }); 33 | 34 | return ; 35 | }, 36 | { 37 | suspense: { 38 | fallback: 'Loading SSR...', 39 | }, 40 | staleWhileRevalidate: false, 41 | } 42 | ); 43 | -------------------------------------------------------------------------------- /examples/react/src/pages/stringArray.tsx: -------------------------------------------------------------------------------- 1 | import { Stack, Text } from '@chakra-ui/react'; 2 | import { useQuery, buildSelection } from '../components/client'; 3 | import { query } from '../graphql/gqless'; 4 | 5 | query.dogs; 6 | 7 | typeof window !== 'undefined' && 8 | console.log( 9 | 'selection', 10 | buildSelection('query', 'dogs', 'owner', 'dogs', 'owner', 'name') 11 | ); 12 | 13 | export default function TestingStringArray() { 14 | const query = useQuery({ 15 | suspense: false, 16 | }); 17 | 18 | return ( 19 | 20 | {query.stringList.map((v, index) => ( 21 | {v} 22 | ))} 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /examples/react/src/pages/subscriptions.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Heading, Stack, Text } from '@chakra-ui/react'; 2 | import { useMutation, useSubscription } from '../components/client'; 3 | 4 | let n = 0; 5 | 6 | function SendNotification() { 7 | const [sendNotification] = useMutation((mutation, message: string) => { 8 | return mutation.sendNotification({ 9 | message, 10 | }); 11 | }); 12 | 13 | return ( 14 | <> 15 | 25 | 34 | 35 | ); 36 | } 37 | 38 | export default function SubscriptionsPage() { 39 | const subscription = useSubscription(); 40 | 41 | return ( 42 | 43 | 44 | Data 45 | {subscription.newNotification} 46 | 47 | 48 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /examples/react/src/pages/transactionQuery1.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Stack, Text } from '@chakra-ui/react'; 2 | import { useTransactionQuery } from '../components/client'; 3 | import { mutate } from '../graphql/gqless'; 4 | 5 | let nRenders = 0; 6 | export default function TransactionQuery1() { 7 | const { data } = useTransactionQuery( 8 | (query) => { 9 | return query.human1.name; 10 | }, 11 | { 12 | suspense: true, 13 | fetchPolicy: 'cache-first', 14 | } 15 | ); 16 | 17 | return ( 18 | 19 | 20 | {++nRenders} 21 |
22 | query1 {JSON.stringify(data)} 23 |
24 | 25 | 37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /examples/react/src/pages/transactionQuery2.tsx: -------------------------------------------------------------------------------- 1 | import { useTransactionQuery } from '../components/client'; 2 | 3 | let nRenders = 0; 4 | 5 | export default function TransactionQuery2() { 6 | const { data } = useTransactionQuery( 7 | (query) => { 8 | return query.human1.name; 9 | }, 10 | { 11 | suspense: false, 12 | } 13 | ); 14 | 15 | return ( 16 |
17 | {++nRenders} 18 | query2 {JSON.stringify(data)} 19 |
20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /examples/react/src/pages/uploadFile.tsx: -------------------------------------------------------------------------------- 1 | import { Input, Stack, Text } from '@chakra-ui/react'; 2 | import { ChangeEvent, useState } from 'react'; 3 | import { useMutation } from '../components/client'; 4 | 5 | export default function UploadFile() { 6 | const [imageb64, setImageb64] = useState(''); 7 | const [uploadFile, { isLoading }] = useMutation( 8 | (mutation, file: File) => { 9 | return mutation.uploadFile({ 10 | file, 11 | })!; 12 | }, 13 | { 14 | onCompleted(data) { 15 | setImageb64(data); 16 | }, 17 | noCache: true, 18 | nonSerializableVariables: true, 19 | } 20 | ); 21 | return ( 22 | 23 | ) => { 33 | files && validity.valid && uploadFile({ args: files[0] }); 34 | }} 35 | /> 36 | {imageb64 ? : null} 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /examples/react/src/pages/useQueryTest.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useQuery } from '../components/client'; 3 | 4 | let nRender = 0; 5 | let nCommitedRender = 0; 6 | 7 | export default function UseQueryPage() { 8 | const query = useQuery({ 9 | suspense: true, 10 | }); 11 | 12 | useEffect(() => { 13 | console.log('Commited render:', ++nCommitedRender); 14 | }); 15 | 16 | if (query.$state.isLoading) { 17 | console.log('IS LOADING!'); 18 | return ( 19 |

20 | Loading...
Render: {++nRender} 21 |

22 | ); 23 | } 24 | 25 | return ( 26 |
27 | {query.time} 28 |
29 | Render: {++nRender} 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /examples/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "api", "types"], 4 | "compilerOptions": { 5 | "target": "es2018", 6 | "module": "esnext", 7 | "lib": ["dom", "esnext"], 8 | "importHelpers": true, 9 | // output .d.ts declaration files for consumers 10 | "declaration": true, 11 | // output .js.map sourcemap files for consumers 12 | "sourceMap": true, 13 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 14 | "rootDir": "../", 15 | // stricter type-checking for stronger correctness. Recommended by TS 16 | "strict": true, 17 | // linter checks for common issues 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 21 | "isolatedModules": true, 22 | "noUnusedLocals": false, 23 | "noUnusedParameters": false, 24 | // use Node's module resolution algorithm, instead of the legacy TS one 25 | "moduleResolution": "node", 26 | // transpile JSX to React.createElement 27 | "jsx": "preserve", 28 | // interop between ESM and CJS modules. Recommended by TS 29 | "esModuleInterop": true, 30 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 31 | "skipLibCheck": true, 32 | // error out if import and file system have a casing mismatch. Recommended by TS 33 | "forceConsistentCasingInFileNames": true, 34 | // "noEmit": true, 35 | "preserveWatchOutput": true, 36 | "outDir": "./dist", 37 | "incremental": true, 38 | "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo", 39 | "allowJs": true, 40 | "noEmit": true, 41 | "resolveJsonModule": true 42 | }, 43 | "exclude": ["node_modules"] 44 | } 45 | -------------------------------------------------------------------------------- /internal/build-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "build-utils", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "bin": { 7 | "build": "./bin/build.js", 8 | "gh-release": "./bin/github-release.js", 9 | "watch": "./bin/watch.js" 10 | }, 11 | "dependencies": { 12 | "@rollup/plugin-replace": "^2.4.2", 13 | "@rollup/plugin-typescript": "^8.2.1", 14 | "commander": "^7.2.0", 15 | "cross-spawn": "^7.0.3", 16 | "execa": "^5.0.0", 17 | "fs-extra": "^9.1.0", 18 | "github-release-cli": "^2.0.0", 19 | "rollup": "^2.45.2", 20 | "rollup-plugin-cleanup": "^3.2.1", 21 | "rollup-plugin-terser": "^7.0.2", 22 | "string-argv": "^0.3.1", 23 | "tree-kill": "^1.2.2" 24 | }, 25 | "devDependencies": { 26 | "@types/cross-spawn": "^6.0.2", 27 | "@types/fs-extra": "^9.0.11" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /internal/build-utils/src/buildWriteTypes.js: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | import fsExtra from 'fs-extra'; 3 | import { existsSync } from 'fs'; 4 | 5 | const { outputFile, remove } = fsExtra; 6 | 7 | export async function buildWriteTypes( 8 | /** 9 | * @type {import("rollup").RollupBuild} 10 | */ 11 | bundle, 12 | /** 13 | * @type {() => void} 14 | */ 15 | afterFileWrite = () => {}, 16 | /** 17 | * @type {string} 18 | */ 19 | cwd = '.' 20 | ) { 21 | const dir = resolve(cwd, 'dist'); 22 | const { output } = await bundle.generate({ 23 | dir, 24 | sourcemap: true, 25 | }); 26 | 27 | const writingPromise = Promise.all( 28 | output.map((chunkOrAsset) => { 29 | if (chunkOrAsset.type === 'asset') { 30 | const destination = resolve(dir, chunkOrAsset.fileName); 31 | 32 | return outputFile(destination, chunkOrAsset.source).then( 33 | afterFileWrite 34 | ); 35 | } 36 | }) 37 | ); 38 | 39 | const duplicatedTypesDist = resolve(dir, './dist'); 40 | 41 | if (existsSync(duplicatedTypesDist)) { 42 | await Promise.all([writingPromise, remove(duplicatedTypesDist)]); 43 | } else { 44 | await writingPromise; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /internal/build-utils/src/index.js: -------------------------------------------------------------------------------- 1 | export * from './buildWriteTypes.js'; 2 | export * from './config.js'; 3 | export * from './writeIndex.js'; 4 | -------------------------------------------------------------------------------- /internal/build-utils/src/writeIndex.js: -------------------------------------------------------------------------------- 1 | import { promises } from 'fs'; 2 | import { resolve } from 'path'; 3 | 4 | const { writeFile } = promises; 5 | 6 | export async function writeIndex( 7 | /** 8 | * @type {string} 9 | */ 10 | moduleName, 11 | /** 12 | * @type {string} 13 | */ 14 | cwd = '.' 15 | ) { 16 | await writeFile( 17 | resolve(cwd, 'dist/index.js'), 18 | `'use strict' 19 | if (process.env.NODE_ENV === "production") { 20 | module.exports = require('./${moduleName}.cjs.production.min.js') 21 | } else { 22 | module.exports = require('./${moduleName}.cjs.development.js') 23 | } 24 | ` 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /internal/build-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "checkJs": true, 4 | "allowJs": true, 5 | "noEmit": true, 6 | "esModuleInterop": true 7 | }, 8 | "include": ["src/**/*.js", "bin/**/*.js"], 9 | "exclude": ["node_modules"] 10 | } 11 | -------------------------------------------------------------------------------- /internal/gqless.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/gqless.sketch -------------------------------------------------------------------------------- /internal/test-utils/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | dist 5 | -------------------------------------------------------------------------------- /internal/test-utils/LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright © `2021` `GQless` 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the “Software”), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /internal/test-utils/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/test-utils/README.md -------------------------------------------------------------------------------- /internal/test-utils/bin/jest-test.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const crossEnv = require('cross-env'); 4 | 5 | crossEnv('jest'.split(' ')); 6 | -------------------------------------------------------------------------------- /internal/test-utils/jest.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import("@jest/types").Config.InitialOptions} 3 | */ 4 | const defaultConfig = { 5 | globals: { 6 | 'ts-jest': {}, 7 | }, 8 | transform: { 9 | '.(ts|tsx)$': require.resolve('ts-jest/dist'), 10 | }, 11 | transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'], 12 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 13 | testEnvironment: 'node', 14 | testMatch: ['**/test/**/*.test.ts', '**/test/**/*.test.tsx'], 15 | testURL: 'http://localhost', 16 | testPathIgnorePatterns: ['/node_modules/', '/test/generated'], 17 | collectCoverage: true, 18 | collectCoverageFrom: ['./src/**/*.ts', './src/**/*.tsx', '!**/*.d.ts'], 19 | testTimeout: 10000, 20 | watchPlugins: [ 21 | require.resolve('jest-watch-typeahead/filename'), 22 | require.resolve('jest-watch-typeahead/testname'), 23 | ], 24 | restoreMocks: true, 25 | }; 26 | 27 | exports.default = defaultConfig; 28 | 29 | exports.getConfig = function getConfig( 30 | /** 31 | * @type {import("@jest/types").Config.InitialOptions} 32 | */ 33 | config = {} 34 | ) { 35 | /** 36 | * @type {import("@jest/types").Config.InitialOptions} 37 | */ 38 | const newConfig = { 39 | ...defaultConfig, 40 | ...config, 41 | }; 42 | 43 | return newConfig; 44 | }; 45 | -------------------------------------------------------------------------------- /internal/test-utils/jest.config.ts: -------------------------------------------------------------------------------- 1 | export default require('./jest.config.js').default; 2 | -------------------------------------------------------------------------------- /internal/test-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-utils", 3 | "version": "0.1.0", 4 | "private": true, 5 | "license": "MIT", 6 | "author": "GQless ", 7 | "main": "dist/index.js", 8 | "module": "dist/index.mjs", 9 | "typings": "src/index.d.ts", 10 | "bin": { 11 | "jest-test": "bin/jest-test.js" 12 | }, 13 | "scripts": { 14 | "analyze": "size-limit --why", 15 | "build": "rimraf dist && tsup src/index.ts --format esm,cjs", 16 | "prepare": "pnpm build", 17 | "size": "size-limit", 18 | "start": "nodemon --exec \"concurrently pnpm:build tsc\" -w src/index.ts", 19 | "test": "jest --config jest.config.ts" 20 | }, 21 | "dependencies": { 22 | "@rollup/plugin-babel": "^5.3.0", 23 | "@types/jest": "^26.0.22", 24 | "cross-env": "^7.0.3", 25 | "esbuild": "^0.11.12", 26 | "fastify": "^3.14.2", 27 | "get-port": "^5.1.1", 28 | "graphql": "^15.5.0", 29 | "jest": "^26.6.3", 30 | "jest-watch-typeahead": "^0.6.2", 31 | "mercurius": "^7.4.0", 32 | "mercurius-codegen": "^1.4.3", 33 | "mercurius-integration-testing": "^3.1.3", 34 | "nodemon": "^2.0.7", 35 | "prettier": "^2.2.1", 36 | "randomstring": "^1.1.5", 37 | "ts-jest": "^26.5.5", 38 | "wait-for-expect": "^3.0.2" 39 | }, 40 | "devDependencies": { 41 | "@jest/types": "^26.6.2", 42 | "@size-limit/preset-small-lib": "^4.10.2", 43 | "@types/randomstring": "^1.1.6", 44 | "concurrently": "^6.0.2", 45 | "rimraf": "^3.0.2", 46 | "size-limit": "^4.10.2", 47 | "tslib": "^2.2.0", 48 | "tsup": "^4.9.1", 49 | "typescript": "^4.2.4" 50 | }, 51 | "engines": { 52 | "node": ">=10" 53 | }, 54 | "size-limit": [ 55 | { 56 | "path": "dist/test-utils.cjs.production.min.js", 57 | "limit": "10 KB" 58 | }, 59 | { 60 | "path": "dist/test-utils.esm.js", 61 | "limit": "10 KB" 62 | } 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /internal/test-utils/src/app.d.ts: -------------------------------------------------------------------------------- 1 | import { FastifyInstance } from 'fastify'; 2 | import { MercuriusOptions } from 'mercurius'; 3 | import { createMercuriusTestClient } from 'mercurius-integration-testing'; 4 | export declare function createTestApp( 5 | options: MercuriusOptions, 6 | { 7 | codegenPath, 8 | }?: { 9 | codegenPath?: string; 10 | } 11 | ): { 12 | server: FastifyInstance; 13 | client: ReturnType; 14 | isReady: Promise; 15 | }; 16 | export * as mercurius from 'mercurius'; 17 | export * as fastify from 'fastify'; 18 | export { gql } from 'mercurius-codegen'; 19 | -------------------------------------------------------------------------------- /internal/test-utils/src/app.ts: -------------------------------------------------------------------------------- 1 | import fastify, { FastifyInstance } from 'fastify'; 2 | import mercurius, { MercuriusOptions } from 'mercurius'; 3 | import { createMercuriusTestClient } from 'mercurius-integration-testing'; 4 | 5 | export function createTestApp( 6 | options: MercuriusOptions, 7 | { 8 | codegenPath, 9 | }: { 10 | codegenPath?: string; 11 | } = {} 12 | ): { 13 | server: FastifyInstance; 14 | client: ReturnType; 15 | isReady: Promise; 16 | } { 17 | const server = fastify(); 18 | 19 | server.register(mercurius, options); 20 | 21 | let isReady = codegenPath 22 | ? new Promise((resolve, reject) => { 23 | import('mercurius-codegen') 24 | .then(({ default: mercuriusCodegen }) => { 25 | mercuriusCodegen(server, { 26 | targetPath: codegenPath, 27 | silent: true, 28 | disable: false, 29 | }) 30 | .then(resolve) 31 | .catch(reject); 32 | }) 33 | .catch(reject); 34 | }) 35 | : ((server.ready() as unknown) as Promise); 36 | 37 | const client = createMercuriusTestClient(server, { 38 | url: options.path, 39 | }); 40 | 41 | return { server, client, isReady }; 42 | } 43 | 44 | export * as mercurius from 'mercurius'; 45 | export * as fastify from 'fastify'; 46 | 47 | export { gql } from 'mercurius-codegen'; 48 | -------------------------------------------------------------------------------- /internal/test-utils/src/index.d.ts: -------------------------------------------------------------------------------- 1 | import * as randomstring from 'randomstring'; 2 | export { default as waitForExpect } from 'wait-for-expect'; 3 | export * as mercurius from 'mercurius'; 4 | export * as fastify from 'fastify'; 5 | export declare function assertIsDefined( 6 | value: T, 7 | message?: string 8 | ): asserts value is NonNullable; 9 | export { randomstring }; 10 | export * from './app'; 11 | -------------------------------------------------------------------------------- /internal/test-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as randomstring from 'randomstring'; 2 | 3 | export { default as waitForExpect } from 'wait-for-expect'; 4 | 5 | export * as mercurius from 'mercurius'; 6 | export * as fastify from 'fastify'; 7 | 8 | export function assertIsDefined( 9 | value: T, 10 | message?: string 11 | ): asserts value is NonNullable { 12 | if (value == null) { 13 | const error = new Error(message || 'value is nullable'); 14 | 15 | Error.captureStackTrace(error, assertIsDefined); 16 | throw error; 17 | } 18 | } 19 | 20 | export { randomstring }; 21 | 22 | export * from './app'; 23 | -------------------------------------------------------------------------------- /internal/test-utils/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "strictNullChecks": true, 5 | "rootDir": "../" 6 | }, 7 | "include": ["**/*.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /internal/test-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "incremental": false, 6 | "module": "esnext", 7 | "lib": ["dom", "esnext"], 8 | "importHelpers": true, 9 | // output .d.ts declaration files for consumers 10 | "declaration": true, 11 | // output .js.map sourcemap files for consumers 12 | "sourceMap": true, 13 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 14 | "rootDir": "./src", 15 | // stricter type-checking for stronger correctness. Recommended by TS 16 | "strict": true, 17 | // linter checks for common issues 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "isolatedModules": true, 21 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 22 | "noUnusedLocals": true, 23 | "noUnusedParameters": true, 24 | // use Node's module resolution algorithm, instead of the legacy TS one 25 | "moduleResolution": "node", 26 | // transpile JSX to React.createElement 27 | "jsx": "react", 28 | // interop between ESM and CJS modules. Recommended by TS 29 | "esModuleInterop": true, 30 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 31 | "skipLibCheck": true, 32 | // error out if import and file system have a casing mismatch. Recommended by TS 33 | "forceConsistentCasingInFileNames": true, 34 | "preserveWatchOutput": true, 35 | "emitDeclarationOnly": true 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /internal/test-utils/types/app.d.ts: -------------------------------------------------------------------------------- 1 | import { FastifyInstance } from 'fastify'; 2 | import { MercuriusOptions } from 'mercurius'; 3 | import { createMercuriusTestClient } from 'mercurius-integration-testing'; 4 | export declare function createTestApp( 5 | options: MercuriusOptions, 6 | { 7 | codegenPath, 8 | }?: { 9 | codegenPath?: string; 10 | } 11 | ): { 12 | server: FastifyInstance; 13 | client: ReturnType; 14 | isReady: Promise; 15 | }; 16 | export * as mercurius from 'mercurius'; 17 | export * as fastify from 'fastify'; 18 | export { gql } from 'mercurius-codegen'; 19 | -------------------------------------------------------------------------------- /internal/test-utils/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import * as randomstring from 'randomstring'; 2 | export { default as waitForExpect } from 'wait-for-expect'; 3 | export * as mercurius from 'mercurius'; 4 | export * as fastify from 'fastify'; 5 | export declare function assertIsDefined( 6 | value: T, 7 | message?: string 8 | ): asserts value is NonNullable; 9 | export { randomstring }; 10 | export * from './app'; 11 | -------------------------------------------------------------------------------- /internal/website/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "semi": true, 4 | "singleQuote": true, 5 | "trailingComma": "es5" 6 | } 7 | -------------------------------------------------------------------------------- /internal/website/fix-typedoc-plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = function (_context, _options) { 2 | return { 3 | name: 'Fix Typedoc', 4 | async contentLoaded() { 5 | require('./fix-typedoc'); 6 | return null; 7 | }, 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /internal/website/fix-typedoc.js: -------------------------------------------------------------------------------- 1 | const { 2 | promises: { readFile, writeFile }, 3 | } = require('fs'); 4 | const { spawnSync } = require('child_process'); 5 | const globby = require('globby'); 6 | 7 | spawnSync('node', ['./node_modules/pretty-quick/bin/pretty-quick.js'], { 8 | stdio: 'ignore', 9 | }); 10 | 11 | const encoding = { 12 | encoding: 'utf-8', 13 | }; 14 | 15 | async function main() { 16 | const docFiles = await globby([ 17 | '../../docs/client/api/**/*.md', 18 | '../../docs/react/api/**/*.md', 19 | ]); 20 | 21 | await Promise.all( 22 | docFiles.map(async (docPath) => { 23 | const docContent = await readFile(docPath, encoding); 24 | 25 | const docContentSplit = docContent.split('\n'); 26 | 27 | // Remove duplicated line references 28 | const filteredDocContent = docContentSplit 29 | .filter((line, index) => { 30 | const isLineReference = !!line.match(/Defined in\: \[(.*?)\)/); 31 | 32 | if ( 33 | isLineReference && 34 | docContentSplit.indexOf(line, Math.max(0, index - 2)) !== index 35 | ) { 36 | return false; 37 | } 38 | 39 | return true; 40 | }) 41 | .join('\n'); 42 | 43 | await writeFile( 44 | docPath, 45 | filteredDocContent.replace(/\/blob\/(.*?)\//g, '/blob/master/'), 46 | encoding 47 | ); 48 | }) 49 | ); 50 | 51 | spawnSync('node', ['./node_modules/pretty-quick/bin/pretty-quick.js'], { 52 | stdio: 'ignore', 53 | }); 54 | } 55 | 56 | main().catch((err) => { 57 | console.error(err); 58 | process.exit(1); 59 | }); 60 | -------------------------------------------------------------------------------- /internal/website/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | docs: [ 3 | { 4 | type: 'category', 5 | label: 'Introduction', 6 | collapsed: false, 7 | items: [ 8 | 'intro', 9 | 'intro/how-it-works', 10 | // 'introduction/features', 11 | 'intro/new-in-2', 12 | 'contributing', 13 | ], 14 | }, 15 | { type: 'doc', id: 'getting-started' }, 16 | { 17 | type: 'category', 18 | label: 'Usage with React', 19 | collapsed: false, 20 | items: [ 21 | 'react/fetching-data', 22 | 'react/mutations', 23 | 'react/subscriptions', 24 | 'react/config', 25 | 'react/suspense', 26 | 'react/ssr', 27 | 'react/meta', 28 | { 29 | type: 'category', 30 | label: 'API Reference', 31 | items: require('./sidebars/react.js'), 32 | }, 33 | ], 34 | }, 35 | { 36 | type: 'category', 37 | label: 'Core Client', 38 | collapsed: false, 39 | items: [ 40 | 'client/fetching-data', 41 | 'client/mutations', 42 | 'client/subscriptions', 43 | 'client/config', 44 | 'client/persistence', 45 | 'client/helper-functions', 46 | 'client/graphql-upload', 47 | { 48 | type: 'category', 49 | label: 'API Reference', 50 | items: require('./sidebars/client.js'), 51 | }, 52 | ], 53 | }, 54 | { 55 | type: 'category', 56 | label: 'CLI', 57 | collapsed: false, 58 | items: [ 59 | 'cli/config', 60 | 'cli/codegen', 61 | 'cli/javascript', 62 | 'cli/programmatic', 63 | ], 64 | }, 65 | { 66 | type: 'category', 67 | label: 'Development Tools', 68 | collapsed: false, 69 | items: ['development/logger'], 70 | }, 71 | ], 72 | }; 73 | -------------------------------------------------------------------------------- /internal/website/src/components/Example.tsx: -------------------------------------------------------------------------------- 1 | import { AnimationProps, motion } from 'framer-motion'; 2 | import * as React from 'react'; 3 | 4 | import styled from '@emotion/styled'; 5 | 6 | const easeInOutCubic = [0.645, 0.045, 0.355, 1]; 7 | 8 | const StyledExample = styled(motion.div)` 9 | overflow: hidden; 10 | display: flex; 11 | flex-wrap: wrap; 12 | justify-content: center; 13 | flex-direction: column; 14 | 15 | .prism-code { 16 | padding: 0; 17 | background: none !important; 18 | } 19 | `; 20 | 21 | const Title = styled(motion.h3)` 22 | font-weight: 500; 23 | margin-bottom: 0.8rem; 24 | font-size: 1.2rem; 25 | color: #e976c3; 26 | margin-bottom: 0.8rem; 27 | `; 28 | 29 | const Content = styled(motion.div)``; 30 | 31 | export const Example = ({ 32 | title, 33 | children, 34 | animate = 'visible', 35 | initial = 'hidden', 36 | }: { 37 | title: string; 38 | children: React.ReactNode; 39 | animate: AnimationProps['animate']; 40 | initial?: 'hidden' | 'visible'; 41 | }) => ( 42 | 43 | 57 | {title} 58 | 59 | 60 | 75 | {children} 76 | 77 | 78 | ); 79 | -------------------------------------------------------------------------------- /internal/website/src/components/Examples/NavLink.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | HStack, 5 | Icon, 6 | Link, 7 | LinkProps, 8 | Text, 9 | useColorModeValue as mode, 10 | } from '@chakra-ui/react'; 11 | import DocusaurusLink from '@docusaurus/Link'; 12 | import { useLocation } from '@docusaurus/router'; 13 | 14 | interface NavLinkProps extends LinkProps { 15 | label: string; 16 | icon?: any; 17 | } 18 | 19 | export const NavLink = (props: NavLinkProps) => { 20 | const { icon, label, href, ...rest } = props; 21 | const { pathname } = useLocation(); 22 | 23 | const isActive = pathname === href; 24 | 25 | return ( 26 | 50 | 51 | 52 | 53 | {label} 54 | 55 | 56 | 57 | ); 58 | }; 59 | -------------------------------------------------------------------------------- /internal/website/src/components/Examples/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FaAngleRight, FaReact } from 'react-icons/fa'; 3 | 4 | import { Flex, FlexProps, Spacer, Stack } from '@chakra-ui/react'; 5 | 6 | import { NavLink } from './NavLink'; 7 | 8 | export const Sidebar = (props: FlexProps) => { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /internal/website/src/components/Overflow.tsx: -------------------------------------------------------------------------------- 1 | import styled from '@emotion/styled'; 2 | 3 | export const Overflow = styled.div` 4 | overflow: hidden; 5 | `; 6 | -------------------------------------------------------------------------------- /internal/website/src/components/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Feature'; 2 | export * from './Arrow'; 3 | export * from './Example'; 4 | export * from './Overflow'; 5 | -------------------------------------------------------------------------------- /internal/website/src/pages/examples/suspense/query.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Heading, Text } from '@chakra-ui/react'; 4 | import Link from '@docusaurus/Link'; 5 | 6 | import { ExamplesPage } from '../../../components/Examples/App'; 7 | import { CodeSandboxEmbed } from '../../../components/Examples/Embed'; 8 | 9 | export default function Page() { 10 | return ( 11 | 12 | GraphQL Queries in React Suspense 13 | 14 | In this example you can see some usage examples of{' '} 15 | useQuery and{' '} 16 | graphql HOC. 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /internal/website/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/favicon.ico -------------------------------------------------------------------------------- /internal/website/static/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: Colfax; 3 | font-weight: 300; 4 | src: url('/fonts/ColfaxWebLight.woff2') format('woff2'); 5 | } 6 | 7 | @font-face { 8 | font-family: 'Operator Mono'; 9 | src: url('/fonts/OperatorMono.otf'); 10 | } 11 | 12 | @font-face { 13 | font-family: Colfax; 14 | font-weight: 400; 15 | src: url('/fonts/ColfaxWebRegular.woff2') format('woff2'); 16 | } 17 | @font-face { 18 | font-family: Colfax; 19 | font-weight: 500; 20 | src: url('/fonts/ColfaxWebMedium.woff2') format('woff2'); 21 | } 22 | @font-face { 23 | font-family: Colfax; 24 | font-weight: 600; 25 | src: url('/fonts/ColfaxWebBold.woff2') format('woff2'); 26 | } 27 | -------------------------------------------------------------------------------- /internal/website/static/fonts/ColfaxWebBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/fonts/ColfaxWebBold.woff2 -------------------------------------------------------------------------------- /internal/website/static/fonts/ColfaxWebLight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/fonts/ColfaxWebLight.woff2 -------------------------------------------------------------------------------- /internal/website/static/fonts/ColfaxWebMedium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/fonts/ColfaxWebMedium.woff2 -------------------------------------------------------------------------------- /internal/website/static/fonts/ColfaxWebRegular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/fonts/ColfaxWebRegular.woff2 -------------------------------------------------------------------------------- /internal/website/static/fonts/OperatorMono.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/fonts/OperatorMono.otf -------------------------------------------------------------------------------- /internal/website/static/icon/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/android-icon-144x144.png -------------------------------------------------------------------------------- /internal/website/static/icon/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/android-icon-192x192.png -------------------------------------------------------------------------------- /internal/website/static/icon/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/android-icon-36x36.png -------------------------------------------------------------------------------- /internal/website/static/icon/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/android-icon-48x48.png -------------------------------------------------------------------------------- /internal/website/static/icon/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/android-icon-72x72.png -------------------------------------------------------------------------------- /internal/website/static/icon/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/android-icon-96x96.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-114x114.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-120x120.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-144x144.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-152x152.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-180x180.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-57x57.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-60x60.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-72x72.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-76x76.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon-precomposed.png -------------------------------------------------------------------------------- /internal/website/static/icon/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/apple-icon.png -------------------------------------------------------------------------------- /internal/website/static/icon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /internal/website/static/icon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/favicon-16x16.png -------------------------------------------------------------------------------- /internal/website/static/icon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/favicon-32x32.png -------------------------------------------------------------------------------- /internal/website/static/icon/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/favicon-96x96.png -------------------------------------------------------------------------------- /internal/website/static/icon/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "App", 3 | "icons": [ 4 | { 5 | "src": "/android-icon-36x36.png", 6 | "sizes": "36x36", 7 | "type": "image/png", 8 | "density": "0.75" 9 | }, 10 | { 11 | "src": "/android-icon-48x48.png", 12 | "sizes": "48x48", 13 | "type": "image/png", 14 | "density": "1.0" 15 | }, 16 | { 17 | "src": "/android-icon-72x72.png", 18 | "sizes": "72x72", 19 | "type": "image/png", 20 | "density": "1.5" 21 | }, 22 | { 23 | "src": "/android-icon-96x96.png", 24 | "sizes": "96x96", 25 | "type": "image/png", 26 | "density": "2.0" 27 | }, 28 | { 29 | "src": "/android-icon-144x144.png", 30 | "sizes": "144x144", 31 | "type": "image/png", 32 | "density": "3.0" 33 | }, 34 | { 35 | "src": "/android-icon-192x192.png", 36 | "sizes": "192x192", 37 | "type": "image/png", 38 | "density": "4.0" 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /internal/website/static/icon/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/ms-icon-144x144.png -------------------------------------------------------------------------------- /internal/website/static/icon/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/ms-icon-150x150.png -------------------------------------------------------------------------------- /internal/website/static/icon/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/ms-icon-310x310.png -------------------------------------------------------------------------------- /internal/website/static/icon/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/icon/ms-icon-70x70.png -------------------------------------------------------------------------------- /internal/website/static/img/gqless-logo.square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/gqless-logo.square.png -------------------------------------------------------------------------------- /internal/website/static/img/graphql.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/website/static/img/intro/client-only_fields.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/intro/client-only_fields.png -------------------------------------------------------------------------------- /internal/website/static/img/intro/intellisense.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/intro/intellisense.png -------------------------------------------------------------------------------- /internal/website/static/img/javascript-output-type-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/javascript-output-type-error.png -------------------------------------------------------------------------------- /internal/website/static/img/logger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/logger.png -------------------------------------------------------------------------------- /internal/website/static/img/logger/devtools_query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/logger/devtools_query.png -------------------------------------------------------------------------------- /internal/website/static/img/logger/devtools_verbose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/logger/devtools_verbose.png -------------------------------------------------------------------------------- /internal/website/static/img/logo-1080p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/logo-1080p.png -------------------------------------------------------------------------------- /internal/website/static/img/logo-200x85.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/logo-200x85.png -------------------------------------------------------------------------------- /internal/website/static/img/logo-436p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/logo-436p.png -------------------------------------------------------------------------------- /internal/website/static/img/logo-full-size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/logo-full-size.png -------------------------------------------------------------------------------- /internal/website/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/logo.png -------------------------------------------------------------------------------- /internal/website/static/img/production_ready.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/production_ready.png -------------------------------------------------------------------------------- /internal/website/static/img/react-key-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/react-key-warning.png -------------------------------------------------------------------------------- /internal/website/static/img/react.svg: -------------------------------------------------------------------------------- 1 | 2 | React Logo 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /internal/website/static/img/suspense-ssr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/suspense-ssr.png -------------------------------------------------------------------------------- /internal/website/static/img/typescript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/img/typescript.png -------------------------------------------------------------------------------- /internal/website/static/video/invisible-data-fetching.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samdenty/gqless/27e289932cf45536c4e91190b96a4c9ce3d95063/internal/website/static/video/invisible-data-fetching.mp4 -------------------------------------------------------------------------------- /internal/website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/docusaurus/tsconfig.json", 3 | "include": ["src/"] 4 | } 5 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/nodemon", 3 | "watch": ["packages/**/*", "./package.json"], 4 | "ext": "ts", 5 | "exec": "pnpm dev:nodemon", 6 | "ignore": ["**/node_modules", "**/generated", "**/dist"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/cli/.browserslistrc: -------------------------------------------------------------------------------- 1 | node 10 -------------------------------------------------------------------------------- /packages/cli/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | dist 5 | -------------------------------------------------------------------------------- /packages/cli/LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright © `2021` `GQless` 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the “Software”), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /packages/cli/README.md: -------------------------------------------------------------------------------- 1 | # @gqless/cli 2 | 3 | ## Visit [https://gqless.com/cli/codegen](https://gqless.com/cli/codegen) 4 | -------------------------------------------------------------------------------- /packages/cli/bin/gqless.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { program } = require('commander'); 4 | 5 | const { 6 | inspectWriteGenerate, 7 | defaultConfig, 8 | __innerState, 9 | } = require('../dist/index'); 10 | 11 | __innerState.isCLI = true; 12 | 13 | program 14 | .version(require('../package.json').version) 15 | .description('CLI for gqless'); 16 | 17 | program 18 | .command('generate [endpoint] [destination]') 19 | .option('--react', 'Create React client') 20 | .description( 21 | `Inspect or read from a file a GraphQL Schema and generate the gqless client in the specified directory (./src/generated/graphql.ts by default). 22 | EXAMPLE 1: "gqless generate ./schema.gql --react" 23 | EXAMPLE 2: "gqless generate http://localhost:3000/graphql src/gqless/index.ts" 24 | EXAMPLE 3 (Configuration file): "gqless generate"` 25 | ) 26 | .action(async (endpoint, destination, opts) => { 27 | let react; 28 | if (opts.react != null) { 29 | react = defaultConfig.react = 30 | typeof opts.react === 'boolean' ? opts.react : !!opts.react; 31 | } 32 | 33 | await inspectWriteGenerate({ 34 | endpoint, 35 | destination, 36 | cli: true, 37 | generateOptions: { 38 | react, 39 | }, 40 | }).catch((err) => { 41 | if (err instanceof Error) delete err.stack; 42 | console.error(err); 43 | process.exit(1); 44 | }); 45 | process.exit(0); 46 | }); 47 | 48 | program.parse(process.argv); 49 | -------------------------------------------------------------------------------- /packages/cli/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('test-utils/jest.config.js').default; 2 | -------------------------------------------------------------------------------- /packages/cli/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './generate'; 2 | export * from './inspectWriteGenerate'; 3 | export * from './introspection'; 4 | export * from './writeGenerate'; 5 | export type { GQlessConfig as gqlessConfig, GQlessConfig } from './config'; 6 | export { defaultConfig, gqlessConfigPromise } from './config'; 7 | export { __innerState } from './innerState'; 8 | -------------------------------------------------------------------------------- /packages/cli/src/innerState.ts: -------------------------------------------------------------------------------- 1 | export const __innerState = { 2 | isCLI: false, 3 | }; 4 | -------------------------------------------------------------------------------- /packages/cli/src/introspection.ts: -------------------------------------------------------------------------------- 1 | import { fetch } from 'cross-fetch'; 2 | import { print } from 'graphql'; 3 | 4 | import { introspectSchema, wrapSchema } from '@graphql-tools/wrap'; 5 | 6 | import { gqlessConfigPromise, defaultConfig } from './config'; 7 | 8 | import type { AsyncExecutor } from '@graphql-tools/delegate'; 9 | export interface IntrospectionOptions { 10 | /** 11 | * Endpoint of the remote GraphQL API or schema file 12 | */ 13 | endpoint?: string; 14 | /** 15 | * Specify headers for the introspection 16 | */ 17 | headers?: Record; 18 | } 19 | 20 | export const getRemoteSchema = async ( 21 | /** 22 | * Endpoint of the remote GraphQL API 23 | */ 24 | endpoint: string, 25 | /** 26 | * Specify options for the introspection 27 | */ 28 | { headers }: Pick = {} 29 | ) => { 30 | const executor: AsyncExecutor = async ({ document, variables }) => { 31 | headers ||= 32 | (await gqlessConfigPromise).config.introspection?.headers || 33 | defaultConfig.introspection.headers; 34 | const query = print(document); 35 | const fetchResult = await fetch(endpoint, { 36 | method: 'POST', 37 | headers: { 38 | 'Content-Type': 'application/json', 39 | ...headers, 40 | }, 41 | body: JSON.stringify({ query, variables }), 42 | }); 43 | return fetchResult.json(); 44 | }; 45 | 46 | const schema = wrapSchema({ 47 | schema: await introspectSchema(executor, { 48 | endpoint, 49 | }), 50 | executor, 51 | }); 52 | 53 | return schema; 54 | }; 55 | -------------------------------------------------------------------------------- /packages/cli/src/prettier.ts: -------------------------------------------------------------------------------- 1 | import { 2 | format as prettierFormat, 3 | Options as PrettierOptions, 4 | resolveConfig, 5 | } from 'prettier'; 6 | 7 | const commonConfig = resolveConfig(process.cwd()); 8 | 9 | export function formatPrettier( 10 | defaultOptions: Omit & 11 | Required> 12 | ) { 13 | const configPromise = commonConfig.then((config) => 14 | Object.assign({}, config, defaultOptions) 15 | ); 16 | 17 | return { 18 | async format(input: string) { 19 | return prettierFormat(input, await configPromise); 20 | }, 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /packages/cli/test/introspection.test.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLObjectType, GraphQLSchema } from 'graphql'; 2 | import { assertIsDefined, createTestApp } from 'test-utils'; 3 | 4 | import { getRemoteSchema } from '../src'; 5 | 6 | const { server, isReady } = createTestApp({ 7 | schema: ` 8 | type Query { 9 | hello: String! 10 | } 11 | `, 12 | resolvers: { 13 | Query: { 14 | hello() { 15 | return 'hello world'; 16 | }, 17 | }, 18 | }, 19 | }); 20 | 21 | let endpoint: string; 22 | beforeAll(async () => { 23 | await isReady; 24 | 25 | endpoint = (await server.listen(0)) + '/graphql'; 26 | }); 27 | 28 | afterAll(async () => { 29 | server.close(); 30 | }); 31 | 32 | test('introspection works', async () => { 33 | const schema = await getRemoteSchema(endpoint); 34 | 35 | expect(schema).toBeInstanceOf(GraphQLSchema); 36 | 37 | const queryType = schema.getQueryType(); 38 | 39 | expect(queryType).toBeInstanceOf(GraphQLObjectType); 40 | 41 | assertIsDefined(queryType); 42 | 43 | const fieldsMap = queryType.getFields(); 44 | 45 | const hello = fieldsMap['hello']; 46 | 47 | assertIsDefined(hello); 48 | }); 49 | -------------------------------------------------------------------------------- /packages/cli/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "../" 5 | }, 6 | "include": ["**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/cli/test/utils.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { resolve } from 'path'; 3 | import tmp from 'tmp-promise'; 4 | 5 | export async function getTempDir({ 6 | initClientFile, 7 | initSchemaFile, 8 | clientFileName = './client.ts', 9 | }: { 10 | initClientFile?: string; 11 | initSchemaFile?: string; 12 | clientFileName?: string; 13 | } = {}) { 14 | const tempDir = await tmp.dir({ 15 | unsafeCleanup: true, 16 | }); 17 | 18 | const clientPath = resolve(tempDir.path, clientFileName); 19 | 20 | const schemaPath = resolve(tempDir.path, './schema.generated.ts'); 21 | 22 | if (initSchemaFile != null) 23 | await fs.promises.writeFile(schemaPath, initSchemaFile); 24 | 25 | if (initClientFile != null) 26 | await fs.promises.writeFile(clientPath, initClientFile); 27 | 28 | return Object.assign(tempDir, { 29 | clientPath, 30 | schemaPath, 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "module": "esnext", 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | // output .d.ts declaration files for consumers 9 | "declaration": true, 10 | // output .js.map sourcemap files for consumers 11 | "sourceMap": true, 12 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 13 | "rootDir": "./src", 14 | // stricter type-checking for stronger correctness. Recommended by TS 15 | "strict": true, 16 | // linter checks for common issues 17 | "isolatedModules": true, 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | // use Node's module resolution algorithm, instead of the legacy TS one 24 | "moduleResolution": "node", 25 | // transpile JSX to React.createElement 26 | "jsx": "react", 27 | // interop between ESM and CJS modules. Recommended by TS 28 | "esModuleInterop": true, 29 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 30 | "skipLibCheck": true, 31 | // error out if import and file system have a casing mismatch. Recommended by TS 32 | "forceConsistentCasingInFileNames": true, 33 | "noEmit": true, 34 | "allowJs": true, 35 | "checkJs": true, 36 | "preserveWatchOutput": true 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/gqless/.browserslistrc: -------------------------------------------------------------------------------- 1 | node 10 -------------------------------------------------------------------------------- /packages/gqless/README.md: -------------------------------------------------------------------------------- 1 | # [GQless](https://gqless.com/getting-started) [![Documentation](https://img.shields.io/badge/documentation-documentation?color=C00B84)](https://gqless.com) [![Twitter](https://img.shields.io/twitter/follow/gqlessdev?label=%40gqlessdev&style=flat&logo=twitter&color=00acee)](https://twitter.com/gqlessdev) 2 | 3 | > GQless is a fully-featured GraphQL client, which lowers the barrier of entry towards using GraphQL. 4 | 5 | Data requirements within your application are picked up automatically, freeing you from having to maintain GraphQL queries by-hand. It offers a first-class TypeScript experience. See API documentation at all times within autocomplete. 6 | 7 | Make breaking changes to your API, and see type-errors exactly where things are breaking, in realtime. No more running a separate validation step. 8 | 9 | **More documentation is available at [gqless.com/getting-started](https://gqless.com/getting-started).** 10 | 11 | 12 | Example usage 13 | 14 | -------------------------------------------------------------------------------- /packages/gqless/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('test-utils/jest.config.js').default; 2 | -------------------------------------------------------------------------------- /packages/gqless/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/nodemon", 3 | "watch": ["src", "./package.json"], 4 | "ext": "ts", 5 | "exec": "pnpm dev:nodemon", 6 | "legacyWatch": true 7 | } 8 | -------------------------------------------------------------------------------- /packages/gqless/src/Cache/index.ts: -------------------------------------------------------------------------------- 1 | export * from './accessorCache'; 2 | export * from './dataCache'; 3 | -------------------------------------------------------------------------------- /packages/gqless/src/Client/index.ts: -------------------------------------------------------------------------------- 1 | export * from './client'; 2 | export type { ResolveOptions, InlineResolveOptions } from './resolvers'; 3 | -------------------------------------------------------------------------------- /packages/gqless/src/Helpers/casters.ts: -------------------------------------------------------------------------------- 1 | export type NotUndefined = T extends undefined ? never : T; 2 | 3 | /** 4 | * Remove all possible 'undefined' values recursively from an object 5 | */ 6 | export type NotSkeletonDeep = T extends Array 7 | ? Array>> 8 | : T extends (...args: any[]) => any 9 | ? (...args: Parameters) => NotSkeletonDeep>> 10 | : T extends object 11 | ? { 12 | [P in keyof T]: NotUndefined>; 13 | } 14 | : NotUndefined; 15 | 16 | /** 17 | * Remove all possible 'undefined' types in the first level. 18 | */ 19 | export type NotSkeleton = T extends Array 20 | ? Array> 21 | : T extends (...args: any[]) => any 22 | ? (...args: Parameters) => NotUndefined> 23 | : T extends object 24 | ? { 25 | [P in keyof T]: NotUndefined; 26 | } 27 | : NotUndefined; 28 | 29 | const noop = (v: any) => v; 30 | 31 | /** 32 | * Runtime no-op that removes all the undefined types recursively 33 | */ 34 | export const castNotSkeletonDeep: (v: T) => NotSkeletonDeep = noop; 35 | 36 | /** 37 | * Runtime no-op that removes all the undefined types in the first level 38 | */ 39 | export const castNotSkeleton: (v: T) => NotSkeleton = noop; 40 | -------------------------------------------------------------------------------- /packages/gqless/src/Helpers/getFields.ts: -------------------------------------------------------------------------------- 1 | import { isObject, isPlainObject } from '../Utils'; 2 | 3 | export function getFields< 4 | TAccesorData extends object | undefined | null, 5 | TAccesorKeys extends keyof NonNullable 6 | >(accessor: TAccesorData, ...keys: TAccesorKeys[]): TAccesorData { 7 | if (!isObject(accessor)) return accessor; 8 | 9 | if (keys.length) for (const key of keys) Reflect.get(accessor, key); 10 | else for (const key in accessor) Reflect.get(accessor, key); 11 | 12 | return accessor; 13 | } 14 | 15 | export function getArrayFields< 16 | TArrayValue extends object | null | undefined, 17 | TArray extends TArrayValue[] | null | undefined, 18 | TArrayValueKeys extends keyof NonNullable[number]> 19 | >(accessorArray: TArray, ...keys: TArrayValueKeys[]): TArray { 20 | if (accessorArray == null) return accessorArray; 21 | 22 | if (Array.isArray(accessorArray)) { 23 | for (const value of accessorArray) { 24 | if (isPlainObject(value)) { 25 | getFields(value, ...keys); 26 | break; 27 | } 28 | } 29 | } 30 | return accessorArray; 31 | } 32 | -------------------------------------------------------------------------------- /packages/gqless/src/Helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './selectFields'; 2 | export type { HydrateCacheOptions } from './ssr'; 3 | export * from './getFields'; 4 | export * from './casters'; 5 | export * from './prepass'; 6 | -------------------------------------------------------------------------------- /packages/gqless/src/Helpers/prefetch.ts: -------------------------------------------------------------------------------- 1 | import { InnerClientState } from '../Client/client'; 2 | import { SchedulerPromiseValue } from '../Scheduler'; 3 | 4 | export interface Prefetch< 5 | GeneratedSchema extends { 6 | query: object; 7 | } 8 | > { 9 | (fn: (query: GeneratedSchema['query']) => TData): 10 | | TData 11 | | (Promise & { schedulerPromise: Promise }); 12 | } 13 | 14 | export function createPrefetch< 15 | GeneratedSchema extends { 16 | query: object; 17 | } 18 | >( 19 | query: GeneratedSchema['query'], 20 | { scheduler }: InnerClientState 21 | ): Prefetch { 22 | return function prefetch( 23 | fn: (query: GeneratedSchema['query']) => TData 24 | ): 25 | | (Promise & { 26 | schedulerPromise: Promise; 27 | }) 28 | | TData { 29 | const existingData = fn(query); 30 | 31 | if (scheduler.resolving) { 32 | return Object.assign( 33 | scheduler.resolving.promise.then(() => prefetch(fn)), 34 | { 35 | schedulerPromise: scheduler.resolving.promise, 36 | } 37 | ); 38 | } 39 | return existingData; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /packages/gqless/src/Helpers/prepass.ts: -------------------------------------------------------------------------------- 1 | import { isObject } from '../Utils'; 2 | 3 | function getFirstNonNullValue(list: T[]): T | void { 4 | for (const value of list) if (value != null) return value; 5 | } 6 | 7 | export interface PrepassObjKey { 8 | field: string; 9 | variables?: Record; 10 | } 11 | 12 | export function prepass( 13 | v: T, 14 | ...keys: Array> 15 | ): T { 16 | if (v == null) return v; 17 | 18 | for (const composedKeys of keys) { 19 | const separatedKeys = 20 | typeof composedKeys === 'string' ? composedKeys.split('.') : composedKeys; 21 | 22 | let obj: unknown = v; 23 | for (const key of separatedKeys) { 24 | if (obj && key) { 25 | let property = typeof key === 'object' ? key.field : key; 26 | let variables = typeof key === 'object' ? key.variables : undefined; 27 | 28 | if (Array.isArray(obj)) { 29 | const firstNonNull = getFirstNonNullValue(obj); 30 | if (firstNonNull) { 31 | obj = firstNonNull; 32 | } else break; 33 | } 34 | 35 | if (isObject(obj)) { 36 | if (property in obj) { 37 | const value: unknown = 38 | //@ts-expect-error 39 | obj[property]; 40 | 41 | if (typeof value === 'function') { 42 | obj = value(variables); 43 | } else { 44 | obj = value; 45 | } 46 | } else break; 47 | } else break; 48 | } else break; 49 | } 50 | } 51 | 52 | return v; 53 | } 54 | -------------------------------------------------------------------------------- /packages/gqless/src/Helpers/refetch.ts: -------------------------------------------------------------------------------- 1 | import { InnerClientState } from '../Client/client'; 2 | import { InlineResolveOptions, Resolvers } from '../Client/resolvers'; 3 | 4 | export function isFunction(v: T | (() => T)): v is () => T { 5 | return typeof v === 'function'; 6 | } 7 | 8 | export interface Refetch { 9 | (refetchArg: T | (() => T)): Promise; 10 | } 11 | 12 | export function createRefetch( 13 | innerState: InnerClientState, 14 | resolveSelections: Resolvers['resolveSelections'], 15 | inlineResolved: Resolvers['inlineResolved'] 16 | ): Refetch { 17 | const { accessorCache } = innerState; 18 | 19 | const inlineResolveRefetch: InlineResolveOptions = { 20 | refetch: true, 21 | }; 22 | 23 | async function refetch(refetchArg: T | (() => T)) { 24 | if (isFunction(refetchArg)) 25 | return inlineResolved(refetchArg, inlineResolveRefetch); 26 | 27 | if (accessorCache.isProxy(refetchArg)) { 28 | const selectionSet = accessorCache.getSelectionSetHistory(refetchArg); 29 | 30 | if (selectionSet) { 31 | await resolveSelections(selectionSet, undefined, { 32 | ignoreResolveCache: true, 33 | }); 34 | } 35 | return refetchArg; 36 | } 37 | 38 | if (process.env.NODE_ENV !== 'production') { 39 | console.warn('gqless: Invalid proxy to refetch!', refetchArg); 40 | } 41 | return refetchArg; 42 | } 43 | 44 | return refetch; 45 | } 46 | -------------------------------------------------------------------------------- /packages/gqless/src/QueryBuilder/index.ts: -------------------------------------------------------------------------------- 1 | export * from './buildQuery'; 2 | -------------------------------------------------------------------------------- /packages/gqless/src/Schema/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types'; 2 | -------------------------------------------------------------------------------- /packages/gqless/src/Selection/index.ts: -------------------------------------------------------------------------------- 1 | export * from './selection'; 2 | export type { SelectionManager } from './SelectionManager'; 3 | export type { 4 | BuildSelectionInput, 5 | BuildSelectionValue, 6 | } from './SelectionBuilder'; 7 | -------------------------------------------------------------------------------- /packages/gqless/src/Utils/cachedJSON.ts: -------------------------------------------------------------------------------- 1 | const serializedVariablesCache = new WeakMap(); 2 | 3 | export function serializeVariables(variables: Record): string { 4 | let serializedVariables: string; 5 | if ((serializedVariables = serializedVariablesCache.get(variables)!)) { 6 | return serializedVariables; 7 | } 8 | serializedVariables = JSON.stringify(variables); 9 | serializedVariablesCache.set(variables, serializedVariables); 10 | return serializedVariables; 11 | } 12 | -------------------------------------------------------------------------------- /packages/gqless/src/Utils/debounce.ts: -------------------------------------------------------------------------------- 1 | export function debounce( 2 | fn: (...args: T) => void, 3 | delay: number 4 | ) { 5 | let timeout: any; 6 | 7 | return function debounced(...args: Parameters) { 8 | const execFetch = () => { 9 | timeout = undefined; 10 | fn(...args); 11 | }; 12 | if (timeout !== undefined) clearTimeout(timeout); 13 | 14 | if (delay < 0) { 15 | execFetch(); 16 | timeout = undefined; 17 | } else { 18 | timeout = setTimeout(execFetch, delay); 19 | } 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /packages/gqless/src/Utils/index.ts: -------------------------------------------------------------------------------- 1 | export interface DeferredPromise { 2 | promise: Promise; 3 | resolve: (value: T) => void; 4 | reject: (reason: unknown) => void; 5 | } 6 | 7 | export function createDeferredPromise(): DeferredPromise { 8 | let resolve: (value: T) => void = undefined as any; 9 | let reject: (reason: unknown) => void = undefined as any; 10 | const promise = new Promise((resolveFn: any, rejectFn) => { 11 | resolve = resolveFn; 12 | reject = rejectFn; 13 | }); 14 | 15 | return { 16 | promise, 17 | resolve, 18 | reject, 19 | }; 20 | } 21 | 22 | export const isInteger = (v: any): v is number => Number.isInteger(v); 23 | 24 | export function isEmptyObject(obj: object) { 25 | for (var _i in obj) return false; 26 | return true; 27 | } 28 | 29 | export * from './debounce'; 30 | export * from './object'; 31 | export * from './cycle'; 32 | export { default as mergeWith } from 'lodash/mergeWith'; 33 | -------------------------------------------------------------------------------- /packages/gqless/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Client'; 2 | export * from './Selection'; 3 | export * from './Schema'; 4 | export * from './Error'; 5 | export * from './Helpers'; 6 | export { debounce } from './Utils/debounce'; 7 | -------------------------------------------------------------------------------- /packages/gqless/test/error.test.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLError } from 'graphql'; 2 | 3 | import { GQlessError } from '../src/Error'; 4 | 5 | test('error creation', () => { 6 | const a = new GQlessError('a'); 7 | 8 | const b = GQlessError.create(Error('a')); 9 | 10 | const c = GQlessError.create(a); 11 | 12 | const d = GQlessError.create(123); 13 | 14 | const e = new GQlessError('abc', { 15 | graphQLErrors: [new GraphQLError('gql error')], 16 | }); 17 | 18 | expect(a).toStrictEqual(b); 19 | 20 | expect(a).toBe(c); 21 | 22 | expect(d.message).toBe('Unexpected error type'); 23 | expect(d.otherError).toBe(123); 24 | 25 | expect(JSON.stringify(e)).toBe( 26 | `{"message":"abc","graphQLErrors":[{"message":"gql error"}]}` 27 | ); 28 | 29 | expect(e).toEqual( 30 | Object.assign(Error('abc'), { 31 | graphqlErrors: [new GraphQLError('gql error')], 32 | }) 33 | ); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/gqless/test/schema.test.ts: -------------------------------------------------------------------------------- 1 | import { parseSchemaType, ParseSchemaTypeInfo } from '../src/Schema'; 2 | 3 | describe('parseSchemaType', () => { 4 | test('nullable type', () => { 5 | const info = parseSchemaType('String'); 6 | 7 | expect(info).toEqual({ 8 | pureType: 'String', 9 | isNullable: true, 10 | nullableItems: true, 11 | isArray: false, 12 | }); 13 | }); 14 | 15 | test('non-nullable type', () => { 16 | const info = parseSchemaType('String!'); 17 | 18 | expect(info).toEqual({ 19 | pureType: 'String', 20 | isNullable: false, 21 | nullableItems: true, 22 | isArray: false, 23 | }); 24 | }); 25 | test('nullable array with nullable items', () => { 26 | const info = parseSchemaType('[String]'); 27 | 28 | expect(info).toEqual({ 29 | pureType: 'String', 30 | isNullable: true, 31 | nullableItems: true, 32 | isArray: true, 33 | }); 34 | }); 35 | 36 | test('nullable array with non-nullable items', () => { 37 | const info = parseSchemaType('[String!]'); 38 | 39 | expect(info).toEqual({ 40 | pureType: 'String', 41 | isNullable: true, 42 | nullableItems: false, 43 | isArray: true, 44 | }); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /packages/gqless/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "../", 5 | "declaration": false 6 | }, 7 | "include": ["**/*.ts", "**/*.tsx"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/gqless/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "target": "es2018", 6 | "module": "esnext", 7 | "lib": ["esnext", "DOM"], 8 | "importHelpers": true, 9 | // output .d.ts declaration files for consumers 10 | "declaration": true, 11 | // output .js.map sourcemap files for consumers 12 | "sourceMap": true, 13 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 14 | "rootDir": "./src", 15 | // stricter type-checking for stronger correctness. Recommended by TS 16 | "strict": true, 17 | "strictNullChecks": true, 18 | "isolatedModules": true, 19 | // linter checks for common issues 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 23 | "noUnusedLocals": true, 24 | "noUnusedParameters": true, 25 | // use Node's module resolution algorithm, instead of the legacy TS one 26 | "moduleResolution": "node", 27 | // transpile JSX to React.createElement 28 | "jsx": "react", 29 | // interop between ESM and CJS modules. Recommended by TS 30 | "esModuleInterop": true, 31 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 32 | "skipLibCheck": true, 33 | // error out if import and file system have a casing mismatch. Recommended by TS 34 | "forceConsistentCasingInFileNames": true, 35 | // "noEmit": true, 36 | "preserveWatchOutput": true, 37 | "outDir": "./dist", 38 | "incremental": false 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/logger/.browserslistrc: -------------------------------------------------------------------------------- 1 | node 10 -------------------------------------------------------------------------------- /packages/logger/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @gqless/logger 2 | 3 | ## 2.0.11 4 | 5 | ### Patch Changes 6 | 7 | - af6a437: - Rename `gqlessConfig` to `GQlessConfig` (so it's consistent with the new logo) 8 | - Rename `gqlessError` to `GQlessError` 9 | - Remove `endpoint` option from the configuration, and instead always defaults to introspection one 10 | - It's confusing why theres two of them, and the user can change it later by modifying the file anyway 11 | - Updated dependencies [4a3d5ef] 12 | - Updated dependencies [af6a437] 13 | - gqless@2.0.13 14 | 15 | ## 2.0.10 16 | 17 | ### Patch Changes 18 | 19 | - Updated dependencies [65c4d32] 20 | - gqless@2.0.10 21 | 22 | ## 2.0.9 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [6a9269f] 27 | - gqless@2.0.9 28 | 29 | ## 2.0.8 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [c74442e] 34 | - Updated dependencies [d78f2ab] 35 | - Updated dependencies [0ffaa9d] 36 | - gqless@2.0.8 37 | 38 | ## 2.0.7 39 | 40 | ### Patch Changes 41 | 42 | - Updated dependencies [ff66195] 43 | - Updated dependencies [63fd3ea] 44 | - Updated dependencies [40d2101] 45 | - gqless@2.0.7 46 | 47 | ## 2.0.6 48 | 49 | ### Patch Changes 50 | 51 | - 173e11d: add subscriptions to events 52 | - Updated dependencies [173e11d] 53 | - Updated dependencies [c613410] 54 | - gqless@2.0.6 55 | 56 | ## 2.0.5 57 | 58 | ### Patch Changes 59 | 60 | - Updated dependencies [6fef085] 61 | - gqless@2.0.5 62 | 63 | ## 2.0.4 64 | 65 | ### Patch Changes 66 | 67 | - Updated dependencies [2bf4ce2] 68 | - gqless@2.0.4 69 | 70 | ## 2.0.3 71 | 72 | ### Patch Changes 73 | 74 | - Updated dependencies [27f9ece] 75 | - gqless@2.0.3 76 | 77 | ## 2.0.2 78 | 79 | ### Patch Changes 80 | 81 | - Updated dependencies [c06ef80] 82 | - gqless@2.0.2 83 | 84 | ## 2.0.1 85 | 86 | ### Patch Changes 87 | 88 | - a57cab4: official beta v2 publish 89 | - Updated dependencies [a57cab4] 90 | - gqless@2.0.1 91 | -------------------------------------------------------------------------------- /packages/logger/LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright © `2021` `GQless` 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the “Software”), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /packages/logger/README.md: -------------------------------------------------------------------------------- 1 | # @gqless/logger 2 | 3 | ## Visit [https://gqless.com/development/logger](https://gqless.com/development/logger) 4 | -------------------------------------------------------------------------------- /packages/logger/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('test-utils/jest.config.js').default; 2 | -------------------------------------------------------------------------------- /packages/logger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@gqless/logger", 3 | "version": "2.0.11", 4 | "homepage": "https://gqless.com", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/gqless/gqless.git" 9 | }, 10 | "author": "GQless ", 11 | "main": "dist/index.js", 12 | "module": "dist/gqless-logger.esm.js", 13 | "typings": "dist/index.d.ts", 14 | "files": [ 15 | "dist", 16 | "src" 17 | ], 18 | "scripts": { 19 | "analyze": "size-limit --why", 20 | "build": "build gqless-logger", 21 | "prepare": "build gqless-logger", 22 | "postpublish": "gh-release", 23 | "size": "size-limit", 24 | "start": "watch gqless-logger", 25 | "test": "jest", 26 | "test:watch": "jest --watch" 27 | }, 28 | "dependencies": { 29 | "prettier": "^2.2.1", 30 | "serialize-error": "^8.1.0" 31 | }, 32 | "devDependencies": { 33 | "@size-limit/preset-small-lib": "^4.10.2", 34 | "@types/prettier": "^2.2.3", 35 | "build-utils": "workspace:*", 36 | "gqless": "workspace:^2.0.13", 37 | "jest": "^26.6.3", 38 | "rimraf": "^3.0.2", 39 | "size-limit": "^4.10.2", 40 | "test-utils": "workspace:^0.1.0", 41 | "tslib": "^2.2.0", 42 | "typescript": "^4.2.4" 43 | }, 44 | "peerDependencies": { 45 | "gqless": "workspace:^2.0.13" 46 | }, 47 | "engines": { 48 | "node": ">=10" 49 | }, 50 | "size-limit": [ 51 | { 52 | "path": "dist/gqless-logger.cjs.production.min.js", 53 | "limit": "260 KB" 54 | }, 55 | { 56 | "path": "dist/gqless-logger.esm.js", 57 | "limit": "260 KB" 58 | } 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /packages/logger/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "module": "esnext", 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | // output .d.ts declaration files for consumers 9 | "declaration": true, 10 | // output .js.map sourcemap files for consumers 11 | "sourceMap": true, 12 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 13 | "rootDir": "./src", 14 | // stricter type-checking for stronger correctness. Recommended by TS 15 | "strict": true, 16 | // linter checks for common issues 17 | "noImplicitReturns": true, 18 | "noFallthroughCasesInSwitch": true, 19 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | // use Node's module resolution algorithm, instead of the legacy TS one 23 | "moduleResolution": "node", 24 | // transpile JSX to React.createElement 25 | "jsx": "react", 26 | // interop between ESM and CJS modules. Recommended by TS 27 | "esModuleInterop": true, 28 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 29 | "skipLibCheck": true, 30 | // error out if import and file system have a casing mismatch. Recommended by TS 31 | "forceConsistentCasingInFileNames": true, 32 | "noEmit": true, 33 | "isolatedModules": true, 34 | "preserveWatchOutput": true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/react/.browserslistrc: -------------------------------------------------------------------------------- 1 | node 10 -------------------------------------------------------------------------------- /packages/react/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | dist 6 | -------------------------------------------------------------------------------- /packages/react/LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright © `2021` `GQless` 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the “Software”), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /packages/react/README.md: -------------------------------------------------------------------------------- 1 | # @gqless/react 2 | 3 | ## Visit [https://gqless.com/react/fetching-data](https://gqless.com/react/fetching-data) 4 | -------------------------------------------------------------------------------- /packages/react/jest.config.js: -------------------------------------------------------------------------------- 1 | const { getConfig } = require('test-utils/jest.config.js'); 2 | 3 | module.exports = getConfig({ 4 | setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'], 5 | testEnvironment: 'jsdom', 6 | }); 7 | -------------------------------------------------------------------------------- /packages/react/src/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './client'; 2 | 3 | export type { 4 | UseQuery, 5 | UseQueryOptions, 6 | UseQueryState, 7 | UseQueryReturnValue, 8 | } from './query/useQuery'; 9 | export type { GraphQLHOC, GraphQLHOCOptions } from './query/hoc'; 10 | export type { 11 | UseTransactionQuery, 12 | UseTransactionQueryOptions, 13 | UseTransactionQueryState, 14 | } from './query/useTransactionQuery'; 15 | export type { 16 | LazyFetchPolicy, 17 | UseLazyQuery, 18 | UseLazyQueryOptions, 19 | UseLazyQueryState, 20 | } from './query/useLazyQuery'; 21 | export type { 22 | UseRefetch, 23 | UseRefetchOptions, 24 | UseRefetchState, 25 | } from './query/useRefetch'; 26 | export type { 27 | PrepareQuery, 28 | PreparedQuery, 29 | UsePreparedQueryOptions, 30 | } from './query/preparedQuery'; 31 | export type { 32 | UseMetaState, 33 | MetaState, 34 | UseMetaStateOptions, 35 | } from './meta/useMetaState'; 36 | export type { 37 | UseMutation, 38 | UseMutationOptions, 39 | UseMutationState, 40 | } from './mutation/useMutation'; 41 | export type { UseSubscription } from './subscription/useSubscription'; 42 | export type { 43 | PaginatedQueryFetchPolicy, 44 | UsePaginatedQuery, 45 | FetchMoreCallbackArgs, 46 | UsePaginatedQueryData, 47 | UsePaginatedQueryMergeParams, 48 | UsePaginatedQueryOptions, 49 | } from './query/usePaginatedQuery'; 50 | export type { 51 | UseHydrateCache, 52 | PrepareReactRender, 53 | PropsWithServerCache, 54 | UseHydrateCacheOptions, 55 | } from './ssr/ssr'; 56 | 57 | export type { OnErrorHandler, FetchPolicy, CoreHelpers } from './common'; 58 | export { coreHelpers, uniqBy, sortBy } from './common'; 59 | -------------------------------------------------------------------------------- /packages/react/src/utils.ts: -------------------------------------------------------------------------------- 1 | import type { CreateReactClientOptions, ReactClientDefaults } from './client'; 2 | 3 | export function areArraysEqual( 4 | a: unknown[] | null | undefined, 5 | b: unknown[] | null | undefined 6 | ) { 7 | if (a === b) return true; 8 | if (a == null || b == null) return false; 9 | const size = a.length; 10 | if (size !== b.length) return false; 11 | 12 | for (let i = 0; i < size; ++i) if (a[i] !== b[i]) return false; 13 | 14 | return true; 15 | } 16 | 17 | export type ReactClientOptionsWithDefaults = Omit< 18 | CreateReactClientOptions, 19 | 'defaults' 20 | > & { 21 | defaults: Required; 22 | }; 23 | -------------------------------------------------------------------------------- /packages/react/test/graphqlHOC.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { render, waitFor } from '@testing-library/react'; 4 | 5 | import { createReactTestClient } from './utils'; 6 | 7 | test('Basic Non-Suspense', async () => { 8 | const { query, graphql } = await createReactTestClient(); 9 | 10 | const Comp = graphql( 11 | () => { 12 | return

{query.hello}

; 13 | }, 14 | { 15 | suspense: false, 16 | } 17 | ); 18 | 19 | const { container } = render(); 20 | 21 | expect(container).not.toBeEmptyDOMElement(); 22 | 23 | expect(container).toHaveTextContent(''); 24 | 25 | await waitFor(() => { 26 | expect(container).toHaveTextContent('hello world'); 27 | }); 28 | }); 29 | 30 | test('Basic Suspense', async () => { 31 | const { query, graphql } = await createReactTestClient(); 32 | 33 | const Comp = graphql( 34 | () => { 35 | return

{query.hello}

; 36 | }, 37 | { 38 | suspense: { 39 | fallback: 'Loading...', 40 | }, 41 | } 42 | ); 43 | 44 | const { container } = render(); 45 | 46 | expect(container).toHaveTextContent('Loading...'); 47 | 48 | await waitFor(() => { 49 | expect(container).toHaveTextContent('hello world'); 50 | }); 51 | 52 | expect(container).not.toHaveTextContent('Loading...'); 53 | }); 54 | -------------------------------------------------------------------------------- /packages/react/test/useQuery.test.tsx: -------------------------------------------------------------------------------- 1 | import { renderHook } from '@testing-library/react-hooks'; 2 | 3 | import { createReactTestClient } from './utils'; 4 | 5 | test('Basic Non-Suspense', async () => { 6 | const { useQuery } = await createReactTestClient(); 7 | 8 | const { result, waitFor } = renderHook(() => { 9 | const query = useQuery({ 10 | suspense: false, 11 | }); 12 | 13 | return { 14 | hello: query.hello, 15 | $state: query.$state, 16 | }; 17 | }); 18 | 19 | expect(result.current.hello).toBe(undefined); 20 | 21 | await waitFor(() => result.current.$state.isLoading === true); 22 | 23 | expect(result.current.hello).toBe(undefined); 24 | 25 | await waitFor(() => result.current.$state.isLoading === false); 26 | 27 | expect(result.current.hello).toBe('hello world'); 28 | }); 29 | 30 | test('Basic Suspense', async () => { 31 | const { useQuery } = await createReactTestClient(); 32 | 33 | const { result, waitForNextUpdate } = renderHook(() => { 34 | const query = useQuery({ 35 | suspense: true, 36 | }); 37 | 38 | return query.hello; 39 | }); 40 | 41 | expect(result.current).toBe(undefined); 42 | 43 | await waitForNextUpdate(); 44 | 45 | expect(result.current).toBe('hello world'); 46 | }); 47 | -------------------------------------------------------------------------------- /packages/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "target": "es2018", 6 | "module": "esnext", 7 | "lib": ["dom", "esnext"], 8 | "importHelpers": true, 9 | // output .d.ts declaration files for consumers 10 | "declaration": true, 11 | // output .js.map sourcemap files for consumers 12 | "sourceMap": true, 13 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 14 | "rootDir": "./src", 15 | // stricter type-checking for stronger correctness. Recommended by TS 16 | "strict": true, 17 | // linter checks for common issues 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 21 | "isolatedModules": true, 22 | "noUnusedLocals": true, 23 | "noUnusedParameters": true, 24 | // use Node's module resolution algorithm, instead of the legacy TS one 25 | "moduleResolution": "node", 26 | // transpile JSX to React.createElement 27 | "jsx": "react", 28 | // interop between ESM and CJS modules. Recommended by TS 29 | "esModuleInterop": true, 30 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 31 | "skipLibCheck": true, 32 | // error out if import and file system have a casing mismatch. Recommended by TS 33 | "forceConsistentCasingInFileNames": true, 34 | // "noEmit": true, 35 | "preserveWatchOutput": true, 36 | "outDir": "./dist", 37 | "incremental": true, 38 | "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/subscriptions/.browserslistrc: -------------------------------------------------------------------------------- 1 | node 10 -------------------------------------------------------------------------------- /packages/subscriptions/LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright © `2021` `GQless` 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the “Software”), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /packages/subscriptions/README.md: -------------------------------------------------------------------------------- 1 | # @gqless/subscription 2 | 3 | ## Visit [https://gqless.com/core/subscriptions](https://gqless.com/core/subscriptions) 4 | -------------------------------------------------------------------------------- /packages/subscriptions/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('test-utils/jest.config.js').default; 2 | -------------------------------------------------------------------------------- /packages/subscriptions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@gqless/subscriptions", 3 | "version": "1.0.11", 4 | "homepage": "https://gqless.com", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/gqless/gqless.git" 8 | }, 9 | "author": "GQless ", 10 | "main": "dist/index.js", 11 | "module": "dist/gqless-subscriptions.esm.js", 12 | "types": "dist/index.d.ts", 13 | "files": [ 14 | "dist", 15 | "src" 16 | ], 17 | "scripts": { 18 | "build": "build gqless-subscriptions", 19 | "prepare": "build gqless-subscriptions", 20 | "postpublish": "gh-release", 21 | "start": "watch gqless-buscriptions", 22 | "test": "jest" 23 | }, 24 | "dependencies": { 25 | "isomorphic-ws": "^4.0.1", 26 | "ws": "^7.4.5" 27 | }, 28 | "devDependencies": { 29 | "@types/ws": "^7.4.1", 30 | "build-utils": "workspace:*", 31 | "gqless": "workspace:^2.0.13", 32 | "graphql": "^15.5.0", 33 | "test-utils": "workspace:^0.1.0", 34 | "tslib": "^2.2.0", 35 | "typescript": "^4.2.4" 36 | }, 37 | "peerDependencies": { 38 | "gqless": "workspace:^2.0.13", 39 | "graphql": "^15.5.0" 40 | }, 41 | "peerDependenciesMeta": { 42 | "graphql": { 43 | "optional": true 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/subscriptions/src/subscription/protocol.ts: -------------------------------------------------------------------------------- 1 | export const GQL_CONNECTION_INIT = 'connection_init'; // Client -> Server 2 | export const GQL_CONNECTION_ACK = 'connection_ack'; // Server -> Client 3 | export const GQL_CONNECTION_ERROR = 'connection_error'; // Server -> Client 4 | export const GQL_CONNECTION_KEEP_ALIVE = 'ka'; // Server -> Client 5 | 6 | export const GQL_CONNECTION_TERMINATE = 'connection_terminate'; // Client -> Server 7 | export const GQL_START = 'start'; // Client -> Server 8 | export const GQL_DATA = 'data'; // Server -> Client 9 | export const GQL_ERROR = 'error'; // Server -> Client 10 | export const GQL_COMPLETE = 'complete'; // Server -> Client 11 | export const GQL_STOP = 'stop'; // Client -> Server 12 | 13 | export const GRAPHQL_WS = 'graphql-ws'; 14 | -------------------------------------------------------------------------------- /packages/subscriptions/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLError } from 'graphql'; 2 | 3 | export interface DeferredPromise { 4 | promise: Promise; 5 | resolve: (value: T) => void; 6 | reject: (reason: unknown) => void; 7 | } 8 | 9 | export function createDeferredPromise(): DeferredPromise { 10 | let resolve: (value: T) => void = undefined as any; 11 | let reject: (reason: unknown) => void = undefined as any; 12 | const promise = new Promise((resolveFn: any, rejectFn) => { 13 | resolve = resolveFn; 14 | reject = rejectFn; 15 | }); 16 | 17 | return { 18 | promise, 19 | resolve, 20 | reject, 21 | }; 22 | } 23 | 24 | export type GQLResponse< 25 | T extends Record = Record 26 | > = { data: T | null; errors?: GraphQLError[] }; 27 | -------------------------------------------------------------------------------- /packages/subscriptions/test/index.test.ts: -------------------------------------------------------------------------------- 1 | test('works', () => { 2 | expect(1).toBe(1); 3 | }); 4 | 5 | export {}; 6 | -------------------------------------------------------------------------------- /packages/subscriptions/tsconfig.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/subscriptions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "target": "es2018", 6 | "module": "esnext", 7 | "lib": ["dom", "esnext"], 8 | "importHelpers": true, 9 | // output .d.ts declaration files for consumers 10 | "declaration": true, 11 | // output .js.map sourcemap files for consumers 12 | "sourceMap": true, 13 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 14 | "rootDir": "./src", 15 | "outDir": "dist", 16 | // stricter type-checking for stronger correctness. Recommended by TS 17 | "strict": true, 18 | // linter checks for common issues 19 | "noImplicitReturns": true, 20 | "noFallthroughCasesInSwitch": true, 21 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 22 | "noUnusedLocals": true, 23 | "noUnusedParameters": true, 24 | // use Node's module resolution algorithm, instead of the legacy TS one 25 | "moduleResolution": "node", 26 | // transpile JSX to React.createElement 27 | "jsx": "react", 28 | // interop between ESM and CJS modules. Recommended by TS 29 | "esModuleInterop": true, 30 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 31 | "skipLibCheck": true, 32 | // error out if import and file system have a casing mismatch. Recommended by TS 33 | "forceConsistentCasingInFileNames": true, 34 | // "noEmit": true, 35 | "isolatedModules": true, 36 | "preserveWatchOutput": true, 37 | "incremental": true, 38 | "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | - 'examples/*' 4 | - 'internal/*' 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "CommonJS", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "noEmit": true, 8 | "checkJs": true, 9 | "allowJs": true 10 | } 11 | } 12 | --------------------------------------------------------------------------------