@trackunit/react-core-contexts 1.30.4 → 1.30.5-alpha-d37885bfce4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.js +94 -17
- package/index.esm.js +97 -20
- package/package.json +8 -8
- package/src/createApolloClient.d.ts +19 -0
- package/src/errorLink/errorLink.d.ts +2 -2
- package/src/errorLink/subscriptionErrorLink.d.ts +11 -0
package/index.cjs.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var client = require('@apollo/client');
|
|
5
|
+
var reactCoreHooks = require('@trackunit/react-core-hooks');
|
|
6
|
+
var react = require('react');
|
|
5
7
|
var context = require('@apollo/client/link/context');
|
|
6
8
|
var removeTypename = require('@apollo/client/link/remove-typename');
|
|
7
9
|
var utilities = require('@apollo/client/utilities');
|
|
8
|
-
var reactCoreHooks = require('@trackunit/react-core-hooks');
|
|
9
10
|
var graphql = require('graphql');
|
|
10
11
|
var graphqlSse = require('graphql-sse');
|
|
11
|
-
var react = require('react');
|
|
12
12
|
var error = require('@apollo/client/link/error');
|
|
13
13
|
var irisAppRuntimeCore = require('@trackunit/iris-app-runtime-core');
|
|
14
14
|
var reactCoreContextsApi = require('@trackunit/react-core-contexts-api');
|
|
@@ -19,7 +19,7 @@ var irisAppRuntimeCoreApi = require('@trackunit/iris-app-runtime-core-api');
|
|
|
19
19
|
/**
|
|
20
20
|
* This error link is used to capture error information, i. e. traceId, graphQL errors, network errors, etc.
|
|
21
21
|
*/
|
|
22
|
-
const createErrorLink = ({ errorHandler,
|
|
22
|
+
const createErrorLink = ({ errorHandler, getToken, }) => {
|
|
23
23
|
return error.onError(({ graphQLErrors, networkError, operation, forward }) => {
|
|
24
24
|
if (networkError) {
|
|
25
25
|
// We skip the error logging if the error is an AbortError
|
|
@@ -67,7 +67,7 @@ const createErrorLink = ({ errorHandler, token, }) => {
|
|
|
67
67
|
x.message.includes("Invalid token specified") ||
|
|
68
68
|
x.message.includes("Access denied! You need to be authorized to perform this action!"));
|
|
69
69
|
});
|
|
70
|
-
if (invalidToken &&
|
|
70
|
+
if (invalidToken && getToken()) {
|
|
71
71
|
errorHandler.captureException(new Error(JSON.stringify({
|
|
72
72
|
category: "GraphQL",
|
|
73
73
|
info: "GraphQL Error - invalidToken",
|
|
@@ -103,6 +103,69 @@ const createErrorLink = ({ errorHandler, token, }) => {
|
|
|
103
103
|
});
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Wraps an SSE subscription link and provides the same error monitoring as the
|
|
108
|
+
* HTTP error link — capturing GraphQL errors, traceIds, FORCE_RELOAD_BROWSER,
|
|
109
|
+
* and UNAUTHENTICATED codes — for long-lived subscription Observables.
|
|
110
|
+
*/
|
|
111
|
+
const createSubscriptionErrorLink = ({ errorHandler, getToken, }) => {
|
|
112
|
+
return new client.ApolloLink((operation, forward) => {
|
|
113
|
+
return new client.Observable(observer => {
|
|
114
|
+
const subscription = forward(operation).subscribe({
|
|
115
|
+
next: response => {
|
|
116
|
+
const { errors } = response;
|
|
117
|
+
if (errors) {
|
|
118
|
+
const code = errors[0]?.extensions?.code;
|
|
119
|
+
if (code === "FORCE_RELOAD_BROWSER") {
|
|
120
|
+
window.location.reload();
|
|
121
|
+
}
|
|
122
|
+
const traceIds = [];
|
|
123
|
+
errors.forEach(error => {
|
|
124
|
+
if ("extensions" in error && error.extensions && typeof error.extensions.traceId === "string") {
|
|
125
|
+
traceIds.push(error.extensions.traceId);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
if (traceIds.length) {
|
|
129
|
+
errorHandler.setTag("traceIds", traceIds.join(", "));
|
|
130
|
+
}
|
|
131
|
+
errorHandler.addBreadcrumb({
|
|
132
|
+
category: "GraphQL",
|
|
133
|
+
message: "GraphQL Subscription Error",
|
|
134
|
+
level: "error",
|
|
135
|
+
data: { log: JSON.stringify(errors) },
|
|
136
|
+
});
|
|
137
|
+
const invalidToken = errors.some(x => x.extensions?.code === "UNAUTHENTICATED" ||
|
|
138
|
+
x.message.includes("Invalid token specified") ||
|
|
139
|
+
x.message.includes("Access denied! You need to be authorized to perform this action!"));
|
|
140
|
+
if (invalidToken && getToken()) {
|
|
141
|
+
errorHandler.captureException(new Error(JSON.stringify({
|
|
142
|
+
category: "GraphQL",
|
|
143
|
+
info: "GraphQL Subscription Error - invalidToken",
|
|
144
|
+
level: "warning",
|
|
145
|
+
data: { log: JSON.stringify(errors) },
|
|
146
|
+
})), { level: "warning", fingerprint: ["GraphQL Subscription Error - invalidToken"] });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
observer.next(response);
|
|
150
|
+
},
|
|
151
|
+
error: err => {
|
|
152
|
+
// eslint-disable-next-line no-console
|
|
153
|
+
console.error(err);
|
|
154
|
+
errorHandler.addBreadcrumb({
|
|
155
|
+
category: "GraphQL",
|
|
156
|
+
message: "GraphQL Subscription Network Error",
|
|
157
|
+
level: "error",
|
|
158
|
+
data: { log: String(err) },
|
|
159
|
+
});
|
|
160
|
+
observer.error(err);
|
|
161
|
+
},
|
|
162
|
+
complete: () => observer.complete(),
|
|
163
|
+
});
|
|
164
|
+
return () => subscription.unsubscribe();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
|
|
106
169
|
// Use a widened `string` key so TypeScript picks the `unknown` overload of
|
|
107
170
|
// `Reflect.get` instead of the typed one — otherwise reads like `module`
|
|
108
171
|
// resolve to `NodeModule` from @types/node.
|
|
@@ -170,11 +233,12 @@ const isInternalGqlContext = () => {
|
|
|
170
233
|
return Reflect.get(globalThis, "gql") === "internal";
|
|
171
234
|
};
|
|
172
235
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
236
|
+
/**
|
|
237
|
+
* @internal
|
|
238
|
+
*/
|
|
239
|
+
const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlReportUrl, isDev, tracingHeaders: initialTracingHeaders, firstToken, errorHandler, }) => {
|
|
240
|
+
let token = firstToken;
|
|
241
|
+
let tracingHeaders = initialTracingHeaders;
|
|
178
242
|
const publicGraphQLLink = client.createHttpLink({
|
|
179
243
|
uri: request => graphqlPublicUrl + "/" + request.operationName,
|
|
180
244
|
});
|
|
@@ -184,7 +248,7 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
184
248
|
const reportGraphQLLink = client.createHttpLink({
|
|
185
249
|
uri: request => graphqlReportUrl + "/" + request.operationName,
|
|
186
250
|
});
|
|
187
|
-
const authLink = context.setContext(
|
|
251
|
+
const authLink = context.setContext((_, { headers: existingHeaders }) => {
|
|
188
252
|
return {
|
|
189
253
|
headers: {
|
|
190
254
|
...existingHeaders,
|
|
@@ -192,7 +256,7 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
192
256
|
},
|
|
193
257
|
};
|
|
194
258
|
});
|
|
195
|
-
const errorLink = createErrorLink({ errorHandler, token });
|
|
259
|
+
const errorLink = createErrorLink({ errorHandler, getToken: () => token });
|
|
196
260
|
const defaultOptions = {
|
|
197
261
|
watchQuery: {
|
|
198
262
|
fetchPolicy: "no-cache",
|
|
@@ -209,10 +273,12 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
209
273
|
};
|
|
210
274
|
const removeTypenameLink = removeTypename.removeTypenameFromVariables();
|
|
211
275
|
class SSELink extends client.ApolloLink {
|
|
276
|
+
/** @inheritdoc */
|
|
212
277
|
constructor(options) {
|
|
213
278
|
super();
|
|
214
279
|
this.client = graphqlSse.createClient(options);
|
|
215
280
|
}
|
|
281
|
+
/** @inheritdoc */
|
|
216
282
|
request(operation) {
|
|
217
283
|
return new utilities.Observable(sink => {
|
|
218
284
|
return this.client.subscribe({ ...operation, query: graphql.print(operation.query) }, {
|
|
@@ -228,12 +294,13 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
228
294
|
headers: () => generateHeaders(token, tracingHeaders),
|
|
229
295
|
});
|
|
230
296
|
// Split links based on operation type
|
|
297
|
+
const subscriptionErrorLink = createSubscriptionErrorLink({ errorHandler, getToken: () => token });
|
|
231
298
|
const splitLink = client.from([
|
|
232
299
|
authLink,
|
|
233
300
|
client.split(({ query }) => {
|
|
234
301
|
const definition = utilities.getMainDefinition(query);
|
|
235
302
|
return definition.kind === "OperationDefinition" && definition.operation === "subscription";
|
|
236
|
-
}, sseLink, client.from([
|
|
303
|
+
}, client.from([subscriptionErrorLink, sseLink]), client.from([
|
|
237
304
|
errorLink,
|
|
238
305
|
removeTypenameLink,
|
|
239
306
|
client.split(operation => operation.getContext().clientName === "report", reportGraphQLLink, client.split(() => isInternalGqlContext(), internalGraphQLLink, publicGraphQLLink)),
|
|
@@ -261,8 +328,12 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
261
328
|
getToken: () => {
|
|
262
329
|
return token;
|
|
263
330
|
},
|
|
331
|
+
setTracingHeaders: (newHeaders) => {
|
|
332
|
+
tracingHeaders = newHeaders;
|
|
333
|
+
},
|
|
264
334
|
};
|
|
265
335
|
};
|
|
336
|
+
|
|
266
337
|
const useApolloClient = () => {
|
|
267
338
|
const { graphqlPublicUrl, graphqlInternalUrl, graphqlReportUrl, environment, tracingHeaders } = reactCoreHooks.useEnvironment();
|
|
268
339
|
const { token: currentToken } = reactCoreHooks.useToken();
|
|
@@ -281,11 +352,17 @@ const useApolloClient = () => {
|
|
|
281
352
|
errorHandler,
|
|
282
353
|
});
|
|
283
354
|
});
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
355
|
+
// Synchronously propagate the token into the Apollo client closure during render
|
|
356
|
+
// so that child components' effects (useLayoutEffect / useEffect) always see the
|
|
357
|
+
// current token when they fire their first request in the same commit.
|
|
358
|
+
// React runs child effects before parent effects, so a parent useEffect here would
|
|
359
|
+
// be too late — child queries would go out with the previous token for one commit.
|
|
360
|
+
if (client.getToken() !== currentToken) {
|
|
361
|
+
client.setToken(currentToken);
|
|
362
|
+
}
|
|
363
|
+
react.useEffect(() => {
|
|
364
|
+
client.setTracingHeaders(tracingHeaders);
|
|
365
|
+
}, [client, tracingHeaders]);
|
|
289
366
|
return client;
|
|
290
367
|
};
|
|
291
368
|
/**
|
package/index.esm.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { ApolloLink, Observable, createHttpLink, from, split, ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
|
|
3
|
+
import { useEnvironment, useToken, useErrorHandler } from '@trackunit/react-core-hooks';
|
|
4
|
+
import { useState, useEffect, useMemo, useCallback, useReducer, Suspense } from 'react';
|
|
3
5
|
import { setContext } from '@apollo/client/link/context';
|
|
4
6
|
import { removeTypenameFromVariables } from '@apollo/client/link/remove-typename';
|
|
5
|
-
import { getMainDefinition, Observable } from '@apollo/client/utilities';
|
|
6
|
-
import { useEnvironment, useToken, useErrorHandler } from '@trackunit/react-core-hooks';
|
|
7
|
+
import { getMainDefinition, Observable as Observable$1 } from '@apollo/client/utilities';
|
|
7
8
|
import { print } from 'graphql';
|
|
8
9
|
import { createClient } from 'graphql-sse';
|
|
9
|
-
import { useState, useMemo, useEffect, useCallback, useReducer, Suspense } from 'react';
|
|
10
10
|
import { onError } from '@apollo/client/link/error';
|
|
11
11
|
import { ToastRuntime, AnalyticsRuntime, registerHostChangeHandler, AssetSortingRuntime, ConfirmationDialogRuntime, EnvironmentRuntime, ExportDataRuntime, AssetsFilterBarRuntime, CustomersFilterBarRuntime, SitesFilterBarRuntime, GeolocationRuntime, ModalDialogRuntime, NavigationRuntime, OemBrandingRuntime, ThemeCssRuntime, TimeRangeRuntime, TokenRuntime, CurrentUserRuntime, CurrentUserPreferenceRuntime, UserSubscriptionRuntime, WidgetConfigRuntime } from '@trackunit/iris-app-runtime-core';
|
|
12
12
|
import { ToastProvider, AnalyticsContextProvider, AssetSortingProvider, ConfirmationDialogProvider, EnvironmentContextProvider, ErrorHandlingContextProvider, ExportDataContext, FilterBarProvider, GeolocationProvider, ModalDialogContextProvider, NavigationContextProvider, OemBrandingContextProvider, TimeRangeProvider, TokenProvider, CurrentUserProvider, CurrentUserPreferenceProvider, UserSubscriptionProvider, WidgetConfigProvider } from '@trackunit/react-core-contexts-api';
|
|
@@ -17,7 +17,7 @@ import { Channels, SortOrder, AssetSortByProperty } from '@trackunit/iris-app-ru
|
|
|
17
17
|
/**
|
|
18
18
|
* This error link is used to capture error information, i. e. traceId, graphQL errors, network errors, etc.
|
|
19
19
|
*/
|
|
20
|
-
const createErrorLink = ({ errorHandler,
|
|
20
|
+
const createErrorLink = ({ errorHandler, getToken, }) => {
|
|
21
21
|
return onError(({ graphQLErrors, networkError, operation, forward }) => {
|
|
22
22
|
if (networkError) {
|
|
23
23
|
// We skip the error logging if the error is an AbortError
|
|
@@ -65,7 +65,7 @@ const createErrorLink = ({ errorHandler, token, }) => {
|
|
|
65
65
|
x.message.includes("Invalid token specified") ||
|
|
66
66
|
x.message.includes("Access denied! You need to be authorized to perform this action!"));
|
|
67
67
|
});
|
|
68
|
-
if (invalidToken &&
|
|
68
|
+
if (invalidToken && getToken()) {
|
|
69
69
|
errorHandler.captureException(new Error(JSON.stringify({
|
|
70
70
|
category: "GraphQL",
|
|
71
71
|
info: "GraphQL Error - invalidToken",
|
|
@@ -101,6 +101,69 @@ const createErrorLink = ({ errorHandler, token, }) => {
|
|
|
101
101
|
});
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Wraps an SSE subscription link and provides the same error monitoring as the
|
|
106
|
+
* HTTP error link — capturing GraphQL errors, traceIds, FORCE_RELOAD_BROWSER,
|
|
107
|
+
* and UNAUTHENTICATED codes — for long-lived subscription Observables.
|
|
108
|
+
*/
|
|
109
|
+
const createSubscriptionErrorLink = ({ errorHandler, getToken, }) => {
|
|
110
|
+
return new ApolloLink((operation, forward) => {
|
|
111
|
+
return new Observable(observer => {
|
|
112
|
+
const subscription = forward(operation).subscribe({
|
|
113
|
+
next: response => {
|
|
114
|
+
const { errors } = response;
|
|
115
|
+
if (errors) {
|
|
116
|
+
const code = errors[0]?.extensions?.code;
|
|
117
|
+
if (code === "FORCE_RELOAD_BROWSER") {
|
|
118
|
+
window.location.reload();
|
|
119
|
+
}
|
|
120
|
+
const traceIds = [];
|
|
121
|
+
errors.forEach(error => {
|
|
122
|
+
if ("extensions" in error && error.extensions && typeof error.extensions.traceId === "string") {
|
|
123
|
+
traceIds.push(error.extensions.traceId);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
if (traceIds.length) {
|
|
127
|
+
errorHandler.setTag("traceIds", traceIds.join(", "));
|
|
128
|
+
}
|
|
129
|
+
errorHandler.addBreadcrumb({
|
|
130
|
+
category: "GraphQL",
|
|
131
|
+
message: "GraphQL Subscription Error",
|
|
132
|
+
level: "error",
|
|
133
|
+
data: { log: JSON.stringify(errors) },
|
|
134
|
+
});
|
|
135
|
+
const invalidToken = errors.some(x => x.extensions?.code === "UNAUTHENTICATED" ||
|
|
136
|
+
x.message.includes("Invalid token specified") ||
|
|
137
|
+
x.message.includes("Access denied! You need to be authorized to perform this action!"));
|
|
138
|
+
if (invalidToken && getToken()) {
|
|
139
|
+
errorHandler.captureException(new Error(JSON.stringify({
|
|
140
|
+
category: "GraphQL",
|
|
141
|
+
info: "GraphQL Subscription Error - invalidToken",
|
|
142
|
+
level: "warning",
|
|
143
|
+
data: { log: JSON.stringify(errors) },
|
|
144
|
+
})), { level: "warning", fingerprint: ["GraphQL Subscription Error - invalidToken"] });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
observer.next(response);
|
|
148
|
+
},
|
|
149
|
+
error: err => {
|
|
150
|
+
// eslint-disable-next-line no-console
|
|
151
|
+
console.error(err);
|
|
152
|
+
errorHandler.addBreadcrumb({
|
|
153
|
+
category: "GraphQL",
|
|
154
|
+
message: "GraphQL Subscription Network Error",
|
|
155
|
+
level: "error",
|
|
156
|
+
data: { log: String(err) },
|
|
157
|
+
});
|
|
158
|
+
observer.error(err);
|
|
159
|
+
},
|
|
160
|
+
complete: () => observer.complete(),
|
|
161
|
+
});
|
|
162
|
+
return () => subscription.unsubscribe();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
|
|
104
167
|
// Use a widened `string` key so TypeScript picks the `unknown` overload of
|
|
105
168
|
// `Reflect.get` instead of the typed one — otherwise reads like `module`
|
|
106
169
|
// resolve to `NodeModule` from @types/node.
|
|
@@ -168,11 +231,12 @@ const isInternalGqlContext = () => {
|
|
|
168
231
|
return Reflect.get(globalThis, "gql") === "internal";
|
|
169
232
|
};
|
|
170
233
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
234
|
+
/**
|
|
235
|
+
* @internal
|
|
236
|
+
*/
|
|
237
|
+
const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlReportUrl, isDev, tracingHeaders: initialTracingHeaders, firstToken, errorHandler, }) => {
|
|
238
|
+
let token = firstToken;
|
|
239
|
+
let tracingHeaders = initialTracingHeaders;
|
|
176
240
|
const publicGraphQLLink = createHttpLink({
|
|
177
241
|
uri: request => graphqlPublicUrl + "/" + request.operationName,
|
|
178
242
|
});
|
|
@@ -182,7 +246,7 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
182
246
|
const reportGraphQLLink = createHttpLink({
|
|
183
247
|
uri: request => graphqlReportUrl + "/" + request.operationName,
|
|
184
248
|
});
|
|
185
|
-
const authLink = setContext(
|
|
249
|
+
const authLink = setContext((_, { headers: existingHeaders }) => {
|
|
186
250
|
return {
|
|
187
251
|
headers: {
|
|
188
252
|
...existingHeaders,
|
|
@@ -190,7 +254,7 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
190
254
|
},
|
|
191
255
|
};
|
|
192
256
|
});
|
|
193
|
-
const errorLink = createErrorLink({ errorHandler, token });
|
|
257
|
+
const errorLink = createErrorLink({ errorHandler, getToken: () => token });
|
|
194
258
|
const defaultOptions = {
|
|
195
259
|
watchQuery: {
|
|
196
260
|
fetchPolicy: "no-cache",
|
|
@@ -207,12 +271,14 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
207
271
|
};
|
|
208
272
|
const removeTypenameLink = removeTypenameFromVariables();
|
|
209
273
|
class SSELink extends ApolloLink {
|
|
274
|
+
/** @inheritdoc */
|
|
210
275
|
constructor(options) {
|
|
211
276
|
super();
|
|
212
277
|
this.client = createClient(options);
|
|
213
278
|
}
|
|
279
|
+
/** @inheritdoc */
|
|
214
280
|
request(operation) {
|
|
215
|
-
return new Observable(sink => {
|
|
281
|
+
return new Observable$1(sink => {
|
|
216
282
|
return this.client.subscribe({ ...operation, query: print(operation.query) }, {
|
|
217
283
|
next: value => sink.next(value),
|
|
218
284
|
complete: sink.complete.bind(sink),
|
|
@@ -226,12 +292,13 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
226
292
|
headers: () => generateHeaders(token, tracingHeaders),
|
|
227
293
|
});
|
|
228
294
|
// Split links based on operation type
|
|
295
|
+
const subscriptionErrorLink = createSubscriptionErrorLink({ errorHandler, getToken: () => token });
|
|
229
296
|
const splitLink = from([
|
|
230
297
|
authLink,
|
|
231
298
|
split(({ query }) => {
|
|
232
299
|
const definition = getMainDefinition(query);
|
|
233
300
|
return definition.kind === "OperationDefinition" && definition.operation === "subscription";
|
|
234
|
-
}, sseLink, from([
|
|
301
|
+
}, from([subscriptionErrorLink, sseLink]), from([
|
|
235
302
|
errorLink,
|
|
236
303
|
removeTypenameLink,
|
|
237
304
|
split(operation => operation.getContext().clientName === "report", reportGraphQLLink, split(() => isInternalGqlContext(), internalGraphQLLink, publicGraphQLLink)),
|
|
@@ -259,8 +326,12 @@ const createApolloClient = ({ graphqlPublicUrl, graphqlInternalUrl, graphqlRepor
|
|
|
259
326
|
getToken: () => {
|
|
260
327
|
return token;
|
|
261
328
|
},
|
|
329
|
+
setTracingHeaders: (newHeaders) => {
|
|
330
|
+
tracingHeaders = newHeaders;
|
|
331
|
+
},
|
|
262
332
|
};
|
|
263
333
|
};
|
|
334
|
+
|
|
264
335
|
const useApolloClient = () => {
|
|
265
336
|
const { graphqlPublicUrl, graphqlInternalUrl, graphqlReportUrl, environment, tracingHeaders } = useEnvironment();
|
|
266
337
|
const { token: currentToken } = useToken();
|
|
@@ -279,11 +350,17 @@ const useApolloClient = () => {
|
|
|
279
350
|
errorHandler,
|
|
280
351
|
});
|
|
281
352
|
});
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
353
|
+
// Synchronously propagate the token into the Apollo client closure during render
|
|
354
|
+
// so that child components' effects (useLayoutEffect / useEffect) always see the
|
|
355
|
+
// current token when they fire their first request in the same commit.
|
|
356
|
+
// React runs child effects before parent effects, so a parent useEffect here would
|
|
357
|
+
// be too late — child queries would go out with the previous token for one commit.
|
|
358
|
+
if (client.getToken() !== currentToken) {
|
|
359
|
+
client.setToken(currentToken);
|
|
360
|
+
}
|
|
361
|
+
useEffect(() => {
|
|
362
|
+
client.setTracingHeaders(tracingHeaders);
|
|
363
|
+
}, [client, tracingHeaders]);
|
|
287
364
|
return client;
|
|
288
365
|
};
|
|
289
366
|
/**
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-core-contexts",
|
|
3
|
-
"version": "1.30.
|
|
3
|
+
"version": "1.30.5-alpha-d37885bfce4.0",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=24.x"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@trackunit/iris-app-api": "1.20.
|
|
11
|
-
"@trackunit/iris-app-runtime-core-api": "1.16.
|
|
12
|
-
"@trackunit/react-core-hooks": "1.17.
|
|
13
|
-
"@trackunit/i18n-library-translation": "1.22.
|
|
14
|
-
"@trackunit/react-components": "1.26.
|
|
15
|
-
"@trackunit/iris-app-runtime-core": "1.17.
|
|
10
|
+
"@trackunit/iris-app-api": "1.20.9-alpha-d37885bfce4.0",
|
|
11
|
+
"@trackunit/iris-app-runtime-core-api": "1.16.8-alpha-d37885bfce4.0",
|
|
12
|
+
"@trackunit/react-core-hooks": "1.17.12-alpha-d37885bfce4.0",
|
|
13
|
+
"@trackunit/i18n-library-translation": "1.22.3-alpha-d37885bfce4.0",
|
|
14
|
+
"@trackunit/react-components": "1.26.5-alpha-d37885bfce4.0",
|
|
15
|
+
"@trackunit/iris-app-runtime-core": "1.17.8-alpha-d37885bfce4.0",
|
|
16
16
|
"graphql-sse": "^2.5.4",
|
|
17
|
-
"@trackunit/react-core-contexts-api": "1.17.
|
|
17
|
+
"@trackunit/react-core-contexts-api": "1.17.8-alpha-d37885bfce4.0"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@apollo/client": "^3.13.8",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ApolloClient } from "@apollo/client";
|
|
2
|
+
import { ErrorHandlingContextValue, TracingHeaders } from "@trackunit/iris-app-runtime-core-api";
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare const createApolloClient: ({ graphqlPublicUrl, graphqlInternalUrl, graphqlReportUrl, isDev, tracingHeaders: initialTracingHeaders, firstToken, errorHandler, }: {
|
|
7
|
+
graphqlPublicUrl: string;
|
|
8
|
+
graphqlInternalUrl: string;
|
|
9
|
+
graphqlReportUrl: string;
|
|
10
|
+
tracingHeaders: TracingHeaders;
|
|
11
|
+
isDev: boolean;
|
|
12
|
+
firstToken?: string;
|
|
13
|
+
errorHandler: ErrorHandlingContextValue;
|
|
14
|
+
}) => {
|
|
15
|
+
client: ApolloClient<import("@apollo/client").NormalizedCacheObject>;
|
|
16
|
+
setToken: (newToken: string | undefined) => void;
|
|
17
|
+
getToken: () => string | undefined;
|
|
18
|
+
setTracingHeaders: (newHeaders: TracingHeaders) => void;
|
|
19
|
+
};
|
|
@@ -3,7 +3,7 @@ import { ErrorHandlingContextValue } from "@trackunit/iris-app-runtime-core-api"
|
|
|
3
3
|
/**
|
|
4
4
|
* This error link is used to capture error information, i. e. traceId, graphQL errors, network errors, etc.
|
|
5
5
|
*/
|
|
6
|
-
export declare const createErrorLink: ({ errorHandler,
|
|
6
|
+
export declare const createErrorLink: ({ errorHandler, getToken, }: {
|
|
7
7
|
errorHandler: ErrorHandlingContextValue;
|
|
8
|
-
|
|
8
|
+
getToken: () => string | undefined;
|
|
9
9
|
}) => ApolloLink;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ApolloLink } from "@apollo/client";
|
|
2
|
+
import { ErrorHandlingContextValue } from "@trackunit/iris-app-runtime-core-api";
|
|
3
|
+
/**
|
|
4
|
+
* Wraps an SSE subscription link and provides the same error monitoring as the
|
|
5
|
+
* HTTP error link — capturing GraphQL errors, traceIds, FORCE_RELOAD_BROWSER,
|
|
6
|
+
* and UNAUTHENTICATED codes — for long-lived subscription Observables.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createSubscriptionErrorLink: ({ errorHandler, getToken, }: {
|
|
9
|
+
errorHandler: ErrorHandlingContextValue;
|
|
10
|
+
getToken: () => string | undefined;
|
|
11
|
+
}) => ApolloLink;
|