@mx-cartographer/experiences 9.4.19-alpha.al0 → 9.4.19-alpha.al3
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/CHANGELOG.md +1 -1
- package/dist/rum/RumRedaction.d.ts +3 -0
- package/dist/rum/RumRedaction.es.js +8 -0
- package/dist/rum/RumRedaction.es.js.map +1 -0
- package/dist/rum/beforeSend.d.ts +40 -0
- package/dist/rum/beforeSend.es.js +16 -0
- package/dist/rum/beforeSend.es.js.map +1 -0
- package/dist/rum/errorBuffer.d.ts +9 -0
- package/dist/rum/errorBuffer.es.js +27 -0
- package/dist/rum/errorBuffer.es.js.map +1 -0
- package/dist/rum/index.d.ts +3 -0
- package/dist/rum/index.es.js +11 -0
- package/package.json +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var a = /\b([A-Za-z]{3}-)?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/g, t = /[-−(]?\$\s*\d(?:[\d,]|[ \u00A0\u202F](?=\d))*(?:[.,]\d+)?(?:\s*[KMB])?\)?|[-−(]?\d(?:[\d,]|[ \u00A0\u202F](?=\d))*(?:[.,]\d+)?(?:\s*[KMB])?\s*\$\)?/gi, d = /(\/(?:md\/[^/?#]+|login)\/)[^?#]+/g, T = (r) => typeof r == "string" ? r.replace(a, (s, A) => `${A ?? ""}REDACTED`) : r, f = (r) => typeof r == "string" ? r.replace(t, "$[amount]") : r, o = (r) => typeof r == "string" ? r.replace(d, "$1REDACTED") : r;
|
|
2
|
+
export {
|
|
3
|
+
f as redactAmounts,
|
|
4
|
+
T as redactGuids,
|
|
5
|
+
o as redactSsoPath
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=RumRedaction.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RumRedaction.es.js","names":[],"sources":["../../src/rum/RumRedaction.ts"],"sourcesContent":["// String scrubbers for Datadog RUM `beforeSend` hooks. RUM records URLs,\n// error messages and clicked-element text verbatim, and in MX apps those carry\n// member-linkable identifiers, balances and — on the firefly host — live SSO\n// tokens. Consumers compose these in their own `beforeSend`. All three are\n// total on `string | undefined` and return their input unchanged when it isn't\n// a string.\n\n// MX GUIDs are a 3-letter uppercase prefix plus a UUID (ACT-…, USR-…, TRN-…).\n// API paths embed them in both the path and the query string\n// (`/accounts/ACT-<uuid>/monthly_account_balances`, `?account_guids[]=ACT-<uuid>`).\n// The prefix is kept so URLs still group by resource kind; only the identifying\n// UUID is dropped. The prefix is optional in the pattern so bare UUIDs\n// (session / correlation ids) are caught too.\nconst GUID_PATTERN =\n /\\b([A-Za-z]{3}-)?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b/g\n\n// Interaction names come from rendered button/link text, which is frequently a\n// balance or transaction amount. Both sign positions are matched (\"$1,234.56\"\n// and fr-CA \"123,45 $\"), the K/M/B abbreviation (\"$1.2K\"), and a leading \"-\",\n// \"−\" (U+2212) or accounting \"(\" with trailing \")\", so a negative renders as\n// \"$[amount]\" rather than \"-$[amount]\". Digit groups may be joined by \",\" or by\n// a space / no-break space / narrow no-break space, which is how\n// Intl.NumberFormat('fr-CA') groups thousands (\"1 234,56 $\"); the lookahead only\n// swallows a space when another digit follows it.\nconst AMOUNT_PATTERN =\n /[-−(]?\\$\\s*\\d(?:[\\d,]|[ \\u00A0\\u202F](?=\\d))*(?:[.,]\\d+)?(?:\\s*[KMB])?\\)?|[-−(]?\\d(?:[\\d,]|[ \\u00A0\\u202F](?=\\d))*(?:[.,]\\d+)?(?:\\s*[KMB])?\\s*\\$\\)?/gi\n\n// Firefly's widget SSO deep-links put a live single-use auth token — and an\n// optional base64 params blob that can carry account/insight GUIDs — directly\n// in the path: /md/<widget>/:single_sign_on_token(/:encoded_params) renders the\n// widget in place, so RUM's first view.url and every later view.referrer would\n// otherwise ship the token verbatim. Neither segment is UUID-shaped, so the GUID\n// pattern cannot catch them; everything after the widget segment is replaced.\n// /login/:single_sign_on_token redirects, but still surfaces as a referrer.\nconst SSO_PATH_PATTERN = /(\\/(?:md\\/[^/?#]+|login)\\/)[^?#]+/g\n\nexport const redactGuids = <T extends string | undefined>(value: T): T =>\n typeof value === 'string'\n ? (value.replace(\n GUID_PATTERN,\n (_match: string, prefix?: string) => `${prefix ?? ''}REDACTED`,\n ) as T)\n : value\n\nexport const redactAmounts = <T extends string | undefined>(value: T): T =>\n typeof value === 'string' ? (value.replace(AMOUNT_PATTERN, '$[amount]') as T) : value\n\nexport const redactSsoPath = <T extends string | undefined>(value: T): T =>\n typeof value === 'string' ? (value.replace(SSO_PATH_PATTERN, '$1REDACTED') as T) : value\n"],"mappings":"AAaA,IAAM,IACJ,mGAUI,IACJ,yJASI,IAAmB,sCAEZ,IAAA,CAA6C,MACxD,OAAO,KAAU,WACZ,EAAM,QACL,GAAA,CACC,GAAgB,MAAoB,GAAG,KAAU,EAAA,UACpD,IACA,GAEO,IAAA,CAA+C,MAC1D,OAAO,KAAU,WAAY,EAAM,QAAQ,GAAgB,WAAW,IAAU,GAErE,IAAA,CAA+C,MAC1D,OAAO,KAAU,WAAY,EAAM,QAAQ,GAAkB,YAAY,IAAU"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface RumBeforeSendEvent {
|
|
2
|
+
type: string;
|
|
3
|
+
view?: {
|
|
4
|
+
url: string;
|
|
5
|
+
referrer?: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
};
|
|
8
|
+
resource?: {
|
|
9
|
+
type?: string;
|
|
10
|
+
url: string;
|
|
11
|
+
status_code?: number;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
};
|
|
14
|
+
error?: {
|
|
15
|
+
message: string;
|
|
16
|
+
stack?: string;
|
|
17
|
+
resource?: {
|
|
18
|
+
url: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
};
|
|
23
|
+
action?: {
|
|
24
|
+
target?: {
|
|
25
|
+
name: string;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
};
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
};
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
export interface RumBeforeSendOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Also scrub firefly's /md/<widget>/:single_sign_on_token deep-link paths and
|
|
35
|
+
* /login/:token referrers. Only the firefly host has those routes; a
|
|
36
|
+
* core-data-served build should leave this off.
|
|
37
|
+
*/
|
|
38
|
+
scrubSsoPaths?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export declare function buildRumBeforeSend({ scrubSsoPaths }?: RumBeforeSendOptions): (event: RumBeforeSendEvent) => boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { redactAmounts as e, redactGuids as c, redactSsoPath as a } from "./RumRedaction.es.js";
|
|
2
|
+
function f({ scrubSsoPaths: i = !1 } = {}) {
|
|
3
|
+
const o = (r) => i ? a(c(r)) : c(r);
|
|
4
|
+
return (r) => {
|
|
5
|
+
if (r.view && (r.view.url = o(r.view.url), r.view.referrer = o(r.view.referrer)), r.resource && (r.resource.url = o(r.resource.url)), r.error && (r.error.message = e(o(r.error.message)), r.error.stack = e(o(r.error.stack)), r.error.resource && (r.error.resource.url = o(r.error.resource.url))), r.action?.target && (r.action.target.name = e(c(r.action.target.name))), r.type !== "resource" || !r.resource) return !0;
|
|
6
|
+
const { resource: u } = r;
|
|
7
|
+
if (u.type === "xhr" || u.type === "fetch") return !0;
|
|
8
|
+
const s = u.status_code;
|
|
9
|
+
return !(s !== void 0 && s > 0 && s < 400);
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
f as buildRumBeforeSend
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=beforeSend.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"beforeSend.es.js","names":[],"sources":["../../src/rum/beforeSend.ts"],"sourcesContent":["import { redactAmounts, redactGuids, redactSsoPath } from './RumRedaction'\n\n// The subset of a Datadog RUM event that beforeSend reads or writes. Structural\n// on purpose: any RumEvent from @datadog/browser-rum satisfies it, and this\n// package takes no dependency on the SDK. Every field written here is on the\n// SDK's beforeSend allowlist (MODIFIABLE_FIELD_PATHS_BY_EVENT in\n// browser-rum-core/domain/assembly) — writes to anything else are silently\n// discarded by the SDK.\n// The index signatures matter: SDK event members carry other fields, and\n// TypeScript's weak-type rule would otherwise reject e.g. RumErrorEvent.action\n// (which has an `id` but no `target`) as sharing no properties with `action`.\nexport interface RumBeforeSendEvent {\n type: string\n view?: { url: string; referrer?: string; [key: string]: unknown }\n resource?: { type?: string; url: string; status_code?: number; [key: string]: unknown }\n error?: {\n message: string\n stack?: string\n resource?: { url: string; [key: string]: unknown }\n [key: string]: unknown\n }\n action?: { target?: { name: string; [key: string]: unknown }; [key: string]: unknown }\n [key: string]: unknown\n}\n\nexport interface RumBeforeSendOptions {\n /**\n * Also scrub firefly's /md/<widget>/:single_sign_on_token deep-link paths and\n * /login/:token referrers. Only the firefly host has those routes; a\n * core-data-served build should leave this off.\n */\n scrubSsoPaths?: boolean\n}\n\n// Builds the beforeSend hook every MX RUM consumer installs: redact\n// member-linkable identifiers and amounts from everything RUM records verbatim,\n// then drop the successful static resources that make up the bulk of the volume\n// while keeping XHR/fetch so client-perceived API latency stays visible.\nexport function buildRumBeforeSend({ scrubSsoPaths = false }: RumBeforeSendOptions = {}) {\n const redactUrl = <T extends string | undefined>(value: T): T =>\n scrubSsoPaths ? redactSsoPath(redactGuids(value)) : redactGuids(value)\n\n return (event: RumBeforeSendEvent): boolean => {\n if (event.view) {\n event.view.url = redactUrl(event.view.url)\n event.view.referrer = redactUrl(event.view.referrer)\n }\n if (event.resource) {\n event.resource.url = redactUrl(event.resource.url)\n }\n if (event.error) {\n event.error.message = redactAmounts(redactUrl(event.error.message))\n event.error.stack = redactAmounts(redactUrl(event.error.stack))\n if (event.error.resource) event.error.resource.url = redactUrl(event.error.resource.url)\n }\n if (event.action?.target) {\n event.action.target.name = redactAmounts(redactGuids(event.action.target.name))\n }\n\n if (event.type !== 'resource' || !event.resource) return true\n const { resource } = event\n if (resource.type === 'xhr' || resource.type === 'fetch') return true\n const status = resource.status_code\n if (status !== undefined && status > 0 && status < 400) return false\n return true\n }\n}\n"],"mappings":";AAsCA,SAAgB,EAAmB,EAAE,eAAA,IAAgB,GAAA,IAAgC,CAAC,GAAG;AACvF,QAAM,IAAA,CAA2C,MAC/C,IAAgB,EAAc,EAAY,CAAK,CAAC,IAAI,EAAY,CAAK;AAEvE,SAAA,CAAQ,MAAuC;AAiB7C,QAhBI,EAAM,SACR,EAAM,KAAK,MAAM,EAAU,EAAM,KAAK,GAAG,GACzC,EAAM,KAAK,WAAW,EAAU,EAAM,KAAK,QAAQ,IAEjD,EAAM,aACR,EAAM,SAAS,MAAM,EAAU,EAAM,SAAS,GAAG,IAE/C,EAAM,UACR,EAAM,MAAM,UAAU,EAAc,EAAU,EAAM,MAAM,OAAO,CAAC,GAClE,EAAM,MAAM,QAAQ,EAAc,EAAU,EAAM,MAAM,KAAK,CAAC,GAC1D,EAAM,MAAM,aAAU,EAAM,MAAM,SAAS,MAAM,EAAU,EAAM,MAAM,SAAS,GAAG,KAErF,EAAM,QAAQ,WAChB,EAAM,OAAO,OAAO,OAAO,EAAc,EAAY,EAAM,OAAO,OAAO,IAAI,CAAC,IAG5E,EAAM,SAAS,cAAc,CAAC,EAAM,SAAU,QAAO;AACzD,UAAM,EAAE,UAAA,EAAA,IAAa;AACrB,QAAI,EAAS,SAAS,SAAS,EAAS,SAAS,QAAS,QAAO;AACjE,UAAM,IAAS,EAAS;AACxB,WAAI,EAAA,MAAW,UAAa,IAAS,KAAK,IAAS;AAAA,EAErD;AACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface RumErrorBuffer<Context = Record<string, unknown>> {
|
|
2
|
+
/** Queue an error. Returns false (and drops it) once the buffer is full. */
|
|
3
|
+
push(error: unknown, context?: Context): boolean;
|
|
4
|
+
/** Drain in arrival order into `send`, typically `datadogRum.addError`. */
|
|
5
|
+
flush(send: (error: unknown, context?: Context) => void): void;
|
|
6
|
+
readonly size: number;
|
|
7
|
+
}
|
|
8
|
+
export declare const DEFAULT_RUM_ERROR_BUFFER_SIZE = 50;
|
|
9
|
+
export declare function createRumErrorBuffer<Context = Record<string, unknown>>(maxSize?: number): RumErrorBuffer<Context>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
var u = 50;
|
|
2
|
+
function s(n = 50) {
|
|
3
|
+
const e = [];
|
|
4
|
+
return {
|
|
5
|
+
push(t, r) {
|
|
6
|
+
return e.length >= n ? !1 : (e.push({
|
|
7
|
+
error: t,
|
|
8
|
+
context: r
|
|
9
|
+
}), !0);
|
|
10
|
+
},
|
|
11
|
+
flush(t) {
|
|
12
|
+
for (; e.length > 0; ) {
|
|
13
|
+
const r = e.shift();
|
|
14
|
+
r && t(r.error, r.context);
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
get size() {
|
|
18
|
+
return e.length;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
u as DEFAULT_RUM_ERROR_BUFFER_SIZE,
|
|
24
|
+
s as createRumErrorBuffer
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=errorBuffer.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorBuffer.es.js","names":[],"sources":["../../src/rum/errorBuffer.ts"],"sourcesContent":["// Errors reported before Datadog RUM has initialized have nowhere to go, so\n// consumers buffer them and flush once `datadogRum.init()` has run. Capped so a\n// configless environment — where RUM never initializes — cannot grow the buffer\n// without bound. The buffer knows nothing about the SDK: the consumer supplies\n// the sink at flush time, so this package takes no dependency on\n// @datadog/browser-rum.\n\nexport interface RumErrorBuffer<Context = Record<string, unknown>> {\n /** Queue an error. Returns false (and drops it) once the buffer is full. */\n push(error: unknown, context?: Context): boolean\n /** Drain in arrival order into `send`, typically `datadogRum.addError`. */\n flush(send: (error: unknown, context?: Context) => void): void\n readonly size: number\n}\n\nexport const DEFAULT_RUM_ERROR_BUFFER_SIZE = 50\n\nexport function createRumErrorBuffer<Context = Record<string, unknown>>(\n maxSize: number = DEFAULT_RUM_ERROR_BUFFER_SIZE,\n): RumErrorBuffer<Context> {\n const items: Array<{ error: unknown; context?: Context }> = []\n return {\n push(error, context) {\n if (items.length >= maxSize) return false\n items.push({ error, context })\n return true\n },\n flush(send) {\n while (items.length > 0) {\n const item = items.shift()\n if (item) send(item.error, item.context)\n }\n },\n get size() {\n return items.length\n },\n }\n}\n"],"mappings":"AAeA,IAAa,IAAgC;AAE7C,SAAgB,EACd,IAAA,IACyB;AACzB,QAAM,IAAsD,CAAC;AAC7D,SAAO;AAAA,IACL,KAAK,GAAO,GAAS;AACnB,aAAI,EAAM,UAAU,IAAgB,MACpC,EAAM,KAAK;AAAA,QAAE,OAAA;AAAA,QAAO,SAAA;AAAA,MAAQ,CAAC,GACtB;AAAA,IACT;AAAA,IACA,MAAM,GAAM;AACV,aAAO,EAAM,SAAS,KAAG;AACvB,cAAM,IAAO,EAAM,MAAM;AACzB,QAAI,KAAM,EAAK,EAAK,OAAO,EAAK,OAAO;AAAA,MACzC;AAAA,IACF;AAAA,IACA,IAAI,OAAO;AACT,aAAO,EAAM;AAAA,IACf;AAAA,EACF;AACF"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { redactAmounts, redactGuids, redactSsoPath } from './RumRedaction';
|
|
2
|
+
export { buildRumBeforeSend, type RumBeforeSendEvent, type RumBeforeSendOptions, } from './beforeSend';
|
|
3
|
+
export { createRumErrorBuffer, DEFAULT_RUM_ERROR_BUFFER_SIZE, type RumErrorBuffer, } from './errorBuffer';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { redactAmounts as o, redactGuids as e, redactSsoPath as t } from "./RumRedaction.es.js";
|
|
2
|
+
import { buildRumBeforeSend as R } from "./beforeSend.es.js";
|
|
3
|
+
import { DEFAULT_RUM_ERROR_BUFFER_SIZE as f, createRumErrorBuffer as u } from "./errorBuffer.es.js";
|
|
4
|
+
export {
|
|
5
|
+
f as DEFAULT_RUM_ERROR_BUFFER_SIZE,
|
|
6
|
+
R as buildRumBeforeSend,
|
|
7
|
+
u as createRumErrorBuffer,
|
|
8
|
+
o as redactAmounts,
|
|
9
|
+
e as redactGuids,
|
|
10
|
+
t as redactSsoPath
|
|
11
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mx-cartographer/experiences",
|
|
3
|
-
"version": "9.4.19-alpha.
|
|
3
|
+
"version": "9.4.19-alpha.al3",
|
|
4
4
|
"description": "Library containing experience widgets",
|
|
5
5
|
"author": "MX",
|
|
6
6
|
"license": "MIT",
|
|
@@ -104,6 +104,10 @@
|
|
|
104
104
|
"./trends": {
|
|
105
105
|
"import": "./dist/trends/index.es.js",
|
|
106
106
|
"types": "./dist/trends/index.d.ts"
|
|
107
|
+
},
|
|
108
|
+
"./rum": {
|
|
109
|
+
"import": "./dist/rum/index.es.js",
|
|
110
|
+
"types": "./dist/rum/index.d.ts"
|
|
107
111
|
}
|
|
108
112
|
},
|
|
109
113
|
"typesVersions": {
|
|
@@ -179,6 +183,9 @@
|
|
|
179
183
|
],
|
|
180
184
|
"trends": [
|
|
181
185
|
"./dist/trends/index.d.ts"
|
|
186
|
+
],
|
|
187
|
+
"rum": [
|
|
188
|
+
"./dist/rum/index.d.ts"
|
|
182
189
|
]
|
|
183
190
|
}
|
|
184
191
|
},
|
|
@@ -232,6 +239,7 @@
|
|
|
232
239
|
},
|
|
233
240
|
"devDependencies": {
|
|
234
241
|
"@babel/core": "^7.29.7",
|
|
242
|
+
"@datadog/browser-rum-core": "7.12.0",
|
|
235
243
|
"@storybook/addon-a11y": "^10.5.5",
|
|
236
244
|
"@storybook/addon-docs": "^10.5.5",
|
|
237
245
|
"@storybook/addon-links": "^10.5.5",
|