@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.mjs CHANGED
@@ -868,8 +868,8 @@ var APIError = class extends Error {
868
868
  var k = /* @__PURE__ */ __name((key, store, personal) => ({ key, store, personal }), "k");
869
869
  var f = /* @__PURE__ */ __name((prefix, store, personal) => ({ prefix, store, personal }), "f");
870
870
  var CFG_KEYS = {
871
- accessToken: k("cfg.auth.access_token", "local", true),
872
- refreshToken: k("cfg.auth.refresh_token", "local", true),
871
+ accessToken: k("cfg.auth.access_token", "cookie", true),
872
+ refreshToken: k("cfg.auth.refresh_token", "cookie", true),
873
873
  apiKey: k("cfg.auth.api_key", "local", true),
874
874
  email: k("cfg.auth.email", "local", false),
875
875
  emailTs: k("cfg.auth.email_ts", "local", false),
@@ -904,6 +904,31 @@ function normalizeSegment(raw) {
904
904
  }
905
905
  __name(normalizeSegment, "normalizeSegment");
906
906
  var hasWindow = /* @__PURE__ */ __name(() => typeof window !== "undefined", "hasWindow");
907
+ var domainByHost = /* @__PURE__ */ new Map();
908
+ function detectCookieDomain() {
909
+ if (!hasWindow() || typeof document === "undefined") return null;
910
+ const host = window.location.hostname.toLowerCase();
911
+ if (!host || !host.includes(".") || host.includes(":") || /^[0-9.]+$/.test(host)) return null;
912
+ const cached = domainByHost.get(host);
913
+ if (cached !== void 0) return cached;
914
+ const labels = host.split(".");
915
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
916
+ let found = null;
917
+ try {
918
+ for (let i = labels.length - 2; i >= 0 && found === null; i -= 1) {
919
+ const candidate = labels.slice(i).join(".");
920
+ const probe = "cfg_probe_" + Math.random().toString(36).slice(2);
921
+ document.cookie = probe + "=1; Domain=" + candidate + "; Path=/; Max-Age=30; SameSite=Lax" + secure;
922
+ if (document.cookie.includes(probe + "=1")) found = candidate;
923
+ document.cookie = probe + "=; Domain=" + candidate + "; Path=/; Max-Age=0; SameSite=Lax" + secure;
924
+ }
925
+ } catch {
926
+ found = null;
927
+ }
928
+ domainByHost.set(host, found);
929
+ return found;
930
+ }
931
+ __name(detectCookieDomain, "detectCookieDomain");
907
932
  function nativeStorage(store) {
908
933
  if (!hasWindow()) return null;
909
934
  try {
@@ -929,6 +954,12 @@ function createStorage(owner, options = {}) {
929
954
  const prefix = `${owner}.`;
930
955
  const pattern = owner === "cfg" ? /^cfg(\.[a-z0-9_]+)+$/ : new RegExp(`^(cfg|${owner})(\\.[a-z0-9_]+)+$`);
931
956
  const cookieMaxAge = options.cookieMaxAgeSeconds ?? 60 * 60 * 24 * 30;
957
+ let cookiePolicy = options.cookieDomain ?? "auto";
958
+ const resolveCookieDomain = /* @__PURE__ */ __name(() => cookiePolicy === false ? null : cookiePolicy === "auto" ? detectCookieDomain() : cookiePolicy, "resolveCookieDomain");
959
+ const expireCookie = /* @__PURE__ */ __name((key, domain) => {
960
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
961
+ document.cookie = encodeURIComponent(key) + "=; Path=/; Max-Age=0; SameSite=Lax" + (domain ? "; Domain=" + domain : "") + secure;
962
+ }, "expireCookie");
932
963
  const specs = Object.values(options.keys ?? {});
933
964
  const families = Object.values(options.families ?? {});
934
965
  const specByKey = /* @__PURE__ */ new Map();
@@ -965,12 +996,15 @@ function createStorage(owner, options = {}) {
965
996
  return memory[store].get(key) ?? null;
966
997
  }
967
998
  __name(rawGet, "rawGet");
968
- function rawSet(store, key, value) {
999
+ function rawSet(store, key, value, maxAgeSeconds) {
969
1000
  if (!hasWindow()) return false;
970
1001
  try {
971
1002
  if (store === "cookie") {
972
1003
  const secure = window.location.protocol === "https:" ? "; Secure" : "";
973
- document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax${secure}`;
1004
+ const domain = resolveCookieDomain();
1005
+ const domainPart = domain ? `; Domain=${domain}` : "";
1006
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; Path=/; Max-Age=${Math.max(1, Math.floor(maxAgeSeconds ?? cookieMaxAge))}; SameSite=Lax${domainPart}${secure}`;
1007
+ if (domain) expireCookie(key, null);
974
1008
  if (rawGet("cookie", key) === value && !memory.cookie.has(key)) return true;
975
1009
  memory.cookie.set(key, value);
976
1010
  return false;
@@ -991,8 +1025,9 @@ function createStorage(owner, options = {}) {
991
1025
  if (!hasWindow()) return;
992
1026
  try {
993
1027
  if (store === "cookie") {
994
- const secure = window.location.protocol === "https:" ? "; Secure" : "";
995
- document.cookie = `${encodeURIComponent(key)}=; Path=/; Max-Age=0; SameSite=Lax${secure}`;
1028
+ expireCookie(key, null);
1029
+ const domain = resolveCookieDomain();
1030
+ if (domain) expireCookie(key, domain);
996
1031
  } else {
997
1032
  nativeStorage(store)?.removeItem(key);
998
1033
  }
@@ -1041,10 +1076,10 @@ function createStorage(owner, options = {}) {
1041
1076
  const target = resolveStore(key, store);
1042
1077
  return rawGet(target, key);
1043
1078
  },
1044
- write(key, value, store) {
1079
+ write(key, value, store, writeOptions) {
1045
1080
  assertOwned(key);
1046
1081
  const target = resolveStore(key, store);
1047
- return rawSet(target, key, value);
1082
+ return rawSet(target, key, value, writeOptions?.maxAgeSeconds);
1048
1083
  },
1049
1084
  remove(key, store) {
1050
1085
  assertOwned(key);
@@ -1082,6 +1117,10 @@ function createStorage(owner, options = {}) {
1082
1117
  for (const name of cookieNames()) if (name.startsWith(prefix)) rawRemove("cookie", name);
1083
1118
  }
1084
1119
  },
1120
+ setCookieDomain(domain) {
1121
+ cookiePolicy = domain;
1122
+ },
1123
+ cookieDomain: resolveCookieDomain,
1085
1124
  onChange(key, listener, store = "local") {
1086
1125
  assertValid(key);
1087
1126
  if (!hasWindow()) return () => {
@@ -1108,6 +1147,11 @@ var REFRESH_KEY = "cfg.auth.refresh_token";
1108
1147
  var API_KEY_KEY = "cfg.auth.api_key";
1109
1148
  var storage = true ? cfgStorage : createStorage2("cfg");
1110
1149
  var isBrowser = typeof window !== "undefined";
1150
+ function secondsUntilExp(token) {
1151
+ const exp = jwtExpMs(token);
1152
+ return exp === null ? void 0 : Math.max(1, Math.floor((exp - Date.now()) / 1e3));
1153
+ }
1154
+ __name(secondsUntilExp, "secondsUntilExp");
1111
1155
  var STORE_OF = {
1112
1156
  localStorage: "local",
1113
1157
  sessionStorage: "session",
@@ -1119,13 +1163,31 @@ function backendFor(mode) {
1119
1163
  get: /* @__PURE__ */ __name((key) => storage.read(key, store), "get"),
1120
1164
  set(key, value) {
1121
1165
  if (value === null) storage.remove(key, store);
1122
- else storage.write(key, value, store);
1166
+ else storage.write(key, value, store, store === "cookie" && key === REFRESH_KEY ? { maxAgeSeconds: secondsUntilExp(value) } : void 0);
1123
1167
  }
1124
1168
  };
1125
1169
  }
1126
1170
  __name(backendFor, "backendFor");
1127
- var _storageMode = "localStorage";
1171
+ var _storageMode = "cookie";
1128
1172
  var _storage = backendFor(_storageMode);
1173
+ var _apiKeyStore = backendFor("localStorage");
1174
+ function adoptLegacySession() {
1175
+ if (!isBrowser || _storageMode !== "cookie") return;
1176
+ try {
1177
+ if (_storage.get(ACCESS_KEY) !== null || _storage.get(REFRESH_KEY) !== null) return;
1178
+ const legacy = backendFor("localStorage");
1179
+ const access = legacy.get(ACCESS_KEY);
1180
+ const refresh = legacy.get(REFRESH_KEY);
1181
+ if (access === null && refresh === null) return;
1182
+ if (access !== null) _storage.set(ACCESS_KEY, access);
1183
+ if (refresh !== null) _storage.set(REFRESH_KEY, refresh);
1184
+ legacy.set(ACCESS_KEY, null);
1185
+ legacy.set(REFRESH_KEY, null);
1186
+ } catch {
1187
+ }
1188
+ }
1189
+ __name(adoptLegacySession, "adoptLegacySession");
1190
+ adoptLegacySession();
1129
1191
  function detectLocale() {
1130
1192
  try {
1131
1193
  if (typeof document === "undefined") return null;
@@ -1270,6 +1332,14 @@ function ensureStorageSync() {
1270
1332
  }
1271
1333
  });
1272
1334
  window.addEventListener(SESSION_SYNC_EVENT, () => notifySessionChanged());
1335
+ window.addEventListener("focus", () => notifySessionChanged());
1336
+ document.addEventListener("visibilitychange", () => {
1337
+ if (document.visibilityState === "visible") notifySessionChanged();
1338
+ });
1339
+ try {
1340
+ window.cookieStore?.addEventListener("change", () => notifySessionChanged());
1341
+ } catch {
1342
+ }
1273
1343
  }
1274
1344
  __name(ensureStorageSync, "ensureStorageSync");
1275
1345
  var SESSION_EXPIRED_REGISTRY = `cfg-auth:expired-handlers:${ACCESS_KEY}`;
@@ -1303,6 +1373,17 @@ var auth = {
1303
1373
  _storage = backendFor(mode);
1304
1374
  notifySessionChanged();
1305
1375
  },
1376
+ // ── Shared cookie domain ──────────────────────────────────────────
1377
+ /** `'auto'` (default): the registrable domain of the page. A domain forces it; `null` keeps
1378
+ * cookies host-only (no sign-in sharing between subdomains). Call before sign-in. */
1379
+ setCookieDomain(domain) {
1380
+ storage.setCookieDomain(domain === null ? false : domain);
1381
+ notifySessionChanged();
1382
+ },
1383
+ /** The `Domain` the session cookie is written with; `null` = host-only. */
1384
+ getCookieDomain() {
1385
+ return storage.cookieDomain();
1386
+ },
1306
1387
  // ── Bearer token ──────────────────────────────────────────────────
1307
1388
  getToken() {
1308
1389
  return _storage.get(ACCESS_KEY);
@@ -1389,18 +1470,18 @@ var auth = {
1389
1470
  },
1390
1471
  // ── API key ───────────────────────────────────────────────────────
1391
1472
  getApiKey() {
1392
- return _apiKeyOverride ?? _storage.get(API_KEY_KEY) ?? defaultApiKey();
1473
+ return _apiKeyOverride ?? _apiKeyStore.get(API_KEY_KEY) ?? defaultApiKey();
1393
1474
  },
1394
1475
  setApiKey(key) {
1395
1476
  _apiKeyOverride = key;
1396
1477
  },
1397
1478
  setApiKeyPersist(key) {
1398
1479
  _apiKeyOverride = key;
1399
- _storage.set(API_KEY_KEY, key);
1480
+ _apiKeyStore.set(API_KEY_KEY, key);
1400
1481
  },
1401
1482
  clearApiKey() {
1402
1483
  _apiKeyOverride = null;
1403
- _storage.set(API_KEY_KEY, null);
1484
+ _apiKeyStore.set(API_KEY_KEY, null);
1404
1485
  },
1405
1486
  // ── Locale ────────────────────────────────────────────────────────
1406
1487
  getLocale() {