@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 +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":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAO/C,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC;AAEtB,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,aAAa,CAAC,QAAQ,GAAG,GAAG;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7B,QAAQ,EAAE,UAAU,CAAC;IACrB,QAAQ,EAAE,UAAU,GAAG,UAAU,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,6BAA6B;IACrC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS,CAAC,QAAQ,GAAG,GAAG;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;IACjC,oBAAoB,EAAE,0BAA0B,EAAE,CAAC;IACnD,uBAAuB,EAAE,6BAA6B,EAAE,CAAC;IACzD,yBAAyB,EAAE,OAAO,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,YAAY,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,4BAA4B,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,0BAA0B,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC;IAC3D,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,wBAAwB,EAAE,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;CACjE,CAAC;AAMF,MAAM,MAAM,8BAA8B,GAAG;IAE3C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,8BAA8B,GAAG;IAE9D,OAAO,EAAE,WAAW,CAAC;IAErB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AACF,MAAM,MAAM,sBAAsB,GAAG,8BAA8B,CAAC;AACpE,MAAM,MAAM,oBAAoB,GAAG,8BAA8B,GAAG;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,IAAI,CAAC;CACd,CAAC;AAMF,KAAK,eAAe,GAChB,aAAa,GACb,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,qBAAqB,GACrB,4BAA4B,CAAC;AAEjC,KAAK,kBAAkB,CAAC,CAAC,SAAS,eAAe,EAAE,CAAC,IAAI;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,EAAE,CAAC,CAAC;CACT,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,kBAAkB,CAC9C,aAAa,EACb;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CACrC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAChD,eAAe,EACf;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CACxC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAChD,eAAe,EACf;IAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;CAAE,CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,CACnD,mBAAmB,EACnB;IAAE,WAAW,EAAE,cAAc,CAAA;CAAE,CAChC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CACrD,qBAAqB,EACrB;IAAE,WAAW,EAAE,cAAc,CAAA;CAAE,CAChC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,kBAAkB,CAC3D,4BAA4B,EAC5B;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CACxC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB,eAAe,GACf,iBAAiB,GACjB,iBAAiB,GACjB,oBAAoB,GACpB,sBAAsB,GACtB,4BAA4B,CAAC;AAMjC,MAAM,WAAW,cAAc,CAAC,QAAQ,GAAG,GAAG,CAC5C,SAAQ,aAAa,CAAC,QAAQ,CAAC;IAC/B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,gBAAgB,EAAE,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAChE,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,8BACf,SAAQ,6BAA6B;IACrC,OAAO,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAE,SAAQ,SAAS,CAAC,QAAQ,CAAC;IACrE,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;IAClC,uBAAuB,EAAE,8BAA8B,EAAE,CAAC;IAC1D,OAAO,EAAE,MAAM,cAAc,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;CACrD;AAED,KAAK,QAAQ,GAAG,MAAM,CAAC;AAEvB,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC;IACnC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7D,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,CAAC;IAC9C,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACvC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;AAEnE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC7B,SAAS,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;CACjD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knocklabs/client",
3
- "version": "0.16.5",
3
+ "version": "0.17.1",
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,14 +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];
112
+
113
+ // Use preview guide if it exists and matches the forced guide key
114
+ if (
115
+ state.debug.forcedGuideKey === guideKey &&
116
+ state.previewGuides[guideKey]
117
+ ) {
118
+ guide = state.previewGuides[guideKey];
119
+ }
120
+
77
121
  if (!guide) continue;
78
122
 
79
- const affirmed = predicate(guide, { location, filters });
123
+ const affirmed = predicate(guide, {
124
+ location,
125
+ filters,
126
+ debug: state.debug,
127
+ });
128
+
80
129
  if (!affirmed) continue;
81
130
 
82
131
  result.set(index, guide);
@@ -89,11 +138,12 @@ const select = (state: StoreState, filters: SelectFilterParams = {}) => {
89
138
  type PredicateOpts = {
90
139
  location?: string | undefined;
91
140
  filters?: SelectFilterParams | undefined;
141
+ debug: DebugState;
92
142
  };
93
143
 
94
144
  const predicate = (
95
145
  guide: KnockGuide,
96
- { location, filters = {} }: PredicateOpts,
146
+ { location, filters = {}, debug = {} }: PredicateOpts,
97
147
  ) => {
98
148
  if (filters.type && filters.type !== guide.type) {
99
149
  return false;
@@ -103,40 +153,28 @@ const predicate = (
103
153
  return false;
104
154
  }
105
155
 
156
+ // Bypass filtering if the debugged guide matches the given filters.
157
+ // This should always run AFTER checking the filters but BEFORE
158
+ // checking archived status and location rules.
159
+ if (debug.forcedGuideKey === guide.key) {
160
+ return true;
161
+ }
162
+
106
163
  if (guide.steps.every((s) => !!s.message.archived_at)) {
107
164
  return false;
108
165
  }
109
166
 
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).
120
-
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
- }
167
+ const url = location ? newUrl(location) : undefined;
130
168
 
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);
169
+ const urlRules = guide.activation_url_rules || [];
170
+ const urlPatterns = guide.activation_url_patterns || [];
139
171
 
