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