Move to Apollo v3

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2021-05-12 18:10:07 +02:00
parent 7cb40bd9e2
commit e96dcc42b9
51 changed files with 1247 additions and 817 deletions

View File

@@ -1,12 +1,14 @@
import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
import { CURRENT_USER_CLIENT } from "@/graphql/user";
import { ICurrentUserRole } from "@/types/enums";
import { ApolloCache } from "apollo-cache";
import { NormalizedCacheObject } from "apollo-cache-inmemory";
import { Resolvers } from "apollo-client/core/types";
import { ApolloCache, NormalizedCacheObject } from "@apollo/client/cache";
import { Resolvers } from "@apollo/client/core/types";
export default function buildCurrentUserResolver(
cache: ApolloCache<NormalizedCacheObject>
): Resolvers {
cache.writeData({
cache.writeQuery({
query: CURRENT_USER_CLIENT,
data: {
currentUser: {
__typename: "CurrentUser",
@@ -15,6 +17,12 @@ export default function buildCurrentUserResolver(
isLoggedIn: false,
role: ICurrentUserRole.USER,
},
},
});
cache.writeQuery({
query: CURRENT_ACTOR_CLIENT,
data: {
currentActor: {
__typename: "CurrentActor",
id: null,
@@ -47,7 +55,7 @@ export default function buildCurrentUserResolver(
},
};
localCache.writeData({ data });
localCache.writeQuery({ data, query: CURRENT_USER_CLIENT });
},
updateCurrentActor: (
_: any,
@@ -74,7 +82,7 @@ export default function buildCurrentUserResolver(
},
};
localCache.writeData({ data });
localCache.writeQuery({ data, query: CURRENT_ACTOR_CLIENT });
},
},
};

View File

@@ -1,16 +1,76 @@
import {
IntrospectionFragmentMatcher,
NormalizedCacheObject,
} from "apollo-cache-inmemory";
import { AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN } from "@/constants";
import { REFRESH_TOKEN } from "@/graphql/auth";
import { IFollower } from "@/types/actor/follower.model";
import { Paginate } from "@/types/paginate";
import { saveTokenData } from "@/utils/auth";
import { ApolloClient } from "apollo-client";
import {
ApolloClient,
FieldPolicy,
NormalizedCacheObject,
Reference,
TypePolicies,
} from "@apollo/client/core";
import introspectionQueryResultData from "../../fragmentTypes.json";
export const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData,
});
type possibleTypes = { name: string };
type schemaType = {
kind: string;
name: string;
possibleTypes: possibleTypes[];
};
// eslint-disable-next-line no-underscore-dangle
const types = introspectionQueryResultData.__schema.types as schemaType[];
export const possibleTypes = types.reduce((acc, type) => {
if (type.kind === "INTERFACE") {
acc[type.name] = type.possibleTypes.map(({ name }) => name);
}
return acc;
}, {} as Record<string, string[]>);
export const typePolicies: TypePolicies = {
Discussion: {
fields: {
comments: pageLimitPagination(),
},
},
Group: {
fields: {
organizedEvents: pageLimitPagination(["afterDatetime", "beforeDatetime"]),
},
},
Person: {
fields: {
organizedEvents: pageLimitPagination(),
participations: pageLimitPagination(["eventId"]),
memberships: pageLimitPagination(["group"]),
},
},
RootQueryType: {
fields: {
relayFollowers: paginatedLimitPagination<IFollower>(),
relayFollowings: paginatedLimitPagination<IFollower>([
"orderBy",
"direction",
]),
events: pageLimitPagination(),
groups: pageLimitPagination([
"preferredUsername",
"name",
"domain",
"local",
"suspended",
]),
persons: pageLimitPagination([
"preferredUsername",
"name",
"domain",
"local",
"suspended",
]),
},
},
};
export async function refreshAccessToken(
apolloClient: ApolloClient<NormalizedCacheObject>
@@ -37,3 +97,71 @@ export async function refreshAccessToken(
return false;
}
}
type KeyArgs = FieldPolicy<any>["keyArgs"];
export function pageLimitPagination<T = Reference>(
keyArgs: KeyArgs = false
): FieldPolicy<T[]> {
console.log("pageLimitPagination");
return {
keyArgs,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
merge(existing, incoming, { args }) {
console.log("existing", existing);
console.log("incoming", incoming);
// console.log("args", args);
if (!incoming) return existing;
if (!existing) return incoming; // existing will be empty the first time
return doMerge(existing as Array<T>, incoming as Array<T>, args);
},
};
}
export function paginatedLimitPagination<T = Paginate<any>>(
keyArgs: KeyArgs = false
): FieldPolicy<Paginate<T>> {
console.log("paginatedLimitPagination");
return {
keyArgs,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
merge(existing, incoming, { args }) {
if (!incoming) return existing;
if (!existing) return incoming; // existing will be empty the first time
return {
total: incoming.total,
elements: doMerge(existing.elements, incoming.elements, args),
};
},
};
}
function doMerge<T = any>(
existing: Array<T>,
incoming: Array<T>,
args: Record<string, any> | null
): Array<T> {
const merged = existing ? existing.slice(0) : [];
let res;
if (args) {
// Assume an page of 1 if args.page omitted.
const { page = 1, limit = 10 } = args;
console.log("args, selected", { page, limit });
for (let i = 0; i < incoming.length; ++i) {
merged[(page - 1) * limit + i] = incoming[i];
}
res = merged;
} else {
// It's unusual (probably a mistake) for a paginated field not
// to receive any arguments, so you might prefer to throw an
// exception here, instead of recovering by appending incoming
// onto the existing array.
res = [...merged, ...incoming];
}
console.log("doMerge returns", res);
return res;
}