@djangocfg/api 2.1.621 → 2.1.622
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/auth.cjs +147 -80
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +6 -1
- package/dist/auth.d.ts +6 -1
- package/dist/auth.mjs +94 -29
- package/dist/auth.mjs.map +1 -1
- package/dist/index.cjs +72 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +72 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/auth/__tests__/sharedContext.test.ts +16 -0
- package/src/auth/__tests__/trace.test.ts +38 -0
- package/src/auth/context/AccountsContext.tsx +3 -2
- package/src/auth/context/AuthContext.tsx +2 -2
- package/src/auth/context/sharedContext.ts +16 -0
- package/src/auth/trace.ts +75 -5
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,10 @@ var KEY = "cfg.auth.trace";
|
|
|
6
6
|
var MAX = 200;
|
|
7
7
|
var MAX_STRING = 120;
|
|
8
8
|
var SENSITIVE = /token|otp|code|email|password|secret|cookie|authorization|key|identifier/i;
|
|
9
|
-
var TAB =
|
|
9
|
+
var TAB = (() => {
|
|
10
|
+
const g = globalThis;
|
|
11
|
+
return g.__cfgAuthTab ??= Math.random().toString(36).slice(2, 6);
|
|
12
|
+
})();
|
|
10
13
|
var hasWindow = typeof window !== "undefined";
|
|
11
14
|
var memory = [];
|
|
12
15
|
var loaded = false;
|
|
@@ -55,10 +58,30 @@ function clean(fields) {
|
|
|
55
58
|
return Object.keys(out).length ? out : void 0;
|
|
56
59
|
}
|
|
57
60
|
__name(clean, "clean");
|
|
61
|
+
function refresh() {
|
|
62
|
+
try {
|
|
63
|
+
const raw = backend()?.getItem(KEY);
|
|
64
|
+
const parsed = raw ? JSON.parse(raw) : null;
|
|
65
|
+
if (Array.isArray(parsed)) memory = parsed.filter((e) => typeof e === "object" && e !== null);
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
__name(refresh, "refresh");
|
|
58
70
|
function record(at, ev, fields) {
|
|
59
|
-
|
|
71
|
+
load();
|
|
72
|
+
refresh();
|
|
73
|
+
const entries = memory;
|
|
60
74
|
const p = hasWindow && typeof performance !== "undefined" ? Math.round(performance.now()) : 0;
|
|
61
|
-
|
|
75
|
+
const f2 = clean(fields);
|
|
76
|
+
const last = entries[entries.length - 1];
|
|
77
|
+
if (last && last.tab === TAB && last.ev === ev && JSON.stringify(last.f) === JSON.stringify(f2)) {
|
|
78
|
+
last.n = (last.n ?? 1) + 1;
|
|
79
|
+
last.t = at;
|
|
80
|
+
last.p = p;
|
|
81
|
+
persist();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
entries.push({ t: at, p, tab: TAB, ev, f: f2 });
|
|
62
85
|
if (entries.length > MAX) entries.splice(0, entries.length - MAX);
|
|
63
86
|
persist();
|
|
64
87
|
}
|
|
@@ -86,7 +109,8 @@ function clearAuthTrace() {
|
|
|
86
109
|
__name(clearAuthTrace, "clearAuthTrace");
|
|
87
110
|
function context() {
|
|
88
111
|
if (!hasWindow) return [];
|
|
89
|
-
const
|
|
112
|
+
const copies = globalThis.__cfgAuthCopies ?? 1;
|
|
113
|
+
const lines = [`url: ${window.location.href.split("?")[0]}`, `copies: ${String(copies)}`, `online: ${navigator.onLine}`, `ua: ${navigator.userAgent}`];
|
|
90
114
|
try {
|
|
91
115
|
const auth2 = globalThis.__cfgAuthNow;
|
|
92
116
|
const now = auth2?.();
|
|
@@ -102,7 +126,7 @@ function dumpAuthTrace() {
|
|
|
102
126
|
const rows = entries.map((e) => {
|
|
103
127
|
const fields = e.f ? ` ${Object.entries(e.f).map(([k2, v]) => `${k2}=${String(v)}`).join(" ")}` : "";
|
|
104
128
|
const at = new Date(e.t).toISOString().slice(11, 23);
|
|
105
|
-
return `${at} +${String(e.t - first).padStart(6)}ms [${e.tab} p${e.p}] ${e.ev}${fields}`;
|
|
129
|
+
return `${at} +${String(e.t - first).padStart(6)}ms [${e.tab} p${e.p}] ${e.ev}${fields}${e.n && e.n > 1 ? ` x${e.n}` : ""}`;
|
|
106
130
|
});
|
|
107
131
|
return [`# cfg auth trace, ${entries.length} events`, ...context(), "", ...rows].join("\n");
|
|
108
132
|
}
|
|
@@ -118,7 +142,21 @@ function installAuthTrace() {
|
|
|
118
142
|
console.log(text);
|
|
119
143
|
return text;
|
|
120
144
|
}, "dump"),
|
|
121
|
-
clear: clearAuthTrace
|
|
145
|
+
clear: clearAuthTrace,
|
|
146
|
+
/** Put the dump on the clipboard (works when the console output is blocked or too long to select). */
|
|
147
|
+
copy: /* @__PURE__ */ __name(() => {
|
|
148
|
+
const text = dumpAuthTrace();
|
|
149
|
+
void navigator.clipboard?.writeText(text);
|
|
150
|
+
return `${text.split("\n").length} lines copied`;
|
|
151
|
+
}, "copy"),
|
|
152
|
+
/** Download the raw trace as a JSON file. */
|
|
153
|
+
download: /* @__PURE__ */ __name(() => {
|
|
154
|
+
const blob = new Blob([JSON.stringify(readAuthTrace(), null, 1)], { type: "application/json" });
|
|
155
|
+
const a = document.createElement("a");
|
|
156
|
+
a.href = URL.createObjectURL(blob);
|
|
157
|
+
a.download = `auth-trace-${Date.now()}.json`;
|
|
158
|
+
a.click();
|
|
159
|
+
}, "download")
|
|
122
160
|
};
|
|
123
161
|
const queued = g.__cfgAuthTraceQ;
|
|
124
162
|
if (Array.isArray(queued)) {
|
|
@@ -134,6 +172,20 @@ function installAuthTrace() {
|
|
|
134
172
|
}
|
|
135
173
|
}
|
|
136
174
|
__name(installAuthTrace, "installAuthTrace");
|
|
175
|
+
function registerCopy() {
|
|
176
|
+
if (!hasWindow) return;
|
|
177
|
+
const g = globalThis;
|
|
178
|
+
const n = (g.__cfgAuthCopies ?? 0) + 1;
|
|
179
|
+
g.__cfgAuthCopies = n;
|
|
180
|
+
if (n > 1) {
|
|
181
|
+
authTrace("dup.copy", { copies: n });
|
|
182
|
+
if (n === 2) {
|
|
183
|
+
console.warn("[@djangocfg/api] more than one copy of the auth package is loaded; see __cfgAuth.dump() (dup.copy). Align the peer set so pnpm installs one instance.");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
__name(registerCopy, "registerCopy");
|
|
188
|
+
registerCopy();
|
|
137
189
|
installAuthTrace();
|
|
138
190
|
|
|
139
191
|
// src/_api/generated/helpers/errors.ts
|
|
@@ -549,10 +601,10 @@ function adoptLegacySession() {
|
|
|
549
601
|
if (_storage.get(ACCESS_KEY) !== null || _storage.get(REFRESH_KEY) !== null) return;
|
|
550
602
|
const legacy = backendFor("localStorage");
|
|
551
603
|
const access = legacy.get(ACCESS_KEY);
|
|
552
|
-
const
|
|
553
|
-
if (access === null &&
|
|
604
|
+
const refresh2 = legacy.get(REFRESH_KEY);
|
|
605
|
+
if (access === null && refresh2 === null) return;
|
|
554
606
|
if (access !== null) _storage.set(ACCESS_KEY, access);
|
|
555
|
-
if (
|
|
607
|
+
if (refresh2 !== null) _storage.set(REFRESH_KEY, refresh2);
|
|
556
608
|
legacy.set(ACCESS_KEY, null);
|
|
557
609
|
legacy.set(REFRESH_KEY, null);
|
|
558
610
|
} catch {
|
|
@@ -637,12 +689,12 @@ function jwtExpMs(token) {
|
|
|
637
689
|
__name(jwtExpMs, "jwtExpMs");
|
|
638
690
|
function computeSnapshot() {
|
|
639
691
|
const access = _storage.get(ACCESS_KEY);
|
|
640
|
-
const
|
|
692
|
+
const refresh2 = _storage.get(REFRESH_KEY);
|
|
641
693
|
const now = Date.now();
|
|
642
694
|
const accessExp = access ? jwtExpMs(access) : null;
|
|
643
695
|
const accessAlive = access !== null && (accessExp === null || accessExp > now);
|
|
644
|
-
const refreshExp =
|
|
645
|
-
const refreshAlive =
|
|
696
|
+
const refreshExp = refresh2 ? jwtExpMs(refresh2) : null;
|
|
697
|
+
const refreshAlive = refresh2 !== null && (refreshExp === null || refreshExp > now);
|
|
646
698
|
return {
|
|
647
699
|
status: accessAlive || refreshAlive ? "authenticated" : "anonymous",
|
|
648
700
|
accessExpiresAt: accessExp
|
|
@@ -665,9 +717,9 @@ function scheduleExpiryFlip() {
|
|
|
665
717
|
const now = Date.now();
|
|
666
718
|
const exps = [];
|
|
667
719
|
const access = _storage.get(ACCESS_KEY);
|
|
668
|
-
const
|
|
720
|
+
const refresh2 = _storage.get(REFRESH_KEY);
|
|
669
721
|
const accessExp = access ? jwtExpMs(access) : null;
|
|
670
|
-
const refreshExp =
|
|
722
|
+
const refreshExp = refresh2 ? jwtExpMs(refresh2) : null;
|
|
671
723
|
if (accessExp !== null && accessExp > now) exps.push(accessExp);
|
|
672
724
|
if (refreshExp !== null && refreshExp > now) exps.push(refreshExp);
|
|
673
725
|
if (!exps.length) return;
|
|
@@ -936,9 +988,9 @@ async function tryRefresh() {
|
|
|
936
988
|
if (_refreshInflight) return _refreshInflight;
|
|
937
989
|
if (!_refreshHandler) return null;
|
|
938
990
|
const runRefresh = /* @__PURE__ */ __name(async () => {
|
|
939
|
-
const
|
|
940
|
-
if (!
|
|
941
|
-
const result = await _refreshHandler(
|
|
991
|
+
const refresh2 = auth.getRefreshToken();
|
|
992
|
+
if (!refresh2) return null;
|
|
993
|
+
const result = await _refreshHandler(refresh2);
|
|
942
994
|
if (!result?.access) {
|
|
943
995
|
trace("refresh", { ok: false, why: "no-access" });
|
|
944
996
|
return null;
|
|
@@ -1139,7 +1191,7 @@ function installAuthOnClient(client2) {
|
|
|
1139
1191
|
}
|
|
1140
1192
|
__name(installAuthOnClient, "installAuthOnClient");
|
|
1141
1193
|
var REFRESH_ENDPOINT = "/cfg/accounts/token/refresh/";
|
|
1142
|
-
auth.setRefreshHandler(async (
|
|
1194
|
+
auth.setRefreshHandler(async (refresh2) => {
|
|
1143
1195
|
try {
|
|
1144
1196
|
const url = `${auth.getBaseUrl()}${REFRESH_ENDPOINT}`;
|
|
1145
1197
|
const headers = { "Content-Type": "application/json" };
|
|
@@ -1151,11 +1203,11 @@ auth.setRefreshHandler(async (refresh) => {
|
|
|
1151
1203
|
method: "POST",
|
|
1152
1204
|
headers,
|
|
1153
1205
|
credentials: auth.getWithCredentials() ? "include" : "same-origin",
|
|
1154
|
-
body: JSON.stringify({ refresh })
|
|
1206
|
+
body: JSON.stringify({ refresh: refresh2 })
|
|
1155
1207
|
});
|
|
1156
1208
|
if (!res.ok) return null;
|
|
1157
1209
|
const data = await res.json();
|
|
1158
|
-
return data?.access ? { access: data.access, refresh: data.refresh ??
|
|
1210
|
+
return data?.access ? { access: data.access, refresh: data.refresh ?? refresh2 } : null;
|
|
1159
1211
|
} catch {
|
|
1160
1212
|
return null;
|
|
1161
1213
|
}
|