@diegotsi/flint-core 1.8.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -177,7 +177,7 @@ interface FlintConfig {
177
177
  environment?: () => EnvironmentInfo;
178
178
  };
179
179
  /** @internal Injected by framework packages to start replay without rrweb in core */
180
- _replayRecorder?: (onEmit: (event: unknown) => void) => Promise<(() => void) | undefined>;
180
+ _replayRecorder?: (onEmit: (event: unknown, isCheckout?: boolean) => void) => Promise<(() => void) | undefined>;
181
181
  }
182
182
  interface CollectedMeta {
183
183
  environment: EnvironmentInfo;
@@ -289,6 +289,36 @@ declare const DATADOG_BLOCKED_HOSTS: string[];
289
289
  * session and returns a deep link to the Session Replay viewer.
290
290
  */
291
291
  declare function createDatadogReplayProvider(site: string): () => string | undefined;
292
+ /**
293
+ * Emits a custom Datadog RUM action at the moment a bug is reported, so it
294
+ * shows up as a clickable marker on the Session Replay timeline — making the
295
+ * report moment easy to find in long sessions.
296
+ *
297
+ * No-op when Datadog RUM (`window.DD_RUM`) is not present on the page.
298
+ */
299
+ declare function trackDatadogBugReported(meta: {
300
+ bugId: string;
301
+ severity?: string;
302
+ url?: string;
303
+ title?: string;
304
+ }): void;
305
+
306
+ /**
307
+ * Rolling buffer for rrweb replay events.
308
+ *
309
+ * rrweb playback requires the event stream to begin with a Meta + FullSnapshot
310
+ * ("checkout"). A naive time-window trim can strip that opening snapshot and
311
+ * leave the player with orphaned incremental mutations it can't render.
312
+ *
313
+ * When the recorder signals checkouts (via `isCheckout`), this buffer trims by
314
+ * *segment* instead of by time: it always retains the current checkout segment
315
+ * plus the previous one, so the buffer never starts mid-stream. Recorders that
316
+ * never signal a checkout fall back to the legacy time-window trim.
317
+ */
318
+ interface ReplayBuffer {
319
+ push(event: unknown, isCheckout?: boolean): void;
320
+ getEvents(): unknown[];
321
+ }
292
322
 
293
323
  interface FlintInstance {
294
324
  config: FlintConfig;
@@ -297,7 +327,7 @@ interface FlintInstance {
297
327
  formErrors: FormErrorCollector | null;
298
328
  frustration: FrustrationCollector | null;
299
329
  errorCapture: ErrorCaptureCollector | null;
300
- replayEvents: unknown[];
330
+ replayBuffer: ReplayBuffer;
301
331
  stopReplay: (() => void) | null;
302
332
  }
303
333
  declare function init(config: FlintConfig): void;
@@ -346,4 +376,4 @@ interface ResolvedTheme {
346
376
  }
347
377
  declare function resolveTheme(theme: Theme): ResolvedTheme;
348
378
 
349
- export { type CollectedMeta, type ConsoleCollector, type ConsoleEntry, DATADOG_BLOCKED_HOSTS, type EnvironmentInfo, type ErrorBreadcrumbs, type ErrorCaptureCollector, type ErrorCaptureOptions, type ErrorEventPayload, Flint, type FlintConfig, type FlintState, type FlintUser, type FlintWidgetProps, type FormErrorCollector, type FormErrorEntry, type FrustrationCollector, type FrustrationEvent, type Locale, type NetworkCollector, type NetworkEntry, type ReportPayload, type ReportResult, type ResolvedTheme, type Severity, type Theme, type ThemeOverride, _setFormErrorCollector, collectEnvironment, createConsoleCollector, createDatadogReplayProvider, createErrorCaptureCollector, createFormErrorCollector, createFrustrationCollector, createNetworkCollector, getSnapshot, resolveTheme, submitReplay, submitReport, subscribe };
379
+ export { type CollectedMeta, type ConsoleCollector, type ConsoleEntry, DATADOG_BLOCKED_HOSTS, type EnvironmentInfo, type ErrorBreadcrumbs, type ErrorCaptureCollector, type ErrorCaptureOptions, type ErrorEventPayload, Flint, type FlintConfig, type FlintState, type FlintUser, type FlintWidgetProps, type FormErrorCollector, type FormErrorEntry, type FrustrationCollector, type FrustrationEvent, type Locale, type NetworkCollector, type NetworkEntry, type ReportPayload, type ReportResult, type ResolvedTheme, type Severity, type Theme, type ThemeOverride, _setFormErrorCollector, collectEnvironment, createConsoleCollector, createDatadogReplayProvider, createErrorCaptureCollector, createFormErrorCollector, createFrustrationCollector, createNetworkCollector, getSnapshot, resolveTheme, submitReplay, submitReport, subscribe, trackDatadogBugReported };
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  DATADOG_BLOCKED_HOSTS,
3
- createDatadogReplayProvider
4
- } from "./chunk-HVSD45YR.js";
3
+ createDatadogReplayProvider,
4
+ trackDatadogBugReported
5
+ } from "./chunk-SO6WYKFF.js";
5
6
 
