@djangocfg/monitor 2.1.427 → 2.1.429
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/README.md +9 -0
- package/dist/client.cjs +103 -2
- package/dist/client.cjs.map +1 -1
- package/dist/client.mjs +103 -2
- package/dist/client.mjs.map +1 -1
- package/dist/index.cjs +102 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +102 -1
- package/dist/index.mjs.map +1 -1
- package/dist/server.cjs +102 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.mjs +102 -1
- package/dist/server.mjs.map +1 -1
- package/package.json +2 -2
- package/src/_api/generated/client/index.ts +1 -0
- package/src/_api/generated/client/utils.gen.ts +2 -2
- package/src/_api/generated/client.gen.ts +2 -2
- package/src/_api/generated/core/auth.gen.ts +7 -0
- package/src/_api/generated/core/params.gen.ts +10 -8
- package/src/_api/generated/core/pathSerializer.gen.ts +6 -6
- package/src/_api/generated/core/queryKeySerializer.gen.ts +1 -1
- package/src/_api/generated/core/utils.gen.ts +4 -4
- package/src/_api/generated/helpers/auth.ts +127 -1
- package/src/_api/generated/sdk.gen.ts +2 -2
package/README.md
CHANGED
|
@@ -171,6 +171,15 @@ pnpm add @djangocfg/debuger
|
|
|
171
171
|
|
|
172
172
|
Events captured by monitor (JS errors, console, network) appear in the panel as `monitor:JS_ERROR`, `monitor:NETWORK_ERROR`, etc.
|
|
173
173
|
|
|
174
|
+
## Relationship to console log level
|
|
175
|
+
|
|
176
|
+
`@djangocfg/*` packages share a runtime console verbosity controlled by
|
|
177
|
+
`applyRoleLogPolicy` / `setLogLevel` from `@djangocfg/api` — quiet for regular
|
|
178
|
+
users in production, verbose for admins/devs. **Monitor capture is independent of
|
|
179
|
+
that level**: errors (and configured console events) are still captured and sent
|
|
180
|
+
to the backend / debug panel even when the browser console is silenced. So
|
|
181
|
+
production incidents stay diagnosable without spamming end-user consoles.
|
|
182
|
+
|
|
174
183
|
## Safety
|
|
175
184
|
|
|
176
185
|
Transport errors are **always swallowed** — monitor never crashes your app and never sends its own errors to itself. If the backend is unreachable, events are silently dropped.
|
package/dist/client.cjs
CHANGED
|
@@ -391,6 +391,99 @@ async function tryRefresh() {
|
|
|
391
391
|
return _refreshInflight;
|
|
392
392
|
}
|
|
393
393
|
__name(tryRefresh, "tryRefresh");
|
|
394
|
+
function dpopEnabled() {
|
|
395
|
+
try {
|
|
396
|
+
return typeof process !== "undefined" && process.env?.NEXT_PUBLIC_DPOP_ENABLED === "true";
|
|
397
|
+
} catch {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
__name(dpopEnabled, "dpopEnabled");
|
|
402
|
+
var _DPOP_DB = "cfg-auth";
|
|
403
|
+
var _DPOP_STORE = "keys";
|
|
404
|
+
var _DPOP_KEY_ID = "dpop-ec-p256";
|
|
405
|
+
function _idbOpen() {
|
|
406
|
+
return new Promise((resolve, reject) => {
|
|
407
|
+
const req = indexedDB.open(_DPOP_DB, 1);
|
|
408
|
+
req.onupgradeneeded = () => req.result.createObjectStore(_DPOP_STORE);
|
|
409
|
+
req.onsuccess = () => resolve(req.result);
|
|
410
|
+
req.onerror = () => reject(req.error);
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
__name(_idbOpen, "_idbOpen");
|
|
414
|
+
function _idbGet(key) {
|
|
415
|
+
return _idbOpen().then((db) => new Promise((resolve, reject) => {
|
|
416
|
+
const tx = db.transaction(_DPOP_STORE, "readonly");
|
|
417
|
+
const req = tx.objectStore(_DPOP_STORE).get(key);
|
|
418
|
+
req.onsuccess = () => resolve(req.result);
|
|
419
|
+
req.onerror = () => reject(req.error);
|
|
420
|
+
}));
|
|
421
|
+
}
|
|
422
|
+
__name(_idbGet, "_idbGet");
|
|
423
|
+
function _idbPut(key, value) {
|
|
424
|
+
return _idbOpen().then((db) => new Promise((resolve, reject) => {
|
|
425
|
+
const tx = db.transaction(_DPOP_STORE, "readwrite");
|
|
426
|
+
tx.objectStore(_DPOP_STORE).put(value, key);
|
|
427
|
+
tx.oncomplete = () => resolve();
|
|
428
|
+
tx.onerror = () => reject(tx.error);
|
|
429
|
+
}));
|
|
430
|
+
}
|
|
431
|
+
__name(_idbPut, "_idbPut");
|
|
432
|
+
var _dpopKeyPromise = null;
|
|
433
|
+
function _getDpopKeyPair() {
|
|
434
|
+
if (_dpopKeyPromise) return _dpopKeyPromise;
|
|
435
|
+
_dpopKeyPromise = (async () => {
|
|
436
|
+
const existing = await _idbGet(_DPOP_KEY_ID).catch(() => void 0);
|
|
437
|
+
if (existing) return existing;
|
|
438
|
+
const pair = await crypto.subtle.generateKey(
|
|
439
|
+
{ name: "ECDSA", namedCurve: "P-256" },
|
|
440
|
+
false,
|
|
441
|
+
// extractable:false — JS can sign but never export the private key
|
|
442
|
+
["sign"]
|
|
443
|
+
);
|
|
444
|
+
await _idbPut(_DPOP_KEY_ID, pair).catch(() => {
|
|
445
|
+
});
|
|
446
|
+
return pair;
|
|
447
|
+
})();
|
|
448
|
+
return _dpopKeyPromise;
|
|
449
|
+
}
|
|
450
|
+
__name(_getDpopKeyPair, "_getDpopKeyPair");
|
|
451
|
+
function _b64urlFromBytes(bytes) {
|
|
452
|
+
const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
453
|
+
let s = "";
|
|
454
|
+
for (let i = 0; i < arr.length; i++) s += String.fromCharCode(arr[i]);
|
|
455
|
+
return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
456
|
+
}
|
|
457
|
+
__name(_b64urlFromBytes, "_b64urlFromBytes");
|
|
458
|
+
function _b64urlFromString(str) {
|
|
459
|
+
return _b64urlFromBytes(new TextEncoder().encode(str));
|
|
460
|
+
}
|
|
461
|
+
__name(_b64urlFromString, "_b64urlFromString");
|
|
462
|
+
async function _publicJwk(pub) {
|
|
463
|
+
const jwk = await crypto.subtle.exportKey("jwk", pub);
|
|
464
|
+
return { kty: "EC", crv: "P-256", x: jwk.x, y: jwk.y };
|
|
465
|
+
}
|
|
466
|
+
__name(_publicJwk, "_publicJwk");
|
|
467
|
+
async function _makeDpopProof(method, url) {
|
|
468
|
+
try {
|
|
469
|
+
const pair = await _getDpopKeyPair();
|
|
470
|
+
const jwk = await _publicJwk(pair.publicKey);
|
|
471
|
+
const header = { typ: "dpop+jwt", alg: "ES256", jwk };
|
|
472
|
+
const htu = url.split("#")[0].split("?")[0];
|
|
473
|
+
const jti = crypto.randomUUID && crypto.randomUUID() || _b64urlFromBytes(crypto.getRandomValues(new Uint8Array(16)));
|
|
474
|
+
const payload = { htm: method.toUpperCase(), htu, iat: Math.floor(Date.now() / 1e3), jti };
|
|
475
|
+
const signingInput = `${_b64urlFromString(JSON.stringify(header))}.${_b64urlFromString(JSON.stringify(payload))}`;
|
|
476
|
+
const sig = await crypto.subtle.sign(
|
|
477
|
+
{ name: "ECDSA", hash: "SHA-256" },
|
|
478
|
+
pair.privateKey,
|
|
479
|
+
new TextEncoder().encode(signingInput)
|
|
480
|
+
);
|
|
481
|
+
return `${signingInput}.${_b64urlFromBytes(sig)}`;
|
|
482
|
+
} catch {
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
__name(_makeDpopProof, "_makeDpopProof");
|
|
394
487
|
function installAuthOnClient(client2) {
|
|
395
488
|
if (_client) return;
|
|
396
489
|
_client = client2;
|
|
@@ -398,7 +491,7 @@ function installAuthOnClient(client2) {
|
|
|
398
491
|
baseUrl: auth.getBaseUrl(),
|
|
399
492
|
credentials: _withCredentials ? "include" : "same-origin"
|
|
400
493
|
});
|
|
401
|
-
client2.interceptors.request.use((request) => {
|
|
494
|
+
client2.interceptors.request.use(async (request) => {
|
|
402
495
|
const token = auth.getToken();
|
|
403
496
|
if (token) request.headers.set("Authorization", `Bearer ${token}`);
|
|
404
497
|
const locale = auth.getLocale();
|
|
@@ -411,6 +504,10 @@ function installAuthOnClient(client2) {
|
|
|
411
504
|
} catch {
|
|
412
505
|
}
|
|
413
506
|
request.headers.set("X-Client-Time", (/* @__PURE__ */ new Date()).toISOString());
|
|
507
|
+
if (dpopEnabled() && typeof window !== "undefined") {
|
|
508
|
+
const proof = await _makeDpopProof(request.method, request.url);
|
|
509
|
+
if (proof) request.headers.set("DPoP", proof);
|
|
510
|
+
}
|
|
414
511
|
return request;
|
|
415
512
|
});
|
|
416
513
|
client2.interceptors.error.use((err, res, req) => {
|
|
@@ -444,6 +541,10 @@ function installAuthOnClient(client2) {
|
|
|
444
541
|
const retry = request.clone();
|
|
445
542
|
retry.headers.set("Authorization", `Bearer ${newToken}`);
|
|
446
543
|
retry.headers.set(RETRY_MARKER, "1");
|
|
544
|
+
if (dpopEnabled() && typeof window !== "undefined") {
|
|
545
|
+
const proof = await _makeDpopProof(retry.method, retry.url);
|
|
546
|
+
if (proof) retry.headers.set("DPoP", proof);
|
|
547
|
+
}
|
|
447
548
|
try {
|
|
448
549
|
const retried = await fetch(retry);
|
|
449
550
|
if (retried.status === 401 && _onUnauthorized) {
|
|
@@ -1489,7 +1590,7 @@ __name(sendBatch, "sendBatch");
|
|
|
1489
1590
|
// src/client/utils/env.ts
|
|
1490
1591
|
var isDevelopment = process.env.NODE_ENV === "development";
|
|
1491
1592
|
var isProduction = !isDevelopment;
|
|
1492
|
-
var MONITOR_VERSION = "2.1.
|
|
1593
|
+
var MONITOR_VERSION = "2.1.429";
|
|
1493
1594
|
|
|
1494
1595
|
// src/client/constants.ts
|
|
1495
1596
|
var MONITOR_INGEST_PATTERN = /cfg\/monitor\/ingest/;
|