@coinlist-co/react 0.12.2-rc.7b430dd → 0.12.2-rc.9fb6364
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/dist/{chunk-MOE5S6CE.js → chunk-BNMF2HMW.js} +114 -4
- package/dist/chunk-BNMF2HMW.js.map +1 -0
- package/dist/{chunk-VH34YC3Q.js → chunk-KRA6EM2L.js} +2 -2
- package/dist/{chunk-DCW7NQXH.js → chunk-STAHYDLY.js} +52 -19
- package/dist/chunk-STAHYDLY.js.map +1 -0
- package/dist/client/index.cjs +322 -96
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +26 -10
- package/dist/client/index.d.ts +26 -10
- package/dist/client/index.js +225 -102
- package/dist/client/index.js.map +1 -1
- package/dist/server/index.cjs +437 -76
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +47 -38
- package/dist/server/index.d.ts +47 -38
- package/dist/server/index.js +316 -61
- package/dist/server/index.js.map +1 -1
- package/dist/time-B5YOQxuh.d.ts +50 -0
- package/dist/time-BY3apBpc.d.cts +50 -0
- package/dist/{token-registry-snapshot-BNBNuDu1.d.ts → token-registry-snapshot-C1NxdBmF.d.ts} +1 -1
- package/dist/{token-registry-snapshot-CqI6dXM_.d.cts → token-registry-snapshot-DyjrA32p.d.cts} +1 -1
- package/dist/{tokens-namespace-CIWBtgt2.d.cts → tokens-namespace-BJfFeowE.d.cts} +53 -1
- package/dist/{tokens-namespace-CIWBtgt2.d.ts → tokens-namespace-BJfFeowE.d.ts} +53 -1
- package/dist/universal/index.cjs +100 -3
- package/dist/universal/index.cjs.map +1 -1
- package/dist/universal/index.d.cts +23 -5
- package/dist/universal/index.d.ts +23 -5
- package/dist/universal/index.js +12 -2
- package/package.json +1 -1
- package/dist/chunk-DCW7NQXH.js.map +0 -1
- package/dist/chunk-MOE5S6CE.js.map +0 -1
- /package/dist/{chunk-VH34YC3Q.js.map → chunk-KRA6EM2L.js.map} +0 -0
package/dist/server/index.js
CHANGED
|
@@ -4,28 +4,37 @@ import {
|
|
|
4
4
|
PINO_LEVEL,
|
|
5
5
|
SDK_LOGGER_NAME,
|
|
6
6
|
loggerOverPino,
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
notifySessionExpired,
|
|
8
|
+
publicClients,
|
|
9
|
+
systemTime
|
|
10
|
+
} from "../chunk-STAHYDLY.js";
|
|
9
11
|
import {
|
|
10
12
|
API_VERSION,
|
|
13
|
+
Attributes,
|
|
11
14
|
ClientCredentialsOAuth,
|
|
12
15
|
CoinListTokenSaleNamespaceImpl,
|
|
16
|
+
EpochMillis,
|
|
13
17
|
Erc20NamespaceImpl,
|
|
14
18
|
HttpError,
|
|
19
|
+
Millis,
|
|
15
20
|
NotAuthenticatedError,
|
|
16
21
|
OAuthSession,
|
|
17
22
|
OndoNamespaceImpl,
|
|
18
23
|
PUBLIC_API_BASE_URL,
|
|
19
24
|
RequirementsNamespaceImpl,
|
|
25
|
+
Seconds,
|
|
20
26
|
SuperstateSwapNamespaceImpl,
|
|
27
|
+
TokenTrigger,
|
|
21
28
|
TokensNamespaceImpl,
|
|
22
29
|
WalletsNamespaceImpl,
|
|
23
30
|
fetchOfferDetails,
|
|
24
31
|
fetchOfferRequirements,
|
|
25
32
|
fetchOffers,
|
|
26
33
|
fetchOffersPage,
|
|
27
|
-
internalLogger
|
|
28
|
-
|
|
34
|
+
internalLogger,
|
|
35
|
+
isExpired,
|
|
36
|
+
isRejectedToken
|
|
37
|
+
} from "../chunk-BNMF2HMW.js";
|
|
29
38
|
|
|
30
39
|
// src/server/core/api/api-client.ts
|
|
31
40
|
var ApiClient = class {
|
|
@@ -42,6 +51,107 @@ var ApiClient = class {
|
|
|
42
51
|
}
|
|
43
52
|
};
|
|
44
53
|
|
|
54
|
+
// src/server/core/session-refresh.ts
|
|
55
|
+
var VERDICT_MIN_GAP = Millis.of(5e3);
|
|
56
|
+
var REJECTION_MEMORY = Millis.of(6e4);
|
|
57
|
+
var RefreshKey = {
|
|
58
|
+
of: ({
|
|
59
|
+
clientId,
|
|
60
|
+
session
|
|
61
|
+
}) => {
|
|
62
|
+
const identity = session.refreshToken === void 0 ? ["access", session.accessToken.value] : ["refresh", session.refreshToken];
|
|
63
|
+
return JSON.stringify([clientId, ...identity]);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var RefreshCoordinator = class {
|
|
67
|
+
constructor(env = systemTime) {
|
|
68
|
+
this.env = env;
|
|
69
|
+
this.inFlight = /* @__PURE__ */ new Map();
|
|
70
|
+
this.rejections = /* @__PURE__ */ new Map();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Runs `exchange` for `key` unless one is already in flight, in which case
|
|
74
|
+
* the caller joins it. `joined` tells the caller whether it led: only the
|
|
75
|
+
* leader reports the outcome, so a burst of N produces one verdict, one log
|
|
76
|
+
* line and one `onSessionExpired`.
|
|
77
|
+
*/
|
|
78
|
+
refresh(key, exchange) {
|
|
79
|
+
const existing = this.inFlight.get(key);
|
|
80
|
+
if (existing !== void 0) {
|
|
81
|
+
return { outcome: existing, joined: true };
|
|
82
|
+
}
|
|
83
|
+
const outcome = this.run(key, exchange).finally(() => {
|
|
84
|
+
this.inFlight.delete(key);
|
|
85
|
+
});
|
|
86
|
+
this.inFlight.set(key, outcome);
|
|
87
|
+
return { outcome, joined: false };
|
|
88
|
+
}
|
|
89
|
+
async run(key, exchange) {
|
|
90
|
+
this.forgetStale(this.env.time.now());
|
|
91
|
+
if (this.rejections.get(key)?.type === "expired") {
|
|
92
|
+
return { type: "already-expired" };
|
|
93
|
+
}
|
|
94
|
+
const result = await exchange();
|
|
95
|
+
switch (result.type) {
|
|
96
|
+
case "renewed":
|
|
97
|
+
case "unknown":
|
|
98
|
+
return result;
|
|
99
|
+
case "rejected":
|
|
100
|
+
case "unrenewable": {
|
|
101
|
+
const judged = judge({
|
|
102
|
+
result: result.type,
|
|
103
|
+
prior: this.rejections.get(key),
|
|
104
|
+
now: this.env.time.now()
|
|
105
|
+
});
|
|
106
|
+
this.rejections.set(key, judged.memory);
|
|
107
|
+
return { type: judged.outcome };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
forgetStale(now) {
|
|
112
|
+
for (const [key, rejection] of this.rejections) {
|
|
113
|
+
if (EpochMillis.elapsed(rejectedAt(rejection), now) > REJECTION_MEMORY) {
|
|
114
|
+
this.rejections.delete(key);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
function judge({
|
|
120
|
+
result,
|
|
121
|
+
prior,
|
|
122
|
+
now
|
|
123
|
+
}) {
|
|
124
|
+
const verdict = {
|
|
125
|
+
outcome: "expired",
|
|
126
|
+
memory: { type: "expired", at: now }
|
|
127
|
+
};
|
|
128
|
+
switch (result) {
|
|
129
|
+
case "unrenewable":
|
|
130
|
+
return verdict;
|
|
131
|
+
case "rejected":
|
|
132
|
+
switch (prior?.type) {
|
|
133
|
+
case void 0:
|
|
134
|
+
return {
|
|
135
|
+
outcome: "suspected",
|
|
136
|
+
memory: { type: "suspected", since: now }
|
|
137
|
+
};
|
|
138
|
+
case "suspected":
|
|
139
|
+
return EpochMillis.elapsed(prior.since, now) >= VERDICT_MIN_GAP ? verdict : { outcome: "suspected", memory: prior };
|
|
140
|
+
case "expired":
|
|
141
|
+
return { outcome: "expired", memory: prior };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function rejectedAt(rejection) {
|
|
146
|
+
switch (rejection.type) {
|
|
147
|
+
case "suspected":
|
|
148
|
+
return rejection.since;
|
|
149
|
+
case "expired":
|
|
150
|
+
return rejection.at;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
var processRefreshCoordinator = new RefreshCoordinator();
|
|
154
|
+
|
|
45
155
|
// src/server/shared/errors.ts
|
|
46
156
|
var WritableSessionStoreRequiredError = class extends Error {
|
|
47
157
|
constructor(message = "This operation requires a writable SessionStore. Provide a `setSession` implementation in your SessionStore to persist or clear OAuth sessions.") {
|
|
@@ -50,10 +160,7 @@ var WritableSessionStoreRequiredError = class extends Error {
|
|
|
50
160
|
}
|
|
51
161
|
};
|
|
52
162
|
|
|
53
|
-
// src/server/core/server-auth-namespace.ts
|
|
54
|
-
function emptySessionStore() {
|
|
55
|
-
return { getSession: async () => null };
|
|
56
|
-
}
|
|
163
|
+
// src/server/core/server-auth-namespace-impl.ts
|
|
57
164
|
var ServerAuthNamespaceImpl = class {
|
|
58
165
|
constructor(api, config) {
|
|
59
166
|
this.api = api;
|
|
@@ -73,7 +180,8 @@ var ServerAuthNamespaceImpl = class {
|
|
|
73
180
|
client_id: this.config.clientId,
|
|
74
181
|
client_secret: this.config.clientSecret,
|
|
75
182
|
code_verifier: params.codeVerifier
|
|
76
|
-
}
|
|
183
|
+
},
|
|
184
|
+
attributes: Attributes.notRetryable()
|
|
77
185
|
});
|
|
78
186
|
const session = OAuthSession.fromDto(sessionDto);
|
|
79
187
|
await setSession(session);
|
|
@@ -81,39 +189,118 @@ var ServerAuthNamespaceImpl = class {
|
|
|
81
189
|
});
|
|
82
190
|
}
|
|
83
191
|
async getAccessToken() {
|
|
192
|
+
return this.tokenFor(TokenTrigger.beforeRequest);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* {@link getAccessToken} with the reason the SDK is asking, which is what
|
|
196
|
+
* the authenticated HTTP pipeline calls: after a 401 the token's own expiry
|
|
197
|
+
* no longer matters, because the API has answered for it.
|
|
198
|
+
*/
|
|
199
|
+
async tokenFor(trigger) {
|
|
84
200
|
return this.log.wrap(
|
|
85
201
|
"getAccessToken",
|
|
86
202
|
void 0,
|
|
87
|
-
() => this.readAccessToken()
|
|
203
|
+
() => this.readAccessToken(trigger)
|
|
88
204
|
);
|
|
89
205
|
}
|
|
90
|
-
async readAccessToken() {
|
|
206
|
+
async readAccessToken(trigger) {
|
|
91
207
|
const sessionStore = this.config.sessionStore;
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
208
|
+
const classification = classifyAccessToken({
|
|
209
|
+
session: await sessionStore.getSession(),
|
|
210
|
+
store: sessionStoreAccess(sessionStore),
|
|
211
|
+
trigger,
|
|
212
|
+
now: this.config.time.now(),
|
|
213
|
+
buffer: Seconds.toMillis(this.config.accessTokenExpiryBufferSeconds)
|
|
214
|
+
});
|
|
215
|
+
switch (classification.type) {
|
|
216
|
+
case "no-session":
|
|
217
|
+
case "refuse":
|
|
218
|
+
return null;
|
|
219
|
+
case "serve":
|
|
220
|
+
return classification.token;
|
|
221
|
+
case "serve-stale":
|
|
222
|
+
this.log.child({ op: "getAccessToken" }).warn(() => ({
|
|
223
|
+
msg: "serving an expired token: the session store is read-only, so it cannot be refreshed"
|
|
224
|
+
}));
|
|
225
|
+
return classification.token;
|
|
226
|
+
case "refresh":
|
|
227
|
+
return this.refresh(classification);
|
|
106
228
|
}
|
|
107
|
-
return this.refreshSession(session.refreshToken, setSession);
|
|
108
229
|
}
|
|
109
|
-
|
|
230
|
+
/**
|
|
231
|
+
* Refreshes through the process-wide coordinator, then acts on the outcome
|
|
232
|
+
* for this caller's own store. The store is written before anything is
|
|
233
|
+
* logged or the host is notified, so `onSessionExpired` always finds it
|
|
234
|
+
* cleared.
|
|
235
|
+
*/
|
|
236
|
+
async refresh({
|
|
237
|
+
session,
|
|
238
|
+
setSession,
|
|
239
|
+
fallback
|
|
240
|
+
}) {
|
|
110
241
|
const log = this.log.child({ op: "refresh" });
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
242
|
+
const key = RefreshKey.of({ clientId: this.config.clientId, session });
|
|
243
|
+
const { outcome, joined } = this.config.refreshes.refresh(
|
|
244
|
+
key,
|
|
245
|
+
() => this.exchange(session.refreshToken)
|
|
246
|
+
);
|
|
247
|
+
if (joined) {
|
|
248
|
+
log.debug(() => ({ msg: "joined a refresh already in flight" }));
|
|
249
|
+
}
|
|
250
|
+
const result = await outcome;
|
|
251
|
+
switch (result.type) {
|
|
252
|
+
case "renewed":
|
|
253
|
+
await setSession(result.session);
|
|
254
|
+
if (!joined) {
|
|
255
|
+
log.info(() => ({ msg: "session renewed" }));
|
|
256
|
+
}
|
|
257
|
+
return result.session.accessToken;
|
|
258
|
+
case "suspected":
|
|
259
|
+
if (!joined) {
|
|
260
|
+
log.warn(() => ({
|
|
261
|
+
msg: "refresh rejected; not clearing until it is confirmed"
|
|
262
|
+
}));
|
|
263
|
+
}
|
|
264
|
+
return fallback;
|
|
265
|
+
case "expired":
|
|
266
|
+
await setSession(null);
|
|
267
|
+
if (!joined) {
|
|
268
|
+
log.info(() => ({
|
|
269
|
+
msg: "session expired",
|
|
270
|
+
fields: {
|
|
271
|
+
reason: session.refreshToken === void 0 ? "no-refresh-token" : "refresh-rejected"
|
|
272
|
+
}
|
|
273
|
+
}));
|
|
274
|
+
notifySessionExpired(this.config.onSessionExpired, log);
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
case "already-expired":
|
|
278
|
+
await setSession(null);
|
|
279
|
+
return null;
|
|
280
|
+
case "unknown":
|
|
281
|
+
if (fallback === null) {
|
|
282
|
+
throw result.error;
|
|
283
|
+
}
|
|
284
|
+
if (!joined) {
|
|
285
|
+
log.warning(
|
|
286
|
+
() => ({ msg: "refresh failed; serving the current token" }),
|
|
287
|
+
result.error
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
return fallback;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* One `POST /oauth/token`, total: every failure comes back as a value, so
|
|
295
|
+
* the coordinator can judge it once for everyone who joined.
|
|
296
|
+
*
|
|
297
|
+
* Never retried. The refresh token is single-use, so a retry of an attempt
|
|
298
|
+
* that reached the server would present a token already rotated away, and
|
|
299
|
+
* its `invalid_grant` would be judged as a rejection of the session.
|
|
300
|
+
*/
|
|
301
|
+
async exchange(refreshToken) {
|
|
302
|
+
if (refreshToken === void 0) {
|
|
303
|
+
return { type: "unrenewable" };
|
|
117
304
|
}
|
|
118
305
|
try {
|
|
119
306
|
const sessionDto = await this.api.send({
|
|
@@ -124,19 +311,12 @@ var ServerAuthNamespaceImpl = class {
|
|
|
124
311
|
refresh_token: refreshToken,
|
|
125
312
|
client_id: this.config.clientId,
|
|
126
313
|
client_secret: this.config.clientSecret
|
|
127
|
-
}
|
|
314
|
+
},
|
|
315
|
+
attributes: Attributes.notRetryable()
|
|
128
316
|
});
|
|
129
|
-
|
|
130
|
-
await setSession(newSession);
|
|
131
|
-
log.info(() => ({ msg: "session renewed" }));
|
|
132
|
-
return newSession.accessToken;
|
|
317
|
+
return { type: "renewed", session: OAuthSession.fromDto(sessionDto) };
|
|
133
318
|
} catch (error) {
|
|
134
|
-
|
|
135
|
-
() => ({ msg: "refresh failed; clearing the session" }),
|
|
136
|
-
error
|
|
137
|
-
);
|
|
138
|
-
await setSession(null);
|
|
139
|
-
return null;
|
|
319
|
+
return isInvalidGrant(error) ? { type: "rejected" } : { type: "unknown", error };
|
|
140
320
|
}
|
|
141
321
|
}
|
|
142
322
|
async clientCredentials() {
|
|
@@ -182,18 +362,91 @@ var ServerAuthNamespaceImpl = class {
|
|
|
182
362
|
await setSession(null);
|
|
183
363
|
}
|
|
184
364
|
/**
|
|
185
|
-
* Returns the store's `setSession`, or throws
|
|
365
|
+
* Returns the store's `setSession`, or throws - the guard every
|
|
186
366
|
* session-writing operation shares.
|
|
187
367
|
*/
|
|
188
368
|
writableSessionStore() {
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
369
|
+
const store = sessionStoreAccess(this.config.sessionStore);
|
|
370
|
+
switch (store.type) {
|
|
371
|
+
case "writable":
|
|
372
|
+
return store.setSession;
|
|
373
|
+
case "read-only":
|
|
374
|
+
throw new WritableSessionStoreRequiredError();
|
|
193
375
|
}
|
|
194
|
-
return setSession;
|
|
195
376
|
}
|
|
196
377
|
};
|
|
378
|
+
function classifyAccessToken({
|
|
379
|
+
session,
|
|
380
|
+
store,
|
|
381
|
+
trigger,
|
|
382
|
+
now,
|
|
383
|
+
buffer
|
|
384
|
+
}) {
|
|
385
|
+
if (session === null) {
|
|
386
|
+
return { type: "no-session" };
|
|
387
|
+
}
|
|
388
|
+
const token = session.accessToken;
|
|
389
|
+
const stale = isExpired({
|
|
390
|
+
expiresAt: EpochMillis.fromDate(token.expiresAt),
|
|
391
|
+
now,
|
|
392
|
+
buffer
|
|
393
|
+
});
|
|
394
|
+
switch (store.type) {
|
|
395
|
+
case "read-only":
|
|
396
|
+
return classifyReadOnly(token, trigger, stale);
|
|
397
|
+
case "writable": {
|
|
398
|
+
if (!needsRefresh(token, trigger, stale)) {
|
|
399
|
+
return { type: "serve", token };
|
|
400
|
+
}
|
|
401
|
+
const fallback = fallbackToken(token, trigger, now);
|
|
402
|
+
return session.refreshToken === void 0 && fallback !== null ? { type: "serve", token: fallback } : {
|
|
403
|
+
type: "refresh",
|
|
404
|
+
session,
|
|
405
|
+
setSession: store.setSession,
|
|
406
|
+
fallback
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
function classifyReadOnly(token, trigger, stale) {
|
|
412
|
+
switch (trigger.type) {
|
|
413
|
+
case "after-401":
|
|
414
|
+
return isRejectedToken(token, trigger.rejected) ? { type: "refuse" } : { type: "serve", token };
|
|
415
|
+
case "before-request":
|
|
416
|
+
return stale ? { type: "serve-stale", token } : { type: "serve", token };
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
function sessionStoreAccess(sessionStore) {
|
|
420
|
+
const setSession = sessionStore.setSession?.bind(sessionStore);
|
|
421
|
+
return setSession === void 0 ? { type: "read-only" } : { type: "writable", setSession };
|
|
422
|
+
}
|
|
423
|
+
function needsRefresh(token, trigger, stale) {
|
|
424
|
+
switch (trigger.type) {
|
|
425
|
+
case "before-request":
|
|
426
|
+
return stale;
|
|
427
|
+
case "after-401":
|
|
428
|
+
return trigger.rejected.type === "no-user-token" || isRejectedToken(token, trigger.rejected) || stale;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
function fallbackToken(token, trigger, now) {
|
|
432
|
+
const unexpired = !isExpired({
|
|
433
|
+
expiresAt: EpochMillis.fromDate(token.expiresAt),
|
|
434
|
+
now
|
|
435
|
+
});
|
|
436
|
+
switch (trigger.type) {
|
|
437
|
+
case "after-401":
|
|
438
|
+
return unexpired && !isRejectedToken(token, trigger.rejected) ? token : null;
|
|
439
|
+
case "before-request":
|
|
440
|
+
return unexpired ? token : null;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
function isInvalidGrant(error) {
|
|
444
|
+
if (!(error instanceof HttpError) || error.response.status !== 400) {
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
const body = error.response.body;
|
|
448
|
+
return typeof body === "object" && body !== null && "error" in body && body.error === "invalid_grant";
|
|
449
|
+
}
|
|
197
450
|
|
|
198
451
|
// src/server/core/server-offers-namespace.ts
|
|
199
452
|
var ServerOffersNamespaceImpl = class {
|
|
@@ -240,28 +493,26 @@ var ServerRequirementsNamespaceImpl = class extends RequirementsNamespaceImpl {
|
|
|
240
493
|
};
|
|
241
494
|
|
|
242
495
|
// src/server/core/coinlist-server.ts
|
|
243
|
-
var
|
|
496
|
+
var ACCESS_TOKEN_EXPIRY_BUFFER = Seconds.of(60);
|
|
244
497
|
var CoinListServerImpl = class {
|
|
245
498
|
constructor(_config) {
|
|
246
|
-
this._config = _config;
|
|
247
499
|
const logger = _config.logger ?? null;
|
|
248
500
|
this.api = new ApiClient(
|
|
249
501
|
{
|
|
250
502
|
baseUrl: _config.baseUrl ?? PUBLIC_API_BASE_URL,
|
|
251
503
|
xApiVersion: API_VERSION
|
|
252
504
|
},
|
|
253
|
-
|
|
254
|
-
// fresh token. A read-only store cannot persist a new session, so return
|
|
255
|
-
// null immediately — this tells the middleware to skip the retry rather
|
|
256
|
-
// than re-sending with the same expired token and wasting a round-trip.
|
|
257
|
-
(refresh) => refresh && !this._config.sessionStore.setSession ? Promise.resolve(null) : this.auth.getAccessToken(),
|
|
505
|
+
(trigger) => auth.tokenFor(trigger),
|
|
258
506
|
logger
|
|
259
507
|
);
|
|
260
|
-
|
|
508
|
+
const auth = new ServerAuthNamespaceImpl(this.api, {
|
|
261
509
|
..._config,
|
|
262
|
-
accessTokenExpiryBufferSeconds: _config.accessTokenExpiryBufferSeconds ??
|
|
263
|
-
strict: _config.strict ?? false
|
|
510
|
+
accessTokenExpiryBufferSeconds: _config.accessTokenExpiryBufferSeconds ?? ACCESS_TOKEN_EXPIRY_BUFFER,
|
|
511
|
+
strict: _config.strict ?? false,
|
|
512
|
+
refreshes: processRefreshCoordinator,
|
|
513
|
+
...systemTime
|
|
264
514
|
});
|
|
515
|
+
this.auth = auth;
|
|
265
516
|
const ctx = {
|
|
266
517
|
api: this.api,
|
|
267
518
|
rpc: publicClients(this.api, _config.rpc, _config.logger ?? null),
|
|
@@ -311,8 +562,12 @@ function pinoServerLogger(options) {
|
|
|
311
562
|
options.level
|
|
312
563
|
);
|
|
313
564
|
}
|
|
565
|
+
|
|
566
|
+
// src/server/core/server-auth-namespace.ts
|
|
567
|
+
function emptySessionStore() {
|
|
568
|
+
return { getSession: async () => null };
|
|
569
|
+
}
|
|
314
570
|
export {
|
|
315
|
-
ServerAuthNamespaceImpl,
|
|
316
571
|
ServerOffersNamespaceImpl,
|
|
317
572
|
ServerRequirementsNamespaceImpl,
|
|
318
573
|
WritableSessionStoreRequiredError,
|