@coinlist-co/react 0.12.2-rc.7b430dd → 0.12.2-rc.a59b344
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-DCW7NQXH.js → chunk-4IZ2F732.js} +52 -19
- package/dist/chunk-4IZ2F732.js.map +1 -0
- package/dist/{chunk-MOE5S6CE.js → chunk-NBO5E2RO.js} +152 -6
- package/dist/chunk-NBO5E2RO.js.map +1 -0
- package/dist/{chunk-VH34YC3Q.js → chunk-UJYSXXJF.js} +168 -3
- package/dist/chunk-UJYSXXJF.js.map +1 -0
- package/dist/client/index.cjs +469 -145
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +114 -35
- package/dist/client/index.d.ts +114 -35
- package/dist/client/index.js +297 -114
- package/dist/client/index.js.map +1 -1
- package/dist/server/index.cjs +507 -116
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +65 -41
- package/dist/server/index.d.ts +65 -41
- package/dist/server/index.js +321 -65
- package/dist/server/index.js.map +1 -1
- package/dist/time-CFocgYyl.d.cts +50 -0
- package/dist/time-DvgN98Q9.d.ts +50 -0
- package/dist/{token-registry-snapshot-BNBNuDu1.d.ts → token-registry-snapshot-BsAfBL_b.d.ts} +9 -7
- package/dist/{token-registry-snapshot-CqI6dXM_.d.cts → token-registry-snapshot-Cc_eA5zM.d.cts} +9 -7
- package/dist/{tokens-namespace-CIWBtgt2.d.cts → tokens-namespace-D_XSpiS-.d.cts} +154 -19
- package/dist/{tokens-namespace-CIWBtgt2.d.ts → tokens-namespace-D_XSpiS-.d.ts} +154 -19
- package/dist/universal/index.cjs +333 -40
- package/dist/universal/index.cjs.map +1 -1
- package/dist/universal/index.d.cts +358 -5
- package/dist/universal/index.d.ts +358 -5
- package/dist/universal/index.js +28 -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 +0 -1
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-4IZ2F732.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-NBO5E2RO.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() {
|
|
@@ -172,28 +352,102 @@ var ServerAuthNamespaceImpl = class {
|
|
|
172
352
|
}
|
|
173
353
|
});
|
|
174
354
|
} catch (err) {
|
|
175
|
-
if (
|
|
355
|
+
if (this.config.strict) {
|
|
176
356
|
throw err;
|
|
177
357
|
}
|
|
178
|
-
this.log.child({ op: "logout" }).
|
|
179
|
-
msg: "
|
|
180
|
-
|
|
358
|
+
this.log.child({ op: "logout" }).warning(
|
|
359
|
+
() => ({ msg: "revoke failed; local session cleared regardless" }),
|
|
360
|
+
err
|
|
361
|
+
);
|
|
181
362
|
}
|
|
182
363
|
await setSession(null);
|
|
183
364
|
}
|
|
184
365
|
/**
|
|
185
|
-
* Returns the store's `setSession`, or throws
|
|
366
|
+
* Returns the store's `setSession`, or throws - the guard every
|
|
186
367
|
* session-writing operation shares.
|
|
187
368
|
*/
|
|
188
369
|
writableSessionStore() {
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
370
|
+
const store = sessionStoreAccess(this.config.sessionStore);
|
|
371
|
+
switch (store.type) {
|
|
372
|
+
case "writable":
|
|
373
|
+
return store.setSession;
|
|
374
|
+
case "read-only":
|
|
375
|
+
throw new WritableSessionStoreRequiredError();
|
|
193
376
|
}
|
|
194
|
-
return setSession;
|
|
195
377
|
}
|
|
196
378
|
};
|
|
379
|
+
function classifyAccessToken({
|
|
380
|
+
session,
|
|
381
|
+
store,
|
|
382
|
+
trigger,
|
|
383
|
+
now,
|
|
384
|
+
buffer
|
|
385
|
+
}) {
|
|
386
|
+
if (session === null) {
|
|
387
|
+
return { type: "no-session" };
|
|
388
|
+
}
|
|
389
|
+
const token = session.accessToken;
|
|
390
|
+
const stale = isExpired({
|
|
391
|
+
expiresAt: EpochMillis.fromDate(token.expiresAt),
|
|
392
|
+
now,
|
|
393
|
+
buffer
|
|
394
|
+
});
|
|
395
|
+
switch (store.type) {
|
|
396
|
+
case "read-only":
|
|
397
|
+
return classifyReadOnly(token, trigger, stale);
|
|
398
|
+
case "writable": {
|
|
399
|
+
if (!needsRefresh(token, trigger, stale)) {
|
|
400
|
+
return { type: "serve", token };
|
|
401
|
+
}
|
|
402
|
+
const fallback = fallbackToken(token, trigger, now);
|
|
403
|
+
return session.refreshToken === void 0 && fallback !== null ? { type: "serve", token: fallback } : {
|
|
404
|
+
type: "refresh",
|
|
405
|
+
session,
|
|
406
|
+
setSession: store.setSession,
|
|
407
|
+
fallback
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function classifyReadOnly(token, trigger, stale) {
|
|
413
|
+
switch (trigger.type) {
|
|
414
|
+
case "after-401":
|
|
415
|
+
return isRejectedToken(token, trigger.rejected) ? { type: "refuse" } : { type: "serve", token };
|
|
416
|
+
case "before-request":
|
|
417
|
+
return stale ? { type: "serve-stale", token } : { type: "serve", token };
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function sessionStoreAccess(sessionStore) {
|
|
421
|
+
const setSession = sessionStore.setSession?.bind(sessionStore);
|
|
422
|
+
return setSession === void 0 ? { type: "read-only" } : { type: "writable", setSession };
|
|
423
|
+
}
|
|
424
|
+
function needsRefresh(token, trigger, stale) {
|
|
425
|
+
switch (trigger.type) {
|
|
426
|
+
case "before-request":
|
|
427
|
+
return stale;
|
|
428
|
+
case "after-401":
|
|
429
|
+
return trigger.rejected.type === "no-user-token" || isRejectedToken(token, trigger.rejected) || stale;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function fallbackToken(token, trigger, now) {
|
|
433
|
+
const unexpired = !isExpired({
|
|
434
|
+
expiresAt: EpochMillis.fromDate(token.expiresAt),
|
|
435
|
+
now
|
|
436
|
+
});
|
|
437
|
+
switch (trigger.type) {
|
|
438
|
+
case "after-401":
|
|
439
|
+
return unexpired && !isRejectedToken(token, trigger.rejected) ? token : null;
|
|
440
|
+
case "before-request":
|
|
441
|
+
return unexpired ? token : null;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
function isInvalidGrant(error) {
|
|
445
|
+
if (!(error instanceof HttpError) || error.response.status !== 400) {
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
const body = error.response.body;
|
|
449
|
+
return typeof body === "object" && body !== null && "error" in body && body.error === "invalid_grant";
|
|
450
|
+
}
|
|
197
451
|
|
|
198
452
|
// src/server/core/server-offers-namespace.ts
|
|
199
453
|
var ServerOffersNamespaceImpl = class {
|
|
@@ -240,28 +494,26 @@ var ServerRequirementsNamespaceImpl = class extends RequirementsNamespaceImpl {
|
|
|
240
494
|
};
|
|
241
495
|
|
|
242
496
|
// src/server/core/coinlist-server.ts
|
|
243
|
-
var
|
|
497
|
+
var ACCESS_TOKEN_EXPIRY_BUFFER = Seconds.of(60);
|
|
244
498
|
var CoinListServerImpl = class {
|
|
245
499
|
constructor(_config) {
|
|
246
|
-
this._config = _config;
|
|
247
500
|
const logger = _config.logger ?? null;
|
|
248
501
|
this.api = new ApiClient(
|
|
249
502
|
{
|
|
250
503
|
baseUrl: _config.baseUrl ?? PUBLIC_API_BASE_URL,
|
|
251
504
|
xApiVersion: API_VERSION
|
|
252
505
|
},
|
|
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(),
|
|
506
|
+
(trigger) => auth.tokenFor(trigger),
|
|
258
507
|
logger
|
|
259
508
|
);
|
|
260
|
-
|
|
509
|
+
const auth = new ServerAuthNamespaceImpl(this.api, {
|
|
261
510
|
..._config,
|
|
262
|
-
accessTokenExpiryBufferSeconds: _config.accessTokenExpiryBufferSeconds ??
|
|
263
|
-
strict: _config.strict ?? false
|
|
511
|
+
accessTokenExpiryBufferSeconds: _config.accessTokenExpiryBufferSeconds ?? ACCESS_TOKEN_EXPIRY_BUFFER,
|
|
512
|
+
strict: _config.strict ?? false,
|
|
513
|
+
refreshes: processRefreshCoordinator,
|
|
514
|
+
...systemTime
|
|
264
515
|
});
|
|
516
|
+
this.auth = auth;
|
|
265
517
|
const ctx = {
|
|
266
518
|
api: this.api,
|
|
267
519
|
rpc: publicClients(this.api, _config.rpc, _config.logger ?? null),
|
|
@@ -311,8 +563,12 @@ function pinoServerLogger(options) {
|
|
|
311
563
|
options.level
|
|
312
564
|
);
|
|
313
565
|
}
|
|
566
|
+
|
|
567
|
+
// src/server/core/server-auth-namespace.ts
|
|
568
|
+
function emptySessionStore() {
|
|
569
|
+
return { getSession: async () => null };
|
|
570
|
+
}
|
|
314
571
|
export {
|
|
315
|
-
ServerAuthNamespaceImpl,
|
|
316
572
|
ServerOffersNamespaceImpl,
|
|
317
573
|
ServerRequirementsNamespaceImpl,
|
|
318
574
|
WritableSessionStoreRequiredError,
|