@knocklabs/client 0.21.2 → 0.21.4

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.
@@ -1,44 +1,44 @@
1
- var I = Object.defineProperty;
2
- var C = (u, e, t) => e in u ? I(u, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[e] = t;
3
- var l = (u, e, t) => C(u, typeof e != "symbol" ? e + "" : e, t);
4
- import { Store as E } from "@tanstack/store";
5
- import { URLPattern as w } from "urlpattern-polyfill";
6
- import { byKey as y, mockDefaultGroup as R, formatFilters as G, formatState as S, checkStateIfThrottled as m, formatGroupStage as v, DEFAULT_GROUP_KEY as P, newUrl as D, predicateUrlRules as A, predicateUrlPatterns as L, findDefaultGroup as T } from "./helpers.mjs";
7
- import { SelectionResult as $ } from "./types.mjs";
8
- const K = 50, O = 30 * 1e3, U = 3, p = {
1
+ var E = Object.defineProperty;
2
+ var w = (u, e, s) => e in u ? E(u, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : u[e] = s;
3
+ var h = (u, e, s) => w(u, typeof e != "symbol" ? e + "" : e, s);
4
+ import { Store as R } from "@tanstack/store";
5
+ import { URLPattern as A } from "urlpattern-polyfill";
6
+ import { byKey as m, mockDefaultGroup as P, formatFilters as v, formatState as b, checkStateIfThrottled as _, formatGroupStage as y, DEFAULT_GROUP_KEY as D, newUrl as K, predicateUrlRules as L, predicateUrlPatterns as $, findDefaultGroup as T } from "./helpers.mjs";
7
+ import { SelectionResult as O } from "./types.mjs";
8
+ const F = 50, U = 30 * 1e3, q = 3, f = {
9
9
  GUIDE_KEY: "knock_guide_key",
10
10
  PREVIEW_SESSION_ID: "knock_preview_session_id"
11
- }, f = "knock_guide_debug", k = () => {
11
+ }, G = "knock_guide_debug", p = () => {
12
12
  if (typeof window < "u")
13
13
  return window;
14
- }, F = (u) => `/v1/users/${u}/guides`, b = () => {
15
- const u = k();
14
+ }, N = (u) => `/v1/users/${u}/guides`, I = () => {
15
+ const u = p();
16
16
  if (!u || !u.location)
17
17
  return { forcedGuideKey: null, previewSessionId: null };
18
- const e = new URLSearchParams(u.location.search), t = e.get(p.GUIDE_KEY), s = e.get(
19
- p.PREVIEW_SESSION_ID
18
+ const e = new URLSearchParams(u.location.search), s = e.get(f.GUIDE_KEY), t = e.get(
19
+ f.PREVIEW_SESSION_ID
20
20
  );
21
- if (t || s) {
21
+ if (s || t) {
22
22
  if (u.localStorage)
23
23
  try {
24
24
  const r = {
25
- forcedGuideKey: t,
26
- previewSessionId: s
25
+ forcedGuideKey: s,
26
+ previewSessionId: t
27
27
  };
28
- u.localStorage.setItem(f, JSON.stringify(r));
28
+ u.localStorage.setItem(G, JSON.stringify(r));
29
29
  } catch {
30
30
  }
31
31
  return {
32
- forcedGuideKey: t,
33
- previewSessionId: s
32
+ forcedGuideKey: s,
33
+ previewSessionId: t
34
34
  };
35
35
  }
36
36
  let i = null, n = null;
37
37
  if (u.localStorage)
38
38
  try {
39
- const r = u.localStorage.getItem(f);
39
+ const r = u.localStorage.getItem(G);
40
40
  if (r) {
41
- const a = q(r);
41
+ const a = j(r);
42
42
  i = a.forcedGuideKey, n = a.previewSessionId;
43
43
  }
44
44
  } catch {
@@ -47,7 +47,7 @@ const K = 50, O = 30 * 1e3, U = 3, p = {
47
47
  forcedGuideKey: i,
48
48
  previewSessionId: n
49
49
  };
50
- }, q = (u) => {
50
+ }, j = (u) => {
51
51
  try {
52
52
  const e = JSON.parse(u);
53
53
  return {
@@ -60,35 +60,35 @@ const K = 50, O = 30 * 1e3, U = 3, p = {
60
60
  previewSessionId: null
61
61
  };
62
62
  }
63
- }, _ = (u, e, t) => {
64
- const s = new $(), i = T(u.guideGroups);
65
- if (!i) return s;
63
+ }, C = (u, e, s) => {
64
+ const t = new O(), i = T(u.guideGroups);
65
+ if (!i) return t;
66
66
  const n = i.display_sequence, r = u.location;
67
67
  for (const [a, o] of n.entries()) {
68
68
  const c = u.previewGuides[o] || u.guides[o];
69
- !c || !N(c, e, {
69
+ !c || !B(c, e, {
70
70
  location: r,
71
71
  ineligibleGuides: u.ineligibleGuides,
72
72
  debug: u.debug
73
- }) || s.set(a, c);
74
- }
75
- return s.metadata = { guideGroup: i, filters: e, ...t }, s;
76
- }, N = (u, e, { location: t, ineligibleGuides: s = {}, debug: i = {} }) => e.type && e.type !== u.type || e.key && e.key !== u.key ? !1 : i.forcedGuideKey ? i.forcedGuideKey === u.key : s[u.key] || !u.active || u.steps.every((r) => !!r.message.archived_at) ? !1 : j(u, t), j = (u, e) => {
77
- const t = e ? D(e) : void 0, s = u.activation_url_rules || [], i = u.activation_url_patterns || [];
78
- if (t && s.length > 0) {
79
- if (!A(t, s)) return !1;
80
- } else if (t && i.length > 0 && !L(t, i))
73
+ }) || t.set(a, c);
74
+ }
75
+ return t.metadata = { guideGroup: i, filters: e, ...s }, t;
76
+ }, B = (u, e, { location: s, ineligibleGuides: t = {}, debug: i = {} }) => e.type && e.type !== u.type || e.key && e.key !== u.key ? !1 : i.focusedGuideKeys && Object.keys(i.focusedGuideKeys).length > 0 ? !!i.focusedGuideKeys[u.key] : i.forcedGuideKey ? i.forcedGuideKey === u.key : t[u.key] || !u.active || u.steps.every((r) => !!r.message.archived_at) ? !1 : M(u, s), M = (u, e) => {
77
+ const s = e ? K(e) : void 0, t = u.activation_url_rules || [], i = u.activation_url_patterns || [];
78
+ if (s && t.length > 0) {
79
+ if (!L(s, t)) return !1;
80
+ } else if (s && i.length > 0 && !$(s, i))
81
81
  return !1;
82
82
  return !0;
83
83
  };
84
- class W {
85
- constructor(e, t, s = {}, i = {}) {
86
- l(this, "store");
84
+ class V {
85
+ constructor(e, s, t = {}, i = {}) {
86
+ h(this, "store");
87
87
  // Phoenix channels for real time guide updates over websocket
88
- l(this, "socket");
89
- l(this, "socketChannel");
90
- l(this, "socketChannelTopic");
91
- l(this, "socketEventTypes", [
88
+ h(this, "socket");
89
+ h(this, "socketChannel");
90
+ h(this, "socketChannelTopic");
91
+ h(this, "socketEventTypes", [
92
92
  "guide.added",
93
93
  "guide.updated",
94
94
  "guide.removed",
@@ -96,44 +96,44 @@ class W {
96
96
  "guide_group.updated",
97
97
  "guide.live_preview_updated"
98
98
  ]);
99
- l(this, "subscribeRetryCount", 0);
99
+ h(this, "subscribeRetryCount", 0);
100
100
  // Original history methods to monkey patch, or restore in cleanups.
101
- l(this, "pushStateFn");
102
- l(this, "replaceStateFn");
101
+ h(this, "pushStateFn");
102
+ h(this, "replaceStateFn");
103
103
  // Guides that are competing to render are "staged" first without rendering
104
104
  // and ranked based on its relative order in the group over a duration of time
105
105
  // to resolve and render the prevailing one.
106
- l(this, "stage");
107
- l(this, "counterIntervalId");
106
+ h(this, "stage");
107
+ h(this, "counterIntervalId");
108
108
  // Define as an arrow func property to always bind this to the class instance.
109
- l(this, "handleLocationChange", () => {
109
+ h(this, "handleLocationChange", () => {
110
110
  this.knock.log("[Guide] .handleLocationChange");
111
- const e = k();
111
+ const e = p();
112
112
  if (!(e != null && e.location)) return;
113
- const t = e.location.href;
114
- if (this.store.state.location === t) return;
115
- if (this.knock.log(`[Guide] Detected a location change: ${t}`), !this.options.trackDebugParams) {
116
- this.setLocation(t);
113
+ const s = e.location.href;
114
+ if (this.store.state.location === s) return;
115
+ if (this.knock.log(`[Guide] Detected a location change: ${s}`), !this.options.trackDebugParams) {
116
+ this.setLocation(s);
117
117
  return;
118
118
  }
119
- const s = this.store.state.debug || {}, i = b();
120
- this.setLocation(t, { debug: i }), this.checkDebugStateChanged(
121
- s,
119
+ const t = this.store.state.debug || {}, i = I();
120
+ this.setLocation(s, { debug: i }), this.checkDebugStateChanged(
121
+ t,
122
122
  i
123
123
  ) && (this.knock.log(
124
124
  "[Guide] Debug state changed, refetching guides and resubscribing to the websocket channel"
125
125
  ), this.fetch(), this.subscribe());
126
126
  });
127
127
  var g;
128
- this.knock = e, this.channelId = t, this.targetParams = s, this.options = i;
128
+ this.knock = e, this.channelId = s, this.targetParams = t, this.options = i;
129
129
  const {
130
130
  trackLocationFromWindow: n = !0,
131
131
  // TODO(KNO-11523): Remove once we ship guide toolbar v2, and offload as
132
132
  // much debugging specific logic and responsibilities to toolbar.
133
133
  trackDebugParams: r = !1,
134
- throttleCheckInterval: a = O
135
- } = i, o = k(), c = n ? (g = o == null ? void 0 : o.location) == null ? void 0 : g.href : void 0, d = r ? b() : void 0;
136
- this.store = new E({
134
+ throttleCheckInterval: a = U
135
+ } = i, o = p(), c = n ? (g = o == null ? void 0 : o.location) == null ? void 0 : g.href : void 0, d = r ? I() : void 0;
136
+ this.store = new R({
137
137
  guideGroups: [],
138
138
  guideGroupDisplayLogs: {},
139
139
  guides: {},
@@ -145,8 +145,8 @@ class W {
145
145
  counter: 0,
146
146
  debug: d
147
147
  });
148
- const { socket: h } = this.knock.client();
149
- this.socket = h, this.socketChannelTopic = `guides:${t}`, n && this.listenForLocationChangesFromWindow(), a && this.startCounterInterval(a), this.knock.log("[Guide] Initialized a guide client");
148
+ const { socket: l } = this.knock.client();
149
+ this.socket = l, this.socketChannelTopic = `guides:${s}`, n && this.listenForLocationChangesFromWindow(), a && this.startCounterInterval(a), this.knock.log("[Guide] Initialized a guide client");
150
150
  }
151
151
  incrementCounter() {
152
152
  this.knock.log("[Guide] Incrementing the counter"), this.store.setState((e) => ({ ...e, counter: e.counter + 1 }));
@@ -164,17 +164,17 @@ class W {
164
164
  }
165
165
  async fetch(e) {
166
166
  this.knock.log("[Guide] .fetch"), this.knock.failIfNotAuthenticated();
167
- const t = this.buildQueryParams(e == null ? void 0 : e.filters), s = this.formatQueryKey(t), i = this.store.state.queries[s];
167
+ const s = this.buildQueryParams(e == null ? void 0 : e.filters), t = this.formatQueryKey(s), i = this.store.state.queries[t];
168
168
  if (i)
169
169
  return i;
170
170
  this.store.setState((r) => ({
171
171
  ...r,
172
- queries: { ...r.queries, [s]: { status: "loading" } }
172
+ queries: { ...r.queries, [t]: { status: "loading" } }
173
173
  }));
174
174
  let n;
175
175
  try {
176
176
  this.knock.log("[Guide] Fetching all eligible guides");
177
- const r = await this.knock.user.getGuides(this.channelId, t);
177
+ const r = await this.knock.user.getGuides(this.channelId, s);
178
178
  n = { status: "ok" };
179
179
  const {
180
180
  entries: a,
@@ -182,18 +182,18 @@ class W {
182
182
  guide_group_display_logs: c,
183
183
  ineligible_guides: d
184
184
  } = r;
185
- this.knock.log("[Guide] Loading fetched guides"), this.store.setState((h) => ({
186
- ...h,
187
- guideGroups: (o == null ? void 0 : o.length) > 0 ? o : [R(a)],
185
+ this.knock.log("[Guide] Loading fetched guides"), this.store.setState((l) => ({
186
+ ...l,
187
+ guideGroups: (o == null ? void 0 : o.length) > 0 ? o : [P(a)],
188
188
  guideGroupDisplayLogs: c || {},
189
- guides: y(a.map((g) => this.localCopy(g))),
190
- ineligibleGuides: y(d || []),
191
- queries: { ...h.queries, [s]: n }
189
+ guides: m(a.map((g) => this.localCopy(g))),
190
+ ineligibleGuides: m(d || []),
191
+ queries: { ...l.queries, [t]: n }
192
192
  }));
193
193
  } catch (r) {
194
194
  n = { status: "error", error: r }, this.store.setState((a) => ({
195
195
  ...a,
196
- queries: { ...a.queries, [s]: n }
196
+ queries: { ...a.queries, [t]: n }
197
197
  }));
198
198
  }
199
199
  return n;
@@ -201,15 +201,15 @@ class W {
201
201
  subscribe() {
202
202
  if (!this.socket) return;
203
203
  this.knock.failIfNotAuthenticated(), this.knock.log("[Guide] Subscribing to real time updates"), this.socket.isConnected() || this.socket.connect(), this.socketChannel && this.unsubscribe();
204
- const e = this.store.state.debug, t = {
204
+ const e = this.store.state.debug, s = {
205
205
  ...this.targetParams,
206
206
  user_id: this.knock.userId,
207
207
  force_all_guides: e != null && e.forcedGuideKey || e != null && e.debugging ? !0 : void 0,
208
208
  preview_session_id: (e == null ? void 0 : e.previewSessionId) || void 0
209
- }, s = this.socket.channel(this.socketChannelTopic, t);
209
+ }, t = this.socket.channel(this.socketChannelTopic, s);
210
210
  for (const i of this.socketEventTypes)
211
- s.on(i, (n) => this.handleSocketEvent(n));
212
- ["closed", "errored"].includes(s.state) && (this.subscribeRetryCount = 0, s.join().receive("ok", () => {
211
+ t.on(i, (n) => this.handleSocketEvent(n));
212
+ ["closed", "errored"].includes(t.state) && (this.subscribeRetryCount = 0, t.join().receive("ok", () => {
213
213
  this.knock.log("[Guide] Successfully joined channel");
214
214
  }).receive("error", (i) => {
215
215
  this.knock.log(
@@ -217,10 +217,10 @@ class W {
217
217
  ), this.handleChannelJoinError();
218
218
  }).receive("timeout", () => {
219
219
  this.knock.log("[Guide] Channel join timed out"), this.handleChannelJoinError();
220
- })), this.socketChannel = s;
220
+ })), this.socketChannel = t;
221
221
  }
222
222
  handleChannelJoinError() {
223
- if (this.subscribeRetryCount >= U) {
223
+ if (this.subscribeRetryCount >= q) {
224
224
  this.knock.log(
225
225
  `[Guide] Channel join max retry limit reached: ${this.subscribeRetryCount}`
226
226
  ), this.unsubscribe();
@@ -237,12 +237,12 @@ class W {
237
237
  }
238
238
  }
239
239
  handleSocketEvent(e) {
240
- const { event: t, data: s } = e;
241
- switch (t) {
240
+ const { event: s, data: t } = e;
241
+ switch (s) {
242
242
  case "guide.added":
243
243
  return this.addOrReplaceGuide(e);
244
244
  case "guide.updated":
245
- return s.eligible ? this.addOrReplaceGuide(e) : this.removeGuide(e);
245
+ return t.eligible ? this.addOrReplaceGuide(e) : this.removeGuide(e);
246
246
  case "guide.removed":
247
247
  return this.removeGuide(e);
248
248
  case "guide_group.added":
@@ -254,13 +254,13 @@ class W {
254
254
  return;
255
255
  }
256
256
  }
257
- setLocation(e, t = {}) {
258
- this.knock.log(`[Guide] .setLocation (loc=${e})`), this.clearGroupStage(), this.knock.log("[Guide] Updating the tracked location"), this.store.setState((s) => {
257
+ setLocation(e, s = {}) {
258
+ this.knock.log(`[Guide] .setLocation (loc=${e})`), this.clearGroupStage(), this.knock.log("[Guide] Updating the tracked location"), this.store.setState((t) => {
259
259
  var n;
260
- const i = (n = t == null ? void 0 : t.debug) != null && n.previewSessionId ? s.previewGuides : {};
260
+ const i = (n = s == null ? void 0 : s.debug) != null && n.previewSessionId ? t.previewGuides : {};
261
261
  return {
262
- ...s,
263
262
  ...t,
263
+ ...s,
264
264
  previewGuides: i,
265
265
  location: e
266
266
  };
@@ -268,83 +268,93 @@ class W {
268
268
  }
269
269
  exitDebugMode() {
270
270
  this.knock.log("[Guide] Exiting debug mode");
271
- const e = k();
271
+ const e = p();
272
272
  if (e != null && e.localStorage)
273
273
  try {
274
- e.localStorage.removeItem(f);
274
+ e.localStorage.removeItem(G);
275
275
  } catch {
276
276
  }
277
- if (this.store.setState((t) => ({
278
- ...t,
279
- debug: { forcedGuideKey: null, previewSessionId: null },
277
+ if (this.store.setState((s) => ({
278
+ ...s,
279
+ debug: {
280
+ forcedGuideKey: null,
281
+ previewSessionId: null,
282
+ focusedGuideKeys: {}
283
+ },
280
284
  previewGuides: {}
281
285
  // Clear preview guides when exiting debug mode
282
286
  })), e != null && e.location) {
283
- const t = new URL(e.location.href);
284
- (t.searchParams.has(p.GUIDE_KEY) || t.searchParams.has(p.PREVIEW_SESSION_ID)) && (t.searchParams.delete(p.GUIDE_KEY), t.searchParams.delete(p.PREVIEW_SESSION_ID), e.location.href = t.toString());
287
+ const s = new URL(e.location.href);
288
+ (s.searchParams.has(f.GUIDE_KEY) || s.searchParams.has(f.PREVIEW_SESSION_ID)) && (s.searchParams.delete(f.GUIDE_KEY), s.searchParams.delete(f.PREVIEW_SESSION_ID), e.location.href = s.toString());
285
289
  }
286
290
  }
287
291
  setDebug(e) {
288
- var s;
292
+ var t;
289
293
  this.knock.log("[Guide] .setDebug()");
290
- const t = !((s = this.store.state.debug) != null && s.debugging);
291
- this.store.setState((i) => ({
294
+ const s = !((t = this.store.state.debug) != null && t.debugging);
295
+ this.clearGroupStage(), this.store.setState((i) => ({
292
296
  ...i,
293
- debug: { ...e, debugging: !0 }
294
- })), t && (this.knock.log(
297
+ debug: {
298
+ skipEngagementTracking: !0,
299
+ ignoreDisplayInterval: !0,
300
+ focusedGuideKeys: {},
301
+ ...e,
302
+ debugging: !0
303
+ }
304
+ })), s && (this.knock.log(
295
305
  "[Guide] Start debugging, refetching guides and resubscribing to the websocket channel"
296
306
  ), this.fetch(), this.subscribe());
297
307
  }
298
308
  unsetDebug() {
299
- var t;
309
+ var s;
300
310
  this.knock.log("[Guide] .unsetDebug()");
301
- const e = (t = this.store.state.debug) == null ? void 0 : t.debugging;
302
- this.store.setState((s) => ({ ...s, debug: void 0 })), e && (this.knock.log(
311
+ const e = (s = this.store.state.debug) == null ? void 0 : s.debugging;
312
+ this.clearGroupStage(), this.store.setState((t) => ({ ...t, debug: void 0 })), e && (this.knock.log(
303
313
  "[Guide] Stop debugging, refetching guides and resubscribing to the websocket channel"
304
314
  ), this.fetch(), this.subscribe());
305
315
  }
306
316
  //
307
317
  // Store selector
308
318
  //
309
- selectGuides(e, t = {}, s = {}) {
319
+ selectGuides(e, s = {}, t = {}) {
310
320
  var c;
311
321
  this.knock.log(
312
- `[Guide] .selectGuides (filters: ${G(t)}; state: ${S(e)})`
322
+ `[Guide] .selectGuides (filters: ${v(s)}; state: ${b(e)})`
313
323
  );
314
- const i = this.selectGuide(e, t, {
315
- ...s,
324
+ const i = this.selectGuide(e, s, {
325
+ ...t,
316
326
  // Don't record this result, not the actual query result we need.
317
327
  recordSelectQuery: !1
318
- }), { recordSelectQuery: n = !!((c = e.debug) != null && c.debugging) } = s, r = {
328
+ }), { recordSelectQuery: n = !!((c = e.debug) != null && c.debugging) } = t, r = {
319
329
  limit: "all",
320
- opts: { ...s, recordSelectQuery: n }
321
- }, a = _(e, t, r);
322
- if (this.maybeRecordSelectResult(a), !i && !s.includeThrottled)
330
+ opts: { ...t, recordSelectQuery: n }
331
+ }, a = C(e, s, r);
332
+ if (this.maybeRecordSelectResult(a), !i && !t.includeThrottled)
323
333
  return [];
324
334
  const o = [...a.values()];
325
- if (!s.includeThrottled && m(e)) {
335
+ if (!t.includeThrottled && _(e)) {
326
336
  const d = o.filter(
327
337
  (g) => g.bypass_global_group_limit
328
- ), h = o.length - d.length;
338
+ ), l = o.length - d.length;
329
339
  return this.knock.log(
330
- `[Guide] Throttling ${h} guides from selection, and returning ${d.length} guides`
340
+ `[Guide] Throttling ${l} guides from selection, and returning ${d.length} guides`
331
341
  ), d;
332
342
  }
333
343
  return this.knock.log(`[Guide] Returning ${o.length} guides from selection`), o;
334
344
  }
335
- selectGuide(e, t = {}, s = {}) {
336
- var d;
345
+ selectGuide(e, s = {}, t = {}) {
346
+ var l, g, S;
337
347
  if (this.knock.log(
338
- `[Guide] .selectGuide (filters: ${G(t)}; state: ${S(e)})`
348
+ `[Guide] .selectGuide (filters: ${v(s)}; state: ${b(e)})`
339
349
  ), Object.keys(e.guides).length === 0 && Object.keys(e.previewGuides).length === 0) {
340
350
  this.knock.log("[Guide] Exiting selection (no guides)");
341
351
  return;
342
352
  }
343
353
  this.stage || (this.stage = this.openGroupStage());
344
- const { recordSelectQuery: i = !!((d = e.debug) != null && d.debugging) } = s, n = {
354
+ const { recordSelectQuery: i = !!((l = e.debug) != null && l.debugging) } = t, n = {
345
355
  limit: "one",
346
- opts: { ...s, recordSelectQuery: i }
347
- }, r = _(e, t, n);
356
+ opts: { ...t, recordSelectQuery: i }
357
+ }, r = C(e, s, n);
348
358
  if (this.maybeRecordSelectResult(r), r.size === 0) {
349
359
  this.knock.log("[Guide] Selection found zero result");
350
360
  return;
@@ -354,31 +364,39 @@ class W {
354
364
  `[Guide] Selection found: \`${o.key}\` (total: ${r.size})`
355
365
  ), o.bypass_global_group_limit)
356
366
  return this.knock.log(`[Guide] Returning the unthrottled guide: ${o.key}`), o;
357
- const c = !s.includeThrottled && m(e);
367
+ const c = (S = (g = e.debug) == null ? void 0 : g.focusedGuideKeys) == null ? void 0 : S[o.key], d = !t.includeThrottled && _(e);
358
368
  switch (this.stage.status) {
359
369
  case "open": {
360
370
  this.knock.log(`[Guide] Adding to the group stage: ${o.key}`), this.stage.ordered[a] = o.key;
361
371
  return;
362
372
  }
363
373
  case "patch": {
364
- if (this.knock.log(`[Guide] Patching the group stage: ${o.key}`), this.stage.ordered[a] = o.key, c) {
374
+ if (this.knock.log(`[Guide] Patching the group stage: ${o.key}`), this.stage.ordered[a] = o.key, c)
375
+ return this.knock.log(
376
+ `[Guide] Focused to return \`${o.key}\` (stage: ${y(this.stage)})`
377
+ ), o;
378
+ if (d) {
365
379
  this.knock.log(`[Guide] Throttling the selected guide: ${o.key}`);
366
380
  return;
367
381
  }
368
- const h = this.stage.resolved === o.key ? o : void 0;
382
+ const k = this.stage.resolved === o.key ? o : void 0;
369
383
  return this.knock.log(
370
- `[Guide] Returning \`${h == null ? void 0 : h.key}\` (stage: ${v(this.stage)})`
371
- ), h;
384
+ `[Guide] Returning \`${k == null ? void 0 : k.key}\` (stage: ${y(this.stage)})`
385
+ ), k;
372
386
  }
373
387
  case "closed": {
374
- if (c) {
388
+ if (c)
389
+ return this.knock.log(
390
+ `[Guide] Focused to return \`${o.key}\` (stage: ${y(this.stage)})`
391
+ ), o;
392
+ if (d) {
375
393
  this.knock.log(`[Guide] Throttling the selected guide: ${o.key}`);
376
394
  return;
377
395
  }
378
- const h = this.stage.resolved === o.key ? o : void 0;
396
+ const k = this.stage.resolved === o.key ? o : void 0;
379
397
  return this.knock.log(
380
- `[Guide] Returning \`${h == null ? void 0 : h.key}\` (stage: ${v(this.stage)})`
381
- ), h;
398
+ `[Guide] Returning \`${k == null ? void 0 : k.key}\` (stage: ${y(this.stage)})`
399
+ ), k;
382
400
  }
383
401
  }
384
402
  }
@@ -386,16 +404,16 @@ class W {
386
404
  // and then 2) "one" or "all".
387
405
  maybeRecordSelectResult(e) {
388
406
  if (!e.metadata) return;
389
- const { opts: t, filters: s, limit: i } = e.metadata;
390
- if (!t.recordSelectQuery || !s.key && !s.type || !this.stage || this.stage.status === "closed") return;
407
+ const { opts: s, filters: t, limit: i } = e.metadata;
408
+ if (!s.recordSelectQuery || !t.key && !t.type || !this.stage || this.stage.status === "closed") return;
391
409
  const n = this.stage.results.key || {};
392
- s.key && (n[s.key] = {
393
- ...n[s.key] || {},
410
+ t.key && (n[t.key] = {
411
+ ...n[t.key] || {},
394
412
  [i]: e
395
413
  });
396
414
  const r = this.stage.results.type || {};
397
- s.type && (r[s.type] = {
398
- ...r[s.type] || {},
415
+ t.type && (r[t.type] = {
416
+ ...r[t.type] || {},
399
417
  [i]: e
400
418
  }), this.stage = {
401
419
  ...this.stage,
@@ -408,15 +426,15 @@ class W {
408
426
  openGroupStage() {
409
427
  this.knock.log("[Guide] Opening a new group stage");
410
428
  const {
411
- orderResolutionDuration: e = K
412
- } = this.options, t = setTimeout(() => {
429
+ orderResolutionDuration: e = F
430
+ } = this.options, s = setTimeout(() => {
413
431
  this.closePendingGroupStage(), this.incrementCounter();
414
432
  }, e);
415
433
  return this.stage = {
416
434
  status: "open",
417
435
  ordered: [],
418
436
  results: {},
419
- timeoutId: t
437
+ timeoutId: s
420
438
  }, this.stage;
421
439
  }
422
440
  // Close the current non-closed stage to resolve the prevailing guide up next
@@ -424,7 +442,7 @@ class W {
424
442
  closePendingGroupStage() {
425
443
  if (this.knock.log("[Guide] .closePendingGroupStage"), !this.stage || this.stage.status === "closed") return;
426
444
  this.ensureClearTimeout();
427
- const e = this.stage.ordered.find((t) => t !== void 0);
445
+ const e = this.stage.ordered.find((s) => s !== void 0);
428
446
  return this.knock.log(
429
447
  `[Guide] Closing the current group stage: resolved=${e}`
430
448
  ), this.stage = {
@@ -440,16 +458,16 @@ class W {
440
458
  // rendered until we are ready to resolve the updated stage and re-render.
441
459
  // Note, must be called ahead of updating the state store.
442
460
  patchClosedGroupStage() {
443
- var s;
444
- if (this.knock.log("[Guide] .patchClosedGroupStage"), ((s = this.stage) == null ? void 0 : s.status) !== "closed") return;
445
- const { orderResolutionDuration: e = 0 } = this.options, t = setTimeout(() => {
461
+ var t;
462
+ if (this.knock.log("[Guide] .patchClosedGroupStage"), ((t = this.stage) == null ? void 0 : t.status) !== "closed") return;
463
+ const { orderResolutionDuration: e = 0 } = this.options, s = setTimeout(() => {
446
464
  this.closePendingGroupStage(), this.incrementCounter();
447
465
  }, e);
448
466
  return this.ensureClearTimeout(), this.knock.log("[Guide] Patching the current group stage"), this.stage = {
449
467
  ...this.stage,
450
468
  status: "patch",
451
469
  ordered: [],
452
- timeoutId: t
470
+ timeoutId: s
453
471
  }, this.stage;
454
472
  }
455
473
  clearGroupStage() {
@@ -461,11 +479,11 @@ class W {
461
479
  }
462
480
  // Test helpers to open and close the group stage to return the select result
463
481
  // immediately.
464
- _selectGuide(e, t = {}, s = {}) {
465
- return this.openGroupStage(), this.selectGuide(e, t, s), this.closePendingGroupStage(), this.selectGuide(e, t, s);
482
+ _selectGuide(e, s = {}, t = {}) {
483
+ return this.openGroupStage(), this.selectGuide(e, s, t), this.closePendingGroupStage(), this.selectGuide(e, s, t);
466
484
  }
467
- _selectGuides(e, t = {}, s = {}) {
468
- return this.openGroupStage(), this.selectGuides(e, t, s), this.closePendingGroupStage(), this.selectGuides(e, t, s);
485
+ _selectGuides(e, s = {}, t = {}) {
486
+ return this.openGroupStage(), this.selectGuides(e, s, t), this.closePendingGroupStage(), this.selectGuides(e, s, t);
469
487
  }
470
488
  //
471
489
  // Engagement event handlers
@@ -473,156 +491,172 @@ class W {
473
491
  // Make an optimistic update on the client side first, then send an engagement
474
492
  // event to the backend.
475
493
  //
476
- async markAsSeen(e, t) {
477
- if (t.message.seen_at) return;
494
+ async markAsSeen(e, s) {
495
+ if (s.message.seen_at) return;
478
496
  this.knock.log(
479
- `[Guide] Marking as seen (Guide key: ${e.key}, Step ref:${t.ref})`
497
+ `[Guide] Marking as seen (Guide key: ${e.key}, Step ref:${s.ref})`
480
498
  );
481
- const s = this.setStepMessageAttrs(e.key, t.ref, {
499
+ const t = this.setStepMessageAttrs(e.key, s.ref, {
482
500
  seen_at: (/* @__PURE__ */ new Date()).toISOString()
483
501
  });
484
- if (!s) return;
502
+ if (!t) return;
503
+ if (this.shouldSkipEngagementApi())
504
+ return this.knock.log(
505
+ "[Guide] Skipping engagement API call for markAsSeen (debug mode)"
506
+ ), t;
485
507
  const i = {
486
- ...this.buildEngagementEventBaseParams(e, s),
487
- content: s.content,
508
+ ...this.buildEngagementEventBaseParams(e, t),
509
+ content: t.content,
488
510
  data: this.targetParams.data
489
511
  };
490
512
  return this.knock.user.markGuideStepAs(
491
513
  "seen",
492
514
  i
493
- ), s;
515
+ ), t;
494
516
  }
495
- async markAsInteracted(e, t, s) {
517
+ async markAsInteracted(e, s, t) {
496
518
  this.knock.log(
497
- `[Guide] Marking as interacted (Guide key: ${e.key}; Step ref:${t.ref})`
519
+ `[Guide] Marking as interacted (Guide key: ${e.key}; Step ref:${s.ref})`
498
520
  );
499
- const i = (/* @__PURE__ */ new Date()).toISOString(), n = this.setStepMessageAttrs(e.key, t.ref, {
521
+ const i = (/* @__PURE__ */ new Date()).toISOString(), n = this.setStepMessageAttrs(e.key, s.ref, {
500
522
  read_at: i,
501
523
  interacted_at: i
502
524
  });
503
525
  if (!n) return;
526
+ if (this.shouldSkipEngagementApi())
527
+ return this.knock.log(
528
+ "[Guide] Skipping engagement API call for markAsInteracted (debug mode)"
529
+ ), n;
504
530
  const r = {
505
531
  ...this.buildEngagementEventBaseParams(e, n),
506
- metadata: s
532
+ metadata: t
507
533
  };
508
534
  return this.knock.user.markGuideStepAs("interacted", r), n;
509
535
  }
510
- async markAsArchived(e, t) {
511
- if (t.message.archived_at) return;
536
+ async markAsArchived(e, s) {
537
+ if (s.message.archived_at) return;
512
538
  this.knock.log(
513
- `[Guide] Marking as archived (Guide key: ${e.key}, Step ref:${t.ref})`
539
+ `[Guide] Marking as archived (Guide key: ${e.key}, Step ref:${s.ref})`
514
540
  );
515
- const s = this.setStepMessageAttrs(e.key, t.ref, {
541
+ const t = this.setStepMessageAttrs(e.key, s.ref, {
516
542
  archived_at: (/* @__PURE__ */ new Date()).toISOString()
517
543
  });
518
- if (!s) return;
519
- const i = this.buildEngagementEventBaseParams(e, s);
544
+ if (!t) return;
545
+ if (this.shouldSkipEngagementApi())
546
+ return this.knock.log(
547
+ "[Guide] Skipping engagement API call for markAsArchived (debug mode)"
548
+ ), t;
549
+ const i = this.buildEngagementEventBaseParams(e, t);
520
550
  return this.knock.user.markGuideStepAs(
521
551
  "archived",
522
552
  {
523
553
  ...i,
524
554
  unthrottled: e.bypass_global_group_limit
525
555
  }
526
- ), s;
556
+ ), t;
557
+ }
558
+ shouldSkipEngagementApi() {
559
+ var e;
560
+ return !!((e = this.store.state.debug) != null && e.skipEngagementTracking);
527
561
  }
528
562
  //
529
563
  // Helpers
530
564
  //
531
565
  localCopy(e) {
532
- const t = this, s = {
566
+ const s = this, t = {
533
567
  ...e,
534
568
  // Get the next unarchived step.
535
569
  getStep() {
536
- var i;
537
- return ((i = t.store.state.debug) == null ? void 0 : i.forcedGuideKey) === this.key ? this.steps[0] : this.steps.find((n) => !n.message.archived_at);
570
+ var i, n, r;
571
+ return ((i = s.store.state.debug) == null ? void 0 : i.forcedGuideKey) === this.key || (r = (n = s.store.state.debug) == null ? void 0 : n.focusedGuideKeys) != null && r[this.key] ? this.steps[0] : this.steps.find((a) => !a.message.archived_at);
538
572
  }
539
573
  };
540
- return s.getStep = s.getStep.bind(s), s.steps = e.steps.map(({ message: i, ...n }) => {
574
+ return t.getStep = t.getStep.bind(t), t.steps = e.steps.map(({ message: i, ...n }) => {
541
575
  const r = {
542
576
  ...n,
543
577
  message: { ...i },
544
578
  markAsSeen() {
545
- return t.markAsSeen(s, this);
579
+ return s.markAsSeen(t, this);
546
580
  },
547
581
  markAsInteracted({ metadata: a } = {}) {
548
- return t.markAsInteracted(s, this, a);
582
+ return s.markAsInteracted(t, this, a);
549
583
  },
550
584
  markAsArchived() {
551
- return t.markAsArchived(s, this);
585
+ return s.markAsArchived(t, this);
552
586
  }
553
587
  };
554
588
  return r.markAsSeen = r.markAsSeen.bind(r), r.markAsInteracted = r.markAsInteracted.bind(r), r.markAsArchived = r.markAsArchived.bind(r), r;
555
- }), s.activation_url_patterns = e.activation_url_patterns.map((i) => ({
589
+ }), t.activation_url_patterns = e.activation_url_patterns.map((i) => ({
556
590
  ...i,
557
- pattern: new w({
591
+ pattern: new A({
558
592
  pathname: i.pathname ?? void 0,
559
593
  search: i.search ?? void 0
560
594
  })
561
- })), s;
595
+ })), t;
562
596
  }
563
597
  buildQueryParams(e = {}) {
564
- const t = {
598
+ const s = {
565
599
  ...this.targetParams,
566
600
  ...e
567
- }, s = this.store.state.debug;
568
- (s != null && s.forcedGuideKey || s != null && s.debugging) && (t.force_all_guides = !0);
601
+ }, t = this.store.state.debug;
602
+ (t != null && t.forcedGuideKey || t != null && t.debugging) && (s.force_all_guides = !0);
569
603
  let i = Object.fromEntries(
570
- Object.entries(t).filter(
604
+ Object.entries(s).filter(
571
605
  ([n, r]) => r != null
572
606
  )
573
607
  );
574
608
  return i = i.data ? { ...i, data: JSON.stringify(i.data) } : i, i;
575
609
  }
576
610
  formatQueryKey(e) {
577
- const s = Object.keys(e).sort().map(
611
+ const t = Object.keys(e).sort().map(
578
612
  (n) => `${encodeURIComponent(n)}=${encodeURIComponent(e[n])}`
579
- ).join("&"), i = F(this.knock.userId);
580
- return s ? `${i}?${s}` : i;
613
+ ).join("&"), i = N(this.knock.userId);
614
+ return t ? `${i}?${t}` : i;
581
615
  }
582
- setStepMessageAttrs(e, t, s) {
616
+ setStepMessageAttrs(e, s, t) {
583
617
  let i;
584
- return s.archived_at && this.clearGroupStage(), this.store.setState((n) => {
618
+ return t.archived_at && this.clearGroupStage(), this.store.setState((n) => {
585
619
  let r = n.guides[e];
586
620
  if (!r) return n;
587
- const a = r.steps.map((d) => (d.ref !== t || (d.message = { ...d.message, ...s }, i = d), d));
621
+ const a = r.steps.map((d) => (d.ref !== s || (d.message = { ...d.message, ...t }, i = d), d));
588
622
  r = i ? { ...r, steps: a } : r;
589
- const o = { ...n.guides, [r.key]: r }, c = s.archived_at && !r.bypass_global_group_limit ? {
623
+ const o = { ...n.guides, [r.key]: r }, c = t.archived_at && !r.bypass_global_group_limit ? {
590
624
  ...n.guideGroupDisplayLogs,
591
- [P]: s.archived_at
625
+ [D]: t.archived_at
592
626
  } : n.guideGroupDisplayLogs;
593
627
  return { ...n, guides: o, guideGroupDisplayLogs: c };
594
628
  }), i;
595
629
  }
596
- buildEngagementEventBaseParams(e, t) {
630
+ buildEngagementEventBaseParams(e, s) {
597
631
  return {
598
632
  channel_id: e.channel_id,
599
633
  guide_key: e.key,
600
634
  guide_id: e.id,
601
- guide_step_ref: t.ref,
635
+ guide_step_ref: s.ref,
602
636
  // Can be used for scoping guide messages.
603
637
  tenant: this.targetParams.tenant
604
638
  };
605
639
  }
606
640
  addOrReplaceGuide({ data: e }) {
607
641
  this.patchClosedGroupStage();
608
- const t = this.localCopy(e.guide);
609
- this.store.setState((s) => {
610
- const i = { ...s.guides, [t.key]: t };
611
- return { ...s, guides: i };
642
+ const s = this.localCopy(e.guide);
643
+ this.store.setState((t) => {
644
+ const i = { ...t.guides, [s.key]: s };
645
+ return { ...t, guides: i };
612
646
  });
613
647
  }
614
648
  removeGuide({ data: e }) {
615
- this.patchClosedGroupStage(), this.store.setState((t) => {
616
- const { [e.guide.key]: s, ...i } = t.guides;
617
- return { ...t, guides: i };
649
+ this.patchClosedGroupStage(), this.store.setState((s) => {
650
+ const { [e.guide.key]: t, ...i } = s.guides;
651
+ return { ...s, guides: i };
618
652
  });
619
653
  }
620
654
  addOrReplaceGuideGroup({
621
655
  data: e
622
656
  }) {
623
- this.patchClosedGroupStage(), this.store.setState((t) => {
624
- const s = [e.guide_group], i = e.guide_group.display_sequence_unthrottled || [], n = e.guide_group.display_sequence_throttled || [];
625
- let r = t.guides;
657
+ this.patchClosedGroupStage(), this.store.setState((s) => {
658
+ const t = [e.guide_group], i = e.guide_group.display_sequence_unthrottled || [], n = e.guide_group.display_sequence_throttled || [];
659
+ let r = s.guides;
626
660
  return r = i.reduce((a, o) => {
627
661
  if (!a[o]) return a;
628
662
  const c = { ...a[o], bypass_global_group_limit: !0 };
@@ -631,53 +665,53 @@ class W {
631
665
  if (!a[o]) return a;
632
666
  const c = { ...a[o], bypass_global_group_limit: !1 };
633
667
  return { ...a, [o]: c };
634
- }, r), { ...t, guides: r, guideGroups: s };
668
+ }, r), { ...s, guides: r, guideGroups: t };
635
669
  });
636
670
  }
637
671
  updatePreviewGuide({ data: e }) {
638
- const t = this.localCopy(e.guide);
639
- this.store.setState((s) => {
640
- const i = { ...s.previewGuides, [t.key]: t };
641
- return { ...s, previewGuides: i };
672
+ const s = this.localCopy(e.guide);
673
+ this.store.setState((t) => {
674
+ const i = { ...t.previewGuides, [s.key]: s };
675
+ return { ...t, previewGuides: i };
642
676
  });
643
677
  }
644
678
  // Returns whether debug params have changed. For guide key, we only check
645
679
  // presence since the exact value has no impact on fetch/subscribe
646
- checkDebugStateChanged(e, t) {
647
- return !!e.forcedGuideKey != !!t.forcedGuideKey || e.previewSessionId !== t.previewSessionId;
680
+ checkDebugStateChanged(e, s) {
681
+ return !!e.forcedGuideKey != !!s.forcedGuideKey || e.previewSessionId !== s.previewSessionId;
648
682
  }
649
683
  listenForLocationChangesFromWindow() {
650
- const e = k();
684
+ const e = p();
651
685
  if (e != null && e.history && (e != null && e.addEventListener)) {
652
686
  e.addEventListener("popstate", this.handleLocationChange), e.addEventListener("hashchange", this.handleLocationChange);
653
- const t = e.history.pushState, s = e.history.replaceState;
654
- e.history.pushState = new Proxy(t, {
687
+ const s = e.history.pushState, t = e.history.replaceState;
688
+ e.history.pushState = new Proxy(s, {
655
689
  apply: (i, n, r) => {
656
690
  Reflect.apply(i, n, r), setTimeout(() => {
657
691
  this.handleLocationChange();
658
692
  }, 0);
659
693
  }
660
- }), e.history.replaceState = new Proxy(s, {
694
+ }), e.history.replaceState = new Proxy(t, {
661
695
  apply: (i, n, r) => {
662
696
  Reflect.apply(i, n, r), setTimeout(() => {
663
697
  this.handleLocationChange();
664
698
  }, 0);
665
699
  }
666
- }), this.pushStateFn = t, this.replaceStateFn = s;
700
+ }), this.pushStateFn = s, this.replaceStateFn = t;
667
701
  } else
668
702
  this.knock.log(
669
703
  "[Guide] Unable to access the `window.history` object to detect location changes"
670
704
  );
671
705
  }
672
706
  removeLocationChangeEventListeners() {
673
- const e = k();
707
+ const e = p();
674
708
  !(e != null && e.history) || !(e != null && e.removeEventListener) || (e.removeEventListener("popstate", this.handleLocationChange), e.removeEventListener("hashchange", this.handleLocationChange), this.pushStateFn && (e.history.pushState = this.pushStateFn, this.pushStateFn = void 0), this.replaceStateFn && (e.history.replaceState = this.replaceStateFn, this.replaceStateFn = void 0));
675
709
  }
676
710
  }
677
711
  export {
678
- p as DEBUG_QUERY_PARAMS,
679
- W as KnockGuideClient,
680
- j as checkActivatable,
681
- F as guidesApiRootPath
712
+ f as DEBUG_QUERY_PARAMS,
713
+ V as KnockGuideClient,
714
+ M as checkActivatable,
715
+ N as guidesApiRootPath
682
716
  };
683
717
  //# sourceMappingURL=client.mjs.map