@kedaruma/revlm-client 1.0.49 → 1.0.52

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/index.d.mts CHANGED
@@ -173,6 +173,7 @@ type EmailPasswordCredential = {
173
173
  type UserInput = Omit<User, 'userType'> & {
174
174
  userType: User['userType'] | string;
175
175
  };
176
+ type LogLevel = 'error' | 'warn' | 'info' | 'debug';
176
177
  type RevlmOptions = {
177
178
  fetchImpl?: typeof fetch;
178
179
  defaultHeaders?: Record<string, string>;
@@ -181,6 +182,7 @@ type RevlmOptions = {
181
182
  provisionalAuthDomain?: string;
182
183
  autoSetToken?: boolean;
183
184
  autoRefreshOn401?: boolean;
185
+ logLevel?: LogLevel;
184
186
  };
185
187
  type RevlmResponse<T = any> = {
186
188
  ok: boolean;
@@ -202,12 +204,14 @@ declare class Revlm {
202
204
  private autoRefreshOn401;
203
205
  private cookieCheckPromise?;
204
206
  private logLevel;
207
+ private refreshPromise;
205
208
  constructor(baseUrl: string, opts?: RevlmOptions);
206
209
  setToken(token: string): void;
207
210
  getToken(): string | undefined;
208
211
  clearToken(): void;
209
212
  logout(): void;
210
213
  refreshToken(): Promise<RevlmResponse>;
214
+ private refreshTokenSingleFlight;
211
215
  verifyToken(): Promise<RevlmResponse>;
212
216
  private makeHeaders;
213
217
  private parseResponse;
package/dist/index.d.ts CHANGED
@@ -173,6 +173,7 @@ type EmailPasswordCredential = {
173
173
  type UserInput = Omit<User, 'userType'> & {
174
174
  userType: User['userType'] | string;
175
175
  };
176
+ type LogLevel = 'error' | 'warn' | 'info' | 'debug';
176
177
  type RevlmOptions = {
177
178
  fetchImpl?: typeof fetch;
178
179
  defaultHeaders?: Record<string, string>;
@@ -181,6 +182,7 @@ type RevlmOptions = {
181
182
  provisionalAuthDomain?: string;
182
183
  autoSetToken?: boolean;
183
184
  autoRefreshOn401?: boolean;
185
+ logLevel?: LogLevel;
184
186
  };
185
187
  type RevlmResponse<T = any> = {
186
188
  ok: boolean;
@@ -202,12 +204,14 @@ declare class Revlm {
202
204
  private autoRefreshOn401;
203
205
  private cookieCheckPromise?;
204
206
  private logLevel;
207
+ private refreshPromise;
205
208
  constructor(baseUrl: string, opts?: RevlmOptions);
206
209
  setToken(token: string): void;
207
210
  getToken(): string | undefined;
208
211
  clearToken(): void;
209
212
  logout(): void;
210
213
  refreshToken(): Promise<RevlmResponse>;
214
+ private refreshTokenSingleFlight;
211
215
  verifyToken(): Promise<RevlmResponse>;
212
216
  private makeHeaders;
213
217
  private parseResponse;
package/dist/index.js CHANGED
@@ -35,7 +35,7 @@ var require_package = __commonJS({
35
35
  "package.json"(exports2, module2) {
36
36
  module2.exports = {
37
37
  name: "@kedaruma/revlm-client",
38
- version: "1.0.49",
38
+ version: "1.0.52",
39
39
  private: false,
40
40
  description: "TypeScript client SDK for talking to the Revlm server replacement for MongoDB Realm.",
41
41
  keywords: [
@@ -217,20 +217,14 @@ var RevlmDBDatabase = class {
217
217
 
218
218
  // src/Revlm.ts
219
219
  function normalizeLogLevel(value) {
220
- if (!value) return "error";
220
+ if (!value) return "info";
221
221
  const lowered = value.toLowerCase();
222
222
  if (lowered === "true" || lowered === "1") return "debug";
223
223
  if (lowered === "false" || lowered === "0") return "error";
224
224
  if (lowered === "error" || lowered === "warn" || lowered === "info" || lowered === "debug") {
225
225
  return lowered;
226
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);
227
+ return "info";
234
228
  }
235
229
  function maskSecret(value) {
236
230
  if (!value) return void 0;
@@ -257,6 +251,7 @@ var Revlm = class {
257
251
  autoRefreshOn401;
258
252
  cookieCheckPromise;
259
253
  logLevel;
254
+ refreshPromise;
260
255
  constructor(baseUrl, opts = {}) {
261
256
  if (!baseUrl) throw new Error("baseUrl is required");
262
257
  this.baseUrl = baseUrl.replace(/\/$/, "");
@@ -267,11 +262,11 @@ var Revlm = class {
267
262
  this.provisionalAuthDomain = opts.provisionalAuthDomain || "";
268
263
  this.autoSetToken = opts.autoSetToken ?? true;
269
264
  this.autoRefreshOn401 = opts.autoRefreshOn401 || false;
270
- this.logLevel = getClientLogLevel();
265
+ this.logLevel = normalizeLogLevel(opts.logLevel);
271
266
  if (!this.fetchImpl) {
272
267
  throw new Error("No fetch implementation available. Provide fetchImpl in options or run in Node 18+ with global fetch.");
273
268
  }
274
- if (this.logLevel === "debug") {
269
+ if (this.logLevel === "debug" || this.logLevel === "info") {
275
270
  console.log("\u{1F680} Revlm Client Init", {
276
271
  version: getRevlmClientVersion(),
277
272
  baseUrl: this.baseUrl,
@@ -309,6 +304,18 @@ var Revlm = class {
309
304
  }
310
305
  return res;
311
306
  }
307
+ async refreshTokenSingleFlight() {
308
+ if (!this.refreshPromise) {
309
+ this.refreshPromise = (async () => {
310
+ try {
311
+ return await this.refreshToken();
312
+ } finally {
313
+ this.refreshPromise = void 0;
314
+ }
315
+ })();
316
+ }
317
+ return this.refreshPromise;
318
+ }
312
319
  // Verify current token with server. If invalid/expired, clear local token.
313
320
  async verifyToken() {
314
321
  if (!this._token) return { ok: false, error: "No token set" };
@@ -422,8 +429,11 @@ var Revlm = class {
422
429
  }
423
430
  if (allowAuthRetry && !retrying && res.status === 401 && !this.shouldSkipAuthRetry(path)) {
424
431
  const beforePayload = this.decodeJwtPayload(this._token || "");
425
- const refreshRes = await this.refreshToken();
432
+ const refreshRes = await this.refreshTokenSingleFlight();
426
433
  if (!refreshRes.ok) {
434
+ if (refreshRes.reason === "not_expired") {
435
+ return this.requestWithRetry(path, method, body, { allowAuthRetry: false, retrying: true });
436
+ }
427
437
  console.warn("### refresh failed:", {
428
438
  reason: refreshRes.reason,
429
439
  status: refreshRes.status,
package/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@ var require_package = __commonJS({
7
7
  "package.json"(exports, module) {
8
8
  module.exports = {
9
9
  name: "@kedaruma/revlm-client",
10
- version: "1.0.49",
10
+ version: "1.0.52",
11
11
  private: false,
12
12
  description: "TypeScript client SDK for talking to the Revlm server replacement for MongoDB Realm.",
13
13
  keywords: [
@@ -173,20 +173,14 @@ var RevlmDBDatabase = class {
173
173
 
174
174
  // src/Revlm.ts
175
175
  function normalizeLogLevel(value) {
176
- if (!value) return "error";
176
+ if (!value) return "info";
177
177
  const lowered = value.toLowerCase();
178
178
  if (lowered === "true" || lowered === "1") return "debug";
179
179
  if (lowered === "false" || lowered === "0") return "error";
180
180
  if (lowered === "error" || lowered === "warn" || lowered === "info" || lowered === "debug") {
181
181
  return lowered;
182
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);
183
+ return "info";
190
184
  }
191
185
  function maskSecret(value) {
192
186
  if (!value) return void 0;
@@ -213,6 +207,7 @@ var Revlm = class {
213
207
  autoRefreshOn401;
214
208
  cookieCheckPromise;
215
209
  logLevel;
210
+ refreshPromise;
216
211
  constructor(baseUrl, opts = {}) {
217
212
  if (!baseUrl) throw new Error("baseUrl is required");
218
213
  this.baseUrl = baseUrl.replace(/\/$/, "");
@@ -223,11 +218,11 @@ var Revlm = class {
223
218
  this.provisionalAuthDomain = opts.provisionalAuthDomain || "";
224
219
  this.autoSetToken = opts.autoSetToken ?? true;
225
220
  this.autoRefreshOn401 = opts.autoRefreshOn401 || false;
226
- this.logLevel = getClientLogLevel();
221
+ this.logLevel = normalizeLogLevel(opts.logLevel);
227
222
  if (!this.fetchImpl) {
228
223
  throw new Error("No fetch implementation available. Provide fetchImpl in options or run in Node 18+ with global fetch.");
229
224
  }
230
- if (this.logLevel === "debug") {
225
+ if (this.logLevel === "debug" || this.logLevel === "info") {
231
226
  console.log("\u{1F680} Revlm Client Init", {
232
227
  version: getRevlmClientVersion(),
233
228
  baseUrl: this.baseUrl,
@@ -265,6 +260,18 @@ var Revlm = class {
265
260
  }
266
261
  return res;
267
262
  }
263
+ async refreshTokenSingleFlight() {
264
+ if (!this.refreshPromise) {
265
+ this.refreshPromise = (async () => {
266
+ try {
267
+ return await this.refreshToken();
268
+ } finally {
269
+ this.refreshPromise = void 0;
270
+ }
271
+ })();
272
+ }
273
+ return this.refreshPromise;
274
+ }
268
275
  // Verify current token with server. If invalid/expired, clear local token.
269
276
  async verifyToken() {
270
277
  if (!this._token) return { ok: false, error: "No token set" };
@@ -378,8 +385,11 @@ var Revlm = class {
378
385
  }
379
386
  if (allowAuthRetry && !retrying && res.status === 401 && !this.shouldSkipAuthRetry(path)) {
380
387
  const beforePayload = this.decodeJwtPayload(this._token || "");
381
- const refreshRes = await this.refreshToken();
388
+ const refreshRes = await this.refreshTokenSingleFlight();
382
389
  if (!refreshRes.ok) {
390
+ if (refreshRes.reason === "not_expired") {
391
+ return this.requestWithRetry(path, method, body, { allowAuthRetry: false, retrying: true });
392
+ }
383
393
  console.warn("### refresh failed:", {
384
394
  reason: refreshRes.reason,
385
395
  status: refreshRes.status,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kedaruma/revlm-client",
3
- "version": "1.0.49",
3
+ "version": "1.0.52",
4
4
  "private": false,
5
5
  "description": "TypeScript client SDK for talking to the Revlm server replacement for MongoDB Realm.",
6
6
  "keywords": [