@safaricom-mxl/web-sdk 0.0.19 → 0.0.21

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.
Files changed (160) hide show
  1. package/DATA_EXPORT.md +11 -8
  2. package/dist/exporters/MXLLogExporter/MXLLogExporter.cjs +2 -2
  3. package/dist/exporters/MXLLogExporter/MXLLogExporter.cjs.map +1 -1
  4. package/dist/exporters/MXLLogExporter/MXLLogExporter.d.cts +1 -1
  5. package/dist/exporters/MXLLogExporter/MXLLogExporter.d.cts.map +1 -1
  6. package/dist/exporters/MXLLogExporter/MXLLogExporter.d.ts +1 -1
  7. package/dist/exporters/MXLLogExporter/MXLLogExporter.d.ts.map +1 -1
  8. package/dist/exporters/MXLLogExporter/MXLLogExporter.js +2 -2
  9. package/dist/exporters/MXLLogExporter/MXLLogExporter.js.map +1 -1
  10. package/dist/exporters/MXLLogExporter/types.d.cts +1 -1
  11. package/dist/exporters/MXLLogExporter/types.d.cts.map +1 -1
  12. package/dist/exporters/MXLLogExporter/types.d.ts +1 -1
  13. package/dist/exporters/MXLLogExporter/types.d.ts.map +1 -1
  14. package/dist/exporters/MXLLogExporter/utils.cjs +1 -1
  15. package/dist/exporters/MXLLogExporter/utils.cjs.map +1 -1
  16. package/dist/exporters/MXLLogExporter/utils.d.cts +1 -1
  17. package/dist/exporters/MXLLogExporter/utils.d.cts.map +1 -1
  18. package/dist/exporters/MXLLogExporter/utils.d.ts +1 -1
  19. package/dist/exporters/MXLLogExporter/utils.d.ts.map +1 -1
  20. package/dist/exporters/MXLLogExporter/utils.js +2 -2
  21. package/dist/exporters/MXLLogExporter/utils.js.map +1 -1
  22. package/dist/exporters/MXLTraceExporter/MXLTraceExporter.cjs +2 -2
  23. package/dist/exporters/MXLTraceExporter/MXLTraceExporter.cjs.map +1 -1
  24. package/dist/exporters/MXLTraceExporter/MXLTraceExporter.d.cts +1 -1
  25. package/dist/exporters/MXLTraceExporter/MXLTraceExporter.d.cts.map +1 -1
  26. package/dist/exporters/MXLTraceExporter/MXLTraceExporter.d.ts +1 -1
  27. package/dist/exporters/MXLTraceExporter/MXLTraceExporter.d.ts.map +1 -1
  28. package/dist/exporters/MXLTraceExporter/MXLTraceExporter.js +2 -2
  29. package/dist/exporters/MXLTraceExporter/MXLTraceExporter.js.map +1 -1
  30. package/dist/exporters/MXLTraceExporter/types.d.cts +1 -1
  31. package/dist/exporters/MXLTraceExporter/types.d.cts.map +1 -1
  32. package/dist/exporters/MXLTraceExporter/types.d.ts +1 -1
  33. package/dist/exporters/MXLTraceExporter/types.d.ts.map +1 -1
  34. package/dist/exporters/MXLTraceExporter/utils.cjs +1 -1
  35. package/dist/exporters/MXLTraceExporter/utils.cjs.map +1 -1
  36. package/dist/exporters/MXLTraceExporter/utils.d.cts +1 -1
  37. package/dist/exporters/MXLTraceExporter/utils.d.cts.map +1 -1
  38. package/dist/exporters/MXLTraceExporter/utils.d.ts +1 -1
  39. package/dist/exporters/MXLTraceExporter/utils.d.ts.map +1 -1
  40. package/dist/exporters/MXLTraceExporter/utils.js +2 -2
  41. package/dist/exporters/MXLTraceExporter/utils.js.map +1 -1
  42. package/dist/exporters/utils.cjs +2 -2
  43. package/dist/exporters/utils.cjs.map +1 -1
  44. package/dist/exporters/utils.d.cts +2 -2
  45. package/dist/exporters/utils.d.cts.map +1 -1
  46. package/dist/exporters/utils.d.ts +2 -2
  47. package/dist/exporters/utils.d.ts.map +1 -1
  48. package/dist/exporters/utils.js +2 -2
  49. package/dist/exporters/utils.js.map +1 -1
  50. package/dist/index.d.cts +2 -2
  51. package/dist/index.d.ts +2 -2
  52. package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.cjs +1 -0
  53. package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.cjs.map +1 -1
  54. package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.d.cts.map +1 -1
  55. package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.d.ts.map +1 -1
  56. package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.js +1 -0
  57. package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.js.map +1 -1
  58. package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.cjs +32 -6
  59. package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.cjs.map +1 -1
  60. package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.cts +1 -2
  61. package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.cts.map +1 -1
  62. package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.ts +1 -2
  63. package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.ts.map +1 -1
  64. package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.js +32 -6
  65. package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.js.map +1 -1
  66. package/dist/instrumentations/replay/session-recording/SessionRecording.cjs +1 -0
  67. package/dist/instrumentations/replay/session-recording/SessionRecording.cjs.map +1 -1
  68. package/dist/instrumentations/replay/session-recording/SessionRecording.js +1 -0
  69. package/dist/instrumentations/replay/session-recording/SessionRecording.js.map +1 -1
  70. package/dist/instrumentations/replay/session-recording/config.cjs.map +1 -1
  71. package/dist/instrumentations/replay/session-recording/config.d.cts +1 -1
  72. package/dist/instrumentations/replay/session-recording/config.d.cts.map +1 -1
  73. package/dist/instrumentations/replay/session-recording/config.d.ts +1 -1
  74. package/dist/instrumentations/replay/session-recording/config.d.ts.map +1 -1
  75. package/dist/instrumentations/replay/session-recording/config.js.map +1 -1
  76. package/dist/instrumentations/replay/transport/replayTransport.cjs +31 -11
  77. package/dist/instrumentations/replay/transport/replayTransport.cjs.map +1 -1
  78. package/dist/instrumentations/replay/transport/replayTransport.d.cts +3 -2
  79. package/dist/instrumentations/replay/transport/replayTransport.d.cts.map +1 -1
  80. package/dist/instrumentations/replay/transport/replayTransport.d.ts +3 -2
  81. package/dist/instrumentations/replay/transport/replayTransport.d.ts.map +1 -1
  82. package/dist/instrumentations/replay/transport/replayTransport.js +31 -11
  83. package/dist/instrumentations/replay/transport/replayTransport.js.map +1 -1
  84. package/dist/instrumentations/replay/transport/types.d.cts +3 -1
  85. package/dist/instrumentations/replay/transport/types.d.cts.map +1 -1
  86. package/dist/instrumentations/replay/transport/types.d.ts +3 -1
  87. package/dist/instrumentations/replay/transport/types.d.ts.map +1 -1
  88. package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.cjs +19 -11
  89. package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.cjs.map +1 -1
  90. package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.d.cts +3 -3
  91. package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.d.cts.map +1 -1
  92. package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.d.ts +3 -3
  93. package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.d.ts.map +1 -1
  94. package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.js +19 -11
  95. package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.js.map +1 -1
  96. package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.cjs +28 -0
  97. package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.cjs.map +1 -0
  98. package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.cts +23 -0
  99. package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.cts.map +1 -0
  100. package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.ts +23 -0
  101. package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.ts.map +1 -0
  102. package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.js +27 -0
  103. package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.js.map +1 -0
  104. package/dist/managers/MXLConfigManager/types.d.cts +16 -6
  105. package/dist/managers/MXLConfigManager/types.d.cts.map +1 -1
  106. package/dist/managers/MXLConfigManager/types.d.ts +16 -6
  107. package/dist/managers/MXLConfigManager/types.d.ts.map +1 -1
  108. package/dist/managers/MXLConfigManager/utils.cjs +66 -1
  109. package/dist/managers/MXLConfigManager/utils.cjs.map +1 -1
  110. package/dist/managers/MXLConfigManager/utils.d.cts +10 -3
  111. package/dist/managers/MXLConfigManager/utils.d.cts.map +1 -1
  112. package/dist/managers/MXLConfigManager/utils.d.ts +10 -3
  113. package/dist/managers/MXLConfigManager/utils.d.ts.map +1 -1
  114. package/dist/managers/MXLConfigManager/utils.js +64 -2
  115. package/dist/managers/MXLConfigManager/utils.js.map +1 -1
  116. package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.cjs +8 -0
  117. package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.cjs.map +1 -1
  118. package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.d.cts +2 -0
  119. package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.d.cts.map +1 -1
  120. package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.d.ts +2 -0
  121. package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.d.ts.map +1 -1
  122. package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.js +8 -0
  123. package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.js.map +1 -1
  124. package/dist/managers/MXLSDKFeaturesManager/types.d.cts +2 -0
  125. package/dist/managers/MXLSDKFeaturesManager/types.d.cts.map +1 -1
  126. package/dist/managers/MXLSDKFeaturesManager/types.d.ts +2 -0
  127. package/dist/managers/MXLSDKFeaturesManager/types.d.ts.map +1 -1
  128. package/dist/mxl-web-sdk.js +2 -2
  129. package/dist/mxl-web-sdk.js.map +1 -1
  130. package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.cjs +10 -1
  131. package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.cjs.map +1 -1
  132. package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.d.cts +3 -0
  133. package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.d.cts.map +1 -1
  134. package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.d.ts +3 -0
  135. package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.d.ts.map +1 -1
  136. package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.js +10 -1
  137. package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.js.map +1 -1
  138. package/dist/processors/MXLSessionPartBatchedSpanProcessor/types.d.cts +1 -0
  139. package/dist/processors/MXLSessionPartBatchedSpanProcessor/types.d.cts.map +1 -1
  140. package/dist/processors/MXLSessionPartBatchedSpanProcessor/types.d.ts +1 -0
  141. package/dist/processors/MXLSessionPartBatchedSpanProcessor/types.d.ts.map +1 -1
  142. package/dist/resources/sdkConstants.cjs +1 -1
  143. package/dist/resources/sdkConstants.cjs.map +1 -1
  144. package/dist/resources/sdkConstants.d.cts +1 -1
  145. package/dist/resources/sdkConstants.d.ts +1 -1
  146. package/dist/resources/sdkConstants.js +1 -1
  147. package/dist/resources/sdkConstants.js.map +1 -1
  148. package/dist/sdk/initSDK.cjs +20 -12
  149. package/dist/sdk/initSDK.cjs.map +1 -1
  150. package/dist/sdk/initSDK.d.cts +3 -2
  151. package/dist/sdk/initSDK.d.cts.map +1 -1
  152. package/dist/sdk/initSDK.d.ts +3 -2
  153. package/dist/sdk/initSDK.d.ts.map +1 -1
  154. package/dist/sdk/initSDK.js +20 -12
  155. package/dist/sdk/initSDK.js.map +1 -1
  156. package/dist/sdk/types.d.cts +29 -7
  157. package/dist/sdk/types.d.cts.map +1 -1
  158. package/dist/sdk/types.d.ts +29 -7
  159. package/dist/sdk/types.d.ts.map +1 -1
  160. package/package.json +1 -1
@@ -1,10 +1,11 @@
1
1
  import { gzip } from "./gzip.js";
2
- import { getDataURL, getMXLHeaders } from "../../../exporters/utils.js";
2
+ import { getApiURL, getOtelCollectorURL } from "../../../managers/MXLConfigManager/utils.js";
3
3
  //#region src/instrumentations/replay/transport/replayTransport.ts
4
4
  /**
5
5
  * Ported from Maple browser SDK (MIT), adapted for MXL auth and endpoints.
6
6
  * @see https://github.com/Makisuo/maple/tree/main/packages/browser/src/replay/transport.ts
7
7
  */
8
+ const getReplayHeaders = (appID) => ({ "mxl-client-id": appID });
8
9
  let lastWarnAt = 0;
