@vrplatform/log 2.0.0-alpha.4 → 2.0.0-alpha.40

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.
Files changed (82) hide show
  1. package/build/main/log/baselog.d.ts +0 -1
  2. package/build/main/log/baselog.js +1 -16
  3. package/build/main/log/baselog.js.map +1 -1
  4. package/build/main/log/common.d.ts +1 -10
  5. package/build/main/log/common.js +3 -13
  6. package/build/main/log/common.js.map +1 -1
  7. package/build/main/log/index.d.ts +2 -2
  8. package/build/main/log/index.js +7 -6
  9. package/build/main/log/index.js.map +1 -1
  10. package/build/main/log/type.d.ts +18 -0
  11. package/build/main/log/type.js +12 -0
  12. package/build/main/log/type.js.map +1 -1
  13. package/build/main/tracking/_intercom.d.ts +109 -0
  14. package/build/main/tracking/_intercom.js +139 -0
  15. package/build/main/tracking/_intercom.js.map +1 -0
  16. package/build/main/tracking/index.d.ts +102 -48
  17. package/build/main/tracking/index.js +183 -69
  18. package/build/main/tracking/index.js.map +1 -1
  19. package/build/main/tracking/intercom.d.ts +2 -1
  20. package/build/main/tracking/intercom.js.map +1 -1
  21. package/build/main/tracking/types.d.ts +87 -0
  22. package/build/main/tracking/types.js +3 -0
  23. package/build/main/tracking/types.js.map +1 -0
  24. package/build/main/utils/convertKeysToSnakeCase.d.ts +1 -0
  25. package/build/main/utils/convertKeysToSnakeCase.js +23 -0
  26. package/build/main/utils/convertKeysToSnakeCase.js.map +1 -0
  27. package/build/main/utils/convertValuesToString.d.ts +5 -0
  28. package/build/main/utils/convertValuesToString.js +11 -0
  29. package/build/main/utils/convertValuesToString.js.map +1 -0
  30. package/build/main/utils/index.d.ts +3 -0
  31. package/build/main/utils/index.js +20 -0
  32. package/build/main/utils/index.js.map +1 -0
  33. package/build/main/utils/isTest.d.ts +1 -0
  34. package/build/main/utils/isTest.js +18 -0
  35. package/build/main/utils/isTest.js.map +1 -0
  36. package/build/module/log/baselog.d.ts +0 -1
  37. package/build/module/log/baselog.js +1 -2
  38. package/build/module/log/baselog.js.map +1 -1
  39. package/build/module/log/common.d.ts +1 -10
  40. package/build/module/log/common.js +1 -11
  41. package/build/module/log/common.js.map +1 -1
  42. package/build/module/log/index.d.ts +2 -2
  43. package/build/module/log/index.js +2 -1
  44. package/build/module/log/index.js.map +1 -1
  45. package/build/module/log/type.d.ts +18 -0
  46. package/build/module/log/type.js +11 -1
  47. package/build/module/log/type.js.map +1 -1
  48. package/build/module/tracking/_intercom.d.ts +109 -0
  49. package/build/module/tracking/_intercom.js +136 -0
  50. package/build/module/tracking/_intercom.js.map +1 -0
  51. package/build/module/tracking/index.d.ts +102 -48
  52. package/build/module/tracking/index.js +167 -67
  53. package/build/module/tracking/index.js.map +1 -1
  54. package/build/module/tracking/intercom.d.ts +2 -1
  55. package/build/module/tracking/intercom.js.map +1 -1
  56. package/build/module/tracking/types.d.ts +87 -0
  57. package/build/module/tracking/types.js +2 -0
  58. package/build/module/tracking/types.js.map +1 -0
  59. package/build/module/utils/convertKeysToSnakeCase.d.ts +1 -0
  60. package/build/module/utils/convertKeysToSnakeCase.js +19 -0
  61. package/build/module/utils/convertKeysToSnakeCase.js.map +1 -0
  62. package/build/module/utils/convertValuesToString.d.ts +5 -0
  63. package/build/module/utils/convertValuesToString.js +8 -0
  64. package/build/module/utils/convertValuesToString.js.map +1 -0
  65. package/build/module/utils/index.d.ts +3 -0
  66. package/build/module/utils/index.js +4 -0
  67. package/build/module/utils/index.js.map +1 -0
  68. package/build/module/utils/isTest.d.ts +1 -0
  69. package/build/module/utils/isTest.js +14 -0
  70. package/build/module/utils/isTest.js.map +1 -0
  71. package/package.json +2 -1
  72. package/src/log/baselog.ts +2 -3
  73. package/src/log/common.ts +1 -14
  74. package/src/log/index.ts +6 -6
  75. package/src/log/type.ts +23 -0
  76. package/src/tracking/{intercom.ts → _intercom.ts} +2 -1
  77. package/src/tracking/index.ts +326 -106
  78. package/src/tracking/types.ts +181 -0
  79. package/src/utils/convertKeysToSnakeCase.ts +21 -0
  80. package/src/utils/convertValuesToString.ts +10 -0
  81. package/src/utils/index.ts +3 -0
  82. package/src/utils/isTest.ts +16 -0
