@wireai/activation 0.11.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.
Files changed (58) hide show
  1. package/AGENTS.md +51 -0
  2. package/CHANGELOG.md +58 -3
  3. package/INTEGRATION_PROMPT.md +13 -1
  4. package/README.md +73 -0
  5. package/dist/analytics/index.d.mts +17 -6
  6. package/dist/analytics/index.d.ts +17 -6
  7. package/dist/analytics/index.js +130 -35
  8. package/dist/analytics/index.js.map +1 -1
  9. package/dist/analytics/index.mjs +126 -36
  10. package/dist/analytics/index.mjs.map +1 -1
  11. package/dist/{currentSession-DdnUq2HQ.d.ts → currentSession-D6RiVtc8.d.ts} +88 -30
  12. package/dist/{currentSession-C0_odnIW.d.mts → currentSession-DsSDHqor.d.mts} +88 -30
  13. package/dist/index.d.mts +236 -36
  14. package/dist/index.d.ts +236 -36
  15. package/dist/index.js +281 -20
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +269 -21
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/questionnaire/index.d.mts +1 -1
  20. package/dist/questionnaire/index.d.ts +1 -1
  21. package/dist/questionnaire/index.js +49 -6
  22. package/dist/questionnaire/index.js.map +1 -1
  23. package/dist/questionnaire/index.mjs +49 -6
  24. package/dist/questionnaire/index.mjs.map +1 -1
  25. package/dist/reviews/index.d.mts +2 -2
  26. package/dist/reviews/index.d.ts +2 -2
  27. package/dist/reviews/index.js +73 -8
  28. package/dist/reviews/index.js.map +1 -1
  29. package/dist/reviews/index.mjs +73 -8
  30. package/dist/reviews/index.mjs.map +1 -1
  31. package/dist/{transport-BGW9uXZJ.d.mts → transport-CF_eHwzC.d.mts} +15 -1
  32. package/dist/{transport-jUJd5kxu.d.ts → transport-DsRe4epC.d.ts} +15 -1
  33. package/llms.txt +1 -0
  34. package/package.json +1 -1
  35. package/src/activation/useWireActivation.ts +12 -1
  36. package/src/activation/wireActivation.ts +36 -24
  37. package/src/analytics/analyticsFacade.ts +41 -20
  38. package/src/analytics/currentSession.ts +83 -0
  39. package/src/analytics/eventQueue.ts +9 -1
  40. package/src/analytics/index.ts +20 -1
  41. package/src/analytics/reportClientEvent.ts +38 -0
  42. package/src/analytics/screenTracking.ts +6 -1
  43. package/src/analytics/useAnalytics.ts +22 -1
  44. package/src/context/deviceId.ts +109 -0
  45. package/src/context/userContext.ts +18 -0
  46. package/src/index.ts +45 -1
  47. package/src/questionnaire/runtime.ts +12 -2
  48. package/src/questionnaire/useQuestionnaireGate.ts +9 -7
  49. package/src/revenuecat/index.ts +55 -0
  50. package/src/revenuecat/purchaseEvents.ts +167 -0
  51. package/src/revenuecat/revenueCatBridge.ts +221 -0
  52. package/src/revenuecat/types.ts +95 -0
  53. package/src/reviews/runtime.ts +92 -1
  54. package/src/reviews/transport.ts +21 -2
  55. package/src/reviews/useReviewGate.ts +12 -7
  56. package/src/session-analytics/lifecycle.ts +9 -2
  57. package/src/session-analytics/reportSessionStart.ts +15 -4
  58. package/src/session-analytics/useLifecycleEvents.ts +28 -2
