feeds-fun 1.21.6 → 1.22.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.
package/src/logic/api.ts CHANGED
@@ -4,92 +4,126 @@ import * as t from "@/logic/types";
4
4
  import type * as e from "@/logic/enums";
5
5
  import * as settings from "@/logic/settings";
6
6
  import * as cookieConsent from "@/plugins/CookieConsent";
7
+ import {useGlobalState} from "@/stores/globalState";
8
+ import {ok, err, Result} from "neverthrow";
7
9
 
8
- const ENTRY_POINT = "/api";
9
-
10
- const API_GET_FEEDS = `${ENTRY_POINT}/get-feeds`;
11
- const API_GET_LAST_ENTRIES = `${ENTRY_POINT}/get-last-entries`;
12
- const API_GET_LAST_COLLECTION_ENTRIES = `${ENTRY_POINT}/get-last-collection-entries`;
13
- const API_GET_ENTRIES_BY_IDS = `${ENTRY_POINT}/get-entries-by-ids`;
14
- const API_CREATE_OR_UPDATE_RULE = `${ENTRY_POINT}/create-or-update-rule`;
15
-
16
- const API_DELETE_RULE = `${ENTRY_POINT}/delete-rule`;
17
- const API_UPDATE_RULE = `${ENTRY_POINT}/update-rule`;
18
- const API_GET_RULES = `${ENTRY_POINT}/get-rules`;
19
- const API_GET_SCORE_DETAILS = `${ENTRY_POINT}/get-score-details`;
20
- const API_SET_MARKER = `${ENTRY_POINT}/set-marker`;
21
- const API_REMOVE_MARKER = `${ENTRY_POINT}/remove-marker`;
22
- const API_DISCOVER_FEEDS = `${ENTRY_POINT}/discover-feeds`;
23
- const API_ADD_FEED = `${ENTRY_POINT}/add-feed`;
24
- const API_ADD_OPML = `${ENTRY_POINT}/add-opml`;
25
- const API_UNSUBSCRIBE = `${ENTRY_POINT}/unsubscribe`;
26
- const API_GET_COLLECTIONS = `${ENTRY_POINT}/get-collections`;
27
- const API_GET_COLLECTION_FEEDS = `${ENTRY_POINT}/get-collection-feeds`;
28
- const API_SUBSCRIBE_TO_COLLECTIONS = `${ENTRY_POINT}/subscribe-to-collections`;
29
- const API_GET_TAGS_INFO = `${ENTRY_POINT}/get-tags-info`;
30
- const API_GET_USER_SETTINGS = `${ENTRY_POINT}/get-user-settings`;
31
- const API_SET_USER_SETTING = `${ENTRY_POINT}/set-user-setting`;
32
- const API_GET_RESOURCE_HISTORY = `${ENTRY_POINT}/get-resource-history`;
33
- const API_GET_INFO = `${ENTRY_POINT}/get-info`;
34
- const API_TRACK_EVENT = `${ENTRY_POINT}/track-event`;
35
- const API_REMOVE_USER = `${ENTRY_POINT}/remove-user`;
36
-
37
- let _onSessionLost: () => void = () => {};
38
-
39
- export function init({onSessionLost}: {onSessionLost: () => void}) {
40
- _onSessionLost = onSessionLost;
41
- }
42
-
43
- async function post({url, data}: {url: string; data: any}) {
44
- try {
45
- const response = await axios.post(url, data);
46
- return response.data;
47
- } catch (error) {
48
- console.log(error);
49
-
50
- if (error instanceof Error && "response" in error) {
51
- const axiosError = error as AxiosError;
52
- if (axiosError.response && axiosError.response.status === 401) {
53
- await _onSessionLost();
54
- }
55
- }
10
+ ///////////////
11
+ // API handlers
12
+ ///////////////
13
+
14
+ const publicEntryPoint = "/spa/api/public";
15
+ const privateEntryPoint = "/spa/api/private";
16
+
17
+ export const downloadOPMLUrl = `${privateEntryPoint}/get-opml`;
18
+
19
+ const apiPublic = axios.create({baseURL: publicEntryPoint, withCredentials: true});
20
+ const apiPrivate = axios.create({baseURL: privateEntryPoint, withCredentials: true});
56
21
 
57
- throw error;
22
+ // It is an open question what should we do in case of session expiration:
23
+ // - redirect to login page
24
+ // - redirect to home page & show notification
25
+ // Currently the easiest way to handle it is to always redirect to login page.
26
+ export function redirectToLogin(returnTo?: string) {
27
+ if (!returnTo) {
28
+ returnTo = window.location.pathname + window.location.search;
58
29
  }
30
+ window.location.assign(`/spa/auth/login?return_to=${encodeURIComponent(returnTo)}`);
59
31
  }
60
32
 
61
- export async function getFeeds() {
62
- const response = await post({url: API_GET_FEEDS, data: {}});
33
+ export function redirectToJoin(returnTo?: string) {
34
+ if (!returnTo) {
35
+ returnTo = window.location.pathname + window.location.search;
36
+ }
37
+ window.location.assign(`/spa/auth/join?return_to=${encodeURIComponent(returnTo)}`);
38
+ }
63
39
 
64
- const feeds = [];
40
+ export function logoutRedirect() {
41
+ window.location.assign("/spa/auth/logout");
42
+ }
65
43
 
66
- for (let rawFeed of response.feeds) {
67
- const feed = t.feedFromJSON(rawFeed);
68
- feeds.push(feed);
69
- }
44
+ let _refreshingAuth: Promise<void> | null = null;
70
45
 
71
- return feeds;
46
+ enum Ffun401Behaviour {
47
+ RedirectToLogin = "redirectToLogin",
48
+ DoNotRetry = "doNotRetry",
49
+ ReturnNull = "returnNull"
72
50
  }
73
51
 
74
- export async function getLastEntries({period, minTagCount}: {period: number; minTagCount: number}) {
75
- const response = await post({
76
- url: API_GET_LAST_ENTRIES,
77
- data: {
78
- period: period,
79
- minTagCount: minTagCount
52
+ // We try to refresh auth on 401 responses for private API.
53
+ // For the public API we do nothing, because it most likely means infrastructure issue.
54
+ apiPrivate.interceptors.response.use(
55
+ (r) => r,
56
+ async (error) => {
57
+ const {config, response} = error;
58
+
59
+ if (!response) {
60
+ throw error;
80
61
  }
81
- });
82
62
 
83
- const entries = [];
63
+ if (response.status !== 401) {
64
+ throw error;
65
+ }
84
66
 
85
- for (let rawEntry of response.entries) {
86
- const entry = t.entryFromJSON(rawEntry, response.tagsMapping);
87
- entries.push(entry);
67
+ if (config?.ffunRequestRetried) {
68
+ throw error;
69
+ }
70
+
71
+ if (config?.ffun401Behaviour === Ffun401Behaviour.RedirectToLogin) {
72
+ redirectToLogin();
73
+ return; // never reached
74
+ }
75
+
76
+ if (config?.ffun401Behaviour === Ffun401Behaviour.DoNotRetry) {
77
+ throw error;
78
+ }
79
+
80
+ if (config?.ffun401Behaviour === Ffun401Behaviour.ReturnNull) {
81
+ return {data: null};
82
+ }
83
+
84
+ (config as any).ffunRequestRetried = true;
85
+
86
+ if (!_refreshingAuth) {
87
+ _refreshingAuth = apiPrivate
88
+ // @ts-ignore
89
+ .post("/refresh-auth", undefined, {ffun401Behaviour: Ffun401Behaviour.RedirectToLogin})
90
+ .then(() => {})
91
+ .finally(() => {
92
+ _refreshingAuth = null;
93
+ });
94
+ }
95
+
96
+ await _refreshingAuth; // all 401s await the same refresh
97
+
98
+ return await apiPrivate(config); // retry the original request generically
88
99
  }
100
+ );
89
101
 
90
- return entries;
102
+ async function postPublic({url, data}: {url: string; data: any}) {
103
+ const response = await apiPublic.post(url, data);
104
+ return response.data;
91
105
  }
92
106
 
107
+ // TODO: deprecated, use postPrivateResult instead
108
+ async function postPrivate({url, data, config}: {url: string; data: any; config?: any}) {
109
+ const response = await apiPrivate.post(url, data, config);
110
+ return response.data;
111
+ }
112
+
113
+ async function postPrivateResult({url, data, config}: {url: string; data: any; config?: any}) {
114
+ const response = await apiPrivate.post(url, data, config);
115
+
116
+ if (response.data.status === "error") {
117
+ return err(new t.ApiError(response.data.code, response.data.message));
118
+ }
119
+
120
+ return ok(response.data.data);
121
+ }
122
+
123
+ /////////////
124
+ // Public API
125
+ /////////////
126
+
93
127
  export async function getLastCollectionEntries({
94
128
  period,
95
129
  collectionSlug,
@@ -99,8 +133,8 @@ export async function getLastCollectionEntries({
99
133
  collectionSlug: t.CollectionSlug | null;
100
134
  minTagCount: number;
101
135
  }) {
102
- const response = await post({
103
- url: API_GET_LAST_COLLECTION_ENTRIES,
136
+ const response = await postPublic({
137
+ url: "/get-last-collection-entries",
104
138
  data: {period: period, collectionSlug: collectionSlug, minTagCount: minTagCount}
105
139
  });
106
140
 
@@ -115,9 +149,157 @@ export async function getLastCollectionEntries({
115
149
  }
116
150
 
117
151
  export async function getEntriesByIds({ids}: {ids: t.EntryId[]}) {
118
- const response = await post({
119
- url: API_GET_ENTRIES_BY_IDS,
120
- data: {ids: ids}
152
+ const globalState = useGlobalState();
153
+
154
+ let response = null;
155
+
156
+ if (globalState.loginConfirmed) {
157
+ response = await postPrivate({
158
+ url: "/get-entries-by-ids",
159
+ data: {ids: ids},
160
+ config: {ffun401Behaviour: Ffun401Behaviour.ReturnNull}
161
+ });
162
+ }
163
+
164
+ if (!response) {
165
+ response = await postPublic({
166
+ url: "/get-entries-by-ids",
167
+ data: {ids: ids}
168
+ });
169
+ }
170
+
171
+ const entries = [];
172
+
173
+ for (let rawEntry of response.entries) {
174
+ const entry = t.entryFromJSON(rawEntry, response.tagsMapping);
175
+ entries.push(entry);
176
+ }
177
+
178
+ return entries;
179
+ }
180
+
181
+ export async function getCollections() {
182
+ const response = await postPublic({url: "/get-collections", data: {}});
183
+
184
+ const collections = [];
185
+
186
+ for (let rawCollection of response.collections) {
187
+ const collection = t.collectionFromJSON(rawCollection);
188
+ collections.push(collection);
189
+ }
190
+
191
+ return collections;
192
+ }
193
+
194
+ export async function getCollectionFeeds({collectionId}: {collectionId: t.CollectionId}) {
195
+ const response = await postPublic({
196
+ url: "/get-collection-feeds",
197
+ data: {collectionId: collectionId}
198
+ });
199
+
200
+ const feeds = [];
201
+
202
+ for (let rawFeed of response.feeds) {
203
+ const feed = t.collectionFeedInfoFromJSON(rawFeed);
204
+ feeds.push(feed);
205
+ }
206
+
207
+ return feeds;
208
+ }
209
+
210
+ export async function getTagsInfo({uids}: {uids: string[]}) {
211
+ const response = await postPublic({url: "/get-tags-info", data: {uids: uids}});
212
+
213
+ const tags: {[key: string]: t.TagInfo} = {};
214
+
215
+ for (let uid in response.tags) {
216
+ const rawTag = response.tags[uid];
217
+ const tag = t.tagInfoFromJSON(rawTag);
218
+ tags[uid] = tag;
219
+ }
220
+
221
+ return tags;
222
+ }
223
+
224
+ export async function getInfo() {
225
+ const response = await postPublic({url: "/get-info", data: {}});
226
+
227
+ return t.stateInfoFromJSON(response);
228
+ }
229
+
230
+ export async function getUser() {
231
+ const response = await postPrivate({
232
+ url: "/get-user",
233
+ data: {},
234
+ config: {ffun401Behaviour: Ffun401Behaviour.ReturnNull}
235
+ });
236
+
237
+ if (!response) {
238
+ return null;
239
+ }
240
+
241
+ return t.userInfoFromJSON(response);
242
+ }
243
+
244
+ export function trackEvent(data: {[key: string]: string | number | null}) {
245
+ if (!settings.trackEvents) {
246
+ return;
247
+ }
248
+
249
+ if (!cookieConsent.isAnalyticsAllowed()) {
250
+ return;
251
+ }
252
+
253
+ const globalState = useGlobalState();
254
+
255
+ let url: string;
256
+
257
+ if (globalState.loginConfirmed) {
258
+ url = privateEntryPoint + "/track-event";
259
+ } else {
260
+ url = publicEntryPoint + "/track-event";
261
+ }
262
+
263
+ let payload = JSON.stringify({event: data});
264
+
265
+ if ("sendBeacon" in navigator) {
266
+ return navigator.sendBeacon(url, payload);
267
+ }
268
+
269
+ // Fallback: fire-and-forget; avoid preflight by using text/plain + no-cors
270
+ fetch(url, {
271
+ method: "POST",
272
+ keepalive: true,
273
+ mode: "no-cors",
274
+ headers: {"Content-Type": "text/plain;charset=UTF-8"},
275
+ body: payload
276
+ }).catch(() => {});
277
+ }
278
+
279
+ //////////////
280
+ // Private API
281
+ //////////////
282
+
283
+ export async function getFeeds() {
284
+ const response = await postPrivate({url: "/get-feeds", data: {}});
285
+
286
+ const feeds = [];
287
+
288
+ for (let rawFeed of response.feeds) {
289
+ const feed = t.feedFromJSON(rawFeed);
290
+ feeds.push(feed);
291
+ }
292
+
293
+ return feeds;
294
+ }
295
+
296
+ export async function getLastEntries({period, minTagCount}: {period: number; minTagCount: number}) {
297
+ const response = await postPrivate({
298
+ url: "/get-last-entries",
299
+ data: {
300
+ period: period,
301
+ minTagCount: minTagCount
302
+ }
121
303
  });
122
304
 
123
305
  const entries = [];
@@ -139,8 +321,8 @@ export async function createOrUpdateRule({
139
321
  excludedTags: string[];
140
322
  score: number;
141
323
  }) {
142
- const response = await post({
143
- url: API_CREATE_OR_UPDATE_RULE,
324
+ const response = await postPrivate({
325
+ url: "/create-or-update-rule",
144
326
  data: {
145
327
  requiredTags: requiredTags,
146
328
  excludedTags: excludedTags,
@@ -151,7 +333,7 @@ export async function createOrUpdateRule({
151
333
  }
152
334
 
153
335
  export async function deleteRule({id}: {id: t.RuleId}) {
154
- const response = await post({url: API_DELETE_RULE, data: {id: id}});
336
+ const response = await postPrivate({url: "/delete-rule", data: {id: id}});
155
337
  return response;
156
338
  }
157
339
 
@@ -166,15 +348,15 @@ export async function updateRule({
166
348
  excludedTags: string[];
167
349
  score: number;
168
350
  }) {
169
- const response = await post({
170
- url: API_UPDATE_RULE,
351
+ const response = await postPrivate({
352
+ url: "/update-rule",
171
353
  data: {id: id, score: score, requiredTags: requiredTags, excludedTags: excludedTags}
172
354
  });
173
355
  return response;
174
356
  }
175
357
 
176
358
  export async function getRules() {
177
- const response = await post({url: API_GET_RULES, data: {}});
359
+ const response = await postPrivate({url: "/get-rules", data: {}});
178
360
 
179
361
  const rules = [];
180
362
 
@@ -187,8 +369,8 @@ export async function getRules() {
187
369
  }
188
370
 
189
371
  export async function getScoreDetails({entryId}: {entryId: t.EntryId}) {
190
- const response = await post({
191
- url: API_GET_SCORE_DETAILS,
372
+ const response = await postPrivate({
373
+ url: "/get-score-details",
192
374
  data: {entryId: entryId}
193
375
  });
194
376
 
@@ -203,21 +385,21 @@ export async function getScoreDetails({entryId}: {entryId: t.EntryId}) {
203
385
  }
204
386
 
205
387
  export async function setMarker({entryId, marker}: {entryId: t.EntryId; marker: e.Marker}) {
206
- await post({
207
- url: API_SET_MARKER,
388
+ await postPrivate({
389
+ url: "/set-marker",
208
390
  data: {entryId: entryId, marker: marker}
209
391
  });
210
392
  }
211
393
 
212
394
  export async function removeMarker({entryId, marker}: {entryId: t.EntryId; marker: e.Marker}) {
213
- await post({
214
- url: API_REMOVE_MARKER,
395
+ await postPrivate({
396
+ url: "/remove-marker",
215
397
  data: {entryId: entryId, marker: marker}
216
398
  });
217
399
  }
218
400
 
219
401
  export async function discoverFeeds({url}: {url: string}) {
220
- const response = await post({url: API_DISCOVER_FEEDS, data: {url: url}});
402
+ const response = await postPrivate({url: "/discover-feeds", data: {url: url}});
221
403
 
222
404
  const feeds = [];
223
405
  const messages = [];
@@ -236,71 +418,28 @@ export async function discoverFeeds({url}: {url: string}) {
236
418
  }
237
419
 
238
420
  export async function addFeed({url}: {url: string}) {
239
- const response = await post({url: API_ADD_FEED, data: {url: url}});
421
+ const response = await postPrivate({url: "/add-feed", data: {url: url}});
240
422
 
241
423
  return t.feedFromJSON(response.feed);
242
424
  }
243
425
 
244
426
  export async function addOPML({content}: {content: string}) {
245
- await post({url: API_ADD_OPML, data: {content: content}});
427
+ return await postPrivateResult({url: "/add-opml", data: {content: content}});
246
428
  }
247
429
 
248
430
  export async function unsubscribe({feedId}: {feedId: t.FeedId}) {
249
- await post({url: API_UNSUBSCRIBE, data: {feedId: feedId}});
250
- }
251
-
252
- export async function getCollections() {
253
- const response = await post({url: API_GET_COLLECTIONS, data: {}});
254
-
255
- const collections = [];
256
-
257
- for (let rawCollection of response.collections) {
258
- const collection = t.collectionFromJSON(rawCollection);
259
- collections.push(collection);
260
- }
261
-
262
- return collections;
263
- }
264
-
265
- export async function getCollectionFeeds({collectionId}: {collectionId: t.CollectionId}) {
266
- const response = await post({
267
- url: API_GET_COLLECTION_FEEDS,
268
- data: {collectionId: collectionId}
269
- });
270
-
271
- const feeds = [];
272
-
273
- for (let rawFeed of response.feeds) {
274
- const feed = t.collectionFeedInfoFromJSON(rawFeed);
275
- feeds.push(feed);
276
- }
277
-
278
- return feeds;
431
+ await postPrivate({url: "/unsubscribe", data: {feedId: feedId}});
279
432
  }
280
433
 
281
434
  export async function subscribeToCollections({collectionsIds}: {collectionsIds: t.CollectionId[]}) {
282
- await post({
283
- url: API_SUBSCRIBE_TO_COLLECTIONS,
435
+ await postPrivate({
436
+ url: "/subscribe-to-collections",
284
437
  data: {collections: collectionsIds}
285
438
  });
286
439
  }
287
440
 
288
- export async function getTagsInfo({uids}: {uids: string[]}) {
289
- const response = await post({url: API_GET_TAGS_INFO, data: {uids: uids}});
290
-
291
- const tags: {[key: string]: t.TagInfo} = {};
292
-
293
- for (let uid in response.tags) {
294
- const rawTag = response.tags[uid];
295
- const tag = t.tagInfoFromJSON(rawTag);
296
- tags[uid] = tag;
297
- }
298
-
299
- return tags;
300
- }
301
-
302
441
  export async function getUserSettings() {
303
- const response = await post({url: API_GET_USER_SETTINGS, data: {}});
442
+ const response = await postPrivate({url: "/get-user-settings", data: {}});
304
443
 
305
444
  const settings: {[key: string]: t.UserSetting} = {};
306
445
 
@@ -313,12 +452,12 @@ export async function getUserSettings() {
313
452
  }
314
453
 
315
454
  export async function setUserSetting({kind, value}: {kind: string; value: string | number | boolean}) {
316
- await post({url: API_SET_USER_SETTING, data: {kind: kind, value: value}});
455
+ await postPrivate({url: "/set-user-setting", data: {kind: kind, value: value}});
317
456
  }
318
457
 
319
458
  export async function getResourceHistory({kind}: {kind: string}) {
320
- const response = await post({
321
- url: API_GET_RESOURCE_HISTORY,
459
+ const response = await postPrivate({
460
+ url: "/get-resource-history",
322
461
  data: {kind: kind}
323
462
  });
324
463
 
@@ -332,24 +471,6 @@ export async function getResourceHistory({kind}: {kind: string}) {
332
471
  return history;
333
472
  }
334
473
 
335
- export async function getInfo() {
336
- const response = await post({url: API_GET_INFO, data: {}});
337
-
338
- return response;
339
- }
340
-
341
- export async function trackEvent(data: {[key: string]: string | number | null}) {
342
- if (!settings.trackEvents) {
343
- return;
344
- }
345
-
346
- if (!cookieConsent.isAnalyticsAllowed()) {
347
- return;
348
- }
349
-
350
- await post({url: API_TRACK_EVENT, data: {event: data}});
351
- }
352
-
353
474
  export async function removeUser() {
354
- await post({url: API_REMOVE_USER, data: {}});
475
+ await postPrivate({url: "/remove-user", data: {}});
355
476
  }
@@ -5,6 +5,16 @@ export type AnyEnum = {
5
5
  [key in keyof any]: string | number;
6
6
  };
7
7
 
8
+ //////////////
9
+ // Login state
10
+ //////////////
11
+
12
+ export enum LoginState {
13
+ Unknown = "unknown",
14
+ LoggedOut = "logged-out",
15
+ LoggedIn = "logged-in"
16
+ }
17
+
8
18
  ///////////////////
9
19
  // Main panel modes
10
20
  ///////////////////
@@ -18,31 +18,39 @@ export type TagChangeSource = "tags_filter" | "entry_record" | "rule_record";
18
18
  export type SidebarVisibilityChangeEvent = "hide" | "show";
19
19
  export type SidebarVisibilityChangeSource = "top_sidebar_button";
20
20
 
21
- export async function newsLinkOpened({entryId, view}: {entryId: t.EntryId; view: EventsViewName}) {
22
- await api.trackEvent({
21
+ export function newsLinkOpened({entryId, view}: {entryId: t.EntryId; view: EventsViewName}) {
22
+ api.trackEvent({
23
23
  name: "news_link_opened",
24
24
  view: view,
25
25
  entry_id: entryId
26
26
  });
27
27
  }
28
28
 
29
- export async function newsBodyOpened({entryId, view}: {entryId: t.EntryId; view: EventsViewName}) {
30
- await api.trackEvent({
29
+ export function newsBodyOpened({entryId, view}: {entryId: t.EntryId; view: EventsViewName}) {
30
+ api.trackEvent({
31
31
  name: "news_body_opened",
32
32
  view: view,
33
33
  entry_id: entryId
34
34
  });
35
35
  }
36
36
 
37
- export async function socialLinkClicked({linkType, view}: {linkType: string; view: EventsViewName}) {
38
- await api.trackEvent({
37
+ export function socialLinkClicked({linkType, view}: {linkType: string; view: EventsViewName}) {
38
+ api.trackEvent({
39
39
  name: "social_link_clicked",
40
40
  view: view,
41
41
  link_type: linkType
42
42
  });
43
43
  }
44
44
 
45
- export async function sidebarStateChanged({
45
+ export function authButtonClicked({buttonType, view}: {buttonType: string; view: EventsViewName}) {
46
+ api.trackEvent({
47
+ name: "auth_button_clicked",
48
+ view: view,
49
+ button_type: buttonType
50
+ });
51
+ }
52
+
53
+ export function sidebarStateChanged({
46
54
  subEvent,
47
55
  view,
48
56
  source
@@ -51,7 +59,7 @@ export async function sidebarStateChanged({
51
59
  view: EventsViewName;
52
60
  source: SidebarVisibilityChangeSource;
53
61
  }) {
54
- await api.trackEvent({
62
+ api.trackEvent({
55
63
  name: "sidebar_state_changed",
56
64
  view: view,
57
65
  sub_event: subEvent,
@@ -59,7 +67,7 @@ export async function sidebarStateChanged({
59
67
  });
60
68
  }
61
69
 
62
- export async function tagStateChanged({
70
+ export function tagStateChanged({
63
71
  tag,
64
72
  fromState,
65
73
  toState,
@@ -74,7 +82,7 @@ export async function tagStateChanged({
74
82
  }) {
75
83
  // const eventsView = inject<events.EventViewName>("eventsViewName");
76
84
 
77
- await api.trackEvent({
85
+ api.trackEvent({
78
86
  name: "tag_filter_state_changed",
79
87
  tag: tag,
80
88
  from_state: fromState,
@@ -84,7 +92,7 @@ export async function tagStateChanged({
84
92
  });
85
93
  }
86
94
 
87
- export async function trackUtm({
95
+ export function trackUtm({
88
96
  utm_source,
89
97
  utm_medium,
90
98
  utm_campaign
@@ -93,7 +101,7 @@ export async function trackUtm({
93
101
  utm_medium: string;
94
102
  utm_campaign: string;
95
103
  }) {
96
- await api.trackEvent({
104
+ api.trackEvent({
97
105
  name: "user_utm",
98
106
  utm_source: utm_source,
99
107
  utm_medium: utm_medium,