├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── nightly.yml
│ ├── pr-title.yml
│ ├── release-notes.yml
│ ├── test-e2e-composable.yml
│ ├── test-e2e-options.yml
│ ├── test-e2e-ssr.yml
│ └── test.yml
├── .gitignore
├── .test-todo
├── test-ssr-composition
│ ├── .browserslistrc
│ ├── .editorconfig
│ ├── .gitignore
│ ├── README.md
│ ├── apollo-server
│ │ ├── context.js
│ │ ├── data-sources.js
│ │ ├── directives.js
│ │ ├── mocks.js
│ │ ├── resolvers.js
│ │ ├── schema.graphql
│ │ ├── server.js
│ │ ├── type-defs.js
│ │ └── utils
│ │ │ ├── db.js
│ │ │ └── upload.js
│ ├── apollo.config.js
│ ├── babel.config.js
│ ├── cypress.json
│ ├── package.json
│ ├── postcss.config.js
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── index.ssr.html
│ ├── src
│ │ ├── App.vue
│ │ ├── assets
│ │ │ └── logo.png
│ │ ├── components
│ │ │ ├── ApolloExample.vue
│ │ │ ├── ApolloLoading.vue
│ │ │ └── HelloWorld.vue
│ │ ├── entry-client.js
│ │ ├── entry-server.js
│ │ ├── graphql
│ │ │ ├── AddMessage.gql
│ │ │ ├── FileFragment.gql
│ │ │ ├── Files.gql
│ │ │ ├── HelloWorld.gql
│ │ │ ├── MessageAdded.gql
│ │ │ ├── MessageFragment.gql
│ │ │ ├── Messages.gql
│ │ │ └── UploadFile.gql
│ │ ├── main.js
│ │ ├── router
│ │ │ └── index.js
│ │ ├── views
│ │ │ ├── About.vue
│ │ │ └── Home.vue
│ │ └── vue-apollo.js
│ ├── tests
│ │ └── e2e
│ │ │ ├── .eslintrc.js
│ │ │ ├── plugins
│ │ │ └── index.js
│ │ │ ├── specs
│ │ │ └── apollo-ssr.js
│ │ │ └── support
│ │ │ ├── commands.js
│ │ │ └── index.js
│ └── vue.config.js
└── test-ssr
│ ├── .browserslistrc
│ ├── .editorconfig
│ ├── .gitignore
│ ├── README.md
│ ├── apollo-server
│ ├── context.js
│ ├── data-sources.js
│ ├── directives.js
│ ├── mocks.js
│ ├── resolvers.js
│ ├── schema.graphql
│ ├── server.js
│ ├── type-defs.js
│ └── utils
│ │ ├── db.js
│ │ └── upload.js
│ ├── apollo.config.js
│ ├── babel.config.js
│ ├── cypress.json
│ ├── package.json
│ ├── postcss.config.js
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ └── index.ssr.html
│ ├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ ├── ApolloExample.vue
│ │ ├── ApolloLoading.vue
│ │ └── HelloWorld.vue
│ ├── entry-client.js
│ ├── entry-server.js
│ ├── graphql
│ │ ├── AddMessage.gql
│ │ ├── FileFragment.gql
│ │ ├── Files.gql
│ │ ├── HelloWorld.gql
│ │ ├── MessageAdded.gql
│ │ ├── MessageFragment.gql
│ │ ├── Messages.gql
│ │ └── UploadFile.gql
│ ├── main.js
│ ├── router
│ │ └── index.js
│ ├── views
│ │ ├── About.vue
│ │ └── Home.vue
│ └── vue-apollo.js
│ ├── tests
│ └── e2e
│ │ ├── .eslintrc.js
│ │ ├── plugins
│ │ └── index.js
│ │ ├── specs
│ │ └── apollo-ssr.js
│ │ └── support
│ │ ├── commands.js
│ │ └── index.js
│ └── vue.config.js
├── .vscode
└── settings.json
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── eslint.config.mjs
├── meow.eslintrc.js
├── package.json
├── packages
├── docs
│ ├── package.json
│ └── src
│ │ ├── .vitepress
│ │ ├── config.js
│ │ └── theme
│ │ │ ├── components
│ │ │ └── SponsorButton.vue
│ │ │ ├── index.js
│ │ │ └── styles
│ │ │ └── index.pcss
│ │ ├── api
│ │ ├── apollo-mutation.md
│ │ ├── apollo-provider.md
│ │ ├── apollo-query.md
│ │ ├── apollo-subscribe-to-more.md
│ │ ├── dollar-apollo.md
│ │ ├── index.md
│ │ ├── smart-query.md
│ │ ├── smart-subscription.md
│ │ ├── ssr.md
│ │ ├── use-apollo-client.md
│ │ ├── use-lazy-query.md
│ │ ├── use-loading.md
│ │ ├── use-mutation.md
│ │ ├── use-query.md
│ │ └── use-subscription.md
│ │ ├── guide-advanced
│ │ ├── index.md
│ │ ├── local-state.md
│ │ ├── ssr.md
│ │ └── testing.md
│ │ ├── guide-components
│ │ ├── index.md
│ │ ├── mutation.md
│ │ ├── query.md
│ │ ├── setup.md
│ │ └── subscribe-to-more.md
│ │ ├── guide-composable
│ │ ├── cache-interaction.md
│ │ ├── error-handling.md
│ │ ├── fragments.md
│ │ ├── index.md
│ │ ├── mutation.md
│ │ ├── pagination.md
│ │ ├── query.md
│ │ ├── setup.md
│ │ └── subscription.md
│ │ ├── guide-option
│ │ ├── index.md
│ │ ├── multiple-clients.md
│ │ ├── mutations.md
│ │ ├── pagination.md
│ │ ├── queries.md
│ │ ├── setup.md
│ │ ├── special-options.md
│ │ ├── subscriptions.md
│ │ └── usage.md
│ │ ├── guide
│ │ ├── index.md
│ │ └── installation.md
│ │ ├── index.md
│ │ ├── migration
│ │ └── index.md
│ │ ├── public
│ │ ├── error-log.jpeg
│ │ ├── favicon.png
│ │ ├── hero.svg
│ │ ├── logo.svg
│ │ └── vue-apollo-graphql.png
│ │ └── zh-cn
│ │ ├── api
│ │ ├── apollo-mutation.md
│ │ ├── apollo-provider.md
│ │ ├── apollo-query.md
│ │ ├── apollo-subscribe-to-more.md
│ │ ├── dollar-apollo.md
│ │ ├── index.md
│ │ ├── smart-query.md
│ │ ├── smart-subscription.md
│ │ ├── ssr.md
│ │ ├── use-apollo-client.md
│ │ ├── use-loading.md
│ │ ├── use-mutation.md
│ │ ├── use-query.md
│ │ └── use-subscription.md
│ │ ├── guide-advanced
│ │ ├── index.md
│ │ ├── local-state.md
│ │ ├── ssr.md
│ │ └── testing.md
│ │ ├── guide-components
│ │ ├── index.md
│ │ ├── mutation.md
│ │ ├── query.md
│ │ ├── setup.md
│ │ └── subscribe-to-more.md
│ │ ├── guide-composable
│ │ ├── cache-interaction.md
│ │ ├── error-handling.md
│ │ ├── fragments.md
│ │ ├── index.md
│ │ ├── mutation.md
│ │ ├── pagination.md
│ │ ├── query.md
│ │ ├── setup.md
│ │ └── subscription.md
│ │ ├── guide-option
│ │ ├── index.md
│ │ ├── multiple-clients.md
│ │ ├── mutations.md
│ │ ├── pagination.md
│ │ ├── queries.md
│ │ ├── setup.md
│ │ ├── special-options.md
│ │ ├── subscriptions.md
│ │ └── usage.md
│ │ ├── guide
│ │ ├── index.md
│ │ └── installation.md
│ │ ├── index.md
│ │ └── migration
│ │ └── index.md
├── test-e2e-composable-vue3
│ ├── .browserslistrc
│ ├── .editorconfig
│ ├── .gitignore
│ ├── README.md
│ ├── cypress.config.ts
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.js
│ ├── src
│ │ ├── apollo.ts
│ │ ├── assets
│ │ │ └── styles
│ │ │ │ └── tailwind.css
│ │ ├── components
│ │ │ ├── App.vue
│ │ │ ├── ChannelList.vue
│ │ │ ├── ChannelListPinia.vue
│ │ │ ├── ChannelListPinia2.vue
│ │ │ ├── ChannelListPiniaContainer.vue
│ │ │ ├── ChannelView.vue
│ │ │ ├── Disabled.vue
│ │ │ ├── GlobalLoading.vue
│ │ │ ├── KeepPreviousResult.vue
│ │ │ ├── LazyQuery.vue
│ │ │ ├── LazyQueryImmediately.vue
│ │ │ ├── LazyQueryLoad.vue
│ │ │ ├── LazyQueryLoadError.vue
│ │ │ ├── MessageForm.vue
│ │ │ ├── MessageItem.vue
│ │ │ ├── NoSetupQuery.vue
│ │ │ ├── NoSetupQueryMultiClient.vue
│ │ │ ├── NoSetupScopeQuery.vue
│ │ │ ├── NullQuery.vue
│ │ │ ├── OnResult.vue
│ │ │ ├── OnResultChild.vue
│ │ │ ├── PartialError.vue
│ │ │ ├── Subscription.vue
│ │ │ ├── Subscriptions.vue
│ │ │ ├── UpdateQuery.vue
│ │ │ └── Welcome.vue
│ │ ├── main.ts
│ │ ├── router.ts
│ │ ├── shims-vue.d.ts
│ │ └── stores
│ │ │ └── channel.ts
│ ├── tailwind.config.js
│ ├── tests
│ │ └── e2e
│ │ │ ├── .eslintrc.js
│ │ │ ├── specs
│ │ │ ├── errorPolicy.cy.ts
│ │ │ ├── keepPreviousResult.cy.ts
│ │ │ ├── lazy.cy.ts
│ │ │ ├── nullableQuery.cy.ts
│ │ │ ├── outsideComponent.cy.ts
│ │ │ ├── pinia.cy.ts
│ │ │ ├── subscription.cy.ts
│ │ │ ├── test.cy.ts
│ │ │ └── updateQuery.cy.ts
│ │ │ └── support
│ │ │ ├── commands.ts
│ │ │ └── index.ts
│ ├── tsconfig.json
│ └── vite.config.ts
├── test-e2e-ssr
│ ├── .browserslistrc
│ ├── .editorconfig
│ ├── .gitignore
│ ├── README.md
│ ├── cypress.config.ts
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.js
│ ├── server.mjs
│ ├── src
│ │ ├── apollo.ts
│ │ ├── app.ts
│ │ ├── assets
│ │ │ └── styles
│ │ │ │ └── tailwind.css
│ │ ├── components
│ │ │ ├── App.vue
│ │ │ ├── ChannelList.vue
│ │ │ ├── ChannelView.vue
│ │ │ ├── ClientOnly.vue
│ │ │ ├── GlobalLoading.vue
│ │ │ ├── LazyQuery.vue
│ │ │ ├── LazyQueryImmediately.vue
│ │ │ ├── MessageForm.vue
│ │ │ ├── MessageItem.vue
│ │ │ └── Welcome.vue
│ │ ├── context.ts
│ │ ├── entry-client.ts
│ │ ├── entry-server.ts
│ │ ├── env.ts
│ │ ├── router.ts
│ │ └── shims-vue.d.ts
│ ├── tailwind.config.js
│ ├── tests
│ │ └── e2e
│ │ │ ├── .eslintrc.js
│ │ │ ├── specs
│ │ │ └── test.cy.ts
│ │ │ └── support
│ │ │ ├── commands.ts
│ │ │ └── index.ts
│ ├── tsconfig.json
│ └── vite.config.ts
├── test-e2e
│ ├── .gitignore
│ ├── .graphqlconfig.yml
│ ├── .postcssrc.js
│ ├── README.md
│ ├── apollo-server
│ │ ├── connectors
│ │ │ ├── channels.js
│ │ │ ├── messages.js
│ │ │ └── users.js
│ │ ├── context.js
│ │ ├── directives.js
│ │ ├── directives
│ │ │ └── private.js
│ │ ├── reset.js
│ │ ├── resolvers.js
│ │ ├── schema.graphql
│ │ ├── triggers.js
│ │ └── type-defs.js
│ ├── babel.config.js
│ ├── cypress.config.ts
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ └── index.html
│ ├── server.js
│ ├── src
│ │ ├── App.vue
│ │ ├── components
│ │ │ ├── ChannelList.vue
│ │ │ ├── ChannelView.vue
│ │ │ ├── ManualAddSmartQuery.vue
│ │ │ ├── MessageForm.vue
│ │ │ ├── MessageItem.vue
│ │ │ ├── MockSendMessage.vue
│ │ │ ├── PartialError.vue
│ │ │ ├── UpdateCache.vue
│ │ │ ├── UserCurrent.vue
│ │ │ ├── UserLogin.vue
│ │ │ └── WelcomeView.vue
│ │ ├── graphql
│ │ │ ├── channel.gql
│ │ │ ├── channelFragment.gql
│ │ │ ├── channels.gql
│ │ │ ├── messageAdd.gql
│ │ │ ├── messageChanged.gql
│ │ │ ├── messageFragment.gql
│ │ │ ├── messageRemove.gql
│ │ │ ├── messageUpdate.gql
│ │ │ ├── userCurrent.gql
│ │ │ ├── userFragment.gql
│ │ │ ├── userLogin.gql
│ │ │ ├── userLogout.gql
│ │ │ └── userRegister.gql
│ │ ├── main.js
│ │ ├── mixins
│ │ │ └── UserCurrent.js
│ │ ├── router.js
│ │ ├── store.js
│ │ ├── style
│ │ │ └── imports.styl
│ │ └── vue-apollo.js
│ ├── tests
│ │ └── e2e
│ │ │ ├── .eslintrc
│ │ │ ├── specs
│ │ │ ├── cache.cy.js
│ │ │ ├── chat.cy.js
│ │ │ ├── errorPolicy.cy.js
│ │ │ └── manual-smart-query.cy.js
│ │ │ └── support
│ │ │ ├── commands.js
│ │ │ └── index.js
│ └── vue.config.js
├── test-server
│ ├── bin.mjs
│ ├── package.json
│ ├── src
│ │ ├── data.ts
│ │ ├── index.ts
│ │ ├── schema.ts
│ │ └── util.ts
│ └── tsconfig.json
├── vue-apollo-components
│ ├── .npmignore
│ ├── README.md
│ ├── babel.config.js
│ ├── build
│ │ ├── rollup.config.base.js
│ │ ├── rollup.config.browser.js
│ │ ├── rollup.config.es.js
│ │ └── rollup.config.umd.js
│ ├── package.json
│ └── src
│ │ ├── ApolloMutation.js
│ │ ├── ApolloQuery.js
│ │ ├── ApolloSubscribeToMore.js
│ │ └── index.js
├── vue-apollo-composable
│ ├── README.md
│ ├── esbuild.mjs
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── useApolloClient.ts
│ │ ├── useLazyQuery.ts
│ │ ├── useLoading.ts
│ │ ├── useMutation.ts
│ │ ├── useQuery.ts
│ │ ├── useResult.ts
│ │ ├── useSubscription.ts
│ │ └── util
│ │ │ ├── ExtractSingleKey.ts
│ │ │ ├── ReactiveFunction.ts
│ │ │ ├── env.ts
│ │ │ ├── loadingTracking.ts
│ │ │ ├── paramToReactive.ts
│ │ │ ├── paramToRef.ts
│ │ │ ├── toApolloError.ts
│ │ │ └── useEventHook.ts
│ ├── tests
│ │ ├── .eslintrc.js
│ │ ├── fixtures
│ │ │ └── graphql-example-types.ts
│ │ └── types
│ │ │ ├── assertions.ts
│ │ │ ├── tsconfig.json
│ │ │ ├── useApolloClient-types.test.ts
│ │ │ ├── useLoading-types.test.ts
│ │ │ ├── useMutation-types.test.ts
│ │ │ ├── useQuery-types.test.ts
│ │ │ ├── useResult-types.test.ts
│ │ │ ├── useSubscription-types.test.ts
│ │ │ └── util
│ │ │ └── ExtractSingleKey.test.ts
│ ├── tsconfig.json
│ └── tsconfig.lint.json
├── vue-apollo-option
│ ├── .npmignore
│ ├── README.md
│ ├── babel.config.js
│ ├── build
│ │ ├── rollup.config.base.js
│ │ ├── rollup.config.browser.js
│ │ ├── rollup.config.es.js
│ │ └── rollup.config.umd.js
│ ├── lib
│ │ ├── consts.js
│ │ └── utils.js
│ ├── package.json
│ ├── src
│ │ ├── apollo-provider.js
│ │ ├── dollar-apollo.js
│ │ ├── env.js
│ │ ├── index.js
│ │ ├── mixin.js
│ │ ├── smart-apollo.js
│ │ ├── smart-query.js
│ │ └── smart-subscription.js
│ ├── tests
│ │ └── unit
│ │ │ ├── .eslintrc.js
│ │ │ └── ssr.test.js
│ ├── types
│ │ ├── .gitignore
│ │ ├── apollo-provider.d.ts
│ │ ├── index.d.ts
│ │ ├── options.d.ts
│ │ ├── test
│ │ │ ├── App.ts
│ │ │ ├── App.vue
│ │ │ ├── Decorator.ts
│ │ │ ├── index.ts
│ │ │ └── tsconfig.json
│ │ ├── utils.d.ts
│ │ ├── vue-apollo.d.ts
│ │ └── vue.d.ts
│ └── vitest.config.ts
├── vue-apollo-ssr
│ ├── README.md
│ ├── build.mjs
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
└── vue-apollo-util
│ ├── README.md
│ ├── package.json
│ ├── src
│ ├── errorLog.ts
│ └── index.ts
│ └── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── postcss.config.js
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: Akryum
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: need team repro
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Versions**
24 | vue:
25 | vue-apollo:
26 | @apollo/client:
27 |
28 | **Additional context**
29 | Add any other context about the problem here.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/nightly.yml:
--------------------------------------------------------------------------------
1 | name: Publish Nightlies
2 | on:
3 | pull_request:
4 | push:
5 | branches:
6 | - '**'
7 | tags:
8 | - '!**'
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - name: Set alternate npm integrity keys
16 | run: |
17 | echo COREPACK_INTEGRITY_KEYS="$(curl https://registry.npmjs.org/-/npm/v1/keys | jq -c '{npm: .keys}')" >> $GITHUB_ENV
18 | - uses: actions/checkout@v4
19 | - run: corepack enable
20 | - uses: actions/setup-node@v4
21 | with:
22 | node-version: 23
23 | cache: pnpm
24 | - run: pnpm install
25 |
26 | - name: Build
27 | run: pnpm build
28 |
29 | - run: pnpx pkg-pr-new publish './packages/*'
30 |
--------------------------------------------------------------------------------
/.github/workflows/pr-title.yml:
--------------------------------------------------------------------------------
1 | name: Check PR title
2 |
3 | on:
4 | pull_request_target:
5 | types:
6 | - opened
7 | - edited
8 | - synchronize
9 |
10 | jobs:
11 | check-pr-title:
12 | runs-on: ubuntu-latest
13 | name: Check PR title
14 | steps:
15 | # Please look up the latest version from
16 | # https://github.com/amannn/action-semantic-pull-request/releases
17 | - uses: amannn/action-semantic-pull-request@v3.4.2
18 | env:
19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20 |
--------------------------------------------------------------------------------
/.github/workflows/release-notes.yml:
--------------------------------------------------------------------------------
1 | name: Create release
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
7 |
8 | jobs:
9 | build:
10 | name: Create Release
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout code
14 | uses: actions/checkout@master
15 | with:
16 | fetch-depth: 0 # Fetch all tags
17 |
18 | - name: Create Release for Tag
19 | id: release_tag
20 | uses: Akryum/release-tag@v4.0.7
21 | env:
22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23 | with:
24 | tag_name: ${{ github.ref }}
25 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Main continuous tests
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - v4
8 | - feat/*
9 | - fix/*
10 | pull_request:
11 | workflow_dispatch:
12 |
13 | concurrency:
14 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
15 | cancel-in-progress: true
16 |
17 | jobs:
18 | build-and-test:
19 | runs-on: ubuntu-latest
20 | name: Build and test
21 |
22 | steps:
23 | - name: Set alternate npm integrity keys
24 | run: |
25 | echo COREPACK_INTEGRITY_KEYS="$(curl https://registry.npmjs.org/-/npm/v1/keys | jq -c '{npm: .keys}')" >> $GITHUB_ENV
26 | - uses: actions/checkout@v4
27 | - run: corepack enable
28 | - uses: actions/setup-node@v4
29 | with:
30 | node-version: 23
31 | cache: pnpm
32 | - run: pnpm install
33 |
34 | - name: Lint
35 | run: pnpm run lint
36 |
37 | - name: Build
38 | run: pnpm run build
39 |
40 | - name: Types
41 | run: pnpm run test:types
42 |
43 | - name: Unit tests
44 | run: pnpm run test:unit
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules/
3 | dist/
4 | cache/
5 | .eslintcache
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | trim_trailing_whitespace = true
5 | insert_final_newline = true
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | /tests/e2e/videos/
6 | /tests/e2e/screenshots/
7 |
8 | # local env files
9 | .env.local
10 | .env.*.local
11 |
12 | # Log files
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 |
17 | # Editor directories and files
18 | .idea
19 | .vscode
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | /live/
27 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/README.md:
--------------------------------------------------------------------------------
1 | # ssr
2 |
3 | ## Project setup
4 | ```
5 | yarn install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | yarn serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | yarn build
16 | ```
17 |
18 | ### Run your end-to-end tests
19 | ```
20 | yarn test:e2e
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/context.js:
--------------------------------------------------------------------------------
1 | import { db } from './utils/db'
2 | import { processUpload } from './utils/upload'
3 |
4 | // Context passed to all resolvers (third argument)
5 | // req => Query
6 | // connection => Subscription
7 | // eslint-disable-next-line no-unused-vars
8 | export default ({ req, connection }) => {
9 | return {
10 | db,
11 | processUpload,
12 |
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/data-sources.js:
--------------------------------------------------------------------------------
1 | export default function () {
2 | return {}
3 | }
4 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/directives.js:
--------------------------------------------------------------------------------
1 | export default {
2 | // Schema directives
3 | // https://www.apollographql.com/docs/graphql-tools/schema-directives.html
4 | }
5 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/mocks.js:
--------------------------------------------------------------------------------
1 | // Enable mocking in vue.config.js with `"pluginOptions": { "enableMocks": true }`
2 | // Customize mocking: https://www.apollographql.com/docs/graphql-tools/mocking.html#Customizing-mocks
3 | export default {
4 | // Mock resolvers here
5 | }
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/schema.graphql:
--------------------------------------------------------------------------------
1 | "Included scalars"
2 | scalar JSON
3 | scalar Upload
4 |
5 | "It will increment!"
6 | type Counter {
7 | "Number of increments"
8 | count: Int!
9 | "Full message for testing"
10 | countStr: String
11 | }
12 |
13 | "A text message send by users"
14 | type Message {
15 | id: ID!
16 | "Message content"
17 | text: String!
18 | }
19 |
20 | "Input from user to create a message"
21 | input MessageInput {
22 | "Message content"
23 | text: String!
24 | }
25 |
26 | type File {
27 | id: ID!
28 | path: String!
29 | filename: String!
30 | mimetype: String!
31 | encoding: String!
32 | }
33 |
34 |
35 | type Query {
36 | "Test query with a parameter"
37 | hello(name: String): String!
38 | "List of messages sent by users"
39 | messages: [Message]
40 | uploads: [File]
41 |
42 | }
43 |
44 | type Mutation {
45 | myMutation: String!
46 | "Add a message and publish it on 'messages' subscription channel"
47 | addMessage (input: MessageInput!): Message!
48 | singleUpload (file: Upload!): File!
49 | multipleUpload (files: [Upload!]!): [File!]!
50 |
51 | }
52 |
53 | type Subscription {
54 | mySub: String!
55 | "This will update every 2 seconds"
56 | counter: Counter!
57 | "When a new message is added"
58 | messageAdded: Message!
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/server.js:
--------------------------------------------------------------------------------
1 | import ssrMiddleware from '@akryum/vue-cli-plugin-ssr/lib/app'
2 | import path from 'path'
3 | import express from 'express'
4 |
5 | export default app => {
6 | app.use('/files', express.static(path.resolve(__dirname, '../live/uploads')))
7 |
8 | ssrMiddleware(app, { prodOnly: true })
9 | }
10 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/type-defs.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import path from 'path'
3 |
4 | export default fs.readFileSync(path.resolve(__dirname, './schema.graphql'), { encoding: 'utf8' })
5 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/utils/db.js:
--------------------------------------------------------------------------------
1 | import Lowdb from 'lowdb'
2 | // import FileSync from 'lowdb/adapters/FileSync'
3 | import Memory from 'lowdb/adapters/Memory'
4 | import mkdirp from 'mkdirp'
5 | import { resolve } from 'path'
6 |
7 | mkdirp(resolve(__dirname, '../../live'))
8 |
9 | // export const db = new Lowdb(new FileSync(resolve(__dirname, '../../live/db.json')))
10 | export const db = new Lowdb(new Memory())
11 |
12 | // Seed an empty DB
13 | db.defaults({
14 | messages: [
15 | {
16 | id: 'a',
17 | text: 'Message 1',
18 | },
19 | {
20 | id: 'b',
21 | text: 'Message 2',
22 | },
23 | {
24 | id: 'c',
25 | text: 'Message 3',
26 | },
27 | ],
28 | uploads: [],
29 | }).write()
30 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo-server/utils/upload.js:
--------------------------------------------------------------------------------
1 | import { createWriteStream } from 'fs'
2 | import { resolve } from 'path'
3 | import { sync } from 'mkdirp'
4 | import { generate } from 'shortid'
5 | import { db } from './db'
6 |
7 | const uploadDir = resolve(__dirname, '../../live/uploads')
8 |
9 | // Ensure upload directory exists
10 | sync(uploadDir)
11 |
12 | const storeUpload = async ({ stream, filename }) => {
13 | const id = generate()
14 | const file = `${id}-${filename}`
15 | const path = `${uploadDir}/${file}`
16 | const urlPath = `files/${file}`
17 |
18 | return new Promise((resolve, reject) =>
19 | stream
20 | .pipe(createWriteStream(path))
21 | .on('finish', () => resolve({ id, path: urlPath }))
22 | .on('error', reject),
23 | )
24 | }
25 |
26 | const recordFile = file =>
27 | db
28 | .get('uploads')
29 | .push(file)
30 | .last()
31 | .write()
32 |
33 | export async function processUpload (file) {
34 | const { stream, filename, mimetype, encoding } = await file
35 | const { id, path } = await storeUpload({ stream, filename })
36 | return recordFile({ id, filename, mimetype, encoding, path })
37 | }
38 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/apollo.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | // Load .env files
4 | const { loadEnv } = require('vue-cli-plugin-apollo/utils/load-env')
5 | const env = loadEnv([
6 | path.resolve(__dirname, '.env'),
7 | path.resolve(__dirname, '.env.local'),
8 | ])
9 |
10 | module.exports = {
11 | client: {
12 | service: env.VUE_APP_APOLLO_ENGINE_SERVICE,
13 | includes: ['src/**/*.{js,jsx,ts,tsx,vue,gql}'],
14 | },
15 | service: {
16 | name: env.VUE_APP_APOLLO_ENGINE_SERVICE,
17 | localSchemaFile: path.resolve(__dirname, './node_modules/.temp/graphql/schema.json'),
18 | },
19 | engine: {
20 | endpoint: process.env.APOLLO_ENGINE_API_ENDPOINT,
21 | apiKey: env.VUE_APP_APOLLO_ENGINE_KEY,
22 | },
23 | }
24 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset',
4 | ],
5 | }
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "pluginsFile": "tests/e2e/plugins/index.js"
3 | }
4 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | },
5 | }
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuejs/apollo/fb027e6adf4d4129fb26f8c918060771a0afd59b/.test-todo/test-ssr-composition/public/favicon.ico
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | ssr
9 |
10 |
11 |
12 | We're sorry but ssr doesn't work properly without JavaScript enabled. Please enable it to continue.
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/public/index.ssr.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ title }}
9 | {{{ renderResourceHints() }}}
10 | {{{ renderStyles() }}}
11 |
12 |
13 |
14 | {{{ renderState() }}}
15 | {{{ renderState({ contextKey: 'apolloState', windowKey: '__APOLLO_STATE__' }) }}}
16 | {{{ renderScripts() }}}
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Home
6 | |
7 |
8 | Apollo
9 | |
10 |
11 | About
12 |
13 |
14 |
15 |
16 |
20 | {{ apolloState }}
21 |
22 |
23 |
24 |
25 |
42 |
43 |
74 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuejs/apollo/fb027e6adf4d4129fb26f8c918060771a0afd59b/.test-todo/test-ssr-composition/src/assets/logo.png
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/components/ApolloLoading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Loading...
4 |
5 |
9 | {{ messages.length }} messages
10 |
11 |
12 |
13 |
29 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 | {{ hello }}
9 |
10 |
11 |
12 |
13 |
32 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/entry-client.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import { loadAsyncComponents } from '@akryum/vue-cli-plugin-ssr/client'
3 |
4 | import { createApp } from './main'
5 |
6 | createApp({
7 | async beforeApp ({
8 | router,
9 | }) {
10 | await loadAsyncComponents({ router })
11 | },
12 |
13 | afterApp ({
14 | app,
15 | router,
16 | }) {
17 | router.onReady(() => {
18 | app.$mount('#app')
19 | })
20 | },
21 | })
22 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/entry-server.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import * as ApolloSSR from '@vue/apollo-ssr'
3 | import { createApp } from './main'
4 |
5 | const prepareUrlForRouting = url => {
6 | const { BASE_URL } = process.env
7 | return url.startsWith(BASE_URL.replace(/\/$/, ''))
8 | ? url.slice(BASE_URL.length)
9 | : url
10 | }
11 |
12 | export default context => {
13 | return new Promise(async (resolve, reject) => {
14 | const {
15 | app,
16 | router,
17 | apolloClient,
18 | } = await createApp()
19 |
20 | router.push(prepareUrlForRouting(context.url))
21 |
22 | router.onReady(() => {
23 | context.rendered = () => {
24 | // Same for Apollo client cache
25 | context.apolloState = ApolloSSR.getStates({
26 | defaultClient: apolloClient,
27 | })
28 | }
29 | resolve(app)
30 | }, reject)
31 | })
32 | }
33 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/graphql/AddMessage.gql:
--------------------------------------------------------------------------------
1 | #import "./MessageFragment.gql"
2 |
3 | mutation addMessage ($input: MessageInput!) {
4 | addMessage (input: $input) {
5 | ...Message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/graphql/FileFragment.gql:
--------------------------------------------------------------------------------
1 | fragment file on File {
2 | id
3 | path
4 | filename
5 | mimetype
6 | encoding
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/graphql/Files.gql:
--------------------------------------------------------------------------------
1 | #import "./FileFragment.gql"
2 |
3 | query files {
4 | files: uploads {
5 | ...file
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/graphql/HelloWorld.gql:
--------------------------------------------------------------------------------
1 | query HelloWorld ($name: String) {
2 | hello (name: $name)
3 | }
4 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/graphql/MessageAdded.gql:
--------------------------------------------------------------------------------
1 | #import "./MessageFragment.gql"
2 |
3 | subscription messageAdded {
4 | messageAdded {
5 | ...Message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/graphql/MessageFragment.gql:
--------------------------------------------------------------------------------
1 | fragment Message on Message {
2 | id
3 | text
4 | }
5 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/graphql/Messages.gql:
--------------------------------------------------------------------------------
1 | #import "./MessageFragment.gql"
2 |
3 | query messages {
4 | messages {
5 | ...Message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/graphql/UploadFile.gql:
--------------------------------------------------------------------------------
1 | #import "./FileFragment.gql"
2 |
3 | mutation uploadFile ($file: Upload!) {
4 | singleUpload (file: $file) {
5 | ...file
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueCompositionAPI, { provide } from '@vue/composition-api'
3 | import { DefaultApolloClient } from '@vue/apollo-composable'
4 | import App from './App.vue'
5 | import { createRouter } from './router'
6 | import { createClient } from './vue-apollo'
7 |
8 | Vue.use(VueCompositionAPI)
9 |
10 | Vue.config.productionTip = false
11 |
12 | export async function createApp ({
13 | beforeApp = () => {},
14 | afterApp = () => {},
15 | } = {}) {
16 | const router = createRouter()
17 |
18 | const apolloClient = createClient({
19 | ssr: process.server,
20 | })
21 |
22 | await beforeApp({
23 | router,
24 | apolloClient,
25 | })
26 |
27 | const app = new Vue({
28 | router,
29 |
30 | setup () {
31 | provide(DefaultApolloClient, apolloClient)
32 | },
33 |
34 | render: h => h(App),
35 | })
36 |
37 | const result = {
38 | app,
39 | router,
40 | apolloClient,
41 | }
42 |
43 | await afterApp(result)
44 |
45 | return result
46 | }
47 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import Home from '../views/Home.vue'
4 |
5 | Vue.use(VueRouter)
6 |
7 | export function createRouter () {
8 | const routes = [
9 | {
10 | path: '/',
11 | name: 'home',
12 | component: Home,
13 | },
14 | {
15 | path: '/apollo',
16 | name: 'apollo',
17 | component: () => import(/* webpackChunkName: "apollo" */ '../components/ApolloExample.vue'),
18 | },
19 | {
20 | path: '/apollo-loading',
21 | name: 'apollo-loading',
22 | component: () => import(/* webpackChunkName: "apollo-loading" */ '../components/ApolloLoading.vue'),
23 | },
24 | {
25 | path: '/hello',
26 | name: 'hello',
27 | component: () => import(/* webpackChunkName: "hello" */ '../components/HelloWorld.vue'),
28 | },
29 | {
30 | path: '/about',
31 | name: 'about',
32 | // route level code-splitting
33 | // this generates a separate chunk (about.[hash].js) for this route
34 | // which is lazy-loaded when the route is visited.
35 | component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
36 | },
37 | ]
38 |
39 | const router = new VueRouter({
40 | mode: 'history',
41 | base: process.env.BASE_URL,
42 | routes,
43 | })
44 |
45 | return router
46 | }
47 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
{{ meow }}
9 |
{{ kui.hi }}
10 |
{{ meuh.hi }}
11 |
{{ isServer }}
12 |
13 |
14 |
15 |
42 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/tests/e2e/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | 'cypress',
4 | ],
5 | env: {
6 | mocha: true,
7 | 'cypress/globals': true,
8 | },
9 | rules: {
10 | strict: 'off',
11 | },
12 | }
13 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/tests/e2e/plugins/index.js:
--------------------------------------------------------------------------------
1 | // https://docs.cypress.io/guides/guides/plugins-guide.html
2 |
3 | // if you need a custom webpack configuration you can uncomment the following import
4 | // and then use the `file:preprocessor` event
5 | // as explained in the cypress docs
6 | // https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples
7 |
8 | /* eslint-disable import/no-extraneous-dependencies, global-require, arrow-body-style */
9 | // const webpack = require('@cypress/webpack-preprocessor')
10 |
11 | module.exports = (on, config) => {
12 | // on('file:preprocessor', webpack({
13 | // webpackOptions: require('@vue/cli-service/webpack.config'),
14 | // watchOptions: {}
15 | // }))
16 |
17 | return Object.assign({}, config, {
18 | fixturesFolder: 'tests/e2e/fixtures',
19 | integrationFolder: 'tests/e2e/specs',
20 | screenshotsFolder: 'tests/e2e/screenshots',
21 | videosFolder: 'tests/e2e/videos',
22 | supportFile: 'tests/e2e/support/index.js',
23 | })
24 | }
25 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/tests/e2e/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This is will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/tests/e2e/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr-composition/vue.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@vue/cli-service').ProjectOptions} */
2 | module.exports = {
3 | pluginOptions: {
4 | apollo: {
5 | enableMocks: false,
6 | enableEngine: false,
7 | },
8 | },
9 |
10 | chainWebpack (config) {
11 | config.resolve.symlinks(false)
12 | config.externals([
13 | 'utf-8-validate',
14 | 'bufferutil',
15 | ])
16 | config.module.noParse([
17 | /iconv-loader/,
18 | ])
19 | config.resolve.alias.set('vue-demi', '@vue/composition-api')
20 | },
21 | }
22 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | trim_trailing_whitespace = true
5 | insert_final_newline = true
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | /tests/e2e/videos/
6 | /tests/e2e/screenshots/
7 |
8 | # local env files
9 | .env.local
10 | .env.*.local
11 |
12 | # Log files
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 |
17 | # Editor directories and files
18 | .idea
19 | .vscode
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | /live/
27 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/README.md:
--------------------------------------------------------------------------------
1 | # ssr
2 |
3 | ## Project setup
4 | ```
5 | yarn install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | yarn serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | yarn build
16 | ```
17 |
18 | ### Run your end-to-end tests
19 | ```
20 | yarn test:e2e
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/context.js:
--------------------------------------------------------------------------------
1 | import { db } from './utils/db'
2 | import { processUpload } from './utils/upload'
3 |
4 | // Context passed to all resolvers (third argument)
5 | // req => Query
6 | // connection => Subscription
7 | // eslint-disable-next-line no-unused-vars
8 | export default ({ req, connection }) => {
9 | return {
10 | db,
11 | processUpload,
12 |
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/data-sources.js:
--------------------------------------------------------------------------------
1 | export default function () {
2 | return {}
3 | }
4 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/directives.js:
--------------------------------------------------------------------------------
1 | export default {
2 | // Schema directives
3 | // https://www.apollographql.com/docs/graphql-tools/schema-directives.html
4 | }
5 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/mocks.js:
--------------------------------------------------------------------------------
1 | // Enable mocking in vue.config.js with `"pluginOptions": { "enableMocks": true }`
2 | // Customize mocking: https://www.apollographql.com/docs/graphql-tools/mocking.html#Customizing-mocks
3 | export default {
4 | // Mock resolvers here
5 | }
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/schema.graphql:
--------------------------------------------------------------------------------
1 | "Included scalars"
2 | scalar JSON
3 | scalar Upload
4 |
5 | "It will increment!"
6 | type Counter {
7 | "Number of increments"
8 | count: Int!
9 | "Full message for testing"
10 | countStr: String
11 | }
12 |
13 | "A text message send by users"
14 | type Message {
15 | id: ID!
16 | "Message content"
17 | text: String!
18 | }
19 |
20 | "Input from user to create a message"
21 | input MessageInput {
22 | "Message content"
23 | text: String!
24 | }
25 |
26 | type File {
27 | id: ID!
28 | path: String!
29 | filename: String!
30 | mimetype: String!
31 | encoding: String!
32 | }
33 |
34 |
35 | type Query {
36 | "Test query with a parameter"
37 | hello(name: String): String!
38 | "List of messages sent by users"
39 | messages: [Message]
40 | uploads: [File]
41 |
42 | }
43 |
44 | type Mutation {
45 | myMutation: String!
46 | "Add a message and publish it on 'messages' subscription channel"
47 | addMessage (input: MessageInput!): Message!
48 | singleUpload (file: Upload!): File!
49 | multipleUpload (files: [Upload!]!): [File!]!
50 |
51 | }
52 |
53 | type Subscription {
54 | mySub: String!
55 | "This will update every 2 seconds"
56 | counter: Counter!
57 | "When a new message is added"
58 | messageAdded: Message!
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/server.js:
--------------------------------------------------------------------------------
1 | import ssrMiddleware from '@akryum/vue-cli-plugin-ssr/lib/app'
2 | import path from 'path'
3 | import express from 'express'
4 |
5 | export default app => {
6 | app.use('/files', express.static(path.resolve(__dirname, '../live/uploads')))
7 |
8 | ssrMiddleware(app, { prodOnly: true })
9 | }
10 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/type-defs.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import path from 'path'
3 |
4 | export default fs.readFileSync(path.resolve(__dirname, './schema.graphql'), { encoding: 'utf8' })
5 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/utils/db.js:
--------------------------------------------------------------------------------
1 | import Lowdb from 'lowdb'
2 | // import FileSync from 'lowdb/adapters/FileSync'
3 | import Memory from 'lowdb/adapters/Memory'
4 | import mkdirp from 'mkdirp'
5 | import { resolve } from 'path'
6 |
7 | mkdirp(resolve(__dirname, '../../live'))
8 |
9 | // export const db = new Lowdb(new FileSync(resolve(__dirname, '../../live/db.json')))
10 | export const db = new Lowdb(new Memory())
11 |
12 | // Seed an empty DB
13 | db.defaults({
14 | messages: [
15 | {
16 | id: 'a',
17 | text: 'Message 1',
18 | },
19 | {
20 | id: 'b',
21 | text: 'Message 2',
22 | },
23 | {
24 | id: 'c',
25 | text: 'Message 3',
26 | },
27 | ],
28 | uploads: [],
29 | }).write()
30 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo-server/utils/upload.js:
--------------------------------------------------------------------------------
1 | import { createWriteStream } from 'fs'
2 | import { resolve } from 'path'
3 | import { sync } from 'mkdirp'
4 | import { generate } from 'shortid'
5 | import { db } from './db'
6 |
7 | const uploadDir = resolve(__dirname, '../../live/uploads')
8 |
9 | // Ensure upload directory exists
10 | sync(uploadDir)
11 |
12 | const storeUpload = async ({ stream, filename }) => {
13 | const id = generate()
14 | const file = `${id}-${filename}`
15 | const path = `${uploadDir}/${file}`
16 | const urlPath = `files/${file}`
17 |
18 | return new Promise((resolve, reject) =>
19 | stream
20 | .pipe(createWriteStream(path))
21 | .on('finish', () => resolve({ id, path: urlPath }))
22 | .on('error', reject),
23 | )
24 | }
25 |
26 | const recordFile = file =>
27 | db
28 | .get('uploads')
29 | .push(file)
30 | .last()
31 | .write()
32 |
33 | export async function processUpload (file) {
34 | const { stream, filename, mimetype, encoding } = await file
35 | const { id, path } = await storeUpload({ stream, filename })
36 | return recordFile({ id, filename, mimetype, encoding, path })
37 | }
38 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/apollo.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | // Load .env files
4 | const { loadEnv } = require('vue-cli-plugin-apollo/utils/load-env')
5 | const env = loadEnv([
6 | path.resolve(__dirname, '.env'),
7 | path.resolve(__dirname, '.env.local'),
8 | ])
9 |
10 | module.exports = {
11 | client: {
12 | service: env.VUE_APP_APOLLO_ENGINE_SERVICE,
13 | includes: ['src/**/*.{js,jsx,ts,tsx,vue,gql}'],
14 | },
15 | service: {
16 | name: env.VUE_APP_APOLLO_ENGINE_SERVICE,
17 | localSchemaFile: path.resolve(__dirname, './node_modules/.temp/graphql/schema.json'),
18 | },
19 | engine: {
20 | endpoint: process.env.APOLLO_ENGINE_API_ENDPOINT,
21 | apiKey: env.VUE_APP_APOLLO_ENGINE_KEY,
22 | },
23 | }
24 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset',
4 | ],
5 | }
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "pluginsFile": "tests/e2e/plugins/index.js"
3 | }
4 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | },
5 | }
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuejs/apollo/fb027e6adf4d4129fb26f8c918060771a0afd59b/.test-todo/test-ssr/public/favicon.ico
--------------------------------------------------------------------------------
/.test-todo/test-ssr/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | ssr
9 |
10 |
11 |
12 | We're sorry but ssr doesn't work properly without JavaScript enabled. Please enable it to continue.
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/public/index.ssr.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ title }}
9 | {{{ renderResourceHints() }}}
10 | {{{ renderStyles() }}}
11 |
12 |
13 |
14 | {{{ renderState() }}}
15 | {{{ renderState({ contextKey: 'apolloState', windowKey: '__APOLLO_STATE__' }) }}}
16 | {{{ renderScripts() }}}
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Home
6 | |
7 |
8 | Apollo
9 | |
10 |
11 | About
12 |
13 |
14 |
15 |
16 |
20 | {{ apolloState }}
21 |
22 |
23 |
24 |
25 |
38 |
39 |
70 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuejs/apollo/fb027e6adf4d4129fb26f8c918060771a0afd59b/.test-todo/test-ssr/src/assets/logo.png
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/components/ApolloLoading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Loading...
4 |
5 |
9 | {{ messages.length }} messages
10 |
11 |
12 |
13 |
22 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 | {{ hello }}
9 |
10 |
11 |
12 |
13 |
35 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/entry-client.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import { loadAsyncComponents } from '@akryum/vue-cli-plugin-ssr/client'
3 |
4 | import { createApp } from './main'
5 |
6 | createApp({
7 | async beforeApp ({
8 | router,
9 | }) {
10 | await loadAsyncComponents({ router })
11 | },
12 |
13 | afterApp ({
14 | app,
15 | router,
16 | }) {
17 | router.onReady(() => {
18 | app.$mount('#app')
19 | })
20 | },
21 | })
22 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/entry-server.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import * as ApolloSSR from '@vue/apollo-ssr'
3 | import { createApp } from './main'
4 |
5 | const prepareUrlForRouting = url => {
6 | const { BASE_URL } = process.env
7 | return url.startsWith(BASE_URL.replace(/\/$/, ''))
8 | ? url.slice(BASE_URL.length)
9 | : url
10 | }
11 |
12 | export default context => {
13 | return new Promise(async (resolve, reject) => {
14 | const {
15 | app,
16 | router,
17 | apolloProvider,
18 | } = await createApp()
19 |
20 | router.push(prepareUrlForRouting(context.url))
21 |
22 | router.onReady(() => {
23 | context.rendered = () => {
24 | // Same for Apollo client cache
25 | context.apolloState = ApolloSSR.getStates(apolloProvider.clients)
26 | }
27 | resolve(app)
28 | }, reject)
29 | })
30 | }
31 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/graphql/AddMessage.gql:
--------------------------------------------------------------------------------
1 | #import "./MessageFragment.gql"
2 |
3 | mutation addMessage ($input: MessageInput!) {
4 | addMessage (input: $input) {
5 | ...Message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/graphql/FileFragment.gql:
--------------------------------------------------------------------------------
1 | fragment file on File {
2 | id
3 | path
4 | filename
5 | mimetype
6 | encoding
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/graphql/Files.gql:
--------------------------------------------------------------------------------
1 | #import "./FileFragment.gql"
2 |
3 | query files {
4 | files: uploads {
5 | ...file
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/graphql/HelloWorld.gql:
--------------------------------------------------------------------------------
1 | query HelloWorld ($name: String) {
2 | hello (name: $name)
3 | }
4 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/graphql/MessageAdded.gql:
--------------------------------------------------------------------------------
1 | #import "./MessageFragment.gql"
2 |
3 | subscription messageAdded {
4 | messageAdded {
5 | ...Message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/graphql/MessageFragment.gql:
--------------------------------------------------------------------------------
1 | fragment Message on Message {
2 | id
3 | text
4 | }
5 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/graphql/Messages.gql:
--------------------------------------------------------------------------------
1 | #import "./MessageFragment.gql"
2 |
3 | query messages {
4 | messages {
5 | ...Message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/graphql/UploadFile.gql:
--------------------------------------------------------------------------------
1 | #import "./FileFragment.gql"
2 |
3 | mutation uploadFile ($file: Upload!) {
4 | singleUpload (file: $file) {
5 | ...file
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import { createRouter } from './router'
4 | import { createProvider } from './vue-apollo'
5 |
6 | Vue.config.productionTip = false
7 |
8 | export async function createApp ({
9 | beforeApp = () => {},
10 | afterApp = () => {},
11 | } = {}) {
12 | const router = createRouter()
13 |
14 | const apolloProvider = createProvider({
15 | ssr: process.server,
16 | })
17 |
18 | await beforeApp({
19 | router,
20 |
21 | apolloProvider,
22 | })
23 |
24 | const app = new Vue({
25 | router,
26 | apolloProvider,
27 | render: h => h(App),
28 | })
29 |
30 | const result = {
31 | app,
32 | router,
33 |
34 | apolloProvider,
35 | }
36 |
37 | await afterApp(result)
38 |
39 | return result
40 | }
41 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import Home from '../views/Home.vue'
4 |
5 | Vue.use(VueRouter)
6 |
7 | export function createRouter () {
8 | const routes = [
9 | {
10 | path: '/',
11 | name: 'home',
12 | component: Home,
13 | },
14 | {
15 | path: '/apollo',
16 | name: 'apollo',
17 | component: () => import(/* webpackChunkName: "apollo" */ '../components/ApolloExample.vue'),
18 | },
19 | {
20 | path: '/apollo-loading',
21 | name: 'apollo-loading',
22 | component: () => import(/* webpackChunkName: "apollo-loading" */ '../components/ApolloLoading.vue'),
23 | },
24 | {
25 | path: '/hello',
26 | name: 'hello',
27 | component: () => import(/* webpackChunkName: "hello" */ '../components/HelloWorld.vue'),
28 | },
29 | {
30 | path: '/about',
31 | name: 'about',
32 | // route level code-splitting
33 | // this generates a separate chunk (about.[hash].js) for this route
34 | // which is lazy-loaded when the route is visited.
35 | component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
36 | },
37 | ]
38 |
39 | const router = new VueRouter({
40 | mode: 'history',
41 | base: process.env.BASE_URL,
42 | routes,
43 | })
44 |
45 | return router
46 | }
47 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
15 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/tests/e2e/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | 'cypress',
4 | ],
5 | env: {
6 | mocha: true,
7 | 'cypress/globals': true,
8 | },
9 | rules: {
10 | strict: 'off',
11 | },
12 | }
13 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/tests/e2e/plugins/index.js:
--------------------------------------------------------------------------------
1 | // https://docs.cypress.io/guides/guides/plugins-guide.html
2 |
3 | // if you need a custom webpack configuration you can uncomment the following import
4 | // and then use the `file:preprocessor` event
5 | // as explained in the cypress docs
6 | // https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples
7 |
8 | /* eslint-disable import/no-extraneous-dependencies, global-require, arrow-body-style */
9 | // const webpack = require('@cypress/webpack-preprocessor')
10 |
11 | module.exports = (on, config) => {
12 | // on('file:preprocessor', webpack({
13 | // webpackOptions: require('@vue/cli-service/webpack.config'),
14 | // watchOptions: {}
15 | // }))
16 |
17 | return Object.assign({}, config, {
18 | fixturesFolder: 'tests/e2e/fixtures',
19 | integrationFolder: 'tests/e2e/specs',
20 | screenshotsFolder: 'tests/e2e/screenshots',
21 | videosFolder: 'tests/e2e/videos',
22 | supportFile: 'tests/e2e/support/index.js',
23 | })
24 | }
25 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/tests/e2e/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This is will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/tests/e2e/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/.test-todo/test-ssr/vue.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@vue/cli-service').ProjectOptions} */
2 | module.exports = {
3 | pluginOptions: {
4 | apollo: {
5 | enableMocks: false,
6 | enableEngine: false,
7 | },
8 | },
9 |
10 | chainWebpack (config) {
11 | config.resolve.symlinks(false)
12 | config.externals([
13 | 'utf-8-validate',
14 | 'bufferutil',
15 | ])
16 | config.module.noParse([
17 | /iconv-loader/,
18 | ])
19 | },
20 | }
21 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.validate": [
3 | "javascript",
4 | "javascriptreact",
5 | "vue"
6 | ],
7 | "eslint.enable": true,
8 | "typescript.tsdk": "node_modules/typescript/lib"
9 | }
10 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ## Development setup
4 |
5 | Install dependencies:
6 |
7 | ```
8 | pnpm install
9 | ```
10 |
11 | Go to a package in `packages`.
12 |
13 | Build the library:
14 |
15 | ```
16 | pnpm run build
17 | ```
18 |
19 | Run tests:
20 |
21 | ```
22 | pnpm run test
23 | ```
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018-present, Guillaume Chau
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | // eslint.config.mjs
2 | import antfu from '@antfu/eslint-config'
3 |
4 | export default antfu({
5 | ignores: [
6 | 'node_modules/',
7 | 'dist/',
8 | 'generated/',
9 | '!.*',
10 | 'schema.graphql',
11 | '.test-todo/',
12 | '**/types/test/',
13 | ],
14 |
15 | rules: {
16 | 'ts/no-use-before-define': 'warn',
17 | 'unused-imports/no-unused-vars': 'warn',
18 | 'accessor-pairs': 'off',
19 | },
20 | }, {
21 | files: [
22 | 'packages/docs/**',
23 | ],
24 | rules: {
25 | 'no-dupe-keys': 'off',
26 | 'no-new': 'off',
27 | 'no-console': 'off',
28 | },
29 | }, {
30 | files: [
31 | 'packages/test-*/**',
32 | '**/*.test.*',
33 | ],
34 | rules: {
35 | 'antfu/no-top-level-await': 'off',
36 | 'no-console': 'off',
37 | 'unused-imports/no-unused-vars': 'off',
38 | 'node/prefer-global/process': 'off',
39 | 'import/no-mutable-exports': 'off',
40 | },
41 |
42 | languageOptions: {
43 | globals: {
44 | cy: false,
45 | expect: false,
46 | describe: false,
47 | it: false,
48 | before: false,
49 | },
50 | },
51 | }, {
52 | files: [
53 | '**/tests/types/**',
54 | ],
55 | rules: {
56 | 'ts/no-unused-expressions': 'off',
57 | },
58 | })
59 |
--------------------------------------------------------------------------------
/packages/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "private-vue-apollo-docs",
3 | "type": "module",
4 | "version": "4.0.0-alpha.16",
5 | "private": true,
6 | "scripts": {
7 | "dev": "vitepress dev src",
8 | "build": "vitepress build src"
9 | },
10 | "dependencies": {
11 | "vue-github-button": "^3.0.3"
12 | },
13 | "devDependencies": {
14 | "vitepress": "^1.0.0-rc.36"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/docs/src/.vitepress/theme/components/SponsorButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/packages/docs/src/.vitepress/theme/index.js:
--------------------------------------------------------------------------------
1 | import DefaultTheme from 'vitepress/theme'
2 | import SponsorButton from './components/SponsorButton.vue'
3 |
4 | import './styles/index.pcss'
5 |
6 | export default {
7 | ...DefaultTheme,
8 | enhanceApp({ app }) {
9 | app.component('SponsorButton', SponsorButton)
10 | },
11 | }
12 |
--------------------------------------------------------------------------------
/packages/docs/src/.vitepress/theme/styles/index.pcss:
--------------------------------------------------------------------------------
1 | :root {
2 | --vp-c-brand-1: #5591d8;
3 | --vp-c-brand-2: #336cb0;
4 | --vp-c-brand-3: #1f4c80;
5 | --vp-c-brand-soft: rgba(42, 95, 156, 0.14);
6 | }
7 |
--------------------------------------------------------------------------------
/packages/docs/src/api/apollo-provider.md:
--------------------------------------------------------------------------------
1 | # createApolloProvider
2 |
3 | ## Example
4 |
5 | ```js
6 | import { createApolloProvider } from '@vue/apollo-option'
7 |
8 | const apolloProvider = createApolloProvider({
9 | // Multiple clients support
10 | // Use the 'client' option inside queries
11 | // or '$client' on the apollo definition
12 | clients: {
13 | a: apolloClientA,
14 | b: apolloClientB,
15 | },
16 | // Default client
17 | defaultClient: apolloClient,
18 | // Default 'apollo' definition
19 | defaultOptions: {
20 | // See 'apollo' definition
21 | // For example: default query options
22 | $query: {
23 | loadingKey: 'loading',
24 | fetchPolicy: 'cache-and-network',
25 | },
26 | },
27 | // Watch loading state for all queries
28 | // See 'Smart Query > options > watchLoading' for detail
29 | watchLoading(isLoading, countModifier) {
30 | loading += countModifier
31 | console.log('Global loading', loading, countModifier)
32 | },
33 | // Global error handler for all smart queries and subscriptions
34 | errorHandler(error) {
35 | console.log('Global error handler')
36 | console.error(error)
37 | },
38 | // Globally turn off prefetch ssr
39 | prefetch: Boolean,
40 | })
41 | ```
42 |
43 | Use the apollo provider into your Vue app:
44 |
45 | ```js
46 | const app = createApp({ /* ... */ })
47 | app.use(apolloProvider)
48 | ```
49 |
--------------------------------------------------------------------------------
/packages/docs/src/api/dollar-apollo.md:
--------------------------------------------------------------------------------
1 | # Dollar Apollo
2 |
3 | This is the Apollo manager added to any component that uses Apollo. It can be accessed inside a component with `this.$apollo`.
4 |
5 | ## Properties
6 |
7 | - `vm`: related component
8 | - `queries`: object map of the component's Reactive Queries.
9 | - `subscriptions`: object map of the component's Reactive Subscriptions.
10 | - `provider`: injected [Apollo Provider](./apollo-provider.md).
11 | - `loading`: whether at least one query is loading.
12 | - `skipAllQueries`: (setter) boolean to pause or unpause all Reactive Queries.
13 | - `skipAllSubscriptions`: (setter) boolean to pause or unpause all Reactive Subscriptions.
14 | - `skipAll`: (setter) boolean to pause or unpause all Reactive Queries and Reactive Subscriptions.
15 |
16 | ## Methods
17 |
18 | - `query`: execute a query (see [Queries](../guide-option/queries.md)).
19 | - `mutate`: execute a mutation (see [Mutations](../guide-option/mutations.md)).
20 | - `subscribe`: standard Apollo subscribe method (see [Subscriptions](../guide-option/subscriptions.md)).
21 | - `addSmartQuery`: manually add a Reactive Query (not recommended).
22 | - `addSmartSubscription`: add a Reactive Subscription (see [Subscriptions](../guide-option/subscriptions.md)).
23 | - `getClient`: returns the underlying ApolloClient.
24 |
--------------------------------------------------------------------------------
/packages/docs/src/api/index.md:
--------------------------------------------------------------------------------
1 | # API Reference
2 |
3 | Welcome to the API Reference!
4 |
--------------------------------------------------------------------------------
/packages/docs/src/api/ssr.md:
--------------------------------------------------------------------------------
1 | # ApolloSSR
2 |
3 | ## Usage
4 |
5 | See [SSR guide](../guide-advanced/ssr.md).
6 |
7 | ## Methods
8 |
9 | ### getStates
10 |
11 | Returns the apollo stores states as JavaScript objects.
12 |
13 | ```js
14 | const states = ApolloSSR.getStates(clientsObject, options)
15 | ```
16 |
17 | `options` defaults to:
18 |
19 | ```js
20 | const defaultOptions = {
21 | // Prefix for the keys of each apollo client state
22 | exportNamespace: '',
23 | }
24 | ```
25 |
26 | ### exportStates
27 |
28 | Returns the apollo stores states as JavaScript code inside a String. This code can be directly injected to the page HTML inside a `
34 | ```
35 |
--------------------------------------------------------------------------------
/packages/docs/src/api/use-lazy-query.md:
--------------------------------------------------------------------------------
1 | # useLazyQuery
2 |
3 | Extends [useQuery](./use-query.md)
4 |
5 | ## Additional Return
6 |
7 | - `load(document?, variables?, options?)`: function to start querying. Returns `Promise` if it is the first time the query is called, `false` otherwise.
8 |
9 | Example:
10 |
11 | ```js
12 | const { load, refetch } = useLazyQuery(query, variables, options)
13 |
14 | function fetchOrRefetch() {
15 | load() || refetch()
16 | }
17 |
18 | async function waitForLoad() {
19 | try {
20 | const result = await load()
21 | // do something with result
22 | }
23 | catch (error) {
24 | // handle error
25 | }
26 | }
27 | ```
28 |
--------------------------------------------------------------------------------
/packages/docs/src/guide-advanced/index.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | This guide is a collection of advanced topic articles.
4 |
--------------------------------------------------------------------------------
/packages/docs/src/guide-components/index.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | ## What are Apollo components?
4 |
5 | Those are components just like any others. They take a GraphQL document in their prop and use the [scoped slot feature](https://vuejs.org/v2/guide-components-slots.html#Scoped-Slots) to pass down the results.
6 |
7 | The benefit is that you can use those components in the template directly instead of using the `apollo` option of your component. In some cases you don't even need to add a script part at all in your `.vue`! This is all even more declarative.
8 |
9 | Here is a quick example of an [ApolloQuery](./query.md) in a template:
10 |
11 | ```vue
12 |
13 |
14 |
18 |
19 | Loading...
20 |
21 |
22 | {{ user.name }}
23 |
24 |
25 |
26 |
27 |
28 |
29 | ```
30 |
--------------------------------------------------------------------------------
/packages/docs/src/guide-composable/cache-interaction.md:
--------------------------------------------------------------------------------
1 | # Interacting with cached data
2 |
3 | This section is not available yet.
4 |
5 | In the meantime, see [react apollo docs](https://www.apollographql.com/docs/react/caching/cache-interaction/).
6 |
--------------------------------------------------------------------------------
/packages/docs/src/guide-composable/index.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | The Composition API is an API where you write data and logic in an easily composable way inside the `setup` option.
4 |
5 | If you are using Typescript, it is strongly recommended to start using the Composition API as its typing capabilities are unmatched by any other Vue API.
6 |
7 | Learn more about the Composition API [here](https://vue-composition-api-rfc.netlify.com/).
8 |
9 | Here is an example using this API:
10 |
11 | ```vue
12 |
26 | ```
27 |
--------------------------------------------------------------------------------
/packages/docs/src/guide-option/index.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | The Option API is based on the `apollo` Vue component option.
4 |
5 | For example:
6 |
7 | ```vue
8 |
15 | ```
16 |
--------------------------------------------------------------------------------
/packages/docs/src/guide-option/setup.md:
--------------------------------------------------------------------------------
1 | # Setup
2 |
3 | Make sure you have [installed Apollo Client](../guide/installation.md).
4 |
5 | ## 1. Install @vue/apollo-option
6 |
7 | ```
8 | npm install --save @vue/apollo-option
9 | ```
10 |
11 | Or:
12 |
13 | ```
14 | yarn add @vue/apollo-option
15 | ```
16 |
17 | ## 2. Create the Apollo client
18 |
19 | ```js
20 | import { ApolloClient, InMemoryCache } from '@apollo/client/core'
21 |
22 | const cache = new InMemoryCache()
23 |
24 | const apolloClient = new ApolloClient({
25 | cache,
26 | uri: 'http://localhost:4042/graphql',
27 | })
28 | ```
29 |
30 | ::: warning
31 | Use the `@apollo/client/core` import path otherwise you will also import React.
32 | :::
33 |
34 | ## 3. Create the Apollo provider
35 |
36 | The provider holds the Apollo client instances that can then be used by all the child components.
37 |
38 | ```js
39 | import { createApolloProvider } from '@vue/apollo-option'
40 |
41 | const apolloProvider = createApolloProvider({
42 | defaultClient: apolloClient,
43 | })
44 | ```
45 |
46 | ## 4. Add the provider to your app
47 |
48 | Add it to your app with the `app.use` function:
49 |
50 | ```js
51 | import { createApp, h } from 'vue'
52 |
53 | const app = createApp({
54 | render: () => h(App),
55 | })
56 |
57 | app.use(apolloProvider)
58 | ```
59 |
60 | You are now ready to use Apollo in your components!
61 |
--------------------------------------------------------------------------------
/packages/docs/src/guide-option/usage.md:
--------------------------------------------------------------------------------
1 | # Usage in Vue components
2 |
3 | After installing `vue-apollo` in your app, all your components can now use Apollo through the `apollo` special option.
4 |
5 | ## `apollo` options
6 |
7 | To declare apollo queries in your Vue component, add the `apollo` object in the component options:
8 |
9 | ```js
10 | new Vue({
11 | apollo: {
12 | // Apollo specific options
13 | },
14 | })
15 | ```
16 |
17 | In a `.vue` file:
18 |
19 | ```vue
20 |
21 | My component
22 |
23 |
24 |
31 | ```
32 |
33 | ### Special options
34 |
35 | In the `apollo` option, there are special options that begin with `$` in the `apollo` object.
36 |
37 | Learn more about those special options in the [Special options section](./special-options.md).
38 |
39 | ## `$apollo`
40 |
41 | All the components under the one which has the `apolloProvider` option have an `$apollo` helper available. This is the glue between your component and Apollo and it does all the heavy lifting for you (including automatic updates and teardowns).
42 |
43 | You can access the [apollo-client](https://www.apollographql.com/docs/react/) instances with `this.$apollo.provider.defaultClient` or `this.$apollo.provider.clients.` (for [Multiple clients](./multiple-clients.md)) in all your vue components.
44 |
45 | If you are curious, see [$apollo API](../api/dollar-apollo.md).
46 |
--------------------------------------------------------------------------------
/packages/docs/src/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 | hero:
4 | name: Vue Apollo
5 | text: GraphQL
6 | tagline: Effortless GraphQL in your Vue app!
7 | image:
8 | src: /hero.svg
9 | alt: Vue Apollo
10 | actions:
11 | - theme: brand
12 | text: Get Started
13 | link: /guide/
14 | features:
15 | - title: Automatic updates
16 | details: Don't think about updating the UI or refetching the queries!
17 | icon: ✨
18 | - title: Supports all Vue APIs
19 | details: Option API, Composition API or Components
20 | icon: 🧩
21 | - title: SSR-ready
22 | details: Run your queries on the server before rendering the page HTML
23 | icon: 🌐
24 | ---
25 |
26 |
27 |
28 | Sponsors
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/packages/docs/src/public/error-log.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuejs/apollo/fb027e6adf4d4129fb26f8c918060771a0afd59b/packages/docs/src/public/error-log.jpeg
--------------------------------------------------------------------------------
/packages/docs/src/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuejs/apollo/fb027e6adf4d4129fb26f8c918060771a0afd59b/packages/docs/src/public/favicon.png
--------------------------------------------------------------------------------
/packages/docs/src/public/vue-apollo-graphql.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuejs/apollo/fb027e6adf4d4129fb26f8c918060771a0afd59b/packages/docs/src/public/vue-apollo-graphql.png
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/api/apollo-provider.md:
--------------------------------------------------------------------------------
1 | # ApolloProvider
2 |
3 | ## 构造函数
4 |
5 | ```js
6 | const apolloProvider = createApolloProvider({
7 | // 支持多客户端
8 | // 在查询中使用 'client' 选项
9 | // 或在 apollo 定义中使用 '$client'
10 | clients: {
11 | a: apolloClientA,
12 | b: apolloClientB,
13 | },
14 | // 默认客户端
15 | defaultClient: apolloClient,
16 | // 'apollo' 对象的默认定义
17 | defaultOptions: {
18 | // 详见 'apollo' 的定义
19 | // 例如:默认查询选项
20 | $query: {
21 | loadingKey: 'loading',
22 | fetchPolicy: 'cache-and-network',
23 | },
24 | },
25 | // 查看所有查询的加载状态
26 | // 详见 '智能查询 > 选项 > watchLoading'
27 | watchLoading(isLoading, countModifier) {
28 | loading += countModifier
29 | console.log('Global loading', loading, countModifier)
30 | },
31 | // 所有智能查询和订阅的全局错误处理函数
32 | errorHandler(error) {
33 | console.log('Global error handler')
34 | console.error(error)
35 | },
36 | // 全局关闭 ssr 的预取
37 | prefetch: Boolean,
38 | })
39 | ```
40 |
41 | 在你的 Vue 应用程序中使用 apollo provider:
42 |
43 | ```js
44 | new Vue({
45 | el: '#app',
46 | apolloProvider,
47 | render: h => h(App),
48 | })
49 | ```
50 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/api/apollo-subscribe-to-more.md:
--------------------------------------------------------------------------------
1 | # ApolloSubscribeToMore 组件
2 |
3 | 示例:
4 |
5 | ```vue
6 |
7 |
8 |
23 |
24 |
25 |
26 |
27 |
28 |
49 | ```
50 |
51 | ## Props
52 |
53 | - `document`:包含订阅的 GraphQL 文档,或一个接收 `gql` 标签作为参数并返回转换后的文档的函数。
54 | - `variables`:将自动更新订阅变量的对象。
55 | - `updateQuery`:可以根据需要更新查询结果的函数。
56 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/api/dollar-apollo.md:
--------------------------------------------------------------------------------
1 | # Dollar Apollo
2 |
3 | 这是添加到任何使用 Apollo 的组件中的 Apollo 管理器。它可以在一个组件内通过 `this.$apollo` 访问到。
4 |
5 | ## 属性
6 |
7 | - `vm`:关联的组件。
8 | - `queries`:组件的智能查询的数组。
9 | - `subscriptions`:组件的智能订阅的数组。
10 | - `provider`:注入的 [Apollo Provider](./apollo-provider.md)。
11 | - `loading`:是否至少有一个查询正在加载。
12 | - `skipAllQueries`:(setter) 布尔值,用于暂停或取消暂停所有智能查询。
13 | - `skipAllSubscriptions`:(setter) 布尔值,用于暂停或取消暂停所有智能订阅。
14 | - `skipAll`:(setter) 布尔值,用于暂停或取消暂停所有智能查询和智能订阅。
15 |
16 | ## 方法
17 |
18 | - `query`:执行一个查询(详见 [查询](../guide-option/queries.md))。
19 | - `mutate`:执行一个变更(详见 [变更](../guide-option/mutations.md))。
20 | - `subscribe`:标准的 Apollo 订阅方法(详见 [订阅](../guide-option/subscriptions.md))。
21 | - `addSmartQuery`:手动添加一个智能查询(不推荐使用)。
22 | - `addSmartSubscription`:添加一个智能订阅(详见 [订阅](../guide-option/subscriptions.md))。
23 | - `getClient`:返回底层的 ApolloClient。
24 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/api/index.md:
--------------------------------------------------------------------------------
1 | # API 参考
2 |
3 | 欢迎查看 API 参考!
4 |
5 | ::: warning Work-in-Progress
6 | 如果你发现缺少了某些东西,请创建一个代码合并请求!
7 | :::
8 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/api/smart-subscription.md:
--------------------------------------------------------------------------------
1 | # 智能订阅
2 |
3 | 每个在组件中的 `apollo.$subscribe` 选项中声明的订阅都会创建一个智能订阅对象。
4 |
5 | ## 选项
6 |
7 | - `query`:GraphQL 文档(可以是一个文件或一个 `gql` 字符串)。
8 | - `variables`:对象或返回对象的响应式函数。每个键将用 `'$'` 映射到 GraphQL 文档中,例如 `foo` 将变为 `$foo`。
9 | - `throttle`:变量更新节流时间(毫秒)。
10 | - `debounce`:变量更新防抖时间(毫秒)。
11 | - `result(data, key)` 是收到结果时调用的钩子。
12 | - `error(error)` 是有错误时调用的钩子。`error` 是一个具有 `graphQLErrors` 属性或 `networkError` 属性的 Apollo 错误对象。
13 | - `skip` 是一个布尔值或一个返回布尔值的(响应式)函数。该函数的参数一个是当前组件,另一个是智能查询的键名,因此可以在 `$query` 或是 `ApolloProvider` 的 `defaultOptions` 中使用。
14 |
15 | ## 属性
16 |
17 | ### skip
18 |
19 | 你可以使用 `skip` 来暂停或停止暂停:
20 |
21 | ```js
22 | this.$apollo.subscriptions.users.skip = true
23 | ```
24 |
25 | ## 方法
26 |
27 | ### refresh
28 |
29 | 停止并重新启动查询:
30 |
31 | ```js
32 | this.$apollo.subscriptions.users.refresh()
33 | ```
34 |
35 | ### start
36 |
37 | 开始查询:
38 |
39 | ```js
40 | this.$apollo.subscriptions.users.start()
41 | ```
42 |
43 | ### stop
44 |
45 | 停止查询:
46 |
47 | ```js
48 | this.$apollo.subscriptions.users.stop()
49 | ```
50 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/api/ssr.md:
--------------------------------------------------------------------------------
1 | # ApolloSSR
2 |
3 | ## 用法
4 |
5 | 详见 [SSR 指南](../guide-advanced/ssr.md)。
6 |
7 | ## 方法
8 |
9 | ### getStates
10 |
11 | 将 apollo store 状态作为 JavaScript 对象返回。
12 |
13 | ```js
14 | const states = ApolloSSR.getStates(apolloProvider, options)
15 | ```
16 |
17 | `options` 的默认值是:
18 |
19 | ```js
20 | const defaultOptions = {
21 | // 每个 apollo 客户端状态的 key 的前缀
22 | exportNamespace: '',
23 | }
24 | ```
25 |
26 | ### exportStates
27 |
28 | 将 apollo store 状态作为字符串内的 JavaScript 代码返回。该代码可以直接注入到页面 HTML 的 `
34 | ```
35 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/api/use-subscription.md:
--------------------------------------------------------------------------------
1 | # useSubscription
2 |
3 | ## 参数
4 |
5 | - `document`:包含订阅的 GraphQL 文档。也可以是一个 `Ref` 或是一个返回文档的函数(将会是响应式的)。
6 |
7 | - `variables`:(默认值:`null`)变量对象。也可以是一个 `Ref` 、一个响应式对象或是一个返回变量对象的函数。
8 |
9 | - `options`:(默认值:`null`)选项对象。也可以是一个 `Ref` 、一个响应式对象或是一个返回选项对象的函数。
10 |
11 | - `clientId`:当提供了多个客户端时,指定使用的客户端 ID。
12 |
13 | - `debounce`:防抖间隔毫秒数。
14 |
15 | - `enabled`:布尔值 `Ref`,用于启用或禁用查询。
16 |
17 | - `fetchPolicy`:自定义缓存行为。
18 | - `cache-first`(默认):从缓存返回结果。仅当无法获得缓存结果时才从网络获取。
19 | - `cache-and-network`:首先从缓存中返回结果(如果存在),然后在网络可用时返回网络结果。
20 | - `cache-only`:从缓存返回结果(如果可用),否则失败。
21 | - `network-only`:从网络返回结果并保存到缓存,如果网络调用未成功则失败。
22 | - `no-cache`:从网络返回结果但不保存到缓存,如果网络调用未成功则失败。
23 |
24 | - `throttle`:节流间隔毫秒数。
25 |
26 | ## 返回值
27 |
28 | - `result`:结果数据对象。
29 |
30 | - `loading`:布尔值 Ref,当订阅正在进行中时为 `true`。
31 |
32 | - `error`:Error Ref,保存任何发生的错误。
33 |
34 | - `variables`:Ref,保存变量对象。
35 |
36 | - `onResult(handler)`:有新结果可用时调用的事件钩子。
37 |
38 | - `onError(handler)`:发生错误时调用的事件钩子。
39 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-advanced/index.md:
--------------------------------------------------------------------------------
1 | # 简介
2 |
3 | 这一部分指南是进阶主题文章的集合。
4 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-components/index.md:
--------------------------------------------------------------------------------
1 | # 简介
2 |
3 | ## 什么是 Apollo 组件?
4 |
5 | 这些组件就像其他组件一样。它们在 prop 中使用 GraphQL 文档,并使用 [作用域插槽功能](https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots) 来传递结果。
6 |
7 | 这样做的好处是你可以直接在模板中使用这些组件,而不是使用组件的 `apollo` 选项。在某些情况下,你甚至不需要在 `.vue` 中添加脚本部分!这种代码会更加声明式。
8 |
9 | 这是一个模板中 [ApolloQuery](./query.md) 的简单示例:
10 |
11 | ```vue
12 |
13 |
14 |
15 |
16 |
17 |
18 | Loading...
19 |
20 |
21 | {{ user.name }}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | ```
30 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-components/setup.md:
--------------------------------------------------------------------------------
1 | # Setup
2 |
3 | 确保你已经 [安装了 Apollo Client](../guide/installation.md)。
4 |
5 | ## 1. 安装 @vue/apollo-components
6 |
7 | ```
8 | npm install --save @vue/apollo-option @vue/apollo-components
9 | ```
10 |
11 | 或:
12 |
13 | ```
14 | yarn add @vue/apollo-option @vue/apollo-components
15 | ```
16 |
17 | ## 2. Create the Apollo client
18 |
19 | ```js
20 | import { ApolloClient, InMemoryCache } from '@apollo/client/core'
21 |
22 | const cache = new InMemoryCache()
23 |
24 | const apolloClient = new ApolloClient({
25 | cache,
26 | uri: 'http://localhost:4042/graphql',
27 | })
28 | ```
29 |
30 | ::: warning
31 | Use the `@apollo/client/core` import path otherwise you will also import React.
32 | :::
33 |
34 | ## 3. Create the Apollo provider
35 |
36 | The provider holds the Apollo client instances that can then be used by all the child components.
37 |
38 | ```js
39 | const apolloProvider = createApolloProvider({
40 | defaultClient: apolloClient,
41 | })
42 | ```
43 | ## 4. Add the provider to your app
44 |
45 | Add it to your app with the `app.use` function:
46 |
47 | ```js
48 | import { createApp, h } from 'vue'
49 |
50 | const app = createApp({
51 | render: () => h(App),
52 | })
53 |
54 | app.use(apolloProvider)
55 | ```
56 |
57 | ## 5. Add the components to your app
58 |
59 | ```js
60 | import VueApolloComponents from '@vue/apollo-components'
61 |
62 | // ...
63 |
64 | app.use(VueApolloComponents)
65 | ```
66 |
67 | 现在你已经完成了在组件中使用 Apollo 的所有准备了!
68 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-composable/cache-interaction.md:
--------------------------------------------------------------------------------
1 | # 与缓存的数据进行交互
2 |
3 | 当前章节尚未完成。
4 |
5 | 在此期间,可参阅 [react apollo 文档](https://www.apollographql.com/docs/react/caching/cache-interaction/)。
6 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-composable/index.md:
--------------------------------------------------------------------------------
1 | # 简介
2 |
3 | 组合 API 是一种让你可以在 `setup` 选项中的以容易组合的方式编写数据和逻辑的 API。
4 |
5 | 如果你正在使用 Typescript,强烈建议开始使用组合 API,因为它的类型能力是任何其他 Vue API 都无法比拟的。
6 |
7 | [在这里](https://vue-composition-api-rfc.netlify.com/) 了解更多关于组合 API 的信息。
8 |
9 | 这里是一个使用该 API 的示例:
10 |
11 | ```vue
12 |
26 | ```
27 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-composable/setup.md:
--------------------------------------------------------------------------------
1 | # Setup
2 |
3 | 确保你已经 [安装了 Apollo Client](../guide/installation.md)。
4 |
5 | ## 1. 安装 @vue/apollo-composable
6 |
7 | ```shell
8 | npm install --save @vue/apollo-composable
9 | ```
10 |
11 | 或:
12 |
13 | ```shell
14 | yarn add @vue/apollo-composable
15 | ```
16 |
17 | ## 2. 连接 Apollo Client 到 Vue
18 |
19 | 你需要在根实例中提供一个默认的 Apollo Client 实例:
20 |
21 | ```js
22 | import { DefaultApolloClient } from '@vue/apollo-composable'
23 | import { provide } from 'vue'
24 |
25 | const app = new Vue({
26 | setup() {
27 | provide(DefaultApolloClient, apolloClient)
28 | },
29 |
30 | render: h => h(App),
31 | })
32 | ```
33 |
34 | ### 多客户端
35 |
36 | 你也可以提供为应用提供多个可用的 Apollo Client 实例。在这种情况下,建议提供一个 `default` 值:
37 |
38 | ```js
39 | import { ApolloClients } from '@vue/apollo-composable'
40 | import { provide } from 'vue'
41 |
42 | const app = new Vue({
43 | setup() {
44 | provide(ApolloClients, {
45 | default: apolloClient,
46 | })
47 | },
48 |
49 | render: h => h(App),
50 | })
51 | ```
52 |
53 | 你可以在旁边添加其他客户端实例:
54 |
55 | ```js
56 | provide(ApolloClients, {
57 | default: apolloClient,
58 | clientA: apolloClientA,
59 | clientB: apolloClientB,
60 | })
61 | ```
62 |
63 | 然后,你可以在函数中通过 `clientId` 选项来选择其中的一个使用(例如`useQuery`、`useMutation` 和 `useSubscription`)。
64 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-option/index.md:
--------------------------------------------------------------------------------
1 | # 简介
2 |
3 | 选项 API 基于 `apollo` Vue 组件选项。
4 |
5 | 示例:
6 |
7 | ```vue
8 |
15 | ```
16 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-option/setup.md:
--------------------------------------------------------------------------------
1 | # Setup
2 |
3 | 确保你已经 [安装了 Apollo Client](../guide/installation.md)。
4 |
5 | ## 1. 安装 @vue/apollo-option
6 |
7 | ```
8 | npm install --save @vue/apollo-option
9 | ```
10 |
11 | 或:
12 |
13 | ```
14 | yarn add @vue/apollo-option
15 | ```
16 |
17 | ## 2. Create the Apollo client
18 |
19 | ```js
20 | import { ApolloClient, InMemoryCache } from '@apollo/client/core'
21 |
22 | const cache = new InMemoryCache()
23 |
24 | const apolloClient = new ApolloClient({
25 | cache,
26 | uri: 'http://localhost:4042/graphql',
27 | })
28 | ```
29 |
30 | ::: warning
31 | Use the `@apollo/client/core` import path otherwise you will also import React.
32 | :::
33 |
34 | ## 3. 注入 Apollo provider
35 |
36 | Provider 保存了可以在接下来被所有子组件使用的 Apollo 客户端实例。
37 |
38 | ```js
39 | import { createApolloProvider } from '@vue/apollo-option'
40 |
41 | const apolloProvider = createApolloProvider({
42 | defaultClient: apolloClient,
43 | })
44 | ```
45 |
46 | ## 4. Add the provider to your app
47 |
48 | 使用 `apolloProvider` 选项将它添加到你的应用程序:
49 |
50 | ```js
51 | import { createApp, h } from 'vue'
52 |
53 | const app = createApp({
54 | render: () => h(App),
55 | })
56 |
57 | app.use(apolloProvider)
58 | ```
59 |
60 | 现在你已经完成了在组件中使用 Apollo 的所有准备了!
61 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/guide-option/usage.md:
--------------------------------------------------------------------------------
1 | # 在 Vue 组件中的用法
2 |
3 | 在你的应用中安装了 `vue-apollo` 之后,所有组件都可以通过 `apollo` 这一特殊选项来使用 Apollo。
4 |
5 | ## `apollo` 选项
6 |
7 | 要在你的 Vue 组件中声明 apollo 查询,在组件的选项中添加 `apollo` 对象:
8 |
9 | ```js
10 | new Vue({
11 | apollo: {
12 | // Apollo 的具体选项
13 | },
14 | })
15 | ```
16 |
17 | 在一个 `.vue` 文件中:
18 |
19 | ```vue
20 |
21 | My component
22 |
23 |
24 |
31 | ```
32 |
33 | ## 特殊选项
34 |
35 | `apollo` 对象中的特殊选项以 `$` 开头表示。
36 |
37 | 请查看 [特殊选项](./special-options.md) 一章以了解更多。
38 |
39 | ## `$apollo`
40 |
41 | 在一个有着 `apolloProvider` 选项的组件之下的所有组件都可以使用一个 `$apollo` 辅助函数。这是你的组件和 Apollo 之间的胶水层,它可以为你完成所有繁重的工作(包括自动更新和销毁)。
42 |
43 | 在你的每个 vue 组件中,你都可以通过 `this.$apollo.provider.defaultClient` 或 `this.$apollo.provider.clients.`(用于 [多客户端](./multiple-clients.md))来访问 [apollo-client](https://www.apollographql.com/docs/react/) 实例。
44 |
45 | 如果你很好奇,请查看 [$apollo API](../api/dollar-apollo.md)。
46 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | sidebar: false
4 | heroImage: /logo.png
5 | actionText: 由此起步 →
6 | actionLink: /zh-cn/guide/
7 | features:
8 | - title: 自动更新
9 | details: 无需考虑更新 UI 或重新获取查询的问题!
10 | - title: 模板内组件
11 | details: 通过 Apollo 组件声明式地使用 Apollo
12 | - title: 支持 SSR
13 | details: 在渲染 HTML 页面之前在服务端运行你的查询
14 | footer: LICENCE MIT - Created by Guillaume CHAU (@Akryum)
15 | ---
16 |
17 |
18 |
19 | ## 赞助商
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | ::: tip 当前版本
28 | 中文文档现在同步至 v4.0.0-alpha.12
29 | :::
30 |
--------------------------------------------------------------------------------
/packages/docs/src/zh-cn/migration/index.md:
--------------------------------------------------------------------------------
1 | # 从 vue-apollo 3 迁移
2 |
3 | 当前章节尚未完成。
4 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | trim_trailing_whitespace = true
5 | insert_final_newline = true
6 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | /tests/e2e/videos/
6 | /tests/e2e/screenshots/
7 | /tests/e2e/downloads/
8 |
9 |
10 | # local env files
11 | .env.local
12 | .env.*.local
13 |
14 | # Log files
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 | pnpm-debug.log*
19 |
20 | # Editor directories and files
21 | .idea
22 | .vscode
23 | *.suo
24 | *.ntvs*
25 | *.njsproj
26 | *.sln
27 | *.sw?
28 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/README.md:
--------------------------------------------------------------------------------
1 | # test-e2e-global-composable-vue3
2 |
3 | ## Project setup
4 | ```
5 | pnpm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | pnpm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | pnpm run build
16 | ```
17 |
18 | ### Run your end-to-end tests
19 | ```
20 | pnpm run test:e2e
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { defineConfig } from 'cypress'
3 | import vitePreprocessor from 'cypress-vite'
4 |
5 | export default defineConfig({
6 | fixturesFolder: 'tests/e2e/fixtures',
7 | screenshotsFolder: 'tests/e2e/screenshots',
8 | videosFolder: 'tests/e2e/videos',
9 | downloadsFolder: 'tests/e2e/downloads',
10 | e2e: {
11 | baseUrl: 'http://localhost:8080',
12 | // We've imported your old cypress plugins here.
13 | // You may want to clean this up later by importing these.
14 | setupNodeEvents(on) {
15 | on('task', {
16 | 'db:reset': async function () {
17 | await axios.get('http://localhost:4042/_reset')
18 | return true
19 | },
20 | })
21 | on('file:preprocessor', vitePreprocessor())
22 | },
23 | specPattern: 'tests/e2e/specs/**/*.cy.{js,jsx,ts,tsx}',
24 | supportFile: 'tests/e2e/support/index.ts',
25 | },
26 | })
27 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | We're sorry but dashboard doesn't work properly without JavaScript enabled. Please enable it to continue.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/apollo.ts:
--------------------------------------------------------------------------------
1 | import { ApolloClient, createHttpLink, InMemoryCache, split } from '@apollo/client/core'
2 | import { onError } from '@apollo/client/link/error'
3 | import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
4 | import { getMainDefinition } from '@apollo/client/utilities'
5 | import { logErrorMessages } from '@vue/apollo-util'
6 | import { createClient } from 'graphql-ws'
7 |
8 | const cache = new InMemoryCache()
9 |
10 | // HTTP connection to the API
11 | const httpLink = createHttpLink({
12 | // You should use an absolute URL here
13 | uri: 'http://localhost:4042/graphql',
14 | })
15 |
16 | const wsLink = new GraphQLWsLink(createClient({
17 | url: 'ws://localhost:4042/graphql',
18 | }))
19 |
20 | const splitLink = split(
21 | ({ query }) => {
22 | const definition = getMainDefinition(query)
23 | if (definition.kind === 'OperationDefinition'
24 | && definition.operation === 'subscription') {
25 | console.log(`Subscribing to ${definition.name?.value ?? 'anonymous'}`)
26 | }
27 | return (
28 | definition.kind === 'OperationDefinition'
29 | && definition.operation === 'subscription'
30 | )
31 | },
32 | wsLink,
33 | httpLink,
34 | )
35 |
36 | // Handle errors
37 | const errorLink = onError((error) => {
38 | logErrorMessages(error)
39 | })
40 |
41 | export const apolloClient = new ApolloClient({
42 | cache,
43 | link: errorLink.concat(splitLink),
44 | })
45 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/assets/styles/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 |
3 | @tailwind components;
4 |
5 | @tailwind utilities;
6 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/App.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/ChannelList.vue:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
31 | Loading channels...
32 |
33 |
34 |
62 |
63 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/ChannelListPinia.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 | Loading channels...
13 |
14 |
15 |
43 |
44 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/ChannelListPinia2.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
51 |
52 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/ChannelListPiniaContainer.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
15 | Toggle ChannelListPinia component
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/GlobalLoading.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 | Global loading...
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/LazyQuery.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 |
32 | Load list
33 |
34 |
35 |
36 | Refetched: {{ refetched }}
37 |
38 |
39 |
40 |
44 | Loading...
45 |
46 |
47 |
48 |
53 | {{ item }}
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/LazyQueryImmediately.vue:
--------------------------------------------------------------------------------
1 |
34 |
35 |
36 |
37 |
41 | Loading...
42 |
43 |
44 |
45 |
Loaded channel: {{ channel.label }}
46 |
Messages: {{ channel.messages.length }}
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/LazyQueryLoad.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
29 | Load list
30 |
31 |
32 |
33 |
37 | Loaded {{ result.length }}
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/LazyQueryLoadError.vue:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 |
31 |
32 |
36 | Load list
37 |
38 |
39 |
40 |
44 | Loaded {{ result.length }}
45 |
46 |
47 |
51 | Error: {{ error.message }}
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/MessageItem.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 | {{ message.text }}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/NoSetupQuery.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 | {{ hello }}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/NoSetupQueryMultiClient.vue:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 | {{ hello }}
34 |
35 |
36 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/NoSetupScopeQuery.vue:
--------------------------------------------------------------------------------
1 |
37 |
38 |
39 |
40 | {{ hello }}
41 |
42 |
43 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/OnResult.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
16 | Show child component
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/OnResultChild.vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
34 | Loading...
35 |
36 |
37 |
41 |
Loaded channel: {{ channel.label }}
42 |
Messages: {{ channel.messages.length }}
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/PartialError.vue:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 |
39 |
errorPolicy: '{{ errorPolicy }}' => {{ results[errorPolicy] }}
40 |
44 | {{ errors[errorPolicy] }}
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/Subscription.vue:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
25 |
30 | {{ message.text }}
31 |
32 |
33 |
34 | No messages yet
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/Subscriptions.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 | Subscription
10 |
11 |
12 |
13 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/components/Welcome.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Welcome
4 |
5 |
6 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/main.ts:
--------------------------------------------------------------------------------
1 | import { DefaultApolloClient } from '@vue/apollo-composable'
2 | import { createPinia } from 'pinia'
3 | import { createApp } from 'vue'
4 | import { apolloClient } from './apollo'
5 | import App from './components/App.vue'
6 | import { router } from './router'
7 | import '@/assets/styles/tailwind.css'
8 |
9 | const app = createApp(App)
10 | app.use(createPinia())
11 | app.use(router)
12 | app.provide(DefaultApolloClient, apolloClient)
13 | app.mount('#app')
14 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import type { DefineComponent } from 'vue'
3 |
4 | const component: DefineComponent
5 | export default component
6 | }
7 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/src/stores/channel.ts:
--------------------------------------------------------------------------------
1 | import { useQuery } from '@vue/apollo-composable'
2 | import gql from 'graphql-tag'
3 | import { defineStore } from 'pinia'
4 | import { computed, watch } from 'vue'
5 |
6 | interface Channel {
7 | id: string
8 | label: string
9 | }
10 |
11 | export const useChannels = defineStore('channel', () => {
12 | const query = useQuery<{ channels: Channel[] }>(gql`
13 | query channels {
14 | channels {
15 | id
16 | label
17 | }
18 | }
19 | `)
20 |
21 | const channels = computed(() => query.result.value?.channels ?? [])
22 |
23 | watch(query.loading, (value) => {
24 | console.log('loading', value)
25 | }, {
26 | immediate: true,
27 | })
28 |
29 | return {
30 | loading: query.loading,
31 | channels,
32 | }
33 | })
34 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | }
9 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | 'cypress',
4 | ],
5 | env: {
6 | 'mocha': true,
7 | 'cypress/globals': true,
8 | },
9 | rules: {
10 | strict: 'off',
11 | },
12 | }
13 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/specs/errorPolicy.cy.ts:
--------------------------------------------------------------------------------
1 | describe('errorPolicy', () => {
2 | it('supports `errorPolicy` option', () => {
3 | cy.visit('/partial-error')
4 |
5 | // All
6 | cy.get('.all .result').should('contain', '"good": "good"').should('contain', '"bad": null')
7 | cy.get('.all .error').should('contain', 'Error: GraphQL response contains errors: An error')
8 |
9 | // None
10 | cy.get('.none .result').should('not.contain', 'good').should('not.contain', 'bad')
11 | cy.get('.none .error').should('contain', 'Error: An error')
12 |
13 | // Ignore
14 | cy.get('.ignore .result').should('contain', '"good": "good"').should('contain', '"bad": null')
15 | cy.get('.ignore .error').should('not.exist')
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/specs/keepPreviousResult.cy.ts:
--------------------------------------------------------------------------------
1 | describe('keepPreviousResult', () => {
2 | beforeEach(() => {
3 | cy.task('db:reset')
4 | cy.visit('/keep-previous-result')
5 | })
6 |
7 | it('keepPreviousResult disabled: should clear previous data', () => {
8 | cy.get('.no-data').should('be.visible')
9 | cy.get('.channel-btn').eq(0).click()
10 | cy.get('.no-data').should('be.visible')
11 | cy.get('.the-channel').should('contain.text', '# General')
12 | cy.get('.no-data').should('not.exist')
13 | cy.get('.channel-btn').eq(1).click()
14 | cy.get('.no-data').should('be.visible')
15 | cy.get('.the-channel').should('contain.text', '# Random')
16 | cy.get('.no-data').should('not.exist')
17 | })
18 |
19 | it('keepPreviousResult enabled: should display previous channel', () => {
20 | cy.get('label').contains('keepPreviousResult').get('input[type="checkbox"]').check()
21 | cy.get('.no-data').should('be.visible')
22 | cy.get('.channel-btn').eq(0).click()
23 | cy.get('.no-data').should('be.visible')
24 | cy.get('.the-channel').should('contain.text', '# General')
25 | cy.get('.no-data').should('not.exist')
26 | cy.get('.channel-btn').eq(1).click()
27 | cy.get('.no-data').should('not.exist')
28 | cy.get('.the-channel').should('contain.text', '# General')
29 | cy.get('.the-channel').should('contain.text', '# Random')
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/specs/nullableQuery.cy.ts:
--------------------------------------------------------------------------------
1 | describe('nullableQuery', () => {
2 | beforeEach(() => {
3 | cy.task('db:reset')
4 | cy.visit('/null-query')
5 | })
6 |
7 | it('should enable useQuery only if query is non-null', () => {
8 | cy.get('button').should('exist')
9 | cy.wait(100)
10 | cy.get('[data-test-id="data"]').should('not.exist')
11 | cy.get('.loading').should('not.exist')
12 | cy.get('button').click()
13 | cy.get('[data-test-id="data"]').should('contain', 'Loaded channel: General')
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/specs/outsideComponent.cy.ts:
--------------------------------------------------------------------------------
1 | describe('Query outside of component', () => {
2 | beforeEach(() => {
3 | cy.task('db:reset')
4 | cy.visit('/')
5 | })
6 |
7 | it('supports queries outside of setup', () => {
8 | cy.visit('/no-setup-query')
9 | cy.contains('.no-setup-query', 'Hello world!')
10 | })
11 |
12 | it('supports queries outside of setup with multiple clients', () => {
13 | cy.visit('/no-setup-query-multi-client')
14 | cy.contains('.no-setup-query', 'Hello world!')
15 | })
16 |
17 | it('supports queries outside of setup but within scope', () => {
18 | cy.visit('/no-setup-scope-query')
19 | cy.contains('.no-setup-scope-query', 'Hello world!')
20 | })
21 | })
22 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/specs/pinia.cy.ts:
--------------------------------------------------------------------------------
1 | describe('Pinia', () => {
2 | beforeEach(() => {
3 | cy.task('db:reset')
4 | })
5 |
6 | it('with current instance', () => {
7 | cy.visit('/pinia')
8 | cy.get('.channel-link').should('have.lengthOf', 2)
9 | cy.contains('.channel-link', '# General')
10 | cy.contains('.channel-link', '# Random')
11 | })
12 |
13 | it('with effect scope only', () => {
14 | cy.visit('/pinia2')
15 | cy.get('.channel-link').should('have.lengthOf', 2)
16 | cy.contains('.channel-link', '# General')
17 | cy.contains('.channel-link', '# Random')
18 | })
19 |
20 | it('works after component unmount if used in pinia', () => {
21 | cy.visit('/pinia3')
22 | cy.get('[data-test-id="channel-list-container"]').should('exist')
23 | cy.get('[data-test-id="channel-list-toggle"]').first().click()
24 | cy.get('[data-test-id="channel-list-container"]').should('not.exist')
25 | cy.get('[data-test-id="channel-list-toggle"]').first().click()
26 | cy.get('.channel-link').should('have.lengthOf', 2)
27 | cy.contains('.channel-link', '# General')
28 | cy.contains('.channel-link', '# Random')
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/specs/subscription.cy.ts:
--------------------------------------------------------------------------------
1 | describe('Subscription', () => {
2 | beforeEach(() => {
3 | cy.task('db:reset')
4 | cy.visit('/')
5 | })
6 |
7 | it('receive messages in real time', () => {
8 | cy.visit('/subscriptions')
9 | cy.get('input').type('Meow{enter}')
10 | cy.get('.message').should('have.length', 3)
11 | cy.get('.message').should('contain', 'Meow')
12 | cy.get('input').should('have.value', '')
13 | cy.get('input').type('Waf{enter}')
14 | cy.get('.message').should('have.length', 6)
15 | cy.get('.message').should('contain', 'Waf')
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/specs/updateQuery.cy.ts:
--------------------------------------------------------------------------------
1 | describe('updateQuery', () => {
2 | beforeEach(() => {
3 | cy.task('db:reset')
4 | cy.visit('/update-query')
5 | })
6 |
7 | it('should add new message to cache using updateQuery', () => {
8 | cy.get('.channel-btn').eq(0).click()
9 | cy.get('.message-input').type('hello 1')
10 | cy.get('.message').should('have.lengthOf', 0)
11 | cy.get('.send-message-btn').click()
12 | cy.get('.message').should('have.lengthOf', 1)
13 | cy.get('.message-input').type('hello 2')
14 | cy.get('.send-message-btn').click()
15 | cy.get('.message').should('have.lengthOf', 2)
16 | cy.contains('.message', 'hello 1')
17 | cy.contains('.message', 'hello 2')
18 |
19 | cy.get('.channel-btn').eq(1).click()
20 | cy.get('.message-input').type('hello 3')
21 | cy.get('.message').should('have.lengthOf', 0)
22 | cy.get('.send-message-btn').click()
23 | cy.get('.message').should('have.lengthOf', 1)
24 | cy.get('.message-input').type('hello 4')
25 | cy.get('.send-message-btn').click()
26 | cy.get('.message').should('have.lengthOf', 2)
27 | cy.contains('.message', 'hello 3')
28 | cy.contains('.message', 'hello 4')
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/support/commands.ts:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This is will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tests/e2e/support/index.ts:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "jsx": "preserve",
5 | "lib": [
6 | "esnext",
7 | "dom",
8 | "dom.iterable",
9 | "scripthost"
10 | ],
11 | "baseUrl": ".",
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "paths": {
15 | "@/*": [
16 | "src/*"
17 | ]
18 | },
19 | "types": [
20 | "vite/client",
21 | "cypress"
22 | ],
23 | "strict": true,
24 | "importHelpers": true,
25 | "sourceMap": true,
26 | "allowSyntheticDefaultImports": true,
27 | "esModuleInterop": true,
28 | "skipLibCheck": true
29 | },
30 | "include": [
31 | "src/**/*.ts",
32 | "src/**/*.tsx",
33 | "src/**/*.vue",
34 | "tests/**/*.ts",
35 | "tests/**/*.tsx"
36 | ],
37 | "exclude": [
38 | "node_modules"
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/packages/test-e2e-composable-vue3/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'node:path'
2 | import vue from '@vitejs/plugin-vue'
3 | import { defineConfig } from 'vite'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [vue()],
8 | resolve: {
9 | alias: {
10 | '@': resolve(__dirname, './src'),
11 | },
12 | },
13 | })
14 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | trim_trailing_whitespace = true
5 | insert_final_newline = true
6 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | /tests/e2e/videos/
6 | /tests/e2e/screenshots/
7 | /tests/e2e/downloads/
8 |
9 |
10 | # local env files
11 | .env.local
12 | .env.*.local
13 |
14 | # Log files
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 | pnpm-debug.log*
19 |
20 | # Editor directories and files
21 | .idea
22 | .vscode
23 | *.suo
24 | *.ntvs*
25 | *.njsproj
26 | *.sln
27 | *.sw?
28 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/README.md:
--------------------------------------------------------------------------------
1 | # test-e2e-global-composable-vue3
2 |
3 | ## Project setup
4 | ```
5 | pnpm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | pnpm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | pnpm run build
16 | ```
17 |
18 | ### Run your end-to-end tests
19 | ```
20 | pnpm run test:e2e
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { defineConfig } from 'cypress'
3 | import vitePreprocessor from 'cypress-vite'
4 |
5 | export default defineConfig({
6 | fixturesFolder: 'tests/e2e/fixtures',
7 | screenshotsFolder: 'tests/e2e/screenshots',
8 | videosFolder: 'tests/e2e/videos',
9 | downloadsFolder: 'tests/e2e/downloads',
10 | e2e: {
11 | baseUrl: 'http://localhost:8080',
12 | // We've imported your old cypress plugins here.
13 | // You may want to clean this up later by importing these.
14 | setupNodeEvents(on) {
15 | on('task', {
16 | 'db:reset': async function () {
17 | await axios.get('http://localhost:4042/_reset')
18 | return true
19 | },
20 |
21 | 'db:seed': async function () {
22 | await axios.get('http://localhost:4042/_seed')
23 | return true
24 | },
25 | })
26 | on('file:preprocessor', vitePreprocessor())
27 | },
28 | specPattern: 'tests/e2e/specs/**/*.cy.{js,jsx,ts,tsx}',
29 | supportFile: 'tests/e2e/support/index.ts',
30 | },
31 | })
32 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | My app
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-e2e-ssr",
3 | "version": "4.0.0-alpha.16",
4 | "private": true,
5 | "scripts": {
6 | "dev": "node ./server.mjs",
7 | "test": "pnpm run test:e2e",
8 | "test:e2e": "start-server-and-test api 'http-get://localhost:4042/graphql?query=%7B__typename%7D' test:e2e:run",
9 | "test:e2e:run": "start-server-and-test dev http://localhost:8080 test:e2e:cy",
10 | "test:e2e:cy": "cypress run --headless",
11 | "test:e2e:dev": "cypress open",
12 | "api": "test-server --simulate-latency 50",
13 | "api:dev": "test-server --simulate-latency 500"
14 | },
15 | "dependencies": {
16 | "@apollo/client": "^3.7.16",
17 | "@vue/apollo-composable": "workspace:*",
18 | "@vue/apollo-util": "workspace:*",
19 | "devalue": "^4.3.2",
20 | "express": "^4.18.2",
21 | "graphql": "^16.7.1",
22 | "graphql-tag": "^2.12.6",
23 | "isomorphic-fetch": "^3.0.0",
24 | "test-server": "workspace:*",
25 | "vue": "^3.3.4",
26 | "vue-router": "^4.2.4"
27 | },
28 | "devDependencies": {
29 | "@types/node": "^20.6.0",
30 | "@vitejs/plugin-vue": "^4.2.3",
31 | "autoprefixer": "^10.4.14",
32 | "axios": "^1.4.0",
33 | "cypress": "^12.17.0",
34 | "cypress-vite": "^1.4.1",
35 | "postcss": "^8.4.25",
36 | "start-server-and-test": "^2.0.0",
37 | "tailwindcss": "^3.3.2",
38 | "typescript": "^5.0.2",
39 | "vite": "^4.4.2",
40 | "vue-tsc": "^1.8.3"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/server.mjs:
--------------------------------------------------------------------------------
1 | import fs from 'node:fs'
2 | import { uneval } from 'devalue'
3 | import express from 'express'
4 | import { createServer } from 'vite'
5 |
6 | const server = express()
7 |
8 | const viteServer = await createServer({
9 | server: {
10 | middlewareMode: true,
11 | },
12 | appType: 'custom',
13 | })
14 | server.use(viteServer.middlewares)
15 |
16 | server.get('*', async (req, res) => {
17 | try {
18 | const url = req.originalUrl
19 | console.log(url)
20 |
21 | let template = fs.readFileSync('./index.html', 'utf8')
22 |
23 | const { render } = await viteServer.ssrLoadModule('/src/entry-server.ts')
24 | const { html, context } = await render(url)
25 |
26 | console.log(context)
27 |
28 | template = template
29 | .replace('', uneval(context.state))
30 | .replace('', html)
31 |
32 | res.send(template)
33 | }
34 | catch (e) {
35 | console.error(e)
36 | res.send(e.stack)
37 | }
38 | })
39 |
40 | server.use(express.static('.'))
41 |
42 | server.listen(8080, () => {
43 | console.log('Server is running on http://localhost:8080')
44 | })
45 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/apollo.ts:
--------------------------------------------------------------------------------
1 | import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core'
2 | import { onError } from '@apollo/client/link/error'
3 | import { logErrorMessages } from '@vue/apollo-util'
4 | import { isServer } from './env.js'
5 |
6 | export function createApollo() {
7 | const cache = new InMemoryCache()
8 |
9 | const restoreCache = !isServer && !!window._INITIAL_STATE_?.apollo
10 | if (restoreCache) {
11 | cache.restore(window._INITIAL_STATE_.apollo)
12 | }
13 |
14 | // HTTP connection to the API
15 | const httpLink = createHttpLink({
16 | // You should use an absolute URL here
17 | uri: 'http://localhost:4042/graphql',
18 | })
19 |
20 | // Handle errors
21 | const errorLink = onError((error) => {
22 | logErrorMessages(error)
23 | })
24 |
25 | const apolloClient = new ApolloClient({
26 | cache,
27 | link: errorLink.concat(httpLink),
28 | ssrForceFetchDelay: restoreCache ? 100 : undefined,
29 | ssrMode: isServer,
30 | })
31 |
32 | return {
33 | apolloClient,
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/app.ts:
--------------------------------------------------------------------------------
1 | import { DefaultApolloClient } from '@vue/apollo-composable'
2 | import { createApp } from 'vue'
3 | import { createApollo } from './apollo'
4 | import App from './components/App.vue'
5 | import { createMyRouter } from './router'
6 | import '@/assets/styles/tailwind.css'
7 |
8 | export function createMyApp() {
9 | const app = createApp(App)
10 |
11 | const { apolloClient } = createApollo()
12 | app.provide(DefaultApolloClient, apolloClient)
13 |
14 | const { router } = createMyRouter()
15 | app.use(router)
16 |
17 | return {
18 | app,
19 | router,
20 | apolloClient,
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/assets/styles/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 |
3 | @tailwind components;
4 |
5 | @tailwind utilities;
6 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/components/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
23 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/components/ClientOnly.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/components/GlobalLoading.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 | Global loading...
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/components/LazyQueryImmediately.vue:
--------------------------------------------------------------------------------
1 |
35 |
36 |
37 |
38 |
42 | Loading...
43 |
44 |
45 |
46 |
Loaded channel: {{ channel.label }}
47 |
Messages: {{ channel.messages.length }}
48 |
49 |
54 | {{ message.text }}
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/components/MessageItem.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 | {{ message.text }}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/components/Welcome.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Welcome
4 |
5 |
6 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/context.ts:
--------------------------------------------------------------------------------
1 | export interface Context {
2 | state: {
3 | apollo?: any
4 | }
5 | }
6 |
7 | declare global {
8 | interface Window {
9 | _INITIAL_STATE_: Context['state']
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/entry-client.ts:
--------------------------------------------------------------------------------
1 | import { createMyApp } from './app.js'
2 |
3 | const { app, router } = createMyApp()
4 |
5 | router.isReady().then(() => {
6 | app.mount('#app')
7 | })
8 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/entry-server.ts:
--------------------------------------------------------------------------------
1 | import type { Context } from '@apollo/client'
2 | import { renderToString } from 'vue/server-renderer'
3 | import { createMyApp } from './app.js'
4 | import 'isomorphic-fetch'
5 |
6 | export async function render(url: string) {
7 | const {
8 | app,
9 | router,
10 | apolloClient,
11 | } = await createMyApp()
12 |
13 | await router.push(url)
14 | await router.isReady()
15 |
16 | const context: Context = {
17 | state: {},
18 | }
19 |
20 | const html = await renderToString(app, context)
21 |
22 | context.state.apollo = apolloClient.extract()
23 |
24 | return {
25 | html,
26 | context,
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/env.ts:
--------------------------------------------------------------------------------
1 | export const isServer = typeof window === 'undefined'
2 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/router.ts:
--------------------------------------------------------------------------------
1 | import { createMemoryHistory, createRouter, createWebHistory } from 'vue-router'
2 | import { isServer } from './env.js'
3 |
4 | export function createMyRouter() {
5 | const router = createRouter({
6 | history: isServer ? createMemoryHistory() : createWebHistory(),
7 | routes: [
8 | {
9 | path: '/',
10 | name: 'home',
11 | component: () => import('./components/Welcome.vue'),
12 | },
13 | {
14 | path: '/channel/:id',
15 | name: 'channel',
16 | component: () => import('./components/ChannelView.vue'),
17 | props: true,
18 | },
19 | {
20 | path: '/lazy-query',
21 | component: () => import('./components/LazyQuery.vue'),
22 | },
23 | {
24 | path: '/lazy-query-immediately',
25 | component: () => import('./components/LazyQueryImmediately.vue'),
26 | },
27 | ],
28 | })
29 |
30 | return {
31 | router,
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import type { DefineComponent } from 'vue'
3 |
4 | const component: DefineComponent
5 | export default component
6 | }
7 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | }
9 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/tests/e2e/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | 'cypress',
4 | ],
5 | env: {
6 | 'mocha': true,
7 | 'cypress/globals': true,
8 | },
9 | rules: {
10 | strict: 'off',
11 | },
12 | }
13 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/tests/e2e/support/commands.ts:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This is will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/tests/e2e/support/index.ts:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "jsx": "preserve",
5 | "lib": [
6 | "esnext",
7 | "dom",
8 | "dom.iterable",
9 | "scripthost"
10 | ],
11 | "baseUrl": ".",
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "paths": {
15 | "@/*": [
16 | "src/*"
17 | ]
18 | },
19 | "types": [
20 | "vite/client",
21 | "cypress",
22 | "node"
23 | ],
24 | "strict": true,
25 | "importHelpers": true,
26 | "sourceMap": true,
27 | "allowSyntheticDefaultImports": true,
28 | "esModuleInterop": true,
29 | "skipLibCheck": true
30 | },
31 | "include": [
32 | "src/**/*.ts",
33 | "src/**/*.tsx",
34 | "src/**/*.vue",
35 | "tests/**/*.ts",
36 | "tests/**/*.tsx"
37 | ],
38 | "exclude": [
39 | "node_modules"
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/packages/test-e2e-ssr/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'node:path'
2 | import vue from '@vitejs/plugin-vue'
3 | import { defineConfig } from 'vite'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [vue()],
8 | resolve: {
9 | alias: {
10 | '@': resolve(__dirname, './src'),
11 | },
12 | },
13 | })
14 |
--------------------------------------------------------------------------------
/packages/test-e2e/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | /tests/e2e/videos/
6 | /tests/e2e/screenshots/
7 |
8 | # local env files
9 | .env.local
10 | .env.*.local
11 |
12 | # Log files
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 |
17 | # Editor directories and files
18 | .idea
19 | .vscode
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw*
25 |
26 | /live/
27 |
--------------------------------------------------------------------------------
/packages/test-e2e/.graphqlconfig.yml:
--------------------------------------------------------------------------------
1 | projects:
2 | app:
3 | schemaPath: apollo-server/schema.graphql
4 | includes:
5 | - '**/*.gql'
6 | extensions:
7 | endpoints:
8 | default: 'http://localhost:4000/graphql'
9 |
--------------------------------------------------------------------------------
/packages/test-e2e/.postcssrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | },
5 | }
6 |
--------------------------------------------------------------------------------
/packages/test-e2e/README.md:
--------------------------------------------------------------------------------
1 | # ApolloChat
2 |
3 | Demo app: Vue + Apollo + Graphql + vue-cli 3
4 |
5 | ### Setup project
6 |
7 | ```
8 | pnpm i
9 | ```
10 |
11 | ### Development
12 |
13 | ```
14 | pnpm run apollo:run
15 | pnpm run serve
16 | ```
17 |
--------------------------------------------------------------------------------
/packages/test-e2e/apollo-server/connectors/channels.js:
--------------------------------------------------------------------------------
1 | const channels = [
2 | { id: 'general', name: 'General discussion' },
3 | { id: 'random', name: 'Have fun chatting!' },
4 | { id: 'help', name: 'Ask for or give help' },
5 | ]
6 |
7 | exports.getAll = (context) => {
8 | return channels
9 | }
10 |
11 | exports.getOne = (id, context) => {
12 | return channels.find(c => c.id === id)
13 | }
14 |
--------------------------------------------------------------------------------
/packages/test-e2e/apollo-server/context.js:
--------------------------------------------------------------------------------
1 | const users = require('./connectors/users')
2 |
3 | // Context passed to all resolvers (third argument)
4 | // req => Query
5 | // connection => Subscription
6 |
7 | module.exports = ({ req, connection }) => {
8 | // If the websocket context was already resolved
9 | if (connection && connection.context)
10 | return connection.context
11 |
12 | let rawToken
13 | // HTTP
14 | if (req)
15 | rawToken = req.get('Authorization')
16 | // Websocket
17 | if (connection)
18 | rawToken = connection.Authorization
19 |
20 | // Token
21 | const token = rawToken ? JSON.parse(rawToken) : null
22 | let userId
23 |
24 | // User validation
25 | if (token && users.validateToken(token)) {
26 | userId = token.userId
27 | }
28 |
29 | // return new Promise(resolve => {
30 | // setTimeout(() => {
31 | // resolve({
32 | // token,
33 | // userId,
34 | // })
35 | // }, 3000)
36 | // })
37 | return {
38 | token,
39 | userId,
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/test-e2e/apollo-server/directives.js:
--------------------------------------------------------------------------------
1 | const PrivateDirective = require('./directives/private')
2 |
3 | module.exports = {
4 | private: PrivateDirective,
5 | }
6 |
--------------------------------------------------------------------------------
/packages/test-e2e/apollo-server/directives/private.js:
--------------------------------------------------------------------------------
1 | const { ApolloError } = require('apollo-server-express')
2 | const { defaultFieldResolver } = require('graphql')
3 | const { SchemaDirectiveVisitor } = require('graphql-tools')
4 |
5 | module.exports = class PrivateDirective extends SchemaDirectiveVisitor {
6 | visitFieldDefinition(field) {
7 | const { resolve = defaultFieldResolver } = field
8 | field.resolve = (root, args, context, info) => {
9 | if (!context.userId)
10 | throw new ApolloError('Unauthorized', 'unauthorized')
11 | return resolve(root, args, context, info)
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/test-e2e/apollo-server/reset.js:
--------------------------------------------------------------------------------
1 | exports.reset = () => {
2 | require('./connectors/messages.js').reset()
3 | require('./connectors/users.js').reset()
4 | }
5 |
--------------------------------------------------------------------------------
/packages/test-e2e/apollo-server/triggers.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | MESSAGE_CHANGED: 'message_changed',
3 | }
4 |
--------------------------------------------------------------------------------
/packages/test-e2e/apollo-server/type-defs.js:
--------------------------------------------------------------------------------
1 | const fs = require('node:fs')
2 | const path = require('node:path')
3 |
4 | module.exports = fs.readFileSync(path.resolve(__dirname, './schema.graphql'), { encoding: 'utf8' })
5 |
--------------------------------------------------------------------------------
/packages/test-e2e/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset',
4 | ],
5 | }
6 |
--------------------------------------------------------------------------------
/packages/test-e2e/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'cypress'
2 |
3 | export default defineConfig({
4 | fixturesFolder: 'tests/e2e/fixtures',
5 | screenshotsFolder: 'tests/e2e/screenshots',
6 | videosFolder: 'tests/e2e/videos',
7 | e2e: {
8 | specPattern: 'tests/e2e/specs/**/*.cy.{js,jsx,ts,tsx}',
9 | supportFile: 'tests/e2e/support/index.js',
10 | },
11 | })
12 |
--------------------------------------------------------------------------------
/packages/test-e2e/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vuejs/apollo/fb027e6adf4d4129fb26f8c918060771a0afd59b/packages/test-e2e/public/favicon.ico
--------------------------------------------------------------------------------
/packages/test-e2e/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 | Apollo Chat
12 |
13 |
14 |
15 | We're sorry but demo doesn't work properly without JavaScript enabled. Please enable it to continue.
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/components/ManualAddSmartQuery.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Loading...
5 |
6 |
7 | {{ number }}
8 |
9 |
10 |
{{ json(history) }}
11 |
12 |
13 |
14 |
47 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/components/MessageItem.vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
31 | {{ message.user.nickname }}
32 |
33 |
37 |
38 |
39 |
40 |
64 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/components/MockSendMessage.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
20 |
21 | Send bot message
25 |
26 |
27 |
28 |
29 |
36 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/components/PartialError.vue:
--------------------------------------------------------------------------------
1 |
38 |
39 |
40 |
41 |
47 |
errorPolicy: '{{ errorPolicy }}' => {{ $data[errorPolicy] }}
48 |
52 | {{ errors[errorPolicy] }}
53 |
54 |
55 |
56 |
57 |
58 |
62 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/components/WelcomeView.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 | Welcome!
11 |
12 |
13 | Select a channel to start messaging
14 |
15 |
16 |
17 |
18 |
36 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/channel.gql:
--------------------------------------------------------------------------------
1 | #import "./channelFragment.gql"
2 | #import "./messageFragment.gql"
3 |
4 | query channel ($id: ID!) {
5 | channel (id: $id) {
6 | ...channel
7 | messages {
8 | ...message
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/channelFragment.gql:
--------------------------------------------------------------------------------
1 | fragment channel on Channel {
2 | id
3 | name
4 | }
5 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/channels.gql:
--------------------------------------------------------------------------------
1 | #import "./channelFragment.gql"
2 |
3 | query channels {
4 | channels {
5 | ...channel
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/messageAdd.gql:
--------------------------------------------------------------------------------
1 | #import "./messageFragment.gql"
2 |
3 | mutation messageAdd ($input: MessageAdd!) {
4 | messageAdd (input: $input) {
5 | ...message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/messageChanged.gql:
--------------------------------------------------------------------------------
1 | #import "./messageFragment.gql"
2 |
3 | subscription messageChanged ($channelId: ID!) {
4 | messageChanged (channelId: $channelId) {
5 | type
6 | message {
7 | ...message
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/messageFragment.gql:
--------------------------------------------------------------------------------
1 | #import "./userFragment.gql"
2 |
3 | fragment message on Message {
4 | id
5 | content
6 | user {
7 | ...user
8 | }
9 | dateAdded
10 | dateUpdated
11 | }
12 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/messageRemove.gql:
--------------------------------------------------------------------------------
1 | #import "./messageFragment.gql"
2 |
3 | mutation messageRemove ($id: ID!) {
4 | messageRemove (id: $id) {
5 | ...message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/messageUpdate.gql:
--------------------------------------------------------------------------------
1 | #import "./messageFragment.gql"
2 |
3 | mutation messageUpdate ($input: MessageUpdate!) {
4 | messageUpdate (input: $input) {
5 | ...message
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/userCurrent.gql:
--------------------------------------------------------------------------------
1 | #import "./userFragment.gql"
2 |
3 | query userCurrent {
4 | userCurrent {
5 | ...user
6 | email
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/userFragment.gql:
--------------------------------------------------------------------------------
1 | fragment user on User {
2 | id
3 | nickname
4 | }
5 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/userLogin.gql:
--------------------------------------------------------------------------------
1 | #import "./userFragment.gql"
2 |
3 | mutation userLogin ($email: String!, $password: String!) {
4 | userLogin (email: $email, password: $password) {
5 | user {
6 | ...user
7 | email
8 | }
9 | token {
10 | id
11 | userId
12 | expiration
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/userLogout.gql:
--------------------------------------------------------------------------------
1 | mutation userLogout {
2 | userLogout
3 | }
4 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/graphql/userRegister.gql:
--------------------------------------------------------------------------------
1 | mutation userRegister ($input: UserRegister!) {
2 | userRegister(input: $input)
3 | }
4 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/main.js:
--------------------------------------------------------------------------------
1 | import VueApolloComponents from '@vue/apollo-components'
2 | import { createApp } from 'vue'
3 | import App from './App.vue'
4 | import router from './router'
5 | import store from './store'
6 | import { apolloProvider } from './vue-apollo'
7 |
8 | const app = createApp(App)
9 | app.use(router)
10 | app.use(store)
11 | app.use(apolloProvider)
12 | app.use(VueApolloComponents)
13 | app.mount('#app')
14 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/mixins/UserCurrent.js:
--------------------------------------------------------------------------------
1 | import USER_CURRENT from '../graphql/userCurrent.gql'
2 |
3 | // @vue/component
4 | export default {
5 | apollo: {
6 | userCurrent: USER_CURRENT,
7 | },
8 | }
9 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/router.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHistory } from 'vue-router'
2 | import ChannelView from './components/ChannelView.vue'
3 | import ManualAddSmartQuery from './components/ManualAddSmartQuery.vue'
4 | import PartialError from './components/PartialError.vue'
5 | import UserLogin from './components/UserLogin.vue'
6 | import WelcomeView from './components/WelcomeView.vue'
7 |
8 | export default createRouter({
9 | history: createWebHistory(),
10 | routes: [
11 | {
12 | path: '/',
13 | name: 'home',
14 | component: WelcomeView,
15 | meta: {
16 | private: true,
17 | },
18 | },
19 | {
20 | path: '/login',
21 | name: 'login',
22 | component: UserLogin,
23 | },
24 | {
25 | path: '/chan/:id',
26 | name: 'channel',
27 | component: ChannelView,
28 | props: true,
29 | meta: {
30 | private: true,
31 | },
32 | },
33 | {
34 | path: '/partial-error',
35 | component: PartialError,
36 | },
37 | {
38 | path: '/manual-add-smart-query',
39 | component: ManualAddSmartQuery,
40 | },
41 | {
42 | path: '/update-cache',
43 | component: () => import('./components/UpdateCache.vue'),
44 | },
45 | ],
46 | })
47 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/store.js:
--------------------------------------------------------------------------------
1 | import { createStore } from 'vuex'
2 |
3 | export default createStore({
4 | state: {
5 |
6 | },
7 | mutations: {
8 |
9 | },
10 | actions: {
11 |
12 | },
13 | })
14 |
--------------------------------------------------------------------------------
/packages/test-e2e/src/style/imports.styl:
--------------------------------------------------------------------------------
1 | $color = #41b883
2 | $border = rgba(black, .08) 1px solid
3 |
--------------------------------------------------------------------------------
/packages/test-e2e/tests/e2e/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "cypress"
4 | ],
5 | "env": {
6 | "mocha": true,
7 | "cypress/globals": true
8 | },
9 | "rules": {
10 | "strict": "off"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/test-e2e/tests/e2e/specs/cache.cy.js:
--------------------------------------------------------------------------------
1 | describe('cache', () => {
2 | it('add an item to the list', () => {
3 | cy.visit('/update-cache')
4 |
5 | cy.get('.item-list ul li').should('have.length', 1)
6 | cy.get('.update-count').should('contain', 'Changes: 1')
7 | cy.get('button.add').click()
8 | cy.get('.item-list ul li').should('have.length', 2)
9 | cy.get('.item-list ul li').should('contain', 'Item 2')
10 | cy.get('.update-count').should('contain', 'Changes: 2')
11 | })
12 | })
13 |
--------------------------------------------------------------------------------
/packages/test-e2e/tests/e2e/specs/errorPolicy.cy.js:
--------------------------------------------------------------------------------
1 | describe('errorPolicy', () => {
2 | it('supports `errorPolicy` option', () => {
3 | cy.visit('/partial-error')
4 |
5 | // All
6 | cy.get('.all .result').should('contain', '"good":"good"').should('contain', '"bad":null')
7 | cy.get('.all .error').should('contain', 'Error: GraphQL error: An error')
8 |
9 | // None
10 | cy.get('.none .result').should('not.contain', 'good').should('not.contain', 'bad')
11 | cy.get('.none .error').should('contain', 'Error: An error')
12 |
13 | // Ignore
14 | cy.get('.ignore .result').should('contain', '"good":"good"').should('contain', '"bad":null')
15 | cy.get('.ignore .error').should('not.exist')
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/packages/test-e2e/tests/e2e/specs/manual-smart-query.cy.js:
--------------------------------------------------------------------------------
1 | describe('Manual Smart Query', () => {
2 | it('should support loading key', () => {
3 | cy.visit('/manual-add-smart-query')
4 | cy.contains('Loading...')
5 | cy.contains('42')
6 | cy.contains('[{"isLoading":true,"countModifier":1},{"isLoading":false,"countModifier":-1}]')
7 | })
8 | })
9 |
--------------------------------------------------------------------------------
/packages/test-e2e/tests/e2e/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This is will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/packages/test-e2e/tests/e2e/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/packages/test-e2e/vue.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@vue/cli-service').ProjectOptions} */
2 | module.exports = {
3 | // pluginOptions: {
4 | // apollo: {
5 | // enableMocks: false,
6 | // enableEngine: false,
7 | // },
8 | // },
9 |
10 | productionSourceMap: false,
11 |
12 | /* Without vue-cli-plugin-apollo 0.20.0+ */
13 | // chainWebpack: config => {
14 | // config.module
15 | // .rule('vue')
16 | // .use('vue-loader')
17 | // .loader('vue-loader')
18 | // .tap(options => {
19 | // options.transpileOptions = {
20 | // transforms: {
21 | // dangerousTaggedTemplateString: true,
22 | // },
23 | // }
24 | // return options
25 | // })
26 | // }
27 |
28 | chainWebpack: (config) => {
29 | config.module.rule('graphql')
30 | .test(/\.gql$/)
31 | .use('graphql-tag/loader')
32 | .loader('graphql-tag/loader')
33 | .end()
34 | },
35 | }
36 |
--------------------------------------------------------------------------------
/packages/test-server/bin.mjs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict'
3 |
4 | import './dist/index.js'
5 |
--------------------------------------------------------------------------------
/packages/test-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-server",
3 | "type": "module",
4 | "version": "4.0.0-alpha.16",
5 | "private": true,
6 | "bin": {
7 | "test-server": "./bin.mjs"
8 | },
9 | "scripts": {
10 | "build": "tsc -d",
11 | "prepare": "pnpm run build"
12 | },
13 | "dependencies": {
14 | "@apollo/server": "^4.7.3",
15 | "@graphql-tools/schema": "^10.0.0",
16 | "body-parser": "^1.20.2",
17 | "cors": "^2.8.5",
18 | "express": "^4.18.1",
19 | "graphql": "^16.6.0",
20 | "graphql-subscriptions": "^2.0.0",
21 | "graphql-tag": "^2.12.6",
22 | "graphql-ws": "^5.13.1",
23 | "shortid": "^2.2.16",
24 | "ws": "^8.13.0"
25 | },
26 | "devDependencies": {
27 | "@types/body-parser": "^1.19.2",
28 | "@types/cors": "^2.8.13",
29 | "@types/express": "^4.17.17",
30 | "@types/shortid": "^0.0.29",
31 | "@types/ws": "^8.5.5",
32 | "typescript": "^4.7.4"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/test-server/src/data.ts:
--------------------------------------------------------------------------------
1 | export interface Channel {
2 | id: string
3 | label: string
4 | messages: Message[]
5 | }
6 |
7 | export interface Message {
8 | id: string
9 | channel: Channel
10 | text: string
11 | }
12 |
13 | export let channels: Channel[] = []
14 |
15 | export function resetDatabase(): void {
16 | channels = [
17 | {
18 | id: 'general',
19 | label: 'General',
20 | messages: [],
21 | },
22 | {
23 | id: 'random',
24 | label: 'Random',
25 | messages: [],
26 | },
27 | ]
28 | }
29 |
30 | export function seedDatabase(): void {
31 | channels[0].messages = [
32 | {
33 | id: '1',
34 | channel: channels[0],
35 | text: 'Meow?',
36 | },
37 | {
38 | id: '2',
39 | channel: channels[0],
40 | text: 'Meow!',
41 | },
42 | ]
43 | channels[1].messages = [
44 | {
45 | id: '3',
46 | channel: channels[1],
47 | text: 'Hello world!',
48 | },
49 | ]
50 | }
51 |
52 | resetDatabase()
53 |
--------------------------------------------------------------------------------
/packages/test-server/src/util.ts:
--------------------------------------------------------------------------------
1 | import type { GraphQLErrorExtensions } from 'graphql'
2 | import { GraphQLError } from 'graphql'
3 |
4 | const shouldSimulateLatency = process.argv.includes('--simulate-latency')
5 |
6 | let latency = 500
7 | if (shouldSimulateLatency) {
8 | const index = process.argv.indexOf('--simulate-latency')
9 | if (index !== -1 && process.argv.length > index + 1) {
10 | latency = Number.parseInt(process.argv[index + 1])
11 | }
12 | }
13 |
14 | export function simulateLatency() {
15 | return new Promise((resolve) => {
16 | if (shouldSimulateLatency) {
17 | setTimeout(resolve, latency)
18 | }
19 | else {
20 | resolve()
21 | }
22 | })
23 | }
24 |
25 | export class GraphQLErrorWithCode extends GraphQLError {
26 | constructor(message: string, code: string, extensions?: GraphQLErrorExtensions) {
27 | super(message, null, null, null, null, null, {
28 | extensions: {
29 | code,
30 | ...extensions,
31 | },
32 | })
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/test-server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "lib": [
5 | "esnext"
6 | ],
7 | "module": "esnext",
8 | "moduleResolution": "node",
9 | "strict": true,
10 | "importHelpers": true,
11 | "outDir": "dist",
12 | "sourceMap": true,
13 | "allowSyntheticDefaultImports": true,
14 | "esModuleInterop": true,
15 | "skipLibCheck": true
16 | },
17 | "include": [
18 | "src/**/*.ts"
19 | ],
20 | "exclude": [
21 | "node_modules"
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/packages/vue-apollo-components/.npmignore:
--------------------------------------------------------------------------------
1 | src/
2 | types/test/
3 | tests/
4 | .babelrc
5 | .eslintrc.js
6 |
--------------------------------------------------------------------------------
/packages/vue-apollo-components/README.md:
--------------------------------------------------------------------------------
1 | # Apollo and GraphQL for Vue.js (Components with Slots)
2 |
3 | [ ](https://www.npmjs.com/package/@vue/apollo-components)
4 | [](https://www.apollographql.com/)
5 | [](https://vuejs.org/)
6 | [](https://circleci.com/gh/vuejs/vue-apollo/tree/v4)
7 |
8 |
9 |
10 |
11 |
12 | :book: Documentation [**for Vue 3**](http://v4.apollo.vuejs.org) | [for Vue 2](https://apollo.vuejs.org/)
13 |
14 | [:pen: Contributing guide](./CONTRIBUTING.md)
15 |
16 | [:heart: Sponsor me!](https://github.com/sponsors/Akryum)
17 |
18 | ```bash
19 | npm i @vue/apollo-components
20 | pnpm i @vue/apollo-components
21 | yarn add @vue/apollo-components
22 | ```
23 |
24 | ## Sponsors
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/vue-apollo-components/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [require('@babel/preset-env'), { modules: false }],
4 | ],
5 | plugins: [
6 | require('@babel/plugin-proposal-class-properties'),
7 | [require('@babel/plugin-transform-for-of'), { assumeArray: true }],
8 | ],
9 | }
10 |
--------------------------------------------------------------------------------
/packages/vue-apollo-components/build/rollup.config.base.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel'
2 | import cjs from 'rollup-plugin-commonjs'
3 | import resolve from 'rollup-plugin-node-resolve'
4 | import replace from 'rollup-plugin-replace'
5 |
6 | const config = require('../package.json')
7 |
8 | export default {
9 | input: 'src/index.js',
10 | plugins: [
11 | resolve({
12 | jsnext: true,
13 | main: true,
14 | browser: true,
15 | }),
16 | cjs({
17 | exclude: 'src/**',
18 | }),
19 | babel({
20 | exclude: 'node_modules/**',
21 | }),
22 | replace({
23 | VERSION: JSON.stringify(config.version),
24 | }),
25 | ],
26 | external: ['@apollo/client', 'graphql-tag', 'vue'],
27 | }
28 |
--------------------------------------------------------------------------------
/packages/vue-apollo-components/build/rollup.config.browser.js:
--------------------------------------------------------------------------------
1 | import { uglify } from 'rollup-plugin-uglify'
2 | import { minify } from 'uglify-es'
3 | import base from './rollup.config.base'
4 |
5 | const config = Object.assign({}, base, {
6 | output: {
7 | file: 'dist/vue-apollo-components.min.js',
8 | format: 'iife',
9 | name: 'VueApolloComponents',
10 | },
11 | })
12 |
13 | config.plugins.push(uglify({}, minify))
14 |
15 | export default config
16 |
--------------------------------------------------------------------------------
/packages/vue-apollo-components/build/rollup.config.es.js:
--------------------------------------------------------------------------------
1 | import base from './rollup.config.base'
2 |
3 | const config = Object.assign({}, base, {
4 | output: {
5 | file: 'dist/vue-apollo-components.esm.mjs',
6 | format: 'es',
7 | name: 'vue-apollo-components',
8 | },
9 | })
10 |
11 | export default config
12 |
--------------------------------------------------------------------------------
/packages/vue-apollo-components/build/rollup.config.umd.js:
--------------------------------------------------------------------------------
1 | import base from './rollup.config.base'
2 |
3 | const config = Object.assign({}, base, {
4 | output: {
5 | file: 'dist/vue-apollo-components.umd.js',
6 | format: 'umd',
7 | name: 'vue-apollo-components',
8 | },
9 | })
10 |
11 | export default config
12 |
--------------------------------------------------------------------------------
/packages/vue-apollo-components/src/index.js:
--------------------------------------------------------------------------------
1 | import CApolloMutation from './ApolloMutation'
2 | import CApolloQuery from './ApolloQuery'
3 | import CApolloSubscribeToMore from './ApolloSubscribeToMore'
4 |
5 | const plugin = {}
6 |
7 | export function install(app, options) {
8 | app.component('ApolloQuery', CApolloQuery)
9 | app.component('ApolloSubscribeToMore', CApolloSubscribeToMore)
10 | app.component('ApolloMutation', CApolloMutation)
11 | }
12 |
13 | plugin.install = install
14 |
15 | // eslint-disable-next-line no-undef
16 | plugin.version = VERSION
17 |
18 | // Apollo provider
19 | export const ApolloProvider = plugin
20 |
21 | // Components
22 | export const ApolloQuery = CApolloQuery
23 | export const ApolloSubscribeToMore = CApolloSubscribeToMore
24 | export const ApolloMutation = CApolloMutation
25 |
26 | // Auto-install
27 | let GlobalVue = null
28 | if (typeof window !== 'undefined') {
29 | GlobalVue = window.Vue
30 | }
31 | else if (typeof globalThis !== 'undefined') {
32 | GlobalVue = globalThis.Vue
33 | }
34 | if (GlobalVue) {
35 | GlobalVue.use(plugin)
36 | }
37 |
38 | export default plugin
39 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/README.md:
--------------------------------------------------------------------------------
1 | # Apollo and GraphQL for Vue.js (Composition API)
2 |
3 | [ ](https://www.npmjs.com/package/@vue/apollo-composable)
4 | [](https://www.apollographql.com/)
5 | [](https://vuejs.org/)
6 | [](https://circleci.com/gh/vuejs/vue-apollo/tree/v4)
7 |
8 |
9 |
10 |
11 |
12 | :book: Documentation [**for Vue 3**](http://v4.apollo.vuejs.org) | [for Vue 2](https://apollo.vuejs.org/)
13 |
14 | [:pen: Contributing guide](./CONTRIBUTING.md)
15 |
16 | [:heart: Sponsor me!](https://github.com/sponsors/Akryum)
17 |
18 | ```bash
19 | npm i @vue/apollo-composable
20 | pnpm i @vue/apollo-composable
21 | yarn add @vue/apollo-composable
22 | ```
23 |
24 | ## Sponsors
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/esbuild.mjs:
--------------------------------------------------------------------------------
1 | import path from 'node:path'
2 | import esbuild from 'esbuild'
3 | import { nodeExternalsPlugin } from 'esbuild-node-externals'
4 |
5 | /** @typedef {import('esbuild').BuildOptions} BuildOptions */
6 |
7 | /**
8 | * @typedef Build
9 | * @prop {BuildOptions['format']} format
10 | * @prop {string} file
11 | */
12 |
13 | (async () => {
14 | /** @type {Build[]} */
15 | const builds = [
16 | { format: 'esm', file: 'index.mjs' },
17 | { format: 'cjs', file: 'index.js' },
18 | ]
19 | for (const { format, file } of builds) {
20 | await esbuild.build({
21 | entryPoints: ['./src/index.ts'],
22 | bundle: true,
23 | platform: 'neutral',
24 | format,
25 | outfile: path.join('dist', file),
26 | sourcemap: true,
27 | target: 'es2018',
28 | plugins: [
29 | nodeExternalsPlugin(),
30 | ],
31 | })
32 | }
33 | })()
34 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/index.ts:
--------------------------------------------------------------------------------
1 | export {
2 | ApolloClients,
3 | DefaultApolloClient,
4 | provideApolloClient,
5 | provideApolloClients,
6 | useApolloClient,
7 | UseApolloClientReturn,
8 | } from './useApolloClient'
9 |
10 | export {
11 | useLazyQuery,
12 | } from './useLazyQuery'
13 |
14 | export {
15 | useGlobalMutationLoading,
16 | useGlobalQueryLoading,
17 | useGlobalSubscriptionLoading,
18 | useMutationLoading,
19 | useQueryLoading,
20 | useSubscriptionLoading,
21 | } from './useLoading'
22 |
23 | export {
24 | MutateFunction,
25 | MutateOverrideOptions,
26 | MutateResult,
27 | useMutation,
28 | UseMutationOptions,
29 | UseMutationReturn,
30 | } from './useMutation'
31 |
32 | export {
33 | useQuery,
34 | UseQueryOptions,
35 | UseQueryReturn,
36 | } from './useQuery'
37 |
38 | export {
39 | useResult,
40 | UseResultReturn,
41 | } from './useResult'
42 |
43 | export {
44 | useSubscription,
45 | UseSubscriptionOptions,
46 | UseSubscriptionReturn,
47 | } from './useSubscription'
48 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/useLoading.ts:
--------------------------------------------------------------------------------
1 | import { computed } from 'vue-demi'
2 | import { getCurrentTracking, globalTracking } from './util/loadingTracking'
3 |
4 | export function useQueryLoading() {
5 | const { tracking } = getCurrentTracking()
6 | if (!tracking)
7 | throw new Error('useQueryLoading must be called inside a setup function.')
8 | return computed(() => tracking.queries.value > 0)
9 | }
10 |
11 | export function useMutationLoading() {
12 | const { tracking } = getCurrentTracking()
13 | if (!tracking)
14 | throw new Error('useMutationLoading must be called inside a setup function.')
15 | return computed(() => tracking.mutations.value > 0)
16 | }
17 |
18 | export function useSubscriptionLoading() {
19 | const { tracking } = getCurrentTracking()
20 | if (!tracking)
21 | throw new Error('useSubscriptionLoading must be called inside a setup function.')
22 | return computed(() => tracking.subscriptions.value > 0)
23 | }
24 |
25 | export function useGlobalQueryLoading() {
26 | return computed(() => globalTracking.queries.value > 0)
27 | }
28 |
29 | export function useGlobalMutationLoading() {
30 | return computed(() => globalTracking.mutations.value > 0)
31 | }
32 |
33 | export function useGlobalSubscriptionLoading() {
34 | return computed(() => globalTracking.subscriptions.value > 0)
35 | }
36 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/util/ExtractSingleKey.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Check if a type is a union, and return true if so, otherwise false.
3 | */
4 | export type IsUnion = U extends any ? ([T] extends [U] ? false : true) : never
5 |
6 | /**
7 | * Extracts an inner type if T has a single key K, otherwise it returns T.
8 | */
9 | export type ExtractSingleKey> = IsUnion extends true ? T : T[KWithoutTypename]
10 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/util/ReactiveFunction.ts:
--------------------------------------------------------------------------------
1 | export type ReactiveFunction = () => TParam
2 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/util/env.ts:
--------------------------------------------------------------------------------
1 | export const isServer = typeof window === 'undefined'
2 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/util/paramToReactive.ts:
--------------------------------------------------------------------------------
1 | import type { Ref } from 'vue-demi'
2 | import type { ReactiveFunction } from './ReactiveFunction'
3 | import { computed, isRef, reactive } from 'vue-demi'
4 |
5 | type TObject = object
6 |
7 | export function paramToReactive(param: T | Ref | ReactiveFunction): T | Ref {
8 | if (isRef(param)) {
9 | return param
10 | }
11 | else if (typeof param === 'function') {
12 | return computed(param as ReactiveFunction)
13 | }
14 | else if (param) {
15 | return reactive(param) as T
16 | }
17 | else {
18 | return param
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/util/paramToRef.ts:
--------------------------------------------------------------------------------
1 | import type { Ref } from 'vue-demi'
2 | import type { ReactiveFunction } from './ReactiveFunction'
3 | import { computed, isRef, ref } from 'vue-demi'
4 |
5 | export function paramToRef(param: T | Ref | ReactiveFunction): Ref {
6 | if (isRef(param)) {
7 | return param
8 | }
9 | else if (typeof param === 'function') {
10 | return computed(param as ReactiveFunction)
11 | }
12 | else {
13 | return ref(param) as Ref
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/util/toApolloError.ts:
--------------------------------------------------------------------------------
1 | import type { GraphQLFormattedError } from 'graphql'
2 | import { ApolloError, isApolloError } from '@apollo/client/core/index.js'
3 |
4 | export function toApolloError(error: unknown): ApolloError {
5 | if (!(error instanceof Error)) {
6 | return new ApolloError({
7 | networkError: Object.assign(new Error((error as any)?.message), { originalError: error }),
8 | errorMessage: String(error),
9 | })
10 | }
11 |
12 | if (isApolloError(error)) {
13 | return error
14 | }
15 |
16 | return new ApolloError({ networkError: error, errorMessage: error.message })
17 | }
18 |
19 | export function resultErrorsToApolloError(errors: ReadonlyArray): ApolloError {
20 | return new ApolloError({
21 | graphQLErrors: errors,
22 | errorMessage: `GraphQL response contains errors: ${errors.map((e: any) => e.message).join(' | ')}`,
23 | })
24 | }
25 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/src/util/useEventHook.ts:
--------------------------------------------------------------------------------
1 | export function useEventHook() {
2 | const fns: Array<(...params: TParams) => void> = []
3 |
4 | function on(fn: (...params: TParams) => void) {
5 | fns.push(fn)
6 | return {
7 | off: () => off(fn),
8 | }
9 | }
10 |
11 | function off(fn: (...params: TParams) => void) {
12 | const index = fns.indexOf(fn)
13 | if (index !== -1) {
14 | fns.splice(index, 1)
15 | }
16 | }
17 |
18 | function trigger(...params: TParams) {
19 | for (const fn of fns) {
20 | fn(...params)
21 | }
22 | }
23 |
24 | function getCount() {
25 | return fns.length
26 | }
27 |
28 | return {
29 | on,
30 | off,
31 | trigger,
32 | getCount,
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/tests/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | '@typescript-eslint/no-unused-expressions': 'off',
4 | '@typescript-eslint/no-floating-promises': 'off',
5 | '@typescript-eslint/naming-convention': 'off',
6 | '@typescript-eslint/no-unused-vars': 'off',
7 | },
8 | }
9 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/tests/types/assertions.ts:
--------------------------------------------------------------------------------
1 | export type ExactType = T extends U ? (U extends T ? T : never) : never
2 |
3 | /**
4 | * Verify that a type matches an exact expected type.
5 | *
6 | * NOTE: Some cases don't work (like `any`, `unknown`) due to how typescript
7 | * widens types. Manually verify the assert is reliable when using.
8 | */
9 | export function assertExactType(expected: ExactType) {}
10 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/tests/types/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "commonjs",
5 | "strict": true,
6 | "noEmit": true,
7 | "esModuleInterop": true,
8 | "skipLibCheck": true
9 | },
10 | "include": [
11 | "*.test.ts"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/tests/types/useApolloClient-types.test.ts:
--------------------------------------------------------------------------------
1 | import type { UseApolloClientReturn } from '../../src'
2 | import { useApolloClient } from '../../src'
3 | import { assertExactType } from './assertions'
4 |
5 | // =============================================================================
6 | // With no type and no clientId
7 | // - the store type should be `any`
8 | // =============================================================================
9 | {
10 | const noClientId = useApolloClient()
11 | noClientId.client?.extract(true).storeType.is.any
12 | }
13 |
14 | // =============================================================================
15 | // With no type and a clientId
16 | // - the store type should be `any`
17 | // =============================================================================
18 | {
19 | const withClientId = useApolloClient('88K2tP')
20 | withClientId.client?.extract(true).storeType.is.any
21 | }
22 |
23 | // =============================================================================
24 | // With specific type and a client id
25 | // - the store type should be the specified tyep
26 | // =============================================================================
27 | {
28 | const withType = useApolloClient<'cacheShape'>('38pX2d')
29 | const store = withType.client?.extract(true)
30 |
31 | assertExactType>(withType)
32 | assertExactType(store)
33 | }
34 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/tests/types/util/ExtractSingleKey.test.ts:
--------------------------------------------------------------------------------
1 | import type { ExtractSingleKey, IsUnion } from '../../../src/util/ExtractSingleKey'
2 | import type { MultiKeyExampleQuery, SingleKeyExampleQuery } from '../../fixtures/graphql-example-types'
3 | import { assertExactType } from '../assertions'
4 |
5 | // IsUnion
6 |
7 | // When the type is a union, it should return true
8 | const trueUnion: IsUnion<'id' | 'name'> = true
9 | const numberTrueUnion: IsUnion<15 | 18> = true
10 |
11 | // When the type is not a union, it should return false
12 | const falseUnion: IsUnion<'id'> = false
13 | const numberFalseUnion: IsUnion<15> = false
14 | const arrayUnion: IsUnion<[string, number]> = false
15 |
16 | // When the type is never, it should return never
17 | let what: IsUnion
18 | assertExactType(what)
19 |
20 | // ExtractSingleKey
21 |
22 | // When the passed in type has a single key, it should return the type of that key
23 | let singleKeyQuery: ExtractSingleKey
24 | assertExactType(singleKeyQuery)
25 |
26 | // When the passed in type has multiple keys, it should return the type
27 | let multiKeyQuery: ExtractSingleKey
28 | assertExactType(multiKeyQuery)
29 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": [
5 | "DOM",
6 | "ES2020",
7 | "ES2020.Symbol.WellKnown"
8 | ],
9 | "moduleResolution": "node",
10 | "strict": true,
11 | "declaration": true,
12 | "outDir": "dist",
13 | "sourceMap": true,
14 | "allowSyntheticDefaultImports": true,
15 | "skipLibCheck": true
16 | },
17 | "include": [
18 | "src/**/*"
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/packages/vue-apollo-composable/tsconfig.lint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": [
4 | "**/*"
5 | ],
6 | "exclude": [
7 | "node_modules/**/*",
8 | "dist/**/*"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/.npmignore:
--------------------------------------------------------------------------------
1 | src/
2 | types/test/
3 | tests/
4 | .babelrc
5 | .eslintrc.js
6 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/README.md:
--------------------------------------------------------------------------------
1 | # Apollo and GraphQL for Vue.js (Options API)
2 |
3 | [ ](https://www.npmjs.com/package/@vue/apollo-option)
4 | [](https://www.apollographql.com/)
5 | [](https://vuejs.org/)
6 | [](https://circleci.com/gh/vuejs/vue-apollo/tree/v4)
7 |
8 |
9 |
10 |
11 |
12 | :book: Documentation [**for Vue 3**](http://v4.apollo.vuejs.org) | [for Vue 2](https://apollo.vuejs.org/)
13 |
14 | [:pen: Contributing guide](./CONTRIBUTING.md)
15 |
16 | [:heart: Sponsor me!](https://github.com/sponsors/Akryum)
17 |
18 | ```bash
19 | npm i @vue/apollo-option
20 | pnpm i @vue/apollo-option
21 | yarn add @vue/apollo-option
22 | ```
23 |
24 | ## Sponsors
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [require('@babel/preset-env'), { modules: false }],
4 | ],
5 | plugins: [
6 | require('@babel/plugin-proposal-class-properties'),
7 | [require('@babel/plugin-transform-for-of'), { assumeArray: true }],
8 | ],
9 | }
10 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/build/rollup.config.base.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel'
2 | import cjs from 'rollup-plugin-commonjs'
3 | import resolve from 'rollup-plugin-node-resolve'
4 | import replace from 'rollup-plugin-replace'
5 |
6 | const config = require('../package.json')
7 |
8 | export default {
9 | input: 'src/index.js',
10 | plugins: [
11 | resolve({
12 | jsnext: true,
13 | main: true,
14 | browser: true,
15 | }),
16 | cjs({
17 | exclude: 'src/**',
18 | }),
19 | babel({
20 | exclude: 'node_modules/**',
21 | }),
22 | replace({
23 | VERSION: JSON.stringify(config.version),
24 | }),
25 | ],
26 | external: ['@apollo/client', 'graphql-tag'],
27 | }
28 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/build/rollup.config.browser.js:
--------------------------------------------------------------------------------
1 | import { uglify } from 'rollup-plugin-uglify'
2 | import { minify } from 'uglify-es'
3 | import base from './rollup.config.base'
4 |
5 | const config = Object.assign({}, base, {
6 | output: {
7 | file: 'dist/vue-apollo-option.min.js',
8 | format: 'iife',
9 | name: 'VueApollo',
10 | },
11 | })
12 |
13 | config.plugins.push(uglify({}, minify))
14 |
15 | export default config
16 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/build/rollup.config.es.js:
--------------------------------------------------------------------------------
1 | import base from './rollup.config.base'
2 |
3 | const config = Object.assign({}, base, {
4 | output: {
5 | file: 'dist/vue-apollo-option.esm.mjs',
6 | format: 'es',
7 | name: 'vue-apollo',
8 | },
9 | })
10 |
11 | export default config
12 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/build/rollup.config.umd.js:
--------------------------------------------------------------------------------
1 | import base from './rollup.config.base'
2 |
3 | const config = Object.assign({}, base, {
4 | output: {
5 | file: 'dist/vue-apollo-option.umd.js',
6 | format: 'umd',
7 | name: 'vue-apollo',
8 | },
9 | })
10 |
11 | export default config
12 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/lib/consts.js:
--------------------------------------------------------------------------------
1 | exports.VUE_APOLLO_QUERY_KEYWORDS = [
2 | 'variables',
3 | 'watch',
4 | 'update',
5 | 'result',
6 | 'error',
7 | 'loadingKey',
8 | 'watchLoading',
9 | 'skip',
10 | 'throttle',
11 | 'debounce',
12 | 'subscribeToMore',
13 | 'prefetch',
14 | 'manual',
15 | ]
16 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/lib/utils.js:
--------------------------------------------------------------------------------
1 | const TD = require('throttle-debounce')
2 |
3 | function factory(action) {
4 | return (cb, time) => action(time, cb)
5 | }
6 |
7 | exports.throttle = factory(TD.throttle)
8 |
9 | exports.debounce = factory(TD.debounce)
10 |
11 | exports.reapply = function (options, context) {
12 | while (typeof options === 'function') {
13 | options = options.call(context)
14 | }
15 | return options
16 | }
17 |
18 | exports.omit = function (obj, properties) {
19 | return Object.entries(obj)
20 | .filter(([key]) => !properties.includes(key))
21 | .reduce((c, [key, val]) => {
22 | c[key] = val
23 | return c
24 | }, {})
25 | }
26 |
27 | exports.addGqlError = function (error) {
28 | if (error.graphQLErrors && error.graphQLErrors.length) {
29 | error.gqlError = error.graphQLErrors[0]
30 | }
31 | }
32 |
33 | exports.noop = () => {}
34 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/src/env.js:
--------------------------------------------------------------------------------
1 | export const isServer = typeof window === 'undefined'
2 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/src/index.js:
--------------------------------------------------------------------------------
1 | import { ApolloProvider } from './apollo-provider'
2 |
3 | export { ApolloProvider } from './apollo-provider'
4 |
5 | export function createApolloProvider(options) {
6 | return new ApolloProvider(options)
7 | }
8 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/tests/unit/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | jest: true,
4 | },
5 | }
6 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/.gitignore:
--------------------------------------------------------------------------------
1 | *.js
2 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/apollo-provider.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint no-unused-vars: 0 */
2 |
3 | import type { ApolloClient } from '@apollo/client/core/index.js'
4 | import type { App, AsyncComponentOptions, ComponentOptions } from 'vue'
5 | import type {
6 | ErrorHandler,
7 | VueApolloComponentOptions,
8 | WatchLoading,
9 | } from './options'
10 |
11 | export type VueApolloComponent = VueApolloComponentOptions | AsyncComponentOptions
12 |
13 | export interface ApolloProviderOptions {
14 | defaultClient: ApolloClient
15 | defaultOptions?: VueApolloComponentOptions
16 | clients?: { [key: string]: ApolloClient }
17 | watchLoading?: WatchLoading
18 | errorHandler?: ErrorHandler
19 | prefetch?: boolean
20 | }
21 |
22 | export class ApolloProvider {
23 | constructor(options: ApolloProviderOptions)
24 | install(app: App): void
25 |
26 | clients: { [key: string]: ApolloClient }
27 | defaultClient: ApolloClient
28 | }
29 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/index.d.ts:
--------------------------------------------------------------------------------
1 | import type { ApolloProviderOptions } from './apollo-provider'
2 | import { ApolloProvider } from './apollo-provider'
3 | import './vue'
4 |
5 | export { ApolloProvider }
6 | export function createApolloProvider(options: ApolloProviderOptions): ApolloProvider
7 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/test/App.vue:
--------------------------------------------------------------------------------
1 |
33 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/test/Decorator.ts:
--------------------------------------------------------------------------------
1 | import type { OperationVariables } from '@apollo/client/core'
2 | import type { VueApolloComponentOptions } from '../options'
3 | import gql from 'graphql-tag'
4 | import { Options, Vue } from 'vue-property-decorator'
5 |
6 | @Options({
7 | apollo: {
8 | allFilms: {
9 | query: gql``,
10 | variables(): OperationVariables {
11 | return {
12 | foo: this.foo,
13 | }
14 | },
15 | },
16 | } as VueApolloComponentOptions,
17 | })
18 | export default class Decorator extends Vue {
19 | allFilms = []
20 | foo = 'bar'
21 | }
22 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/test/index.ts:
--------------------------------------------------------------------------------
1 | import { ApolloClient, HttpLink } from '@apollo/client/core'
2 |
3 | import { createApp, h } from 'vue'
4 | import { createApolloProvider } from '../index'
5 |
6 | import App from './App'
7 | import Decorator from './Decorator'
8 | import 'isomorphic-fetch'
9 |
10 | const httpLink = new HttpLink({ uri: 'https://dummy.test.com' })
11 | const cache: any = 'dummy cache'
12 | const apolloClient = new ApolloClient({
13 | link: httpLink,
14 | cache,
15 | connectToDevTools: true,
16 | })
17 | const apolloProvider = createApolloProvider({
18 | defaultClient: apolloClient,
19 | defaultOptions: {
20 | $query: {
21 | fetchPolicy: 'cache-and-network',
22 | },
23 | },
24 | })
25 |
26 | /* eslint no-new: 0 */
27 | const app = createApp({
28 | el: '#app',
29 | render: () => h(App, [
30 | h(Decorator),
31 | ]),
32 | })
33 | app.use(apolloProvider)
34 |
35 | // test to able to call below methods
36 | console.log(apolloProvider.defaultClient.query)
37 | console.log(apolloProvider.clients.key.query)
38 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/test/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2015",
4 | "lib": [
5 | "es5",
6 | "es6",
7 | "dom",
8 | "es2015.core",
9 | "es2015.collection",
10 | "es2015.generator",
11 | "es2015.iterable",
12 | "es2015.promise",
13 | "es2015.proxy",
14 | "es2015.reflect",
15 | "es2015.symbol",
16 | "es2015.symbol.wellknown",
17 | "esnext.asynciterable"
18 | ],
19 | "experimentalDecorators": true,
20 | "module": "es2015",
21 | "moduleResolution": "node",
22 | "allowJs": true,
23 | "strict": true,
24 | "noImplicitAny": true,
25 | "allowSyntheticDefaultImports": true,
26 | "skipLibCheck": true
27 | },
28 | "include": [
29 | "*.ts",
30 | "../*.d.ts"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/utils.d.ts:
--------------------------------------------------------------------------------
1 | export type DeepApplyThisType = { [K in keyof T]: DeepApplyThisType } & ThisType
2 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/types/vue.d.ts:
--------------------------------------------------------------------------------
1 | import type { ApolloProvider } from './apollo-provider'
2 | import type { VueApolloComponentOptions } from './options'
3 | import type { DollarApollo } from './vue-apollo'
4 |
5 | declare module 'vue' {
6 | interface ComponentOptionsBase<
7 | Props,
8 | RawBindings,
9 | D,
10 | C extends ComputedOptions,
11 | M extends MethodOptions,
12 | Mixin extends ComponentOptionsMixin,
13 | Extends extends ComponentOptionsMixin,
14 | E extends EmitsOptions,
15 | EE extends string = string,
16 | Defaults = object,
17 | > {
18 | apolloProvider?: ApolloProvider
19 | apollo?: VueApolloComponentOptions>
20 | }
21 |
22 | interface ComponentCustomProperties {
23 | $apolloProvider: ApolloProvider
24 | $apollo: DollarApollo
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/packages/vue-apollo-option/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config'
2 |
3 | export default defineConfig({
4 | test: {
5 | globals: true,
6 | },
7 | })
8 |
--------------------------------------------------------------------------------
/packages/vue-apollo-ssr/README.md:
--------------------------------------------------------------------------------
1 | # Server-Side Rendering Utilities for Vue Apollo
2 |
3 | [ ](https://www.npmjs.com/package/@vue/apollo-ssr)
4 | [](https://www.apollographql.com/)
5 | [](https://vuejs.org/)
6 | [](https://circleci.com/gh/vuejs/vue-apollo/tree/v4)
7 |
8 |
9 |
10 |
11 |
12 | :book: Documentation [**for Vue 3**](http://v4.apollo.vuejs.org) | [for Vue 2](https://apollo.vuejs.org/)
13 |
14 | [:pen: Contributing guide](./CONTRIBUTING.md)
15 |
16 | [:heart: Sponsor me!](https://github.com/sponsors/Akryum)
17 |
18 | ```bash
19 | npm i @vue/apollo-ssr
20 | yarn add @vue/apollo-ssr
21 | ```
22 |
23 | ## Sponsors
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/packages/vue-apollo-ssr/build.mjs:
--------------------------------------------------------------------------------
1 | import fs from 'node:fs'
2 | import path from 'node:path'
3 | import process from 'node:process'
4 |
5 | const file = path.join(process.cwd(), 'dist', 'esm', 'package.json')
6 |
7 | fs.writeFileSync(file, JSON.stringify({
8 | type: 'module',
9 | }, null, 2), 'utf-8')
10 |
--------------------------------------------------------------------------------
/packages/vue-apollo-ssr/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "moduleResolution": "node",
6 | "strict": true,
7 | "sourceMap": true,
8 | "esModuleInterop": true,
9 | "skipLibCheck": true
10 | },
11 | "include": [
12 | "src/**/*"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/vue-apollo-util/README.md:
--------------------------------------------------------------------------------
1 | # Utilities for Vue Apollo
2 |
3 | [ ](https://www.npmjs.com/package/@vue/apollo-util)
4 | [](https://www.apollographql.com/)
5 | [](https://vuejs.org/)
6 | [](https://circleci.com/gh/vuejs/vue-apollo/tree/v4)
7 |
8 |
9 |
10 |
11 |
12 | :book: Documentation [**for Vue 3**](http://v4.apollo.vuejs.org) | [for Vue 2](https://apollo.vuejs.org/)
13 |
14 | [:pen: Contributing guide](./CONTRIBUTING.md)
15 |
16 | [:heart: Sponsor me!](https://github.com/sponsors/Akryum)
17 |
18 | ```bash
19 | npm i @vue/apollo-util
20 | pnpm i @vue/apollo-util
21 | yarn add @vue/apollo-util
22 | ```
23 |
24 | ## Sponsors
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/vue-apollo-util/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@vue/apollo-util",
3 | "version": "4.2.2",
4 | "description": "Apollo GraphQL for Vue - Utilities",
5 | "author": "Guillaume Chau ",
6 | "license": "MIT",
7 | "homepage": "https://apollo.vuejs.org/",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/vuejs/vue-apollo.git",
11 | "directory": "packages/vue-apollo-util"
12 | },
13 | "bugs": {
14 | "url": "https://github.com/vuejs/vue-apollo/issues"
15 | },
16 | "keywords": [
17 | "vue",
18 | "apollo",
19 | "graphql",
20 | "util"
21 | ],
22 | "publishConfig": {
23 | "access": "public"
24 | },
25 | "exports": {
26 | ".": {
27 | "types": "./dist/esm/index.d.ts",
28 | "import": "./dist/esm/index.js",
29 | "require": "./dist/cjs/index.js"
30 | },
31 | "./*": "./*"
32 | },
33 | "main": "dist/cjs/index.js",
34 | "types": "dist/esm/index.d.ts",
35 | "files": [
36 | "dist"
37 | ],
38 | "scripts": {
39 | "dev": "pnpm run build --watch",
40 | "build": "rm -rf dist && tsc --outDir dist/esm -d && tsc --outDir dist/cjs --module commonjs --target ES2017",
41 | "prepublishOnly": "pnpm run build"
42 | },
43 | "devDependencies": {
44 | "@apollo/client": "^3.7.7",
45 | "graphql": "^16.6.0",
46 | "typescript": "^4.7.4"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/packages/vue-apollo-util/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './errorLog'
2 |
--------------------------------------------------------------------------------
/packages/vue-apollo-util/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "moduleResolution": "node",
6 | "strict": true,
7 | "sourceMap": true,
8 | "esModuleInterop": true,
9 | "skipLibCheck": true
10 | },
11 | "include": [
12 | "src/**/*"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - packages/*
3 | onlyBuiltDependencies:
4 | - '@apollo/protobufjs'
5 | - core-js
6 | - core-js-pure
7 | - cypress
8 | - esbuild
9 | - nodemon
10 | - vue-demi
11 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {}
2 |
--------------------------------------------------------------------------------