@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/hooks.cjs CHANGED
@@ -1003,8 +1003,8 @@ var APIError = class extends Error {
1003
1003
  var k = /* @__PURE__ */ __name((key, store, personal) => ({ key, store, personal }), "k");
1004
1004
  var f = /* @__PURE__ */ __name((prefix, store, personal) => ({ prefix, store, personal }), "f");
1005
1005
  var CFG_KEYS = {
1006
- accessToken: k("cfg.auth.access_token", "local", true),
1007
- refreshToken: k("cfg.auth.refresh_token", "local", true),
1006
+ accessToken: k("cfg.auth.access_token", "cookie", true),
1007
+ refreshToken: k("cfg.auth.refresh_token", "cookie", true),
1008
1008
  apiKey: k("cfg.auth.api_key", "local", true),
1009
1009
  email: k("cfg.auth.email", "local", false),
1010
1010
  emailTs: k("cfg.auth.email_ts", "local", false),
@@ -1039,6 +1039,31 @@ function normalizeSegment(raw) {
1039
1039
  }
1040
1040
  __name(normalizeSegment, "normalizeSegment");
1041
1041
  var hasWindow = /* @__PURE__ */ __name(() => typeof window !== "undefined", "hasWindow");
1042
+ var domainByHost = /* @__PURE__ */ new Map();
1043
+ function detectCookieDomain() {
1044
+ if (!hasWindow() || typeof document === "undefined") return null;
1045
+ const host = window.location.hostname.toLowerCase();
1046
+ if (!host || !host.includes(".") || host.includes(":") || /^[0-9.]+$/.test(host)) return null;
1047
+ const cached = domainByHost.get(host);
1048
+ if (cached !== void 0) return cached;
1049
+ const labels = host.split(".");
1050
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
1051
+ let found = null;
1052
+ try {
1053
+ for (let i = labels.length - 2; i >= 0 && found === null; i -= 1) {
1054
+ const candidate = labels.slice(i).join(".");
1055
+ const probe = "cfg_probe_" + Math.random().toString(36).slice(2);
1056
+ document.cookie = probe + "=1; Domain=" + candidate + "; Path=/; Max-Age=30; SameSite=Lax" + secure;
1057
+ if (document.cookie.includes(probe + "=1")) found = candidate;
1058
+ document.cookie = probe + "=; Domain=" + candidate + "; Path=/; Max-Age=0; SameSite=Lax" + secure;
1059
+ }
1060
+ } catch {
1061
+ found = null;
1062
+ }
1063
+ domainByHost.set(host, found);
1064
+ return found;
1065
+ }
1066
+ __name(detectCookieDomain, "detectCookieDomain");
1042
1067
  function nativeStorage(store) {
1043
1068
  if (!hasWindow()) return null;
1044
1069
  try {
@@ -1064,6 +1089,12 @@ function createStorage(owner, options = {}) {
1064
1089
  const prefix = `${owner}.`;
1065
1090
  const pattern = owner === "cfg" ? /^cfg(\.[a-z0-9_]+)+$/ : new RegExp(`^(cfg|${owner})(\\.[a-z0-9_]+)+$`);
1066
1091
  const cookieMaxAge = options.cookieMaxAgeSeconds ?? 60 * 60 * 24 * 30;
1092
+ let cookiePolicy = options.cookieDomain ?? "auto";
1093
+ const resolveCookieDomain = /* @__PURE__ */ __name(() => cookiePolicy === false ? null : cookiePolicy === "auto" ? detectCookieDomain() : cookiePolicy, "resolveCookieDomain");
1094
+ const expireCookie = /* @__PURE__ */ __name((key, domain) => {
1095
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
1096
+ document.cookie = encodeURIComponent(key) + "=; Path=/; Max-Age=0; SameSite=Lax" + (domain ? "; Domain=" + domain : "") + secure;
1097
+ }, "expireCookie");
1067
1098
  const specs = Object.values(options.keys ?? {});
1068
1099
  const families = Object.values(options.families ?? {});
1069
1100
  const specByKey = /* @__PURE__ */ new Map();
@@ -1100,12 +1131,15 @@ function createStorage(owner, options = {}) {
1100
1131
  return memory[store].get(key) ?? null;
1101
1132
  }
1102
1133
  __name(rawGet, "rawGet");
1103
- function rawSet(store, key, value) {
1134
+ function rawSet(store, key, value, maxAgeSeconds) {
1104
1135
  if (!hasWindow()) return false;
1105
1136
  try {
1106
1137
  if (store === "cookie") {
1107
1138
  const secure = window.location.protocol === "https:" ? "; Secure" : "";
1108
- document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax${secure}`;
1139
+ const domain = resolveCookieDomain();
1140
+ const domainPart = domain ? `; Domain=${domain}` : "";
1141
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; Path=/; Max-Age=${Math.max(1, Math.floor(maxAgeSeconds ?? cookieMaxAge))}; SameSite=Lax${domainPart}${secure}`;
1142
+ if (domain) expireCookie(key, null);
1109
1143
  if (rawGet("cookie", key) === value && !memory.cookie.has(key)) return true;
1110
1144
  memory.cookie.set(key, value);
1111
1145
  return false;
@@ -1126,8 +1160,9 @@ function createStorage(owner, options = {}) {
1126
1160
  if (!hasWindow()) return;
1127
1161
  try {
1128
1162
  if (store === "cookie") {
1129
- const secure = window.location.protocol === "https:" ? "; Secure" : "";
1130
- document.cookie = `${encodeURIComponent(key)}=; Path=/; Max-Age=0; SameSite=Lax${secure}`;
1163
+ expireCookie(key, null);
1164
+ const domain = resolveCookieDomain();
1165
+ if (domain) expireCookie(key, domain);
1131
1166
  } else {
1132
1167
  nativeStorage(store)?.removeItem(key);
1133
1168
  }
@@ -1176,10 +1211,10 @@ function createStorage(owner, options = {}) {
1176
1211
  const target = resolveStore(key, store);
1177
1212
  return rawGet(target, key);
1178
1213
  },
1179
- write(key, value, store) {
1214
+ write(key, value, store, writeOptions) {
1180
1215
  assertOwned(key);
1181
1216
  const target = resolveStore(key, store);
1182
- return rawSet(target, key, value);
1217
+ return rawSet(target, key, value, writeOptions?.maxAgeSeconds);
1183
1218
  },
1184
1219
  remove(key, store) {
1185
1220
  assertOwned(key);
@@ -1217,6 +1252,10 @@ function createStorage(owner, options = {}) {
1217
1252
  for (const name of cookieNames()) if (name.startsWith(prefix)) rawRemove("cookie", name);
1218
1253
  }
1219
1254
  },
1255
+ setCookieDomain(domain) {
1256
+ cookiePolicy = domain;
1257
+ },
1258
+ cookieDomain: resolveCookieDomain,
1220
1259
  onChange(key, listener, store = "local") {
1221
1260
  assertValid(key);
1222
1261
  if (!hasWindow()) return () => {
@@ -1243,6 +1282,11 @@ var REFRESH_KEY = "cfg.auth.refresh_token";
1243
1282
  var API_KEY_KEY = "cfg.auth.api_key";
1244
1283
  var storage = true ? cfgStorage : createStorage2("cfg");
1245
1284
  var isBrowser = typeof window !== "undefined";
1285
+ function secondsUntilExp(token) {
1286
+ const exp = jwtExpMs(token);
1287
+ return exp === null ? void 0 : Math.max(1, Math.floor((exp - Date.now()) / 1e3));
1288
+ }
1289
+ __name(secondsUntilExp, "secondsUntilExp");
1246
1290
  var STORE_OF = {
1247
1291
  localStorage: "local",
1248
1292
  sessionStorage: "session",
@@ -1254,13 +1298,31 @@ function backendFor(mode) {
1254
1298
  get: /* @__PURE__ */ __name((key) => storage.read(key, store), "get"),
1255
1299
  set(key, value) {
1256
1300
  if (value === null) storage.remove(key, store);
1257
- else storage.write(key, value, store);
1301
+ else storage.write(key, value, store, store === "cookie" && key === REFRESH_KEY ? { maxAgeSeconds: secondsUntilExp(value) } : void 0);
1258
1302
  }
1259
1303
  };
1260
1304
  }
1261
1305
  __name(backendFor, "backendFor");
1262
- var _storageMode = "localStorage";
1306
+ var _storageMode = "cookie";
1263
1307
  var _storage = backendFor(_storageMode);
1308
+ var _apiKeyStore = backendFor("localStorage");
1309
+ function adoptLegacySession() {
1310
+ if (!isBrowser || _storageMode !== "cookie") return;
1311
+ try {
1312
+ if (_storage.get(ACCESS_KEY) !== null || _storage.get(REFRESH_KEY) !== null) return;
1313
+ const legacy = backendFor("localStorage");
1314
+ const access = legacy.get(ACCESS_KEY);
1315
+ const refresh = legacy.get(REFRESH_KEY);
1316
+ if (access === null && refresh === null) return;
1317
+ if (access !== null) _storage.set(ACCESS_KEY, access);
1318
+ if (refresh !== null) _storage.set(REFRESH_KEY, refresh);
1319
+ legacy.set(ACCESS_KEY, null);
1320
+ legacy.set(REFRESH_KEY, null);
1321
+ } catch {
1322
+ }
1323
+ }
1324
+ __name(adoptLegacySession, "adoptLegacySession");
1325
+ adoptLegacySession();
1264
1326
  function detectLocale() {
1265
1327
  try {
1266
1328
  if (typeof document === "undefined") return null;
@@ -1405,6 +1467,14 @@ function ensureStorageSync() {
1405
1467
  }
1406
1468
  });
1407
1469
  window.addEventListener(SESSION_SYNC_EVENT, () => notifySessionChanged());
1470
+ window.addEventListener("focus", () => notifySessionChanged());
1471
+ document.addEventListener("visibilitychange", () => {
1472
+ if (document.visibilityState === "visible") notifySessionChanged();
1473
+ });
1474
+ try {
1475
+ window.cookieStore?.addEventListener("change", () => notifySessionChanged());
1476
+ } catch {
1477
+ }
1408
1478
  }
1409
1479
  __name(ensureStorageSync, "ensureStorageSync");
1410
1480
  var SESSION_EXPIRED_REGISTRY = `cfg-auth:expired-handlers:${ACCESS_KEY}`;
@@ -1438,6 +1508,17 @@ var auth = {
1438
1508
  _storage = backendFor(mode);
1439
1509
  notifySessionChanged();
1440
1510
  },
1511
+ // ── Shared cookie domain ──────────────────────────────────────────
1512
+ /** `'auto'` (default): the registrable domain of the page. A domain forces it; `null` keeps
1513
+ * cookies host-only (no sign-in sharing between subdomains). Call before sign-in. */
1514
+ setCookieDomain(domain) {
1515
+ storage.setCookieDomain(domain === null ? false : domain);
1516
+ notifySessionChanged();
1517
+ },
1518
+ /** The `Domain` the session cookie is written with; `null` = host-only. */
1519
+ getCookieDomain() {
1520
+ return storage.cookieDomain();
1521
+ },
1441
1522
  // ── Bearer token ──────────────────────────────────────────────────
1442
1523
  getToken() {
1443
1524
  return _storage.get(ACCESS_KEY);
@@ -1524,18 +1605,18 @@ var auth = {
1524
1605
  },
1525
1606
  // ── API key ───────────────────────────────────────────────────────
1526
1607
  getApiKey() {
1527
- return _apiKeyOverride ?? _storage.get(API_KEY_KEY) ?? defaultApiKey();
1608
+ return _apiKeyOverride ?? _apiKeyStore.get(API_KEY_KEY) ?? defaultApiKey();
1528
1609
  },
1529
1610
  setApiKey(key) {
1530
1611
  _apiKeyOverride = key;
1531
1612
  },
1532
1613
  setApiKeyPersist(key) {
1533
1614
  _apiKeyOverride = key;
1534
- _storage.set(API_KEY_KEY, key);
1615
+ _apiKeyStore.set(API_KEY_KEY, key);
1535
1616
  },
1536
1617
  clearApiKey() {
1537
1618
  _apiKeyOverride = null;
1538
- _storage.set(API_KEY_KEY, null);
1619
+ _apiKeyStore.set(API_KEY_KEY, null);
1539
1620
  },
1540
1621
  // ── Locale ────────────────────────────────────────────────────────
1541
1622
  getLocale() {