@tracelog/lib 0.11.5 → 0.12.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.
@@ -202,12 +202,12 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
202
202
  })(Mode || {});
203
203
 
204
204
  // src/types/scroll.types.ts
205
- function isPrimaryScrollEvent(event2) {
205
+ var isPrimaryScrollEvent = (event2) => {
206
206
  return event2.type === "scroll" /* SCROLL */ && "scroll_data" in event2 && event2.scroll_data.is_primary === true;
207
- }
208
- function isSecondaryScrollEvent(event2) {
207
+ };
208
+ var isSecondaryScrollEvent = (event2) => {
209
209
  return event2.type === "scroll" /* SCROLL */ && "scroll_data" in event2 && event2.scroll_data.is_primary === false;
210
- }
210
+ };
211
211
 
212
212
  // src/types/validation-error.types.ts
213
213
  var TraceLogValidationError = class extends Error {
@@ -255,12 +255,25 @@ var formatLogMsg = (msg, error) => {
255
255
  const sanitizedMessage = error.message.replace(/\s+at\s+.*$/gm, "").replace(/\(.*?:\d+:\d+\)/g, "");
256
256
  return `[TraceLog] ${msg}: ${sanitizedMessage}`;
257
257
  }
258
- return `[TraceLog] ${msg}: ${error instanceof Error ? error.message : "Unknown error"}`;
258
+ if (error instanceof Error) {
259
+ return `[TraceLog] ${msg}: ${error.message}`;
260
+ }
261
+ if (typeof error === "string") {
262
+ return `[TraceLog] ${msg}: ${error}`;
263
+ }
264
+ if (typeof error === "object") {
265
+ try {
266
+ return `[TraceLog] ${msg}: ${JSON.stringify(error)}`;
267
+ } catch {
268
+ return `[TraceLog] ${msg}: [Unable to serialize error]`;
269
+ }
270
+ }
271
+ return `[TraceLog] ${msg}: ${String(error)}`;
259
272
  }
260
273
  return `[TraceLog] ${msg}`;
261
274
  };
262
275
  var log = (type, msg, extra) => {
263
- const { error, data, showToClient = false } = extra ?? {};
276
+ const { error, data, showToClient = false, style } = extra ?? {};
264
277
  const formattedMsg = error ? formatLogMsg(msg, error) : `[TraceLog] ${msg}`;
265
278
  const method = type === "error" ? "error" : type === "warn" ? "warn" : "log";
266
279
  const isProduction = process.env.NODE_ENV !== "development";
@@ -272,13 +285,21 @@ var log = (type, msg, extra) => {
272
285
  return;
273
286
  }
274
287
  }
275
- if (isProduction && data !== void 0) {
276
- const sanitizedData = sanitizeLogData(data);
277
- console[method](formattedMsg, sanitizedData);
278
- } else if (data !== void 0) {
279
- console[method](formattedMsg, data);
288
+ const hasStyle = style !== void 0 && style !== "";
289
+ const styledMsg = hasStyle ? `%c${formattedMsg}` : formattedMsg;
290
+ if (data !== void 0) {
291
+ const sanitizedData = isProduction ? sanitizeLogData(data) : data;
292
+ if (hasStyle) {
293
+ console[method](styledMsg, style, sanitizedData);
294
+ } else {
295
+ console[method](styledMsg, sanitizedData);
296
+ }
280
297
  } else {
281
- console[method](formattedMsg);
298
+ if (hasStyle) {
299
+ console[method](styledMsg, style);
300
+ } else {
301
+ console[method](styledMsg);
302
+ }
282
303
  }
283
304
  };
