@trackunit/react-core-contexts 2.1.31 → 2.1.33
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 +34 -9
- package/index.esm.js +34 -9
- package/package.json +8 -8
- package/src/errorLink/subscriptionErrorLink.d.ts +7 -1
package/index.cjs.js
CHANGED
|
@@ -103,14 +103,28 @@ const createErrorLink = ({ errorHandler, getToken, }) => {
|
|
|
103
103
|
});
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
+
const DEFAULT_AUTH_GRACE_MS = 30000;
|
|
106
107
|
/**
|
|
107
108
|
* Wraps an SSE subscription link and provides the same error monitoring as the
|
|
108
109
|
* HTTP error link — capturing GraphQL errors, traceIds, FORCE_RELOAD_BROWSER,
|
|
109
110
|
* and UNAUTHENTICATED codes — for long-lived subscription Observables.
|
|
111
|
+
*
|
|
112
|
+
* UNAUTHENTICATED errors are deferred by a grace period (default 30s) to allow
|
|
113
|
+
* Okta's autoRenew to refresh the token. If a successful response arrives
|
|
114
|
+
* within the window the capture is cancelled; if the timer fires, a single
|
|
115
|
+
* captureException is sent — an actionable signal that token refresh failed.
|
|
110
116
|
*/
|
|
111
|
-
const createSubscriptionErrorLink = ({ errorHandler, getToken, }) => {
|
|
117
|
+
const createSubscriptionErrorLink = ({ errorHandler, getToken, graceMs = DEFAULT_AUTH_GRACE_MS, }) => {
|
|
112
118
|
return new client.ApolloLink((operation, forward) => {
|
|
113
119
|
return new client.Observable(observer => {
|
|
120
|
+
let authGraceTimer = null;
|
|
121
|
+
let authErrorReported = false;
|
|
122
|
+
const clearGraceTimer = () => {
|
|
123
|
+
if (authGraceTimer !== null) {
|
|
124
|
+
clearTimeout(authGraceTimer);
|
|
125
|
+
authGraceTimer = null;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
114
128
|
const subscription = forward(operation).subscribe({
|
|
115
129
|
next: response => {
|
|
116
130
|
const { errors } = response;
|
|
@@ -137,15 +151,23 @@ const createSubscriptionErrorLink = ({ errorHandler, getToken, }) => {
|
|
|
137
151
|
const invalidToken = errors.some(x => x.extensions?.code === "UNAUTHENTICATED" ||
|
|
138
152
|
x.message.includes("Invalid token specified") ||
|
|
139
153
|
x.message.includes("Access denied! You need to be authorized to perform this action!"));
|
|
140
|
-
if (invalidToken && getToken()) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
154
|
+
if (invalidToken && getToken() && authGraceTimer === null && !authErrorReported) {
|
|
155
|
+
authGraceTimer = setTimeout(() => {
|
|
156
|
+
authGraceTimer = null;
|
|
157
|
+
authErrorReported = true;
|
|
158
|
+
errorHandler.captureException(new Error(JSON.stringify({
|
|
159
|
+
category: "GraphQL",
|
|
160
|
+
info: "GraphQL Subscription Error - invalidToken",
|
|
161
|
+
level: "warning",
|
|
162
|
+
data: { log: JSON.stringify(errors) },
|
|
163
|
+
})), { level: "warning", fingerprint: ["GraphQL Subscription Error - invalidToken"] });
|
|
164
|
+
}, graceMs);
|
|
147
165
|
}
|
|
148
166
|
}
|
|
167
|
+
else {
|
|
168
|
+
clearGraceTimer();
|
|
169
|
+
authErrorReported = false;
|
|
170
|
+
}
|
|
149
171
|
observer.next(response);
|
|
150
172
|
},
|
|
151
173
|
error: err => {
|
|
@@ -168,7 +190,10 @@ const createSubscriptionErrorLink = ({ errorHandler, getToken, }) => {
|
|
|
168
190
|
},
|
|
169
191
|
complete: () => observer.complete(),
|
|
170
192
|
});
|
|
171
|
-
return () =>
|
|
193
|
+
return () => {
|
|
194
|
+
clearGraceTimer();
|
|
195
|
+
subscription.unsubscribe();
|
|
196
|
+
};
|
|
172
197
|
});
|
|
173
198
|
});
|
|
174
199
|
};
|
package/index.esm.js
CHANGED
|
@@ -101,14 +101,28 @@ const createErrorLink = ({ errorHandler, getToken, }) => {
|
|
|
101
101
|
});
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
+
const DEFAULT_AUTH_GRACE_MS = 30000;
|
|
104
105
|
/**
|
|
105
106
|
* Wraps an SSE subscription link and provides the same error monitoring as the
|
|
106
107
|
* HTTP error link — capturing GraphQL errors, traceIds, FORCE_RELOAD_BROWSER,
|
|
107
108
|
* and UNAUTHENTICATED codes — for long-lived subscription Observables.
|
|
109
|
+
*
|
|
110
|
+
* UNAUTHENTICATED errors are deferred by a grace period (default 30s) to allow
|
|
111
|
+
* Okta's autoRenew to refresh the token. If a successful response arrives
|
|
112
|
+
* within the window the capture is cancelled; if the timer fires, a single
|
|
113
|
+
* captureException is sent — an actionable signal that token refresh failed.
|
|
108
114
|
*/
|
|
109
|
-
const createSubscriptionErrorLink = ({ errorHandler, getToken, }) => {
|
|
115
|
+
const createSubscriptionErrorLink = ({ errorHandler, getToken, graceMs = DEFAULT_AUTH_GRACE_MS, }) => {
|
|
110
116
|
return new ApolloLink((operation, forward) => {
|
|
111
117
|
return new Observable(observer => {
|
|
118
|
+
let authGraceTimer = null;
|
|
119
|
+
let authErrorReported = false;
|
|
120
|
+
const clearGraceTimer = () => {
|
|
121
|
+
if (authGraceTimer !== null) {
|
|
122
|
+
clearTimeout(authGraceTimer);
|
|
123
|
+
authGraceTimer = null;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
112
126
|
const subscription = forward(operation).subscribe({
|
|
113
127
|
next: response => {
|
|
114
128
|
const { errors } = response;
|
|
@@ -135,15 +149,23 @@ const createSubscriptionErrorLink = ({ errorHandler, getToken, }) => {
|
|
|
135
149
|
const invalidToken = errors.some(x => x.extensions?.code === "UNAUTHENTICATED" ||
|
|
136
150
|
x.message.includes("Invalid token specified") ||
|
|
137
151
|
x.message.includes("Access denied! You need to be authorized to perform this action!"));
|
|
138
|
-
if (invalidToken && getToken()) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
152
|
+
if (invalidToken && getToken() && authGraceTimer === null && !authErrorReported) {
|
|
153
|
+
authGraceTimer = setTimeout(() => {
|
|
154
|
+
authGraceTimer = null;
|
|
155
|
+
authErrorReported = true;
|
|
156
|
+
errorHandler.captureException(new Error(JSON.stringify({
|
|
157
|
+
category: "GraphQL",
|
|
158
|
+
info: "GraphQL Subscription Error - invalidToken",
|
|
159
|
+
level: "warning",
|
|
160
|
+
data: { log: JSON.stringify(errors) },
|
|
161
|
+
})), { level: "warning", fingerprint: ["GraphQL Subscription Error - invalidToken"] });
|
|
162
|
+
}, graceMs);
|
|
145
163
|
}
|
|
146
164
|
}
|
|
165
|
+
else {
|
|
166
|
+
clearGraceTimer();
|
|
167
|
+
authErrorReported = false;
|
|
168
|
+
}
|
|
147
169
|
observer.next(response);
|
|
148
170
|
},
|
|
149
171
|
error: err => {
|
|
@@ -166,7 +188,10 @@ const createSubscriptionErrorLink = ({ errorHandler, getToken, }) => {
|
|
|
166
188
|
},
|
|
167
189
|
complete: () => observer.complete(),
|
|
168
190
|
});
|
|
169
|
-
return () =>
|
|
191
|
+
return () => {
|
|
192
|
+
clearGraceTimer();
|
|
193
|
+
subscription.unsubscribe();
|
|
194
|
+
};
|
|
170
195
|
});
|
|
171
196
|
});
|
|
172
197
|
};
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-core-contexts",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.33",
|
|
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": "2.0.
|
|
11
|
-
"@trackunit/iris-app-runtime-core-api": "1.16.
|
|
12
|
-
"@trackunit/react-core-hooks": "1.17.
|
|
13
|
-
"@trackunit/i18n-library-translation": "2.0.
|
|
14
|
-
"@trackunit/react-components": "2.1.
|
|
15
|
-
"@trackunit/iris-app-runtime-core": "1.17.
|
|
10
|
+
"@trackunit/iris-app-api": "2.0.28",
|
|
11
|
+
"@trackunit/iris-app-runtime-core-api": "1.16.40",
|
|
12
|
+
"@trackunit/react-core-hooks": "1.17.45",
|
|
13
|
+
"@trackunit/i18n-library-translation": "2.0.33",
|
|
14
|
+
"@trackunit/react-components": "2.1.32",
|
|
15
|
+
"@trackunit/iris-app-runtime-core": "1.17.41",
|
|
16
16
|
"graphql-sse": "^2.5.4",
|
|
17
|
-
"@trackunit/react-core-contexts-api": "1.17.
|
|
17
|
+
"@trackunit/react-core-contexts-api": "1.17.40"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@apollo/client": "^3.13.8",
|
|
@@ -4,8 +4,14 @@ import { ErrorHandlingContextValue } from "@trackunit/iris-app-runtime-core-api"
|
|
|
4
4
|
* Wraps an SSE subscription link and provides the same error monitoring as the
|
|
5
5
|
* HTTP error link — capturing GraphQL errors, traceIds, FORCE_RELOAD_BROWSER,
|
|
6
6
|
* and UNAUTHENTICATED codes — for long-lived subscription Observables.
|
|
7
|
+
*
|
|
8
|
+
* UNAUTHENTICATED errors are deferred by a grace period (default 30s) to allow
|
|
9
|
+
* Okta's autoRenew to refresh the token. If a successful response arrives
|
|
10
|
+
* within the window the capture is cancelled; if the timer fires, a single
|
|
11
|
+
* captureException is sent — an actionable signal that token refresh failed.
|
|
7
12
|
*/
|
|
8
|
-
export declare const createSubscriptionErrorLink: ({ errorHandler, getToken, }: {
|
|
13
|
+
export declare const createSubscriptionErrorLink: ({ errorHandler, getToken, graceMs, }: {
|
|
9
14
|
errorHandler: ErrorHandlingContextValue;
|
|
10
15
|
getToken: () => string | undefined;
|
|
16
|
+
graceMs?: number;
|
|
11
17
|
}) => ApolloLink;
|