@@ -1,56 +1,152 @@
1
+ declare module 'intercom-client' {
2
+ export namespace Intercom {
3
+ export interface CreateContactRequestWithExternalId {
4
+ /** A unique identifier for the contact which is given to Intercom */
5
+ external_id: string;
6
+ /** The contacts phone */
7
+ phone?: string;
8
+ /** The contacts name */
9
+ name?: string;
10
+ /** An image URL containing the avatar of a contact */
11
+ avatar?: string;
12
+ /** The time specified for when a contact signed up */
13
+ signed_up_at?: number;
14
+ /** The time when the contact was last seen (either where the Intercom Messenger was installed or when specified manually) */
15
+ last_seen_at?: number;
16
+ /** The id of an admin that has been assigned account ownership of the contact */
17
+ owner_id?: number;
18
+ /** Whether the contact is unsubscribed from emails */
19
+ unsubscribed_from_emails?: boolean;
20
+ /** The custom attributes which are set for the contact */
21
+ custom_attributes?: ContactCustomAttributes;
22
+ }
23
+ interface UpdateContactRequest {
24
+ /** The role of the contact. */
25
+ role?: 'user' | 'lead';
26
+ /** A unique identifier for the contact which is given to Intercom */
27
+ external_id?: string;
28
+ /** The contacts email */
29
+ email?: string;
30
+ /** The contacts phone */
31
+ phone?: string;
32
+ /** The contacts name */
33
+ name?: string;
34
+ /** An image URL containing the avatar of a contact */
35
+ avatar?: string;
36
+ /** The time specified for when a contact signed up */
37
+ signed_up_at?: number;
38
+ /** The time when the contact was last seen (either where the Intercom Messenger was installed or when specified manually) */
39
+ last_seen_at?: number;
40
+ /** The id of an admin that has been assigned account ownership of the contact */
41
+ owner_id?: number;
42
+ /** Whether the contact is unsubscribed from emails */
43
+ unsubscribed_from_emails?: boolean;
44
+ /** The custom attributes which are set for the contact */
45
+ custom_attributes?: ContactCustomAttributes;
46
+ }
47
+ interface ContactCustomAttributes {
48
+ Onboarding_Support?: string; // The customer's preferred onboarding level
49
+ userType?: string; // User Type (user or owner)
50
+ // ARCHIVED
51
+ // article_id?: string; // undefined
52
+ // workflowInstanceId?: number; // undefined
53
+ // Active_Listings?: string; // The number of active listings a user has
54
+ // Accounting_Software?: string; // The client's accounting software
55
+ }
56
+ interface CreateOrUpdateCompanyRequest {
57
+ /** The name of the Company */
58
+ name?: string;
59
+ /** The company id you have defined for the company. Can't be updated */
60
+ company_id?: string;
61
+ /** The name of the plan you have associated with the company. */
62
+ plan?: string;
63
+ /** The number of employees in this company. */
64
+ size?: number;
65
+ /** The URL for this company's website. Please note that the value specified here is not validated. Accepts any string. */
66
+ website?: string;
67
+ /** The industry that this company operates in. */
68
+ industry?: string;
69
+ /** A hash of key/value pairs containing any other data about the company you want Intercom to store. */
70
+ custom_attributes?: CompanyCustomAttributes;
71
+ /** The time the company was created by you. */
72
+ remote_created_at?: number;
73
+ /** How much revenue the company generates for your business. Note that this will truncate floats. i.e. it only allow for whole integers, 155.98 will be truncated to 155. Note that this has an upper limit of 2\*\*31-1 or 2147483647.. */
74
+ monthly_spend?: number;
75
+ }
76
+ interface CompanyCustomAttributes {
77
+ teamId?: string; // undefined
78
+ team?: string; // undefined
79
+ type?: string; // undefined
80
+ status?: string; // undefined
81
+ pms?: string; // undefined
82
+ accountingSoftware?: string; // Accounting software used by the team.
83
+ creation_source?: string; // undefined
84
+ activeListings?: number; // Active Listings
85
+ paymentMethodType?: string; // Payment Method
86
+ partnerName?: string; // Partner Name
87
+ billingPortalUrl?: string; // Billing Portal URL
88
+ billingStatus?: string; // undefined
89
+ billingPartner?: string; // Name of billing partner
90
+ // ARCHIVED
91
+ // firstName?: string; // undefined
92
+ // lastName?: string; // undefined
93
+ // email?: string; // undefined
94
+ // apps?: string; // All active connections besides pms/accounting
95
+ // accountingPartner?: string; // Name of accounting partner
96
+ // 'SaaS User'?: boolean; // undefined
97
+ }
98
+ }
99
+ }
100
+
1
101
  import { Analytics } from '@june-so/analytics-node';