284
305
  var sanitizeLogData = (data) => {
@@ -288,6 +309,14 @@ var sanitizeLogData = (data) => {
288
309
  const lowerKey = key.toLowerCase();
289
310
  if (sensitiveKeys.some((sensitiveKey) => lowerKey.includes(sensitiveKey))) {
290
311
  sanitized[key] = "[REDACTED]";
312
+ continue;
313
+ }
314
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
315
+ sanitized[key] = sanitizeLogData(value);
316
+ } else if (Array.isArray(value)) {
317
+ sanitized[key] = value.map(
318
+ (item) => item !== null && typeof item === "object" && !Array.isArray(item) ? sanitizeLogData(item) : item
319
+ );
291
320
  } else {
292
321
  sanitized[key] = value;
293
322
  }
@@ -335,23 +364,75 @@ var getDeviceType = () => {
335
364
  }
336
365
  };
337
366
 
367
+ // src/constants/app.constants.ts
368
+ var LOG_STYLE_ACTIVE = "background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;";
369
+ var LOG_STYLE_DISABLED = "background: #9e9e9e; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;";
370
+
338
371
  // src/constants/storage.constants.ts
339
372
  var STORAGE_BASE_KEY = "tlog";
340
373
  var QA_MODE_KEY = `${STORAGE_BASE_KEY}:qa_mode`;
341
374
  var USER_ID_KEY = `${STORAGE_BASE_KEY}:uid`;
375
+ var QA_MODE_URL_PARAM = "tlog_mode";
376
+ var QA_MODE_ENABLE_VALUE = "qa";
377
+ var QA_MODE_DISABLE_VALUE = "qa_off";
342
378
  var QUEUE_KEY = (id) => id ? `${STORAGE_BASE_KEY}:${id}:queue` : `${STORAGE_BASE_KEY}:queue`;
343
379
  var SESSION_STORAGE_KEY = (id) => id ? `${STORAGE_BASE_KEY}:${id}:session` : `${STORAGE_BASE_KEY}:session`;
344
380
  var BROADCAST_CHANNEL_NAME = (id) => id ? `${STORAGE_BASE_KEY}:${id}:broadcast` : `${STORAGE_BASE_KEY}:broadcast`;
345
381
 
346
382
  // src/constants/performance.constants.ts
