@knocklabs/client 0.16.5 → 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 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/clients/guide/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/clients/guide/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knocklabs/client",
3
- "version": "0.16.5",
3
+ "version": "0.17.0",
4
4
  "description": "The clientside library for interacting with Knock",
5
5
  "homepage": "https://github.com/knocklabs/javascript/tree/main/packages/client",
6
6
  "author": "@knocklabs",
@@ -62,7 +62,7 @@
62
62
  "jsonwebtoken": "^9.0.2",
63
63
  "prettier": "^3.5.3",
64
64
  "rimraf": "^6.0.1",
65
- "rollup": "^4.41.1",
65
+ "rollup": "^4.46.2",
66
66
  "typescript": "^5.8.3",
67
67
  "vite": "^5.4.19",
68
68
  "vitest": "^3.1.1"
@@ -13,9 +13,14 @@ import {
13
13
  findDefaultGroup,
14
14
  formatFilters,
15
15
  mockDefaultGroup,
16
+ newUrl,
17
+ predicateUrlPatterns,
18
+ predicateUrlRules,
16
19
  } from "./helpers";
17
20
  import {
21
+ Any,
18
22
  ConstructorOpts,
23
+ DebugState,
19
24
  GetGuidesQueryParams,
20
25
  GetGuidesResponse,
21
26
  GroupStage,
@@ -23,6 +28,7 @@ import {
23
28
  GuideData,
24
29
  GuideGroupAddedEvent,
25
30
  GuideGroupUpdatedEvent,
31
+ GuideLivePreviewUpdatedEvent,
26
32
  GuideRemovedEvent,
27
33
  GuideSocketEvent,
28
34
  GuideStepData,
@@ -52,6 +58,12 @@ const DEFAULT_COUNTER_INCREMENT_INTERVAL = 30 * 1000; // in milliseconds
52
58
  // Maximum number of retry attempts for channel subscription
53
59
  const SUBSCRIBE_RETRY_LIMIT = 3;
54
60
 
61
+ // Debug query param keys
62
+ export const DEBUG_QUERY_PARAMS = {
63
+ GUIDE_KEY: "knock_guide_key",
64
+ PREVIEW_SESSION_ID: "knock_preview_session_id",
65
+ };
66
+
55
67
  // Return the global window object if defined, so to safely guard against SSR.
56
68
  const checkForWindow = () => {
57
69
  if (typeof window !== "undefined") {
@@ -62,6 +74,20 @@ const checkForWindow = () => {
62
74
  export const guidesApiRootPath = (userId: string | undefined | null) =>
63
75
  `/v1/users/${userId}/guides`;
64
76
 
77
+ // Detect debug params like "knock_guide_key" from URL.
78
+ const detectDebugParams = (): DebugState => {
79
+ const win = checkForWindow();
80
+ if (!win) {
81
+ return { forcedGuideKey: null, previewSessionId: null };
82
+ }
83
+
84
+ const urlParams = new URLSearchParams(win.location.search);
85
+ const forcedGuideKey = urlParams.get(DEBUG_QUERY_PARAMS.GUIDE_KEY);
86
+ const previewSessionId = urlParams.get(DEBUG_QUERY_PARAMS.PREVIEW_SESSION_ID);
87
+
88
+ return { forcedGuideKey, previewSessionId };
89
+ };
90
+
65
91
  const select = (state: StoreState, filters: SelectFilterParams = {}) => {
66
92
  // A map of selected guides as values, with its order index as keys.
67
93
  const result = new SelectionResult();
@@ -69,16 +95,37 @@ const select = (state: StoreState, filters: SelectFilterParams = {}) => {
69
95
  const defaultGroup = findDefaultGroup(state.guideGroups);
70
96
  if (!defaultGroup) return result;
71
97
 
72
- const displaySequence = defaultGroup.display_sequence;
98
+ const displaySequence = [...defaultGroup.display_sequence];
73
99
  const location = state.location;
74
100
 
101
+ // If in debug mode, put the forced guide at the beginning of the display sequence.
102
+ if (state.debug.forcedGuideKey) {
103
+ const forcedKeyIndex = displaySequence.indexOf(state.debug.forcedGuideKey);
104
+ if (forcedKeyIndex > -1) {
105
+ displaySequence.splice(forcedKeyIndex, 1);
106
+ }
107
+ displaySequence.unshift(state.debug.forcedGuideKey);
108
+ }
109
+
75
110
  for (const [index, guideKey] of displaySequence.entries()) {
76
- const guide = state.guides[guideKey];
111
+ let guide = state.guides[guideKey];
77
112
  if (!guide) continue;
78
113
 
79
- const affirmed = predicate(guide, { location, filters });
114
+ const affirmed = predicate(guide, {
115
+ location,
116
+ filters,
117
+ debug: state.debug,
118
+ });
80
119
  if (!affirmed) continue;
81
120
 
121
+ // Use preview guide if it exists and matches the forced guide key
122
+ if (
123
+ state.debug.forcedGuideKey === guideKey &&
124
+ state.previewGuides[guideKey]
125
+ ) {
126
+ guide = state.previewGuides[guideKey];
127
+ }
128
+
82
129
  result.set(index, guide);
83
130
  }
84
131
 
@@ -89,12 +136,18 @@ const select = (state: StoreState, filters: SelectFilterParams = {}) => {
89
136
  type PredicateOpts = {
90
137
  location?: string | undefined;
91
138
  filters?: SelectFilterParams | undefined;
139
+ debug: DebugState;
92
140
  };
93
141
 
94
142
  const predicate = (
95
143
  guide: KnockGuide,
96
- { location, filters = {} }: PredicateOpts,
144
+ { location, filters = {}, debug = {} }: PredicateOpts,
97
145
  ) => {
146
+ // Bypass filtering if debugging the current guide.
147
+ if (debug.forcedGuideKey === guide.key) {
148
+ return true;
149
+ }
150
+
98
151
  if (filters.type && filters.type !== guide.type) {
99
152
  return false;
100
153
  }
@@ -107,36 +160,17 @@ const predicate = (
107
160
  return false;
108
161
  }
109
162
 
110
- const locationRules = guide.activation_location_rules || [];
111
-
112
- if (locationRules.length > 0 && location) {
113
- const allowed = locationRules.reduce<boolean | undefined>((acc, rule) => {
114
- // Any matched block rule prevails so no need to evaluate further
115
- // as soon as there is one.
116
- if (acc === false) return false;
117
-
118
- // At this point we either have a matched allow rule (acc is true),
119
- // or no matched rule found yet (acc is undefined).
163
+ const url = location ? newUrl(location) : undefined;
120
164
 
121
- switch (rule.directive) {
122
- case "allow": {
123
- // No need to evaluate more allow rules once we matched one
124
- // since any matched allowed rule means allow.
125
- if (acc === true) return true;
126
-
127
- const matched = rule.pattern.test(location);
128
- return matched ? true : undefined;
129
- }
130
-
131
- case "block": {
132
- // Always test block rules (unless already matched to block)
133
- // because they'd prevail over matched allow rules.
134
- const matched = rule.pattern.test(location);
135
- return matched ? false : acc;
136
- }
137
- }
138
- }, undefined);
165
+ const urlRules = guide.activation_url_rules || [];
166
+ const urlPatterns = guide.activation_url_patterns || [];
139
167
 
168
+ // A guide can have either activation url rules XOR url patterns, but not both.
169
+ if (url && urlRules.length > 0) {
170
+ const allowed = predicateUrlRules(url, urlRules);
171
+ if (!allowed) return false;
172
+ } else if (url && urlPatterns.length > 0) {
173
+ const allowed = predicateUrlPatterns(url, urlPatterns);
140
174
  if (!allowed) return false;
141
175
  }
142
176
 
@@ -156,6 +190,7 @@ export class KnockGuideClient {
156
190
  "guide.removed",
157
191
  "guide_group.added",
158
192
  "guide_group.updated",
193
+ "guide.live_preview_updated",
159
194
  ];
160
195
  private subscribeRetryCount = 0;
161
196
 
@@ -181,14 +216,18 @@ export class KnockGuideClient {
181
216
 
182
217
  const location = trackLocationFromWindow ? win?.location.href : undefined;
183
218
 
219
+ const debug = detectDebugParams();
220
+
184
221
  this.store = new Store<StoreState>({
185
222
  guideGroups: [],
186
223
  guideGroupDisplayLogs: {},
187
224
  guides: {},
225
+ previewGuides: {},
188
226
  queries: {},
189
227
  location,
190
228
  // Increment to update the state store and trigger re-selection.
191
229
  counter: 0,
230
+ debug,
192
231
  });
193
232
 
194
233
  // In server environments we might not have a socket connection.
@@ -302,7 +341,14 @@ export class KnockGuideClient {
302
341
  }
303
342
 
304
343
  // Join the channel topic and subscribe to supported events.
305
- const params = { ...this.targetParams, user_id: this.knock.userId };
344
+ const debugState = this.store.state.debug;
345
+ const params = {
346
+ ...this.targetParams,
347
+ user_id: this.knock.userId,
348
+ force_all_guides: debugState.forcedGuideKey ? true : undefined,
349
+ preview_session_id: debugState.previewSessionId || undefined,
350
+ };
351
+
306
352
  const newChannel = this.socket.channel(this.socketChannelTopic, params);
307
353
 
308
354
  for (const eventType of this.socketEventTypes) {
@@ -381,23 +427,41 @@ export class KnockGuideClient {
381
427
  case "guide_group.updated":
382
428
  return this.addOrReplaceGuideGroup(payload);
383
429
 
430
+ case "guide.live_preview_updated":
431
+ return this.updatePreviewGuide(payload);
432
+
384
433
  default:
385
434
  return;
386
435
  }
387
436
  }
388
437
 
389
- setLocation(href: string) {
438
+ setLocation(href: string, additionalParams: Partial<StoreState> = {}) {
390
439
  // Make sure to clear out the stage.
391
440
  this.clearGroupStage();
392
441
 
393
- this.store.setState((state) => ({ ...state, location: href }));
442
+ this.store.setState((state) => {
443
+ // Clear preview guides if no longer in preview mode
444
+ const previewGuides = additionalParams?.debug?.previewSessionId
445
+ ? state.previewGuides
446
+ : {};
447
+
448
+ return {
449
+ ...state,
450
+ ...additionalParams,
451
+ previewGuides,
452
+ location: href,
453
+ };
454
+ });
394
455
  }
395
456
 
396
457
  //
397
458
  // Store selector
398
459
  //
399
460
 
400
- selectGuides(state: StoreState, filters: SelectFilterParams = {}) {
461
+ selectGuides<C = Any>(
462
+ state: StoreState,
463
+ filters: SelectFilterParams = {},
464
+ ): KnockGuide<C>[] {
401
465
  if (Object.keys(state.guides).length === 0) {
402
466
  return [];
403
467
  }
@@ -416,7 +480,10 @@ export class KnockGuideClient {
416
480
  return [...result.values()];
417
481
  }
418
482
 
419
- selectGuide(state: StoreState, filters: SelectFilterParams = {}) {
483
+ selectGuide<C = Any>(
484
+ state: StoreState,
485
+ filters: SelectFilterParams = {},
486
+ ): KnockGuide<C> | undefined {
420
487
  if (Object.keys(state.guides).length === 0) {
421
488
  return undefined;
422
489
  }
@@ -539,10 +606,22 @@ export class KnockGuideClient {
539
606
  // callback to a setTimeout, but just to be safe.
540
607
  this.ensureClearTimeout();
541
608
 
609
+ // If in debug mode, try to resolve the forced guide, otherwise return the first non-undefined guide.
610
+ let resolved = undefined;
611
+ if (this.store.state.debug.forcedGuideKey) {
612
+ resolved = this.stage.ordered.find(
613
+ (x) => x === this.store.state.debug.forcedGuideKey,
614
+ );
615
+ }
616
+
617
+ if (!resolved) {
618
+ resolved = this.stage.ordered.find((x) => x !== undefined);
619
+ }
620
+
542
621
  this.stage = {
543
622
  ...this.stage,
544
623
  status: "closed",
545
- resolved: this.stage.ordered.find((x) => x !== undefined),
624
+ resolved,
546
625
  timeoutId: null,
547
626
  };
548
627
 
@@ -706,6 +785,11 @@ export class KnockGuideClient {
706
785
  ...remoteGuide,
707
786
  // Get the next unarchived step.
708
787
  getStep() {
788
+ // If debugging this guide, return the first step regardless of archive status
789
+ if (self.store.state.debug.forcedGuideKey === this.key) {
790
+ return this.steps[0];
791
+ }
792
+
709
793
  return this.steps.find((s) => !s.message.archived_at);
710
794
  },
711
795
  } as KnockGuide;
@@ -741,8 +825,8 @@ export class KnockGuideClient {
741
825
  return localStep;
742
826
  });
743
827
 
744
- localGuide.activation_location_rules =
745
- remoteGuide.activation_location_rules.map((rule) => {
828
+ localGuide.activation_url_patterns =
829
+ remoteGuide.activation_url_patterns.map((rule) => {
746
830
  return {
747
831
  ...rule,
748
832
  pattern: new URLPattern({ pathname: rule.pathname }),
@@ -754,7 +838,16 @@ export class KnockGuideClient {
754
838
 
755
839
  private buildQueryParams(filterParams: QueryFilterParams = {}) {
756
840
  // Combine the target params with the given filter params.
757
- const combinedParams = { ...this.targetParams, ...filterParams };
841
+ const combinedParams: GenericData = {
842
+ ...this.targetParams,
843
+ ...filterParams,
844
+ };
845
+
846
+ // Append debug params
847
+ const debugState = this.store.state.debug;
848
+ if (debugState.forcedGuideKey) {
849
+ combinedParams.force_all_guides = true;
850
+ }
758
851
 
759
852
  // Prune out any keys that have an undefined or null value.
760
853
  let params = Object.fromEntries(
@@ -899,6 +992,15 @@ export class KnockGuideClient {
899
992
  });
900
993
  }
901
994
 
995
+ private updatePreviewGuide({ data }: GuideLivePreviewUpdatedEvent) {
996
+ const guide = this.localCopy(data.guide);
997
+
998
+ this.store.setState((state) => {
999
+ const previewGuides = { ...state.previewGuides, [guide.key]: guide };
1000
+ return { ...state, previewGuides };
1001
+ });
1002
+ }
1003
+
902
1004
  // Define as an arrow func property to always bind this to the class instance.
903
1005
  private handleLocationChange = () => {
904
1006
  const win = checkForWindow();
@@ -908,9 +1010,36 @@ export class KnockGuideClient {
908
1010
  if (this.store.state.location === href) return;
909
1011
 
910
1012
  this.knock.log(`[Guide] Handle Location change: ${href}`);
911
- this.setLocation(href);
1013
+
1014
+ // If entering debug mode, fetch all guides.
1015
+ const currentDebugParams = this.store.state.debug;
1016
+ const newDebugParams = detectDebugParams();
1017
+ this.setLocation(href, { debug: newDebugParams });
1018
+
1019
+ // If debug state has changed, refetch guides and resubscribe to the websocket channel
1020
+ const debugStateChanged = this.checkDebugStateChanged(
1021
+ currentDebugParams,
1022
+ newDebugParams,
1023
+ );
1024
+
1025
+ if (debugStateChanged) {
1026
+ this.knock.log(
1027
+ `[Guide] Debug state changed, refetching guides and resubscribing to the websocket channel`,
1028
+ );
1029
+ this.fetch();
1030
+ this.subscribe();
1031
+ }
912
1032
  };
913
1033
 
1034
+ // Returns whether debug params have changed. For guide key, we only check
1035
+ // presence since the exact value has no impact on fetch/subscribe
1036
+ private checkDebugStateChanged(a: DebugState, b: DebugState): boolean {
1037
+ return (
1038
+ Boolean(a.forcedGuideKey) !== Boolean(b.forcedGuideKey) ||
1039
+ a.previewSessionId !== b.previewSessionId
1040
+ );
1041
+ }
1042
+
914
1043
  private listenForLocationChangesFromWindow() {
915
1044
  const win = checkForWindow();
916
1045
  if (win?.history) {
@@ -1,7 +1,9 @@
1
1
  import {
2
+ GuideActivationUrlRuleData,
2
3
  GuideData,
3
4
  GuideGroupData,
4
5
  KnockGuide,
6
+ KnockGuideActivationUrlPattern,
5
7
  SelectFilterParams,
6
8
  } from "./types";
7
9
 
@@ -96,3 +98,100 @@ export const checkIfThrottled = (
96
98
  // accurate regardless of local timezones.
97
99
  return currentTimeInMilliseconds <= throttleWindowEndInMilliseconds;
98
100
  };
101
+
102
+ // Safely parse and build a new URL object.
103
+ export const newUrl = (location: string) => {
104
+ try {
105
+ return new URL(location);
106
+ } catch {
107
+ return undefined;
108
+ }
109
+ };
110
+
111
+ // Evaluates whether the given location url satisfies the url rule.
112
+ export const evaluateUrlRule = (
113
+ url: URL,
114
+ urlRule: GuideActivationUrlRuleData,
115
+ ) => {
116
+ if (urlRule.variable === "pathname") {
117
+ if (urlRule.operator === "equal_to") {
118
+ const argument = urlRule.argument.startsWith("/")
119
+ ? urlRule.argument
120
+ : `/${urlRule.argument}`;
121
+
122
+ return argument === url.pathname;
123
+ }
124
+
125
+ if (urlRule.operator === "contains") {
126
+ return url.pathname.includes(urlRule.argument);
127
+ }
128
+
129
+ return false;
130
+ }
131
+
132
+ return false;
133
+ };
134
+
135
+ export const predicateUrlRules = (
136
+ url: URL,
137
+ urlRules: GuideActivationUrlRuleData[],
138
+ ) => {
139
+ return urlRules.reduce<boolean | undefined>((acc, urlRule) => {
140
+ // Any matched block rule prevails so no need to evaluate further
141
+ // as soon as there is one.
142
+ if (acc === false) return false;
143
+
144
+ // At this point we either have a matched allow rule (acc is true),
145
+ // or no matched rule found yet (acc is undefined).
146
+
147
+ switch (urlRule.directive) {
148
+ case "allow": {
149
+ // No need to evaluate more allow rules once we matched one
150
+ // since any matched allowed rule means allow.
151
+ if (acc === true) return true;
152
+
153
+ const matched = evaluateUrlRule(url, urlRule);
154
+ return matched ? true : undefined;
155
+ }
156
+
157
+ case "block": {
158
+ // Always test block rules (unless already matched to block)
159
+ // because they'd prevail over matched allow rules.
160
+ const matched = evaluateUrlRule(url, urlRule);
161
+ return matched ? false : acc;
162
+ }
163
+ }
164
+ }, undefined);
165
+ };
166
+
167
+ export const predicateUrlPatterns = (
168
+ url: URL,
169
+ urlPatterns: KnockGuideActivationUrlPattern[],
170
+ ) => {
171
+ return urlPatterns.reduce<boolean | undefined>((acc, urlPattern) => {
172
+ // Any matched block rule prevails so no need to evaluate further
173
+ // as soon as there is one.
174
+ if (acc === false) return false;
175
+
176
+ // At this point we either have a matched allow rule (acc is true),
177
+ // or no matched rule found yet (acc is undefined).
178
+
179
+ switch (urlPattern.directive) {
180
+ case "allow": {
181
+ // No need to evaluate more allow rules once we matched one
182
+ // since any matched allowed rule means allow.
183
+ if (acc === true) return true;
184
+
185
+ const matched = urlPattern.pattern.test(url);
186
+ return matched ? true : undefined;
187
+ }
188
+
189
+ case "block": {
190
+ // Always test block rules (unless already matched to block)
191
+ // because they'd prevail over matched allow rules.
192
+ const matched = urlPattern.pattern.test(url);
193
+ return matched ? false : acc;
194
+ }
195
+ }
196
+ }, undefined);
197
+ };
@@ -1,4 +1,4 @@
1
- export { KnockGuideClient } from "./client";
1
+ export { KnockGuideClient, DEBUG_QUERY_PARAMS } from "./client";
2
2
  export type {
3
3
  KnockGuide,
4
4
  KnockGuideStep,
@@ -4,6 +4,9 @@ import { GenericData } from "@knocklabs/types";
4
4
  // Fetch guides API
5
5
  //
6
6
 
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ export type Any = any;
9
+
7
10
  export interface StepMessageState {
8
11
  id: string;
9
12
  seen_at: string | null;
@@ -13,30 +16,37 @@ export interface StepMessageState {
13
16
  link_clicked_at: string | null;
14
17
  }
15
18
 
16
- export interface GuideStepData {
19
+ export interface GuideStepData<TContent = Any> {
17
20
  ref: string;
18
21
  schema_key: string;
19
22
  schema_semver: string;
20
23
  schema_variant_key: string;
21
24
  message: StepMessageState;
22
- // eslint-disable-next-line
23
- content: any;
25
+ content: TContent;
24
26
  }
25
27
 
26
- interface GuideActivationLocationRuleData {
28
+ export interface GuideActivationUrlRuleData {
29
+ directive: "allow" | "block";
30
+ variable: "pathname";
31
+ operator: "equal_to" | "contains";
32
+ argument: string;
33
+ }
34
+
35
+ interface GuideActivationUrlPatternData {
27
36
  directive: "allow" | "block";
28
37
  pathname: string;
29
38
  }
30
39
 
31
- export interface GuideData {
40
+ export interface GuideData<TContent = Any> {
32
41
  __typename: "Guide";
33
42
  channel_id: string;
34
43
  id: string;
35
44
  key: string;
36
45
  type: string;
37
46
  semver: string;
38
- steps: GuideStepData[];
39
- activation_location_rules: GuideActivationLocationRuleData[];
47
+ steps: GuideStepData<TContent>[];
48
+ activation_url_rules: GuideActivationUrlRuleData[];
49
+ activation_url_patterns: GuideActivationUrlPatternData[];
40
50
  bypass_global_group_limit: boolean;
41
51
  inserted_at: string;
42
52
  updated_at: string;
@@ -57,6 +67,7 @@ export type GetGuidesQueryParams = {
57
67
  data?: string;
58
68
  tenant?: string;
59
69
  type?: string;
70
+ force_all_guides?: boolean;
60
71
  };
61
72
 
62
73
  export type GetGuidesResponse = {
@@ -103,7 +114,8 @@ type SocketEventType =
103
114
  | "guide.updated"
104
115
  | "guide.removed"
105
116
  | "guide_group.added"
106
- | "guide_group.updated";
117
+ | "guide_group.updated"
118
+ | "guide.live_preview_updated";
107
119
 
108
120
  type SocketEventPayload<E extends SocketEventType, D> = {
109
121
  topic: string;
@@ -136,32 +148,39 @@ export type GuideGroupUpdatedEvent = SocketEventPayload<
136
148
  { guide_group: GuideGroupData }
137
149
  >;
138
150
 
151
+ export type GuideLivePreviewUpdatedEvent = SocketEventPayload<
152
+ "guide.live_preview_updated",
153
+ { guide: GuideData; eligible: boolean }
154
+ >;
155
+
139
156
  export type GuideSocketEvent =
140
157
  | GuideAddedEvent
141
158
  | GuideUpdatedEvent
142
159
  | GuideRemovedEvent
143
160
  | GuideGroupAddedEvent
144
- | GuideGroupUpdatedEvent;
161
+ | GuideGroupUpdatedEvent
162
+ | GuideLivePreviewUpdatedEvent;
145
163
 
146
164
  //
147
165
  // Guide client
148
166
  //
149
167
 
150
- export interface KnockGuideStep extends GuideStepData {
168
+ export interface KnockGuideStep<TContent = Any>
169
+ extends GuideStepData<TContent> {
151
170
  markAsSeen: () => void;
152
171
  markAsInteracted: (params?: { metadata?: GenericData }) => void;
153
172
  markAsArchived: () => void;
154
173
  }
155
174
 
156
- interface KnockGuideActivationLocationRule
157
- extends GuideActivationLocationRuleData {
175
+ export interface KnockGuideActivationUrlPattern
176
+ extends GuideActivationUrlPatternData {
158
177
  pattern: URLPattern;
159
178
  }
160
179
 
161
- export interface KnockGuide extends GuideData {
162
- steps: KnockGuideStep[];
163
- activation_location_rules: KnockGuideActivationLocationRule[];
164
- getStep: () => KnockGuideStep | undefined;
180
+ export interface KnockGuide<TContent = Any> extends GuideData<TContent> {
181
+ steps: KnockGuideStep<TContent>[];
182
+ activation_url_patterns: KnockGuideActivationUrlPattern[];
183
+ getStep: () => KnockGuideStep<TContent> | undefined;
165
184
  }
166
185
 
167
186
  type QueryKey = string;
@@ -171,13 +190,20 @@ export type QueryStatus = {
171
190
  error?: Error;
172
191
  };
173
192
 
193
+ export type DebugState = {
194
+ forcedGuideKey?: string | null;
195
+ previewSessionId?: string | null;
196
+ };
197
+
174
198
  export type StoreState = {
175
199
  guideGroups: GuideGroupData[];
176
200
  guideGroupDisplayLogs: Record<GuideGroupData["key"], string>;
177
201
  guides: Record<KnockGuide["key"], KnockGuide>;
202
+ previewGuides: Record<KnockGuide["key"], KnockGuide>;
178
203
  queries: Record<QueryKey, QueryStatus>;
179
204
  location: string | undefined;
180
205
  counter: number;
206
+ debug: DebugState;
181
207
  };
182
208
 
183
209
  export type QueryFilterParams = Pick<GetGuidesQueryParams, "type">;