102
+ import { Intercom, IntercomClient } from 'intercom-client';
103
+ import { fetcher } from 'intercom-client/core/fetcher/Fetcher';
2
104
  import { PostHog } from 'posthog-node';
3
- import { useLog } from '../log';
4
- import { useIntercom } from './intercom';
5
-
6
- const E2E_TEST_USERS = [
7
- '9e7dfc88-503c-4222-9905-9116169d2203', // lars+checkly@finalytic.co
8
- '113d73d8-ee21-46b7-a12a-a74f632401ca', // e2e-invite-member@finalytic.io
9
- '917b7c4e-cb03-491c-9e94-d33a5bdeca05', // e2e-invite-owner@finalytic.io
10
- 'ec8e5572-74d0-4ae6-af73-bca8db9a27e9', // e2e-sign-up@finalytic.io
11
- ];
12
- const E2E_TEST_TEAMS = [
13
- 'c4fd21b4-8447-43a2-bdcb-f06a85a935ad', // VRP Automated Testing
14
- '8f21060e-afe6-410a-b2f4-00a3caa20786', // test_company_xxxx
15
- ];
16
-
17
- const isTest = (userId: string, groupId?: string) =>
18
- E2E_TEST_USERS.includes(userId) ||
19
- (groupId && E2E_TEST_TEAMS.includes(groupId));
20
-
21
- export type TrackingProps = {
22
- name: string;
23
- dataset: string;
24
- env: {
25
- INTERCOM_TOKEN: string;
26
- JUNESO_ANALYTICS_WRITE_KEY: string;
27
- POSTHOG_API_KEY: string;
28
- };
29
- };
30
- export type Tracking = ReturnType<typeof useTracking>;
105
+ import { type WorkerLog, useLog } from '../log';
106
+ import { convertKeysToSnakeCase, isTest } from '../utils';
107
+ import { convertValuesToString } from '../utils/convertValuesToString';
108
+ import type {
109
+ GroupProps,
110
+ IdentifyProps,
111
+ TrackProps,
112
+ TrackingProps,
113
+ } from './types';
31
114
 
