This repository has been archived by the owner on Jul 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move cache and links to separate files
- Loading branch information
Showing
2 changed files
with
185 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { InMemoryCache } from "@apollo/client"; | ||
|
||
export const cache = new InMemoryCache({ | ||
typePolicies: { | ||
Query: { | ||
fields: { | ||
distroEvents: { | ||
keyArgs: ["$distroId"], | ||
}, | ||
projectEvents: { | ||
keyArgs: ["$identifier"], | ||
}, | ||
repoEvents: { | ||
keyArgs: ["$id"], | ||
}, | ||
}, | ||
}, | ||
GeneralSubscription: { | ||
keyFields: false, | ||
}, | ||
DistroEventsPayload: { | ||
fields: { | ||
count: { | ||
merge(existing = 0, incoming = 0) { | ||
return existing + incoming; | ||
}, | ||
}, | ||
eventLogEntries: { | ||
merge(existing = [], incoming = []) { | ||
return [...existing, ...incoming]; | ||
}, | ||
}, | ||
}, | ||
}, | ||
ProjectEvents: { | ||
fields: { | ||
count: { | ||
merge(existing = 0, incoming = 0) { | ||
return existing + incoming; | ||
}, | ||
}, | ||
eventLogEntries: { | ||
merge(existing = [], incoming = []) { | ||
return [...existing, ...incoming]; | ||
}, | ||
}, | ||
}, | ||
}, | ||
ProjectAlias: { | ||
keyFields: false, | ||
}, | ||
Project: { | ||
keyFields: false, | ||
}, | ||
User: { | ||
keyFields: ["userId"], | ||
}, | ||
Task: { | ||
keyFields: ["execution", "id"], | ||
fields: { | ||
annotation: { | ||
merge(existing, incoming, { mergeObjects }) { | ||
return mergeObjects(existing, incoming); | ||
}, | ||
}, | ||
taskLogs: { | ||
merge(_, incoming) { | ||
return incoming; | ||
}, | ||
}, | ||
}, | ||
}, | ||
Patch: { | ||
fields: { | ||
time: { | ||
merge(existing, incoming, { mergeObjects }) { | ||
return mergeObjects(existing, incoming); | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { ApolloLink } from "@apollo/client"; | ||
import { onError } from "@apollo/client/link/error"; | ||
import { RetryLink } from "@apollo/client/link/retry"; | ||
import { routes } from "constants/routes"; | ||
import { | ||
leaveBreadcrumb, | ||
SentryBreadcrumb, | ||
reportError, | ||
} from "utils/errorReporting"; | ||
import { omit } from "utils/object"; | ||
|
||
export const authLink = (logout: () => void): ApolloLink => | ||
onError(({ networkError }) => { | ||
if ( | ||
// must perform these checks so that TS does not complain bc typings for network does not include 'statusCode' | ||
networkError && | ||
"statusCode" in networkError && | ||
networkError.statusCode === 401 && | ||
window.location.pathname !== routes.login | ||
) { | ||
leaveBreadcrumb( | ||
"Not Authenticated", | ||
{ status_code: 401 }, | ||
SentryBreadcrumb.User, | ||
); | ||
logout(); | ||
} | ||
}); | ||
|
||
export const logErrorsLink = onError(({ graphQLErrors, operation }) => { | ||
if (Array.isArray(graphQLErrors)) { | ||
graphQLErrors.forEach((gqlErr) => { | ||
const fingerprint = [operation.operationName]; | ||
if (gqlErr?.path?.length) { | ||
fingerprint.push(...gqlErr.path); | ||
} | ||
reportError(new Error(gqlErr.message), { | ||
fingerprint, | ||
tags: { operationName: operation.operationName }, | ||
context: { | ||
gqlErr, | ||
variables: operation.variables, | ||
}, | ||
}).warning(); | ||
}); | ||
} | ||
// dont track network errors here because they are | ||
// very common when a user is not authenticated | ||
}); | ||
|
||
export const authenticateIfSuccessfulLink = ( | ||
dispatchAuthenticated: () => void, | ||
): ApolloLink => | ||
new ApolloLink((operation, forward) => | ||
forward(operation).map((response) => { | ||
if (response && response.data) { | ||
// if there is data in response then server responded with 200; therefore, is authenticated. | ||
dispatchAuthenticated(); | ||
} | ||
leaveBreadcrumb( | ||
"Graphql Request", | ||
{ | ||
operationName: operation.operationName, | ||
variables: operation.variables, | ||
status: !response.errors ? "OK" : "ERROR", | ||
errors: response.errors, | ||
}, | ||
SentryBreadcrumb.HTTP, | ||
); | ||
return response; | ||
}), | ||
); | ||
|
||
export const leaveBreadcrumbLink = (secretFields: string[]): ApolloLink => | ||
new ApolloLink((operation, forward) => | ||
forward(operation).map((response) => { | ||
leaveBreadcrumb( | ||
"Graphql Request", | ||
{ | ||
operationName: operation.operationName, | ||
variables: omit(operation.variables, secretFields), | ||
status: !response.errors ? "OK" : "ERROR", | ||
errors: response.errors, | ||
}, | ||
SentryBreadcrumb.HTTP, | ||
); | ||
return response; | ||
}), | ||
); | ||
|
||
export const retryLink = new RetryLink({ | ||
delay: { | ||
initial: 300, | ||
max: 3000, | ||
jitter: true, | ||
}, | ||
attempts: { | ||
max: 5, | ||
retryIf: (error): boolean => | ||
error && error.response && error.response.status >= 500, | ||
}, | ||
}); |