-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathplugin.ts
More file actions
148 lines (132 loc) · 4.92 KB
/
plugin.ts
File metadata and controls
148 lines (132 loc) · 4.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import {
ApolloClient,
InMemoryCache,
createHttpLink,
concat,
} from '@apollo/client/core'
// @ts-expect-error #app resolved by Nuxt3
import { defineNuxtPlugin, NuxtApp } from '#app'
import { ApolloClients, provideApolloClient } from '@vue/apollo-composable'
import { setContext } from '@apollo/client/link/context';
import { parse, serialize } from "cookie-es";
import { ApolloModuleOptions } from './index'
// @ts-expect-error #build resolved by Nuxt3
import apolloOptions from '#build/apollo.options.mjs' // generated by index.ts
const apolloModuleOptions: ApolloModuleOptions = apolloOptions;
const DEFAULT_CLIENT_ID = 'default'
export default defineNuxtPlugin((nuxt: NuxtApp) => {
const apolloClients: {
[key: string]: ApolloClient<any>
} = {};
const tokenNames: Record<string, string> = {};
const clientConfigs = apolloModuleOptions.clientConfigs ? apolloModuleOptions.clientConfigs : apolloModuleOptions
const defaultCookieAttributes = apolloModuleOptions.cookieAttributes
function getTokenName(clientId: string) {
return 'apollo_' + clientId + '_token'
}
function getToken(name: string, opts = {}) {
if (process.server) {
const cookies = parse(nuxt.ssrContext?.req.headers.cookie || "", opts) as Record<string, string>
return cookies[name]
} else if (process.client) {
const cookies = parse(document.cookie, opts) as Record<string, string>
return cookies[name]
}
}
function getAuthLink(clientId: string, authenticationType = 'Bearer') {
const authLink = setContext(async (_, { headers }) => {
const token = getToken(getTokenName(clientId))
const authorizationHeader = token ? { Authorization: authenticationType ? 'Bearer ' + token : token } : {}
return {
headers: {
...headers,
...authorizationHeader,
},
}
})
return authLink
}
function serializeCookie(name:string, value: string | null, opts = {}) {
if (value == null) {
return serialize(name, '', { ...opts, maxAge: -1 });
}
return serialize(name, value, opts);
}
function writeClientCookie(name:string, value: string | null, opts = {}) {
if (process.client) {
document.cookie = serializeCookie(name, value, opts);
}
}
for (const clientId in clientConfigs) {
const options = clientConfigs[clientId]
const authLink = getAuthLink(clientId, options.authenticationType)
const httpLink = createHttpLink(options)
const cache = new InMemoryCache();
if (process.server) {
const apolloClient = new ApolloClient(Object.assign(options, {
ssrMode: true,
link: concat(authLink, httpLink),
cache: new InMemoryCache()
}))
nuxt.hook("app:rendered", () => {
// store the result
nuxt.payload.data['apollo-' + clientId] = apolloClient.extract();
});
apolloClients[clientId] = apolloClient;
} else {
// restore to cache, so the client won't request
cache.restore(JSON.parse(JSON.stringify(nuxt.payload.data['apollo-' + clientId])))
const apolloClient = new ApolloClient(Object.assign(options, {
link: concat(authLink, httpLink),
cache: cache,
ssrForceFetchDelay: 100,
}))
apolloClients[clientId] = apolloClient;
}
}
const apolloHelpers = {
onLogin: async (token: string, clientId: string, cookieAttributes: any, skipResetStore = false) => {
clientId = clientId || DEFAULT_CLIENT_ID
cookieAttributes = cookieAttributes || defaultCookieAttributes
// Fallback for tokenExpires param
if (typeof cookieAttributes === 'number') cookieAttributes = { expires: cookieAttributes }
if (typeof cookieAttributes.expires === 'number') {
cookieAttributes.expires = new Date(Date.now()+ 86400*1000*cookieAttributes.expires)
}
writeClientCookie(getTokenName(clientId), token, cookieAttributes)
if (!skipResetStore) {
try {
await apolloClients[clientId].resetStore()
} catch (e: any) {
console.log('%cError on cache reset (setToken)', 'color: orange;', e.message)
}
}
},
onLogout: async (clientId = DEFAULT_CLIENT_ID, skipResetStore = false) => {
writeClientCookie(getTokenName(clientId), null)
if (!skipResetStore) {
try {
await apolloClients[clientId].resetStore()
} catch (e: any) {
console.log('%cError on cache reset (logout)', 'color: orange;', e.message)
}
}
},
getToken: (clientId = DEFAULT_CLIENT_ID) => {
return getToken(getTokenName(clientId))
}
}
// provide client, used in useQuery()
nuxt.vueApp.provide(ApolloClients, apolloClients)
// provide $apollo, used directly: $apollo.default
nuxt.provide("apollo", apolloClients)
nuxt.provide("apolloHelpers", apolloHelpers);
})
// @ts-expect-error #app resolved by Nuxt3
declare module '#app' {
interface NuxtApp {
$apollo: {
[key: string]: ApolloClient<any>
}
}
}