@wireai/activation 0.13.3 → 0.13.5
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 +3 -1
- package/CHANGELOG.md +63 -0
- package/INTEGRATION_PROMPT.md +7 -1
- package/README.md +52 -0
- package/dist/analytics/index.d.mts +86 -6
- package/dist/analytics/index.d.ts +86 -6
- package/dist/analytics/index.js +167 -2
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +167 -3
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/coachmarks/index.d.mts +1 -1
- package/dist/coachmarks/index.d.ts +1 -1
- package/dist/coachmarks/index.js.map +1 -1
- package/dist/coachmarks/index.mjs.map +1 -1
- package/dist/{currentSession-BoWtr3Jp.d.mts → currentSession-DgJf0fRz.d.mts} +2 -2
- package/dist/{currentSession-CCOMlaQ2.d.ts → currentSession-EOHU64QD.d.ts} +2 -2
- package/dist/{decision-Cjw0jbEj.d.mts → decision-Bgo17oH7.d.mts} +1 -1
- package/dist/{decision-GfpXAsk_.d.ts → decision-Bkh_LigV.d.ts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -2
- package/dist/index.mjs.map +1 -1
- package/dist/questionnaire/index.d.mts +3 -3
- package/dist/questionnaire/index.d.ts +3 -3
- package/dist/questionnaire/index.js.map +1 -1
- package/dist/questionnaire/index.mjs.map +1 -1
- package/dist/reviews/index.d.mts +5 -5
- package/dist/reviews/index.d.ts +5 -5
- package/dist/reviews/index.js +4 -2
- package/dist/reviews/index.js.map +1 -1
- package/dist/reviews/index.mjs +4 -2
- package/dist/reviews/index.mjs.map +1 -1
- package/dist/showcase/index.d.mts +1 -1
- package/dist/showcase/index.d.ts +1 -1
- package/dist/showcase/index.js.map +1 -1
- package/dist/showcase/index.mjs.map +1 -1
- package/dist/{transport-DFuPyCoJ.d.ts → transport-B_0SgCBe.d.ts} +1 -1
- package/dist/{transport-CefdERPs.d.mts → transport-j5gFfJhK.d.mts} +1 -1
- package/dist/{types-CKFhyrMu.d.mts → types-BpwiRpA8.d.mts} +1 -1
- package/dist/{types-CKFhyrMu.d.ts → types-BpwiRpA8.d.ts} +1 -1
- package/dist/{types-l2tfg23P.d.mts → types-Cju-1_jT.d.mts} +1 -1
- package/dist/{types-UVYt9BJe.d.ts → types-h2BZvl1t.d.ts} +1 -1
- package/llms.txt +1 -1
- package/package.json +3 -1
- package/src/activation/revalidation.ts +9 -1
- package/src/analytics/currentSession.ts +10 -0
- package/src/analytics/eventQueue.ts +5 -0
- package/src/analytics/index.ts +6 -0
- package/src/analytics/reportClientEvent.ts +29 -7
- package/src/analytics/wireDoctor.ts +330 -0
- package/src/coachmarks/runtime.ts +10 -1
- package/src/context/deviceId.ts +10 -1
- package/src/features/WireFeaturesProvider.tsx +8 -0
- package/src/identity/identityRecord.ts +9 -1
- package/src/reviews/runtime.ts +11 -1
- package/src/theme/ThemeContext.tsx +7 -0
package/dist/analytics/index.mjs
CHANGED
|
@@ -20,13 +20,15 @@ var toWireEvents = (events) => events.map((event) => {
|
|
|
20
20
|
return rest;
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
|
-
var buildEventsRequest = (target, events) => {
|
|
23
|
+
var buildEventsRequest = (target, events, options) => {
|
|
24
24
|
if (!(target == null ? void 0 : target.serverUrl) || events.length === 0) return null;
|
|
25
25
|
try {
|
|
26
26
|
const url = `${target.serverUrl.replace(/\/$/, "")}/v1/events`;
|
|
27
27
|
const headers = { "Content-Type": "application/json" };
|
|
28
28
|
if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;
|
|
29
|
-
const
|
|
29
|
+
const envelope = { events: toWireEvents(events) };
|
|
30
|
+
if ((options == null ? void 0 : options.dryRun) === true) envelope.dry_run = true;
|
|
31
|
+
const body = JSON.stringify(envelope);
|
|
30
32
|
return { url, init: { method: "POST", headers, body } };
|
|
31
33
|
} catch {
|
|
32
34
|
return null;
|
|
@@ -223,6 +225,168 @@ var useScreenTracking = (navigationRef, options = {}) => {
|
|
|
223
225
|
}, [navigationRef]);
|
|
224
226
|
};
|
|
225
227
|
|
|
228
|
+
// src/analytics/wireDoctor.ts
|
|
229
|
+
var PROBE_STORAGE_KEY = "wireai:doctor:probe";
|
|
230
|
+
var PROBE_QUESTION_KEY = "wire_doctor_probe";
|
|
231
|
+
var EXPECTED_KEY_PREFIX = "wai_";
|
|
232
|
+
var NETWORK_TIMEOUT_MS = 1e4;
|
|
233
|
+
var check = (name, ok, detail) => ({ name, ok, detail });
|
|
234
|
+
var fetchWithTimeout = async (url, init) => {
|
|
235
|
+
if (typeof fetch === "undefined") return void 0;
|
|
236
|
+
const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
|
|
237
|
+
const timer = setTimeout(() => controller == null ? void 0 : controller.abort(), NETWORK_TIMEOUT_MS);
|
|
238
|
+
try {
|
|
239
|
+
return await fetch(url, controller ? { ...init, signal: controller.signal } : init);
|
|
240
|
+
} catch {
|
|
241
|
+
return void 0;
|
|
242
|
+
} finally {
|
|
243
|
+
clearTimeout(timer);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
var checkTarget = (target) => {
|
|
247
|
+
const serverUrl = target == null ? void 0 : target.serverUrl;
|
|
248
|
+
if (typeof serverUrl !== "string" || serverUrl.trim().length === 0) {
|
|
249
|
+
return check("target", false, "no serverUrl configured: set `serverUrl` on the kit config.");
|
|
250
|
+
}
|
|
251
|
+
let parsedHost = false;
|
|
252
|
+
try {
|
|
253
|
+
const parsed = new URL(serverUrl);
|
|
254
|
+
parsedHost = parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
255
|
+
} catch {
|
|
256
|
+
parsedHost = false;
|
|
257
|
+
}
|
|
258
|
+
if (!parsedHost) {
|
|
259
|
+
return check("target", false, "serverUrl is not a valid http(s) URL.");
|
|
260
|
+
}
|
|
261
|
+
const apiKey = target == null ? void 0 : target.apiKey;
|
|
262
|
+
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
263
|
+
return check("target", false, "serverUrl looks valid, but no apiKey is configured.");
|
|
264
|
+
}
|
|
265
|
+
const prefixOk = apiKey.startsWith(EXPECTED_KEY_PREFIX);
|
|
266
|
+
return check(
|
|
267
|
+
"target",
|
|
268
|
+
true,
|
|
269
|
+
`serverUrl is a valid http(s) URL; apiKey present (${apiKey.length} chars, expected prefix: ${prefixOk ? "yes" : "no"}).`
|
|
270
|
+
);
|
|
271
|
+
};
|
|
272
|
+
var checkReachability = async (serverUrl) => {
|
|
273
|
+
const url = `${serverUrl.replace(/\/$/, "")}/v1/events/contract`;
|
|
274
|
+
const res = await fetchWithTimeout(url, { method: "GET" });
|
|
275
|
+
if (!res) {
|
|
276
|
+
return check("reachability", false, "could not reach the server (network error or timeout).");
|
|
277
|
+
}
|
|
278
|
+
const status = res.status;
|
|
279
|
+
const ok = !!res.ok;
|
|
280
|
+
if (!ok) {
|
|
281
|
+
return check(
|
|
282
|
+
"reachability",
|
|
283
|
+
false,
|
|
284
|
+
`the server answered ${typeof status === "number" ? status : "an error"} for the events contract; check the serverUrl points at a Wire server.`
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
return check("reachability", true, "the server answered the events contract.");
|
|
288
|
+
};
|
|
289
|
+
var checkStorage = async (storage) => {
|
|
290
|
+
if (!storage) {
|
|
291
|
+
return check(
|
|
292
|
+
"storage",
|
|
293
|
+
true,
|
|
294
|
+
"no storage injected: the queue runs in DEGRADED in-memory mode and loses pending events on an app kill. Pass AsyncStorage (or an MMKV wrapper) to make it durable."
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
const token = `probe_${Date.now().toString(36)}`;
|
|
298
|
+
try {
|
|
299
|
+
await storage.setItem(PROBE_STORAGE_KEY, token);
|
|
300
|
+
const read = await storage.getItem(PROBE_STORAGE_KEY);
|
|
301
|
+
if (read !== token) {
|
|
302
|
+
return check(
|
|
303
|
+
"storage",
|
|
304
|
+
false,
|
|
305
|
+
"the storage adapter accepted a write but did not read the same value back, so the queue cannot persist."
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
return check("storage", true, "storage write / read round trip succeeded.");
|
|
309
|
+
} catch {
|
|
310
|
+
return check("storage", false, "the storage adapter threw, so the queue cannot persist events.");
|
|
311
|
+
} finally {
|
|
312
|
+
try {
|
|
313
|
+
await storage.removeItem(PROBE_STORAGE_KEY);
|
|
314
|
+
} catch {
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
var checkRoundTrip = async (target) => {
|
|
319
|
+
var _a;
|
|
320
|
+
const event = {
|
|
321
|
+
event_type: "app_event",
|
|
322
|
+
session_id: makeSessionId(),
|
|
323
|
+
question_key: PROBE_QUESTION_KEY
|
|
324
|
+
};
|
|
325
|
+
const req = buildEventsRequest(target, [event], { dryRun: true });
|
|
326
|
+
if (!req) {
|
|
327
|
+
return check("round_trip", false, "could not build the events request from this target.");
|
|
328
|
+
}
|
|
329
|
+
const res = await fetchWithTimeout(req.url, req.init);
|
|
330
|
+
if (!res) {
|
|
331
|
+
return check("round_trip", false, "the events POST failed (network error or timeout).");
|
|
332
|
+
}
|
|
333
|
+
if (!res.ok) {
|
|
334
|
+
const status = res.status;
|
|
335
|
+
return check(
|
|
336
|
+
"round_trip",
|
|
337
|
+
false,
|
|
338
|
+
`the events endpoint answered ${typeof status === "number" ? status : "an error"}; a 401 here means the apiKey is not accepted.`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
const ack = await readEventsAck(res);
|
|
342
|
+
if (!ack) {
|
|
343
|
+
return check(
|
|
344
|
+
"round_trip",
|
|
345
|
+
false,
|
|
346
|
+
"the server answered 2xx but sent no readable ack body, so it is unknown whether the event validated."
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
if (ack.written === 1 && ack.skipped === 0) {
|
|
350
|
+
return check("round_trip", true, "the server validated the probe event: written=1, skipped=0.");
|
|
351
|
+
}
|
|
352
|
+
return check(
|
|
353
|
+
"round_trip",
|
|
354
|
+
false,
|
|
355
|
+
`the server DISCARDED the probe event: written=${(_a = ack.written) != null ? _a : "unknown"}, skipped=${ack.skipped}` + (ack.reasons.length > 0 ? `, reasons: ${ack.reasons.join(", ")}.` : ". It gave no reason; check the server's ingest log for this request.")
|
|
356
|
+
);
|
|
357
|
+
};
|
|
358
|
+
var wireDoctor = async (options) => {
|
|
359
|
+
if (typeof __DEV__ === "undefined" || !__DEV__) {
|
|
360
|
+
return {
|
|
361
|
+
ok: false,
|
|
362
|
+
checks: [
|
|
363
|
+
check(
|
|
364
|
+
"dev_only",
|
|
365
|
+
false,
|
|
366
|
+
"wireDoctor is dev-only and did NOT run: __DEV__ is unset or false. Nothing was checked."
|
|
367
|
+
)
|
|
368
|
+
]
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
const target = options == null ? void 0 : options.target;
|
|
373
|
+
const checks = [checkTarget(target)];
|
|
374
|
+
if (checks[0].ok && target) {
|
|
375
|
+
checks.push(await checkReachability(target.serverUrl));
|
|
376
|
+
checks.push(await checkStorage(options == null ? void 0 : options.storage));
|
|
377
|
+
checks.push(await checkRoundTrip(target));
|
|
378
|
+
} else {
|
|
379
|
+
checks.push(await checkStorage(options == null ? void 0 : options.storage));
|
|
380
|
+
}
|
|
381
|
+
return { ok: checks.every((c) => c.ok), checks };
|
|
382
|
+
} catch {
|
|
383
|
+
return {
|
|
384
|
+
ok: false,
|
|
385
|
+
checks: [check("internal_error", false, "wireDoctor could not complete: an unexpected error was swallowed.")]
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
|
|
226
390
|
// src/permissions/permissionEvents.ts
|
|
227
391
|
var WIRE_PERMISSION_EVENTS = {
|
|
228
392
|
/** The priming screen became visible. The denominator for every rate below. */
|
|
@@ -1101,6 +1265,6 @@ var useAnalytics = (config, options = {}) => {
|
|
|
1101
1265
|
return ref.current;
|
|
1102
1266
|
};
|
|
1103
1267
|
|
|
1104
|
-
export { AUTO_DEVICE_ID_PREFIX, WIRE_ONBOARDING_EVENTS, analyticsUserIdStorageKey, buildContextEnvelope, clearPiiFromContext, clearUserContext, createAnalytics, createEventQueue, createScreenTracker, deviceIdStorageKey, ensureCurrentSessionId, getActiveRouteName, getCurrentSessionId, looksLikeEmail, makeSessionId, reportAppEvent, reportClientEvent, reportClientEventAwait, reportClientEvents, reportClientEventsAwait, resetAutoDeviceKeys, resetCurrentSessionId, resetEventQueueKeys, resolveAutoDeviceKey, screenTrackingHandler, setCurrentSessionId, toAnalyticsEvent, useAnalytics, useScreenTracking };
|
|
1268
|
+
export { AUTO_DEVICE_ID_PREFIX, WIRE_ONBOARDING_EVENTS, analyticsUserIdStorageKey, buildContextEnvelope, clearPiiFromContext, clearUserContext, createAnalytics, createEventQueue, createScreenTracker, deviceIdStorageKey, ensureCurrentSessionId, getActiveRouteName, getCurrentSessionId, looksLikeEmail, makeSessionId, reportAppEvent, reportClientEvent, reportClientEventAwait, reportClientEvents, reportClientEventsAwait, resetAutoDeviceKeys, resetCurrentSessionId, resetEventQueueKeys, resolveAutoDeviceKey, screenTrackingHandler, setCurrentSessionId, toAnalyticsEvent, useAnalytics, useScreenTracking, wireDoctor };
|
|
1105
1269
|
//# sourceMappingURL=index.mjs.map
|
|
1106
1270
|
//# sourceMappingURL=index.mjs.map
|