@knocklabs/client 0.16.5 → 0.17.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.
@@ -1,85 +1,113 @@
1
- var y = Object.defineProperty;
2
- var S = (u, e, t) => e in u ? y(u, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[e] = t;
3
- var c = (u, e, t) => S(u, typeof e != "symbol" ? e + "" : e, t);
4
- import { Store as v } from "@tanstack/store";
5
- import { URLPattern as G } from "urlpattern-polyfill";
6
- import { byKey as _, mockDefaultGroup as C, formatFilters as g, findDefaultGroup as m, DEFAULT_GROUP_KEY as p, checkIfThrottled as b, SelectionResult as I } from "./helpers.mjs";
7
- const A = 50, E = 30 * 1e3, L = 3, l = () => {
1
+ var v = Object.defineProperty;
2
+ var G = (a, e, t) => e in a ? v(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t;
3
+ var d = (a, e, t) => G(a, typeof e != "symbol" ? e + "" : e, t);
4
+ import { Store as _ } from "@tanstack/store";
5
+ import { URLPattern as b } from "urlpattern-polyfill";
6
+ import { byKey as C, mockDefaultGroup as I, formatFilters as g, findDefaultGroup as y, DEFAULT_GROUP_KEY as p, checkIfThrottled as w, SelectionResult as E, newUrl as A, predicateUrlRules as R, predicateUrlPatterns as L } from "./helpers.mjs";
7
+ const P = 50, D = 30 * 1e3, T = 3, k = {
8
+ GUIDE_KEY: "knock_guide_key",
9
+ PREVIEW_SESSION_ID: "knock_preview_session_id"
10
+ }, l = () => {
8
11
  if (typeof window < "u")
9
12
  return window;
10
- }, R = (u) => `/v1/users/${u}/guides`, k = (u, e = {}) => {
11
- const t = new I(), s = m(u.guideGroups);
13
+ }, K = (a) => `/v1/users/${a}/guides`, f = () => {
14
+ const a = l();
15
+ if (!a)
16
+ return { forcedGuideKey: null, previewSessionId: null };
17
+ const e = new URLSearchParams(a.location.search), t = e.get(k.GUIDE_KEY), s = e.get(k.PREVIEW_SESSION_ID);
18
+ return { forcedGuideKey: t, previewSessionId: s };
19
+ }, m = (a, e = {}) => {
20
+ const t = new E(), s = y(a.guideGroups);
12
21
  if (!s) return t;
13
- const n = s.display_sequence, i = u.location;
14
- for (const [r, o] of n.entries()) {
15
- const a = u.guides[o];
16
- !a || !T(a, { location: i, filters: e }) || t.set(r, a);
22
+ const i = [...s.display_sequence], n = a.location;
23
+ if (a.debug.forcedGuideKey) {
24
+ const r = i.indexOf(a.debug.forcedGuideKey);
25
+ r > -1 && i.splice(r, 1), i.unshift(a.debug.forcedGuideKey);
26
+ }
27
+ for (const [r, o] of i.entries()) {
28
+ let u = a.guides[o];
29
+ a.debug.forcedGuideKey === o && a.previewGuides[o] && (u = a.previewGuides[o]), !(!u || !O(u, {
30
+ location: n,
31
+ filters: e,
32
+ debug: a.debug
33
+ })) && t.set(r, u);
17
34
  }
18
35
  return t.metadata = { guideGroup: s }, t;
19
- }, T = (u, { location: e, filters: t = {} }) => {
20
- if (t.type && t.type !== u.type || t.key && t.key !== u.key || u.steps.every((n) => !!n.message.archived_at))
36
+ }, O = (a, { location: e, filters: t = {}, debug: s = {} }) => {
37
+ if (t.type && t.type !== a.type || t.key && t.key !== a.key)
21
38
  return !1;
22
- const s = u.activation_location_rules || [];
23
- return !(s.length > 0 && e && !s.reduce((i, r) => {
24
- if (i === !1) return !1;
25
- switch (r.directive) {
26
- case "allow":
27
- return i === !0 || r.pattern.test(e) ? !0 : void 0;
28
- case "block":
29
- return r.pattern.test(e) ? !1 : i;
30
- }
31
- }, void 0));
39
+ if (s.forcedGuideKey === a.key)
40
+ return !0;
41
+ if (a.steps.every((o) => !!o.message.archived_at))
42
+ return !1;
43
+ const i = e ? A(e) : void 0, n = a.activation_url_rules || [], r = a.activation_url_patterns || [];
44
+ if (i && n.length > 0) {
45
+ if (!R(i, n)) return !1;
46
+ } else if (i && r.length > 0 && !L(i, r))
47
+ return !1;
48
+ return !0;
32
49
  };
33
- class $ {
34
- constructor(e, t, s = {}, n = {}) {
35
- c(this, "store");
50
+ class j {
51
+ constructor(e, t, s = {}, i = {}) {
52
+ d(this, "store");
36
53
  // Phoenix channels for real time guide updates over websocket
37
- c(this, "socket");
38
- c(this, "socketChannel");
39
- c(this, "socketChannelTopic");
40
- c(this, "socketEventTypes", [
54
+ d(this, "socket");
55
+ d(this, "socketChannel");
56
+ d(this, "socketChannelTopic");
57
+ d(this, "socketEventTypes", [
41
58
  "guide.added",
42
59
  "guide.updated",
43
60
  "guide.removed",
44
61
  "guide_group.added",
45
- "guide_group.updated"
62
+ "guide_group.updated",
63
+ "guide.live_preview_updated"
46
64
  ]);
47
- c(this, "subscribeRetryCount", 0);
65
+ d(this, "subscribeRetryCount", 0);
48
66
  // Original history methods to monkey patch, or restore in cleanups.
49
- c(this, "pushStateFn");
50
- c(this, "replaceStateFn");
67
+ d(this, "pushStateFn");
68
+ d(this, "replaceStateFn");
51
69
  // Guides that are competing to render are "staged" first without rendering
52
70
  // and ranked based on its relative order in the group over a duration of time
53
71
  // to resolve and render the prevailing one.
54
- c(this, "stage");
55
- c(this, "counterIntervalId");
72
+ d(this, "stage");
73
+ d(this, "counterIntervalId");
56
74
  // Define as an arrow func property to always bind this to the class instance.
57
- c(this, "handleLocationChange", () => {
75
+ d(this, "handleLocationChange", () => {
58
76
  const e = l();
59
77
  if (!(e != null && e.location)) return;
60
78
  const t = e.location.href;
61
- this.store.state.location !== t && (this.knock.log(`[Guide] Handle Location change: ${t}`), this.setLocation(t));
79
+ if (this.store.state.location === t) return;
80
+ this.knock.log(`[Guide] Handle Location change: ${t}`);
81
+ const s = this.store.state.debug, i = f();
82
+ this.setLocation(t, { debug: i }), this.checkDebugStateChanged(
83
+ s,
84
+ i
85
+ ) && (this.knock.log(
86
+ "[Guide] Debug state changed, refetching guides and resubscribing to the websocket channel"
87
+ ), this.fetch(), this.subscribe());
62
88
  });
63
- this.knock = e, this.channelId = t, this.targetParams = s, this.options = n;
64
- const { trackLocationFromWindow: i = !0 } = n, r = l(), o = i ? r == null ? void 0 : r.location.href : void 0;
65
- this.store = new v({
89
+ this.knock = e, this.channelId = t, this.targetParams = s, this.options = i;
90
+ const { trackLocationFromWindow: n = !0 } = i, r = l(), o = n ? r == null ? void 0 : r.location.href : void 0, u = f();
91
+ this.store = new _({
66
92
  guideGroups: [],
67
93
  guideGroupDisplayLogs: {},
68
94
  guides: {},
95
+ previewGuides: {},
69
96
  queries: {},
70
97
  location: o,
71
98
  // Increment to update the state store and trigger re-selection.
72
- counter: 0
99
+ counter: 0,
100
+ debug: u
73
101
  });
74
- const { socket: a } = this.knock.client();
75
- this.socket = a, this.socketChannelTopic = `guides:${t}`, i && this.listenForLocationChangesFromWindow(), this.startCounterInterval(), this.knock.log("[Guide] Initialized a guide client");
102
+ const { socket: c } = this.knock.client();
103
+ this.socket = c, this.socketChannelTopic = `guides:${t}`, n && this.listenForLocationChangesFromWindow(), this.startCounterInterval(), this.knock.log("[Guide] Initialized a guide client");
76
104
  }
77
105
  incrementCounter() {
78
106
  this.knock.log("[Guide] Incrementing the counter"), this.store.setState((e) => ({ ...e, counter: e.counter + 1 }));
79
107
  }
80
108
  startCounterInterval() {
81
109
  const {
82
- throttleCheckInterval: e = E
110
+ throttleCheckInterval: e = D
83
111
  } = this.options;
84
112
  this.counterIntervalId = setInterval(() => {
85
113
  this.knock.log("[Guide] Counter interval tick"), !(this.stage && this.stage.status !== "closed") && this.incrementCounter();
@@ -93,51 +121,56 @@ class $ {
93
121
  }
94
122
  async fetch(e) {
95
123
  this.knock.failIfNotAuthenticated(), this.knock.log("[Guide] Loading all eligible guides");
96
- const t = this.buildQueryParams(e == null ? void 0 : e.filters), s = this.formatQueryKey(t), n = this.store.state.queries[s];
97
- if (n)
98
- return n;
124
+ const t = this.buildQueryParams(e == null ? void 0 : e.filters), s = this.formatQueryKey(t), i = this.store.state.queries[s];
125
+ if (i)
126
+ return i;
99
127
  this.store.setState((r) => ({
100
128
  ...r,
101
129
  queries: { ...r.queries, [s]: { status: "loading" } }
102
130
  }));
103
- let i;
131
+ let n;
104
132
  try {
105
133
  const r = await this.knock.user.getGuides(this.channelId, t);
106
- i = { status: "ok" };
107
- const { entries: o, guide_groups: a, guide_group_display_logs: h } = r;
108
- this.store.setState((d) => ({
109
- ...d,
110
- guideGroups: (a == null ? void 0 : a.length) > 0 ? a : [C(o)],
111
- guideGroupDisplayLogs: h || {},
112
- guides: _(o.map((f) => this.localCopy(f))),
113
- queries: { ...d.queries, [s]: i }
134
+ n = { status: "ok" };
135
+ const { entries: o, guide_groups: u, guide_group_display_logs: c } = r;
136
+ this.store.setState((h) => ({
137
+ ...h,
138
+ guideGroups: (u == null ? void 0 : u.length) > 0 ? u : [I(o)],
139
+ guideGroupDisplayLogs: c || {},
140
+ guides: C(o.map((S) => this.localCopy(S))),
141
+ queries: { ...h.queries, [s]: n }
114
142
  }));
115
143
  } catch (r) {
116
- i = { status: "error", error: r }, this.store.setState((o) => ({
144
+ n = { status: "error", error: r }, this.store.setState((o) => ({
117
145
  ...o,
118
- queries: { ...o.queries, [s]: i }
146
+ queries: { ...o.queries, [s]: n }
119
147
  }));
120
148
  }
121
- return i;
149
+ return n;
122
150
  }
123
151
  subscribe() {
124
152
  if (!this.socket) return;
125
153
  this.knock.failIfNotAuthenticated(), this.knock.log("[Guide] Subscribing to real time updates"), this.socket.isConnected() || this.socket.connect(), this.socketChannel && this.unsubscribe();
126
- const e = { ...this.targetParams, user_id: this.knock.userId }, t = this.socket.channel(this.socketChannelTopic, e);
127
- for (const s of this.socketEventTypes)
128
- t.on(s, (n) => this.handleSocketEvent(n));
129
- ["closed", "errored"].includes(t.state) && (this.subscribeRetryCount = 0, t.join().receive("ok", () => {
154
+ const e = this.store.state.debug, t = {
155
+ ...this.targetParams,
156
+ user_id: this.knock.userId,
157
+ force_all_guides: e.forcedGuideKey ? !0 : void 0,
158
+ preview_session_id: e.previewSessionId || void 0
159
+ }, s = this.socket.channel(this.socketChannelTopic, t);
160
+ for (const i of this.socketEventTypes)
161
+ s.on(i, (n) => this.handleSocketEvent(n));
162
+ ["closed", "errored"].includes(s.state) && (this.subscribeRetryCount = 0, s.join().receive("ok", () => {
130
163
  this.knock.log("[Guide] Successfully joined channel");
131
- }).receive("error", (s) => {
164
+ }).receive("error", (i) => {
132
165
  this.knock.log(
133
- `[Guide] Failed to join channel: ${JSON.stringify(s)}`
166
+ `[Guide] Failed to join channel: ${JSON.stringify(i)}`
134
167
  ), this.handleChannelJoinError();
135
168
  }).receive("timeout", () => {
136
169
  this.knock.log("[Guide] Channel join timed out"), this.handleChannelJoinError();
137
- })), this.socketChannel = t;
170
+ })), this.socketChannel = s;
138
171
  }
139
172
  handleChannelJoinError() {
140
- if (this.subscribeRetryCount >= L) {
173
+ if (this.subscribeRetryCount >= T) {
141
174
  this.knock.log(
142
175
  `[Guide] Channel join max retry limit reached: ${this.subscribeRetryCount}`
143
176
  ), this.unsubscribe();
@@ -165,12 +198,23 @@ class $ {
165
198
  case "guide_group.added":
166
199
  case "guide_group.updated":
167
200
  return this.addOrReplaceGuideGroup(e);
201
+ case "guide.live_preview_updated":
202
+ return this.updatePreviewGuide(e);
168
203
  default:
169
204
  return;
170
205
  }
171
206
  }
172
- setLocation(e) {
173
- this.clearGroupStage(), this.store.setState((t) => ({ ...t, location: e }));
207
+ setLocation(e, t = {}) {
208
+ this.clearGroupStage(), this.store.setState((s) => {
209
+ var n;
210
+ const i = (n = t == null ? void 0 : t.debug) != null && n.previewSessionId ? s.previewGuides : {};
211
+ return {
212
+ ...s,
213
+ ...t,
214
+ previewGuides: i,
215
+ location: e
216
+ };
217
+ });
174
218
  }
175
219
  //
176
220
  // Store selector
@@ -179,41 +223,41 @@ class $ {
179
223
  if (Object.keys(e.guides).length === 0)
180
224
  return [];
181
225
  this.knock.log(`[Guide] Selecting guides for: ${g(t)}`);
182
- const s = k(e, t);
226
+ const s = m(e, t);
183
227
  return s.size === 0 ? (this.knock.log("[Guide] Selection returned zero result"), []) : [...s.values()];
184
228
  }
185
229
  selectGuide(e, t = {}) {
186
230
  if (Object.keys(e.guides).length === 0)
187
231
  return;
188
232
  this.knock.log(`[Guide] Selecting a guide for: ${g(t)}`);
189
- const s = k(e, t);
233
+ const s = m(e, t);
190
234
  if (s.size === 0) {
191
235
  this.knock.log("[Guide] Selection returned zero result");
192
236
  return;
193
237
  }
194
- const [n, i] = [...s][0];
195
- if (i.bypass_global_group_limit)
196
- return i;
197
- const r = m(e.guideGroups), o = e.guideGroupDisplayLogs[p];
198
- if (!(r && r.display_interval && o && b(
238
+ const [i, n] = [...s][0];
239
+ if (n.bypass_global_group_limit)
240
+ return n;
241
+ const r = y(e.guideGroups), o = e.guideGroupDisplayLogs[p];
242
+ if (!(r && r.display_interval && o && w(
199
243
  o,
200
244
  r.display_interval
201
245
  )))
202
246
  switch (this.stage || (this.stage = this.openGroupStage()), this.stage.status) {
203
247
  case "open": {
204
- this.knock.log(`[Guide] Addng to the group stage: ${i.key}`), this.stage.ordered[n] = i.key;
248
+ this.knock.log(`[Guide] Addng to the group stage: ${n.key}`), this.stage.ordered[i] = n.key;
205
249
  return;
206
250
  }
207
251
  case "patch":
208
- return this.knock.log(`[Guide] Patching the group stage: ${i.key}`), this.stage.ordered[n] = i.key, this.stage.resolved === i.key ? i : void 0;
252
+ return this.knock.log(`[Guide] Patching the group stage: ${n.key}`), this.stage.ordered[i] = n.key, this.stage.resolved === n.key ? n : void 0;
209
253
  case "closed":
210
- return this.stage.resolved === i.key ? i : void 0;
254
+ return this.stage.resolved === n.key ? n : void 0;
211
255
  }
212
256
  }
213
257
  openGroupStage() {
214
258
  this.knock.log("[Guide] Opening a new group stage");
215
259
  const {
216
- orderResolutionDuration: e = A
260
+ orderResolutionDuration: e = P
217
261
  } = this.options, t = setTimeout(() => {
218
262
  this.closePendingGroupStage(), this.incrementCounter();
219
263
  }, e);
@@ -226,13 +270,17 @@ class $ {
226
270
  // Close the current non-closed stage to resolve the prevailing guide up next
227
271
  // for display amongst the ones that have been staged.
228
272
  closePendingGroupStage() {
229
- if (!(!this.stage || this.stage.status === "closed"))
230
- return this.knock.log("[Guide] Closing the current group stage"), this.ensureClearTimeout(), this.stage = {
231
- ...this.stage,
232
- status: "closed",
233
- resolved: this.stage.ordered.find((e) => e !== void 0),
234
- timeoutId: null
235
- }, this.stage;
273
+ if (!this.stage || this.stage.status === "closed") return;
274
+ this.knock.log("[Guide] Closing the current group stage"), this.ensureClearTimeout();
275
+ let e;
276
+ return this.store.state.debug.forcedGuideKey && (e = this.stage.ordered.find(
277
+ (t) => t === this.store.state.debug.forcedGuideKey
278
+ )), e || (e = this.stage.ordered.find((t) => t !== void 0)), this.stage = {
279
+ ...this.stage,
280
+ status: "closed",
281
+ resolved: e,
282
+ timeoutId: null
283
+ }, this.stage;
236
284
  }
237
285
  // Set the current closed stage status to "patch" to allow re-running
238
286
  // selections and re-building a group stage with the latest/updated state,
@@ -280,7 +328,7 @@ class $ {
280
328
  seen_at: (/* @__PURE__ */ new Date()).toISOString()
281
329
  });
282
330
  if (!s) return;
283
- const n = {
331
+ const i = {
284
332
  ...this.buildEngagementEventBaseParams(e, s),
285
333
  content: s.content,
286
334
  data: this.targetParams.data,
@@ -288,23 +336,23 @@ class $ {
288
336
  };
289
337
  return this.knock.user.markGuideStepAs(
290
338
  "seen",
291
- n
339
+ i
292
340
  ), s;
293
341
  }
294
342
  async markAsInteracted(e, t, s) {
295
343
  this.knock.log(
296
344
  `[Guide] Marking as interacted (Guide key: ${e.key}, Step ref:${t.ref})`
297
345
  );
298
- const n = (/* @__PURE__ */ new Date()).toISOString(), i = this.setStepMessageAttrs(e.key, t.ref, {
299
- read_at: n,
300
- interacted_at: n
346
+ const i = (/* @__PURE__ */ new Date()).toISOString(), n = this.setStepMessageAttrs(e.key, t.ref, {
347
+ read_at: i,
348
+ interacted_at: i
301
349
  });
302
- if (!i) return;
350
+ if (!n) return;
303
351
  const r = {
304
- ...this.buildEngagementEventBaseParams(e, i),
352
+ ...this.buildEngagementEventBaseParams(e, n),
305
353
  metadata: s
306
354
  };
307
- return this.knock.user.markGuideStepAs("interacted", r), i;
355
+ return this.knock.user.markGuideStepAs("interacted", r), n;
308
356
  }
309
357
  async markAsArchived(e, t) {
310
358
  if (t.message.archived_at) return;
@@ -315,11 +363,11 @@ class $ {
315
363
  archived_at: (/* @__PURE__ */ new Date()).toISOString()
316
364
  });
317
365
  if (!s) return;
318
- const n = this.buildEngagementEventBaseParams(e, s);
366
+ const i = this.buildEngagementEventBaseParams(e, s);
319
367
  return this.knock.user.markGuideStepAs(
320
368
  "archived",
321
369
  {
322
- ...n,
370
+ ...i,
323
371
  unthrottled: e.bypass_global_group_limit
324
372
  }
325
373
  ), s;
@@ -332,13 +380,13 @@ class $ {
332
380
  ...e,
333
381
  // Get the next unarchived step.
334
382
  getStep() {
335
- return this.steps.find((n) => !n.message.archived_at);
383
+ return t.store.state.debug.forcedGuideKey === this.key ? this.steps[0] : this.steps.find((i) => !i.message.archived_at);
336
384
  }
337
385
  };
338
- return s.getStep = s.getStep.bind(s), s.steps = e.steps.map(({ message: n, ...i }) => {
386
+ return s.getStep = s.getStep.bind(s), s.steps = e.steps.map(({ message: i, ...n }) => {
339
387
  const r = {
340
- ...i,
341
- message: { ...n },
388
+ ...n,
389
+ message: { ...i },
342
390
  markAsSeen() {
343
391
  if (!this.message.seen_at)
344
392
  return t.markAsSeen(s, this);
@@ -352,39 +400,43 @@ class $ {
352
400
  }
353
401
  };
354
402
  return r.markAsSeen = r.markAsSeen.bind(r), r.markAsInteracted = r.markAsInteracted.bind(r), r.markAsArchived = r.markAsArchived.bind(r), r;
355
- }), s.activation_location_rules = e.activation_location_rules.map((n) => ({
356
- ...n,
357
- pattern: new G({ pathname: n.pathname })
403
+ }), s.activation_url_patterns = e.activation_url_patterns.map((i) => ({
404
+ ...i,
405
+ pattern: new b({ pathname: i.pathname })
358
406
  })), s;
359
407
  }
360
408
  buildQueryParams(e = {}) {
361
- const t = { ...this.targetParams, ...e };
362
- let s = Object.fromEntries(
409
+ const t = {
410
+ ...this.targetParams,
411
+ ...e
412
+ };
413
+ this.store.state.debug.forcedGuideKey && (t.force_all_guides = !0);
414
+ let i = Object.fromEntries(
363
415
  Object.entries(t).filter(
364
- ([n, i]) => i != null
416
+ ([n, r]) => r != null
365
417
  )
366
418
  );
367
- return s = s.data ? { ...s, data: JSON.stringify(s.data) } : s, s;
419
+ return i = i.data ? { ...i, data: JSON.stringify(i.data) } : i, i;
368
420
  }
369
421
  formatQueryKey(e) {
370
422
  const s = Object.keys(e).sort().map(
371
- (i) => `${encodeURIComponent(i)}=${encodeURIComponent(e[i])}`
372
- ).join("&"), n = R(this.knock.userId);
373
- return s ? `${n}?${s}` : n;
423
+ (n) => `${encodeURIComponent(n)}=${encodeURIComponent(e[n])}`
424
+ ).join("&"), i = K(this.knock.userId);
425
+ return s ? `${i}?${s}` : i;
374
426
  }
375
427
  setStepMessageAttrs(e, t, s) {
376
- let n;
377
- return s.archived_at && this.clearGroupStage(), this.store.setState((i) => {
378
- const r = i.guides[e];
379
- if (!r) return i;
380
- const o = r.steps.map((d) => (d.ref !== t || (d.message = { ...d.message, ...s }, n = d), d));
428
+ let i;
429
+ return s.archived_at && this.clearGroupStage(), this.store.setState((n) => {
430
+ const r = n.guides[e];
431
+ if (!r) return n;
432
+ const o = r.steps.map((h) => (h.ref !== t || (h.message = { ...h.message, ...s }, i = h), h));
381
433
  r.steps = o;
382
- const a = { ...i.guides, [r.key]: r }, h = s.archived_at && !r.bypass_global_group_limit ? {
383
- ...i.guideGroupDisplayLogs,
434
+ const u = { ...n.guides, [r.key]: r }, c = s.archived_at && !r.bypass_global_group_limit ? {
435
+ ...n.guideGroupDisplayLogs,
384
436
  [p]: s.archived_at
385
- } : i.guideGroupDisplayLogs;
386
- return { ...i, guides: a, guideGroupDisplayLogs: h };
387
- }), n;
437
+ } : n.guideGroupDisplayLogs;
438
+ return { ...n, guides: u, guideGroupDisplayLogs: c };
439
+ }), i;
388
440
  }
389
441
  buildEngagementEventBaseParams(e, t) {
390
442
  return {
@@ -399,47 +451,59 @@ class $ {
399
451
  this.patchClosedGroupStage();
400
452
  const t = this.localCopy(e.guide);
401
453
  this.store.setState((s) => {
402
- const n = { ...s.guides, [t.key]: t };
403
- return { ...s, guides: n };
454
+ const i = { ...s.guides, [t.key]: t };
455
+ return { ...s, guides: i };
404
456
  });
405
457
  }
406
458
  removeGuide({ data: e }) {
407
459
  this.patchClosedGroupStage(), this.store.setState((t) => {
408
- const { [e.guide.key]: s, ...n } = t.guides;
409
- return { ...t, guides: n };
460
+ const { [e.guide.key]: s, ...i } = t.guides;
461
+ return { ...t, guides: i };
410
462
  });
411
463
  }
412
464
  addOrReplaceGuideGroup({
413
465
  data: e
414
466
  }) {
415
467
  this.patchClosedGroupStage(), this.store.setState((t) => {
416
- const s = [e.guide_group], n = e.guide_group.display_sequence_unthrottled || [], i = e.guide_group.display_sequence_throttled || [];
468
+ const s = [e.guide_group], i = e.guide_group.display_sequence_unthrottled || [], n = e.guide_group.display_sequence_throttled || [];
417
469
  let r = t.guides;
418
- return r = n.reduce((o, a) => {
419
- if (!o[a]) return o;
420
- const h = { ...o[a], bypass_global_group_limit: !0 };
421
- return { ...o, [a]: h };
422
- }, r), r = i.reduce((o, a) => {
423
- if (!o[a]) return o;
424
- const h = { ...o[a], bypass_global_group_limit: !1 };
425
- return { ...o, [a]: h };
470
+ return r = i.reduce((o, u) => {
471
+ if (!o[u]) return o;
472
+ const c = { ...o[u], bypass_global_group_limit: !0 };
473
+ return { ...o, [u]: c };
474
+ }, r), r = n.reduce((o, u) => {
475
+ if (!o[u]) return o;
476
+ const c = { ...o[u], bypass_global_group_limit: !1 };
477
+ return { ...o, [u]: c };
426
478
  }, r), { ...t, guides: r, guideGroups: s };
427
479
  });
428
480
  }
481
+ updatePreviewGuide({ data: e }) {
482
+ const t = this.localCopy(e.guide);
483
+ this.store.setState((s) => {
484
+ const i = { ...s.previewGuides, [t.key]: t };
485
+ return { ...s, previewGuides: i };
486
+ });
487
+ }
488
+ // Returns whether debug params have changed. For guide key, we only check
489
+ // presence since the exact value has no impact on fetch/subscribe
490
+ checkDebugStateChanged(e, t) {
491
+ return !!e.forcedGuideKey != !!t.forcedGuideKey || e.previewSessionId !== t.previewSessionId;
492
+ }
429
493
  listenForLocationChangesFromWindow() {
430
494
  const e = l();
431
495
  if (e != null && e.history) {
432
496
  e.addEventListener("popstate", this.handleLocationChange), e.addEventListener("hashchange", this.handleLocationChange);
433
497
  const t = e.history.pushState, s = e.history.replaceState;
434
498
  e.history.pushState = new Proxy(t, {
435
- apply: (n, i, r) => {
436
- Reflect.apply(n, i, r), setTimeout(() => {
499
+ apply: (i, n, r) => {
500
+ Reflect.apply(i, n, r), setTimeout(() => {
437
501
  this.handleLocationChange();
438
502
  }, 0);
439
503
  }
440
504
  }), e.history.replaceState = new Proxy(s, {
441
- apply: (n, i, r) => {
442
- Reflect.apply(n, i, r), setTimeout(() => {
505
+ apply: (i, n, r) => {
506
+ Reflect.apply(i, n, r), setTimeout(() => {
443
507
  this.handleLocationChange();
444
508
  }, 0);
445
509
  }
@@ -455,7 +519,8 @@ class $ {
455
519
  }
456
520
  }
457
521
  export {
458
- $ as KnockGuideClient,
459
- R as guidesApiRootPath
522
+ k as DEBUG_QUERY_PARAMS,
523
+ j as KnockGuideClient,
524
+ K as guidesApiRootPath
460
525
  };
461
526
  //# sourceMappingURL=client.mjs.map