@wireai/activation 0.10.0 → 0.12.0
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/AGENTS.md +51 -0
- package/CHANGELOG.md +111 -1
- package/INTEGRATION_PROMPT.md +13 -1
- package/README.md +106 -4
- package/dist/analytics/index.d.mts +35 -6
- package/dist/analytics/index.d.ts +35 -6
- package/dist/analytics/index.js +222 -94
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +214 -95
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/{currentSession-D0Vq7_VE.d.ts → currentSession-D6RiVtc8.d.ts} +187 -29
- package/dist/{currentSession-DdDkprpM.d.mts → currentSession-DsSDHqor.d.mts} +187 -29
- package/dist/index.d.mts +236 -82
- package/dist/index.d.ts +236 -82
- package/dist/index.js +330 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +314 -61
- package/dist/index.mjs.map +1 -1
- package/dist/questionnaire/index.d.mts +1 -1
- package/dist/questionnaire/index.d.ts +1 -1
- package/dist/questionnaire/index.js +59 -8
- package/dist/questionnaire/index.js.map +1 -1
- package/dist/questionnaire/index.mjs +59 -8
- package/dist/questionnaire/index.mjs.map +1 -1
- package/dist/reviews/index.d.mts +2 -2
- package/dist/reviews/index.d.ts +2 -2
- package/dist/reviews/index.js +97 -17
- package/dist/reviews/index.js.map +1 -1
- package/dist/reviews/index.mjs +97 -17
- package/dist/reviews/index.mjs.map +1 -1
- package/dist/{transport-Bzb-bcB2.d.mts → transport-CF_eHwzC.d.mts} +15 -16
- package/dist/{transport-B31G0Cib.d.ts → transport-DsRe4epC.d.ts} +15 -16
- package/llms.txt +9 -0
- package/package.json +1 -1
- package/src/activation/useWireActivation.ts +12 -1
- package/src/activation/wireActivation.ts +36 -24
- package/src/analytics/analyticsFacade.ts +113 -29
- package/src/analytics/currentSession.ts +83 -0
- package/src/analytics/eventQueue.ts +20 -11
- package/src/analytics/index.ts +29 -1
- package/src/analytics/reportClientEvent.ts +50 -2
- package/src/analytics/screenTracking.ts +6 -1
- package/src/analytics/useAnalytics.ts +22 -1
- package/src/context/deviceId.ts +109 -0
- package/src/context/userContext.ts +73 -0
- package/src/identity/userIdentity.ts +10 -0
- package/src/index.ts +50 -2
- package/src/questionnaire/runtime.ts +12 -2
- package/src/questionnaire/transport.ts +5 -1
- package/src/questionnaire/useQuestionnaireGate.ts +9 -7
- package/src/revenuecat/index.ts +55 -0
- package/src/revenuecat/purchaseEvents.ts +167 -0
- package/src/revenuecat/revenueCatBridge.ts +221 -0
- package/src/revenuecat/types.ts +95 -0
- package/src/reviews/decision.ts +8 -1
- package/src/reviews/runtime.ts +92 -1
- package/src/reviews/transport.ts +27 -10
- package/src/reviews/useReviewGate.ts +12 -7
- package/src/session-analytics/lifecycle.ts +15 -13
- package/src/session-analytics/reportSessionStart.ts +15 -4
- package/src/session-analytics/useLifecycleEvents.ts +68 -28
package/dist/index.js
CHANGED
|
@@ -1518,6 +1518,23 @@ var buildEventsRequest = (target, events) => {
|
|
|
1518
1518
|
return null;
|
|
1519
1519
|
}
|
|
1520
1520
|
};
|
|
1521
|
+
var warnOnSkippedEvents = (res) => {
|
|
1522
|
+
try {
|
|
1523
|
+
const json = res == null ? void 0 : res.json;
|
|
1524
|
+
if (typeof json !== "function") return;
|
|
1525
|
+
void Promise.resolve(json.call(res)).then((body) => {
|
|
1526
|
+
const skipped = body == null ? void 0 : body.skipped;
|
|
1527
|
+
if (typeof skipped !== "number" || skipped <= 0) return;
|
|
1528
|
+
if (typeof __DEV__ !== "undefined" && __DEV__ && typeof console !== "undefined" && console.warn) {
|
|
1529
|
+
console.warn(
|
|
1530
|
+
`[wireai] the server ACCEPTED the /v1/events POST but DISCARDED ${skipped} event(s) (skipped in the response body) \u2014 they are gone, not retried. The usual cause is an event with a missing or empty session_id.`
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
}).catch(() => {
|
|
1534
|
+
});
|
|
1535
|
+
} catch {
|
|
1536
|
+
}
|
|
1537
|
+
};
|
|
1521
1538
|
var reportClientEvents = (target, events) => {
|
|
1522
1539
|
try {
|
|
1523
1540
|
const req = buildEventsRequest(target, events);
|
|
@@ -3314,6 +3331,28 @@ var getCurrentSessionId = () => globalSlot[CURRENT_SESSION_ID_SLOT];
|
|
|
3314
3331
|
var resetCurrentSessionId = () => {
|
|
3315
3332
|
globalSlot[CURRENT_SESSION_ID_SLOT] = void 0;
|
|
3316
3333
|
};
|
|
3334
|
+
var warnInDev = (message) => {
|
|
3335
|
+
if (typeof __DEV__ !== "undefined" && __DEV__ && typeof console !== "undefined" && console.warn) {
|
|
3336
|
+
console.warn(message);
|
|
3337
|
+
return true;
|
|
3338
|
+
}
|
|
3339
|
+
return false;
|
|
3340
|
+
};
|
|
3341
|
+
var MINT_WARNING = "[wireai] No app-open session was registered, so a session id was minted for this event (the server drops an event that has no session_id, and still answers 200). Mount useLifecycleEvents at your app root so events correlate to a real app-open.";
|
|
3342
|
+
var MINT_WARNED_SLOT = /* @__PURE__ */ Symbol.for(
|
|
3343
|
+
"@wireai/activation:currentSessionIdMintWarned"
|
|
3344
|
+
);
|
|
3345
|
+
var warnSlot = globalThis;
|
|
3346
|
+
var ensureCurrentSessionId = () => {
|
|
3347
|
+
const existing = globalSlot[CURRENT_SESSION_ID_SLOT];
|
|
3348
|
+
if (typeof existing === "string" && existing.length > 0) return existing;
|
|
3349
|
+
const minted = makeSessionId();
|
|
3350
|
+
globalSlot[CURRENT_SESSION_ID_SLOT] = minted;
|
|
3351
|
+
if (!warnSlot[MINT_WARNED_SLOT] && warnInDev(MINT_WARNING)) {
|
|
3352
|
+
warnSlot[MINT_WARNED_SLOT] = true;
|
|
3353
|
+
}
|
|
3354
|
+
return minted;
|
|
3355
|
+
};
|
|
3317
3356
|
|
|
3318
3357
|
// src/session/persistedSession.ts
|
|
3319
3358
|
var DEFAULT_SESSION_TTL_MS = 36e5;
|
|
@@ -3382,6 +3421,7 @@ var sanitizeUserId = (raw) => {
|
|
|
3382
3421
|
if (!trimmed) return void 0;
|
|
3383
3422
|
return trimmed.length > USER_ID_MAX_LENGTH ? trimmed.slice(0, USER_ID_MAX_LENGTH) : trimmed;
|
|
3384
3423
|
};
|
|
3424
|
+
var looksLikeEmail = (value) => typeof value === "string" && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
|
|
3385
3425
|
var identifyOnboarding = async (opts) => {
|
|
3386
3426
|
var _a2, _b, _c;
|
|
3387
3427
|
const userId = sanitizeUserId(opts.userId);
|
|
@@ -4097,6 +4137,25 @@ var namespaceExtra = (extra) => {
|
|
|
4097
4137
|
}
|
|
4098
4138
|
return out;
|
|
4099
4139
|
};
|
|
4140
|
+
var analyticsUserIdStorageKey = (appId) => `wireai:analytics:userId:${appId != null ? appId : "default"}`;
|
|
4141
|
+
var clearPiiFromContext = (ctx = {}) => {
|
|
4142
|
+
const rest = {};
|
|
4143
|
+
if (typeof ctx.appVersion === "string") rest.appVersion = ctx.appVersion;
|
|
4144
|
+
if (typeof ctx.deviceKey === "string") rest.deviceKey = ctx.deviceKey;
|
|
4145
|
+
return rest;
|
|
4146
|
+
};
|
|
4147
|
+
var clearUserContext = async (opts = {}) => {
|
|
4148
|
+
const storage = opts.storage;
|
|
4149
|
+
if (!storage) return;
|
|
4150
|
+
try {
|
|
4151
|
+
await storage.removeItem(analyticsUserIdStorageKey(opts.appId));
|
|
4152
|
+
} catch {
|
|
4153
|
+
}
|
|
4154
|
+
};
|
|
4155
|
+
var activationJoinContext = (deviceKey) => {
|
|
4156
|
+
var _a2;
|
|
4157
|
+
return (_a2 = resolveUserContext({ deviceKey }).userContext) != null ? _a2 : {};
|
|
4158
|
+
};
|
|
4100
4159
|
var resolveUserContext = (ctx = {}, opts = {}) => {
|
|
4101
4160
|
var _a2;
|
|
4102
4161
|
const result = {};
|
|
@@ -4135,6 +4194,47 @@ var mintDeviceId = () => {
|
|
|
4135
4194
|
const time = Date.now().toString(36);
|
|
4136
4195
|
return `${AUTO_DEVICE_ID_PREFIX}${time}_${randomChunk()}${randomChunk()}`;
|
|
4137
4196
|
};
|
|
4197
|
+
var AUTO_DEVICE_KEY_SLOT = /* @__PURE__ */ Symbol.for("@wireai/activation:autoDeviceKeys");
|
|
4198
|
+
var deviceKeyGlobal = globalThis;
|
|
4199
|
+
var autoDeviceKeyRegistry = () => {
|
|
4200
|
+
const existing = deviceKeyGlobal[AUTO_DEVICE_KEY_SLOT];
|
|
4201
|
+
if (existing) return existing;
|
|
4202
|
+
const created = { keys: /* @__PURE__ */ new Map(), hydrating: /* @__PURE__ */ new Set() };
|
|
4203
|
+
deviceKeyGlobal[AUTO_DEVICE_KEY_SLOT] = created;
|
|
4204
|
+
return created;
|
|
4205
|
+
};
|
|
4206
|
+
var resolveAutoDeviceKey = (opts = {}) => {
|
|
4207
|
+
var _a2, _b;
|
|
4208
|
+
const registry = autoDeviceKeyRegistry();
|
|
4209
|
+
const appId = (_a2 = opts.appId) != null ? _a2 : "default";
|
|
4210
|
+
let id = registry.keys.get(appId);
|
|
4211
|
+
if (!id) {
|
|
4212
|
+
id = mintDeviceId();
|
|
4213
|
+
registry.keys.set(appId, id);
|
|
4214
|
+
}
|
|
4215
|
+
const storage = opts.storage;
|
|
4216
|
+
if (storage && !registry.hydrating.has(appId)) {
|
|
4217
|
+
registry.hydrating.add(appId);
|
|
4218
|
+
const slot = deviceIdStorageKey(appId);
|
|
4219
|
+
const minted = id;
|
|
4220
|
+
try {
|
|
4221
|
+
void Promise.resolve(storage.getItem(slot)).then((saved) => {
|
|
4222
|
+
const persisted = typeof saved === "string" && saved.trim() ? saved.trim() : void 0;
|
|
4223
|
+
if (persisted) registry.keys.set(appId, persisted);
|
|
4224
|
+
else void Promise.resolve(storage.setItem(slot, minted)).catch(() => {
|
|
4225
|
+
});
|
|
4226
|
+
}).catch(() => {
|
|
4227
|
+
});
|
|
4228
|
+
} catch {
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
return (_b = registry.keys.get(appId)) != null ? _b : id;
|
|
4232
|
+
};
|
|
4233
|
+
var resetAutoDeviceKeys = () => {
|
|
4234
|
+
const registry = autoDeviceKeyRegistry();
|
|
4235
|
+
registry.keys.clear();
|
|
4236
|
+
registry.hydrating.clear();
|
|
4237
|
+
};
|
|
4138
4238
|
|
|
4139
4239
|
// src/activation/revalidation.ts
|
|
4140
4240
|
var REVALIDATION_SLOT = /* @__PURE__ */ Symbol.for(
|
|
@@ -4182,22 +4282,20 @@ var createWireActivation = (config) => {
|
|
|
4182
4282
|
var _a2, _b;
|
|
4183
4283
|
const target = { serverUrl: config.serverUrl, apiKey: config.apiKey };
|
|
4184
4284
|
const explicitDeviceKey = (_b = clean(config.deviceKey)) != null ? _b : clean((_a2 = config.userContext) == null ? void 0 : _a2.deviceKey);
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
if (persisted) autoDeviceKey = persisted;
|
|
4192
|
-
else void storage.setItem(key, autoDeviceKey).catch(() => {
|
|
4193
|
-
});
|
|
4194
|
-
}).catch(() => {
|
|
4195
|
-
});
|
|
4196
|
-
}
|
|
4285
|
+
const autoDeviceKeyOptions = {
|
|
4286
|
+
appId: config.appId,
|
|
4287
|
+
// An explicit key opts out of minting AND persisting (unchanged contract).
|
|
4288
|
+
storage: explicitDeviceKey ? void 0 : config.storage
|
|
4289
|
+
};
|
|
4290
|
+
if (!explicitDeviceKey) resolveAutoDeviceKey(autoDeviceKeyOptions);
|
|
4197
4291
|
const applyContext = (event) => {
|
|
4198
4292
|
var _a3, _b2;
|
|
4199
4293
|
const resolved = resolveUserContext(
|
|
4200
|
-
|
|
4294
|
+
// `??` is lazy on purpose: an explicit key must never even touch the auto registry.
|
|
4295
|
+
{
|
|
4296
|
+
...(_a3 = config.userContext) != null ? _a3 : {},
|
|
4297
|
+
deviceKey: explicitDeviceKey != null ? explicitDeviceKey : resolveAutoDeviceKey(autoDeviceKeyOptions)
|
|
4298
|
+
},
|
|
4201
4299
|
{ autoAppVersion: config.appVersion }
|
|
4202
4300
|
);
|
|
4203
4301
|
if (resolved.userContext) {
|
|
@@ -4206,8 +4304,8 @@ var createWireActivation = (config) => {
|
|
|
4206
4304
|
if (resolved.userId && !event.user_id) event.user_id = resolved.userId;
|
|
4207
4305
|
};
|
|
4208
4306
|
const track = async (name2, meta) => {
|
|
4209
|
-
|
|
4210
|
-
|
|
4307
|
+
if (!clean(name2)) return false;
|
|
4308
|
+
const sessionId = ensureCurrentSessionId();
|
|
4211
4309
|
const event = {
|
|
4212
4310
|
event_type: "app_event",
|
|
4213
4311
|
session_id: sessionId,
|
|
@@ -4234,9 +4332,16 @@ var useActivationRevalidation = () => React18.useSyncExternalStore(
|
|
|
4234
4332
|
getActivationRevalidationVersion
|
|
4235
4333
|
);
|
|
4236
4334
|
var useWireActivation = (config) => {
|
|
4335
|
+
var _a2;
|
|
4237
4336
|
const ref = React18.useRef(void 0);
|
|
4238
4337
|
const prevKeys = React18.useRef("");
|
|
4239
|
-
const currentKeys =
|
|
4338
|
+
const currentKeys = [
|
|
4339
|
+
config.serverUrl,
|
|
4340
|
+
config.apiKey,
|
|
4341
|
+
config.appId,
|
|
4342
|
+
config.deviceKey,
|
|
4343
|
+
(_a2 = config.userContext) == null ? void 0 : _a2.deviceKey
|
|
4344
|
+
].join("|");
|
|
4240
4345
|
if (!ref.current || prevKeys.current !== currentKeys) {
|
|
4241
4346
|
prevKeys.current = currentKeys;
|
|
4242
4347
|
ref.current = createWireActivation(config);
|
|
@@ -4245,6 +4350,154 @@ var useWireActivation = (config) => {
|
|
|
4245
4350
|
return { track: ref.current.track, sessionId: ref.current.sessionId, revalidation };
|
|
4246
4351
|
};
|
|
4247
4352
|
|
|
4353
|
+
// src/revenuecat/purchaseEvents.ts
|
|
4354
|
+
var WIRE_PURCHASE_EVENTS = {
|
|
4355
|
+
/** The paywall became visible (offerings loaded). */
|
|
4356
|
+
paywallShown: "wire_paywall_shown",
|
|
4357
|
+
/** The user tapped buy; the store sheet is about to open. */
|
|
4358
|
+
checkoutStarted: "wire_checkout_started",
|
|
4359
|
+
/** The store confirmed the purchase AND the entitlement is now active. */
|
|
4360
|
+
purchased: "wire_purchase_completed",
|
|
4361
|
+
/** The purchase did not land: a user cancel or a real store/network error (see `reason`). */
|
|
4362
|
+
purchaseFailed: "wire_purchase_failed",
|
|
4363
|
+
/** A restore ran (whether or not it produced an entitlement; see `plan_tier`). */
|
|
4364
|
+
restored: "wire_purchase_restored"
|
|
4365
|
+
};
|
|
4366
|
+
var PLAN_TIER_CONTEXT_KEY = "plan_tier";
|
|
4367
|
+
var asRecord = (value) => typeof value === "object" && value !== null ? value : void 0;
|
|
4368
|
+
var activeEntitlement = (info, entitlementId) => {
|
|
4369
|
+
var _a2, _b;
|
|
4370
|
+
const active = asRecord((_b = asRecord((_a2 = asRecord(info)) == null ? void 0 : _a2.entitlements)) == null ? void 0 : _b.active);
|
|
4371
|
+
const found = active == null ? void 0 : active[entitlementId];
|
|
4372
|
+
const entitlement = asRecord(found);
|
|
4373
|
+
if (!entitlement) return void 0;
|
|
4374
|
+
return entitlement.isActive === false ? void 0 : entitlement;
|
|
4375
|
+
};
|
|
4376
|
+
var isTrial = (entitlement) => typeof entitlement.periodType === "string" && entitlement.periodType.toUpperCase() === "TRIAL";
|
|
4377
|
+
var resolvePlanTier = (info, entitlementId) => {
|
|
4378
|
+
const entitlement = activeEntitlement(info, entitlementId);
|
|
4379
|
+
if (!entitlement) return "free";
|
|
4380
|
+
return isTrial(entitlement) ? "trial" : "paid";
|
|
4381
|
+
};
|
|
4382
|
+
var describePackage = (pkg) => {
|
|
4383
|
+
const props = {};
|
|
4384
|
+
if (!pkg) return props;
|
|
4385
|
+
if (typeof pkg.identifier === "string") props.package_id = pkg.identifier;
|
|
4386
|
+
if (typeof pkg.packageType === "string") props.package_type = pkg.packageType;
|
|
4387
|
+
if (typeof pkg.offeringIdentifier === "string") props.offering_id = pkg.offeringIdentifier;
|
|
4388
|
+
const product = asRecord(pkg.product);
|
|
4389
|
+
if (product) {
|
|
4390
|
+
if (typeof product.identifier === "string") props.product_id = product.identifier;
|
|
4391
|
+
if (typeof product.price === "number" && Number.isFinite(product.price)) {
|
|
4392
|
+
props.price = product.price;
|
|
4393
|
+
}
|
|
4394
|
+
if (typeof product.currencyCode === "string") props.currency = product.currencyCode;
|
|
4395
|
+
}
|
|
4396
|
+
return props;
|
|
4397
|
+
};
|
|
4398
|
+
var describeEntitlement = (info, entitlementId) => {
|
|
4399
|
+
const entitlement = activeEntitlement(info, entitlementId);
|
|
4400
|
+
const props = {
|
|
4401
|
+
entitlement: entitlementId,
|
|
4402
|
+
plan_tier: entitlement ? isTrial(entitlement) ? "trial" : "paid" : "free"
|
|
4403
|
+
};
|
|
4404
|
+
if (!entitlement) return props;
|
|
4405
|
+
if (typeof entitlement.periodType === "string") props.period_type = entitlement.periodType;
|
|
4406
|
+
props.is_trial = isTrial(entitlement);
|
|
4407
|
+
if (typeof entitlement.willRenew === "boolean") props.will_renew = entitlement.willRenew;
|
|
4408
|
+
if (typeof entitlement.store === "string") props.store = entitlement.store;
|
|
4409
|
+
if (typeof entitlement.productIdentifier === "string") {
|
|
4410
|
+
props.product_id = entitlement.productIdentifier;
|
|
4411
|
+
}
|
|
4412
|
+
if (typeof entitlement.isSandbox === "boolean") props.is_sandbox = entitlement.isSandbox;
|
|
4413
|
+
return props;
|
|
4414
|
+
};
|
|
4415
|
+
var PURCHASE_CANCELLED_CODE = "1";
|
|
4416
|
+
var isUserCancelled = (error) => {
|
|
4417
|
+
const record = asRecord(error);
|
|
4418
|
+
if (!record) return false;
|
|
4419
|
+
if (record.userCancelled === true) return true;
|
|
4420
|
+
return record.code === PURCHASE_CANCELLED_CODE;
|
|
4421
|
+
};
|
|
4422
|
+
var describeFailure = (error) => {
|
|
4423
|
+
const record = asRecord(error);
|
|
4424
|
+
const code = typeof (record == null ? void 0 : record.code) === "string" ? record.code : "unknown";
|
|
4425
|
+
return { reason: isUserCancelled(error) ? "cancelled" : "error", code };
|
|
4426
|
+
};
|
|
4427
|
+
|
|
4428
|
+
// src/revenuecat/revenueCatBridge.ts
|
|
4429
|
+
var createRevenueCatBridge = (config) => {
|
|
4430
|
+
const { analytics, entitlementId } = config;
|
|
4431
|
+
const writeTier = config.writePlanTier !== false;
|
|
4432
|
+
const emit = (event, props) => {
|
|
4433
|
+
try {
|
|
4434
|
+
const result = analytics.track(event, { ...config.commonProps, ...props });
|
|
4435
|
+
if (result && typeof result.catch === "function") {
|
|
4436
|
+
void result.catch(() => {
|
|
4437
|
+
});
|
|
4438
|
+
}
|
|
4439
|
+
} catch {
|
|
4440
|
+
}
|
|
4441
|
+
};
|
|
4442
|
+
const syncPlanTier = (customerInfo) => {
|
|
4443
|
+
var _a2;
|
|
4444
|
+
const tier = resolvePlanTier(customerInfo, entitlementId);
|
|
4445
|
+
if (!writeTier) return tier;
|
|
4446
|
+
try {
|
|
4447
|
+
(_a2 = analytics.setUserContext) == null ? void 0 : _a2.call(analytics, { extra: { [PLAN_TIER_CONTEXT_KEY]: tier } });
|
|
4448
|
+
} catch {
|
|
4449
|
+
}
|
|
4450
|
+
return tier;
|
|
4451
|
+
};
|
|
4452
|
+
const paywallShown = (offering, props) => {
|
|
4453
|
+
var _a2, _b;
|
|
4454
|
+
const shown = {
|
|
4455
|
+
packages_count: (_b = (_a2 = offering == null ? void 0 : offering.availablePackages) == null ? void 0 : _a2.length) != null ? _b : 0
|
|
4456
|
+
};
|
|
4457
|
+
if (typeof (offering == null ? void 0 : offering.identifier) === "string") shown.offering_id = offering.identifier;
|
|
4458
|
+
emit(WIRE_PURCHASE_EVENTS.paywallShown, { ...shown, ...props });
|
|
4459
|
+
};
|
|
4460
|
+
const checkoutStarted = (pkg, props) => {
|
|
4461
|
+
emit(WIRE_PURCHASE_EVENTS.checkoutStarted, { ...describePackage(pkg), ...props });
|
|
4462
|
+
};
|
|
4463
|
+
const purchaseCompleted = (customerInfo, pkg, props) => {
|
|
4464
|
+
const tier = syncPlanTier(customerInfo);
|
|
4465
|
+
const entitled = tier !== "free";
|
|
4466
|
+
if (entitled) {
|
|
4467
|
+
emit(WIRE_PURCHASE_EVENTS.purchased, {
|
|
4468
|
+
...describePackage(pkg),
|
|
4469
|
+
...describeEntitlement(customerInfo, entitlementId),
|
|
4470
|
+
...props
|
|
4471
|
+
});
|
|
4472
|
+
return true;
|
|
4473
|
+
}
|
|
4474
|
+
emit(WIRE_PURCHASE_EVENTS.purchaseFailed, {
|
|
4475
|
+
...describePackage(pkg),
|
|
4476
|
+
reason: "not_entitled",
|
|
4477
|
+
code: "unknown",
|
|
4478
|
+
entitlement: entitlementId,
|
|
4479
|
+
...props
|
|
4480
|
+
});
|
|
4481
|
+
return false;
|
|
4482
|
+
};
|
|
4483
|
+
const purchaseFailed = (error, pkg, props) => {
|
|
4484
|
+
emit(WIRE_PURCHASE_EVENTS.purchaseFailed, {
|
|
4485
|
+
...describePackage(pkg),
|
|
4486
|
+
...describeFailure(error),
|
|
4487
|
+
...props
|
|
4488
|
+
});
|
|
4489
|
+
};
|
|
4490
|
+
const purchasesRestored = (customerInfo, props) => {
|
|
4491
|
+
const tier = syncPlanTier(customerInfo);
|
|
4492
|
+
emit(WIRE_PURCHASE_EVENTS.restored, {
|
|
4493
|
+
...describeEntitlement(customerInfo, entitlementId),
|
|
4494
|
+
...props
|
|
4495
|
+
});
|
|
4496
|
+
return tier !== "free";
|
|
4497
|
+
};
|
|
4498
|
+
return { paywallShown, checkoutStarted, purchaseCompleted, purchaseFailed, purchasesRestored, syncPlanTier };
|
|
4499
|
+
};
|
|
4500
|
+
|
|
4248
4501
|
// src/session-analytics/reportSessionStart.ts
|
|
4249
4502
|
var SESSION_STARTED_EVENT = "app.session_started";
|
|
4250
4503
|
var _emitted = /* @__PURE__ */ new Set();
|
|
@@ -4297,6 +4550,8 @@ var reportSessionStart = (opts) => {
|
|
|
4297
4550
|
method: "POST",
|
|
4298
4551
|
headers,
|
|
4299
4552
|
body: JSON.stringify({ events: [event] })
|
|
4553
|
+
}).then((res) => {
|
|
4554
|
+
warnOnSkippedEvents(res);
|
|
4300
4555
|
}).catch(() => {
|
|
4301
4556
|
});
|
|
4302
4557
|
} catch {
|
|
@@ -4390,16 +4645,9 @@ var routeLifecycleEvent = (event, opts) => {
|
|
|
4390
4645
|
opts.sink(event);
|
|
4391
4646
|
return;
|
|
4392
4647
|
}
|
|
4393
|
-
const
|
|
4394
|
-
if (!
|
|
4395
|
-
|
|
4396
|
-
const headers = { "Content-Type": "application/json" };
|
|
4397
|
-
if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;
|
|
4398
|
-
void fetch(url, {
|
|
4399
|
-
method: "POST",
|
|
4400
|
-
headers,
|
|
4401
|
-
body: JSON.stringify({ events: [event] })
|
|
4402
|
-
}).catch(() => {
|
|
4648
|
+
const req = buildEventsRequest(opts.target, [event]);
|
|
4649
|
+
if (!req) return;
|
|
4650
|
+
void fetch(req.url, req.init).catch(() => {
|
|
4403
4651
|
});
|
|
4404
4652
|
} catch {
|
|
4405
4653
|
}
|
|
@@ -4434,11 +4682,13 @@ var reportFirstOpen = (opts) => {
|
|
|
4434
4682
|
})();
|
|
4435
4683
|
};
|
|
4436
4684
|
var wireLifecycleEvents = (opts) => {
|
|
4437
|
-
|
|
4685
|
+
var _a2;
|
|
4686
|
+
const sessionId = (_a2 = opts.sessionId) != null ? _a2 : makeSessionId();
|
|
4687
|
+
reportFirstOpen({ ...opts, sessionId });
|
|
4438
4688
|
reportSessionStart({
|
|
4439
4689
|
target: opts.target,
|
|
4440
4690
|
sink: opts.sink,
|
|
4441
|
-
sessionId
|
|
4691
|
+
sessionId,
|
|
4442
4692
|
userId: opts.userId,
|
|
4443
4693
|
deviceKey: opts.deviceKey,
|
|
4444
4694
|
sessionCount: opts.sessionCount,
|
|
@@ -4511,6 +4761,7 @@ var createEventQueue = (options) => {
|
|
|
4511
4761
|
var _a3;
|
|
4512
4762
|
const env = resolveEnvelope();
|
|
4513
4763
|
const stamped = { ...event };
|
|
4764
|
+
if (stamped.ts === void 0) stamped.ts = Date.now();
|
|
4514
4765
|
if (!env) return stamped;
|
|
4515
4766
|
if (!stamped.device && env.device) stamped.device = env.device;
|
|
4516
4767
|
if (!stamped.session_id && env.sessionId) stamped.session_id = env.sessionId;
|
|
@@ -4566,19 +4817,13 @@ var createEventQueue = (options) => {
|
|
|
4566
4817
|
}
|
|
4567
4818
|
})();
|
|
4568
4819
|
const postBatch = async (events) => {
|
|
4569
|
-
|
|
4820
|
+
const req = buildEventsRequest(target, events);
|
|
4821
|
+
if (!req) return false;
|
|
4570
4822
|
const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
|
|
4571
4823
|
const timer = setTimeout(() => controller == null ? void 0 : controller.abort(), 15e3);
|
|
4572
4824
|
try {
|
|
4573
|
-
const
|
|
4574
|
-
|
|
4575
|
-
if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;
|
|
4576
|
-
const res = await fetch(url, {
|
|
4577
|
-
method: "POST",
|
|
4578
|
-
headers,
|
|
4579
|
-
body: JSON.stringify({ events }),
|
|
4580
|
-
signal: controller == null ? void 0 : controller.signal
|
|
4581
|
-
});
|
|
4825
|
+
const res = await fetch(req.url, { ...req.init, signal: controller == null ? void 0 : controller.signal });
|
|
4826
|
+
warnOnSkippedEvents(res);
|
|
4582
4827
|
return !!(res && res.ok);
|
|
4583
4828
|
} catch {
|
|
4584
4829
|
return false;
|
|
@@ -4684,6 +4929,34 @@ var useLifecycleEvents = (config, options = {}) => {
|
|
|
4684
4929
|
var _a3;
|
|
4685
4930
|
return (cfg == null ? void 0 : cfg.serverUrl) ? { serverUrl: cfg.serverUrl, apiKey: (_a3 = cfg.apiKey) != null ? _a3 : "" } : void 0;
|
|
4686
4931
|
};
|
|
4932
|
+
const resolveDeviceKey = (cfg, opts) => {
|
|
4933
|
+
const host = typeof opts.deviceKey === "string" && opts.deviceKey.trim() ? opts.deviceKey : void 0;
|
|
4934
|
+
if (host) return host;
|
|
4935
|
+
if (!(cfg == null ? void 0 : cfg.storage)) return void 0;
|
|
4936
|
+
return resolveAutoDeviceKey({ appId: cfg.appId, storage: cfg.storage });
|
|
4937
|
+
};
|
|
4938
|
+
const mountOpenSessionId = makeSessionId();
|
|
4939
|
+
const fireSession = (sessionId) => {
|
|
4940
|
+
var _a3;
|
|
4941
|
+
const { config: cfg, options: opts } = latest.current;
|
|
4942
|
+
if (opts.enabled === false) return;
|
|
4943
|
+
if (!(cfg == null ? void 0 : cfg.serverUrl) && !opts.sink) return;
|
|
4944
|
+
const device = collectDeviceContext();
|
|
4945
|
+
if (cfg == null ? void 0 : cfg.appVersion) device.appVersion = cfg.appVersion;
|
|
4946
|
+
reportSessionStart({
|
|
4947
|
+
target: targetOf(cfg),
|
|
4948
|
+
sink: resolveSink(),
|
|
4949
|
+
sessionId,
|
|
4950
|
+
userId: opts.userId,
|
|
4951
|
+
deviceKey: resolveDeviceKey(cfg, opts),
|
|
4952
|
+
sessionCount: opts.sessionCount,
|
|
4953
|
+
appVersion: (_a3 = cfg == null ? void 0 : cfg.appVersion) != null ? _a3 : device.appVersion,
|
|
4954
|
+
platform: reactNative.Platform.OS,
|
|
4955
|
+
device,
|
|
4956
|
+
meta: opts.meta
|
|
4957
|
+
});
|
|
4958
|
+
};
|
|
4959
|
+
fireSession(mountOpenSessionId);
|
|
4687
4960
|
{
|
|
4688
4961
|
const { config: cfg, options: opts } = latest.current;
|
|
4689
4962
|
if (opts.enabled !== false) {
|
|
@@ -4692,10 +4965,11 @@ var useLifecycleEvents = (config, options = {}) => {
|
|
|
4692
4965
|
reportFirstOpen({
|
|
4693
4966
|
target: targetOf(cfg),
|
|
4694
4967
|
sink: resolveSink(),
|
|
4968
|
+
sessionId: mountOpenSessionId,
|
|
4695
4969
|
storage: cfg == null ? void 0 : cfg.storage,
|
|
4696
4970
|
appId: cfg == null ? void 0 : cfg.appId,
|
|
4697
4971
|
userId: opts.userId,
|
|
4698
|
-
deviceKey: opts
|
|
4972
|
+
deviceKey: resolveDeviceKey(cfg, opts),
|
|
4699
4973
|
sessionCount: opts.sessionCount,
|
|
4700
4974
|
appVersion: (_a2 = cfg == null ? void 0 : cfg.appVersion) != null ? _a2 : device.appVersion,
|
|
4701
4975
|
platform: reactNative.Platform.OS,
|
|
@@ -4704,27 +4978,6 @@ var useLifecycleEvents = (config, options = {}) => {
|
|
|
4704
4978
|
});
|
|
4705
4979
|
}
|
|
4706
4980
|
}
|
|
4707
|
-
const fireSession = () => {
|
|
4708
|
-
var _a3;
|
|
4709
|
-
const { config: cfg, options: opts } = latest.current;
|
|
4710
|
-
if (opts.enabled === false) return;
|
|
4711
|
-
if (!(cfg == null ? void 0 : cfg.serverUrl) && !opts.sink) return;
|
|
4712
|
-
const device = collectDeviceContext();
|
|
4713
|
-
if (cfg == null ? void 0 : cfg.appVersion) device.appVersion = cfg.appVersion;
|
|
4714
|
-
reportSessionStart({
|
|
4715
|
-
target: targetOf(cfg),
|
|
4716
|
-
sink: resolveSink(),
|
|
4717
|
-
// A fresh per-open id each fire; the emitter's once-guard dedupes within the open.
|
|
4718
|
-
userId: opts.userId,
|
|
4719
|
-
deviceKey: opts.deviceKey,
|
|
4720
|
-
sessionCount: opts.sessionCount,
|
|
4721
|
-
appVersion: (_a3 = cfg == null ? void 0 : cfg.appVersion) != null ? _a3 : device.appVersion,
|
|
4722
|
-
platform: reactNative.Platform.OS,
|
|
4723
|
-
device,
|
|
4724
|
-
meta: opts.meta
|
|
4725
|
-
});
|
|
4726
|
-
};
|
|
4727
|
-
fireSession();
|
|
4728
4981
|
let backgroundedAt = null;
|
|
4729
4982
|
const onChange = (state) => {
|
|
4730
4983
|
if (state === "background" || state === "inactive") {
|
|
@@ -4769,6 +5022,7 @@ exports.OnboardingButton = Button;
|
|
|
4769
5022
|
exports.OnboardingFlow = OnboardingFlow;
|
|
4770
5023
|
exports.OnboardingScaffold = OnboardingScaffold;
|
|
4771
5024
|
exports.OnboardingThemeProvider = OnboardingThemeProvider;
|
|
5025
|
+
exports.PLAN_TIER_CONTEXT_KEY = PLAN_TIER_CONTEXT_KEY;
|
|
4772
5026
|
exports.RESERVED_USER_CONTEXT_KEYS = RESERVED_USER_CONTEXT_KEYS;
|
|
4773
5027
|
exports.SESSION_STARTED_EVENT = SESSION_STARTED_EVENT;
|
|
4774
5028
|
exports.SelectionCard = SelectionCard;
|
|
@@ -4779,21 +5033,32 @@ exports.USER_ID_MAX_LENGTH = USER_ID_MAX_LENGTH;
|
|
|
4779
5033
|
exports.WIRE_ICON_GLYPHS = WIRE_ICON_GLYPHS;
|
|
4780
5034
|
exports.WIRE_ICON_NAMES = WIRE_ICON_NAMES;
|
|
4781
5035
|
exports.WIRE_ONBOARDING_EVENTS = WIRE_ONBOARDING_EVENTS;
|
|
5036
|
+
exports.WIRE_PURCHASE_EVENTS = WIRE_PURCHASE_EVENTS;
|
|
4782
5037
|
exports.WireFeaturesProvider = WireFeaturesProvider;
|
|
4783
5038
|
exports.WireIcon = WireIcon;
|
|
4784
5039
|
exports.WireOnboarding = WireOnboarding;
|
|
5040
|
+
exports.activationJoinContext = activationJoinContext;
|
|
5041
|
+
exports.activeEntitlement = activeEntitlement;
|
|
5042
|
+
exports.analyticsUserIdStorageKey = analyticsUserIdStorageKey;
|
|
4785
5043
|
exports.attributionMetadata = attributionMetadata;
|
|
4786
5044
|
exports.bumpActivationRevalidation = bumpActivationRevalidation;
|
|
4787
5045
|
exports.clearPersistedSession = clearPersistedSession;
|
|
5046
|
+
exports.clearPiiFromContext = clearPiiFromContext;
|
|
5047
|
+
exports.clearUserContext = clearUserContext;
|
|
4788
5048
|
exports.collectDeviceContext = collectDeviceContext;
|
|
5049
|
+
exports.createRevenueCatBridge = createRevenueCatBridge;
|
|
4789
5050
|
exports.createWireActivation = createWireActivation;
|
|
4790
5051
|
exports.defaultIllustrations = defaultIllustrations;
|
|
4791
5052
|
exports.defaultOnboardingTheme = defaultOnboardingTheme;
|
|
4792
5053
|
exports.defaultWireFeatures = defaultWireFeatures;
|
|
4793
5054
|
exports.deriveAnswers = deriveAnswers;
|
|
5055
|
+
exports.describeEntitlement = describeEntitlement;
|
|
5056
|
+
exports.describeFailure = describeFailure;
|
|
5057
|
+
exports.describePackage = describePackage;
|
|
4794
5058
|
exports.detectAppVersion = detectAppVersion;
|
|
4795
5059
|
exports.detectNativeModel = detectNativeModel;
|
|
4796
5060
|
exports.deviceIdStorageKey = deviceIdStorageKey;
|
|
5061
|
+
exports.ensureCurrentSessionId = ensureCurrentSessionId;
|
|
4797
5062
|
exports.featuresCacheKey = featuresCacheKey;
|
|
4798
5063
|
exports.featuresEqual = featuresEqual;
|
|
4799
5064
|
exports.fetchWireFeatures = fetchWireFeatures;
|
|
@@ -4804,8 +5069,10 @@ exports.hashEmailFnv1a = hashEmailFnv1a;
|
|
|
4804
5069
|
exports.identifyOnboarding = identifyOnboarding;
|
|
4805
5070
|
exports.isFeaturesFresh = isFeaturesFresh;
|
|
4806
5071
|
exports.isOnboardingEnabled = isOnboardingEnabled;
|
|
5072
|
+
exports.isUserCancelled = isUserCancelled;
|
|
4807
5073
|
exports.isWireScalar = isWireScalar;
|
|
4808
5074
|
exports.loadPersistedSession = loadPersistedSession;
|
|
5075
|
+
exports.looksLikeEmail = looksLikeEmail;
|
|
4809
5076
|
exports.lookupIconGlyph = lookupIconGlyph;
|
|
4810
5077
|
exports.makeSessionId = makeSessionId;
|
|
4811
5078
|
exports.mergeTheme = mergeTheme;
|
|
@@ -4824,9 +5091,12 @@ exports.reportClientEventsAwait = reportClientEventsAwait;
|
|
|
4824
5091
|
exports.reportFirstOpen = reportFirstOpen;
|
|
4825
5092
|
exports.reportSessionStart = reportSessionStart;
|
|
4826
5093
|
exports.resetActivationRevalidation = resetActivationRevalidation;
|
|
5094
|
+
exports.resetAutoDeviceKeys = resetAutoDeviceKeys;
|
|
4827
5095
|
exports.resetCurrentSessionId = resetCurrentSessionId;
|
|
4828
5096
|
exports.resetFirstOpenLatch = resetFirstOpenLatch;
|
|
4829
5097
|
exports.resetSessionStartGuard = resetSessionStartGuard;
|
|
5098
|
+
exports.resolveAutoDeviceKey = resolveAutoDeviceKey;
|
|
5099
|
+
exports.resolvePlanTier = resolvePlanTier;
|
|
4830
5100
|
exports.resolveUserContext = resolveUserContext;
|
|
4831
5101
|
exports.sanitizeUserId = sanitizeUserId;
|
|
4832
5102
|
exports.savePersistedSession = savePersistedSession;
|