6
7
  // src/api.ts
7
8
  import { gzipSync } from "fflate";
@@ -1056,6 +1057,34 @@ function createNetworkCollector(extraBlockedHosts = []) {
1056
1057
  };
1057
1058
  }
1058
1059
 
1060
+ // src/replayBuffer.ts
1061
+ function createReplayBuffer(replayBufferMs, now = Date.now) {
1062
+ const events = [];
1063
+ let checkoutSeen = false;
1064
+ let recentCheckoutIdx = 0;
1065
+ return {
1066
+ push(event, isCheckout) {
1067
+ if (isCheckout) {
1068
+ checkoutSeen = true;
1069
+ if (events.length > 0) {
1070
+ events.splice(0, recentCheckoutIdx);
1071
+ recentCheckoutIdx = events.length;
1072
+ }
1073
+ }
1074
+ events.push(event);
1075
+ if (!checkoutSeen) {
1076
+ const cutoff = now() - replayBufferMs;
1077
+ while (events.length > 0 && events[0].timestamp < cutoff) {
1078
+ events.shift();
1079
+ }
1080
+ }
1081
+ },
1082
+ getEvents() {
1083
+ return [...events];
1084
+ }
1085
+ };
1086
+ }
1087
+
1059
1088
  // src/store.ts
1060
1089
  var formErrorCollectorRef = null;
1061
1090
  function _setFormErrorCollector(collector) {
@@ -1171,7 +1200,7 @@ function init(config) {
1171
1200
  if (config.user) {
1172
1201
  flint.setUser(config.user);
1173
1202
  }
1174
- const replayEvents = [];
1203
+ const replayBuffer = createReplayBuffer(replayBufferMs);
1175
1204
  let stopReplay = null;
1176
1205
  debugLog(config, "Collectors started", {
1177
1206
  console: !!consoleCol,
@@ -1187,16 +1216,12 @@ function init(config) {
1187
1216
  formErrors: formErrorsCol,
1188
1217
  frustration: frustrationCol,
1189
1218
  errorCapture: errorCaptureCol,
1190
- replayEvents,
1219
+ replayBuffer,
1191
1220
  stopReplay: null
1192
1221
  };
1193
1222
  if (enableReplay && _replayRecorder) {
1194
- _replayRecorder((event) => {
1195
- replayEvents.push(event);
1196
- const cutoff = Date.now() - replayBufferMs;
1197
- while (replayEvents.length > 0 && replayEvents[0].timestamp < cutoff) {
1198
- replayEvents.shift();
1199
- }
1223
+ _replayRecorder((event, isCheckout) => {
1224
+ replayBuffer.push(event, isCheckout);
1200
1225
  }).then((stop) => {
1201
1226
  stopReplay = stop ?? null;
1202
1227
  if (instance) instance.stopReplay = stopReplay;
@@ -1237,7 +1262,7 @@ function init(config) {
1237
1262
  if (!instance || !remote?.integrations) return;
1238
1263
  const dd = remote.integrations.datadog;
1239
1264
  if (dd?.enabled && dd.site) {
1240
- import("./datadog-I3QKI6Q3.js").then(({ createDatadogReplayProvider: createDatadogReplayProvider2 }) => {
1265
+ import("./datadog-FLEAFTUB.js").then(({ createDatadogReplayProvider: createDatadogReplayProvider2 }) => {
1241
1266
  if (!instance) return;
1242
1267
  instance.config = {
1243
1268
  ...instance.config,
@@ -1288,7 +1313,7 @@ function getMeta(extraMeta) {
1288
1313
  };
1289
1314
  }
1290
1315
  function getReplayEvents() {
1291
- return instance ? [...instance.replayEvents] : [];
1316
+ return instance ? instance.replayBuffer.getEvents() : [];
1292
1317
  }
1293
1318
  function getConfig() {
1294
1319
  return instance?.config ?? null;
@@ -1366,6 +1391,7 @@ export {
1366
1391
  resolveTheme,
1367
1392
  submitReplay,
1368
1393
  submitReport,
1369
- subscribe
1394
+ subscribe,
1395
+ trackDatadogBugReported
1370
1396
  };
1371
1397
  //# sourceMappingURL=index.js.map