@djangocfg/api 2.1.603 → 2.1.605

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.cjs CHANGED
@@ -145,8 +145,8 @@ var NetworkError = class extends Error {
145
145
  var k = /* @__PURE__ */ __name((key, store, personal) => ({ key, store, personal }), "k");
146
146
  var f = /* @__PURE__ */ __name((prefix, store, personal) => ({ prefix, store, personal }), "f");
147
147
  var CFG_KEYS = {
148
- accessToken: k("cfg.auth.access_token", "local", true),
149
- refreshToken: k("cfg.auth.refresh_token", "local", true),
148
+ accessToken: k("cfg.auth.access_token", "cookie", true),
149
+ refreshToken: k("cfg.auth.refresh_token", "cookie", true),
150
150
  apiKey: k("cfg.auth.api_key", "local", true),
151
151
  email: k("cfg.auth.email", "local", false),
152
152
  emailTs: k("cfg.auth.email_ts", "local", false),
@@ -181,6 +181,31 @@ function normalizeSegment(raw) {
181
181
  }
182
182
  __name(normalizeSegment, "normalizeSegment");
183
183
  var hasWindow = /* @__PURE__ */ __name(() => typeof window !== "undefined", "hasWindow");
184
+ var domainByHost = /* @__PURE__ */ new Map();
185
+ function detectCookieDomain() {
186
+ if (!hasWindow() || typeof document === "undefined") return null;
187
+ const host = window.location.hostname.toLowerCase();
188
+ if (!host || !host.includes(".") || host.includes(":") || /^[0-9.]+$/.test(host)) return null;
189
+ const cached = domainByHost.get(host);
190
+ if (cached !== void 0) return cached;
191
+ const labels = host.split(".");
192
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
193
+ let found = null;
194
+ try {
195
+ for (let i = labels.length - 2; i >= 0 && found === null; i -= 1) {
196
+ const candidate = labels.slice(i).join(".");
197
+ const probe = "cfg_probe_" + Math.random().toString(36).slice(2);
198
+ document.cookie = probe + "=1; Domain=" + candidate + "; Path=/; Max-Age=30; SameSite=Lax" + secure;
199
+ if (document.cookie.includes(probe + "=1")) found = candidate;
200
+ document.cookie = probe + "=; Domain=" + candidate + "; Path=/; Max-Age=0; SameSite=Lax" + secure;
201
+ }
202
+ } catch {
203
+ found = null;
204
+ }
205
+ domainByHost.set(host, found);
206
+ return found;
207
+ }
208
+ __name(detectCookieDomain, "detectCookieDomain");
184
209
  function nativeStorage(store) {
185
210
  if (!hasWindow()) return null;
186
211
  try {
@@ -206,6 +231,12 @@ function createStorage(owner, options = {}) {
206
231
  const prefix = `${owner}.`;
207
232
  const pattern = owner === "cfg" ? /^cfg(\.[a-z0-9_]+)+$/ : new RegExp(`^(cfg|${owner})(\\.[a-z0-9_]+)+$`);
208
233
  const cookieMaxAge = options.cookieMaxAgeSeconds ?? 60 * 60 * 24 * 30;
234
+ let cookiePolicy = options.cookieDomain ?? "auto";
235
+ const resolveCookieDomain = /* @__PURE__ */ __name(() => cookiePolicy === false ? null : cookiePolicy === "auto" ? detectCookieDomain() : cookiePolicy, "resolveCookieDomain");
236
+ const expireCookie = /* @__PURE__ */ __name((key, domain) => {
237
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
238
+ document.cookie = encodeURIComponent(key) + "=; Path=/; Max-Age=0; SameSite=Lax" + (domain ? "; Domain=" + domain : "") + secure;
239
+ }, "expireCookie");
209
240
  const specs = Object.values(options.keys ?? {});
210
241
  const families = Object.values(options.families ?? {});
211
242
  const specByKey = /* @__PURE__ */ new Map();
@@ -242,12 +273,15 @@ function createStorage(owner, options = {}) {
242
273
  return memory[store].get(key) ?? null;
243
274
  }
244
275
  __name(rawGet, "rawGet");
245
- function rawSet(store, key, value) {
276
+ function rawSet(store, key, value, maxAgeSeconds) {
246
277
  if (!hasWindow()) return false;
247
278
  try {
248
279
  if (store === "cookie") {
249
280
  const secure = window.location.protocol === "https:" ? "; Secure" : "";
250
- document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax${secure}`;
281
+ const domain = resolveCookieDomain();
282
+ const domainPart = domain ? `; Domain=${domain}` : "";
283
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; Path=/; Max-Age=${Math.max(1, Math.floor(maxAgeSeconds ?? cookieMaxAge))}; SameSite=Lax${domainPart}${secure}`;
284
+ if (domain) expireCookie(key, null);
251
285
  if (rawGet("cookie", key) === value && !memory.cookie.has(key)) return true;
252
286
  memory.cookie.set(key, value);
253
287
  return false;
@@ -268,8 +302,9 @@ function createStorage(owner, options = {}) {
268
302
  if (!hasWindow()) return;
269
303
  try {
270
304
  if (store === "cookie") {
271
- const secure = window.location.protocol === "https:" ? "; Secure" : "";
272
- document.cookie = `${encodeURIComponent(key)}=; Path=/; Max-Age=0; SameSite=Lax${secure}`;
305
+ expireCookie(key, null);
306
+ const domain = resolveCookieDomain();
307
+ if (domain) expireCookie(key, domain);
273
308
  } else {
274
309
  nativeStorage(store)?.removeItem(key);
275
310
  }
@@ -318,10 +353,10 @@ function createStorage(owner, options = {}) {
318
353
  const target = resolveStore(key, store);
319
354
  return rawGet(target, key);
320
355
  },
321
- write(key, value, store) {
356
+ write(key, value, store, writeOptions) {
322
357
  assertOwned(key);
323
358
  const target = resolveStore(key, store);
324
- return rawSet(target, key, value);
359
+ return rawSet(target, key, value, writeOptions?.maxAgeSeconds);
325
360
  },
326
361
  remove(key, store) {
327
362
  assertOwned(key);
@@ -359,6 +394,10 @@ function createStorage(owner, options = {}) {
359
394
  for (const name of cookieNames()) if (name.startsWith(prefix)) rawRemove("cookie", name);
360
395
  }
361
396
  },
397
+ setCookieDomain(domain) {
398
+ cookiePolicy = domain;
399
+ },
400
+ cookieDomain: resolveCookieDomain,
362
401
  onChange(key, listener, store = "local") {
363
402
  assertValid(key);
364
403
  if (!hasWindow()) return () => {
@@ -385,6 +424,11 @@ var REFRESH_KEY = "cfg.auth.refresh_token";
385
424
  var API_KEY_KEY = "cfg.auth.api_key";
386
425
  var storage = true ? cfgStorage : createStorage2("cfg");
387
426
  var isBrowser = typeof window !== "undefined";
427
+ function secondsUntilExp(token) {
428
+ const exp = jwtExpMs(token);
429
+ return exp === null ? void 0 : Math.max(1, Math.floor((exp - Date.now()) / 1e3));
430
+ }
431
+ __name(secondsUntilExp, "secondsUntilExp");
388
432
  var STORE_OF = {
389
433
  localStorage: "local",
390
434
  sessionStorage: "session",
@@ -396,13 +440,31 @@ function backendFor(mode) {
396
440
  get: /* @__PURE__ */ __name((key) => storage.read(key, store), "get"),
397
441
  set(key, value) {
398
442
  if (value === null) storage.remove(key, store);
399
- else storage.write(key, value, store);
443
+ else storage.write(key, value, store, store === "cookie" && key === REFRESH_KEY ? { maxAgeSeconds: secondsUntilExp(value) } : void 0);
400
444
  }
401
445
  };
402
446
  }
403
447
  __name(backendFor, "backendFor");
404
- var _storageMode = "localStorage";
448
+ var _storageMode = "cookie";
405
449
  var _storage = backendFor(_storageMode);
450
+ var _apiKeyStore = backendFor("localStorage");
451
+ function adoptLegacySession() {
452
+ if (!isBrowser || _storageMode !== "cookie") return;
453
+ try {
454
+ if (_storage.get(ACCESS_KEY) !== null || _storage.get(REFRESH_KEY) !== null) return;
455
+ const legacy = backendFor("localStorage");
456
+ const access = legacy.get(ACCESS_KEY);
457
+ const refresh = legacy.get(REFRESH_KEY);
458
+ if (access === null && refresh === null) return;
459
+ if (access !== null) _storage.set(ACCESS_KEY, access);
460
+ if (refresh !== null) _storage.set(REFRESH_KEY, refresh);
461
+ legacy.set(ACCESS_KEY, null);
462
+ legacy.set(REFRESH_KEY, null);
463
+ } catch {
464
+ }
465
+ }
466
+ __name(adoptLegacySession, "adoptLegacySession");
467
+ adoptLegacySession();
406
468
  function detectLocale() {
407
469
  try {
408
470
  if (typeof document === "undefined") return null;
@@ -547,6 +609,14 @@ function ensureStorageSync() {
547
609
  }
548
610
  });
549
611
  window.addEventListener(SESSION_SYNC_EVENT, () => notifySessionChanged());
612
+ window.addEventListener("focus", () => notifySessionChanged());
613
+ document.addEventListener("visibilitychange", () => {
614
+ if (document.visibilityState === "visible") notifySessionChanged();
615
+ });
616
+ try {
617
+ window.cookieStore?.addEventListener("change", () => notifySessionChanged());
618
+ } catch {
619
+ }
550
620
  }
551
621
  __name(ensureStorageSync, "ensureStorageSync");
552
622
  var SESSION_EXPIRED_REGISTRY = `cfg-auth:expired-handlers:${ACCESS_KEY}`;
@@ -580,6 +650,17 @@ var auth = {
580
650
  _storage = backendFor(mode);
581
651
  notifySessionChanged();
582
652
  },
653
+ // ── Shared cookie domain ──────────────────────────────────────────
654
+ /** `'auto'` (default): the registrable domain of the page. A domain forces it; `null` keeps
655
+ * cookies host-only (no sign-in sharing between subdomains). Call before sign-in. */
656
+ setCookieDomain(domain) {
657
+ storage.setCookieDomain(domain === null ? false : domain);
658
+ notifySessionChanged();
659
+ },
660
+ /** The `Domain` the session cookie is written with; `null` = host-only. */
661
+ getCookieDomain() {
662
+ return storage.cookieDomain();
663
+ },
583
664
  // ── Bearer token ──────────────────────────────────────────────────
584
665
  getToken() {
585
666
  return _storage.get(ACCESS_KEY);
@@ -666,18 +747,18 @@ var auth = {
666
747
  },
667
748
  // ── API key ───────────────────────────────────────────────────────
668
749
  getApiKey() {
669
- return _apiKeyOverride ?? _storage.get(API_KEY_KEY) ?? defaultApiKey();
750
+ return _apiKeyOverride ?? _apiKeyStore.get(API_KEY_KEY) ?? defaultApiKey();
670
751
  },
671
752
  setApiKey(key) {
672
753
  _apiKeyOverride = key;
673
754
  },
674
755
  setApiKeyPersist(key) {
675
756
  _apiKeyOverride = key;
676
- _storage.set(API_KEY_KEY, key);
757
+ _apiKeyStore.set(API_KEY_KEY, key);
677
758
  },
678
759
  clearApiKey() {
679
760
  _apiKeyOverride = null;
680
- _storage.set(API_KEY_KEY, null);
761
+ _apiKeyStore.set(API_KEY_KEY, null);
681
762
  },
682
763
  // ── Locale ────────────────────────────────────────────────────────
683
764
  getLocale() {