32
- type OptionalUser<T> = T &
33
- (
34
- | { userId: string; anonymousId?: string }
35
- | {
36
- userId?: string;
37
- anonymousId: string;
38
- }
39
- );
115
+ export * from './types';
116
+ export * from 'intercom-client';
117
+
118
+ export type Tracking = ReturnType<typeof useTracking>;
40
119
 
41
120
  export const useTracking = (
42
121
  { dataset, env, name }: TrackingProps,
43
122
  isDev?: boolean
44
- ) => {
45
- const axiom = useLog({ name, dataset, env });
123
+ ): {
124
+ track: (props: TrackProps) => Promise<void>;
125
+ identify: (props: IdentifyProps) => Promise<void>;
126
+ group: (props: GroupProps) => Promise<void>;
127
+ shutdown: () => Promise<any>;
128
+ log: WorkerLog;
129
+ june?: Analytics;
130
+ intercom?: IntercomClient;
131
+ posthog?: PostHog;
132
+ } => {
133
+ const log = useLog({ name, dataset, env });
134
+
46
135
  const intercom = env.INTERCOM_TOKEN
47
- ? useIntercom(env.INTERCOM_TOKEN, axiom)
48
- : undefined;
49
- const juneso = env.JUNESO_ANALYTICS_WRITE_KEY
50
- ? new Analytics(env.JUNESO_ANALYTICS_WRITE_KEY)
136
+ ? new IntercomClient({
137
+ token: env.INTERCOM_TOKEN,
138
+ fetcher: (args) =>
139
+ fetcher({
140
+ ...args,
141
+ headers: { ...args.headers, accept: 'application/json' },
142
+ }),
143
+ })
51
144
  : undefined;
52
- const posthog = env.POSTHOG_API_KEY
53
- ? new PostHog(env.POSTHOG_API_KEY, {
145
+
146
+ const june = env.JUNESO_TOKEN ? new Analytics(env.JUNESO_TOKEN) : undefined;
147
+
148
+ const posthog = env.POSTHOG_TOKEN
149
+ ? new PostHog(env.POSTHOG_TOKEN, {
54
150
  host: 'https://app.posthog.com',
55
151
  })
56
152
  : undefined;
@@ -59,94 +155,218 @@ export const useTracking = (
59
155
  // General
60
156
  track: async ({
61
157
  userId,
158
+ anonymousId,
62
159
  groupId,
63
160
  event,
64
161
  properties,
65
- }: {
66
- userId: string;
67
- groupId: string;
68
- event: string;
69
- properties: Record<string, any>;
70
- }) => {
71
- if (isDev || isTest(userId, groupId)) return;
72
-
73
- posthog?.capture({
74
- distinctId: userId,
75
- event,
76
- groups: {
77
- tenant: groupId,
78
- },
79
- properties,
80
- });
81
- juneso?.track({
82
- userId,
83
- event,
84
- properties,
85
- context: { groupId },
86
- });
162
+ timestamp,
163
+ }: TrackProps) => {
164
+ if (isDev || isTest(userId || anonymousId || '', groupId)) return;
87
165
 
88
- try {
89
- await intercom?.trackEvent({
90
- user_id: userId,
91
- event_name: event,
92
- metadata: properties,
166
+ if (anonymousId) {
167
+ posthog?.capture({
168
+ distinctId: anonymousId,
169
+ event,
170
+ groups: {
171
+ tenant: groupId,
172
+ },
173
+ timestamp,
174
+ properties: convertKeysToSnakeCase(properties),
93
175
  });
94
- } catch (error: any) {
95
- console.error(error);
176
+
177
+ june?.track(
178
+ {
179
+ anonymousId,
180
+ event,
181
+ properties,
182
+ timestamp,
183
+ context: { groupId },
184
+ },
185
+ (err) => {
186
+ if (err) console.error(err);
187
+ }
188
+ );
189
+
190
+ // no intercom for anonymous
191
+ } else if (userId) {
192
+ posthog?.capture({
193
+ distinctId: userId,
194
+ event,
195
+ groups: {
196
+ tenant: groupId,
197
+ },
198
+ timestamp,
199
+ properties: convertKeysToSnakeCase(properties),
200
+ });
201
+
202
+ june?.track(
203
+ {
204
+ userId,
205
+ event,
206
+ properties,
207
+ timestamp,
208
+ context: { groupId },
209
+ },
210
+ (err) => {
211
+ if (err) console.error(err);
212
+ }
213
+ );
214
+
215
+ const intercomUserId = (
216
+ await intercom?.contacts.search({
217
+ query: {
218
+ field: 'external_id',
219
+ operator: Intercom.SingleFilterSearchRequestOperator.Equals,
220
+ value: userId,
221
+ },
222
+ })
223
+ )?.data.at(0)?.id;
224
+ if (intercomUserId)
225
+ await intercom?.events.create({
226
+ user_id: intercomUserId,
227
+ event_name: event,
228
+ metadata: convertValuesToString(properties),
229
+ created_at: timestamp ? timestamp.getTime() : Date.now(),
230
+ });
96
231
  }
97
232
  },
98
- identify: ({
233
+ identify: async ({
99
234
  traits,
100
235
  userId,
101
236
  disableGeoip,
102
- }: {
103
- userId: string;
104
- traits: Record<string, any>;
105
- disableGeoip?: boolean;
106
- }) => {
237
+ timestamp,
238
+ }: IdentifyProps) => {
107
239
  if (isDev || isTest(userId)) return;
108
240
 
109
241
  posthog?.identify({
110
242
  distinctId: userId,
111
- properties: traits,
243
+ properties: convertKeysToSnakeCase(traits),
112
244
  disableGeoip,
113
245
  });
114
- juneso?.identify({
115
- userId,
116
- traits,
117
- });
246
+
247
+ june?.identify(
248
+ {
249
+ userId,
250
+ traits,
251
+ timestamp,
252
+ },
253
+ (err) => (err ? console.error(err) : {})
254
+ );
255
+
256
+ // upsert intercom user
257
+ const data = {
258
+ external_id: userId,
259
+ email: traits?.email,
260
+ name:
261
+ traits?.name ||
262
+ (traits?.firstName
263
+ ? `${traits.firstName} ${traits.lastName}`
264
+ : traits?.lastName),
265
+ avatar: traits?.avatar,
266
+ signed_up_at: traits?.createdAt
267
+ ? new Date(traits.createdAt).getTime() / 1000
268
+ : undefined,
269
+ last_seen_at: new Date().getTime() / 1000,
270
+ custom_attributes: { userType: traits?.role },
271
+ };
272
+
273
+ const intercomUser = (
274
+ await intercom?.contacts.search({
275
+ query: {
276
+ field: 'external_id',
277
+ operator: Intercom.SingleFilterSearchRequestOperator.Equals,
278
+ value: userId,
279
+ },
280
+ })
281
+ )?.data.at(0);
282
+ if (intercomUser?.id)
283
+ await intercom?.contacts.update(intercomUser?.id, data);
284
+ else await intercom?.contacts.create(data);
118
285
  },
119
- group: ({
286
+ group: async ({
120
287
  traits,
121
288
  groupId,
122
289
  userId,
123
290
  anonymousId,
124
- }: OptionalUser<{
125
- groupId: string;
126
- traits?: Record<string, any>;
127
- }>) => {
291
+ timestamp,
292
+ }: GroupProps) => {
128
293
  if (isDev || isTest(userId || anonymousId || '', groupId)) return;
129
294
 
130
- posthog?.groupIdentify({
131
- groupKey: groupId,
132
- groupType: 'tenant',
133
- properties: traits,
134
- distinctId: userId,
295
+ const cid = traits?.billingCustomerId || traits?.hyperlineCustomerId;
296
+ const intercomCompany = await intercom?.companies.create({
297
+ name: traits?.name,
298
+ company_id: groupId,
299
+ // plan: string;
300
+ remote_created_at: traits?.createdAt
301
+ ? new Date(traits.createdAt).getTime() / 1000
302
+ : undefined,
303
+ // monthly_spend: number;
304
+ custom_attributes: {
305
+ teamId: groupId,
306
+ team: traits?.name,
307
+ type: traits?.type,
308
+ status: traits?.status,
309
+ pms: traits?.pms,
310
+ accountingSoftware: traits?.accountingSoftware,
311
+ activeListings: traits?.activeListings,
312
+ // paymentMethodType: string; // Payment Method
313
+ partnerName: traits?.partner || traits?.accountingPartner,
314
+ billingPortalUrl: cid
315
+ ? `https://billing.vrplatform.app/portal/${cid}`
316
+ : undefined,
317
+ billingStatus: traits?.billingSubscriptionStatus,
318
+ billingPartner:
319
+ traits?.billingPartner ||
320
+ traits?.partner ||
321
+ traits?.accountingPartner,
322
+ },
135
323
  });
136
- if (anonymousId) juneso?.group({ anonymousId, groupId, traits });
137
- else if (userId) juneso?.group({ userId, groupId, traits });
324
+
325
+ if (anonymousId) {
326
+ posthog?.groupIdentify({
327
+ groupKey: groupId,
328
+ groupType: 'tenant',
329
+ properties: convertKeysToSnakeCase(traits),
330
+ distinctId: anonymousId,
331
+ });
332
+
333
+ june?.group({ anonymousId, groupId, traits, timestamp }, (err) =>
334
+ err ? console.error(err) : {}
335
+ );
336
+ } else if (userId) {
337
+ posthog?.groupIdentify({
338
+ groupKey: groupId,
339
+ groupType: 'tenant',
340
+ properties: convertKeysToSnakeCase(traits),
341
+ distinctId: userId,
342
+ });
343
+
344
+ june?.group({ userId, groupId, traits, timestamp }, (err) =>
345
+ err ? console.error(err) : {}
346
+ );
347
+
348
+ // attach intercom user to intercom company
349
+ const intercomUser = (
350
+ await intercom?.contacts.search({
351
+ query: {
352
+ field: 'external_id',
353
+ operator: Intercom.SingleFilterSearchRequestOperator.Equals,
354
+ value: userId,
355
+ },
356
+ })
357
+ )?.data.at(0);
358
+ if (intercomUser?.id && intercomCompany?.id)
359
+ intercom?.companies.attachContact(intercomUser?.id, {
360
+ id: intercomCompany?.id,
361
+ });
362
+ }
138
363
  },
139
364
  shutdown: async () =>
140
- Promise.all([
141
- posthog?.shutdown(),
142
- juneso?.closeAndFlush(),
143
- axiom.flush(),
144
- ]),
145
- // Posthog specific
146
- alias: posthog?.alias,
147
- isFeatureEnabled: posthog?.isFeatureEnabled,
148
- // export intercom and axiom
365
+ Promise.all([posthog?.shutdown(), june?.closeAndFlush(), log?.flush()]),
366
+ // export dependencies
149
367
  intercom,
150
- log: axiom,
368
+ posthog,
369
+ june,
370
+ log,
151
371
  };
152
372
  };
@@ -0,0 +1,181 @@
1
+ import type { LogBindings } from '../log';
2
+
3
+ type AuthEvent =
4
+ | 'account_signin_completed'
5
+ | 'account_signup_code_requested'
6
+ | 'account_signup_code_completed'
7
+ | 'account_signup_code_failed'
8
+ | 'account_signup_completed'
9
+ | 'account_password_reset_requested'
10
+ | 'account_password_reset_failed'
11
+ | 'account_password_reset_completed'
12
+ | 'account_invitation_accepted'
13
+ | 'account_signed_out';
14
+
15
+ type TeamEvent =
16
+ | 'team_added'
17
+ | 'team_info_updated'
18
+ | 'team_deleted'
19
+ | 'team_member_removed';
20
+
21
+ type ConnectionEvent =
22
+ | 'connection_created'
23
+ | 'connection_reconnected'
24
+ | 'connection_deleted'
25
+ | 'connection_requested';
26
+
27
+ type OwnershipEvent =
28
+ | 'ownership_created'
29
+ | 'ownership_updated'
30
+ | 'ownership_deleted';
31
+
32
+ type OwnerEvent =
33
+ | 'owner_created'
34
+ | 'owner_updated'
35
+ | 'owner_deleted'
36
+ | 'owner_tax_info_modal_opened'
37
+ | 'owner_tax_info_modal_submitted';
38
+
39
+ type SetupEvent =
40
+ | 'setup_classes_set'
41
+ | 'setup_accounting_version_completed'
42
+ | 'setup_accounting_config_completed'
43
+ | 'setup_owner_imported'
44
+ | 'setup_listing_imported';
45
+
46
+ type AutomationEvent =
47
+ | 'automation_created'
48
+ | 'automation_updated'
49
+ | 'automation_deleted';
50
+
51
+ type TaxStatementEvent =
52
+ | 'tax_statement_preview_opened'
53
+ | 'tax_statement_downloaded';
54
+
55
+ type GLOwnerStatementEvent =
56
+ | 'gl_owner_statement_preview_opened'
57
+ | 'gl_owner_statement_downloaded';
58
+
59
+ type HyperlineEvent =
60
+ | 'hyperline_invoice_ready'
61
+ | 'hyperline_invoice_settled'
62
+ | 'hyperline_trial_started'
63
+ | 'hyperline_trial_ended'
64
+ | 'hyperline_subscription_activated'
65
+ | 'hyperline_subscription_cancelled'
66
+ | 'hyperline_subscription_created'
67
+ | 'hyperline_subscription_errored'
68
+ | 'hyperline_subscription_paused'
69
+ | 'hyperline_subscription_voided'
70
+ | 'hyperline_subscription_charged'
71
+ | 'hyperline_customer_created'
72
+ | 'hyperline_customer_updated'
73
+ | 'hyperline_payment_method_created'
74
+ | 'hyperline_payment_method_errored'
75
+ | 'hyperline_payment_method_deleted';
76
+
77
+ type ListingEvent = 'listing_activated' | 'listing_deactivated';
78
+
79
+ type ReportEvent = 'listings_reported';
80
+
81
+ type UserEvent = 'update_refresh_accepted' | 'owner_statement_opened';
82
+
83
+ type TestEvent = 'test_event' | 'test_error';
84
+
85
+ export type TrackingEvent =
86
+ | AuthEvent
87
+ | TeamEvent
88
+ | ConnectionEvent
89
+ | OwnershipEvent
90
+ | OwnerEvent
91
+ | SetupEvent
92
+ | AutomationEvent
93
+ | TaxStatementEvent
94
+ | GLOwnerStatementEvent
95
+ | HyperlineEvent
96
+ | UserEvent
97
+ | ListingEvent
98
+ | ReportEvent
99
+ | TestEvent;
100
+
101
+ export type TrackingProps = {
102
+ name: string;
103
+ dataset: string;
104
+ env: {
105
+ INTERCOM_TOKEN?: string;
106
+ JUNESO_TOKEN?: string;
107
+ POSTHOG_TOKEN?: string;
108
+ } & LogBindings;
109
+ debugging?: boolean;
110
+ };
111
+
112
+ export type TrackProps = OptionalUser<{
113
+ groupId: string;
114
+ event: TrackingEvent;
115
+ properties: Record<string, string | number | boolean | null | undefined>;
116
+ timestamp?: Date;
117
+ }>;
118
+ export type IdentifyProps = {
119
+ userId: string;
120
+ traits?: {
121
+ id?: string;
122
+ email?: string;
123
+ avatar?: string;
124
+ name?: string;
125
+ firstName?: string;
126
+ lastName?: string;
127
+ createdAt?: string;
128
+ country?: string;
129
+ isSuperAdmin?: boolean;
130
+ isVrpAdmin?: boolean;
131
+ isPartnerAdmin?: boolean;
132
+ isTeamAdmin?: boolean;
133
+ role?: UserRole;
134
+ [key: string]: string | number | boolean | null | undefined;
135
+ };
136
+ disableGeoip?: boolean;
137
+ timestamp?: Date;
138
+ };
139
+ export type GroupProps = OptionalUser<{
140
+ groupId: string;
141
+ traits?: {
142
+ name?: string;
143
+ type?: TenantType;
144
+ avatar?: string;
145
+ createdAt?: string;
146
+ partner?: string;
147
+ partnerId?: string;
148
+ billingCustomerId?: string;
149
+ billingSubscriptionStatus?: string; // todo: update type as enum
150
+ status?: TenantStatus;
151
+ isOnboarding?: boolean;
152
+ accountingPartner?: string;
153
+ billingPartner?: string;
154
+ pms?: string;
155
+ apps?: string;
156
+ accountingSoftware?: string;
157
+ activeListings?: number;
158
+ [key: string]: string | number | boolean | null | undefined;
159
+ };
160
+ timestamp?: Date;
161
+ }>;
162
+
163
+ export type UserRole =
164
+ | 'super-admin'
165
+ | 'vrp-admin'
166
+ | 'partner-admin'
167
+ | 'team-admin'
168
+ | 'admin'
169
+ | 'owner'
170
+ | 'user';
171
+ export type TenantType = 'admin' | 'partner' | 'propertyManager';
172
+ export type TenantStatus = 'active' | 'inactive';
173
+
174
+ type OptionalUser<T> = T &
175
+ (
176
+ | { userId: string; anonymousId?: string }
177
+ | {
178
+ userId?: string;
179
+ anonymousId: string;
180
+ }
181
+ );
@@ -0,0 +1,21 @@
1
+ export const convertKeysToSnakeCase = (obj?: Record<string, any>) => {
2
+ const result: Record<string, any> = {};
3
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
4
+
5
+ for (const key in obj) {
6
+ if (hasOwnProperty.call(obj, key)) {
7
+ const snakeKey = key.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();
8
+ if (
9
+ typeof obj[key] === 'object' &&
10
+ !Array.isArray(obj[key]) &&
11
+ obj[key] !== null
12
+ ) {
13
+ result[snakeKey] = convertKeysToSnakeCase(obj[key]);
14
+ } else {
15
+ result[snakeKey] = obj[key];
16
+ }
17
+ }
18
+ }
19
+
20
+ return result;
21
+ };
@@ -0,0 +1,10 @@
1
+ export function convertValuesToString(obj: { [key: string]: any }): {
2
+ [key: string]: string;
3
+ } {
4
+ const result: { [key: string]: string } = {};
5
+
6
+ for (const key of Object.keys(obj))
7
+ if (obj[key] !== undefined) result[key] = obj[key].toString();
8
+
9
+ return result;
10
+ }
@@ -0,0 +1,3 @@
1
+ export * from './convertKeysToSnakeCase';
2
+ export * from './convertValuesToString';
3
+ export * from './isTest';