9
10
  function warnDropped(what, error) {
10
11
  const now = Date.now();
@@ -13,18 +14,35 @@ function warnDropped(what, error) {
13
14
  console.warn(`[mxl] session replay ${what} failed (dropping; will retry on next chunk):`, error);
14
15
  }
15
16
  function createReplayTransport(config) {
16
- const headers = getMXLHeaders(config.appID, config.userID);
17
+ const headers = getReplayHeaders(config.appID);
17
18
  const baseUrl = config.baseUrl.replace(/\/$/, "");
19
+ const otelCollectorURL = config.otelCollectorURL.replace(/\/$/, "");
18
20
  const ignoredPathPrefixes = [
19
- `${baseUrl}/v1/sessionReplays/`,
20
- `${baseUrl}/v1/sessionEvents`,
21
- `${baseUrl}/v1/logs`,
22
- `${baseUrl}/v1/traces`
21
+ `${baseUrl}/sessionReplays/`,
22
+ `${baseUrl}/sessionEvents`,
23
+ `${baseUrl}/replay`,
24
+ `${otelCollectorURL}/v1/logs`,
25
+ `${otelCollectorURL}/v1/traces`
23
26
  ];
24
27
  const shouldIgnoreUrl = (url) => ignoredPathPrefixes.some((prefix) => url.startsWith(prefix));
28
+ const postReplay = async (keepalive = false) => {
29
+ if (!config.apiKey) return;
30
+ await fetch(`${baseUrl}/replay`, {
31
+ body: "null",
32
+ headers: {
33
+ ...headers,
34
+ "content-type": "application/json",
35
+ "mxl-api-key": config.apiKey
36
+ },
37
+ keepalive,
38
+ method: "POST"
39
+ }).catch((error) => {
40
+ warnDropped("replay POST", error);
41
+ });
42
+ };
25
43
  const postSessionMeta = async (row, keepalive = false) => {
26
44
  const body = `${JSON.stringify(row)}\n`;
27
- await fetch(`${baseUrl}/v1/sessionReplays/meta`, {
45
+ await fetch(`${baseUrl}/sessionReplays/meta`, {
28
46
  body,
29
47
  headers: {
30
48
  ...headers,
@@ -39,7 +57,7 @@ function createReplayTransport(config) {
39
57
  const postSessionEvents = async (rows, keepalive = false) => {
40
58
  if (rows.length === 0) return;
41
59
  const body = `${rows.map((row) => JSON.stringify(row)).join("\n")}\n`;
42
- await fetch(`${baseUrl}/v1/sessionEvents`, {
60
+ await fetch(`${baseUrl}/sessionEvents`, {
43
61
  body,
44
62
  headers: {
45
63
  ...headers,
@@ -52,7 +70,7 @@ function createReplayTransport(config) {
52
70
  });
53
71
  };
54
72
  const postSessionBlob = async (meta, gzipped, keepalive = false) => {
55
- await fetch(`${baseUrl}/v1/sessionReplays/blob`, {
73
+ await fetch(`${baseUrl}/sessionReplays/blob`, {
56
74
  body: gzipped,
57
75
  headers: {
58
76
  ...headers,
@@ -70,6 +88,7 @@ function createReplayTransport(config) {
70
88
  });
71
89
  };
72
90
  return {
91
+ postReplay,
73
92
  postSessionBlob,
74
93
  postSessionEvents,
75
94
  postSessionMeta,
@@ -78,9 +97,10 @@ function createReplayTransport(config) {
78
97
  }
79
98
  function createReplayTransportFromInit(args) {
80
99
  return createReplayTransport({
100
+ apiKey: args.apiKey,
81
101
  appID: args.appID,
82
- baseUrl: getDataURL(args.appID, args.mxlDataURL),
83
- userID: args.userID
102
+ baseUrl: getApiURL(args.apiURL),
103
+ otelCollectorURL: getOtelCollectorURL(args.otelCollectorURL)
84
104
  });
85
105
  }
86
106
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"replayTransport.js","names":[],"sources":["../../../../src/instrumentations/replay/transport/replayTransport.ts"],"sourcesContent":["/**\n * Ported from Maple browser SDK (MIT), adapted for MXL auth and endpoints.\n * @see https://github.com/Makisuo/maple/tree/main/packages/browser/src/replay/transport.ts\n */\n\nimport { getDataURL, getMXLHeaders } from '../../../exporters/utils';\nimport { gzip } from './gzip';\nimport type { ChunkMeta, ReplayTransport, ReplayTransportConfig } from './types';\n\nexport { gzip };\n\nlet lastWarnAt = 0;\n\nfunction warnDropped(what: string, error: unknown): void {\n const now = Date.now();\n if (now - lastWarnAt < 30_000) {\n return;\n }\n lastWarnAt = now;\n // oxlint-disable-next-line no-console -- best-effort replay diagnostics\n console.warn(\n `[mxl] session replay ${what} failed (dropping; will retry on next chunk):`,\n error,\n );\n}\n\nexport function createReplayTransport(\n config: ReplayTransportConfig,\n): ReplayTransport {\n const headers = getMXLHeaders(config.appID, config.userID);\n const baseUrl = config.baseUrl.replace(/\\/$/, '');\n\n const ignoredPathPrefixes = [\n `${baseUrl}/v1/sessionReplays/`,\n `${baseUrl}/v1/sessionEvents`,\n `${baseUrl}/v1/logs`,\n `${baseUrl}/v1/traces`,\n ];\n\n const shouldIgnoreUrl = (url: string): boolean =>\n ignoredPathPrefixes.some((prefix) => url.startsWith(prefix));\n\n const postSessionMeta = async (\n row: Record<string, unknown>,\n keepalive = false,\n ): Promise<void> => {\n const body = `${JSON.stringify(row)}\\n`;\n await fetch(`${baseUrl}/v1/sessionReplays/meta`, {\n body,\n headers: {\n ...headers,\n 'content-type': 'application/x-ndjson',\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('metadata POST', error);\n });\n };\n\n const postSessionEvents = async (\n rows: ReadonlyArray<Record<string, unknown>>,\n keepalive = false,\n ): Promise<void> => {\n if (rows.length === 0) {\n return;\n }\n const body = `${rows.map((row) => JSON.stringify(row)).join('\\n')}\\n`;\n await fetch(`${baseUrl}/v1/sessionEvents`, {\n body,\n headers: {\n ...headers,\n 'content-type': 'application/x-ndjson',\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('events POST', error);\n });\n };\n\n const postSessionBlob = async (\n meta: ChunkMeta,\n gzipped: Uint8Array,\n keepalive = false,\n ): Promise<void> => {\n await fetch(`${baseUrl}/v1/sessionReplays/blob`, {\n body: gzipped as unknown as BodyInit,\n headers: {\n ...headers,\n 'content-type': 'application/octet-stream',\n 'x-mxl-chunk-seq': String(meta.chunkSeq),\n 'x-mxl-duration-ms': String(meta.durationMs),\n 'x-mxl-event-count': String(meta.eventCount),\n 'x-mxl-is-checkpoint': meta.isCheckpoint ? '1' : '0',\n 'x-mxl-session-id': meta.sessionId,\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('blob POST', error);\n });\n };\n\n return {\n postSessionBlob,\n postSessionEvents,\n postSessionMeta,\n shouldIgnoreUrl,\n };\n}\n\nexport function createReplayTransportFromInit(args: {\n appID: string;\n userID: string;\n mxlDataURL?: string;\n}): ReplayTransport {\n return createReplayTransport({\n appID: args.appID,\n baseUrl: getDataURL(args.appID, args.mxlDataURL),\n userID: args.userID,\n });\n}\n"],"mappings":";;;;;;;AAWA,IAAI,aAAa;AAEjB,SAAS,YAAY,MAAc,OAAsB;CACvD,MAAM,MAAM,KAAK,KAAK;AACtB,KAAI,MAAM,aAAa,IACrB;AAEF,cAAa;AAEb,SAAQ,KACN,wBAAwB,KAAK,gDAC7B,MACD;;AAGH,SAAgB,sBACd,QACiB;CACjB,MAAM,UAAU,cAAc,OAAO,OAAO,OAAO,OAAO;CAC1D,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GAAG;CAEjD,MAAM,sBAAsB;EAC1B,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,QAAQ;EACZ;CAED,MAAM,mBAAmB,QACvB,oBAAoB,MAAM,WAAW,IAAI,WAAW,OAAO,CAAC;CAE9D,MAAM,kBAAkB,OACtB,KACA,YAAY,UACM;EAClB,MAAM,OAAO,GAAG,KAAK,UAAU,IAAI,CAAC;AACpC,QAAM,MAAM,GAAG,QAAQ,0BAA0B;GAC/C;GACA,SAAS;IACP,GAAG;IACH,gBAAgB;IACjB;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,iBAAiB,MAAM;IACnC;;CAGJ,MAAM,oBAAoB,OACxB,MACA,YAAY,UACM;AAClB,MAAI,KAAK,WAAW,EAClB;EAEF,MAAM,OAAO,GAAG,KAAK,KAAK,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC;AAClE,QAAM,MAAM,GAAG,QAAQ,oBAAoB;GACzC;GACA,SAAS;IACP,GAAG;IACH,gBAAgB;IACjB;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,eAAe,MAAM;IACjC;;CAGJ,MAAM,kBAAkB,OACtB,MACA,SACA,YAAY,UACM;AAClB,QAAM,MAAM,GAAG,QAAQ,0BAA0B;GAC/C,MAAM;GACN,SAAS;IACP,GAAG;IACH,gBAAgB;IAChB,mBAAmB,OAAO,KAAK,SAAS;IACxC,qBAAqB,OAAO,KAAK,WAAW;IAC5C,qBAAqB,OAAO,KAAK,WAAW;IAC5C,uBAAuB,KAAK,eAAe,MAAM;IACjD,oBAAoB,KAAK;IAC1B;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,aAAa,MAAM;IAC/B;;AAGJ,QAAO;EACL;EACA;EACA;EACA;EACD;;AAGH,SAAgB,8BAA8B,MAI1B;AAClB,QAAO,sBAAsB;EAC3B,OAAO,KAAK;EACZ,SAAS,WAAW,KAAK,OAAO,KAAK,WAAW;EAChD,QAAQ,KAAK;EACd,CAAC"}
1
+ {"version":3,"file":"replayTransport.js","names":[],"sources":["../../../../src/instrumentations/replay/transport/replayTransport.ts"],"sourcesContent":["/**\n * Ported from Maple browser SDK (MIT), adapted for MXL auth and endpoints.\n * @see https://github.com/Makisuo/maple/tree/main/packages/browser/src/replay/transport.ts\n */\n\nimport {\n getApiURL,\n getOtelCollectorURL,\n} from '../../../managers/MXLConfigManager/utils';\nimport { gzip } from './gzip';\nimport type { ChunkMeta, ReplayTransport, ReplayTransportConfig } from './types';\n\nexport { gzip };\n\nconst getReplayHeaders = (appID: string): Record<string, string> => ({\n 'mxl-client-id': appID,\n});\n\nlet lastWarnAt = 0;\n\nfunction warnDropped(what: string, error: unknown): void {\n const now = Date.now();\n if (now - lastWarnAt < 30_000) {\n return;\n }\n lastWarnAt = now;\n // oxlint-disable-next-line no-console -- best-effort replay diagnostics\n console.warn(\n `[mxl] session replay ${what} failed (dropping; will retry on next chunk):`,\n error,\n );\n}\n\nexport function createReplayTransport(\n config: ReplayTransportConfig,\n): ReplayTransport {\n const headers = getReplayHeaders(config.appID);\n const baseUrl = config.baseUrl.replace(/\\/$/, '');\n const otelCollectorURL = config.otelCollectorURL.replace(/\\/$/, '');\n\n const ignoredPathPrefixes = [\n `${baseUrl}/sessionReplays/`,\n `${baseUrl}/sessionEvents`,\n `${baseUrl}/replay`,\n `${otelCollectorURL}/v1/logs`,\n `${otelCollectorURL}/v1/traces`,\n ];\n\n const shouldIgnoreUrl = (url: string): boolean =>\n ignoredPathPrefixes.some((prefix) => url.startsWith(prefix));\n\n const postReplay = async (keepalive = false): Promise<void> => {\n if (!config.apiKey) {\n return;\n }\n await fetch(`${baseUrl}/replay`, {\n body: 'null',\n headers: {\n ...headers,\n 'content-type': 'application/json',\n 'mxl-api-key': config.apiKey,\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('replay POST', error);\n });\n };\n\n const postSessionMeta = async (\n row: Record<string, unknown>,\n keepalive = false,\n ): Promise<void> => {\n const body = `${JSON.stringify(row)}\\n`;\n await fetch(`${baseUrl}/sessionReplays/meta`, {\n body,\n headers: {\n ...headers,\n 'content-type': 'application/x-ndjson',\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('metadata POST', error);\n });\n };\n\n const postSessionEvents = async (\n rows: ReadonlyArray<Record<string, unknown>>,\n keepalive = false,\n ): Promise<void> => {\n if (rows.length === 0) {\n return;\n }\n const body = `${rows.map((row) => JSON.stringify(row)).join('\\n')}\\n`;\n await fetch(`${baseUrl}/sessionEvents`, {\n body,\n headers: {\n ...headers,\n 'content-type': 'application/x-ndjson',\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('events POST', error);\n });\n };\n\n const postSessionBlob = async (\n meta: ChunkMeta,\n gzipped: Uint8Array,\n keepalive = false,\n ): Promise<void> => {\n await fetch(`${baseUrl}/sessionReplays/blob`, {\n body: gzipped as unknown as BodyInit,\n headers: {\n ...headers,\n 'content-type': 'application/octet-stream',\n 'x-mxl-chunk-seq': String(meta.chunkSeq),\n 'x-mxl-duration-ms': String(meta.durationMs),\n 'x-mxl-event-count': String(meta.eventCount),\n 'x-mxl-is-checkpoint': meta.isCheckpoint ? '1' : '0',\n 'x-mxl-session-id': meta.sessionId,\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('blob POST', error);\n });\n };\n\n return {\n postReplay,\n postSessionBlob,\n postSessionEvents,\n postSessionMeta,\n shouldIgnoreUrl,\n };\n}\n\nexport function createReplayTransportFromInit(args: {\n appID: string;\n apiKey?: string;\n apiURL?: string;\n otelCollectorURL?: string;\n}): ReplayTransport {\n return createReplayTransport({\n apiKey: args.apiKey,\n appID: args.appID,\n baseUrl: getApiURL(args.apiURL),\n otelCollectorURL: getOtelCollectorURL(args.otelCollectorURL),\n });\n}\n"],"mappings":";;;;;;;AAcA,MAAM,oBAAoB,WAA2C,EACnE,iBAAiB,OAClB;AAED,IAAI,aAAa;AAEjB,SAAS,YAAY,MAAc,OAAsB;CACvD,MAAM,MAAM,KAAK,KAAK;AACtB,KAAI,MAAM,aAAa,IACrB;AAEF,cAAa;AAEb,SAAQ,KACN,wBAAwB,KAAK,gDAC7B,MACD;;AAGH,SAAgB,sBACd,QACiB;CACjB,MAAM,UAAU,iBAAiB,OAAO,MAAM;CAC9C,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GAAG;CACjD,MAAM,mBAAmB,OAAO,iBAAiB,QAAQ,OAAO,GAAG;CAEnE,MAAM,sBAAsB;EAC1B,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,iBAAiB;EACpB,GAAG,iBAAiB;EACrB;CAED,MAAM,mBAAmB,QACvB,oBAAoB,MAAM,WAAW,IAAI,WAAW,OAAO,CAAC;CAE9D,MAAM,aAAa,OAAO,YAAY,UAAyB;AAC7D,MAAI,CAAC,OAAO,OACV;AAEF,QAAM,MAAM,GAAG,QAAQ,UAAU;GAC/B,MAAM;GACN,SAAS;IACP,GAAG;IACH,gBAAgB;IAChB,eAAe,OAAO;IACvB;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,eAAe,MAAM;IACjC;;CAGJ,MAAM,kBAAkB,OACtB,KACA,YAAY,UACM;EAClB,MAAM,OAAO,GAAG,KAAK,UAAU,IAAI,CAAC;AACpC,QAAM,MAAM,GAAG,QAAQ,uBAAuB;GAC5C;GACA,SAAS;IACP,GAAG;IACH,gBAAgB;IACjB;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,iBAAiB,MAAM;IACnC;;CAGJ,MAAM,oBAAoB,OACxB,MACA,YAAY,UACM;AAClB,MAAI,KAAK,WAAW,EAClB;EAEF,MAAM,OAAO,GAAG,KAAK,KAAK,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC;AAClE,QAAM,MAAM,GAAG,QAAQ,iBAAiB;GACtC;GACA,SAAS;IACP,GAAG;IACH,gBAAgB;IACjB;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,eAAe,MAAM;IACjC;;CAGJ,MAAM,kBAAkB,OACtB,MACA,SACA,YAAY,UACM;AAClB,QAAM,MAAM,GAAG,QAAQ,uBAAuB;GAC5C,MAAM;GACN,SAAS;IACP,GAAG;IACH,gBAAgB;IAChB,mBAAmB,OAAO,KAAK,SAAS;IACxC,qBAAqB,OAAO,KAAK,WAAW;IAC5C,qBAAqB,OAAO,KAAK,WAAW;IAC5C,uBAAuB,KAAK,eAAe,MAAM;IACjD,oBAAoB,KAAK;IAC1B;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,aAAa,MAAM;IAC/B;;AAGJ,QAAO;EACL;EACA;EACA;EACA;EACA;EACD;;AAGH,SAAgB,8BAA8B,MAK1B;AAClB,QAAO,sBAAsB;EAC3B,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,SAAS,UAAU,KAAK,OAAO;EAC/B,kBAAkB,oBAAoB,KAAK,iBAAiB;EAC7D,CAAC"}
@@ -1,8 +1,9 @@
1
1
  //#region src/instrumentations/replay/transport/types.d.ts
2
2
  interface ReplayTransportConfig {
3
3
  readonly appID: string;
4
- readonly userID: string;
4
+ readonly apiKey?: string;
5
5
  readonly baseUrl: string;
6
+ readonly otelCollectorURL: string;
6
7
  }
7
8
  interface ChunkMeta {
8
9
  readonly sessionId: string;
@@ -12,6 +13,7 @@ interface ChunkMeta {
12
13
  readonly durationMs: number;
13
14
  }
14
15
  interface ReplayTransport {
16
+ postReplay: (keepalive?: boolean) => Promise<void>;
15
17
  postSessionMeta: (row: Record<string, unknown>, keepalive?: boolean) => Promise<void>;
16
18
  postSessionEvents: (rows: ReadonlyArray<Record<string, unknown>>, keepalive?: boolean) => Promise<void>;
17
19
  postSessionBlob: (meta: ChunkMeta, gzipped: Uint8Array, keepalive?: boolean) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.cts","names":[],"sources":["../../../../src/instrumentations/replay/transport/types.ts"],"mappings":";UAAiB,qBAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,OAAA;AAAA;AAAA,UAGM,SAAA;EAAA,SACN,SAAA;EAAA,SACA,QAAA;EAAA,SACA,YAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;AAAA;AAAA,UAGM,eAAA;EACf,eAAA,GACE,GAAA,EAAK,MAAA,mBACL,SAAA,eACG,OAAA;EACL,iBAAA,GACE,IAAA,EAAM,aAAA,CAAc,MAAA,oBACpB,SAAA,eACG,OAAA;EACL,eAAA,GACE,IAAA,EAAM,SAAA,EACN,OAAA,EAAS,UAAA,EACT,SAAA,eACG,OAAA;EACL,eAAA,GAAkB,GAAA;AAAA"}
1
+ {"version":3,"file":"types.d.cts","names":[],"sources":["../../../../src/instrumentations/replay/transport/types.ts"],"mappings":";UAAiB,qBAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,OAAA;EAAA,SACA,gBAAA;AAAA;AAAA,UAGM,SAAA;EAAA,SACN,SAAA;EAAA,SACA,QAAA;EAAA,SACA,YAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;AAAA;AAAA,UAGM,eAAA;EACf,UAAA,GAAa,SAAA,eAAwB,OAAA;EACrC,eAAA,GACE,GAAA,EAAK,MAAA,mBACL,SAAA,eACG,OAAA;EACL,iBAAA,GACE,IAAA,EAAM,aAAA,CAAc,MAAA,oBACpB,SAAA,eACG,OAAA;EACL,eAAA,GACE,IAAA,EAAM,SAAA,EACN,OAAA,EAAS,UAAA,EACT,SAAA,eACG,OAAA;EACL,eAAA,GAAkB,GAAA;AAAA"}
@@ -1,8 +1,9 @@
1
1
  //#region src/instrumentations/replay/transport/types.d.ts
2
2
  interface ReplayTransportConfig {
3
3
  readonly appID: string;
4
- readonly userID: string;
4
+ readonly apiKey?: string;
5
5
  readonly baseUrl: string;
6
+ readonly otelCollectorURL: string;
6
7
  }
7
8
  interface ChunkMeta {
8
9
  readonly sessionId: string;
@@ -12,6 +13,7 @@ interface ChunkMeta {
12
13
  readonly durationMs: number;
13
14
  }
14
15
  interface ReplayTransport {
16
+ postReplay: (keepalive?: boolean) => Promise<void>;
15
17
  postSessionMeta: (row: Record<string, unknown>, keepalive?: boolean) => Promise<void>;
16
18
  postSessionEvents: (rows: ReadonlyArray<Record<string, unknown>>, keepalive?: boolean) => Promise<void>;
17
19
  postSessionBlob: (meta: ChunkMeta, gzipped: Uint8Array, keepalive?: boolean) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../../src/instrumentations/replay/transport/types.ts"],"mappings":";UAAiB,qBAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,OAAA;AAAA;AAAA,UAGM,SAAA;EAAA,SACN,SAAA;EAAA,SACA,QAAA;EAAA,SACA,YAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;AAAA;AAAA,UAGM,eAAA;EACf,eAAA,GACE,GAAA,EAAK,MAAA,mBACL,SAAA,eACG,OAAA;EACL,iBAAA,GACE,IAAA,EAAM,aAAA,CAAc,MAAA,oBACpB,SAAA,eACG,OAAA;EACL,eAAA,GACE,IAAA,EAAM,SAAA,EACN,OAAA,EAAS,UAAA,EACT,SAAA,eACG,OAAA;EACL,eAAA,GAAkB,GAAA;AAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../../src/instrumentations/replay/transport/types.ts"],"mappings":";UAAiB,qBAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,OAAA;EAAA,SACA,gBAAA;AAAA;AAAA,UAGM,SAAA;EAAA,SACN,SAAA;EAAA,SACA,QAAA;EAAA,SACA,YAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;AAAA;AAAA,UAGM,eAAA;EACf,UAAA,GAAa,SAAA,eAAwB,OAAA;EACrC,eAAA,GACE,GAAA,EAAK,MAAA,mBACL,SAAA,eACG,OAAA;EACL,iBAAA,GACE,IAAA,EAAM,aAAA,CAAc,MAAA,oBACpB,SAAA,eACG,OAAA;EACL,eAAA,GACE,IAAA,EAAM,SAAA,EACN,OAAA,EAAS,UAAA,EACT,SAAA,eACG,OAAA;EACL,eAAA,GAAkB,GAAA;AAAA"}
@@ -1,14 +1,16 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../_virtual/_rolldown/runtime.cjs");
3
+ const require_managers_MXLConfigManager_utils = require("./utils.cjs");
3
4
  const require_resources_webSdkResource = require("../../resources/webSdkResource.cjs");
4
5
  const require_managers_MXLConfigManager_constants = require("./constants.cjs");
5
- const require_managers_MXLConfigManager_utils = require("./utils.cjs");
6
6
  let _opentelemetry_api = require("@opentelemetry/api");
7
7
  //#region src/managers/MXLConfigManager/MXLDynamicConfigManager.ts
8
8
  const parseRemoteConfig = (remoteConfig) => {
9
9
  const parsed = { samplingPct: remoteConfig.threshold };
10
- if (remoteConfig.network_span_forwarding !== void 0) parsed.networkSpansForwardingThreshold = remoteConfig.network_span_forwarding.pct_enabled;
11
- if (remoteConfig.service_name !== void 0 && remoteConfig.service_name !== "") parsed.serviceName = remoteConfig.service_name;
10
+ if (remoteConfig.networkSpanForwarding !== void 0) parsed.networkSpansForwardingThreshold = remoteConfig.networkSpanForwarding.pctEnabled;
11
+ if (remoteConfig.serviceName !== void 0 && remoteConfig.serviceName !== "") parsed.serviceName = remoteConfig.serviceName;
12
+ if (remoteConfig.emptySessionAvoidanceEnabledPct !== void 0) parsed.emptySessionAvoidanceEnabledPct = remoteConfig.emptySessionAvoidanceEnabledPct;
13
+ if (remoteConfig.sessionReplay !== void 0) parsed.replay = { ...remoteConfig.sessionReplay };
12
14
  return parsed;
13
15
  };
14
16
  var MXLDynamicConfigManager = class {
@@ -19,14 +21,14 @@ var MXLDynamicConfigManager = class {
19
21
  _baseConfig;
20
22
  _sdkConfig;
21
23
  _etag = null;
22
- /** Non-empty `service_name` from the last persisted or fetched remote payload (if any). */
24
+ /** Non-empty `serviceName` from the last persisted or fetched remote payload (if any). */
23
25
  _remoteSourceServiceName;
24
- constructor({ appID, appVersion, deviceId, diag: diagParam = _opentelemetry_api.diag.createComponentLogger({ namespace: "mxl-config-manager" }), storage = window.localStorage, defaultConfig = {}, mxlConfigURL } = {}) {
26
+ constructor({ appID, appVersion, deviceId, diag: diagParam = _opentelemetry_api.diag.createComponentLogger({ namespace: "mxl-config-manager" }), storage = window.localStorage, defaultConfig = {}, apiURL } = {}) {
25
27
  if (appID && appVersion && deviceId) this._remoteConfigURL = require_managers_MXLConfigManager_utils.getConfigURL(appID, {
26
28
  appVersion,
27
29
  deviceId,
28
30
  osVersion: "1"
29
- }, mxlConfigURL);
31
+ }, apiURL);
30
32
  this._diag = diagParam;
31
33
  this._storage = storage;
32
34
  const storedRemoteConfig = this._getRemoteConfigFromStorage();
@@ -53,7 +55,7 @@ var MXLDynamicConfigManager = class {
53
55
  return this._sdkConfig;
54
56
  }
55
57
  /**
56
- * OpenTelemetry `service.name`: remote `service_name` wins, then explicit init `serviceName`,
58
+ * OpenTelemetry `service.name`: remote `serviceName` wins, then explicit init `serviceName`,
57
59
  * then bootstrap {@link DynamicSDKConfig.serviceName}, then `unknown_service`.
58
60
  */
59
61
  resolveApplicationServiceName(initServiceName) {
@@ -66,8 +68,8 @@ var MXLDynamicConfigManager = class {
66
68
  return require_resources_webSdkResource.OTEL_DEFAULT_SERVICE_NAME;
67
69
  }
68
70
  _captureRemoteServiceName(raw) {
69
- if (raw.service_name === void 0) return;
70
- const sn = raw.service_name.trim();
71
+ if (raw.serviceName === void 0) return;
72
+ const sn = raw.serviceName.trim();
71
73
  this._remoteSourceServiceName = sn.length > 0 ? sn : void 0;
72
74
  }
73
75
  async refreshRemoteConfig() {
@@ -96,7 +98,13 @@ var MXLDynamicConfigManager = class {
96
98
  _getRemoteConfigFromStorage() {
97
99
  try {
98
100
  const configString = this._storage.getItem(require_managers_MXLConfigManager_constants.LOCAL_STORAGE_REMOTE_CONFIG_KEY);
99
- if (configString) return JSON.parse(configString);
101
+ if (configString) {
102
+ const stored = JSON.parse(configString);
103
+ return {
104
+ config: require_managers_MXLConfigManager_utils.normalizeStoredRemoteConfig(stored.config),
105
+ etag: stored.etag
106
+ };
107
+ }
100
108
  return null;
101
109
  } catch (error) {
102
110
  this._diag.warn(`Failed to parse remote config from storage: ${error instanceof Error ? error.message : String(error)}`);
@@ -111,7 +119,7 @@ var MXLDynamicConfigManager = class {
111
119
  this._diag.warn(`Failed to fetch remote config from ${url}: ${response.statusText}`);
112
120
  return null;
113
121
  }
114
- return [await response.json(), etag];
122
+ return [require_managers_MXLConfigManager_utils.normalizeStoredRemoteConfig(await response.json()), etag];
115
123
  }
116
124
  };
117
125
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"MXLDynamicConfigManager.cjs","names":["diag","getConfigURL","DEFAULT_CONFIG","OTEL_DEFAULT_SERVICE_NAME","LOCAL_STORAGE_REMOTE_CONFIG_KEY"],"sources":["../../../src/managers/MXLConfigManager/MXLDynamicConfigManager.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport { diag } from '@opentelemetry/api';\nimport { OTEL_DEFAULT_SERVICE_NAME } from '../../resources/webSdkResource';\nimport type { DynamicConfigManager, DynamicSDKConfig } from '../../sdk/types';\nimport { DEFAULT_CONFIG, LOCAL_STORAGE_REMOTE_CONFIG_KEY } from './constants';\nimport type {\n MXLDynamicConfigManagerArgs,\n RemoteConfig,\n StoredRemoteConfig,\n} from './types';\nimport { getConfigURL } from './utils';\n\nconst parseRemoteConfig = (remoteConfig: RemoteConfig): DynamicSDKConfig => {\n const parsed: DynamicSDKConfig = {\n samplingPct: remoteConfig.threshold,\n };\n\n if (remoteConfig.network_span_forwarding !== undefined) {\n parsed.networkSpansForwardingThreshold =\n remoteConfig.network_span_forwarding.pct_enabled;\n }\n\n if (\n remoteConfig.service_name !== undefined &&\n remoteConfig.service_name !== ''\n ) {\n parsed.serviceName = remoteConfig.service_name;\n }\n\n return parsed;\n};\n\nexport class MXLDynamicConfigManager implements DynamicConfigManager {\n // Set to null if appID is not provided, in that case only rely on local config\n private readonly _remoteConfigURL: string | null = null;\n private readonly _diag: DiagLogger;\n private readonly _storage: Storage;\n /** Defaults + user's `dynamicSDKConfig` / init-time merge; survives remote refresh merges. */\n private readonly _baseConfig: DynamicSDKConfig;\n\n private _sdkConfig: DynamicSDKConfig;\n private _etag: string | null = null;\n /** Non-empty `service_name` from the last persisted or fetched remote payload (if any). */\n private _remoteSourceServiceName: string | undefined;\n\n public constructor({\n appID,\n appVersion,\n deviceId,\n diag: diagParam = diag.createComponentLogger({\n namespace: 'mxl-config-manager',\n }),\n storage = window.localStorage,\n defaultConfig = {},\n mxlConfigURL,\n }: MXLDynamicConfigManagerArgs = {}) {\n if (appID && appVersion && deviceId) {\n this._remoteConfigURL = getConfigURL(\n appID,\n {\n appVersion,\n deviceId,\n // TODO: Replace with actual OS version once we start capturing it\n osVersion: '1',\n },\n mxlConfigURL,\n );\n }\n\n this._diag = diagParam;\n this._storage = storage;\n\n const storedRemoteConfig = this._getRemoteConfigFromStorage();\n\n if (storedRemoteConfig) {\n this._etag = storedRemoteConfig.etag;\n this._captureRemoteServiceName(storedRemoteConfig.config);\n }\n\n // Default config merged with any user-provided defaults; user-provided values take precedence.\n // Kept around so refreshRemoteConfig can re-merge against it instead of dropping defaults.\n this._baseConfig = {\n ...DEFAULT_CONFIG,\n ...defaultConfig,\n };\n\n this._sdkConfig = {\n ...this._baseConfig,\n // Stored remote config values will override both defaults and user-provided defaults\n ...(storedRemoteConfig\n ? parseRemoteConfig(storedRemoteConfig.config)\n : {}),\n };\n }\n\n public setConfig(config: Partial<DynamicSDKConfig>): void {\n this._sdkConfig = {\n ...this._sdkConfig,\n ...config,\n };\n }\n\n public getConfig(): DynamicSDKConfig {\n return this._sdkConfig;\n }\n\n /**\n * OpenTelemetry `service.name`: remote `service_name` wins, then explicit init `serviceName`,\n * then bootstrap {@link DynamicSDKConfig.serviceName}, then `unknown_service`.\n */\n public resolveApplicationServiceName(initServiceName?: string): string {\n const remote = this._remoteSourceServiceName?.trim();\n if (remote) {\n return remote;\n }\n const fromInit = initServiceName?.trim();\n if (fromInit) {\n return fromInit;\n }\n const fromBootstrap = this._baseConfig.serviceName?.trim();\n if (fromBootstrap) {\n return fromBootstrap;\n }\n return OTEL_DEFAULT_SERVICE_NAME;\n }\n\n private _captureRemoteServiceName(raw: RemoteConfig): void {\n if (raw.service_name === undefined) {\n return;\n }\n const sn = raw.service_name.trim();\n this._remoteSourceServiceName = sn.length > 0 ? sn : undefined;\n }\n\n // No-op if not sending data to mxl\n public async refreshRemoteConfig(): Promise<void> {\n if (!this._remoteConfigURL) {\n return;\n }\n\n try {\n const remoteConfigResponse = await this._fetchRemoteConfig(\n this._remoteConfigURL,\n );\n\n if (!remoteConfigResponse) {\n this._diag.debug('No changes in remote config, skipping update');\n return;\n }\n\n const [remoteConfig, etag] = remoteConfigResponse;\n this._captureRemoteServiceName(remoteConfig);\n this._storage.setItem(\n LOCAL_STORAGE_REMOTE_CONFIG_KEY,\n JSON.stringify({\n config: remoteConfig,\n etag,\n } as StoredRemoteConfig),\n );\n\n this._sdkConfig = {\n ...this._baseConfig,\n ...parseRemoteConfig(remoteConfig),\n };\n this._etag = etag;\n } catch (error: unknown) {\n this._diag.warn(\n `Failed to refresh remote config: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private _getRemoteConfigFromStorage(): StoredRemoteConfig | null {\n try {\n const configString = this._storage.getItem(\n LOCAL_STORAGE_REMOTE_CONFIG_KEY,\n );\n\n if (configString) {\n return JSON.parse(configString) as StoredRemoteConfig;\n }\n\n return null;\n } catch (error) {\n this._diag.warn(\n `Failed to parse remote config from storage: ${error instanceof Error ? error.message : String(error)}`,\n );\n\n return null;\n }\n }\n\n private async _fetchRemoteConfig(\n url: string,\n ): Promise<[RemoteConfig, string | null] | null> {\n const response = await fetch(url, {\n headers: this._etag ? { 'If-None-Match': this._etag } : {},\n });\n\n const etag = response.headers.get('etag');\n\n // Nothing changed, return null\n if (response.status === 304) {\n return null;\n }\n\n if (!response.ok) {\n this._diag.warn(\n `Failed to fetch remote config from ${url}: ${response.statusText}`,\n );\n\n return null;\n }\n\n const remoteConfig = (await response.json()) as RemoteConfig;\n\n return [remoteConfig, etag];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MXLDynamicConfigManager.cjs","names":["diag","getConfigURL","DEFAULT_CONFIG","OTEL_DEFAULT_SERVICE_NAME","LOCAL_STORAGE_REMOTE_CONFIG_KEY","normalizeStoredRemoteConfig"],"sources":["../../../src/managers/MXLConfigManager/MXLDynamicConfigManager.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport { diag } from '@opentelemetry/api';\nimport { OTEL_DEFAULT_SERVICE_NAME } from '../../resources/webSdkResource';\nimport type { DynamicConfigManager, DynamicSDKConfig } from '../../sdk/types';\nimport { DEFAULT_CONFIG, LOCAL_STORAGE_REMOTE_CONFIG_KEY } from './constants';\nimport type {\n MXLDynamicConfigManagerArgs,\n RemoteConfig,\n StoredRemoteConfig,\n} from './types';\nimport { getConfigURL, normalizeStoredRemoteConfig } from './utils';\n\nconst parseRemoteConfig = (remoteConfig: RemoteConfig): DynamicSDKConfig => {\n const parsed: DynamicSDKConfig = {\n samplingPct: remoteConfig.threshold,\n };\n\n if (remoteConfig.networkSpanForwarding !== undefined) {\n parsed.networkSpansForwardingThreshold =\n remoteConfig.networkSpanForwarding.pctEnabled;\n }\n\n if (\n remoteConfig.serviceName !== undefined &&\n remoteConfig.serviceName !== ''\n ) {\n parsed.serviceName = remoteConfig.serviceName;\n }\n\n if (remoteConfig.emptySessionAvoidanceEnabledPct !== undefined) {\n parsed.emptySessionAvoidanceEnabledPct =\n remoteConfig.emptySessionAvoidanceEnabledPct;\n }\n\n if (remoteConfig.sessionReplay !== undefined) {\n parsed.replay = { ...remoteConfig.sessionReplay };\n }\n\n return parsed;\n};\n\nexport class MXLDynamicConfigManager implements DynamicConfigManager {\n // Set to null if appID is not provided, in that case only rely on local config\n private readonly _remoteConfigURL: string | null = null;\n private readonly _diag: DiagLogger;\n private readonly _storage: Storage;\n /** Defaults + user's `dynamicSDKConfig` / init-time merge; survives remote refresh merges. */\n private readonly _baseConfig: DynamicSDKConfig;\n\n private _sdkConfig: DynamicSDKConfig;\n private _etag: string | null = null;\n /** Non-empty `serviceName` from the last persisted or fetched remote payload (if any). */\n private _remoteSourceServiceName: string | undefined;\n\n public constructor({\n appID,\n appVersion,\n deviceId,\n diag: diagParam = diag.createComponentLogger({\n namespace: 'mxl-config-manager',\n }),\n storage = window.localStorage,\n defaultConfig = {},\n apiURL,\n }: MXLDynamicConfigManagerArgs = {}) {\n if (appID && appVersion && deviceId) {\n this._remoteConfigURL = getConfigURL(\n appID,\n {\n appVersion,\n deviceId,\n // TODO: Replace with actual OS version once we start capturing it\n osVersion: '1',\n },\n apiURL,\n );\n }\n\n this._diag = diagParam;\n this._storage = storage;\n\n const storedRemoteConfig = this._getRemoteConfigFromStorage();\n\n if (storedRemoteConfig) {\n this._etag = storedRemoteConfig.etag;\n this._captureRemoteServiceName(storedRemoteConfig.config);\n }\n\n // Default config merged with any user-provided defaults; user-provided values take precedence.\n // Kept around so refreshRemoteConfig can re-merge against it instead of dropping defaults.\n this._baseConfig = {\n ...DEFAULT_CONFIG,\n ...defaultConfig,\n };\n\n this._sdkConfig = {\n ...this._baseConfig,\n // Stored remote config values will override both defaults and user-provided defaults\n ...(storedRemoteConfig\n ? parseRemoteConfig(storedRemoteConfig.config)\n : {}),\n };\n }\n\n public setConfig(config: Partial<DynamicSDKConfig>): void {\n this._sdkConfig = {\n ...this._sdkConfig,\n ...config,\n };\n }\n\n public getConfig(): DynamicSDKConfig {\n return this._sdkConfig;\n }\n\n /**\n * OpenTelemetry `service.name`: remote `serviceName` wins, then explicit init `serviceName`,\n * then bootstrap {@link DynamicSDKConfig.serviceName}, then `unknown_service`.\n */\n public resolveApplicationServiceName(initServiceName?: string): string {\n const remote = this._remoteSourceServiceName?.trim();\n if (remote) {\n return remote;\n }\n const fromInit = initServiceName?.trim();\n if (fromInit) {\n return fromInit;\n }\n const fromBootstrap = this._baseConfig.serviceName?.trim();\n if (fromBootstrap) {\n return fromBootstrap;\n }\n return OTEL_DEFAULT_SERVICE_NAME;\n }\n\n private _captureRemoteServiceName(raw: RemoteConfig): void {\n if (raw.serviceName === undefined) {\n return;\n }\n const sn = raw.serviceName.trim();\n this._remoteSourceServiceName = sn.length > 0 ? sn : undefined;\n }\n\n // No-op if not sending data to mxl\n public async refreshRemoteConfig(): Promise<void> {\n if (!this._remoteConfigURL) {\n return;\n }\n\n try {\n const remoteConfigResponse = await this._fetchRemoteConfig(\n this._remoteConfigURL,\n );\n\n if (!remoteConfigResponse) {\n this._diag.debug('No changes in remote config, skipping update');\n return;\n }\n\n const [remoteConfig, etag] = remoteConfigResponse;\n this._captureRemoteServiceName(remoteConfig);\n this._storage.setItem(\n LOCAL_STORAGE_REMOTE_CONFIG_KEY,\n JSON.stringify({\n config: remoteConfig,\n etag,\n } as StoredRemoteConfig),\n );\n\n this._sdkConfig = {\n ...this._baseConfig,\n ...parseRemoteConfig(remoteConfig),\n };\n this._etag = etag;\n } catch (error: unknown) {\n this._diag.warn(\n `Failed to refresh remote config: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private _getRemoteConfigFromStorage(): StoredRemoteConfig | null {\n try {\n const configString = this._storage.getItem(\n LOCAL_STORAGE_REMOTE_CONFIG_KEY,\n );\n\n if (configString) {\n const stored = JSON.parse(configString) as {\n config: unknown;\n etag: string | null;\n };\n\n return {\n config: normalizeStoredRemoteConfig(stored.config),\n etag: stored.etag,\n };\n }\n\n return null;\n } catch (error) {\n this._diag.warn(\n `Failed to parse remote config from storage: ${error instanceof Error ? error.message : String(error)}`,\n );\n\n return null;\n }\n }\n\n private async _fetchRemoteConfig(\n url: string,\n ): Promise<[RemoteConfig, string | null] | null> {\n const response = await fetch(url, {\n headers: this._etag ? { 'If-None-Match': this._etag } : {},\n });\n\n const etag = response.headers.get('etag');\n\n // Nothing changed, return null\n if (response.status === 304) {\n return null;\n }\n\n if (!response.ok) {\n this._diag.warn(\n `Failed to fetch remote config from ${url}: ${response.statusText}`,\n );\n\n return null;\n }\n\n const remoteConfig = normalizeStoredRemoteConfig(await response.json());\n\n return [remoteConfig, etag];\n }\n}\n"],"mappings":";;;;;;;AAYA,MAAM,qBAAqB,iBAAiD;CAC1E,MAAM,SAA2B,EAC/B,aAAa,aAAa,WAC3B;AAED,KAAI,aAAa,0BAA0B,KAAA,EACzC,QAAO,kCACL,aAAa,sBAAsB;AAGvC,KACE,aAAa,gBAAgB,KAAA,KAC7B,aAAa,gBAAgB,GAE7B,QAAO,cAAc,aAAa;AAGpC,KAAI,aAAa,oCAAoC,KAAA,EACnD,QAAO,kCACL,aAAa;AAGjB,KAAI,aAAa,kBAAkB,KAAA,EACjC,QAAO,SAAS,EAAE,GAAG,aAAa,eAAe;AAGnD,QAAO;;AAGT,IAAa,0BAAb,MAAqE;CAEnE,mBAAmD;CACnD;CACA;;CAEA;CAEA;CACA,QAA+B;;CAE/B;CAEA,YAAmB,EACjB,OACA,YACA,UACA,MAAM,YAAYA,mBAAAA,KAAK,sBAAsB,EAC3C,WAAW,sBACZ,CAAC,EACF,UAAU,OAAO,cACjB,gBAAgB,EAAE,EAClB,WAC+B,EAAE,EAAE;AACnC,MAAI,SAAS,cAAc,SACzB,MAAK,mBAAmBC,wCAAAA,aACtB,OACA;GACE;GACA;GAEA,WAAW;GACZ,EACD,OACD;AAGH,OAAK,QAAQ;AACb,OAAK,WAAW;EAEhB,MAAM,qBAAqB,KAAK,6BAA6B;AAE7D,MAAI,oBAAoB;AACtB,QAAK,QAAQ,mBAAmB;AAChC,QAAK,0BAA0B,mBAAmB,OAAO;;AAK3D,OAAK,cAAc;GACjB,GAAGC,4CAAAA;GACH,GAAG;GACJ;AAED,OAAK,aAAa;GAChB,GAAG,KAAK;GAER,GAAI,qBACA,kBAAkB,mBAAmB,OAAO,GAC5C,EAAE;GACP;;CAGH,UAAiB,QAAyC;AACxD,OAAK,aAAa;GAChB,GAAG,KAAK;GACR,GAAG;GACJ;;CAGH,YAAqC;AACnC,SAAO,KAAK;;;;;;CAOd,8BAAqC,iBAAkC;EACrE,MAAM,SAAS,KAAK,0BAA0B,MAAM;AACpD,MAAI,OACF,QAAO;EAET,MAAM,WAAW,iBAAiB,MAAM;AACxC,MAAI,SACF,QAAO;EAET,MAAM,gBAAgB,KAAK,YAAY,aAAa,MAAM;AAC1D,MAAI,cACF,QAAO;AAET,SAAOC,iCAAAA;;CAGT,0BAAkC,KAAyB;AACzD,MAAI,IAAI,gBAAgB,KAAA,EACtB;EAEF,MAAM,KAAK,IAAI,YAAY,MAAM;AACjC,OAAK,2BAA2B,GAAG,SAAS,IAAI,KAAK,KAAA;;CAIvD,MAAa,sBAAqC;AAChD,MAAI,CAAC,KAAK,iBACR;AAGF,MAAI;GACF,MAAM,uBAAuB,MAAM,KAAK,mBACtC,KAAK,iBACN;AAED,OAAI,CAAC,sBAAsB;AACzB,SAAK,MAAM,MAAM,+CAA+C;AAChE;;GAGF,MAAM,CAAC,cAAc,QAAQ;AAC7B,QAAK,0BAA0B,aAAa;AAC5C,QAAK,SAAS,QACZC,4CAAAA,iCACA,KAAK,UAAU;IACb,QAAQ;IACR;IACD,CAAuB,CACzB;AAED,QAAK,aAAa;IAChB,GAAG,KAAK;IACR,GAAG,kBAAkB,aAAa;IACnC;AACD,QAAK,QAAQ;WACN,OAAgB;AACvB,QAAK,MAAM,KACT,oCAAoC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAC3F;;;CAIL,8BAAiE;AAC/D,MAAI;GACF,MAAM,eAAe,KAAK,SAAS,QACjCA,4CAAAA,gCACD;AAED,OAAI,cAAc;IAChB,MAAM,SAAS,KAAK,MAAM,aAAa;AAKvC,WAAO;KACL,QAAQC,wCAAAA,4BAA4B,OAAO,OAAO;KAClD,MAAM,OAAO;KACd;;AAGH,UAAO;WACA,OAAO;AACd,QAAK,MAAM,KACT,+CAA+C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACtG;AAED,UAAO;;;CAIX,MAAc,mBACZ,KAC+C;EAC/C,MAAM,WAAW,MAAM,MAAM,KAAK,EAChC,SAAS,KAAK,QAAQ,EAAE,iBAAiB,KAAK,OAAO,GAAG,EAAE,EAC3D,CAAC;EAEF,MAAM,OAAO,SAAS,QAAQ,IAAI,OAAO;AAGzC,MAAI,SAAS,WAAW,IACtB,QAAO;AAGT,MAAI,CAAC,SAAS,IAAI;AAChB,QAAK,MAAM,KACT,sCAAsC,IAAI,IAAI,SAAS,aACxD;AAED,UAAO;;AAKT,SAAO,CAFcA,wCAAAA,4BAA4B,MAAM,SAAS,MAAM,CAElD,EAAE,KAAK"}
@@ -10,7 +10,7 @@ declare class MXLDynamicConfigManager implements DynamicConfigManager {
10
10
  private readonly _baseConfig;
11
11
  private _sdkConfig;
12
12
  private _etag;
13
- /** Non-empty `service_name` from the last persisted or fetched remote payload (if any). */
13
+ /** Non-empty `serviceName` from the last persisted or fetched remote payload (if any). */
14
14
  private _remoteSourceServiceName;
15
15
  constructor({
16
16
  appID,
@@ -19,12 +19,12 @@ declare class MXLDynamicConfigManager implements DynamicConfigManager {
19
19
  diag: diagParam,
20
20
  storage,
21
21
  defaultConfig,
22
- mxlConfigURL
22
+ apiURL
23
23
  }?: MXLDynamicConfigManagerArgs);
24
24
  setConfig(config: Partial<DynamicSDKConfig>): void;
25
25
  getConfig(): DynamicSDKConfig;
26
26
  /**
27
- * OpenTelemetry `service.name`: remote `service_name` wins, then explicit init `serviceName`,
27
+ * OpenTelemetry `service.name`: remote `serviceName` wins, then explicit init `serviceName`,
28
28
  * then bootstrap {@link DynamicSDKConfig.serviceName}, then `unknown_service`.
29
29
  */
30
30
  resolveApplicationServiceName(initServiceName?: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"MXLDynamicConfigManager.d.cts","names":[],"sources":["../../../src/managers/MXLConfigManager/MXLDynamicConfigManager.ts"],"mappings":";;;;cAgCa,uBAAA,YAAmC,oBAAA;EAAA,iBAE7B,gBAAA;EAAA,iBACA,KAAA;EAAA,iBACA,QAAA;;mBAEA,WAAA;EAAA,QAET,UAAA;EAAA,QACA,KAAA;EAQA;EAAA,QANA,wBAAA;;IAGN,KAAA;IACA,UAAA;IACA,QAAA;IACA,IAAA,EAAM,SAAA;IAGN,OAAA;IACA,aAAA;IACA;EAAA,IACC,2BAAA;EAwCI,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,gBAAA;EAO1B,SAAA,CAAA,GAAa,gBAAA;EAPa;;;;EAe1B,6BAAA,CAA8B,eAAA;EAAA,QAgB7B,yBAAA;EASK,mBAAA,CAAA,GAAuB,OAAA;EAAA,QAqC5B,2BAAA;EAAA,QAoBM,kBAAA;AAAA"}
1
+ {"version":3,"file":"MXLDynamicConfigManager.d.cts","names":[],"sources":["../../../src/managers/MXLConfigManager/MXLDynamicConfigManager.ts"],"mappings":";;;;cAyCa,uBAAA,YAAmC,oBAAA;EAAA,iBAE7B,gBAAA;EAAA,iBACA,KAAA;EAAA,iBACA,QAAA;;mBAEA,WAAA;EAAA,QAET,UAAA;EAAA,QACA,KAAA;EAQA;EAAA,QANA,wBAAA;;IAGN,KAAA;IACA,UAAA;IACA,QAAA;IACA,IAAA,EAAM,SAAA;IAGN,OAAA;IACA,aAAA;IACA;EAAA,IACC,2BAAA;EAwCI,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,gBAAA;EAO1B,SAAA,CAAA,GAAa,gBAAA;EAPa;;;;EAe1B,6BAAA,CAA8B,eAAA;EAAA,QAgB7B,yBAAA;EASK,mBAAA,CAAA,GAAuB,OAAA;EAAA,QAqC5B,2BAAA;EAAA,QA4BM,kBAAA;AAAA"}
@@ -10,7 +10,7 @@ declare class MXLDynamicConfigManager implements DynamicConfigManager {
10
10
  private readonly _baseConfig;
11
11
  private _sdkConfig;
12
12
  private _etag;
13
- /** Non-empty `service_name` from the last persisted or fetched remote payload (if any). */
13
+ /** Non-empty `serviceName` from the last persisted or fetched remote payload (if any). */
14
14
  private _remoteSourceServiceName;
15
15
  constructor({
16
16
  appID,
@@ -19,12 +19,12 @@ declare class MXLDynamicConfigManager implements DynamicConfigManager {
19
19
  diag: diagParam,
20
20
  storage,
21
21
  defaultConfig,
22
- mxlConfigURL
22
+ apiURL
23
23
  }?: MXLDynamicConfigManagerArgs);
24
24
  setConfig(config: Partial<DynamicSDKConfig>): void;
25
25
  getConfig(): DynamicSDKConfig;
26
26
  /**
27
- * OpenTelemetry `service.name`: remote `service_name` wins, then explicit init `serviceName`,
27
+ * OpenTelemetry `service.name`: remote `serviceName` wins, then explicit init `serviceName`,
28
28
  * then bootstrap {@link DynamicSDKConfig.serviceName}, then `unknown_service`.
29
29
  */
30
30
  resolveApplicationServiceName(initServiceName?: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"MXLDynamicConfigManager.d.ts","names":[],"sources":["../../../src/managers/MXLConfigManager/MXLDynamicConfigManager.ts"],"mappings":";;;;cAgCa,uBAAA,YAAmC,oBAAA;EAAA,iBAE7B,gBAAA;EAAA,iBACA,KAAA;EAAA,iBACA,QAAA;;mBAEA,WAAA;EAAA,QAET,UAAA;EAAA,QACA,KAAA;EAQA;EAAA,QANA,wBAAA;;IAGN,KAAA;IACA,UAAA;IACA,QAAA;IACA,IAAA,EAAM,SAAA;IAGN,OAAA;IACA,aAAA;IACA;EAAA,IACC,2BAAA;EAwCI,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,gBAAA;EAO1B,SAAA,CAAA,GAAa,gBAAA;EAPa;;;;EAe1B,6BAAA,CAA8B,eAAA;EAAA,QAgB7B,yBAAA;EASK,mBAAA,CAAA,GAAuB,OAAA;EAAA,QAqC5B,2BAAA;EAAA,QAoBM,kBAAA;AAAA"}
1
+ {"version":3,"file":"MXLDynamicConfigManager.d.ts","names":[],"sources":["../../../src/managers/MXLConfigManager/MXLDynamicConfigManager.ts"],"mappings":";;;;cAyCa,uBAAA,YAAmC,oBAAA;EAAA,iBAE7B,gBAAA;EAAA,iBACA,KAAA;EAAA,iBACA,QAAA;;mBAEA,WAAA;EAAA,QAET,UAAA;EAAA,QACA,KAAA;EAQA;EAAA,QANA,wBAAA;;IAGN,KAAA;IACA,UAAA;IACA,QAAA;IACA,IAAA,EAAM,SAAA;IAGN,OAAA;IACA,aAAA;IACA;EAAA,IACC,2BAAA;EAwCI,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,gBAAA;EAO1B,SAAA,CAAA,GAAa,gBAAA;EAPa;;;;EAe1B,6BAAA,CAA8B,eAAA;EAAA,QAgB7B,yBAAA;EASK,mBAAA,CAAA,GAAuB,OAAA;EAAA,QAqC5B,2BAAA;EAAA,QA4BM,kBAAA;AAAA"}
@@ -1,12 +1,14 @@
1
+ import { getConfigURL, normalizeStoredRemoteConfig } from "./utils.js";
1
2
  import { OTEL_DEFAULT_SERVICE_NAME } from "../../resources/webSdkResource.js";
2
3
  import { DEFAULT_CONFIG, LOCAL_STORAGE_REMOTE_CONFIG_KEY } from "./constants.js";
3
- import { getConfigURL } from "./utils.js";
4
4
  import { diag } from "@opentelemetry/api";
5
5
  //#region src/managers/MXLConfigManager/MXLDynamicConfigManager.ts
6
6
  const parseRemoteConfig = (remoteConfig) => {
7
7
  const parsed = { samplingPct: remoteConfig.threshold };
8
- if (remoteConfig.network_span_forwarding !== void 0) parsed.networkSpansForwardingThreshold = remoteConfig.network_span_forwarding.pct_enabled;
9
- if (remoteConfig.service_name !== void 0 && remoteConfig.service_name !== "") parsed.serviceName = remoteConfig.service_name;
8
+ if (remoteConfig.networkSpanForwarding !== void 0) parsed.networkSpansForwardingThreshold = remoteConfig.networkSpanForwarding.pctEnabled;
9
+ if (remoteConfig.serviceName !== void 0 && remoteConfig.serviceName !== "") parsed.serviceName = remoteConfig.serviceName;
10
+ if (remoteConfig.emptySessionAvoidanceEnabledPct !== void 0) parsed.emptySessionAvoidanceEnabledPct = remoteConfig.emptySessionAvoidanceEnabledPct;
11
+ if (remoteConfig.sessionReplay !== void 0) parsed.replay = { ...remoteConfig.sessionReplay };
10
12
  return parsed;
11
13
  };
12
14
  var MXLDynamicConfigManager = class {
@@ -17,14 +19,14 @@ var MXLDynamicConfigManager = class {
17
19
  _baseConfig;
18
20
  _sdkConfig;
19
21
  _etag = null;
20
- /** Non-empty `service_name` from the last persisted or fetched remote payload (if any). */
22
+ /** Non-empty `serviceName` from the last persisted or fetched remote payload (if any). */
21
23
  _remoteSourceServiceName;
22
- constructor({ appID, appVersion, deviceId, diag: diagParam = diag.createComponentLogger({ namespace: "mxl-config-manager" }), storage = window.localStorage, defaultConfig = {}, mxlConfigURL } = {}) {
24
+ constructor({ appID, appVersion, deviceId, diag: diagParam = diag.createComponentLogger({ namespace: "mxl-config-manager" }), storage = window.localStorage, defaultConfig = {}, apiURL } = {}) {
23
25
  if (appID && appVersion && deviceId) this._remoteConfigURL = getConfigURL(appID, {
24
26
  appVersion,
25
27
  deviceId,
26
28
  osVersion: "1"
27
- }, mxlConfigURL);
29
+ }, apiURL);
28
30
  this._diag = diagParam;
29
31
  this._storage = storage;
30
32
  const storedRemoteConfig = this._getRemoteConfigFromStorage();
@@ -51,7 +53,7 @@ var MXLDynamicConfigManager = class {
51
53
  return this._sdkConfig;
52
54
  }
53
55
  /**
54
- * OpenTelemetry `service.name`: remote `service_name` wins, then explicit init `serviceName`,
56
+ * OpenTelemetry `service.name`: remote `serviceName` wins, then explicit init `serviceName`,
55
57
  * then bootstrap {@link DynamicSDKConfig.serviceName}, then `unknown_service`.
56
58
  */
57
59
  resolveApplicationServiceName(initServiceName) {
@@ -64,8 +66,8 @@ var MXLDynamicConfigManager = class {
64
66
  return OTEL_DEFAULT_SERVICE_NAME;
65
67
  }
66
68
  _captureRemoteServiceName(raw) {
67
- if (raw.service_name === void 0) return;
68
- const sn = raw.service_name.trim();
69
+ if (raw.serviceName === void 0) return;
70
+ const sn = raw.serviceName.trim();
69
71
  this._remoteSourceServiceName = sn.length > 0 ? sn : void 0;
70
72
  }
71
73
  async refreshRemoteConfig() {
@@ -94,7 +96,13 @@ var MXLDynamicConfigManager = class {
94
96
  _getRemoteConfigFromStorage() {
95
97
  try {
96
98
  const configString = this._storage.getItem(LOCAL_STORAGE_REMOTE_CONFIG_KEY);
97
- if (configString) return JSON.parse(configString);
99
+ if (configString) {
100
+ const stored = JSON.parse(configString);
101
+ return {
102
+ config: normalizeStoredRemoteConfig(stored.config),
103
+ etag: stored.etag
104
+ };
105
+ }
98
106
  return null;
99
107
  } catch (error) {
100
108
  this._diag.warn(`Failed to parse remote config from storage: ${error instanceof Error ? error.message : String(error)}`);
@@ -109,7 +117,7 @@ var MXLDynamicConfigManager = class {
109
117
  this._diag.warn(`Failed to fetch remote config from ${url}: ${response.statusText}`);
110
118
  return null;
111
119
  }
112
- return [await response.json(), etag];
120
+ return [normalizeStoredRemoteConfig(await response.json()), etag];
113
121
  }
114
122
  };
115
123
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"MXLDynamicConfigManager.js","names":[],"sources":["../../../src/managers/MXLConfigManager/MXLDynamicConfigManager.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport { diag } from '@opentelemetry/api';\nimport { OTEL_DEFAULT_SERVICE_NAME } from '../../resources/webSdkResource';\nimport type { DynamicConfigManager, DynamicSDKConfig } from '../../sdk/types';\nimport { DEFAULT_CONFIG, LOCAL_STORAGE_REMOTE_CONFIG_KEY } from './constants';\nimport type {\n MXLDynamicConfigManagerArgs,\n RemoteConfig,\n StoredRemoteConfig,\n} from './types';\nimport { getConfigURL } from './utils';\n\nconst parseRemoteConfig = (remoteConfig: RemoteConfig): DynamicSDKConfig => {\n const parsed: DynamicSDKConfig = {\n samplingPct: remoteConfig.threshold,\n };\n\n if (remoteConfig.network_span_forwarding !== undefined) {\n parsed.networkSpansForwardingThreshold =\n remoteConfig.network_span_forwarding.pct_enabled;\n }\n\n if (\n remoteConfig.service_name !== undefined &&\n remoteConfig.service_name !== ''\n ) {\n parsed.serviceName = remoteConfig.service_name;\n }\n\n return parsed;\n};\n\nexport class MXLDynamicConfigManager implements DynamicConfigManager {\n // Set to null if appID is not provided, in that case only rely on local config\n private readonly _remoteConfigURL: string | null = null;\n private readonly _diag: DiagLogger;\n private readonly _storage: Storage;\n /** Defaults + user's `dynamicSDKConfig` / init-time merge; survives remote refresh merges. */\n private readonly _baseConfig: DynamicSDKConfig;\n\n private _sdkConfig: DynamicSDKConfig;\n private _etag: string | null = null;\n /** Non-empty `service_name` from the last persisted or fetched remote payload (if any). */\n private _remoteSourceServiceName: string | undefined;\n\n public constructor({\n appID,\n appVersion,\n deviceId,\n diag: diagParam = diag.createComponentLogger({\n namespace: 'mxl-config-manager',\n }),\n storage = window.localStorage,\n defaultConfig = {},\n mxlConfigURL,\n }: MXLDynamicConfigManagerArgs = {}) {\n if (appID && appVersion && deviceId) {\n this._remoteConfigURL = getConfigURL(\n appID,\n {\n appVersion,\n deviceId,\n // TODO: Replace with actual OS version once we start capturing it\n osVersion: '1',\n },\n mxlConfigURL,\n );\n }\n\n this._diag = diagParam;\n this._storage = storage;\n\n const storedRemoteConfig = this._getRemoteConfigFromStorage();\n\n if (storedRemoteConfig) {\n this._etag = storedRemoteConfig.etag;\n this._captureRemoteServiceName(storedRemoteConfig.config);\n }\n\n // Default config merged with any user-provided defaults; user-provided values take precedence.\n // Kept around so refreshRemoteConfig can re-merge against it instead of dropping defaults.\n this._baseConfig = {\n ...DEFAULT_CONFIG,\n ...defaultConfig,\n };\n\n this._sdkConfig = {\n ...this._baseConfig,\n // Stored remote config values will override both defaults and user-provided defaults\n ...(storedRemoteConfig\n ? parseRemoteConfig(storedRemoteConfig.config)\n : {}),\n };\n }\n\n public setConfig(config: Partial<DynamicSDKConfig>): void {\n this._sdkConfig = {\n ...this._sdkConfig,\n ...config,\n };\n }\n\n public getConfig(): DynamicSDKConfig {\n return this._sdkConfig;\n }\n\n /**\n * OpenTelemetry `service.name`: remote `service_name` wins, then explicit init `serviceName`,\n * then bootstrap {@link DynamicSDKConfig.serviceName}, then `unknown_service`.\n */\n public resolveApplicationServiceName(initServiceName?: string): string {\n const remote = this._remoteSourceServiceName?.trim();\n if (remote) {\n return remote;\n }\n const fromInit = initServiceName?.trim();\n if (fromInit) {\n return fromInit;\n }\n const fromBootstrap = this._baseConfig.serviceName?.trim();\n if (fromBootstrap) {\n return fromBootstrap;\n }\n return OTEL_DEFAULT_SERVICE_NAME;\n }\n\n private _captureRemoteServiceName(raw: RemoteConfig): void {\n if (raw.service_name === undefined) {\n return;\n }\n const sn = raw.service_name.trim();\n this._remoteSourceServiceName = sn.length > 0 ? sn : undefined;\n }\n\n // No-op if not sending data to mxl\n public async refreshRemoteConfig(): Promise<void> {\n if (!this._remoteConfigURL) {\n return;\n }\n\n try {\n const remoteConfigResponse = await this._fetchRemoteConfig(\n this._remoteConfigURL,\n );\n\n if (!remoteConfigResponse) {\n this._diag.debug('No changes in remote config, skipping update');\n return;\n }\n\n const [remoteConfig, etag] = remoteConfigResponse;\n this._captureRemoteServiceName(remoteConfig);\n this._storage.setItem(\n LOCAL_STORAGE_REMOTE_CONFIG_KEY,\n JSON.stringify({\n config: remoteConfig,\n etag,\n } as StoredRemoteConfig),\n );\n\n this._sdkConfig = {\n ...this._baseConfig,\n ...parseRemoteConfig(remoteConfig),\n };\n this._etag = etag;\n } catch (error: unknown) {\n this._diag.warn(\n `Failed to refresh remote config: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private _getRemoteConfigFromStorage(): StoredRemoteConfig | null {\n try {\n const configString = this._storage.getItem(\n LOCAL_STORAGE_REMOTE_CONFIG_KEY,\n );\n\n if (configString) {\n return JSON.parse(configString) as StoredRemoteConfig;\n }\n\n return null;\n } catch (error) {\n this._diag.warn(\n `Failed to parse remote config from storage: ${error instanceof Error ? error.message : String(error)}`,\n );\n\n return null;\n }\n }\n\n private async _fetchRemoteConfig(\n url: string,\n ): Promise<[RemoteConfig, string | null] | null> {\n const response = await fetch(url, {\n headers: this._etag ? { 'If-None-Match': this._etag } : {},\n });\n\n const etag = response.headers.get('etag');\n\n // Nothing changed, return null\n if (response.status === 304) {\n return null;\n }\n\n if (!response.ok) {\n this._diag.warn(\n `Failed to fetch remote config from ${url}: ${response.statusText}`,\n );\n\n return null;\n }\n\n const remoteConfig = (await response.json()) as RemoteConfig;\n\n return [remoteConfig, etag];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MXLDynamicConfigManager.js","names":[],"sources":["../../../src/managers/MXLConfigManager/MXLDynamicConfigManager.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport { diag } from '@opentelemetry/api';\nimport { OTEL_DEFAULT_SERVICE_NAME } from '../../resources/webSdkResource';\nimport type { DynamicConfigManager, DynamicSDKConfig } from '../../sdk/types';\nimport { DEFAULT_CONFIG, LOCAL_STORAGE_REMOTE_CONFIG_KEY } from './constants';\nimport type {\n MXLDynamicConfigManagerArgs,\n RemoteConfig,\n StoredRemoteConfig,\n} from './types';\nimport { getConfigURL, normalizeStoredRemoteConfig } from './utils';\n\nconst parseRemoteConfig = (remoteConfig: RemoteConfig): DynamicSDKConfig => {\n const parsed: DynamicSDKConfig = {\n samplingPct: remoteConfig.threshold,\n };\n\n if (remoteConfig.networkSpanForwarding !== undefined) {\n parsed.networkSpansForwardingThreshold =\n remoteConfig.networkSpanForwarding.pctEnabled;\n }\n\n if (\n remoteConfig.serviceName !== undefined &&\n remoteConfig.serviceName !== ''\n ) {\n parsed.serviceName = remoteConfig.serviceName;\n }\n\n if (remoteConfig.emptySessionAvoidanceEnabledPct !== undefined) {\n parsed.emptySessionAvoidanceEnabledPct =\n remoteConfig.emptySessionAvoidanceEnabledPct;\n }\n\n if (remoteConfig.sessionReplay !== undefined) {\n parsed.replay = { ...remoteConfig.sessionReplay };\n }\n\n return parsed;\n};\n\nexport class MXLDynamicConfigManager implements DynamicConfigManager {\n // Set to null if appID is not provided, in that case only rely on local config\n private readonly _remoteConfigURL: string | null = null;\n private readonly _diag: DiagLogger;\n private readonly _storage: Storage;\n /** Defaults + user's `dynamicSDKConfig` / init-time merge; survives remote refresh merges. */\n private readonly _baseConfig: DynamicSDKConfig;\n\n private _sdkConfig: DynamicSDKConfig;\n private _etag: string | null = null;\n /** Non-empty `serviceName` from the last persisted or fetched remote payload (if any). */\n private _remoteSourceServiceName: string | undefined;\n\n public constructor({\n appID,\n appVersion,\n deviceId,\n diag: diagParam = diag.createComponentLogger({\n namespace: 'mxl-config-manager',\n }),\n storage = window.localStorage,\n defaultConfig = {},\n apiURL,\n }: MXLDynamicConfigManagerArgs = {}) {\n if (appID && appVersion && deviceId) {\n this._remoteConfigURL = getConfigURL(\n appID,\n {\n appVersion,\n deviceId,\n // TODO: Replace with actual OS version once we start capturing it\n osVersion: '1',\n },\n apiURL,\n );\n }\n\n this._diag = diagParam;\n this._storage = storage;\n\n const storedRemoteConfig = this._getRemoteConfigFromStorage();\n\n if (storedRemoteConfig) {\n this._etag = storedRemoteConfig.etag;\n this._captureRemoteServiceName(storedRemoteConfig.config);\n }\n\n // Default config merged with any user-provided defaults; user-provided values take precedence.\n // Kept around so refreshRemoteConfig can re-merge against it instead of dropping defaults.\n this._baseConfig = {\n ...DEFAULT_CONFIG,\n ...defaultConfig,\n };\n\n this._sdkConfig = {\n ...this._baseConfig,\n // Stored remote config values will override both defaults and user-provided defaults\n ...(storedRemoteConfig\n ? parseRemoteConfig(storedRemoteConfig.config)\n : {}),\n };\n }\n\n public setConfig(config: Partial<DynamicSDKConfig>): void {\n this._sdkConfig = {\n ...this._sdkConfig,\n ...config,\n };\n }\n\n public getConfig(): DynamicSDKConfig {\n return this._sdkConfig;\n }\n\n /**\n * OpenTelemetry `service.name`: remote `serviceName` wins, then explicit init `serviceName`,\n * then bootstrap {@link DynamicSDKConfig.serviceName}, then `unknown_service`.\n */\n public resolveApplicationServiceName(initServiceName?: string): string {\n const remote = this._remoteSourceServiceName?.trim();\n if (remote) {\n return remote;\n }\n const fromInit = initServiceName?.trim();\n if (fromInit) {\n return fromInit;\n }\n const fromBootstrap = this._baseConfig.serviceName?.trim();\n if (fromBootstrap) {\n return fromBootstrap;\n }\n return OTEL_DEFAULT_SERVICE_NAME;\n }\n\n private _captureRemoteServiceName(raw: RemoteConfig): void {\n if (raw.serviceName === undefined) {\n return;\n }\n const sn = raw.serviceName.trim();\n this._remoteSourceServiceName = sn.length > 0 ? sn : undefined;\n }\n\n // No-op if not sending data to mxl\n public async refreshRemoteConfig(): Promise<void> {\n if (!this._remoteConfigURL) {\n return;\n }\n\n try {\n const remoteConfigResponse = await this._fetchRemoteConfig(\n this._remoteConfigURL,\n );\n\n if (!remoteConfigResponse) {\n this._diag.debug('No changes in remote config, skipping update');\n return;\n }\n\n const [remoteConfig, etag] = remoteConfigResponse;\n this._captureRemoteServiceName(remoteConfig);\n this._storage.setItem(\n LOCAL_STORAGE_REMOTE_CONFIG_KEY,\n JSON.stringify({\n config: remoteConfig,\n etag,\n } as StoredRemoteConfig),\n );\n\n this._sdkConfig = {\n ...this._baseConfig,\n ...parseRemoteConfig(remoteConfig),\n };\n this._etag = etag;\n } catch (error: unknown) {\n this._diag.warn(\n `Failed to refresh remote config: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private _getRemoteConfigFromStorage(): StoredRemoteConfig | null {\n try {\n const configString = this._storage.getItem(\n LOCAL_STORAGE_REMOTE_CONFIG_KEY,\n );\n\n if (configString) {\n const stored = JSON.parse(configString) as {\n config: unknown;\n etag: string | null;\n };\n\n return {\n config: normalizeStoredRemoteConfig(stored.config),\n etag: stored.etag,\n };\n }\n\n return null;\n } catch (error) {\n this._diag.warn(\n `Failed to parse remote config from storage: ${error instanceof Error ? error.message : String(error)}`,\n );\n\n return null;\n }\n }\n\n private async _fetchRemoteConfig(\n url: string,\n ): Promise<[RemoteConfig, string | null] | null> {\n const response = await fetch(url, {\n headers: this._etag ? { 'If-None-Match': this._etag } : {},\n });\n\n const etag = response.headers.get('etag');\n\n // Nothing changed, return null\n if (response.status === 304) {\n return null;\n }\n\n if (!response.ok) {\n this._diag.warn(\n `Failed to fetch remote config from ${url}: ${response.statusText}`,\n );\n\n return null;\n }\n\n const remoteConfig = normalizeStoredRemoteConfig(await response.json());\n\n return [remoteConfig, etag];\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/managers/MXLConfigManager/resolveEffectiveReplayConfig.ts
3
+ function resolveEffectiveReplayConfig({ recordUserSessions, replay, dynamicConfig, isSessionReplayEnabled }) {
4
+ if (!isSessionReplayEnabled) return {
5
+ recordUserSessions: false,
6
+ replay
7
+ };
8
+ const remoteReplay = dynamicConfig.replay;
9
+ if (!remoteReplay) return {
10
+ recordUserSessions,
11
+ replay
12
+ };
13
+ const merged = { ...replay };
14
+ if (remoteReplay.sampleRate !== void 0) merged.sampleRate = remoteReplay.sampleRate;
15
+ if (remoteReplay.maskAllInputs !== void 0) merged.maskAllInputs = remoteReplay.maskAllInputs;
16
+ if (remoteReplay.maskAllText !== void 0) merged.maskAllText = remoteReplay.maskAllText;
17
+ if (remoteReplay.flushIntervalMs !== void 0) merged.flushIntervalMs = remoteReplay.flushIntervalMs;
18
+ if (remoteReplay.omitRedundantInstrumentations !== void 0) merged.omitRedundantInstrumentations = remoteReplay.omitRedundantInstrumentations;
19
+ if (remoteReplay.debug !== void 0) merged.debug = remoteReplay.debug;
20
+ return {
21
+ recordUserSessions,
22
+ replay: merged
23
+ };
24
+ }
25
+ //#endregion
26
+ exports.resolveEffectiveReplayConfig = resolveEffectiveReplayConfig;
27
+
28
+ //# sourceMappingURL=resolveEffectiveReplayConfig.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveEffectiveReplayConfig.cjs","names":[],"sources":["../../../src/managers/MXLConfigManager/resolveEffectiveReplayConfig.ts"],"sourcesContent":["import type { ReplayUserConfig } from '../../instrumentations/replay/ReplayInstrumentation/types';\nimport type { DynamicSDKConfig } from '../../sdk/types';\n\nexport interface ResolveEffectiveReplayConfigArgs {\n recordUserSessions: boolean;\n replay?: ReplayUserConfig;\n dynamicConfig: DynamicSDKConfig;\n isSessionReplayEnabled: boolean;\n}\n\nexport interface EffectiveReplayConfig {\n recordUserSessions: boolean;\n replay?: ReplayUserConfig;\n}\n\nexport function resolveEffectiveReplayConfig({\n recordUserSessions,\n replay,\n dynamicConfig,\n isSessionReplayEnabled,\n}: ResolveEffectiveReplayConfigArgs): EffectiveReplayConfig {\n if (!isSessionReplayEnabled) {\n return { recordUserSessions: false, replay };\n }\n\n const remoteReplay = dynamicConfig.replay;\n if (!remoteReplay) {\n return { recordUserSessions, replay };\n }\n\n const merged: ReplayUserConfig = { ...replay };\n\n if (remoteReplay.sampleRate !== undefined) {\n merged.sampleRate = remoteReplay.sampleRate;\n }\n if (remoteReplay.maskAllInputs !== undefined) {\n merged.maskAllInputs = remoteReplay.maskAllInputs;\n }\n if (remoteReplay.maskAllText !== undefined) {\n merged.maskAllText = remoteReplay.maskAllText;\n }\n if (remoteReplay.flushIntervalMs !== undefined) {\n merged.flushIntervalMs = remoteReplay.flushIntervalMs;\n }\n if (remoteReplay.omitRedundantInstrumentations !== undefined) {\n merged.omitRedundantInstrumentations =\n remoteReplay.omitRedundantInstrumentations;\n }\n if (remoteReplay.debug !== undefined) {\n merged.debug = remoteReplay.debug;\n }\n\n return {\n recordUserSessions,\n replay: merged,\n };\n}\n"],"mappings":";;AAeA,SAAgB,6BAA6B,EAC3C,oBACA,QACA,eACA,0BAC0D;AAC1D,KAAI,CAAC,uBACH,QAAO;EAAE,oBAAoB;EAAO;EAAQ;CAG9C,MAAM,eAAe,cAAc;AACnC,KAAI,CAAC,aACH,QAAO;EAAE;EAAoB;EAAQ;CAGvC,MAAM,SAA2B,EAAE,GAAG,QAAQ;AAE9C,KAAI,aAAa,eAAe,KAAA,EAC9B,QAAO,aAAa,aAAa;AAEnC,KAAI,aAAa,kBAAkB,KAAA,EACjC,QAAO,gBAAgB,aAAa;AAEtC,KAAI,aAAa,gBAAgB,KAAA,EAC/B,QAAO,cAAc,aAAa;AAEpC,KAAI,aAAa,oBAAoB,KAAA,EACnC,QAAO,kBAAkB,aAAa;AAExC,KAAI,aAAa,kCAAkC,KAAA,EACjD,QAAO,gCACL,aAAa;AAEjB,KAAI,aAAa,UAAU,KAAA,EACzB,QAAO,QAAQ,aAAa;AAG9B,QAAO;EACL;EACA,QAAQ;EACT"}
@@ -0,0 +1,23 @@
1
+ import { ReplayUserConfig } from "../../instrumentations/replay/ReplayInstrumentation/types.cjs";
2
+ import { DynamicSDKConfig } from "../../sdk/types.cjs";
3
+
4
+ //#region src/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.ts
5
+ interface ResolveEffectiveReplayConfigArgs {
6
+ recordUserSessions: boolean;
7
+ replay?: ReplayUserConfig;
8
+ dynamicConfig: DynamicSDKConfig;
9
+ isSessionReplayEnabled: boolean;
10
+ }
11
+ interface EffectiveReplayConfig {
12
+ recordUserSessions: boolean;
13
+ replay?: ReplayUserConfig;
14
+ }
15
+ declare function resolveEffectiveReplayConfig({
16
+ recordUserSessions,
17
+ replay,
18
+ dynamicConfig,
19
+ isSessionReplayEnabled
20
+ }: ResolveEffectiveReplayConfigArgs): EffectiveReplayConfig;
21
+ //#endregion
22
+ export { EffectiveReplayConfig, ResolveEffectiveReplayConfigArgs, resolveEffectiveReplayConfig };
23
+ //# sourceMappingURL=resolveEffectiveReplayConfig.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveEffectiveReplayConfig.d.cts","names":[],"sources":["../../../src/managers/MXLConfigManager/resolveEffectiveReplayConfig.ts"],"mappings":";;;;UAGiB,gCAAA;EACf,kBAAA;EACA,MAAA,GAAS,gBAAA;EACT,aAAA,EAAe,gBAAA;EACf,sBAAA;AAAA;AAAA,UAGe,qBAAA;EACf,kBAAA;EACA,MAAA,GAAS,gBAAA;AAAA;AAAA,iBAGK,4BAAA,CAAA;EACd,kBAAA;EACA,MAAA;EACA,aAAA;EACA;AAAA,GACC,gCAAA,GAAmC,qBAAA"}
@@ -0,0 +1,23 @@
1
+ import { ReplayUserConfig } from "../../instrumentations/replay/ReplayInstrumentation/types.js";
2
+ import { DynamicSDKConfig } from "../../sdk/types.js";
3
+
4
+ //#region src/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.ts
5
+ interface ResolveEffectiveReplayConfigArgs {
6
+ recordUserSessions: boolean;
7
+ replay?: ReplayUserConfig;
8
+ dynamicConfig: DynamicSDKConfig;
9
+ isSessionReplayEnabled: boolean;
10
+ }
11
+ interface EffectiveReplayConfig {
12
+ recordUserSessions: boolean;
13
+ replay?: ReplayUserConfig;
14
+ }
15
+ declare function resolveEffectiveReplayConfig({
16
+ recordUserSessions,
17
+ replay,
18
+ dynamicConfig,
19
+ isSessionReplayEnabled
20
+ }: ResolveEffectiveReplayConfigArgs): EffectiveReplayConfig;
21
+ //#endregion
22
+ export { EffectiveReplayConfig, ResolveEffectiveReplayConfigArgs, resolveEffectiveReplayConfig };
23
+ //# sourceMappingURL=resolveEffectiveReplayConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveEffectiveReplayConfig.d.ts","names":[],"sources":["../../../src/managers/MXLConfigManager/resolveEffectiveReplayConfig.ts"],"mappings":";;;;UAGiB,gCAAA;EACf,kBAAA;EACA,MAAA,GAAS,gBAAA;EACT,aAAA,EAAe,gBAAA;EACf,sBAAA;AAAA;AAAA,UAGe,qBAAA;EACf,kBAAA;EACA,MAAA,GAAS,gBAAA;AAAA;AAAA,iBAGK,4BAAA,CAAA;EACd,kBAAA;EACA,MAAA;EACA,aAAA;EACA;AAAA,GACC,gCAAA,GAAmC,qBAAA"}
@@ -0,0 +1,27 @@
1
+ //#region src/managers/MXLConfigManager/resolveEffectiveReplayConfig.ts
2
+ function resolveEffectiveReplayConfig({ recordUserSessions, replay, dynamicConfig, isSessionReplayEnabled }) {
3
+ if (!isSessionReplayEnabled) return {
4
+ recordUserSessions: false,
5
+ replay
6
+ };
7
+ const remoteReplay = dynamicConfig.replay;
8
+ if (!remoteReplay) return {
9
+ recordUserSessions,
10
+ replay
11
+ };
12
+ const merged = { ...replay };
13
+ if (remoteReplay.sampleRate !== void 0) merged.sampleRate = remoteReplay.sampleRate;
14
+ if (remoteReplay.maskAllInputs !== void 0) merged.maskAllInputs = remoteReplay.maskAllInputs;
15
+ if (remoteReplay.maskAllText !== void 0) merged.maskAllText = remoteReplay.maskAllText;
16
+ if (remoteReplay.flushIntervalMs !== void 0) merged.flushIntervalMs = remoteReplay.flushIntervalMs;
17
+ if (remoteReplay.omitRedundantInstrumentations !== void 0) merged.omitRedundantInstrumentations = remoteReplay.omitRedundantInstrumentations;
18
+ if (remoteReplay.debug !== void 0) merged.debug = remoteReplay.debug;
19
+ return {
20
+ recordUserSessions,
21
+ replay: merged
22
+ };
23
+ }
24
+ //#endregion
25
+ export { resolveEffectiveReplayConfig };
26
+
27
+ //# sourceMappingURL=resolveEffectiveReplayConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveEffectiveReplayConfig.js","names":[],"sources":["../../../src/managers/MXLConfigManager/resolveEffectiveReplayConfig.ts"],"sourcesContent":["import type { ReplayUserConfig } from '../../instrumentations/replay/ReplayInstrumentation/types';\nimport type { DynamicSDKConfig } from '../../sdk/types';\n\nexport interface ResolveEffectiveReplayConfigArgs {\n recordUserSessions: boolean;\n replay?: ReplayUserConfig;\n dynamicConfig: DynamicSDKConfig;\n isSessionReplayEnabled: boolean;\n}\n\nexport interface EffectiveReplayConfig {\n recordUserSessions: boolean;\n replay?: ReplayUserConfig;\n}\n\nexport function resolveEffectiveReplayConfig({\n recordUserSessions,\n replay,\n dynamicConfig,\n isSessionReplayEnabled,\n}: ResolveEffectiveReplayConfigArgs): EffectiveReplayConfig {\n if (!isSessionReplayEnabled) {\n return { recordUserSessions: false, replay };\n }\n\n const remoteReplay = dynamicConfig.replay;\n if (!remoteReplay) {\n return { recordUserSessions, replay };\n }\n\n const merged: ReplayUserConfig = { ...replay };\n\n if (remoteReplay.sampleRate !== undefined) {\n merged.sampleRate = remoteReplay.sampleRate;\n }\n if (remoteReplay.maskAllInputs !== undefined) {\n merged.maskAllInputs = remoteReplay.maskAllInputs;\n }\n if (remoteReplay.maskAllText !== undefined) {\n merged.maskAllText = remoteReplay.maskAllText;\n }\n if (remoteReplay.flushIntervalMs !== undefined) {\n merged.flushIntervalMs = remoteReplay.flushIntervalMs;\n }\n if (remoteReplay.omitRedundantInstrumentations !== undefined) {\n merged.omitRedundantInstrumentations =\n remoteReplay.omitRedundantInstrumentations;\n }\n if (remoteReplay.debug !== undefined) {\n merged.debug = remoteReplay.debug;\n }\n\n return {\n recordUserSessions,\n replay: merged,\n };\n}\n"],"mappings":";AAeA,SAAgB,6BAA6B,EAC3C,oBACA,QACA,eACA,0BAC0D;AAC1D,KAAI,CAAC,uBACH,QAAO;EAAE,oBAAoB;EAAO;EAAQ;CAG9C,MAAM,eAAe,cAAc;AACnC,KAAI,CAAC,aACH,QAAO;EAAE;EAAoB;EAAQ;CAGvC,MAAM,SAA2B,EAAE,GAAG,QAAQ;AAE9C,KAAI,aAAa,eAAe,KAAA,EAC9B,QAAO,aAAa,aAAa;AAEnC,KAAI,aAAa,kBAAkB,KAAA,EACjC,QAAO,gBAAgB,aAAa;AAEtC,KAAI,aAAa,gBAAgB,KAAA,EAC/B,QAAO,cAAc,aAAa;AAEpC,KAAI,aAAa,oBAAoB,KAAA,EACnC,QAAO,kBAAkB,aAAa;AAExC,KAAI,aAAa,kCAAkC,KAAA,EACjD,QAAO,gCACL,aAAa;AAEjB,KAAI,aAAa,UAAU,KAAA,EACzB,QAAO,QAAQ,aAAa;AAG9B,QAAO;EACL;EACA,QAAQ;EACT"}