@@ -4,7 +4,7 @@ export { e as RatingRoute, f as ReviewConfig, g as ReviewDecisionResponse, h as
4
4
  export { C as ReviewModal, a as ReviewModalHandle, b as ReviewModalProps } from '../CenteredModal-C3qQBHsA.mjs';
5
5
  export { G as GateRules, a as GateSignals, b as buildReviewSubmission, d as decideReview, e as evaluateGate, r as resolveRules, c as routeRating } from '../decision-Bl_M2y3r.mjs';
6
6
  import { c as OnboardingFonts } from '../types-BKfpdZzX.mjs';
7
- export { F as FetchReviewDecisionOptions, R as ReportAppEventOptions, f as fetchReviewDecision, r as reportAppEvent, s as submitReview } from '../transport-BGW9uXZJ.mjs';
7
+ export { F as FetchReviewDecisionOptions, R as ReportAppEventOptions, f as fetchReviewDecision, r as reportAppEvent, s as submitReview } from '../transport-CF_eHwzC.mjs';
8
8
  import '../types-BcmagF6K.mjs';
9
9
  import '../types-CKFhyrMu.mjs';
10
10
 
@@ -19,7 +19,7 @@ import '../types-CKFhyrMu.mjs';
19
19
  declare const reviewSeenKey: (id: string, version?: string) => string;
20
20
  /** Last-shown timestamp key (epoch ms), for the cooldown rule. */
21
21
  declare const reviewLastShownKey: (id: string) => string;
22
- /** Session-count key, incremented once per gate mount, for the min-sessions rule. */
22
+ /** Session-count key, incremented once per APP-OPEN (not per mount), for the min-sessions rule. */
23
23
  declare const reviewSessionsKey: (id: string) => string;
24
24
 
25
25
  /**
@@ -4,7 +4,7 @@ export { e as RatingRoute, f as ReviewConfig, g as ReviewDecisionResponse, h as
4
4
  export { C as ReviewModal, a as ReviewModalHandle, b as ReviewModalProps } from '../CenteredModal-Cdgns6--.js';
5
5
  export { G as GateRules, a as GateSignals, b as buildReviewSubmission, d as decideReview, e as evaluateGate, r as resolveRules, c as routeRating } from '../decision-Cau5KmP6.js';
6
6
  import { c as OnboardingFonts } from '../types-BKfpdZzX.js';
7
- export { F as FetchReviewDecisionOptions, R as ReportAppEventOptions, f as fetchReviewDecision, r as reportAppEvent, s as submitReview } from '../transport-jUJd5kxu.js';
7
+ export { F as FetchReviewDecisionOptions, R as ReportAppEventOptions, f as fetchReviewDecision, r as reportAppEvent, s as submitReview } from '../transport-DsRe4epC.js';
8
8
  import '../types-BcmagF6K.js';
9
9
  import '../types-CKFhyrMu.js';
10
10
 
@@ -19,7 +19,7 @@ import '../types-CKFhyrMu.js';
19
19
  declare const reviewSeenKey: (id: string, version?: string) => string;
20
20
  /** Last-shown timestamp key (epoch ms), for the cooldown rule. */
21
21
  declare const reviewLastShownKey: (id: string) => string;
22
- /** Session-count key, incremented once per gate mount, for the min-sessions rule. */
22
+ /** Session-count key, incremented once per APP-OPEN (not per mount), for the min-sessions rule. */
23
23
  declare const reviewSessionsKey: (id: string) => string;
24
24
 
25
25
  /**
@@ -736,6 +736,7 @@ var requestStoreReview = async (store) => {
736
736
  };
737
737
 
738
738
  // src/analytics/reportClientEvent.ts
739
+ var makeSessionId = () => `wire_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
739
740
  var buildEventsRequest = (target, events) => {
740
741
  if (!(target == null ? void 0 : target.serverUrl) || events.length === 0) return null;
741
742
  try {
@@ -748,6 +749,35 @@ var buildEventsRequest = (target, events) => {
748
749
  }
749
750
  };
750
751
 
752
+ // src/analytics/currentSession.ts
753
+ var CURRENT_SESSION_ID_SLOT = /* @__PURE__ */ Symbol.for(
754
+ "@wireai/activation:currentSessionId"
755
+ );
756
+ var globalSlot = globalThis;
757
+ var getCurrentSessionId = () => globalSlot[CURRENT_SESSION_ID_SLOT];
758
+ var warnInDev = (message) => {
759
+ if (typeof __DEV__ !== "undefined" && __DEV__ && typeof console !== "undefined" && console.warn) {
760
+ console.warn(message);
761
+ return true;
762
+ }
763
+ return false;
764
+ };
765
+ 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.";
766
+ var MINT_WARNED_SLOT = /* @__PURE__ */ Symbol.for(
767
+ "@wireai/activation:currentSessionIdMintWarned"
768
+ );
769
+ var warnSlot = globalThis;
770
+ var ensureCurrentSessionId = () => {
771
+ const existing = globalSlot[CURRENT_SESSION_ID_SLOT];
772
+ if (typeof existing === "string" && existing.length > 0) return existing;
773
+ const minted = makeSessionId();
774
+ globalSlot[CURRENT_SESSION_ID_SLOT] = minted;
775
+ if (!warnSlot[MINT_WARNED_SLOT] && warnInDev(MINT_WARNING)) {
776
+ warnSlot[MINT_WARNED_SLOT] = true;
777
+ }
778
+ return minted;
779
+ };
780
+
751
781
  // src/reviews/transport.ts
752
782
  var submitReview = (target, review) => {
753
783
  if (!(target == null ? void 0 : target.serverUrl)) return;
@@ -785,13 +815,15 @@ var fetchReviewDecision = async (target, options = {}) => {
785
815
  }
786
816
  };
787
817
  var reportAppEvent = (target, name, options = {}) => {
818
+ var _a;
788
819
  if (!(target == null ? void 0 : target.serverUrl) || !name) return;
789
820
  try {
821
+ const supplied = (_a = options.sessionId) != null ? _a : "";
790
822
  const event = {
791
823
  event_type: "app_event",
792
- question_key: name
824
+ question_key: name,
825
+ session_id: supplied.trim().length > 0 ? supplied : ensureCurrentSessionId()
793
826
  };
794
- if (options.sessionId) event.session_id = options.sessionId;
795
827
  if (options.deviceKey) event.user_context = { device_key: options.deviceKey };
796
828
  if (options.meta && Object.keys(options.meta).length > 0) {
797
829
  event.meta = JSON.stringify(options.meta);
@@ -1258,6 +1290,7 @@ var sameDecision = (a, b) => {
1258
1290
  var reviewSeenKey = (id, version) => version ? `wire_review_${id}_${version}_seen` : `wire_review_${id}_seen`;
1259
1291
  var reviewLastShownKey = (id) => `wire_review_${id}_last`;
1260
1292
  var reviewSessionsKey = (id) => `wire_review_${id}_sessions`;
1293
+ var reviewSessionOpenKey = (id) => `wire_review_${id}_open`;
1261
1294
  var resolveStorage = (override) => override != null ? override : getCoachmarkStorage();
1262
1295
  var readInt = (storage, key) => {
1263
1296
  if (!storage) return 0;
@@ -1276,6 +1309,40 @@ var writeInt = (storage, key, value) => {
1276
1309
  } catch {
1277
1310
  }
1278
1311
  };
1312
+ var readStr = (storage, key) => {
1313
+ if (!storage) return void 0;
1314
+ try {
1315
+ const raw = storage.getItem(key);
1316
+ return typeof raw === "string" && raw.length > 0 ? raw : void 0;
1317
+ } catch {
1318
+ return void 0;
1319
+ }
1320
+ };
1321
+ var PROCESS_OPEN_ID_SLOT = /* @__PURE__ */ Symbol.for("@wireai/activation:processOpenId");
1322
+ var openIdGlobal = globalThis;
1323
+ var currentOpenId = () => {
1324
+ const live = getCurrentSessionId();
1325
+ if (live) return live;
1326
+ const existing = openIdGlobal[PROCESS_OPEN_ID_SLOT];
1327
+ if (existing) return existing;
1328
+ const created = makeSessionId();
1329
+ openIdGlobal[PROCESS_OPEN_ID_SLOT] = created;
1330
+ return created;
1331
+ };
1332
+ var bumpSessionCount = (storage, sessionsKey, openKey, openId = currentOpenId()) => {
1333
+ const lastOpen = readStr(storage, openKey);
1334
+ const stored = readInt(storage, sessionsKey);
1335
+ if (lastOpen === openId) return stored > 0 ? stored : 1;
1336
+ const next = stored + 1;
1337
+ writeInt(storage, sessionsKey, next);
1338
+ if (storage) {
1339
+ try {
1340
+ storage.setItem(openKey, openId);
1341
+ } catch {
1342
+ }
1343
+ }
1344
+ return next;
1345
+ };
1279
1346
 
1280
1347
  // src/reviews/useReviewGate.ts
1281
1348
  var useStableValue2 = (value, isEqual) => {
@@ -1302,12 +1369,10 @@ var useReviewGate = ({
1302
1369
  const seenKey = reviewSeenKey(config.id, config.oncePerVersion === false ? void 0 : config.appVersion);
1303
1370
  const lastKey = reviewLastShownKey(config.id);
1304
1371
  const sessionsKey = reviewSessionsKey(config.id);
1305
- const sessions = React7.useState(() => {
1306
- const store = resolveStorage(storage);
1307
- const next = readInt(store, sessionsKey) + 1;
1308
- writeInt(store, sessionsKey, next);
1309
- return next;
1310
- })[0];
1372
+ const sessionOpenKey = reviewSessionOpenKey(config.id);
1373
+ const sessions = React7.useState(
1374
+ () => bumpSessionCount(resolveStorage(storage), sessionsKey, sessionOpenKey)
1375
+ )[0];
1311
1376
  const hasServerDecision = decision != null;
1312
1377
  const timeoutMs = config.timeoutFallbackMs;
1313
1378
  const waits = !hasServerDecision && timeoutMs != null && timeoutMs > 0;