172
+ // A guide can have either activation url rules XOR url patterns, but not both.
173
+ if (url && urlRules.length > 0) {
174
+ const allowed = predicateUrlRules(url, urlRules);
175
+ if (!allowed) return false;
176
+ } else if (url && urlPatterns.length > 0) {
177
+ const allowed = predicateUrlPatterns(url, urlPatterns);
140
178
  if (!allowed) return false;
141
179
  }
142
180
 
@@ -156,6 +194,7 @@ export class KnockGuideClient {
156
194
  "guide.removed",
157
195
  "guide_group.added",
158
196
  "guide_group.updated",
197
+ "guide.live_preview_updated",
159
198
  ];
160
199
  private subscribeRetryCount = 0;
161
200
 
@@ -181,14 +220,18 @@ export class KnockGuideClient {
181
220
 
182
221
  const location = trackLocationFromWindow ? win?.location.href : undefined;
183
222
 
223
+ const debug = detectDebugParams();
224
+
184
225
  this.store = new Store<StoreState>({
185
226
  guideGroups: [],
186
227
  guideGroupDisplayLogs: {},
187
228
  guides: {},
229
+ previewGuides: {},
188
230
  queries: {},
189
231
  location,
190
232
  // Increment to update the state store and trigger re-selection.
191
233
  counter: 0,
234
+ debug,
192
235
  });
193
236
 
194
237
  // In server environments we might not have a socket connection.
@@ -302,7 +345,14 @@ export class KnockGuideClient {
302
345
  }
303
346
 
304
347
  // Join the channel topic and subscribe to supported events.
305
- const params = { ...this.targetParams, user_id: this.knock.userId };
348
+ const debugState = this.store.state.debug;
349
+ const params = {
350
+ ...this.targetParams,
351
+ user_id: this.knock.userId,
352
+ force_all_guides: debugState.forcedGuideKey ? true : undefined,
353
+ preview_session_id: debugState.previewSessionId || undefined,
354
+ };
355
+
306
356
  const newChannel = this.socket.channel(this.socketChannelTopic, params);
307
357
 
308
358
  for (const eventType of this.socketEventTypes) {
@@ -381,23 +431,41 @@ export class KnockGuideClient {
381
431
  case "guide_group.updated":
382
432
  return this.addOrReplaceGuideGroup(payload);
383
433
 
434
+ case "guide.live_preview_updated":
435
+ return this.updatePreviewGuide(payload);
436
+
384
437
  default:
385
438
  return;
386
439
  }
387
440
  }
388
441
 
389
- setLocation(href: string) {
442
+ setLocation(href: string, additionalParams: Partial<StoreState> = {}) {
390
443
  // Make sure to clear out the stage.
391
444
  this.clearGroupStage();
392
445
 
393
- this.store.setState((state) => ({ ...state, location: href }));
446
+ this.store.setState((state) => {
447
+ // Clear preview guides if no longer in preview mode
448
+ const previewGuides = additionalParams?.debug?.previewSessionId
449
+ ? state.previewGuides
450
+ : {};
451
+
452
+ return {
453
+ ...state,
454
+ ...additionalParams,
455
+ previewGuides,
456
+ location: href,
457
+ };
458
+ });
394
459
  }
395
460
 
396
461
  //
397
462
  // Store selector
398
463
  //
399
464
 
400
- selectGuides(state: StoreState, filters: SelectFilterParams = {}) {
465
+ selectGuides<C = Any>(
466
+ state: StoreState,
467
+ filters: SelectFilterParams = {},
468
+ ): KnockGuide<C>[] {
401
469
  if (Object.keys(state.guides).length === 0) {
402
470
  return [];
403
471
  }
@@ -416,7 +484,10 @@ export class KnockGuideClient {
416
484
  return [...result.values()];
417
485
  }
418
486
 
419
- selectGuide(state: StoreState, filters: SelectFilterParams = {}) {
487
+ selectGuide<C = Any>(
488
+ state: StoreState,
489
+ filters: SelectFilterParams = {},
490
+ ): KnockGuide<C> | undefined {
420
491
  if (Object.keys(state.guides).length === 0) {
421
492
  return undefined;
422
493
  }
@@ -539,10 +610,22 @@ export class KnockGuideClient {
539
610
  // callback to a setTimeout, but just to be safe.
540
611
  this.ensureClearTimeout();
541
612
 
613
+ // If in debug mode, try to resolve the forced guide, otherwise return the first non-undefined guide.
614
+ let resolved = undefined;
615
+ if (this.store.state.debug.forcedGuideKey) {
616
+ resolved = this.stage.ordered.find(
617
+ (x) => x === this.store.state.debug.forcedGuideKey,
618
+ );
619
+ }
620
+
621
+ if (!resolved) {
622
+ resolved = this.stage.ordered.find((x) => x !== undefined);
623
+ }
624
+
542
625
  this.stage = {
543
626
  ...this.stage,
544
627
  status: "closed",
545
- resolved: this.stage.ordered.find((x) => x !== undefined),
628
+ resolved,
546
629
  timeoutId: null,
547
630
  };
548
631
 
@@ -706,6 +789,11 @@ export class KnockGuideClient {
706
789
  ...remoteGuide,
707
790
  // Get the next unarchived step.
708
791
  getStep() {
792
+ // If debugging this guide, return the first step regardless of archive status
793
+ if (self.store.state.debug.forcedGuideKey === this.key) {
794
+ return this.steps[0];
795
+ }
796
+
709
797
  return this.steps.find((s) => !s.message.archived_at);
710
798
  },
711
799
  } as KnockGuide;
@@ -741,8 +829,8 @@ export class KnockGuideClient {
741
829
  return localStep;
742
830
  });
743
831
 
744
- localGuide.activation_location_rules =
745
- remoteGuide.activation_location_rules.map((rule) => {
832
+ localGuide.activation_url_patterns =
833
+ remoteGuide.activation_url_patterns.map((rule) => {
746
834
  return {
747
835
  ...rule,
748
836
  pattern: new URLPattern({ pathname: rule.pathname }),
@@ -754,7 +842,16 @@ export class KnockGuideClient {
754
842
 
755
843
  private buildQueryParams(filterParams: QueryFilterParams = {}) {
756
844
  // Combine the target params with the given filter params.
757
- const combinedParams = { ...this.targetParams, ...filterParams };
845
+ const combinedParams: GenericData = {
846
+ ...this.targetParams,
847
+ ...filterParams,
848
+ };
849
+
850
+ // Append debug params
851
+ const debugState = this.store.state.debug;
852
+ if (debugState.forcedGuideKey) {
853
+ combinedParams.force_all_guides = true;
854
+ }
758
855
 
759
856
  // Prune out any keys that have an undefined or null value.
760
857
  let params = Object.fromEntries(
@@ -899,6 +996,15 @@ export class KnockGuideClient {
899
996
  });
900
997
  }
901
998
 
999
+ private updatePreviewGuide({ data }: GuideLivePreviewUpdatedEvent) {
1000
+ const guide = this.localCopy(data.guide);
1001
+
1002
+ this.store.setState((state) => {
1003
+ const previewGuides = { ...state.previewGuides, [guide.key]: guide };
1004
+ return { ...state, previewGuides };
1005
+ });
1006
+ }
1007
+
902
1008
  // Define as an arrow func property to always bind this to the class instance.
903
1009
  private handleLocationChange = () => {
904
1010
  const win = checkForWindow();
@@ -908,9 +1014,36 @@ export class KnockGuideClient {
908
1014
  if (this.store.state.location === href) return;
909
1015
 
910
1016
  this.knock.log(`[Guide] Handle Location change: ${href}`);
911
- this.setLocation(href);
1017
+
1018
+ // If entering debug mode, fetch all guides.
1019
+ const currentDebugParams = this.store.state.debug;
1020
+ const newDebugParams = detectDebugParams();
1021
+ this.setLocation(href, { debug: newDebugParams });
1022
+
1023
+ // If debug state has changed, refetch guides and resubscribe to the websocket channel
1024
+ const debugStateChanged = this.checkDebugStateChanged(
1025
+ currentDebugParams,
1026
+ newDebugParams,
1027
+ );
1028
+
1029
+ if (debugStateChanged) {
1030
+ this.knock.log(
1031
+ `[Guide] Debug state changed, refetching guides and resubscribing to the websocket channel`,
1032
+ );
1033
+ this.fetch();
1034
+ this.subscribe();
1035
+ }
912
1036
  };
913
1037
 
1038
+ // Returns whether debug params have changed. For guide key, we only check
1039
+ // presence since the exact value has no impact on fetch/subscribe
1040
+ private checkDebugStateChanged(a: DebugState, b: DebugState): boolean {
1041
+ return (
1042
+ Boolean(a.forcedGuideKey) !== Boolean(b.forcedGuideKey) ||
1043
+ a.previewSessionId !== b.previewSessionId
1044
+ );
1045
+ }
1046
+
914
1047
  private listenForLocationChangesFromWindow() {
915
1048
  const win = checkForWindow();
916
1049
  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">;