347
- var WEB_VITALS_THRESHOLDS = {
348
- LCP: 4e3,
383
+ var WEB_VITALS_GOOD_THRESHOLDS = {
384
+ LCP: 2500,
385
+ // Good: ≤ 2.5s
349
386
  FCP: 1800,
350
- CLS: 0.25,
387
+ // Good: ≤ 1.8s
388
+ CLS: 0.1,
389
+ // Good: ≤ 0.1
390
+ INP: 200,
391
+ // Good: ≤ 200ms
392
+ TTFB: 800,
393
+ // Good: ≤ 800ms
394
+ LONG_TASK: 50
395
+ };
396
+ var WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS = {
397
+ LCP: 2500,
398
+ // Needs improvement: > 2.5s (same as good boundary)
399
+ FCP: 1800,
400
+ // Needs improvement: > 1.8s
401
+ CLS: 0.1,
402
+ // Needs improvement: > 0.1
351
403
  INP: 200,
404
+ // Needs improvement: > 200ms
352
405
  TTFB: 800,
406
+ // Needs improvement: > 800ms
407
+ LONG_TASK: 50
408
+ };
409
+ var WEB_VITALS_POOR_THRESHOLDS = {
410
+ LCP: 4e3,
411
+ // Poor: > 4s
412
+ FCP: 3e3,
413
+ // Poor: > 3s
414
+ CLS: 0.25,
415
+ // Poor: > 0.25
416
+ INP: 500,
417
+ // Poor: > 500ms
418
+ TTFB: 1800,
419
+ // Poor: > 1800ms
353
420
  LONG_TASK: 50
354
421
  };
422
+ var DEFAULT_WEB_VITALS_MODE = "needs-improvement";
423
+ var getWebVitalsThresholds = (mode = DEFAULT_WEB_VITALS_MODE) => {
424
+ switch (mode) {
425
+ case "all":
426
+ return { LCP: 0, FCP: 0, CLS: 0, INP: 0, TTFB: 0, LONG_TASK: 0 };
427
+ // Track everything
428
+ case "needs-improvement":
429
+ return WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS;
430
+ case "poor":
431
+ return WEB_VITALS_POOR_THRESHOLDS;
432
+ default:
433
+ return WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS;
434
+ }
435
+ };
355
436
  var LONG_TASK_THROTTLE_MS = 1e3;
356
437
  var MAX_NAVIGATION_HISTORY = 50;
357
438
 
@@ -383,32 +464,65 @@ var ERROR_BURST_BACKOFF_MS = 5e3;
383
464
  var PERMANENT_ERROR_LOG_THROTTLE_MS = 6e4;
384
465
 
385
466
  // src/utils/browser/qa-mode.utils.ts
386
- var QA_MODE_PARAM = "tlog_mode";
387
- var QA_MODE_VALUE = "qa";
388
467
  var detectQaMode = () => {
389
- const stored = sessionStorage.getItem(QA_MODE_KEY);
390
- if (stored === "true") {
391
- return true;
468
+ if (typeof window === "undefined" || typeof document === "undefined") {
469
+ return false;
392
470
  }
393
- const params = new URLSearchParams(window.location.search);
394
- const modeParam = params.get(QA_MODE_PARAM);
395
- const isQaMode = modeParam === QA_MODE_VALUE;
396
- if (isQaMode) {
397
- sessionStorage.setItem(QA_MODE_KEY, "true");
398
- params.delete(QA_MODE_PARAM);
399
- const newSearch = params.toString();
400
- const newUrl = `${window.location.pathname}${newSearch ? "?" + newSearch : ""}${window.location.hash}`;
401
- try {
402
- window.history.replaceState({}, "", newUrl);
403
- } catch (error) {
404
- log("warn", "History API not available, cannot replace URL", { error });
471
+ try {
472
+ const params = new URLSearchParams(window.location.search);
473
+ const urlParam = params.get(QA_MODE_URL_PARAM);
474
+ const storedState = sessionStorage.getItem(QA_MODE_KEY);
475
+ let newState = null;
476
+ if (urlParam === QA_MODE_ENABLE_VALUE) {
477
+ newState = true;
478
+ sessionStorage.setItem(QA_MODE_KEY, "true");
479
+ log("info", "QA Mode ACTIVE", {
480
+ showToClient: true,
481
+ style: LOG_STYLE_ACTIVE
482
+ });
483
+ } else if (urlParam === QA_MODE_DISABLE_VALUE) {
484
+ newState = false;
485
+ sessionStorage.removeItem(QA_MODE_KEY);
486
+ log("info", "QA Mode DISABLED", {
487
+ showToClient: true,
488
+ style: LOG_STYLE_DISABLED
489
+ });
405
490
  }
406
- console.log(
407
- "%c[TraceLog] QA Mode ACTIVE",
408
- "background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;"
409
- );
491
+ if (urlParam === QA_MODE_ENABLE_VALUE || urlParam === QA_MODE_DISABLE_VALUE) {
492
+ try {
493
+ params.delete(QA_MODE_URL_PARAM);
494
+ const search = params.toString();
495
+ const url = window.location.pathname + (search ? "?" + search : "") + window.location.hash;
496
+ window.history.replaceState({}, "", url);
497
+ } catch {
498
+ }
499
+ }
500
+ return newState ?? storedState === "true";
501
+ } catch {
502
+ return false;
503
+ }
504
+ };
505
+ var setQaMode = (enabled) => {
506
+ if (typeof window === "undefined" || typeof document === "undefined") {
507
+ return;
508
+ }
509
+ try {
510
+ if (enabled) {
511
+ sessionStorage.setItem(QA_MODE_KEY, "true");
512
+ log("info", "QA Mode ENABLED", {
513
+ showToClient: true,
514
+ style: LOG_STYLE_ACTIVE
515
+ });
516
+ } else {
517
+ sessionStorage.removeItem(QA_MODE_KEY);
518
+ log("info", "QA Mode DISABLED", {
519
+ showToClient: true,
520
+ style: LOG_STYLE_DISABLED
521
+ });
522
+ }
523
+ } catch {
524
+ log("warn", "Cannot set QA mode: sessionStorage unavailable");
410
525
  }
411
- return isQaMode;
412
526
  };
413
527
 
414
528
  // src/utils/browser/utm-params.utils.ts
@@ -693,6 +807,41 @@ var validateAppConfig = (config) => {
693
807
  if (config.viewport !== void 0) {
694
808
  validateViewportConfig(config.viewport);
695
809
  }
810
+ if (config.webVitalsMode !== void 0) {
811
+ if (typeof config.webVitalsMode !== "string") {
812
+ throw new AppConfigValidationError(
813
+ `Invalid webVitalsMode type: ${typeof config.webVitalsMode}. Must be a string`,
814
+ "config"
815
+ );
816
+ }
817
+ const validModes = ["all", "needs-improvement", "poor"];
818
+ if (!validModes.includes(config.webVitalsMode)) {
819
+ throw new AppConfigValidationError(
820
+ `Invalid webVitalsMode: "${config.webVitalsMode}". Must be one of: ${validModes.join(", ")}`,
821
+ "config"
822
+ );
823
+ }
824
+ }
825
+ if (config.webVitalsThresholds !== void 0) {
826
+ if (typeof config.webVitalsThresholds !== "object" || config.webVitalsThresholds === null || Array.isArray(config.webVitalsThresholds)) {
827
+ throw new AppConfigValidationError("webVitalsThresholds must be an object", "config");
828
+ }
829
+ const validKeys = ["LCP", "FCP", "CLS", "INP", "TTFB", "LONG_TASK"];
830
+ for (const [key, value] of Object.entries(config.webVitalsThresholds)) {
831
+ if (!validKeys.includes(key)) {
832
+ throw new AppConfigValidationError(
833
+ `Invalid Web Vitals threshold key: "${key}". Must be one of: ${validKeys.join(", ")}`,
834
+ "config"
835
+ );
836
+ }
837
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
838
+ throw new AppConfigValidationError(
839
+ `Invalid Web Vitals threshold value for ${key}: ${value}. Must be a non-negative finite number`,
840
+ "config"
841
+ );
842
+ }
843
+ }
844
+ }
696
845
  };
697
846
  var validateViewportConfig = (viewport) => {
698
847
  if (typeof viewport !== "object" || viewport === null) {
@@ -1500,9 +1649,12 @@ var EventManager = class extends StateManager {
1500
1649
  return;
1501
1650
  }
1502
1651
  if (this.get("mode") === "qa" /* QA */ && eventType === "custom" /* CUSTOM */ && custom_event) {
1503
- console.log("[TraceLog] Event", {
1504
- name: custom_event.name,
1505
- ...custom_event.metadata && { metadata: custom_event.metadata }
1652
+ log("info", "Event", {
1653
+ showToClient: true,
1654
+ data: {
1655
+ name: custom_event.name,
1656
+ ...custom_event.metadata && { metadata: custom_event.metadata }
1657
+ }
1506
1658
  });
1507
1659
  this.emitEvent(payload);
1508
1660
  return;
@@ -3459,13 +3611,20 @@ var PerformanceHandler = class extends StateManager {
3459
3611
  navigationHistory = [];
3460
3612
  // FIFO queue for tracking navigation order
3461
3613
  observers = [];
3462
- vitalThresholds = WEB_VITALS_THRESHOLDS;
3614
+ vitalThresholds;
3463
3615
  lastLongTaskSentAt = 0;
3464
3616
  constructor(eventManager) {
3465
3617
  super();
3466
3618
  this.eventManager = eventManager;
3619
+ this.vitalThresholds = getWebVitalsThresholds(DEFAULT_WEB_VITALS_MODE);
3467
3620
  }
3468
3621
  async startTracking() {
3622
+ const config = this.get("config");
3623
+ const mode = config?.webVitalsMode ?? DEFAULT_WEB_VITALS_MODE;
3624
+ this.vitalThresholds = getWebVitalsThresholds(mode);
3625
+ if (config?.webVitalsThresholds) {
3626
+ this.vitalThresholds = { ...this.vitalThresholds, ...config.webVitalsThresholds };
3627
+ }
3469
3628
  await this.initWebVitals();
3470
3629
  this.observeLongTasks();
3471
3630
  }
@@ -4271,6 +4430,12 @@ var __setAppInstance = (instance) => {
4271
4430
  }
4272
4431
  app = instance;
4273
4432
  };
4433
+ var setQaMode2 = (enabled) => {
4434
+ if (typeof window === "undefined" || typeof document === "undefined") {
4435
+ return;
4436
+ }
4437
+ setQaMode(enabled);
4438
+ };
4274
4439
  if (process.env.NODE_ENV === "development" && typeof window !== "undefined" && typeof document !== "undefined") {
4275
4440
  const injectTestingBridge = () => {
4276
4441
  window.__traceLogBridge = new TestBridge(isInitializing, isDestroying);
@@ -4283,14 +4448,6 @@ if (process.env.NODE_ENV === "development" && typeof window !== "undefined" && t
4283
4448
  }
4284
4449
 
4285
4450
  // src/app.constants.ts
4286
- var PERFORMANCE_CONFIG = {
4287
- WEB_VITALS_THRESHOLDS
4288
- // Business thresholds for performance analysis
4289
- };
4290
- var DATA_PROTECTION = {
4291
- PII_PATTERNS
4292
- // Patterns for sensitive data protection
4293
- };
4294
4451
  var ENGAGEMENT_THRESHOLDS = {
4295
4452
  LOW_ACTIVITY_EVENT_COUNT: 50,
4296
4453
  HIGH_ACTIVITY_EVENT_COUNT: 1e3,
@@ -4308,23 +4465,10 @@ var SESSION_ANALYTICS = {
4308
4465
  SHORT_SESSION_THRESHOLD_MS: 30 * 1e3,
4309
4466
  MEDIUM_SESSION_THRESHOLD_MS: 5 * 60 * 1e3,
4310
4467
  LONG_SESSION_THRESHOLD_MS: 30 * 60 * 1e3,
4311
- MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1e3
4468
+ MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1e3,
4312
4469
  // Filter outliers
4313
- };
4314
- var DEVICE_ANALYTICS = {
4315
- MOBILE_MAX_WIDTH: 768,
4316
- TABLET_MAX_WIDTH: 1024,
4317
- MOBILE_PERFORMANCE_FACTOR: 1.5,
4318
- // Mobile typically 1.5x slower
4319
- TABLET_PERFORMANCE_FACTOR: 1.2
4320
- };
4321
- var CONTENT_ANALYTICS = {
4322
- MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,
4323
- MIN_CLICKS_FOR_HOT_ELEMENT: 10,
4324
- // Popular element threshold
4325
- MIN_SCROLL_COMPLETION_PERCENT: 80,
4326
- // Page consumption threshold
4327
- MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1e3
4470
+ MIN_EVENTS_FOR_DURATION: 2
4471
+ // Minimum events required to calculate session duration
4328
4472
  };
4329
4473
  var INSIGHT_THRESHOLDS = {
4330
4474
  SIGNIFICANT_CHANGE_PERCENT: 20,
@@ -4337,20 +4481,6 @@ var INSIGHT_THRESHOLDS = {
4337
4481
  HIGH_ERROR_RATE_PERCENT: 5,
4338
4482
  CRITICAL_ERROR_RATE_PERCENT: 10
4339
4483
  };
4340
- var TEMPORAL_ANALYSIS = {
4341
- SHORT_TERM_TREND_HOURS: 24,
4342
- MEDIUM_TERM_TREND_DAYS: 7,
4343
- LONG_TERM_TREND_DAYS: 30,
4344
- MIN_DATA_POINTS_FOR_TREND: 5,
4345
- WEEKLY_PATTERN_MIN_WEEKS: 4,
4346
- DAILY_PATTERN_MIN_DAYS: 14
4347
- };
4348
- var SEGMENTATION_ANALYTICS = {
4349
- MIN_SEGMENT_SIZE: 10,
4350
- MIN_COHORT_SIZE: 5,
4351
- COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],
4352
- MIN_FUNNEL_EVENTS: 20
4353
- };
4354
4484
  var ANALYTICS_QUERY_LIMITS = {
4355
4485
  DEFAULT_EVENTS_LIMIT: 5,
4356
4486
  DEFAULT_SESSIONS_LIMIT: 5,
@@ -4360,14 +4490,6 @@ var ANALYTICS_QUERY_LIMITS = {
4360
4490
  ANALYTICS_BATCH_SIZE: 1e3
4361
4491
  // For historical analysis
4362
4492
  };
4363
- var ANOMALY_DETECTION = {
4364
- ANOMALY_THRESHOLD_SIGMA: 2.5,
4365
- STRONG_ANOMALY_THRESHOLD_SIGMA: 3,
4366
- TRAFFIC_DROP_ALERT_PERCENT: -30,
4367
- TRAFFIC_SPIKE_ALERT_PERCENT: 200,
4368
- MIN_BASELINE_DAYS: 7,
4369
- MIN_EVENTS_FOR_ANOMALY_DETECTION: 50
4370
- };
4371
4493
  var SPECIAL_PAGE_URLS = {
4372
4494
  PAGE_URL_EXCLUDED: "excluded",
4373
4495
  PAGE_URL_UNKNOWN: "unknown"
@@ -4380,9 +4502,10 @@ var tracelog = {
4380
4502
  on,
4381
4503
  off,
4382
4504
  isInitialized,
4383
- destroy
4505
+ destroy,
4506
+ setQaMode: setQaMode2
4384
4507
  };
4385
4508
 
4386
- export { ANALYTICS_QUERY_LIMITS, ANOMALY_DETECTION, AppConfigValidationError, CONTENT_ANALYTICS, DATA_PROTECTION, DEVICE_ANALYTICS, DeviceType, ENGAGEMENT_THRESHOLDS, EmitterEvent, ErrorType, EventType, INSIGHT_THRESHOLDS, InitializationTimeoutError, IntegrationValidationError, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, Mode, PERFORMANCE_CONFIG, PermanentError, SEGMENTATION_ANALYTICS, SESSION_ANALYTICS, SPECIAL_PAGE_URLS, SamplingRateValidationError, ScrollDirection, SessionTimeoutValidationError, SpecialApiUrl, TEMPORAL_ANALYSIS, TraceLogValidationError, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
4509
+ export { ANALYTICS_QUERY_LIMITS, AppConfigValidationError, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, DeviceType, ENGAGEMENT_THRESHOLDS, EmitterEvent, ErrorType, EventType, INSIGHT_THRESHOLDS, InitializationTimeoutError, IntegrationValidationError, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, Mode, PII_PATTERNS, PermanentError, SESSION_ANALYTICS, SPECIAL_PAGE_URLS, SamplingRateValidationError, ScrollDirection, SessionTimeoutValidationError, SpecialApiUrl, TraceLogValidationError, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
4387
4510
  //# sourceMappingURL=public-api.js.map
4388
4511
  //# sourceMappingURL=public-api.js.map