Merge branch 'feature/apollo-link-state' into 'master'
Fix login/logout flow See merge request framasoft/mobilizon!48
This commit is contained in:
commit
759a740625
1363
js/package-lock.json
generated
1363
js/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -12,16 +12,20 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"apollo-absinthe-upload-link": "^1.4.0",
|
"apollo-absinthe-upload-link": "^1.4.0",
|
||||||
"apollo-cache-inmemory": "^1.3.11",
|
"apollo-cache-inmemory": "^1.4.0",
|
||||||
"apollo-link": "^1.2.4",
|
"apollo-client": "^2.4.9",
|
||||||
"apollo-link-http": "^1.5.7",
|
"apollo-link": "^1.2.6",
|
||||||
|
"apollo-link-http": "^1.5.9",
|
||||||
|
"apollo-link-state": "^0.4.2",
|
||||||
"easygettext": "^2.7.0",
|
"easygettext": "^2.7.0",
|
||||||
"graphql-tag": "^2.9.0",
|
"graphql": "^14.1.1",
|
||||||
|
"graphql-tag": "^2.10.1",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
"material-design-icons": "^3.0.1",
|
"material-design-icons": "^3.0.1",
|
||||||
"ngeohash": "^0.6.3",
|
"ngeohash": "^0.6.3",
|
||||||
"register-service-worker": "^1.4.1",
|
"register-service-worker": "^1.4.1",
|
||||||
"vue": "^2.5.17",
|
"vue": "^2.5.17",
|
||||||
"vue-apollo": "^3.0.0-beta.26",
|
"vue-apollo": "^3.0.0-beta.27",
|
||||||
"vue-class-component": "^6.3.2",
|
"vue-class-component": "^6.3.2",
|
||||||
"vue-gettext": "^2.1.1",
|
"vue-gettext": "^2.1.1",
|
||||||
"vue-gravatar": "^1.3.0",
|
"vue-gravatar": "^1.3.0",
|
||||||
|
@ -34,6 +38,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.1.0",
|
"@types/chai": "^4.1.0",
|
||||||
|
"@types/lodash": "^4.14.120",
|
||||||
"@types/mocha": "^5.2.4",
|
"@types/mocha": "^5.2.4",
|
||||||
"@vue/cli-plugin-babel": "^3.1.1",
|
"@vue/cli-plugin-babel": "^3.1.1",
|
||||||
"@vue/cli-plugin-e2e-nightwatch": "^3.1.1",
|
"@vue/cli-plugin-e2e-nightwatch": "^3.1.1",
|
||||||
|
@ -49,7 +54,6 @@
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
"tslint-config-airbnb": "^5.11.1",
|
"tslint-config-airbnb": "^5.11.1",
|
||||||
"typescript": "^3.0.0",
|
"typescript": "^3.0.0",
|
||||||
"vue-cli-plugin-apollo": "^0.17.4",
|
|
||||||
"vue-template-compiler": "^2.5.17",
|
"vue-template-compiler": "^2.5.17",
|
||||||
"webpack-bundle-analyzer": "^3.0.3"
|
"webpack-bundle-analyzer": "^3.0.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
direction="top"
|
direction="top"
|
||||||
open-on-hover
|
open-on-hover
|
||||||
transition="scale-transition"
|
transition="scale-transition"
|
||||||
v-if="user"
|
v-if="currentUser"
|
||||||
>
|
>
|
||||||
<v-btn
|
<v-btn
|
||||||
slot="activator"
|
slot="activator"
|
||||||
|
@ -152,9 +152,16 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import NavBar from '@/components/NavBar.vue';
|
import NavBar from '@/components/NavBar.vue';
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
import { AUTH_USER_ACTOR, AUTH_USER_ID } from '@/constants';
|
import { AUTH_TOKEN, AUTH_USER_ACTOR, AUTH_USER_EMAIL, AUTH_USER_ID } from '@/constants';
|
||||||
|
import { CURRENT_USER_CLIENT, UPDATE_CURRENT_USER_CLIENT } from '@/graphql/user';
|
||||||
|
import { ICurrentUser } from '@/types/current-user.model'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
apollo: {
|
||||||
|
currentUser: {
|
||||||
|
query: CURRENT_USER_CLIENT
|
||||||
|
}
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
NavBar,
|
NavBar,
|
||||||
},
|
},
|
||||||
|
@ -162,7 +169,6 @@ import { AUTH_USER_ACTOR, AUTH_USER_ID } from '@/constants';
|
||||||
export default class App extends Vue {
|
export default class App extends Vue {
|
||||||
drawer = false;
|
drawer = false;
|
||||||
fab = false;
|
fab = false;
|
||||||
user = localStorage.getItem(AUTH_USER_ID);
|
|
||||||
items = [
|
items = [
|
||||||
{
|
{
|
||||||
icon: 'poll', text: 'Events', route: 'EventList', role: null,
|
icon: 'poll', text: 'Events', route: 'EventList', role: null,
|
||||||
|
@ -183,9 +189,14 @@ export default class App extends Vue {
|
||||||
show: false,
|
show: false,
|
||||||
text: '',
|
text: '',
|
||||||
};
|
};
|
||||||
|
currentUser!: ICurrentUser;
|
||||||
|
|
||||||
actor = localStorage.getItem(AUTH_USER_ACTOR);
|
actor = localStorage.getItem(AUTH_USER_ACTOR);
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
this.initializeCurrentUser()
|
||||||
|
}
|
||||||
|
|
||||||
get displayed_name () {
|
get displayed_name () {
|
||||||
// FIXME: load actor
|
// FIXME: load actor
|
||||||
return 'no implemented';
|
return 'no implemented';
|
||||||
|
@ -199,12 +210,28 @@ export default class App extends Vue {
|
||||||
}
|
}
|
||||||
|
|
||||||
getUser () {
|
getUser () {
|
||||||
return this.user === undefined ? false : this.user;
|
return this.currentUser.id ? this.currentUser : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleDrawer () {
|
toggleDrawer () {
|
||||||
this.drawer = !this.drawer;
|
this.drawer = !this.drawer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initializeCurrentUser() {
|
||||||
|
const userId = localStorage.getItem(AUTH_USER_ID);
|
||||||
|
const userEmail = localStorage.getItem(AUTH_USER_EMAIL);
|
||||||
|
const token = localStorage.getItem(AUTH_TOKEN);
|
||||||
|
|
||||||
|
if (userId && userEmail && token) {
|
||||||
|
return this.$apollo.mutate({
|
||||||
|
mutation: UPDATE_CURRENT_USER_CLIENT,
|
||||||
|
variables: {
|
||||||
|
id: userId,
|
||||||
|
email: userEmail,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
25
js/src/apollo/user.ts
Normal file
25
js/src/apollo/user.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
export const currentUser = {
|
||||||
|
defaults: {
|
||||||
|
currentUser: {
|
||||||
|
__typename: 'CurrentUser',
|
||||||
|
id: null,
|
||||||
|
email: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
resolvers: {
|
||||||
|
Mutation: {
|
||||||
|
updateCurrentUser: (_, { id, email }, { cache }) => {
|
||||||
|
const data = {
|
||||||
|
currentUser: {
|
||||||
|
id,
|
||||||
|
email,
|
||||||
|
__typename: 'CurrentUser',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
cache.writeData({ data });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
|
@ -67,6 +67,8 @@
|
||||||
import { validateEmailField, validateRequiredField } from '@/utils/validators';
|
import { validateEmailField, validateRequiredField } from '@/utils/validators';
|
||||||
import { saveUserData } from '@/utils/auth';
|
import { saveUserData } from '@/utils/auth';
|
||||||
import { ILogin } from '@/types/login.model'
|
import { ILogin } from '@/types/login.model'
|
||||||
|
import { UPDATE_CURRENT_USER_CLIENT } from '@/graphql/user'
|
||||||
|
import { onLogin } from '@/vue-apollo'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
@ -123,6 +125,17 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
saveUserData(result.data.login);
|
saveUserData(result.data.login);
|
||||||
|
|
||||||
|
await this.$apollo.mutate({
|
||||||
|
mutation: UPDATE_CURRENT_USER_CLIENT,
|
||||||
|
variables: {
|
||||||
|
id: result.data.login.user.id,
|
||||||
|
email: this.credentials.email,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onLogin(this.$apollo);
|
||||||
|
|
||||||
this.$router.push({ name: 'Home' });
|
this.$router.push({ name: 'Home' });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
src="https://picsum.photos/1200/900"
|
src="https://picsum.photos/1200/900"
|
||||||
dark
|
dark
|
||||||
height="300"
|
height="300"
|
||||||
v-if="!user"
|
v-if="!currentUser.id"
|
||||||
>
|
>
|
||||||
<v-container fill-height>
|
<v-container fill-height>
|
||||||
<v-layout align-center>
|
<v-layout align-center>
|
||||||
|
@ -88,12 +88,17 @@
|
||||||
import { AUTH_USER_ACTOR, AUTH_USER_ID } from '@/constants';
|
import { AUTH_USER_ACTOR, AUTH_USER_ID } from '@/constants';
|
||||||
import { FETCH_EVENTS } from '@/graphql/event';
|
import { FETCH_EVENTS } from '@/graphql/event';
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
import { ICurrentUser } from '@/types/current-user.model';
|
||||||
|
import { CURRENT_USER_CLIENT } from '@/graphql/user';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
apollo: {
|
apollo: {
|
||||||
events: {
|
events: {
|
||||||
query: FETCH_EVENTS,
|
query: FETCH_EVENTS,
|
||||||
},
|
},
|
||||||
|
currentUser: {
|
||||||
|
query: CURRENT_USER_CLIENT,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class Home extends Vue {
|
export default class Home extends Vue {
|
||||||
|
@ -109,7 +114,7 @@
|
||||||
country = { name: null };
|
country = { name: null };
|
||||||
// FIXME: correctly parse local storage
|
// FIXME: correctly parse local storage
|
||||||
actor = JSON.parse(localStorage.getItem(AUTH_USER_ACTOR) || '{}');
|
actor = JSON.parse(localStorage.getItem(AUTH_USER_ACTOR) || '{}');
|
||||||
user = localStorage.getItem(AUTH_USER_ID);
|
currentUser!: ICurrentUser;
|
||||||
|
|
||||||
get displayed_name() {
|
get displayed_name() {
|
||||||
return this.actor.name === null ? this.actor.preferredUsername : this.actor.name;
|
return this.actor.name === null ? this.actor.preferredUsername : this.actor.name;
|
||||||
|
@ -126,7 +131,7 @@
|
||||||
|
|
||||||
geoLocalize() {
|
geoLocalize() {
|
||||||
const router = this.$router;
|
const router = this.$router;
|
||||||
const sessionCity = sessionStorage.getItem('City')
|
const sessionCity = sessionStorage.getItem('City');
|
||||||
if (sessionCity) {
|
if (sessionCity) {
|
||||||
router.push({ name: 'EventList', params: { location: sessionCity } });
|
router.push({ name: 'EventList', params: { location: sessionCity } });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -46,12 +46,15 @@
|
||||||
</template>
|
</template>
|
||||||
</v-autocomplete>
|
</v-autocomplete>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
|
|
||||||
|
<span v-if="currentUser.id" @click="logout()">Logout</span>
|
||||||
|
|
||||||
<v-menu
|
<v-menu
|
||||||
offset-y
|
offset-y
|
||||||
:close-on-content-click="false"
|
:close-on-content-click="false"
|
||||||
:nudge-width="200"
|
:nudge-width="200"
|
||||||
v-model="notificationMenu"
|
v-model="notificationMenu"
|
||||||
v-if="user"
|
v-if="currentUser.id"
|
||||||
>
|
>
|
||||||
<v-btn icon slot="activator">
|
<v-btn icon slot="activator">
|
||||||
<v-badge left color="red">
|
<v-badge left color="red">
|
||||||
|
@ -83,7 +86,7 @@
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
<v-btn v-if="!user" :to="{ name: 'Login' }">
|
<v-btn v-if="!currentUser.id" :to="{ name: 'Login' }">
|
||||||
<translate>Login</translate>
|
<translate>Login</translate>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
|
@ -96,11 +99,14 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
||||||
import { AUTH_USER_ACTOR, AUTH_USER_ID } from '@/constants';
|
import { AUTH_USER_ACTOR } from '@/constants';
|
||||||
import { SEARCH } from '@/graphql/search';
|
import { SEARCH } from '@/graphql/search';
|
||||||
|
import { CURRENT_USER_CLIENT } from '@/graphql/user';
|
||||||
|
import { onLogout } from '@/vue-apollo';
|
||||||
|
import { deleteUserData } from '@/utils/auth';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
apollo: {
|
apollo: {
|
||||||
search: {
|
search: {
|
||||||
query: SEARCH,
|
query: SEARCH,
|
||||||
|
@ -113,6 +119,9 @@ import { SEARCH } from '@/graphql/search';
|
||||||
return !this.searchText;
|
return !this.searchText;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
currentUser: {
|
||||||
|
query: CURRENT_USER_CLIENT
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class NavBar extends Vue {
|
export default class NavBar extends Vue {
|
||||||
|
@ -128,7 +137,6 @@ export default class NavBar extends Vue {
|
||||||
searchText: string | null = null;
|
searchText: string | null = null;
|
||||||
searchSelect = null;
|
searchSelect = null;
|
||||||
actor = localStorage.getItem(AUTH_USER_ACTOR);
|
actor = localStorage.getItem(AUTH_USER_ACTOR);
|
||||||
user = localStorage.getItem(AUTH_USER_ID);
|
|
||||||
|
|
||||||
get items() {
|
get items() {
|
||||||
return this.search.map(searchEntry => {
|
return this.search.map(searchEntry => {
|
||||||
|
@ -165,5 +173,13 @@ export default class NavBar extends Vue {
|
||||||
this.$apollo.queries['search'].refetch();
|
this.$apollo.queries['search'].refetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
alert('logout !');
|
||||||
|
|
||||||
|
deleteUserData();
|
||||||
|
|
||||||
|
return onLogout(this.$apollo);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export const AUTH_TOKEN = 'auth-token';
|
export const AUTH_TOKEN = 'auth-token';
|
||||||
export const AUTH_USER_ID = 'auth-user-id';
|
export const AUTH_USER_ID = 'auth-user-id';
|
||||||
|
export const AUTH_USER_EMAIL = 'auth-user-email';
|
||||||
export const AUTH_USER_ACTOR = 'auth-user-actor';
|
export const AUTH_USER_ACTOR = 'auth-user-actor';
|
||||||
|
|
|
@ -19,3 +19,18 @@ mutation ValidateUser($token: String!) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const CURRENT_USER_CLIENT = gql`
|
||||||
|
query {
|
||||||
|
currentUser @client {
|
||||||
|
id,
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const UPDATE_CURRENT_USER_CLIENT = gql`
|
||||||
|
mutation UpdateCurrentUser($id: Int!, $email: String!) {
|
||||||
|
updateCurrentUser(id: $id, email: $email) @client
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
|
@ -9,8 +9,7 @@ import 'material-design-icons/iconfont/material-icons.css';
|
||||||
import 'vuetify/dist/vuetify.min.css';
|
import 'vuetify/dist/vuetify.min.css';
|
||||||
import App from '@/App.vue';
|
import App from '@/App.vue';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
// import store from './store';
|
import { apolloProvider } from './vue-apollo';
|
||||||
import { createProvider } from './vue-apollo';
|
|
||||||
|
|
||||||
const translations = require('@/i18n/translations.json');
|
const translations = require('@/i18n/translations.json');
|
||||||
|
|
||||||
|
@ -36,6 +35,6 @@ new Vue({
|
||||||
router,
|
router,
|
||||||
el: '#app',
|
el: '#app',
|
||||||
template: '<App/>',
|
template: '<App/>',
|
||||||
apolloProvider: createProvider(),
|
apolloProvider,
|
||||||
components: { App },
|
components: { App },
|
||||||
});
|
});
|
||||||
|
|
4
js/src/types/current-user.model.ts
Normal file
4
js/src/types/current-user.model.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export interface ICurrentUser {
|
||||||
|
id: number,
|
||||||
|
email: string,
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
|
import { ICurrentUser } from '@/types/current-user.model';
|
||||||
|
|
||||||
export interface ILogin {
|
export interface ILogin {
|
||||||
user: {
|
user: ICurrentUser,
|
||||||
id: number,
|
|
||||||
},
|
|
||||||
|
|
||||||
token: string,
|
token: string,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
import { AUTH_TOKEN, AUTH_USER_ID } from '@/constants';
|
import { AUTH_TOKEN, AUTH_USER_EMAIL, AUTH_USER_ID } from '@/constants';
|
||||||
import { ILogin } from '@/types/login.model';
|
import { ILogin } from '@/types/login.model';
|
||||||
|
|
||||||
export function saveUserData(obj: ILogin) {
|
export function saveUserData(obj: ILogin) {
|
||||||
localStorage.setItem(AUTH_USER_ID, `${obj.user.id}`);
|
localStorage.setItem(AUTH_USER_ID, `${obj.user.id}`);
|
||||||
|
localStorage.setItem(AUTH_USER_EMAIL, obj.user.email);
|
||||||
localStorage.setItem(AUTH_TOKEN, obj.token);
|
localStorage.setItem(AUTH_TOKEN, obj.token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function deleteUserData() {
|
||||||
|
for (const key of [ AUTH_USER_ID, AUTH_USER_EMAIL, AUTH_TOKEN ]) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,9 +3,13 @@ import VueApollo from 'vue-apollo';
|
||||||
import { ApolloLink } from 'apollo-link';
|
import { ApolloLink } from 'apollo-link';
|
||||||
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
|
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
|
||||||
import { createLink } from 'apollo-absinthe-upload-link';
|
import { createLink } from 'apollo-absinthe-upload-link';
|
||||||
import { createApolloClient, restartWebsockets } from 'vue-cli-plugin-apollo/graphql-client';
|
|
||||||
import { AUTH_TOKEN } from './constants';
|
import { AUTH_TOKEN } from './constants';
|
||||||
import { GRAPHQL_API_ENDPOINT, GRAPHQL_API_FULL_PATH } from './api/_entrypoint';
|
import { GRAPHQL_API_ENDPOINT, GRAPHQL_API_FULL_PATH } from './api/_entrypoint';
|
||||||
|
import { withClientState } from 'apollo-link-state';
|
||||||
|
import { currentUser } from '@/apollo/user';
|
||||||
|
import merge from 'lodash/merge';
|
||||||
|
import { ApolloClient } from 'apollo-client';
|
||||||
|
import { DollarApollo } from 'vue-apollo/types/vue-apollo';
|
||||||
|
|
||||||
// Install the vue plugin
|
// Install the vue plugin
|
||||||
Vue.use(VueApollo);
|
Vue.use(VueApollo);
|
||||||
|
@ -51,82 +55,40 @@ const uploadLink = createLink({
|
||||||
uri: httpEndpoint,
|
uri: httpEndpoint,
|
||||||
});
|
});
|
||||||
|
|
||||||
// const link = ApolloLink.from([
|
const stateLink = withClientState({
|
||||||
// uploadLink,
|
...merge(currentUser),
|
||||||
// authMiddleware,
|
cache,
|
||||||
// HttpLink,
|
});
|
||||||
// ]);
|
|
||||||
|
|
||||||
const link = authMiddleware.concat(uploadLink);
|
const link = stateLink.concat(authMiddleware).concat(uploadLink);
|
||||||
|
|
||||||
// Config
|
const apolloClient = new ApolloClient({
|
||||||
const defaultOptions = {
|
|
||||||
cache,
|
cache,
|
||||||
link,
|
link,
|
||||||
// You can use `https` for secure connection (recommended in production)
|
|
||||||
httpEndpoint,
|
|
||||||
// You can use `wss` for secure connection (recommended in production)
|
|
||||||
// Use `null` to disable subscriptions
|
|
||||||
// wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:4000/graphql',
|
|
||||||
// LocalStorage token
|
|
||||||
tokenName: AUTH_TOKEN,
|
|
||||||
// Enable Automatic Query persisting with Apollo Engine
|
|
||||||
persisting: false,
|
|
||||||
// Use websockets for everything (no HTTP)
|
|
||||||
// You need to pass a `wsEndpoint` for this to work
|
|
||||||
websocketsOnly: false,
|
|
||||||
// Is being rendered on the server?
|
|
||||||
ssr: false,
|
|
||||||
defaultHttpLink: false,
|
|
||||||
connectToDevTools: true,
|
connectToDevTools: true,
|
||||||
};
|
});
|
||||||
|
|
||||||
// Call this in the Vue app file
|
apolloClient.onResetStore(stateLink.writeDefaults as any);
|
||||||
export function createProvider(options = {}) {
|
|
||||||
// Create apollo client
|
|
||||||
const { apolloClient, wsClient } = createApolloClient({
|
|
||||||
...defaultOptions,
|
|
||||||
...options,
|
|
||||||
});
|
|
||||||
apolloClient.wsClient = wsClient;
|
|
||||||
|
|
||||||
// Create vue apollo provider
|
export const apolloProvider = new VueApollo({
|
||||||
return new VueApollo({
|
|
||||||
defaultClient: apolloClient,
|
defaultClient: apolloClient,
|
||||||
// defaultOptions: {
|
|
||||||
// $query: {
|
|
||||||
// fetchPolicy: 'cache-and-network',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
errorHandler(error) {
|
errorHandler(error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message);
|
console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Manually call this when user log in
|
// Manually call this when user log in
|
||||||
export async function onLogin(apolloClient, token) {
|
export function onLogin(apolloClient) {
|
||||||
if (typeof localStorage !== 'undefined' && token) {
|
// if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
|
||||||
localStorage.setItem(AUTH_TOKEN, token);
|
|
||||||
}
|
|
||||||
if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
|
|
||||||
try {
|
|
||||||
await apolloClient.resetStore();
|
|
||||||
} catch (e) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('%cError on cache reset (login)', 'color: orange;', e.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manually call this when user log out
|
// Manually call this when user log out
|
||||||
export async function onLogout(apolloClient) {
|
export async function onLogout(apolloClient: DollarApollo<any>) {
|
||||||
if (typeof localStorage !== 'undefined') {
|
// if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
|
||||||
localStorage.removeItem(AUTH_TOKEN);
|
|
||||||
}
|
|
||||||
if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
|
|
||||||
try {
|
try {
|
||||||
await apolloClient.resetStore();
|
await apolloClient.provider.defaultClient.resetStore();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('%cError on cache reset (logout)', 'color: orange;', e.message);
|
console.log('%cError on cache reset (logout)', 'color: orange;', e.message);
|
||||||
|
|
|
@ -9,5 +9,14 @@ module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
new Dotenv({ path: path.resolve(process.cwd(), '../.env') }),
|
new Dotenv({ path: path.resolve(process.cwd(), '../.env') }),
|
||||||
],
|
],
|
||||||
|
module: {
|
||||||
|
rules: [ // fixes https://github.com/graphql/graphql-js/issues/1272
|
||||||
|
{
|
||||||
|
test: /\.mjs$/,
|
||||||
|
include: /node_modules/,
|
||||||
|
type: 'javascript/auto',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue