@wireai/activation 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +62 -8
- package/CHANGELOG.md +188 -3
- package/INTEGRATION_PROMPT.md +25 -2
- package/README.md +112 -1
- package/dist/analytics/index.d.mts +18 -6
- package/dist/analytics/index.d.ts +18 -6
- package/dist/analytics/index.js +151 -41
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +147 -42
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/coachmarks/index.d.mts +16 -0
- package/dist/coachmarks/index.d.ts +16 -0
- package/dist/coachmarks/index.js +19 -13
- package/dist/coachmarks/index.js.map +1 -1
- package/dist/coachmarks/index.mjs +19 -13
- package/dist/coachmarks/index.mjs.map +1 -1
- package/dist/{currentSession-C0_odnIW.d.mts → currentSession-BlCeDP0f.d.mts} +145 -33
- package/dist/{currentSession-DdnUq2HQ.d.ts → currentSession-BxEB37xt.d.ts} +145 -33
- package/dist/index.d.mts +243 -53
- package/dist/index.d.ts +243 -53
- package/dist/index.js +531 -156
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +517 -157
- 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 +79 -14
- package/dist/questionnaire/index.js.map +1 -1
- package/dist/questionnaire/index.mjs +79 -14
- 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 +103 -16
- package/dist/reviews/index.js.map +1 -1
- package/dist/reviews/index.mjs +103 -16
- package/dist/reviews/index.mjs.map +1 -1
- package/dist/showcase/index.js +15 -6
- package/dist/showcase/index.js.map +1 -1
- package/dist/showcase/index.mjs +15 -6
- package/dist/showcase/index.mjs.map +1 -1
- package/dist/{transport-BGW9uXZJ.d.mts → transport-CF_eHwzC.d.mts} +15 -1
- package/dist/{transport-jUJd5kxu.d.ts → transport-DsRe4epC.d.ts} +15 -1
- package/llms.txt +3 -0
- package/package.json +1 -1
- package/src/WireOnboarding.tsx +140 -5
- package/src/activation/useWireActivation.ts +12 -1
- package/src/activation/wireActivation.ts +44 -25
- package/src/analytics/analyticsFacade.ts +54 -29
- package/src/analytics/currentSession.ts +83 -0
- package/src/analytics/eventQueue.ts +9 -1
- package/src/analytics/index.ts +20 -1
- package/src/analytics/reportClientEvent.ts +42 -0
- package/src/analytics/screenTracking.ts +6 -1
- package/src/analytics/useAnalytics.ts +22 -1
- package/src/coachmarks/runtime.ts +53 -17
- package/src/config/wireConfigFromEnv.ts +46 -2
- package/src/context/deviceId.ts +173 -0
- package/src/context/userContext.ts +18 -0
- package/src/index.ts +54 -2
- package/src/questionnaire/runtime.ts +13 -2
- package/src/questionnaire/useQuestionnaireGate.ts +11 -4
- 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/runtime.ts +153 -1
- package/src/reviews/transport.ts +21 -2
- package/src/reviews/useReviewGate.ts +14 -4
- package/src/session-analytics/lifecycle.ts +9 -2
- package/src/session-analytics/reportSessionStart.ts +15 -4
- package/src/session-analytics/useLifecycleEvents.ts +83 -27
- package/src/session-analytics/useSessionStart.ts +37 -1
- package/src/types.ts +41 -4
|
@@ -290,7 +290,7 @@ declare const fetchQuestionnaireDecision: (target: QuestionnaireTarget | undefin
|
|
|
290
290
|
declare const questionnaireSeenKey: (id: string, version?: string) => string;
|
|
291
291
|
/** Last-shown timestamp key (epoch ms), for the cooldown rule. */
|
|
292
292
|
declare const questionnaireLastShownKey: (id: string) => string;
|
|
293
|
-
/** Session-count key, incremented once per
|
|
293
|
+
/** Session-count key, incremented once per APP-OPEN (not per mount), for the min-sessions rule. */
|
|
294
294
|
declare const questionnaireSessionsKey: (id: string) => string;
|
|
295
295
|
|
|
296
296
|
export { type FetchQuestionnaireDecisionOptions, type QuestionnaireAnswers, type QuestionnaireDecision, type QuestionnaireDecisionResponse, type QuestionnaireDefinition, QuestionnaireGate, type QuestionnaireGateController, type QuestionnaireGateEvent, type QuestionnaireGateEventName, type QuestionnaireGateProps, type QuestionnaireMeta, type QuestionnaireSubmission, type QuestionnaireTarget, type UseQuestionnaireGateOptions, buildQuestionnaireSubmission, decideQuestionnaire, fetchQuestionnaireDecision, questionnaireLastShownKey, questionnaireSeenKey, questionnaireSessionsKey, submitQuestionnaireResponse, useQuestionnaireGate };
|
|
@@ -290,7 +290,7 @@ declare const fetchQuestionnaireDecision: (target: QuestionnaireTarget | undefin
|
|
|
290
290
|
declare const questionnaireSeenKey: (id: string, version?: string) => string;
|
|
291
291
|
/** Last-shown timestamp key (epoch ms), for the cooldown rule. */
|
|
292
292
|
declare const questionnaireLastShownKey: (id: string) => string;
|
|
293
|
-
/** Session-count key, incremented once per
|
|
293
|
+
/** Session-count key, incremented once per APP-OPEN (not per mount), for the min-sessions rule. */
|
|
294
294
|
declare const questionnaireSessionsKey: (id: string) => string;
|
|
295
295
|
|
|
296
296
|
export { type FetchQuestionnaireDecisionOptions, type QuestionnaireAnswers, type QuestionnaireDecision, type QuestionnaireDecisionResponse, type QuestionnaireDefinition, QuestionnaireGate, type QuestionnaireGateController, type QuestionnaireGateEvent, type QuestionnaireGateEventName, type QuestionnaireGateProps, type QuestionnaireMeta, type QuestionnaireSubmission, type QuestionnaireTarget, type UseQuestionnaireGateOptions, buildQuestionnaireSubmission, decideQuestionnaire, fetchQuestionnaireDecision, questionnaireLastShownKey, questionnaireSeenKey, questionnaireSessionsKey, submitQuestionnaireResponse, useQuestionnaireGate };
|
|
@@ -1091,14 +1091,21 @@ var styles7 = reactNative.StyleSheet.create({
|
|
|
1091
1091
|
});
|
|
1092
1092
|
|
|
1093
1093
|
// src/coachmarks/runtime.ts
|
|
1094
|
-
var
|
|
1095
|
-
var
|
|
1096
|
-
var
|
|
1097
|
-
|
|
1094
|
+
var COACHMARK_RUNTIME_SLOT = /* @__PURE__ */ Symbol.for("@wireai/activation:coachmarkRuntime");
|
|
1095
|
+
var runtimeGlobal = globalThis;
|
|
1096
|
+
var coachmarkRuntime = () => {
|
|
1097
|
+
const existing = runtimeGlobal[COACHMARK_RUNTIME_SLOT];
|
|
1098
|
+
if (existing) return existing;
|
|
1099
|
+
const created = { storage: null, testing: false, coachmarksEnabled: true };
|
|
1100
|
+
runtimeGlobal[COACHMARK_RUNTIME_SLOT] = created;
|
|
1101
|
+
return created;
|
|
1102
|
+
};
|
|
1103
|
+
var getCoachmarkStorage = () => coachmarkRuntime().storage;
|
|
1104
|
+
var isCoachmarkTesting = () => coachmarkRuntime().testing;
|
|
1098
1105
|
var SEEN_VALUE = "1";
|
|
1099
1106
|
var hasSeenGate = (key, storageOverride, testingOverride) => {
|
|
1100
|
-
if (testingOverride != null ? testingOverride :
|
|
1101
|
-
const storage = storageOverride != null ? storageOverride :
|
|
1107
|
+
if (testingOverride != null ? testingOverride : isCoachmarkTesting()) return false;
|
|
1108
|
+
const storage = storageOverride != null ? storageOverride : getCoachmarkStorage();
|
|
1102
1109
|
if (!storage) return false;
|
|
1103
1110
|
try {
|
|
1104
1111
|
return storage.getItem(key) === SEEN_VALUE;
|
|
@@ -1107,8 +1114,8 @@ var hasSeenGate = (key, storageOverride, testingOverride) => {
|
|
|
1107
1114
|
}
|
|
1108
1115
|
};
|
|
1109
1116
|
var markSeenGate = (key, storageOverride, testingOverride) => {
|
|
1110
|
-
if (testingOverride != null ? testingOverride :
|
|
1111
|
-
const storage = storageOverride != null ? storageOverride :
|
|
1117
|
+
if (testingOverride != null ? testingOverride : isCoachmarkTesting()) return;
|
|
1118
|
+
const storage = storageOverride != null ? storageOverride : getCoachmarkStorage();
|
|
1112
1119
|
if (!storage) return;
|
|
1113
1120
|
try {
|
|
1114
1121
|
storage.setItem(key, SEEN_VALUE);
|
|
@@ -1290,8 +1297,32 @@ var sameDecision = (a, b) => {
|
|
|
1290
1297
|
return a.fire === b.fire && a.reason === b.reason;
|
|
1291
1298
|
};
|
|
1292
1299
|
|
|
1300
|
+
// src/analytics/reportClientEvent.ts
|
|
1301
|
+
var makeSessionId = () => `wire_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
1302
|
+
|
|
1303
|
+
// src/analytics/currentSession.ts
|
|
1304
|
+
var CURRENT_SESSION_ID_SLOT = /* @__PURE__ */ Symbol.for(
|
|
1305
|
+
"@wireai/activation:currentSessionId"
|
|
1306
|
+
);
|
|
1307
|
+
var globalSlot = globalThis;
|
|
1308
|
+
var getCurrentSessionId = () => globalSlot[CURRENT_SESSION_ID_SLOT];
|
|
1309
|
+
|
|
1293
1310
|
// src/reviews/runtime.ts
|
|
1294
1311
|
var resolveStorage = (override) => override != null ? override : getCoachmarkStorage();
|
|
1312
|
+
var NO_STORAGE_WARNED_SLOT = /* @__PURE__ */ Symbol.for(
|
|
1313
|
+
"@wireai/activation:gateStorageWarned"
|
|
1314
|
+
);
|
|
1315
|
+
var gateWarnGlobal = globalThis;
|
|
1316
|
+
var warnMissingGateStorage = (storage, gate) => {
|
|
1317
|
+
if (storage) return;
|
|
1318
|
+
if (gateWarnGlobal[NO_STORAGE_WARNED_SLOT]) return;
|
|
1319
|
+
if (typeof __DEV__ === "undefined" || !__DEV__) return;
|
|
1320
|
+
if (typeof console === "undefined" || !console.warn) return;
|
|
1321
|
+
gateWarnGlobal[NO_STORAGE_WARNED_SLOT] = true;
|
|
1322
|
+
console.warn(
|
|
1323
|
+
`[wireai] the ${gate} gate has no sync storage, so its app-open counter is stuck at 1 and the fail-closed minSessions rule can never be satisfied \u2014 the gate will never fire. Mount CoachmarkProvider with a sync storage adapter at your app root, or pass \`storage\` to the gate.`
|
|
1324
|
+
);
|
|
1325
|
+
};
|
|
1295
1326
|
var readInt = (storage, key) => {
|
|
1296
1327
|
if (!storage) return 0;
|
|
1297
1328
|
try {
|
|
@@ -1309,11 +1340,45 @@ var writeInt = (storage, key, value) => {
|
|
|
1309
1340
|
} catch {
|
|
1310
1341
|
}
|
|
1311
1342
|
};
|
|
1343
|
+
var readStr = (storage, key) => {
|
|
1344
|
+
if (!storage) return void 0;
|
|
1345
|
+
try {
|
|
1346
|
+
const raw = storage.getItem(key);
|
|
1347
|
+
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
1348
|
+
} catch {
|
|
1349
|
+
return void 0;
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
var PROCESS_OPEN_ID_SLOT = /* @__PURE__ */ Symbol.for("@wireai/activation:processOpenId");
|
|
1353
|
+
var openIdGlobal = globalThis;
|
|
1354
|
+
var currentOpenId = () => {
|
|
1355
|
+
var _a;
|
|
1356
|
+
const existing = openIdGlobal[PROCESS_OPEN_ID_SLOT];
|
|
1357
|
+
if (existing) return existing;
|
|
1358
|
+
const resolved = (_a = getCurrentSessionId()) != null ? _a : makeSessionId();
|
|
1359
|
+
openIdGlobal[PROCESS_OPEN_ID_SLOT] = resolved;
|
|
1360
|
+
return resolved;
|
|
1361
|
+
};
|
|
1362
|
+
var bumpSessionCount = (storage, sessionsKey, openKey, openId = currentOpenId()) => {
|
|
1363
|
+
const lastOpen = readStr(storage, openKey);
|
|
1364
|
+
const stored = readInt(storage, sessionsKey);
|
|
1365
|
+
if (lastOpen === openId) return stored > 0 ? stored : 1;
|
|
1366
|
+
const next = stored + 1;
|
|
1367
|
+
writeInt(storage, sessionsKey, next);
|
|
1368
|
+
if (storage) {
|
|
1369
|
+
try {
|
|
1370
|
+
storage.setItem(openKey, openId);
|
|
1371
|
+
} catch {
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
return next;
|
|
1375
|
+
};
|
|
1312
1376
|
|
|
1313
1377
|
// src/questionnaire/runtime.ts
|
|
1314
1378
|
var questionnaireSeenKey = (id, version) => version ? `wire_questionnaire_${id}_${version}_seen` : `wire_questionnaire_${id}_seen`;
|
|
1315
1379
|
var questionnaireLastShownKey = (id) => `wire_questionnaire_${id}_last`;
|
|
1316
1380
|
var questionnaireSessionsKey = (id) => `wire_questionnaire_${id}_sessions`;
|
|
1381
|
+
var questionnaireSessionOpenKey = (id) => `wire_questionnaire_${id}_open`;
|
|
1317
1382
|
|
|
1318
1383
|
// src/questionnaire/useQuestionnaireGate.ts
|
|
1319
1384
|
var useStableValue2 = (value, isEqual) => {
|
|
@@ -1333,18 +1398,18 @@ var useQuestionnaireGate = ({
|
|
|
1333
1398
|
const config = useStableValue2(configProp, shallowEqual);
|
|
1334
1399
|
const decision = useStableValue2(decisionProp, (a, b) => sameDecision(a, b));
|
|
1335
1400
|
const featureEnabled = useResolvedFeatures({ flags: features, config: featuresConfig }).questionnaire.enabled;
|
|
1336
|
-
const
|
|
1401
|
+
const testing = isTesting != null ? isTesting : isCoachmarkTesting();
|
|
1337
1402
|
const seenKey = questionnaireSeenKey(
|
|
1338
1403
|
config.id,
|
|
1339
1404
|
config.oncePerVersion === false ? void 0 : config.appVersion
|
|
1340
1405
|
);
|
|
1341
1406
|
const lastKey = questionnaireLastShownKey(config.id);
|
|
1342
1407
|
const sessionsKey = questionnaireSessionsKey(config.id);
|
|
1408
|
+
const sessionOpenKey = questionnaireSessionOpenKey(config.id);
|
|
1343
1409
|
const sessions = React8.useState(() => {
|
|
1344
1410
|
const store = resolveStorage(storage);
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
return next;
|
|
1411
|
+
warnMissingGateStorage(store, "questionnaire");
|
|
1412
|
+
return bumpSessionCount(store, sessionsKey, sessionOpenKey);
|
|
1348
1413
|
})[0];
|
|
1349
1414
|
const hasServerDecision = decision != null;
|
|
1350
1415
|
const timeoutMs = config.timeoutFallbackMs;
|
|
@@ -1364,7 +1429,7 @@ var useQuestionnaireGate = ({
|
|
|
1364
1429
|
visible: false,
|
|
1365
1430
|
verdict: { fire: false, reason: "feature_disabled" }
|
|
1366
1431
|
};
|
|
1367
|
-
if (
|
|
1432
|
+
if (testing)
|
|
1368
1433
|
return {
|
|
1369
1434
|
visible: true,
|
|
1370
1435
|
verdict: { fire: true, reason: "testing" }
|
|
@@ -1383,7 +1448,7 @@ var useQuestionnaireGate = ({
|
|
|
1383
1448
|
return { visible: ready && resolved.fire && !alreadySeen, verdict: resolved };
|
|
1384
1449
|
}, [
|
|
1385
1450
|
featureEnabled,
|
|
1386
|
-
|
|
1451
|
+
testing,
|
|
1387
1452
|
config,
|
|
1388
1453
|
decision,
|
|
1389
1454
|
events,
|