@kedaruma/revlm-client 1.0.46 → 1.0.49
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-Y6FXYEAI.mjs → chunk-EBO3CZXG.mjs} +6 -1
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +169 -0
- package/dist/index.mjs +169 -1
- package/dist/rn-setup.mjs +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
1
2
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
3
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
4
|
}) : x)(function(x) {
|
|
4
5
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
6
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
7
|
});
|
|
8
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
7
11
|
|
|
8
12
|
export {
|
|
9
|
-
__require
|
|
13
|
+
__require,
|
|
14
|
+
__commonJS
|
|
10
15
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -201,6 +201,7 @@ declare class Revlm {
|
|
|
201
201
|
private autoSetToken;
|
|
202
202
|
private autoRefreshOn401;
|
|
203
203
|
private cookieCheckPromise?;
|
|
204
|
+
private logLevel;
|
|
204
205
|
constructor(baseUrl: string, opts?: RevlmOptions);
|
|
205
206
|
setToken(token: string): void;
|
|
206
207
|
getToken(): string | undefined;
|
|
@@ -213,6 +214,8 @@ declare class Revlm {
|
|
|
213
214
|
private request;
|
|
214
215
|
private shouldSkipAuthRetry;
|
|
215
216
|
private shouldSkipCookieCheck;
|
|
217
|
+
private decodeJwtPayload;
|
|
218
|
+
private logTokenTtl;
|
|
216
219
|
private signIfNeeded;
|
|
217
220
|
private requestWithRetry;
|
|
218
221
|
login(authId: string, password: string): Promise<LoginResponse>;
|
package/dist/index.d.ts
CHANGED
|
@@ -201,6 +201,7 @@ declare class Revlm {
|
|
|
201
201
|
private autoSetToken;
|
|
202
202
|
private autoRefreshOn401;
|
|
203
203
|
private cookieCheckPromise?;
|
|
204
|
+
private logLevel;
|
|
204
205
|
constructor(baseUrl: string, opts?: RevlmOptions);
|
|
205
206
|
setToken(token: string): void;
|
|
206
207
|
getToken(): string | undefined;
|
|
@@ -213,6 +214,8 @@ declare class Revlm {
|
|
|
213
214
|
private request;
|
|
214
215
|
private shouldSkipAuthRetry;
|
|
215
216
|
private shouldSkipCookieCheck;
|
|
217
|
+
private decodeJwtPayload;
|
|
218
|
+
private logTokenTtl;
|
|
216
219
|
private signIfNeeded;
|
|
217
220
|
private requestWithRetry;
|
|
218
221
|
login(authId: string, password: string): Promise<LoginResponse>;
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +30,73 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
33
|
+
// package.json
|
|
34
|
+
var require_package = __commonJS({
|
|
35
|
+
"package.json"(exports2, module2) {
|
|
36
|
+
module2.exports = {
|
|
37
|
+
name: "@kedaruma/revlm-client",
|
|
38
|
+
version: "1.0.49",
|
|
39
|
+
private: false,
|
|
40
|
+
description: "TypeScript client SDK for talking to the Revlm server replacement for MongoDB Realm.",
|
|
41
|
+
keywords: [
|
|
42
|
+
"realm",
|
|
43
|
+
"realm-web",
|
|
44
|
+
"mongodb-realm",
|
|
45
|
+
"mongodb",
|
|
46
|
+
"realm-alternative",
|
|
47
|
+
"app-services",
|
|
48
|
+
"auth"
|
|
49
|
+
],
|
|
50
|
+
main: "dist/index.js",
|
|
51
|
+
module: "dist/index.mjs",
|
|
52
|
+
types: "dist/index.d.ts",
|
|
53
|
+
exports: {
|
|
54
|
+
".": {
|
|
55
|
+
import: {
|
|
56
|
+
types: "./dist/index.d.mts",
|
|
57
|
+
default: "./dist/index.mjs"
|
|
58
|
+
},
|
|
59
|
+
require: {
|
|
60
|
+
types: "./dist/index.d.ts",
|
|
61
|
+
default: "./dist/index.js"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"./rn-setup": {
|
|
65
|
+
import: {
|
|
66
|
+
types: "./dist/rn-setup.d.mts",
|
|
67
|
+
default: "./dist/rn-setup.mjs"
|
|
68
|
+
},
|
|
69
|
+
require: {
|
|
70
|
+
types: "./dist/rn-setup.d.ts",
|
|
71
|
+
default: "./dist/rn-setup.js"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
sideEffects: false,
|
|
76
|
+
files: [
|
|
77
|
+
"dist/"
|
|
78
|
+
],
|
|
79
|
+
license: "ISC",
|
|
80
|
+
publishConfig: {
|
|
81
|
+
access: "public"
|
|
82
|
+
},
|
|
83
|
+
scripts: {
|
|
84
|
+
build: "tsup src/index.ts src/rn-setup.ts --format cjs,esm --dts --tsconfig tsconfig.build.json",
|
|
85
|
+
clean: "rm -rf dist node_modules kedaruma-revlm-client-*.tgz",
|
|
86
|
+
test: "pnpm exec jest --config ../../jest.config.cjs packages/revlm-client/src/__tests__/ --runInBand --watchman=false --verbose"
|
|
87
|
+
},
|
|
88
|
+
dependencies: {
|
|
89
|
+
"@kedaruma/revlm-shared": "workspace:*",
|
|
90
|
+
bson: "^6.10.4",
|
|
91
|
+
dotenv: "^17.2.3"
|
|
92
|
+
},
|
|
93
|
+
devDependencies: {
|
|
94
|
+
tsup: "^8.5.1"
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
30
100
|
// src/index.ts
|
|
31
101
|
var index_exports = {};
|
|
32
102
|
__export(index_exports, {
|
|
@@ -146,6 +216,35 @@ var RevlmDBDatabase = class {
|
|
|
146
216
|
};
|
|
147
217
|
|
|
148
218
|
// src/Revlm.ts
|
|
219
|
+
function normalizeLogLevel(value) {
|
|
220
|
+
if (!value) return "error";
|
|
221
|
+
const lowered = value.toLowerCase();
|
|
222
|
+
if (lowered === "true" || lowered === "1") return "debug";
|
|
223
|
+
if (lowered === "false" || lowered === "0") return "error";
|
|
224
|
+
if (lowered === "error" || lowered === "warn" || lowered === "info" || lowered === "debug") {
|
|
225
|
+
return lowered;
|
|
226
|
+
}
|
|
227
|
+
return "error";
|
|
228
|
+
}
|
|
229
|
+
function getClientLogLevel() {
|
|
230
|
+
const envValue = typeof process !== "undefined" && process.env ? process.env.LOG_LEVEL : void 0;
|
|
231
|
+
const globalValue = globalThis?.LOG_LEVEL;
|
|
232
|
+
const value = typeof envValue === "string" ? envValue : typeof globalValue === "string" ? globalValue : void 0;
|
|
233
|
+
return normalizeLogLevel(value);
|
|
234
|
+
}
|
|
235
|
+
function maskSecret(value) {
|
|
236
|
+
if (!value) return void 0;
|
|
237
|
+
return `<...:${value.length}>`;
|
|
238
|
+
}
|
|
239
|
+
function getRevlmClientVersion() {
|
|
240
|
+
try {
|
|
241
|
+
const pkg = require_package();
|
|
242
|
+
if (pkg && typeof pkg.version === "string") return pkg.version;
|
|
243
|
+
} catch {
|
|
244
|
+
}
|
|
245
|
+
const globalVersion = globalThis?.REVLM_CLIENT_VERSION;
|
|
246
|
+
return typeof globalVersion === "string" ? globalVersion : "unknown";
|
|
247
|
+
}
|
|
149
248
|
var Revlm = class {
|
|
150
249
|
baseUrl;
|
|
151
250
|
fetchImpl;
|
|
@@ -157,6 +256,7 @@ var Revlm = class {
|
|
|
157
256
|
autoSetToken;
|
|
158
257
|
autoRefreshOn401;
|
|
159
258
|
cookieCheckPromise;
|
|
259
|
+
logLevel;
|
|
160
260
|
constructor(baseUrl, opts = {}) {
|
|
161
261
|
if (!baseUrl) throw new Error("baseUrl is required");
|
|
162
262
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -167,9 +267,24 @@ var Revlm = class {
|
|
|
167
267
|
this.provisionalAuthDomain = opts.provisionalAuthDomain || "";
|
|
168
268
|
this.autoSetToken = opts.autoSetToken ?? true;
|
|
169
269
|
this.autoRefreshOn401 = opts.autoRefreshOn401 || false;
|
|
270
|
+
this.logLevel = getClientLogLevel();
|
|
170
271
|
if (!this.fetchImpl) {
|
|
171
272
|
throw new Error("No fetch implementation available. Provide fetchImpl in options or run in Node 18+ with global fetch.");
|
|
172
273
|
}
|
|
274
|
+
if (this.logLevel === "debug") {
|
|
275
|
+
console.log("\u{1F680} Revlm Client Init", {
|
|
276
|
+
version: getRevlmClientVersion(),
|
|
277
|
+
baseUrl: this.baseUrl,
|
|
278
|
+
autoSetToken: this.autoSetToken,
|
|
279
|
+
autoRefreshOn401: this.autoRefreshOn401,
|
|
280
|
+
provisionalEnabled: this.provisionalEnabled,
|
|
281
|
+
provisionalAuthDomain: this.provisionalAuthDomain || void 0,
|
|
282
|
+
provisionalAuthSecretMaster: maskSecret(this.provisionalAuthSecretMaster),
|
|
283
|
+
defaultHeaders: Object.keys(this.defaultHeaders || {}),
|
|
284
|
+
fetchImplProvided: !!opts.fetchImpl,
|
|
285
|
+
logLevel: this.logLevel
|
|
286
|
+
});
|
|
287
|
+
}
|
|
173
288
|
}
|
|
174
289
|
setToken(token) {
|
|
175
290
|
this._token = token;
|
|
@@ -240,6 +355,43 @@ var Revlm = class {
|
|
|
240
355
|
const pathname = path.startsWith("http") ? new URL(path).pathname : path;
|
|
241
356
|
return pathname.includes("/cookie-check");
|
|
242
357
|
}
|
|
358
|
+
decodeJwtPayload(token) {
|
|
359
|
+
if (!token) return null;
|
|
360
|
+
const parts = token.split(".");
|
|
361
|
+
const payloadPart = parts[1];
|
|
362
|
+
if (!payloadPart) return null;
|
|
363
|
+
const raw = payloadPart.replace(/-/g, "+").replace(/_/g, "/");
|
|
364
|
+
const pad = raw.length % 4 ? "=".repeat(4 - raw.length % 4) : "";
|
|
365
|
+
const base64 = raw + pad;
|
|
366
|
+
let jsonText = null;
|
|
367
|
+
if (typeof atob === "function") {
|
|
368
|
+
jsonText = atob(base64);
|
|
369
|
+
} else if (typeof Buffer !== "undefined") {
|
|
370
|
+
jsonText = Buffer.from(base64, "base64").toString("utf8");
|
|
371
|
+
}
|
|
372
|
+
if (!jsonText) return null;
|
|
373
|
+
try {
|
|
374
|
+
const payload = JSON.parse(jsonText);
|
|
375
|
+
return { exp: payload?.exp, iat: payload?.iat };
|
|
376
|
+
} catch {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
logTokenTtl(event, path, tokenOverride) {
|
|
381
|
+
const token = tokenOverride || this._token;
|
|
382
|
+
if (!token) return;
|
|
383
|
+
const payload = this.decodeJwtPayload(token);
|
|
384
|
+
if (!payload || typeof payload.exp !== "number") return;
|
|
385
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
386
|
+
const ttlSec = payload.exp - now;
|
|
387
|
+
console.log("### token ttl", {
|
|
388
|
+
event,
|
|
389
|
+
path,
|
|
390
|
+
ttlSec,
|
|
391
|
+
exp: payload.exp,
|
|
392
|
+
iat: payload.iat
|
|
393
|
+
});
|
|
394
|
+
}
|
|
243
395
|
async signIfNeeded(_url, _method, headers, _body) {
|
|
244
396
|
return { signedUrl: _url, signedHeaders: headers };
|
|
245
397
|
}
|
|
@@ -269,6 +421,7 @@ var Revlm = class {
|
|
|
269
421
|
out.error = parsed?.reason || parsed?.message || "Unknown error";
|
|
270
422
|
}
|
|
271
423
|
if (allowAuthRetry && !retrying && res.status === 401 && !this.shouldSkipAuthRetry(path)) {
|
|
424
|
+
const beforePayload = this.decodeJwtPayload(this._token || "");
|
|
272
425
|
const refreshRes = await this.refreshToken();
|
|
273
426
|
if (!refreshRes.ok) {
|
|
274
427
|
console.warn("### refresh failed:", {
|
|
@@ -283,9 +436,23 @@ var Revlm = class {
|
|
|
283
436
|
}
|
|
284
437
|
}
|
|
285
438
|
if (refreshRes && refreshRes.ok && refreshRes.token) {
|
|
439
|
+
const afterPayload = this.decodeJwtPayload(refreshRes.token);
|
|
440
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
441
|
+
const oldExp = beforePayload?.exp;
|
|
442
|
+
const newExp = afterPayload?.exp;
|
|
443
|
+
console.log("### refresh success", {
|
|
444
|
+
path,
|
|
445
|
+
oldExp,
|
|
446
|
+
newExp,
|
|
447
|
+
oldTtlSec: typeof oldExp === "number" ? oldExp - now : void 0,
|
|
448
|
+
newTtlSec: typeof newExp === "number" ? newExp - now : void 0
|
|
449
|
+
});
|
|
286
450
|
return this.requestWithRetry(path, method, body, { allowAuthRetry: false, retrying: true });
|
|
287
451
|
}
|
|
288
452
|
}
|
|
453
|
+
if (out.ok && !this.shouldSkipCookieCheck(path)) {
|
|
454
|
+
this.logTokenTtl("request_ok", path);
|
|
455
|
+
}
|
|
289
456
|
return out;
|
|
290
457
|
} catch (err) {
|
|
291
458
|
if (err && err.revlmReason === "no_refresh_secret") {
|
|
@@ -337,11 +504,13 @@ var Revlm = class {
|
|
|
337
504
|
if (this.cookieCheckPromise) return this.cookieCheckPromise;
|
|
338
505
|
this.cookieCheckPromise = (async () => {
|
|
339
506
|
const first = await this.requestWithRetry("/cookie-check", "POST", void 0, { allowAuthRetry: false, retrying: false });
|
|
507
|
+
console.log("### cookie check", { step: "first", ok: first.ok, reason: first.reason, status: first.status });
|
|
340
508
|
if (first.ok) return;
|
|
341
509
|
if (first.reason !== "cookie_missing") {
|
|
342
510
|
throw new Error(`Cookie check failed: ${first.reason || first.error || "unknown_error"}`);
|
|
343
511
|
}
|
|
344
512
|
const second = await this.requestWithRetry("/cookie-check", "POST", void 0, { allowAuthRetry: false, retrying: false });
|
|
513
|
+
console.log("### cookie check", { step: "second", ok: second.ok, reason: second.reason, status: second.status });
|
|
345
514
|
if (!second.ok) {
|
|
346
515
|
throw new Error("Cookie support missing. Provide a cookie-aware fetch implementation for Node/RN.");
|
|
347
516
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,73 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
__commonJS
|
|
3
|
+
} from "./chunk-EBO3CZXG.mjs";
|
|
4
|
+
|
|
5
|
+
// package.json
|
|
6
|
+
var require_package = __commonJS({
|
|
7
|
+
"package.json"(exports, module) {
|
|
8
|
+
module.exports = {
|
|
9
|
+
name: "@kedaruma/revlm-client",
|
|
10
|
+
version: "1.0.49",
|
|
11
|
+
private: false,
|
|
12
|
+
description: "TypeScript client SDK for talking to the Revlm server replacement for MongoDB Realm.",
|
|
13
|
+
keywords: [
|
|
14
|
+
"realm",
|
|
15
|
+
"realm-web",
|
|
16
|
+
"mongodb-realm",
|
|
17
|
+
"mongodb",
|
|
18
|
+
"realm-alternative",
|
|
19
|
+
"app-services",
|
|
20
|
+
"auth"
|
|
21
|
+
],
|
|
22
|
+
main: "dist/index.js",
|
|
23
|
+
module: "dist/index.mjs",
|
|
24
|
+
types: "dist/index.d.ts",
|
|
25
|
+
exports: {
|
|
26
|
+
".": {
|
|
27
|
+
import: {
|
|
28
|
+
types: "./dist/index.d.mts",
|
|
29
|
+
default: "./dist/index.mjs"
|
|
30
|
+
},
|
|
31
|
+
require: {
|
|
32
|
+
types: "./dist/index.d.ts",
|
|
33
|
+
default: "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"./rn-setup": {
|
|
37
|
+
import: {
|
|
38
|
+
types: "./dist/rn-setup.d.mts",
|
|
39
|
+
default: "./dist/rn-setup.mjs"
|
|
40
|
+
},
|
|
41
|
+
require: {
|
|
42
|
+
types: "./dist/rn-setup.d.ts",
|
|
43
|
+
default: "./dist/rn-setup.js"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
sideEffects: false,
|
|
48
|
+
files: [
|
|
49
|
+
"dist/"
|
|
50
|
+
],
|
|
51
|
+
license: "ISC",
|
|
52
|
+
publishConfig: {
|
|
53
|
+
access: "public"
|
|
54
|
+
},
|
|
55
|
+
scripts: {
|
|
56
|
+
build: "tsup src/index.ts src/rn-setup.ts --format cjs,esm --dts --tsconfig tsconfig.build.json",
|
|
57
|
+
clean: "rm -rf dist node_modules kedaruma-revlm-client-*.tgz",
|
|
58
|
+
test: "pnpm exec jest --config ../../jest.config.cjs packages/revlm-client/src/__tests__/ --runInBand --watchman=false --verbose"
|
|
59
|
+
},
|
|
60
|
+
dependencies: {
|
|
61
|
+
"@kedaruma/revlm-shared": "workspace:*",
|
|
62
|
+
bson: "^6.10.4",
|
|
63
|
+
dotenv: "^17.2.3"
|
|
64
|
+
},
|
|
65
|
+
devDependencies: {
|
|
66
|
+
tsup: "^8.5.1"
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
});
|
|
2
71
|
|
|
3
72
|
// src/Revlm.ts
|
|
4
73
|
import { EJSON } from "bson";
|
|
@@ -103,6 +172,35 @@ var RevlmDBDatabase = class {
|
|
|
103
172
|
};
|
|
104
173
|
|
|
105
174
|
// src/Revlm.ts
|
|
175
|
+
function normalizeLogLevel(value) {
|
|
176
|
+
if (!value) return "error";
|
|
177
|
+
const lowered = value.toLowerCase();
|
|
178
|
+
if (lowered === "true" || lowered === "1") return "debug";
|
|
179
|
+
if (lowered === "false" || lowered === "0") return "error";
|
|
180
|
+
if (lowered === "error" || lowered === "warn" || lowered === "info" || lowered === "debug") {
|
|
181
|
+
return lowered;
|
|
182
|
+
}
|
|
183
|
+
return "error";
|
|
184
|
+
}
|
|
185
|
+
function getClientLogLevel() {
|
|
186
|
+
const envValue = typeof process !== "undefined" && process.env ? process.env.LOG_LEVEL : void 0;
|
|
187
|
+
const globalValue = globalThis?.LOG_LEVEL;
|
|
188
|
+
const value = typeof envValue === "string" ? envValue : typeof globalValue === "string" ? globalValue : void 0;
|
|
189
|
+
return normalizeLogLevel(value);
|
|
190
|
+
}
|
|
191
|
+
function maskSecret(value) {
|
|
192
|
+
if (!value) return void 0;
|
|
193
|
+
return `<...:${value.length}>`;
|
|
194
|
+
}
|
|
195
|
+
function getRevlmClientVersion() {
|
|
196
|
+
try {
|
|
197
|
+
const pkg = require_package();
|
|
198
|
+
if (pkg && typeof pkg.version === "string") return pkg.version;
|
|
199
|
+
} catch {
|
|
200
|
+
}
|
|
201
|
+
const globalVersion = globalThis?.REVLM_CLIENT_VERSION;
|
|
202
|
+
return typeof globalVersion === "string" ? globalVersion : "unknown";
|
|
203
|
+
}
|
|
106
204
|
var Revlm = class {
|
|
107
205
|
baseUrl;
|
|
108
206
|
fetchImpl;
|
|
@@ -114,6 +212,7 @@ var Revlm = class {
|
|
|
114
212
|
autoSetToken;
|
|
115
213
|
autoRefreshOn401;
|
|
116
214
|
cookieCheckPromise;
|
|
215
|
+
logLevel;
|
|
117
216
|
constructor(baseUrl, opts = {}) {
|
|
118
217
|
if (!baseUrl) throw new Error("baseUrl is required");
|
|
119
218
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -124,9 +223,24 @@ var Revlm = class {
|
|
|
124
223
|
this.provisionalAuthDomain = opts.provisionalAuthDomain || "";
|
|
125
224
|
this.autoSetToken = opts.autoSetToken ?? true;
|
|
126
225
|
this.autoRefreshOn401 = opts.autoRefreshOn401 || false;
|
|
226
|
+
this.logLevel = getClientLogLevel();
|
|
127
227
|
if (!this.fetchImpl) {
|
|
128
228
|
throw new Error("No fetch implementation available. Provide fetchImpl in options or run in Node 18+ with global fetch.");
|
|
129
229
|
}
|
|
230
|
+
if (this.logLevel === "debug") {
|
|
231
|
+
console.log("\u{1F680} Revlm Client Init", {
|
|
232
|
+
version: getRevlmClientVersion(),
|
|
233
|
+
baseUrl: this.baseUrl,
|
|
234
|
+
autoSetToken: this.autoSetToken,
|
|
235
|
+
autoRefreshOn401: this.autoRefreshOn401,
|
|
236
|
+
provisionalEnabled: this.provisionalEnabled,
|
|
237
|
+
provisionalAuthDomain: this.provisionalAuthDomain || void 0,
|
|
238
|
+
provisionalAuthSecretMaster: maskSecret(this.provisionalAuthSecretMaster),
|
|
239
|
+
defaultHeaders: Object.keys(this.defaultHeaders || {}),
|
|
240
|
+
fetchImplProvided: !!opts.fetchImpl,
|
|
241
|
+
logLevel: this.logLevel
|
|
242
|
+
});
|
|
243
|
+
}
|
|
130
244
|
}
|
|
131
245
|
setToken(token) {
|
|
132
246
|
this._token = token;
|
|
@@ -197,6 +311,43 @@ var Revlm = class {
|
|
|
197
311
|
const pathname = path.startsWith("http") ? new URL(path).pathname : path;
|
|
198
312
|
return pathname.includes("/cookie-check");
|
|
199
313
|
}
|
|
314
|
+
decodeJwtPayload(token) {
|
|
315
|
+
if (!token) return null;
|
|
316
|
+
const parts = token.split(".");
|
|
317
|
+
const payloadPart = parts[1];
|
|
318
|
+
if (!payloadPart) return null;
|
|
319
|
+
const raw = payloadPart.replace(/-/g, "+").replace(/_/g, "/");
|
|
320
|
+
const pad = raw.length % 4 ? "=".repeat(4 - raw.length % 4) : "";
|
|
321
|
+
const base64 = raw + pad;
|
|
322
|
+
let jsonText = null;
|
|
323
|
+
if (typeof atob === "function") {
|
|
324
|
+
jsonText = atob(base64);
|
|
325
|
+
} else if (typeof Buffer !== "undefined") {
|
|
326
|
+
jsonText = Buffer.from(base64, "base64").toString("utf8");
|
|
327
|
+
}
|
|
328
|
+
if (!jsonText) return null;
|
|
329
|
+
try {
|
|
330
|
+
const payload = JSON.parse(jsonText);
|
|
331
|
+
return { exp: payload?.exp, iat: payload?.iat };
|
|
332
|
+
} catch {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
logTokenTtl(event, path, tokenOverride) {
|
|
337
|
+
const token = tokenOverride || this._token;
|
|
338
|
+
if (!token) return;
|
|
339
|
+
const payload = this.decodeJwtPayload(token);
|
|
340
|
+
if (!payload || typeof payload.exp !== "number") return;
|
|
341
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
342
|
+
const ttlSec = payload.exp - now;
|
|
343
|
+
console.log("### token ttl", {
|
|
344
|
+
event,
|
|
345
|
+
path,
|
|
346
|
+
ttlSec,
|
|
347
|
+
exp: payload.exp,
|
|
348
|
+
iat: payload.iat
|
|
349
|
+
});
|
|
350
|
+
}
|
|
200
351
|
async signIfNeeded(_url, _method, headers, _body) {
|
|
201
352
|
return { signedUrl: _url, signedHeaders: headers };
|
|
202
353
|
}
|
|
@@ -226,6 +377,7 @@ var Revlm = class {
|
|
|
226
377
|
out.error = parsed?.reason || parsed?.message || "Unknown error";
|
|
227
378
|
}
|
|
228
379
|
if (allowAuthRetry && !retrying && res.status === 401 && !this.shouldSkipAuthRetry(path)) {
|
|
380
|
+
const beforePayload = this.decodeJwtPayload(this._token || "");
|
|
229
381
|
const refreshRes = await this.refreshToken();
|
|
230
382
|
if (!refreshRes.ok) {
|
|
231
383
|
console.warn("### refresh failed:", {
|
|
@@ -240,9 +392,23 @@ var Revlm = class {
|
|
|
240
392
|
}
|
|
241
393
|
}
|
|
242
394
|
if (refreshRes && refreshRes.ok && refreshRes.token) {
|
|
395
|
+
const afterPayload = this.decodeJwtPayload(refreshRes.token);
|
|
396
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
397
|
+
const oldExp = beforePayload?.exp;
|
|
398
|
+
const newExp = afterPayload?.exp;
|
|
399
|
+
console.log("### refresh success", {
|
|
400
|
+
path,
|
|
401
|
+
oldExp,
|
|
402
|
+
newExp,
|
|
403
|
+
oldTtlSec: typeof oldExp === "number" ? oldExp - now : void 0,
|
|
404
|
+
newTtlSec: typeof newExp === "number" ? newExp - now : void 0
|
|
405
|
+
});
|
|
243
406
|
return this.requestWithRetry(path, method, body, { allowAuthRetry: false, retrying: true });
|
|
244
407
|
}
|
|
245
408
|
}
|
|
409
|
+
if (out.ok && !this.shouldSkipCookieCheck(path)) {
|
|
410
|
+
this.logTokenTtl("request_ok", path);
|
|
411
|
+
}
|
|
246
412
|
return out;
|
|
247
413
|
} catch (err) {
|
|
248
414
|
if (err && err.revlmReason === "no_refresh_secret") {
|
|
@@ -294,11 +460,13 @@ var Revlm = class {
|
|
|
294
460
|
if (this.cookieCheckPromise) return this.cookieCheckPromise;
|
|
295
461
|
this.cookieCheckPromise = (async () => {
|
|
296
462
|
const first = await this.requestWithRetry("/cookie-check", "POST", void 0, { allowAuthRetry: false, retrying: false });
|
|
463
|
+
console.log("### cookie check", { step: "first", ok: first.ok, reason: first.reason, status: first.status });
|
|
297
464
|
if (first.ok) return;
|
|
298
465
|
if (first.reason !== "cookie_missing") {
|
|
299
466
|
throw new Error(`Cookie check failed: ${first.reason || first.error || "unknown_error"}`);
|
|
300
467
|
}
|
|
301
468
|
const second = await this.requestWithRetry("/cookie-check", "POST", void 0, { allowAuthRetry: false, retrying: false });
|
|
469
|
+
console.log("### cookie check", { step: "second", ok: second.ok, reason: second.reason, status: second.status });
|
|
302
470
|
if (!second.ok) {
|
|
303
471
|
throw new Error("Cookie support missing. Provide a cookie-aware fetch implementation for Node/RN.");
|
|
304
472
|
}
|
package/dist/rn-setup.mjs
CHANGED