@analyticscli/sdk 0.1.0-preview.7 → 0.1.0-preview.8
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/browser.cjs +136 -7
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1 -1
- package/dist/{chunk-O4FIH647.js → chunk-S3MLRL5U.js} +136 -7
- package/dist/index.cjs +136 -7
- package/dist/index.d.cts +75 -1
- package/dist/index.d.ts +75 -1
- package/dist/index.js +1 -1
- package/dist/react-native.cjs +136 -7
- package/dist/react-native.d.cts +1 -1
- package/dist/react-native.d.ts +1 -1
- package/dist/react-native.js +1 -1
- package/package.json +1 -1
package/dist/browser.cjs
CHANGED
|
@@ -587,6 +587,28 @@ var sanitizeSurveyResponseInput = (input) => {
|
|
|
587
587
|
|
|
588
588
|
// src/analytics-client.ts
|
|
589
589
|
var DEFAULT_CONSENT_STORAGE_KEY = "analyticscli:consent:v1";
|
|
590
|
+
var AUTH_FAILURE_FLUSH_PAUSE_MS = 6e4;
|
|
591
|
+
var IngestSendError = class extends Error {
|
|
592
|
+
retryable;
|
|
593
|
+
attempts;
|
|
594
|
+
status;
|
|
595
|
+
errorCode;
|
|
596
|
+
serverMessage;
|
|
597
|
+
requestId;
|
|
598
|
+
constructor(input) {
|
|
599
|
+
super(input.message);
|
|
600
|
+
this.name = "IngestSendError";
|
|
601
|
+
this.retryable = input.retryable;
|
|
602
|
+
this.attempts = input.attempts;
|
|
603
|
+
this.status = input.status;
|
|
604
|
+
this.errorCode = input.errorCode;
|
|
605
|
+
this.serverMessage = input.serverMessage;
|
|
606
|
+
this.requestId = input.requestId;
|
|
607
|
+
if (input.cause !== void 0) {
|
|
608
|
+
this.cause = input.cause;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
};
|
|
590
612
|
var AnalyticsClient = class {
|
|
591
613
|
apiKey;
|
|
592
614
|
hasIngestConfig;
|
|
@@ -595,6 +617,7 @@ var AnalyticsClient = class {
|
|
|
595
617
|
flushIntervalMs;
|
|
596
618
|
maxRetries;
|
|
597
619
|
debug;
|
|
620
|
+
onIngestError;
|
|
598
621
|
platform;
|
|
599
622
|
projectSurface;
|
|
600
623
|
appVersion;
|
|
@@ -627,6 +650,7 @@ var AnalyticsClient = class {
|
|
|
627
650
|
deferredEventsBeforeHydration = [];
|
|
628
651
|
onboardingStepViewStateSessionId = null;
|
|
629
652
|
onboardingStepViewsSeen = /* @__PURE__ */ new Set();
|
|
653
|
+
flushPausedUntilMs = 0;
|
|
630
654
|
constructor(options) {
|
|
631
655
|
const normalizedOptions = this.normalizeOptions(options);
|
|
632
656
|
this.apiKey = this.readRequiredStringOption(normalizedOptions.apiKey);
|
|
@@ -639,6 +663,7 @@ var AnalyticsClient = class {
|
|
|
639
663
|
this.flushIntervalMs = normalizedOptions.flushIntervalMs ?? 5e3;
|
|
640
664
|
this.maxRetries = normalizedOptions.maxRetries ?? 4;
|
|
641
665
|
this.debug = normalizedOptions.debug ?? false;
|
|
666
|
+
this.onIngestError = typeof normalizedOptions.onIngestError === "function" ? normalizedOptions.onIngestError : null;
|
|
642
667
|
this.platform = this.normalizePlatformOption(normalizedOptions.platform) ?? detectDefaultPlatform();
|
|
643
668
|
this.projectSurface = this.normalizeProjectSurfaceOption(normalizedOptions.projectSurface);
|
|
644
669
|
this.appVersion = this.readRequiredStringOption(normalizedOptions.appVersion) || detectDefaultAppVersion();
|
|
@@ -1102,6 +1127,9 @@ var AnalyticsClient = class {
|
|
|
1102
1127
|
if (this.queue.length === 0 || this.isFlushing || !this.consentGranted) {
|
|
1103
1128
|
return;
|
|
1104
1129
|
}
|
|
1130
|
+
if (Date.now() < this.flushPausedUntilMs) {
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1105
1133
|
this.isFlushing = true;
|
|
1106
1134
|
const batch = this.queue.splice(0, this.batchSize);
|
|
1107
1135
|
const payload = {
|
|
@@ -1116,9 +1144,20 @@ var AnalyticsClient = class {
|
|
|
1116
1144
|
}
|
|
1117
1145
|
try {
|
|
1118
1146
|
await this.sendWithRetry(payload);
|
|
1147
|
+
this.flushPausedUntilMs = 0;
|
|
1119
1148
|
} catch (error) {
|
|
1120
|
-
this.log("Send failed permanently, requeueing batch", error);
|
|
1121
1149
|
this.queue = [...batch, ...this.queue];
|
|
1150
|
+
const ingestError = this.toIngestSendError(error);
|
|
1151
|
+
const diagnostics = this.createIngestDiagnostics(ingestError, batch.length, this.queue.length);
|
|
1152
|
+
if (ingestError.status === 401 || ingestError.status === 403) {
|
|
1153
|
+
this.flushPausedUntilMs = Date.now() + AUTH_FAILURE_FLUSH_PAUSE_MS;
|
|
1154
|
+
this.log("Pausing ingest flush after auth failure", {
|
|
1155
|
+
status: ingestError.status,
|
|
1156
|
+
retryAfterMs: AUTH_FAILURE_FLUSH_PAUSE_MS
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
this.log("Send failed permanently, requeueing batch", diagnostics);
|
|
1160
|
+
this.reportIngestError(diagnostics);
|
|
1122
1161
|
} finally {
|
|
1123
1162
|
this.isFlushing = false;
|
|
1124
1163
|
}
|
|
@@ -1147,9 +1186,8 @@ var AnalyticsClient = class {
|
|
|
1147
1186
|
});
|
|
1148
1187
|
}
|
|
1149
1188
|
async sendWithRetry(payload) {
|
|
1150
|
-
let attempt = 0;
|
|
1151
1189
|
let delay = 250;
|
|
1152
|
-
|
|
1190
|
+
for (let attempt = 1; attempt <= this.maxRetries + 1; attempt += 1) {
|
|
1153
1191
|
try {
|
|
1154
1192
|
const response = await fetch(`${this.endpoint}/v1/collect`, {
|
|
1155
1193
|
method: "POST",
|
|
@@ -1161,19 +1199,110 @@ var AnalyticsClient = class {
|
|
|
1161
1199
|
keepalive: true
|
|
1162
1200
|
});
|
|
1163
1201
|
if (!response.ok) {
|
|
1164
|
-
throw
|
|
1202
|
+
throw await this.createHttpIngestSendError(response, attempt);
|
|
1165
1203
|
}
|
|
1166
1204
|
return;
|
|
1167
1205
|
} catch (error) {
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1206
|
+
const normalized = this.toIngestSendError(error, attempt);
|
|
1207
|
+
const finalAttempt = attempt >= this.maxRetries + 1;
|
|
1208
|
+
this.log("Ingest attempt failed", {
|
|
1209
|
+
attempt: normalized.attempts,
|
|
1210
|
+
maxRetries: this.maxRetries,
|
|
1211
|
+
retryable: normalized.retryable,
|
|
1212
|
+
status: normalized.status,
|
|
1213
|
+
errorCode: normalized.errorCode,
|
|
1214
|
+
requestId: normalized.requestId,
|
|
1215
|
+
nextRetryInMs: !finalAttempt && normalized.retryable ? delay : null
|
|
1216
|
+
});
|
|
1217
|
+
if (finalAttempt || !normalized.retryable) {
|
|
1218
|
+
throw normalized;
|
|
1171
1219
|
}
|
|
1172
1220
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1173
1221
|
delay *= 2;
|
|
1174
1222
|
}
|
|
1175
1223
|
}
|
|
1176
1224
|
}
|
|
1225
|
+
async createHttpIngestSendError(response, attempts) {
|
|
1226
|
+
const requestId = response.headers.get("x-request-id") ?? response.headers.get("cf-ray") ?? void 0;
|
|
1227
|
+
let errorCode;
|
|
1228
|
+
let serverMessage;
|
|
1229
|
+
try {
|
|
1230
|
+
const parsed = await response.json();
|
|
1231
|
+
const errorBody = parsed && typeof parsed === "object" && parsed.error && typeof parsed.error === "object" ? parsed.error : void 0;
|
|
1232
|
+
if (typeof errorBody?.code === "string") {
|
|
1233
|
+
errorCode = errorBody.code;
|
|
1234
|
+
}
|
|
1235
|
+
if (typeof errorBody?.message === "string") {
|
|
1236
|
+
serverMessage = errorBody.message;
|
|
1237
|
+
}
|
|
1238
|
+
} catch {
|
|
1239
|
+
}
|
|
1240
|
+
const retryable = this.shouldRetryHttpStatus(response.status);
|
|
1241
|
+
const statusSuffix = errorCode ? ` ${errorCode}` : "";
|
|
1242
|
+
const message = `ingest status=${response.status}${statusSuffix}`;
|
|
1243
|
+
return new IngestSendError({
|
|
1244
|
+
message,
|
|
1245
|
+
retryable,
|
|
1246
|
+
attempts,
|
|
1247
|
+
status: response.status,
|
|
1248
|
+
errorCode,
|
|
1249
|
+
serverMessage,
|
|
1250
|
+
requestId
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
shouldRetryHttpStatus(status) {
|
|
1254
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
1255
|
+
}
|
|
1256
|
+
toIngestSendError(error, attempts) {
|
|
1257
|
+
if (error instanceof IngestSendError) {
|
|
1258
|
+
const resolvedAttempts = attempts ?? error.attempts;
|
|
1259
|
+
return new IngestSendError({
|
|
1260
|
+
message: error.message,
|
|
1261
|
+
retryable: error.retryable,
|
|
1262
|
+
attempts: resolvedAttempts,
|
|
1263
|
+
status: error.status,
|
|
1264
|
+
errorCode: error.errorCode,
|
|
1265
|
+
serverMessage: error.serverMessage,
|
|
1266
|
+
requestId: error.requestId,
|
|
1267
|
+
cause: error.cause
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
const fallbackMessage = error instanceof Error ? error.message : "ingest request failed";
|
|
1271
|
+
return new IngestSendError({
|
|
1272
|
+
message: fallbackMessage,
|
|
1273
|
+
retryable: true,
|
|
1274
|
+
attempts: attempts ?? 1,
|
|
1275
|
+
cause: error
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
createIngestDiagnostics(error, batchSize, queueSize) {
|
|
1279
|
+
return {
|
|
1280
|
+
name: "AnalyticsIngestError",
|
|
1281
|
+
message: error.message,
|
|
1282
|
+
endpoint: this.endpoint,
|
|
1283
|
+
path: "/v1/collect",
|
|
1284
|
+
status: error.status,
|
|
1285
|
+
errorCode: error.errorCode,
|
|
1286
|
+
serverMessage: error.serverMessage,
|
|
1287
|
+
requestId: error.requestId,
|
|
1288
|
+
retryable: error.retryable,
|
|
1289
|
+
attempts: error.attempts,
|
|
1290
|
+
maxRetries: this.maxRetries,
|
|
1291
|
+
batchSize,
|
|
1292
|
+
queueSize,
|
|
1293
|
+
timestamp: nowIso()
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
reportIngestError(error) {
|
|
1297
|
+
if (!this.onIngestError) {
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
try {
|
|
1301
|
+
this.onIngestError(error);
|
|
1302
|
+
} catch (callbackError) {
|
|
1303
|
+
this.log("onIngestError callback threw", callbackError);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1177
1306
|
parsePersistedConsent(raw) {
|
|
1178
1307
|
if (raw === "granted") {
|
|
1179
1308
|
return true;
|
package/dist/browser.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { AnalyticsClient, AnalyticsClientOptions, AnalyticsConsentState, AnalyticsContext, AnalyticsContextConsentControls, AnalyticsContextUserControls, AnalyticsStorageAdapter, CreateAnalyticsContextOptions, EventContext, EventProperties, IdentityTrackingMode, InitInput, InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, OnboardingEventName, OnboardingEventProperties, OnboardingStepTracker, OnboardingSurveyAnswerType, OnboardingSurveyEventName, OnboardingSurveyResponseInput, OnboardingTracker, OnboardingTrackerDefaults, OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, PaywallEventName, PaywallEventProperties, PaywallJourneyEventName, PaywallTracker, PaywallTrackerDefaults, PaywallTrackerProperties, PurchaseEventName, SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync } from './index.cjs';
|
|
1
|
+
export { AnalyticsClient, AnalyticsClientOptions, AnalyticsConsentState, AnalyticsContext, AnalyticsContextConsentControls, AnalyticsContextUserControls, AnalyticsIngestError, AnalyticsIngestErrorHandler, AnalyticsStorageAdapter, CreateAnalyticsContextOptions, EventContext, EventProperties, IdentityTrackingMode, InitInput, InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, OnboardingEventName, OnboardingEventProperties, OnboardingStepTracker, OnboardingSurveyAnswerType, OnboardingSurveyEventName, OnboardingSurveyResponseInput, OnboardingTracker, OnboardingTrackerDefaults, OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, PaywallEventName, PaywallEventProperties, PaywallJourneyEventName, PaywallTracker, PaywallTrackerDefaults, PaywallTrackerProperties, PurchaseEventName, SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync } from './index.cjs';
|
package/dist/browser.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { AnalyticsClient, AnalyticsClientOptions, AnalyticsConsentState, AnalyticsContext, AnalyticsContextConsentControls, AnalyticsContextUserControls, AnalyticsStorageAdapter, CreateAnalyticsContextOptions, EventContext, EventProperties, IdentityTrackingMode, InitInput, InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, OnboardingEventName, OnboardingEventProperties, OnboardingStepTracker, OnboardingSurveyAnswerType, OnboardingSurveyEventName, OnboardingSurveyResponseInput, OnboardingTracker, OnboardingTrackerDefaults, OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, PaywallEventName, PaywallEventProperties, PaywallJourneyEventName, PaywallTracker, PaywallTrackerDefaults, PaywallTrackerProperties, PurchaseEventName, SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync } from './index.js';
|
|
1
|
+
export { AnalyticsClient, AnalyticsClientOptions, AnalyticsConsentState, AnalyticsContext, AnalyticsContextConsentControls, AnalyticsContextUserControls, AnalyticsIngestError, AnalyticsIngestErrorHandler, AnalyticsStorageAdapter, CreateAnalyticsContextOptions, EventContext, EventProperties, IdentityTrackingMode, InitInput, InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, OnboardingEventName, OnboardingEventProperties, OnboardingStepTracker, OnboardingSurveyAnswerType, OnboardingSurveyEventName, OnboardingSurveyResponseInput, OnboardingTracker, OnboardingTrackerDefaults, OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, PaywallEventName, PaywallEventProperties, PaywallJourneyEventName, PaywallTracker, PaywallTrackerDefaults, PaywallTrackerProperties, PurchaseEventName, SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync } from './index.js';
|
package/dist/browser.js
CHANGED
|
@@ -546,6 +546,28 @@ var sanitizeSurveyResponseInput = (input) => {
|
|
|
546
546
|
|
|
547
547
|
// src/analytics-client.ts
|
|
548
548
|
var DEFAULT_CONSENT_STORAGE_KEY = "analyticscli:consent:v1";
|
|
549
|
+
var AUTH_FAILURE_FLUSH_PAUSE_MS = 6e4;
|
|
550
|
+
var IngestSendError = class extends Error {
|
|
551
|
+
retryable;
|
|
552
|
+
attempts;
|
|
553
|
+
status;
|
|
554
|
+
errorCode;
|
|
555
|
+
serverMessage;
|
|
556
|
+
requestId;
|
|
557
|
+
constructor(input) {
|
|
558
|
+
super(input.message);
|
|
559
|
+
this.name = "IngestSendError";
|
|
560
|
+
this.retryable = input.retryable;
|
|
561
|
+
this.attempts = input.attempts;
|
|
562
|
+
this.status = input.status;
|
|
563
|
+
this.errorCode = input.errorCode;
|
|
564
|
+
this.serverMessage = input.serverMessage;
|
|
565
|
+
this.requestId = input.requestId;
|
|
566
|
+
if (input.cause !== void 0) {
|
|
567
|
+
this.cause = input.cause;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
};
|
|
549
571
|
var AnalyticsClient = class {
|
|
550
572
|
apiKey;
|
|
551
573
|
hasIngestConfig;
|
|
@@ -554,6 +576,7 @@ var AnalyticsClient = class {
|
|
|
554
576
|
flushIntervalMs;
|
|
555
577
|
maxRetries;
|
|
556
578
|
debug;
|
|
579
|
+
onIngestError;
|
|
557
580
|
platform;
|
|
558
581
|
projectSurface;
|
|
559
582
|
appVersion;
|
|
@@ -586,6 +609,7 @@ var AnalyticsClient = class {
|
|
|
586
609
|
deferredEventsBeforeHydration = [];
|
|
587
610
|
onboardingStepViewStateSessionId = null;
|
|
588
611
|
onboardingStepViewsSeen = /* @__PURE__ */ new Set();
|
|
612
|
+
flushPausedUntilMs = 0;
|
|
589
613
|
constructor(options) {
|
|
590
614
|
const normalizedOptions = this.normalizeOptions(options);
|
|
591
615
|
this.apiKey = this.readRequiredStringOption(normalizedOptions.apiKey);
|
|
@@ -598,6 +622,7 @@ var AnalyticsClient = class {
|
|
|
598
622
|
this.flushIntervalMs = normalizedOptions.flushIntervalMs ?? 5e3;
|
|
599
623
|
this.maxRetries = normalizedOptions.maxRetries ?? 4;
|
|
600
624
|
this.debug = normalizedOptions.debug ?? false;
|
|
625
|
+
this.onIngestError = typeof normalizedOptions.onIngestError === "function" ? normalizedOptions.onIngestError : null;
|
|
601
626
|
this.platform = this.normalizePlatformOption(normalizedOptions.platform) ?? detectDefaultPlatform();
|
|
602
627
|
this.projectSurface = this.normalizeProjectSurfaceOption(normalizedOptions.projectSurface);
|
|
603
628
|
this.appVersion = this.readRequiredStringOption(normalizedOptions.appVersion) || detectDefaultAppVersion();
|
|
@@ -1061,6 +1086,9 @@ var AnalyticsClient = class {
|
|
|
1061
1086
|
if (this.queue.length === 0 || this.isFlushing || !this.consentGranted) {
|
|
1062
1087
|
return;
|
|
1063
1088
|
}
|
|
1089
|
+
if (Date.now() < this.flushPausedUntilMs) {
|
|
1090
|
+
return;
|
|
1091
|
+
}
|
|
1064
1092
|
this.isFlushing = true;
|
|
1065
1093
|
const batch = this.queue.splice(0, this.batchSize);
|
|
1066
1094
|
const payload = {
|
|
@@ -1075,9 +1103,20 @@ var AnalyticsClient = class {
|
|
|
1075
1103
|
}
|
|
1076
1104
|
try {
|
|
1077
1105
|
await this.sendWithRetry(payload);
|
|
1106
|
+
this.flushPausedUntilMs = 0;
|
|
1078
1107
|
} catch (error) {
|
|
1079
|
-
this.log("Send failed permanently, requeueing batch", error);
|
|
1080
1108
|
this.queue = [...batch, ...this.queue];
|
|
1109
|
+
const ingestError = this.toIngestSendError(error);
|
|
1110
|
+
const diagnostics = this.createIngestDiagnostics(ingestError, batch.length, this.queue.length);
|
|
1111
|
+
if (ingestError.status === 401 || ingestError.status === 403) {
|
|
1112
|
+
this.flushPausedUntilMs = Date.now() + AUTH_FAILURE_FLUSH_PAUSE_MS;
|
|
1113
|
+
this.log("Pausing ingest flush after auth failure", {
|
|
1114
|
+
status: ingestError.status,
|
|
1115
|
+
retryAfterMs: AUTH_FAILURE_FLUSH_PAUSE_MS
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
this.log("Send failed permanently, requeueing batch", diagnostics);
|
|
1119
|
+
this.reportIngestError(diagnostics);
|
|
1081
1120
|
} finally {
|
|
1082
1121
|
this.isFlushing = false;
|
|
1083
1122
|
}
|
|
@@ -1106,9 +1145,8 @@ var AnalyticsClient = class {
|
|
|
1106
1145
|
});
|
|
1107
1146
|
}
|
|
1108
1147
|
async sendWithRetry(payload) {
|
|
1109
|
-
let attempt = 0;
|
|
1110
1148
|
let delay = 250;
|
|
1111
|
-
|
|
1149
|
+
for (let attempt = 1; attempt <= this.maxRetries + 1; attempt += 1) {
|
|
1112
1150
|
try {
|
|
1113
1151
|
const response = await fetch(`${this.endpoint}/v1/collect`, {
|
|
1114
1152
|
method: "POST",
|
|
@@ -1120,19 +1158,110 @@ var AnalyticsClient = class {
|
|
|
1120
1158
|
keepalive: true
|
|
1121
1159
|
});
|
|
1122
1160
|
if (!response.ok) {
|
|
1123
|
-
throw
|
|
1161
|
+
throw await this.createHttpIngestSendError(response, attempt);
|
|
1124
1162
|
}
|
|
1125
1163
|
return;
|
|
1126
1164
|
} catch (error) {
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1165
|
+
const normalized = this.toIngestSendError(error, attempt);
|
|
1166
|
+
const finalAttempt = attempt >= this.maxRetries + 1;
|
|
1167
|
+
this.log("Ingest attempt failed", {
|
|
1168
|
+
attempt: normalized.attempts,
|
|
1169
|
+
maxRetries: this.maxRetries,
|
|
1170
|
+
retryable: normalized.retryable,
|
|
1171
|
+
status: normalized.status,
|
|
1172
|
+
errorCode: normalized.errorCode,
|
|
1173
|
+
requestId: normalized.requestId,
|
|
1174
|
+
nextRetryInMs: !finalAttempt && normalized.retryable ? delay : null
|
|
1175
|
+
});
|
|
1176
|
+
if (finalAttempt || !normalized.retryable) {
|
|
1177
|
+
throw normalized;
|
|
1130
1178
|
}
|
|
1131
1179
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1132
1180
|
delay *= 2;
|
|
1133
1181
|
}
|
|
1134
1182
|
}
|
|
1135
1183
|
}
|
|
1184
|
+
async createHttpIngestSendError(response, attempts) {
|
|
1185
|
+
const requestId = response.headers.get("x-request-id") ?? response.headers.get("cf-ray") ?? void 0;
|
|
1186
|
+
let errorCode;
|
|
1187
|
+
let serverMessage;
|
|
1188
|
+
try {
|
|
1189
|
+
const parsed = await response.json();
|
|
1190
|
+
const errorBody = parsed && typeof parsed === "object" && parsed.error && typeof parsed.error === "object" ? parsed.error : void 0;
|
|
1191
|
+
if (typeof errorBody?.code === "string") {
|
|
1192
|
+
errorCode = errorBody.code;
|
|
1193
|
+
}
|
|
1194
|
+
if (typeof errorBody?.message === "string") {
|
|
1195
|
+
serverMessage = errorBody.message;
|
|
1196
|
+
}
|
|
1197
|
+
} catch {
|
|
1198
|
+
}
|
|
1199
|
+
const retryable = this.shouldRetryHttpStatus(response.status);
|
|
1200
|
+
const statusSuffix = errorCode ? ` ${errorCode}` : "";
|
|
1201
|
+
const message = `ingest status=${response.status}${statusSuffix}`;
|
|
1202
|
+
return new IngestSendError({
|
|
1203
|
+
message,
|
|
1204
|
+
retryable,
|
|
1205
|
+
attempts,
|
|
1206
|
+
status: response.status,
|
|
1207
|
+
errorCode,
|
|
1208
|
+
serverMessage,
|
|
1209
|
+
requestId
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
shouldRetryHttpStatus(status) {
|
|
1213
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
1214
|
+
}
|
|
1215
|
+
toIngestSendError(error, attempts) {
|
|
1216
|
+
if (error instanceof IngestSendError) {
|
|
1217
|
+
const resolvedAttempts = attempts ?? error.attempts;
|
|
1218
|
+
return new IngestSendError({
|
|
1219
|
+
message: error.message,
|
|
1220
|
+
retryable: error.retryable,
|
|
1221
|
+
attempts: resolvedAttempts,
|
|
1222
|
+
status: error.status,
|
|
1223
|
+
errorCode: error.errorCode,
|
|
1224
|
+
serverMessage: error.serverMessage,
|
|
1225
|
+
requestId: error.requestId,
|
|
1226
|
+
cause: error.cause
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
const fallbackMessage = error instanceof Error ? error.message : "ingest request failed";
|
|
1230
|
+
return new IngestSendError({
|
|
1231
|
+
message: fallbackMessage,
|
|
1232
|
+
retryable: true,
|
|
1233
|
+
attempts: attempts ?? 1,
|
|
1234
|
+
cause: error
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1237
|
+
createIngestDiagnostics(error, batchSize, queueSize) {
|
|
1238
|
+
return {
|
|
1239
|
+
name: "AnalyticsIngestError",
|
|
1240
|
+
message: error.message,
|
|
1241
|
+
endpoint: this.endpoint,
|
|
1242
|
+
path: "/v1/collect",
|
|
1243
|
+
status: error.status,
|
|
1244
|
+
errorCode: error.errorCode,
|
|
1245
|
+
serverMessage: error.serverMessage,
|
|
1246
|
+
requestId: error.requestId,
|
|
1247
|
+
retryable: error.retryable,
|
|
1248
|
+
attempts: error.attempts,
|
|
1249
|
+
maxRetries: this.maxRetries,
|
|
1250
|
+
batchSize,
|
|
1251
|
+
queueSize,
|
|
1252
|
+
timestamp: nowIso()
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
reportIngestError(error) {
|
|
1256
|
+
if (!this.onIngestError) {
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
try {
|
|
1260
|
+
this.onIngestError(error);
|
|
1261
|
+
} catch (callbackError) {
|
|
1262
|
+
this.log("onIngestError callback threw", callbackError);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1136
1265
|
parsePersistedConsent(raw) {
|
|
1137
1266
|
if (raw === "granted") {
|
|
1138
1267
|
return true;
|
package/dist/index.cjs
CHANGED
|
@@ -587,6 +587,28 @@ var sanitizeSurveyResponseInput = (input) => {
|
|
|
587
587
|
|
|
588
588
|
// src/analytics-client.ts
|
|
589
589
|
var DEFAULT_CONSENT_STORAGE_KEY = "analyticscli:consent:v1";
|
|
590
|
+
var AUTH_FAILURE_FLUSH_PAUSE_MS = 6e4;
|
|
591
|
+
var IngestSendError = class extends Error {
|
|
592
|
+
retryable;
|
|
593
|
+
attempts;
|
|
594
|
+
status;
|
|
595
|
+
errorCode;
|
|
596
|
+
serverMessage;
|
|
597
|
+
requestId;
|
|
598
|
+
constructor(input) {
|
|
599
|
+
super(input.message);
|
|
600
|
+
this.name = "IngestSendError";
|
|
601
|
+
this.retryable = input.retryable;
|
|
602
|
+
this.attempts = input.attempts;
|
|
603
|
+
this.status = input.status;
|
|
604
|
+
this.errorCode = input.errorCode;
|
|
605
|
+
this.serverMessage = input.serverMessage;
|
|
606
|
+
this.requestId = input.requestId;
|
|
607
|
+
if (input.cause !== void 0) {
|
|
608
|
+
this.cause = input.cause;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
};
|
|
590
612
|
var AnalyticsClient = class {
|
|
591
613
|
apiKey;
|
|
592
614
|
hasIngestConfig;
|
|
@@ -595,6 +617,7 @@ var AnalyticsClient = class {
|
|
|
595
617
|
flushIntervalMs;
|
|
596
618
|
maxRetries;
|
|
597
619
|
debug;
|
|
620
|
+
onIngestError;
|
|
598
621
|
platform;
|
|
599
622
|
projectSurface;
|
|
600
623
|
appVersion;
|
|
@@ -627,6 +650,7 @@ var AnalyticsClient = class {
|
|
|
627
650
|
deferredEventsBeforeHydration = [];
|
|
628
651
|
onboardingStepViewStateSessionId = null;
|
|
629
652
|
onboardingStepViewsSeen = /* @__PURE__ */ new Set();
|
|
653
|
+
flushPausedUntilMs = 0;
|
|
630
654
|
constructor(options) {
|
|
631
655
|
const normalizedOptions = this.normalizeOptions(options);
|
|
632
656
|
this.apiKey = this.readRequiredStringOption(normalizedOptions.apiKey);
|
|
@@ -639,6 +663,7 @@ var AnalyticsClient = class {
|
|
|
639
663
|
this.flushIntervalMs = normalizedOptions.flushIntervalMs ?? 5e3;
|
|
640
664
|
this.maxRetries = normalizedOptions.maxRetries ?? 4;
|
|
641
665
|
this.debug = normalizedOptions.debug ?? false;
|
|
666
|
+
this.onIngestError = typeof normalizedOptions.onIngestError === "function" ? normalizedOptions.onIngestError : null;
|
|
642
667
|
this.platform = this.normalizePlatformOption(normalizedOptions.platform) ?? detectDefaultPlatform();
|
|
643
668
|
this.projectSurface = this.normalizeProjectSurfaceOption(normalizedOptions.projectSurface);
|
|
644
669
|
this.appVersion = this.readRequiredStringOption(normalizedOptions.appVersion) || detectDefaultAppVersion();
|
|
@@ -1102,6 +1127,9 @@ var AnalyticsClient = class {
|
|
|
1102
1127
|
if (this.queue.length === 0 || this.isFlushing || !this.consentGranted) {
|
|
1103
1128
|
return;
|
|
1104
1129
|
}
|
|
1130
|
+
if (Date.now() < this.flushPausedUntilMs) {
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1105
1133
|
this.isFlushing = true;
|
|
1106
1134
|
const batch = this.queue.splice(0, this.batchSize);
|
|
1107
1135
|
const payload = {
|
|
@@ -1116,9 +1144,20 @@ var AnalyticsClient = class {
|
|
|
1116
1144
|
}
|
|
1117
1145
|
try {
|
|
1118
1146
|
await this.sendWithRetry(payload);
|
|
1147
|
+
this.flushPausedUntilMs = 0;
|
|
1119
1148
|
} catch (error) {
|
|
1120
|
-
this.log("Send failed permanently, requeueing batch", error);
|
|
1121
1149
|
this.queue = [...batch, ...this.queue];
|
|
1150
|
+
const ingestError = this.toIngestSendError(error);
|
|
1151
|
+
const diagnostics = this.createIngestDiagnostics(ingestError, batch.length, this.queue.length);
|
|
1152
|
+
if (ingestError.status === 401 || ingestError.status === 403) {
|
|
1153
|
+
this.flushPausedUntilMs = Date.now() + AUTH_FAILURE_FLUSH_PAUSE_MS;
|
|
1154
|
+
this.log("Pausing ingest flush after auth failure", {
|
|
1155
|
+
status: ingestError.status,
|
|
1156
|
+
retryAfterMs: AUTH_FAILURE_FLUSH_PAUSE_MS
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
this.log("Send failed permanently, requeueing batch", diagnostics);
|
|
1160
|
+
this.reportIngestError(diagnostics);
|
|
1122
1161
|
} finally {
|
|
1123
1162
|
this.isFlushing = false;
|
|
1124
1163
|
}
|
|
@@ -1147,9 +1186,8 @@ var AnalyticsClient = class {
|
|
|
1147
1186
|
});
|
|
1148
1187
|
}
|
|
1149
1188
|
async sendWithRetry(payload) {
|
|
1150
|
-
let attempt = 0;
|
|
1151
1189
|
let delay = 250;
|
|
1152
|
-
|
|
1190
|
+
for (let attempt = 1; attempt <= this.maxRetries + 1; attempt += 1) {
|
|
1153
1191
|
try {
|
|
1154
1192
|
const response = await fetch(`${this.endpoint}/v1/collect`, {
|
|
1155
1193
|
method: "POST",
|
|
@@ -1161,19 +1199,110 @@ var AnalyticsClient = class {
|
|
|
1161
1199
|
keepalive: true
|
|
1162
1200
|
});
|
|
1163
1201
|
if (!response.ok) {
|
|
1164
|
-
throw
|
|
1202
|
+
throw await this.createHttpIngestSendError(response, attempt);
|
|
1165
1203
|
}
|
|
1166
1204
|
return;
|
|
1167
1205
|
} catch (error) {
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1206
|
+
const normalized = this.toIngestSendError(error, attempt);
|
|
1207
|
+
const finalAttempt = attempt >= this.maxRetries + 1;
|
|
1208
|
+
this.log("Ingest attempt failed", {
|
|
1209
|
+
attempt: normalized.attempts,
|
|
1210
|
+
maxRetries: this.maxRetries,
|
|
1211
|
+
retryable: normalized.retryable,
|
|
1212
|
+
status: normalized.status,
|
|
1213
|
+
errorCode: normalized.errorCode,
|
|
1214
|
+
requestId: normalized.requestId,
|
|
1215
|
+
nextRetryInMs: !finalAttempt && normalized.retryable ? delay : null
|
|
1216
|
+
});
|
|
1217
|
+
if (finalAttempt || !normalized.retryable) {
|
|
1218
|
+
throw normalized;
|
|
1171
1219
|
}
|
|
1172
1220
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1173
1221
|
delay *= 2;
|
|
1174
1222
|
}
|
|
1175
1223
|
}
|
|
1176
1224
|
}
|
|
1225
|
+
async createHttpIngestSendError(response, attempts) {
|
|
1226
|
+
const requestId = response.headers.get("x-request-id") ?? response.headers.get("cf-ray") ?? void 0;
|
|
1227
|
+
let errorCode;
|
|
1228
|
+
let serverMessage;
|
|
1229
|
+
try {
|
|
1230
|
+
const parsed = await response.json();
|
|
1231
|
+
const errorBody = parsed && typeof parsed === "object" && parsed.error && typeof parsed.error === "object" ? parsed.error : void 0;
|
|
1232
|
+
if (typeof errorBody?.code === "string") {
|
|
1233
|
+
errorCode = errorBody.code;
|
|
1234
|
+
}
|
|
1235
|
+
if (typeof errorBody?.message === "string") {
|
|
1236
|
+
serverMessage = errorBody.message;
|
|
1237
|
+
}
|
|
1238
|
+
} catch {
|
|
1239
|
+
}
|
|
1240
|
+
const retryable = this.shouldRetryHttpStatus(response.status);
|
|
1241
|
+
const statusSuffix = errorCode ? ` ${errorCode}` : "";
|
|
1242
|
+
const message = `ingest status=${response.status}${statusSuffix}`;
|
|
1243
|
+
return new IngestSendError({
|
|
1244
|
+
message,
|
|
1245
|
+
retryable,
|
|
1246
|
+
attempts,
|
|
1247
|
+
status: response.status,
|
|
1248
|
+
errorCode,
|
|
1249
|
+
serverMessage,
|
|
1250
|
+
requestId
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
shouldRetryHttpStatus(status) {
|
|
1254
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
1255
|
+
}
|
|
1256
|
+
toIngestSendError(error, attempts) {
|
|
1257
|
+
if (error instanceof IngestSendError) {
|
|
1258
|
+
const resolvedAttempts = attempts ?? error.attempts;
|
|
1259
|
+
return new IngestSendError({
|
|
1260
|
+
message: error.message,
|
|
1261
|
+
retryable: error.retryable,
|
|
1262
|
+
attempts: resolvedAttempts,
|
|
1263
|
+
status: error.status,
|
|
1264
|
+
errorCode: error.errorCode,
|
|
1265
|
+
serverMessage: error.serverMessage,
|
|
1266
|
+
requestId: error.requestId,
|
|
1267
|
+
cause: error.cause
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
const fallbackMessage = error instanceof Error ? error.message : "ingest request failed";
|
|
1271
|
+
return new IngestSendError({
|
|
1272
|
+
message: fallbackMessage,
|
|
1273
|
+
retryable: true,
|
|
1274
|
+
attempts: attempts ?? 1,
|
|
1275
|
+
cause: error
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
createIngestDiagnostics(error, batchSize, queueSize) {
|
|
1279
|
+
return {
|
|
1280
|
+
name: "AnalyticsIngestError",
|
|
1281
|
+
message: error.message,
|
|
1282
|
+
endpoint: this.endpoint,
|
|
1283
|
+
path: "/v1/collect",
|
|
1284
|
+
status: error.status,
|
|
1285
|
+
errorCode: error.errorCode,
|
|
1286
|
+
serverMessage: error.serverMessage,
|
|
1287
|
+
requestId: error.requestId,
|
|
1288
|
+
retryable: error.retryable,
|
|
1289
|
+
attempts: error.attempts,
|
|
1290
|
+
maxRetries: this.maxRetries,
|
|
1291
|
+
batchSize,
|
|
1292
|
+
queueSize,
|
|
1293
|
+
timestamp: nowIso()
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
reportIngestError(error) {
|
|
1297
|
+
if (!this.onIngestError) {
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
try {
|
|
1301
|
+
this.onIngestError(error);
|
|
1302
|
+
} catch (callbackError) {
|
|
1303
|
+
this.log("onIngestError callback threw", callbackError);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1177
1306
|
parsePersistedConsent(raw) {
|
|
1178
1307
|
if (raw === "granted") {
|
|
1179
1308
|
return true;
|
package/dist/index.d.cts
CHANGED
|
@@ -130,6 +130,65 @@ type PaywallTracker = {
|
|
|
130
130
|
};
|
|
131
131
|
type AnalyticsConsentState = 'granted' | 'denied' | 'unknown';
|
|
132
132
|
type IdentityTrackingMode = 'strict' | 'consent_gated' | 'always_on';
|
|
133
|
+
type AnalyticsIngestError = {
|
|
134
|
+
/**
|
|
135
|
+
* Stable error name for host-app monitoring.
|
|
136
|
+
*/
|
|
137
|
+
name: 'AnalyticsIngestError';
|
|
138
|
+
/**
|
|
139
|
+
* Human-readable summary of the ingest failure.
|
|
140
|
+
*/
|
|
141
|
+
message: string;
|
|
142
|
+
/**
|
|
143
|
+
* Collector endpoint base URL configured in the SDK client.
|
|
144
|
+
*/
|
|
145
|
+
endpoint: string;
|
|
146
|
+
/**
|
|
147
|
+
* Collector path that failed.
|
|
148
|
+
*/
|
|
149
|
+
path: '/v1/collect';
|
|
150
|
+
/**
|
|
151
|
+
* HTTP status when available.
|
|
152
|
+
*/
|
|
153
|
+
status?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Structured server error code when available.
|
|
156
|
+
*/
|
|
157
|
+
errorCode?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Structured server message when available.
|
|
160
|
+
*/
|
|
161
|
+
serverMessage?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Request correlation id when exposed by the collector response.
|
|
164
|
+
*/
|
|
165
|
+
requestId?: string;
|
|
166
|
+
/**
|
|
167
|
+
* Whether retrying can help (`true` for network/5xx/429 class failures).
|
|
168
|
+
*/
|
|
169
|
+
retryable: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Number of attempts that were made for this batch.
|
|
172
|
+
*/
|
|
173
|
+
attempts: number;
|
|
174
|
+
/**
|
|
175
|
+
* SDK max retries configured on the client.
|
|
176
|
+
*/
|
|
177
|
+
maxRetries: number;
|
|
178
|
+
/**
|
|
179
|
+
* Number of events in the failed batch.
|
|
180
|
+
*/
|
|
181
|
+
batchSize: number;
|
|
182
|
+
/**
|
|
183
|
+
* Current queue size after requeue.
|
|
184
|
+
*/
|
|
185
|
+
queueSize: number;
|
|
186
|
+
/**
|
|
187
|
+
* ISO timestamp when the failure was surfaced to host-app callbacks.
|
|
188
|
+
*/
|
|
189
|
+
timestamp: string;
|
|
190
|
+
};
|
|
191
|
+
type AnalyticsIngestErrorHandler = (error: AnalyticsIngestError) => void;
|
|
133
192
|
type SetConsentOptions = {
|
|
134
193
|
/**
|
|
135
194
|
* Whether consent state should be persisted to storage when enabled.
|
|
@@ -158,6 +217,14 @@ type AnalyticsClientOptions = {
|
|
|
158
217
|
* `debug: __DEV__`
|
|
159
218
|
*/
|
|
160
219
|
debug?: boolean | null;
|
|
220
|
+
/**
|
|
221
|
+
* Optional host-app hook for ingest delivery failures.
|
|
222
|
+
* Use this to forward operational diagnostics to your own monitoring stack.
|
|
223
|
+
*
|
|
224
|
+
* GDPR recommendation:
|
|
225
|
+
* forward this structured metadata only and avoid attaching event payloads or raw identifiers.
|
|
226
|
+
*/
|
|
227
|
+
onIngestError?: AnalyticsIngestErrorHandler | null;
|
|
161
228
|
/**
|
|
162
229
|
* Optional platform hint.
|
|
163
230
|
* React Native/Expo: passing `Platform.OS` directly is supported.
|
|
@@ -246,6 +313,7 @@ declare class AnalyticsClient {
|
|
|
246
313
|
private readonly flushIntervalMs;
|
|
247
314
|
private readonly maxRetries;
|
|
248
315
|
private readonly debug;
|
|
316
|
+
private readonly onIngestError;
|
|
249
317
|
private readonly platform;
|
|
250
318
|
private readonly projectSurface;
|
|
251
319
|
private readonly appVersion;
|
|
@@ -278,6 +346,7 @@ declare class AnalyticsClient {
|
|
|
278
346
|
private deferredEventsBeforeHydration;
|
|
279
347
|
private onboardingStepViewStateSessionId;
|
|
280
348
|
private onboardingStepViewsSeen;
|
|
349
|
+
private flushPausedUntilMs;
|
|
281
350
|
constructor(options: AnalyticsClientOptions);
|
|
282
351
|
/**
|
|
283
352
|
* Resolves once client initialization work completes.
|
|
@@ -373,6 +442,11 @@ declare class AnalyticsClient {
|
|
|
373
442
|
private enqueue;
|
|
374
443
|
private scheduleFlush;
|
|
375
444
|
private sendWithRetry;
|
|
445
|
+
private createHttpIngestSendError;
|
|
446
|
+
private shouldRetryHttpStatus;
|
|
447
|
+
private toIngestSendError;
|
|
448
|
+
private createIngestDiagnostics;
|
|
449
|
+
private reportIngestError;
|
|
376
450
|
private parsePersistedConsent;
|
|
377
451
|
private readPersistedConsentSync;
|
|
378
452
|
private readPersistedConsentAsync;
|
|
@@ -489,4 +563,4 @@ declare const initConsentFirst: (input?: InitInput) => AnalyticsClient;
|
|
|
489
563
|
declare const initAsync: (input?: InitInput) => Promise<AnalyticsClient>;
|
|
490
564
|
declare const initConsentFirstAsync: (input?: InitInput) => Promise<AnalyticsClient>;
|
|
491
565
|
|
|
492
|
-
export { AnalyticsClient, type AnalyticsClientOptions, type AnalyticsConsentState, type AnalyticsContext, type AnalyticsContextConsentControls, type AnalyticsContextUserControls, type AnalyticsStorageAdapter, type CreateAnalyticsContextOptions, type EventContext, type EventProperties, type IdentityTrackingMode, type InitInput, type InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, type OnboardingEventName, type OnboardingEventProperties, type OnboardingStepTracker, type OnboardingSurveyAnswerType, type OnboardingSurveyEventName, type OnboardingSurveyResponseInput, type OnboardingTracker, type OnboardingTrackerDefaults, type OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, type PaywallEventName, type PaywallEventProperties, type PaywallJourneyEventName, type PaywallTracker, type PaywallTrackerDefaults, type PaywallTrackerProperties, type PurchaseEventName, type SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync };
|
|
566
|
+
export { AnalyticsClient, type AnalyticsClientOptions, type AnalyticsConsentState, type AnalyticsContext, type AnalyticsContextConsentControls, type AnalyticsContextUserControls, type AnalyticsIngestError, type AnalyticsIngestErrorHandler, type AnalyticsStorageAdapter, type CreateAnalyticsContextOptions, type EventContext, type EventProperties, type IdentityTrackingMode, type InitInput, type InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, type OnboardingEventName, type OnboardingEventProperties, type OnboardingStepTracker, type OnboardingSurveyAnswerType, type OnboardingSurveyEventName, type OnboardingSurveyResponseInput, type OnboardingTracker, type OnboardingTrackerDefaults, type OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, type PaywallEventName, type PaywallEventProperties, type PaywallJourneyEventName, type PaywallTracker, type PaywallTrackerDefaults, type PaywallTrackerProperties, type PurchaseEventName, type SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync };
|
package/dist/index.d.ts
CHANGED
|
@@ -130,6 +130,65 @@ type PaywallTracker = {
|
|
|
130
130
|
};
|
|
131
131
|
type AnalyticsConsentState = 'granted' | 'denied' | 'unknown';
|
|
132
132
|
type IdentityTrackingMode = 'strict' | 'consent_gated' | 'always_on';
|
|
133
|
+
type AnalyticsIngestError = {
|
|
134
|
+
/**
|
|
135
|
+
* Stable error name for host-app monitoring.
|
|
136
|
+
*/
|
|
137
|
+
name: 'AnalyticsIngestError';
|
|
138
|
+
/**
|
|
139
|
+
* Human-readable summary of the ingest failure.
|
|
140
|
+
*/
|
|
141
|
+
message: string;
|
|
142
|
+
/**
|
|
143
|
+
* Collector endpoint base URL configured in the SDK client.
|
|
144
|
+
*/
|
|
145
|
+
endpoint: string;
|
|
146
|
+
/**
|
|
147
|
+
* Collector path that failed.
|
|
148
|
+
*/
|
|
149
|
+
path: '/v1/collect';
|
|
150
|
+
/**
|
|
151
|
+
* HTTP status when available.
|
|
152
|
+
*/
|
|
153
|
+
status?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Structured server error code when available.
|
|
156
|
+
*/
|
|
157
|
+
errorCode?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Structured server message when available.
|
|
160
|
+
*/
|
|
161
|
+
serverMessage?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Request correlation id when exposed by the collector response.
|
|
164
|
+
*/
|
|
165
|
+
requestId?: string;
|
|
166
|
+
/**
|
|
167
|
+
* Whether retrying can help (`true` for network/5xx/429 class failures).
|
|
168
|
+
*/
|
|
169
|
+
retryable: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Number of attempts that were made for this batch.
|
|
172
|
+
*/
|
|
173
|
+
attempts: number;
|
|
174
|
+
/**
|
|
175
|
+
* SDK max retries configured on the client.
|
|
176
|
+
*/
|
|
177
|
+
maxRetries: number;
|
|
178
|
+
/**
|
|
179
|
+
* Number of events in the failed batch.
|
|
180
|
+
*/
|
|
181
|
+
batchSize: number;
|
|
182
|
+
/**
|
|
183
|
+
* Current queue size after requeue.
|
|
184
|
+
*/
|
|
185
|
+
queueSize: number;
|
|
186
|
+
/**
|
|
187
|
+
* ISO timestamp when the failure was surfaced to host-app callbacks.
|
|
188
|
+
*/
|
|
189
|
+
timestamp: string;
|
|
190
|
+
};
|
|
191
|
+
type AnalyticsIngestErrorHandler = (error: AnalyticsIngestError) => void;
|
|
133
192
|
type SetConsentOptions = {
|
|
134
193
|
/**
|
|
135
194
|
* Whether consent state should be persisted to storage when enabled.
|
|
@@ -158,6 +217,14 @@ type AnalyticsClientOptions = {
|
|
|
158
217
|
* `debug: __DEV__`
|
|
159
218
|
*/
|
|
160
219
|
debug?: boolean | null;
|
|
220
|
+
/**
|
|
221
|
+
* Optional host-app hook for ingest delivery failures.
|
|
222
|
+
* Use this to forward operational diagnostics to your own monitoring stack.
|
|
223
|
+
*
|
|
224
|
+
* GDPR recommendation:
|
|
225
|
+
* forward this structured metadata only and avoid attaching event payloads or raw identifiers.
|
|
226
|
+
*/
|
|
227
|
+
onIngestError?: AnalyticsIngestErrorHandler | null;
|
|
161
228
|
/**
|
|
162
229
|
* Optional platform hint.
|
|
163
230
|
* React Native/Expo: passing `Platform.OS` directly is supported.
|
|
@@ -246,6 +313,7 @@ declare class AnalyticsClient {
|
|
|
246
313
|
private readonly flushIntervalMs;
|
|
247
314
|
private readonly maxRetries;
|
|
248
315
|
private readonly debug;
|
|
316
|
+
private readonly onIngestError;
|
|
249
317
|
private readonly platform;
|
|
250
318
|
private readonly projectSurface;
|
|
251
319
|
private readonly appVersion;
|
|
@@ -278,6 +346,7 @@ declare class AnalyticsClient {
|
|
|
278
346
|
private deferredEventsBeforeHydration;
|
|
279
347
|
private onboardingStepViewStateSessionId;
|
|
280
348
|
private onboardingStepViewsSeen;
|
|
349
|
+
private flushPausedUntilMs;
|
|
281
350
|
constructor(options: AnalyticsClientOptions);
|
|
282
351
|
/**
|
|
283
352
|
* Resolves once client initialization work completes.
|
|
@@ -373,6 +442,11 @@ declare class AnalyticsClient {
|
|
|
373
442
|
private enqueue;
|
|
374
443
|
private scheduleFlush;
|
|
375
444
|
private sendWithRetry;
|
|
445
|
+
private createHttpIngestSendError;
|
|
446
|
+
private shouldRetryHttpStatus;
|
|
447
|
+
private toIngestSendError;
|
|
448
|
+
private createIngestDiagnostics;
|
|
449
|
+
private reportIngestError;
|
|
376
450
|
private parsePersistedConsent;
|
|
377
451
|
private readPersistedConsentSync;
|
|
378
452
|
private readPersistedConsentAsync;
|
|
@@ -489,4 +563,4 @@ declare const initConsentFirst: (input?: InitInput) => AnalyticsClient;
|
|
|
489
563
|
declare const initAsync: (input?: InitInput) => Promise<AnalyticsClient>;
|
|
490
564
|
declare const initConsentFirstAsync: (input?: InitInput) => Promise<AnalyticsClient>;
|
|
491
565
|
|
|
492
|
-
export { AnalyticsClient, type AnalyticsClientOptions, type AnalyticsConsentState, type AnalyticsContext, type AnalyticsContextConsentControls, type AnalyticsContextUserControls, type AnalyticsStorageAdapter, type CreateAnalyticsContextOptions, type EventContext, type EventProperties, type IdentityTrackingMode, type InitInput, type InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, type OnboardingEventName, type OnboardingEventProperties, type OnboardingStepTracker, type OnboardingSurveyAnswerType, type OnboardingSurveyEventName, type OnboardingSurveyResponseInput, type OnboardingTracker, type OnboardingTrackerDefaults, type OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, type PaywallEventName, type PaywallEventProperties, type PaywallJourneyEventName, type PaywallTracker, type PaywallTrackerDefaults, type PaywallTrackerProperties, type PurchaseEventName, type SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync };
|
|
566
|
+
export { AnalyticsClient, type AnalyticsClientOptions, type AnalyticsConsentState, type AnalyticsContext, type AnalyticsContextConsentControls, type AnalyticsContextUserControls, type AnalyticsIngestError, type AnalyticsIngestErrorHandler, type AnalyticsStorageAdapter, type CreateAnalyticsContextOptions, type EventContext, type EventProperties, type IdentityTrackingMode, type InitInput, type InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, type OnboardingEventName, type OnboardingEventProperties, type OnboardingStepTracker, type OnboardingSurveyAnswerType, type OnboardingSurveyEventName, type OnboardingSurveyResponseInput, type OnboardingTracker, type OnboardingTrackerDefaults, type OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, type PaywallEventName, type PaywallEventProperties, type PaywallJourneyEventName, type PaywallTracker, type PaywallTrackerDefaults, type PaywallTrackerProperties, type PurchaseEventName, type SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync };
|
package/dist/index.js
CHANGED
package/dist/react-native.cjs
CHANGED
|
@@ -587,6 +587,28 @@ var sanitizeSurveyResponseInput = (input) => {
|
|
|
587
587
|
|
|
588
588
|
// src/analytics-client.ts
|
|
589
589
|
var DEFAULT_CONSENT_STORAGE_KEY = "analyticscli:consent:v1";
|
|
590
|
+
var AUTH_FAILURE_FLUSH_PAUSE_MS = 6e4;
|
|
591
|
+
var IngestSendError = class extends Error {
|
|
592
|
+
retryable;
|
|
593
|
+
attempts;
|
|
594
|
+
status;
|
|
595
|
+
errorCode;
|
|
596
|
+
serverMessage;
|
|
597
|
+
requestId;
|
|
598
|
+
constructor(input) {
|
|
599
|
+
super(input.message);
|
|
600
|
+
this.name = "IngestSendError";
|
|
601
|
+
this.retryable = input.retryable;
|
|
602
|
+
this.attempts = input.attempts;
|
|
603
|
+
this.status = input.status;
|
|
604
|
+
this.errorCode = input.errorCode;
|
|
605
|
+
this.serverMessage = input.serverMessage;
|
|
606
|
+
this.requestId = input.requestId;
|
|
607
|
+
if (input.cause !== void 0) {
|
|
608
|
+
this.cause = input.cause;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
};
|
|
590
612
|
var AnalyticsClient = class {
|
|
591
613
|
apiKey;
|
|
592
614
|
hasIngestConfig;
|
|
@@ -595,6 +617,7 @@ var AnalyticsClient = class {
|
|
|
595
617
|
flushIntervalMs;
|
|
596
618
|
maxRetries;
|
|
597
619
|
debug;
|
|
620
|
+
onIngestError;
|
|
598
621
|
platform;
|
|
599
622
|
projectSurface;
|
|
600
623
|
appVersion;
|
|
@@ -627,6 +650,7 @@ var AnalyticsClient = class {
|
|
|
627
650
|
deferredEventsBeforeHydration = [];
|
|
628
651
|
onboardingStepViewStateSessionId = null;
|
|
629
652
|
onboardingStepViewsSeen = /* @__PURE__ */ new Set();
|
|
653
|
+
flushPausedUntilMs = 0;
|
|
630
654
|
constructor(options) {
|
|
631
655
|
const normalizedOptions = this.normalizeOptions(options);
|
|
632
656
|
this.apiKey = this.readRequiredStringOption(normalizedOptions.apiKey);
|
|
@@ -639,6 +663,7 @@ var AnalyticsClient = class {
|
|
|
639
663
|
this.flushIntervalMs = normalizedOptions.flushIntervalMs ?? 5e3;
|
|
640
664
|
this.maxRetries = normalizedOptions.maxRetries ?? 4;
|
|
641
665
|
this.debug = normalizedOptions.debug ?? false;
|
|
666
|
+
this.onIngestError = typeof normalizedOptions.onIngestError === "function" ? normalizedOptions.onIngestError : null;
|
|
642
667
|
this.platform = this.normalizePlatformOption(normalizedOptions.platform) ?? detectDefaultPlatform();
|
|
643
668
|
this.projectSurface = this.normalizeProjectSurfaceOption(normalizedOptions.projectSurface);
|
|
644
669
|
this.appVersion = this.readRequiredStringOption(normalizedOptions.appVersion) || detectDefaultAppVersion();
|
|
@@ -1102,6 +1127,9 @@ var AnalyticsClient = class {
|
|
|
1102
1127
|
if (this.queue.length === 0 || this.isFlushing || !this.consentGranted) {
|
|
1103
1128
|
return;
|
|
1104
1129
|
}
|
|
1130
|
+
if (Date.now() < this.flushPausedUntilMs) {
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1105
1133
|
this.isFlushing = true;
|
|
1106
1134
|
const batch = this.queue.splice(0, this.batchSize);
|
|
1107
1135
|
const payload = {
|
|
@@ -1116,9 +1144,20 @@ var AnalyticsClient = class {
|
|
|
1116
1144
|
}
|
|
1117
1145
|
try {
|
|
1118
1146
|
await this.sendWithRetry(payload);
|
|
1147
|
+
this.flushPausedUntilMs = 0;
|
|
1119
1148
|
} catch (error) {
|
|
1120
|
-
this.log("Send failed permanently, requeueing batch", error);
|
|
1121
1149
|
this.queue = [...batch, ...this.queue];
|
|
1150
|
+
const ingestError = this.toIngestSendError(error);
|
|
1151
|
+
const diagnostics = this.createIngestDiagnostics(ingestError, batch.length, this.queue.length);
|
|
1152
|
+
if (ingestError.status === 401 || ingestError.status === 403) {
|
|
1153
|
+
this.flushPausedUntilMs = Date.now() + AUTH_FAILURE_FLUSH_PAUSE_MS;
|
|
1154
|
+
this.log("Pausing ingest flush after auth failure", {
|
|
1155
|
+
status: ingestError.status,
|
|
1156
|
+
retryAfterMs: AUTH_FAILURE_FLUSH_PAUSE_MS
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
this.log("Send failed permanently, requeueing batch", diagnostics);
|
|
1160
|
+
this.reportIngestError(diagnostics);
|
|
1122
1161
|
} finally {
|
|
1123
1162
|
this.isFlushing = false;
|
|
1124
1163
|
}
|
|
@@ -1147,9 +1186,8 @@ var AnalyticsClient = class {
|
|
|
1147
1186
|
});
|
|
1148
1187
|
}
|
|
1149
1188
|
async sendWithRetry(payload) {
|
|
1150
|
-
let attempt = 0;
|
|
1151
1189
|
let delay = 250;
|
|
1152
|
-
|
|
1190
|
+
for (let attempt = 1; attempt <= this.maxRetries + 1; attempt += 1) {
|
|
1153
1191
|
try {
|
|
1154
1192
|
const response = await fetch(`${this.endpoint}/v1/collect`, {
|
|
1155
1193
|
method: "POST",
|
|
@@ -1161,19 +1199,110 @@ var AnalyticsClient = class {
|
|
|
1161
1199
|
keepalive: true
|
|
1162
1200
|
});
|
|
1163
1201
|
if (!response.ok) {
|
|
1164
|
-
throw
|
|
1202
|
+
throw await this.createHttpIngestSendError(response, attempt);
|
|
1165
1203
|
}
|
|
1166
1204
|
return;
|
|
1167
1205
|
} catch (error) {
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1206
|
+
const normalized = this.toIngestSendError(error, attempt);
|
|
1207
|
+
const finalAttempt = attempt >= this.maxRetries + 1;
|
|
1208
|
+
this.log("Ingest attempt failed", {
|
|
1209
|
+
attempt: normalized.attempts,
|
|
1210
|
+
maxRetries: this.maxRetries,
|
|
1211
|
+
retryable: normalized.retryable,
|
|
1212
|
+
status: normalized.status,
|
|
1213
|
+
errorCode: normalized.errorCode,
|
|
1214
|
+
requestId: normalized.requestId,
|
|
1215
|
+
nextRetryInMs: !finalAttempt && normalized.retryable ? delay : null
|
|
1216
|
+
});
|
|
1217
|
+
if (finalAttempt || !normalized.retryable) {
|
|
1218
|
+
throw normalized;
|
|
1171
1219
|
}
|
|
1172
1220
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1173
1221
|
delay *= 2;
|
|
1174
1222
|
}
|
|
1175
1223
|
}
|
|
1176
1224
|
}
|
|
1225
|
+
async createHttpIngestSendError(response, attempts) {
|
|
1226
|
+
const requestId = response.headers.get("x-request-id") ?? response.headers.get("cf-ray") ?? void 0;
|
|
1227
|
+
let errorCode;
|
|
1228
|
+
let serverMessage;
|
|
1229
|
+
try {
|
|
1230
|
+
const parsed = await response.json();
|
|
1231
|
+
const errorBody = parsed && typeof parsed === "object" && parsed.error && typeof parsed.error === "object" ? parsed.error : void 0;
|
|
1232
|
+
if (typeof errorBody?.code === "string") {
|
|
1233
|
+
errorCode = errorBody.code;
|
|
1234
|
+
}
|
|
1235
|
+
if (typeof errorBody?.message === "string") {
|
|
1236
|
+
serverMessage = errorBody.message;
|
|
1237
|
+
}
|
|
1238
|
+
} catch {
|
|
1239
|
+
}
|
|
1240
|
+
const retryable = this.shouldRetryHttpStatus(response.status);
|
|
1241
|
+
const statusSuffix = errorCode ? ` ${errorCode}` : "";
|
|
1242
|
+
const message = `ingest status=${response.status}${statusSuffix}`;
|
|
1243
|
+
return new IngestSendError({
|
|
1244
|
+
message,
|
|
1245
|
+
retryable,
|
|
1246
|
+
attempts,
|
|
1247
|
+
status: response.status,
|
|
1248
|
+
errorCode,
|
|
1249
|
+
serverMessage,
|
|
1250
|
+
requestId
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
shouldRetryHttpStatus(status) {
|
|
1254
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
1255
|
+
}
|
|
1256
|
+
toIngestSendError(error, attempts) {
|
|
1257
|
+
if (error instanceof IngestSendError) {
|
|
1258
|
+
const resolvedAttempts = attempts ?? error.attempts;
|
|
1259
|
+
return new IngestSendError({
|
|
1260
|
+
message: error.message,
|
|
1261
|
+
retryable: error.retryable,
|
|
1262
|
+
attempts: resolvedAttempts,
|
|
1263
|
+
status: error.status,
|
|
1264
|
+
errorCode: error.errorCode,
|
|
1265
|
+
serverMessage: error.serverMessage,
|
|
1266
|
+
requestId: error.requestId,
|
|
1267
|
+
cause: error.cause
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
const fallbackMessage = error instanceof Error ? error.message : "ingest request failed";
|
|
1271
|
+
return new IngestSendError({
|
|
1272
|
+
message: fallbackMessage,
|
|
1273
|
+
retryable: true,
|
|
1274
|
+
attempts: attempts ?? 1,
|
|
1275
|
+
cause: error
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
createIngestDiagnostics(error, batchSize, queueSize) {
|
|
1279
|
+
return {
|
|
1280
|
+
name: "AnalyticsIngestError",
|
|
1281
|
+
message: error.message,
|
|
1282
|
+
endpoint: this.endpoint,
|
|
1283
|
+
path: "/v1/collect",
|
|
1284
|
+
status: error.status,
|
|
1285
|
+
errorCode: error.errorCode,
|
|
1286
|
+
serverMessage: error.serverMessage,
|
|
1287
|
+
requestId: error.requestId,
|
|
1288
|
+
retryable: error.retryable,
|
|
1289
|
+
attempts: error.attempts,
|
|
1290
|
+
maxRetries: this.maxRetries,
|
|
1291
|
+
batchSize,
|
|
1292
|
+
queueSize,
|
|
1293
|
+
timestamp: nowIso()
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
reportIngestError(error) {
|
|
1297
|
+
if (!this.onIngestError) {
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
try {
|
|
1301
|
+
this.onIngestError(error);
|
|
1302
|
+
} catch (callbackError) {
|
|
1303
|
+
this.log("onIngestError callback threw", callbackError);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1177
1306
|
parsePersistedConsent(raw) {
|
|
1178
1307
|
if (raw === "granted") {
|
|
1179
1308
|
return true;
|
package/dist/react-native.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { AnalyticsClient, AnalyticsClientOptions, AnalyticsConsentState, AnalyticsContext, AnalyticsContextConsentControls, AnalyticsContextUserControls, AnalyticsStorageAdapter, CreateAnalyticsContextOptions, EventContext, EventProperties, IdentityTrackingMode, InitInput, InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, OnboardingEventName, OnboardingEventProperties, OnboardingStepTracker, OnboardingSurveyAnswerType, OnboardingSurveyEventName, OnboardingSurveyResponseInput, OnboardingTracker, OnboardingTrackerDefaults, OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, PaywallEventName, PaywallEventProperties, PaywallJourneyEventName, PaywallTracker, PaywallTrackerDefaults, PaywallTrackerProperties, PurchaseEventName, SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync } from './index.cjs';
|
|
1
|
+
export { AnalyticsClient, AnalyticsClientOptions, AnalyticsConsentState, AnalyticsContext, AnalyticsContextConsentControls, AnalyticsContextUserControls, AnalyticsIngestError, AnalyticsIngestErrorHandler, AnalyticsStorageAdapter, CreateAnalyticsContextOptions, EventContext, EventProperties, IdentityTrackingMode, InitInput, InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, OnboardingEventName, OnboardingEventProperties, OnboardingStepTracker, OnboardingSurveyAnswerType, OnboardingSurveyEventName, OnboardingSurveyResponseInput, OnboardingTracker, OnboardingTrackerDefaults, OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, PaywallEventName, PaywallEventProperties, PaywallJourneyEventName, PaywallTracker, PaywallTrackerDefaults, PaywallTrackerProperties, PurchaseEventName, SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync } from './index.cjs';
|
package/dist/react-native.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { AnalyticsClient, AnalyticsClientOptions, AnalyticsConsentState, AnalyticsContext, AnalyticsContextConsentControls, AnalyticsContextUserControls, AnalyticsStorageAdapter, CreateAnalyticsContextOptions, EventContext, EventProperties, IdentityTrackingMode, InitInput, InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, OnboardingEventName, OnboardingEventProperties, OnboardingStepTracker, OnboardingSurveyAnswerType, OnboardingSurveyEventName, OnboardingSurveyResponseInput, OnboardingTracker, OnboardingTrackerDefaults, OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, PaywallEventName, PaywallEventProperties, PaywallJourneyEventName, PaywallTracker, PaywallTrackerDefaults, PaywallTrackerProperties, PurchaseEventName, SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync } from './index.js';
|
|
1
|
+
export { AnalyticsClient, AnalyticsClientOptions, AnalyticsConsentState, AnalyticsContext, AnalyticsContextConsentControls, AnalyticsContextUserControls, AnalyticsIngestError, AnalyticsIngestErrorHandler, AnalyticsStorageAdapter, CreateAnalyticsContextOptions, EventContext, EventProperties, IdentityTrackingMode, InitInput, InitOptions, ONBOARDING_EVENTS, ONBOARDING_PROGRESS_EVENT_ORDER, ONBOARDING_SCREEN_EVENT_PREFIXES, ONBOARDING_SURVEY_EVENTS, OnboardingEventName, OnboardingEventProperties, OnboardingStepTracker, OnboardingSurveyAnswerType, OnboardingSurveyEventName, OnboardingSurveyResponseInput, OnboardingTracker, OnboardingTrackerDefaults, OnboardingTrackerSurveyInput, PAYWALL_ANCHOR_EVENT_CANDIDATES, PAYWALL_EVENTS, PAYWALL_JOURNEY_EVENT_ORDER, PAYWALL_SKIP_EVENT_CANDIDATES, PURCHASE_EVENTS, PURCHASE_SUCCESS_EVENT_CANDIDATES, PaywallEventName, PaywallEventProperties, PaywallJourneyEventName, PaywallTracker, PaywallTrackerDefaults, PaywallTrackerProperties, PurchaseEventName, SetConsentOptions, createAnalyticsContext, init, initAsync, initConsentFirst, initConsentFirstAsync } from './index.js';
|
package/dist/react-native.js
CHANGED
package/package.json
CHANGED