graphql-code-generator
graphql-code-generator copied to clipboard
[typescript-vue-apollo-smart-ops] The TypeScript types for subscriptions are completely broken
Describe the bug
I'm wondering how no one's noticed this before, but the subscription functions generated using createSmartSubscriptionOptionsFunction
return incomplete or even invalid types.
The main issues are:
- There's no generic argument for specifying the value of
this
inside the options functions likevariables()
. The functions generated for standard queries & mutations do have this argument, however. Instead, by default thethis
value seems to just be the options object, which definitely is a bug.
apollo: {
$subscribe: {
userCreated: useUserCreatedSubscription({
variables() {
return {
id: this.id, // TS will throw an error that `this` does not have an `id` field, even if it's available in the Vue component
}
}
})
}
}
The examples in the docs also only show variables having static/hardcoded values, even tho no one's ever going to have static/hardcoded variables for these operations. Almost always you're going to want to rely on the properties of the Vue component to resolve the variables.
- The subscription options type doesn't specify that the
result
andskip
functions are available, so if you use them, TS will throw an error. This issue I was at least able to solve myself through type augmentation.
Lastly, I wanted to comment on the fact that the need to specify the type of this
inside these option objects isn't very good DX in the first place, because you end up duplicating these types first in the actual Vue component and then inside this generic argument. But here I will assume that there's a technical reason why these functions can't correctly resolve the this
values automatically.
data() {
return {id: null}
},
apollo: {
user: useMainUserDataQuery<Vue & {id: null | string}>({
variables() {
return { id: this.id }
}
})
}
Your Example Website or App
none
Steps to Reproduce the Bug or Issue
No reproduction is really necessary, you can just look at the TS type definitions to see what I mean. I also tried to provide short code examples above.
Expected behavior
- Subscription option type should contain a definition for the
skip()
andresult()
functions - Subscription type should either infer the Vue component's this value correctly or at the very least allow specifying it through a generic argument
Screenshots or Videos
No response
Platform
- OS: Ubuntu 20
- NodeJS: 16.14.0
-
graphql
version: 15.8.0 - @graphql-codegen/typescript-vue-apollo-smart-ops version: 2.3.1
Codegen Config File
overwrite: true
schema: 'http://localhost:3000/graphql'
documents:
- 'src/graphql/**/*.gql'
- 'src/**/*.{ts,tsx,js,jsx,vue}'
generates:
src/graphql/generated/graphql.ts:
plugins:
- 'typescript'
- 'typescript-operations'
- 'typescript-document-nodes'
- 'typescript-vue-apollo-smart-ops'
config:
vueApolloErrorHandlerFunction: handleApolloError
vueApolloErrorHandlerFunctionImportFrom: '@/config/vueApolloSmartOpsConfig'
scalars:
JSONObject: Record<string, unknown>
Additional context
No response
Are you using Vue 3?
I had to write a patch script to get it working with Vue 3.
Something along those lines:
const patchVue3 = () => {
let file = fs.readFileSync(options.typesPath, "utf-8").toString();
file = file.split("@vue/composition-api").join("vue");
fs.writeFileSync(options.typesPath, file);
console.log(clc.green(`[codegen] Vue3 patch applied to ${options.typesPath}`));
}
@cwdx Nope, this is just on Vue 2. I ended up discarding this plugin, it's too much trouble than it's worth. Besides the issues I mentioned, the core vue-apollo-smart-ops lib relies on an old version of Apollo Client (v2), which is another deal breaker.
If you are using Vue 3 (and especially if you are using vue apollo 4 composables), I highly recommend checking out typed-document-node documentation.
It is a more generic way to get typed graphql query support and is supported by the most popular graphql libraries (including vue-apollo 4)