@vrplatform/log 2.0.0-alpha.9 → 2.0.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.
Files changed (94) 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/index.spec.d.ts +0 -0
  11. package/build/main/log/index.spec.js +2 -0
  12. package/build/main/log/index.spec.js.map +1 -0
  13. package/build/main/log/type.d.ts +21 -1
  14. package/build/main/log/type.js +12 -0
  15. package/build/main/log/type.js.map +1 -1
  16. package/build/main/tracking/_intercom.d.ts +109 -0
  17. package/build/main/tracking/_intercom.js +139 -0
  18. package/build/main/tracking/_intercom.js.map +1 -0
  19. package/build/main/tracking/eventTypes.d.ts +16 -0
  20. package/build/main/tracking/eventTypes.js +3 -0
  21. package/build/main/tracking/eventTypes.js.map +1 -0
  22. package/build/main/tracking/index.d.ts +106 -55
  23. package/build/main/tracking/index.js +180 -74
  24. package/build/main/tracking/index.js.map +1 -1
  25. package/build/main/tracking/intercom.d.ts +2 -1
  26. package/build/main/tracking/intercom.js.map +1 -1
  27. package/build/main/tracking/types.d.ts +509 -0
  28. package/build/main/tracking/types.js +3 -0
  29. package/build/main/tracking/types.js.map +1 -0
  30. package/build/main/utils/convertKeysToSnakeCase.d.ts +1 -0
  31. package/build/main/utils/convertKeysToSnakeCase.js +23 -0
  32. package/build/main/utils/convertKeysToSnakeCase.js.map +1 -0
  33. package/build/main/utils/convertValuesToString.d.ts +5 -0
  34. package/build/main/utils/convertValuesToString.js +11 -0
  35. package/build/main/utils/convertValuesToString.js.map +1 -0
  36. package/build/main/utils/index.d.ts +3 -0
  37. package/build/main/utils/index.js +20 -0
  38. package/build/main/utils/index.js.map +1 -0
  39. package/build/main/utils/isTest.d.ts +1 -0
  40. package/build/main/utils/isTest.js +18 -0
  41. package/build/main/utils/isTest.js.map +1 -0
  42. package/build/module/log/baselog.d.ts +0 -1
  43. package/build/module/log/baselog.js +1 -2
  44. package/build/module/log/baselog.js.map +1 -1
  45. package/build/module/log/common.d.ts +1 -10
  46. package/build/module/log/common.js +1 -11
  47. package/build/module/log/common.js.map +1 -1
  48. package/build/module/log/index.d.ts +2 -2
  49. package/build/module/log/index.js +2 -1
  50. package/build/module/log/index.js.map +1 -1
  51. package/build/module/log/index.spec.d.ts +0 -0
  52. package/build/module/log/index.spec.js +2 -0
  53. package/build/module/log/index.spec.js.map +1 -0
  54. package/build/module/log/type.d.ts +21 -1
  55. package/build/module/log/type.js +11 -1
  56. package/build/module/log/type.js.map +1 -1
  57. package/build/module/tracking/_intercom.d.ts +109 -0
  58. package/build/module/tracking/_intercom.js +136 -0
  59. package/build/module/tracking/_intercom.js.map +1 -0
  60. package/build/module/tracking/eventTypes.d.ts +16 -0
  61. package/build/module/tracking/eventTypes.js +2 -0
  62. package/build/module/tracking/eventTypes.js.map +1 -0
  63. package/build/module/tracking/index.d.ts +106 -55
  64. package/build/module/tracking/index.js +164 -72
  65. package/build/module/tracking/index.js.map +1 -1
  66. package/build/module/tracking/intercom.d.ts +2 -1
  67. package/build/module/tracking/intercom.js.map +1 -1
  68. package/build/module/tracking/types.d.ts +509 -0
  69. package/build/module/tracking/types.js +2 -0
  70. package/build/module/tracking/types.js.map +1 -0
  71. package/build/module/utils/convertKeysToSnakeCase.d.ts +1 -0
  72. package/build/module/utils/convertKeysToSnakeCase.js +19 -0
  73. package/build/module/utils/convertKeysToSnakeCase.js.map +1 -0
  74. package/build/module/utils/convertValuesToString.d.ts +5 -0
  75. package/build/module/utils/convertValuesToString.js +8 -0
  76. package/build/module/utils/convertValuesToString.js.map +1 -0
  77. package/build/module/utils/index.d.ts +3 -0
  78. package/build/module/utils/index.js +4 -0
  79. package/build/module/utils/index.js.map +1 -0
  80. package/build/module/utils/isTest.d.ts +1 -0
  81. package/build/module/utils/isTest.js +14 -0
  82. package/build/module/utils/isTest.js.map +1 -0
  83. package/package.json +22 -23
  84. package/src/log/baselog.ts +2 -3
  85. package/src/log/common.ts +1 -14
  86. package/src/log/index.ts +6 -6
  87. package/src/log/type.ts +28 -1
  88. package/src/tracking/index.ts +322 -167
  89. package/src/tracking/types.ts +622 -0
  90. package/src/utils/convertKeysToSnakeCase.ts +21 -0
  91. package/src/utils/convertValuesToString.ts +10 -0
  92. package/src/utils/index.ts +3 -0
  93. package/src/utils/isTest.ts +16 -0
  94. package/src/tracking/intercom.ts +0 -257
package/src/log/common.ts CHANGED
@@ -1,17 +1,4 @@
1
- import type { RequestLike } from './type';
2
-
3
- // Headers
4
- export const CONNECTION_ID_HEADER = 'X-Connection-ID';
5
- export const WORKFLOW_ID_HEADER = 'X-Workflow-ID';
6
- export const TASK_QUEUE_HEADER = 'X-Task-Queue';
7
- export const CORRELATION_ID_HEADER = 'X-Correlation-ID';
8
- export const VERIFICATION_HEADER = 'X-Verification-Key';
9
-
10
- // Env
11
- export const AXIOM_AUTH_TOKEN_ENV = 'AXIOM_AUTH_TOKEN';
12
- export const AXIOM_ORG_ID_ENV = 'AXIOM_ORG_ID';
13
- export const AXIOM_DATASET_ENV = 'AXIOM_DATASET';
14
- export const LOG_ENV = 'LOG';
1
+ import { CORRELATION_ID_HEADER, type RequestLike } from './type';
15
2
 
16
3
  export const requestHeadersToCapture = ['user-agent'];
17
4
 
package/src/log/index.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import { createBaseLog } from './baselog';
2
+ import { getCorrelationId, getEnvironment, requestToContext } from './common';
2
3
  import {
3
4
  AXIOM_AUTH_TOKEN_ENV,
4
5
  AXIOM_DATASET_ENV,
5
6
  AXIOM_ORG_ID_ENV,
6
7
  LOG_ENV,
8
+ type LogBindings,
9
+ type RequestLike,
7
10
  TASK_QUEUE_HEADER,
8
11
  WORKFLOW_ID_HEADER,
9
- getCorrelationId,
10
- getEnvironment,
11
- requestToContext,
12
- } from './common';
13
- import type { RequestLike, WorkerLog } from './type';
12
+ type WorkerLog,
13
+ } from './type';
14
14
 
15
15
  export * from './common';
16
16
  export * from './baselog';
@@ -37,7 +37,7 @@ export function useLog({
37
37
  correlationId?: string;
38
38
  version?: string;
39
39
  dataset?: string;
40
- env?: Record<string, any>;
40
+ env?: LogBindings;
41
41
  context?: Record<string, any>;
42
42
  executionContext?: {
43
43
  waitUntil(promise: Promise<any>): void;
package/src/log/type.ts CHANGED
@@ -1,12 +1,39 @@
1
+ // Headers
2
+ export const CONNECTION_ID_HEADER = 'X-Connection-ID';
3
+ export const WORKFLOW_ID_HEADER = 'X-Workflow-ID';
4
+ export const TASK_QUEUE_HEADER = 'X-Task-Queue';
5
+ export const CORRELATION_ID_HEADER = 'X-Correlation-ID';
6
+ export const VERIFICATION_HEADER = 'X-Verification-Key';
7
+
8
+ // Env
9
+ export const AXIOM_AUTH_TOKEN_ENV = 'AXIOM_AUTH_TOKEN';
10
+ export const AXIOM_ORG_ID_ENV = 'AXIOM_ORG_ID';
11
+ export const AXIOM_DATASET_ENV = 'AXIOM_DATASET';
12
+ export const LOG_ENV = 'LOG';
13
+
14
+ export type LogBindings = {
15
+ [LOG_ENV]?: string;
16
+ [AXIOM_AUTH_TOKEN_ENV]?: string;
17
+ [AXIOM_ORG_ID_ENV]?: string;
18
+ [AXIOM_DATASET_ENV]?: string;
19
+ NODE_ENV?: string;
20
+ IS_LOCAL_DEV?: string;
21
+ MACHINE_NAME?: string;
22
+ };
23
+
1
24
  export type LogFn = (
2
25
  message: any,
3
26
  additionalContext?: Record<string, any>
4
27
  ) => void;
5
- export type Log = {
28
+
29
+ export type LogFns = {
6
30
  error: LogFn;
7
31
  info: LogFn;
8
32
  debug: LogFn;
9
33
  warn: LogFn;
34
+ };
35
+
36
+ export type Log = LogFns & {
10
37
  child: (data: ChildLogOptions) => Log;
11
38
  addContext: (data: Record<string, any>) => void;
12
39
  };
@@ -1,112 +1,161 @@
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
- type AuthEvent =
22
- | 'account_signin_completed'
23
- | 'account_signed_out'
24
- | 'account_signup_code_requested'
25
- | 'account_signup_code_completed'
26
- | 'account_signup_code_failed'
27
- | 'account_password_reset_requested'
28
- | 'account_password_reset_failed'
29
- | 'account_password_reset_completed';
30
-
31
- type TeamEvent =
32
- | 'team_added'
33
- | 'team_info_updated'
34
- | 'team_deleted'
35
- | 'team_member_removed';
36
-
37
- type OwnerEvent =
38
- | 'owner_created'
39
- | 'owner_updated'
40
- | 'owner_deleted'
41
- | 'owner_tax_info_modal_opened'
42
- | 'owner_tax_info_modal_submitted';
43
-
44
- type OwnershipEvent =
45
- | 'ownership_created'
46
- | 'ownership_updated'
47
- | 'ownership_deleted';
48
-
49
- type ConnectionEvent =
50
- | 'connection_created'
51
- | 'connection_reconnected'
52
- | 'connection_deleted'
53
- | 'connection_requested';
54
-
55
- type AutomationEvent =
56
- | 'automation_created'
57
- | 'automation_updated'
58
- | 'automation_deleted';
59
-
60
- type TaxStatementEvent =
61
- | 'tax_statement_preview_opened'
62
- | 'tax_statement_downloaded';
63
-
64
- type GLOwnerStatementEvent =
65
- | 'gl_owner_statement_preview_opened'
66
- | 'gl_owner_statement_downloaded';
67
-
68
- type TestEvent = 'test_event';
69
-
70
- export type TrackingEvent =
71
- | AuthEvent
72
- | TeamEvent
73
- | OwnerEvent
74
- | OwnershipEvent
75
- | ConnectionEvent
76
- | AutomationEvent
77
- | TaxStatementEvent
78
- | GLOwnerStatementEvent
79
- | TestEvent;
80
-
81
- export type TrackingProps = {
105
+ import { type LogBindings, 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
+ TrackingEvent,
113
+ } from './types';
114
+
115
+ export * from './types';
116
+ export * from 'intercom-client';
117
+ export * from '../utils';
118
+
119
+ export type Tracking = ReturnType<typeof useTracking>;
120
+ export type UseTracking = {
82
121
  name: string;
83
122
  dataset: string;
84
123
  env: {
85
124
  INTERCOM_TOKEN?: string;
86
125
  JUNESO_TOKEN?: string;
87
126
  POSTHOG_TOKEN?: string;
88
- };
127
+ } & LogBindings;
128
+ debugging?: boolean;
89
129
  };
90
- export type Tracking = ReturnType<typeof useTracking>;
91
-
92
- type OptionalUser<T> = T &
93
- (
94
- | { userId: string; anonymousId?: string }
95
- | {
96
- userId?: string;
97
- anonymousId: string;
98
- }
99
- );
100
130
 
101
131
  export const useTracking = (
102
- { dataset, env, name }: TrackingProps,
132
+ { dataset, env, name }: UseTracking,
103
133
  isDev?: boolean
104
- ) => {
105
- const axiom = useLog({ name, dataset, env });
134
+ ): {
135
+ track: <T extends TrackingEvent>(props: TrackProps<T>) => Promise<void>;
136
+ identify: (props: IdentifyProps) => Promise<void>;
137
+ group: (props: GroupProps) => Promise<void>;
138
+ shutdown: () => Promise<any>;
139
+ log: WorkerLog;
140
+ june?: Analytics;
141
+ intercom?: IntercomClient;
142
+ posthog?: PostHog;
143
+ } => {
144
+ const log = useLog({ name, dataset, env });
145
+
106
146
  const intercom = env.INTERCOM_TOKEN
107
- ? useIntercom(env.INTERCOM_TOKEN, axiom)
147
+ ? new IntercomClient({
148
+ token: env.INTERCOM_TOKEN,
149
+ fetcher: (args) =>
150
+ fetcher({
151
+ ...args,
152
+ headers: { ...args.headers, accept: 'application/json' },
153
+ }),
154
+ })
108
155
  : undefined;
109
- const juneso = env.JUNESO_TOKEN ? new Analytics(env.JUNESO_TOKEN) : undefined;
156
+
157
+ const june = env.JUNESO_TOKEN ? new Analytics(env.JUNESO_TOKEN) : undefined;
158
+
110
159
  const posthog = env.POSTHOG_TOKEN
111
160
  ? new PostHog(env.POSTHOG_TOKEN, {
112
161
  host: 'https://app.posthog.com',
@@ -115,114 +164,220 @@ export const useTracking = (
115
164
 
116
165
  return {
117
166
  // General
118
- track: async ({
167
+ track: async <T extends TrackingEvent>({
119
168
  userId,
169
+ anonymousId,
120
170
  groupId,
121
171
  event,
122
172
  properties,
123
- }: {
124
- userId: string;
125
- groupId: string;
126
- event: TrackingEvent;
127
- properties: Record<string, any>;
128
- }) => {
129
- if (isDev || isTest(userId, groupId)) return;
130
-
131
- posthog?.capture({
132
- distinctId: userId,
133
- event,
134
- groups: {
135
- tenant: groupId,
136
- },
137
- properties,
138
- });
139
- juneso?.track(
140
- {
141
- userId,
173
+ timestamp,
174
+ }: TrackProps<T>) => {
175
+ if (isDev || isTest(userId || anonymousId || '', groupId)) return;
176
+
177
+ if (anonymousId) {
178
+ posthog?.capture({
179
+ distinctId: anonymousId,
142
180
  event,
143
- properties,
144
- context: { groupId },
145
- },
146
- (err) => {
147
- if (err) console.error(err);
148
- }
149
- );
181
+ groups: {
182
+ tenant: groupId,
183
+ },
184
+ timestamp,
185
+ properties: convertKeysToSnakeCase(properties),
186
+ });
150
187
 
151
- try {
152
- await intercom?.trackEvent({
153
- user_id: userId,
154
- event_name: event,
155
- metadata: properties,
188
+ june?.track(
189
+ {
190
+ anonymousId,
191
+ event,
192
+ properties,
193
+ timestamp,
194
+ context: { groupId },
195
+ },
196
+ (err) => {
197
+ if (err) console.error(err);
198
+ }
199
+ );
200
+
201
+ // no intercom for anonymous
202
+ } else if (userId) {
203
+ posthog?.capture({
204
+ distinctId: userId,
205
+ event,
206
+ groups: {
207
+ tenant: groupId,
208
+ },
209
+ timestamp,
210
+ properties: convertKeysToSnakeCase(properties),
156
211
  });
157
- } catch (error: any) {
158
- console.error(error);
212
+
213
+ june?.track(
214
+ {
215
+ userId,
216
+ event,
217
+ properties,
218
+ timestamp,
219
+ context: { groupId },
220
+ },
221
+ (err) => {
222
+ if (err) console.error(err);
223
+ }
224
+ );
225
+
226
+ const intercomUserId = (
227
+ await intercom?.contacts.search({
228
+ query: {
229
+ field: 'external_id',
230
+ operator: Intercom.SingleFilterSearchRequestOperator.Equals,
231
+ value: userId,
232
+ },
233
+ })
234
+ )?.data.at(0)?.id;
235
+ if (intercomUserId)
236
+ await intercom?.events.create({
237
+ user_id: intercomUserId,
238
+ event_name: event,
239
+ metadata: convertValuesToString(properties),
240
+ created_at: timestamp ? timestamp.getTime() : Date.now(),
241
+ });
159
242
  }
160
243
  },
161
- identify: ({
244
+ identify: async ({
162
245
  traits,
163
246
  userId,
164
247
  disableGeoip,
165
- }: {
166
- userId: string;
167
- traits: Record<string, any>;
168
- disableGeoip?: boolean;
169
- }) => {
248
+ timestamp,
249
+ }: IdentifyProps) => {
170
250
  if (isDev || isTest(userId)) return;
171
251
 
172
252
  posthog?.identify({
173
253
  distinctId: userId,
174
- properties: traits,
254
+ properties: convertKeysToSnakeCase(traits),
175
255
  disableGeoip,
176
256
  });
177
- juneso?.identify(
257
+
258
+ june?.identify(
178
259
  {
179
260
  userId,
180
261
  traits,
262
+ timestamp,
181
263
  },
182
- (err) => {
183
- if (err) console.error(err);
184
- }
264
+ (err) => (err ? console.error(err) : {})
185
265
  );
266
+
267
+ // upsert intercom user
268
+ const data = {
269
+ external_id: userId,
270
+ email: traits?.email,
271
+ name:
272
+ traits?.name ||
273
+ (traits?.firstName
274
+ ? `${traits.firstName} ${traits.lastName}`
275
+ : traits?.lastName),
276
+ avatar: traits?.avatar,
277
+ signed_up_at: traits?.createdAt
278
+ ? new Date(traits.createdAt).getTime() / 1000
279
+ : undefined,
280
+ last_seen_at: new Date().getTime() / 1000,
281
+ custom_attributes: { userType: traits?.role },
282
+ };
283
+
284
+ const intercomUser = (
285
+ await intercom?.contacts.search({
286
+ query: {
287
+ field: 'external_id',
288
+ operator: Intercom.SingleFilterSearchRequestOperator.Equals,
289
+ value: userId,
290
+ },
291
+ })
292
+ )?.data.at(0);
293
+ if (intercomUser?.id)
294
+ await intercom?.contacts.update(intercomUser?.id, data);
295
+ else await intercom?.contacts.create(data);
186
296
  },
187
- group: ({
297
+ group: async ({
188
298
  traits,
189
299
  groupId,
190
300
  userId,
191
301
  anonymousId,
192
- }: OptionalUser<{
193
- groupId: string;
194
- traits?: Record<string, any>;
195
- }>) => {
302
+ timestamp,
303
+ }: GroupProps) => {
196
304
  if (isDev || isTest(userId || anonymousId || '', groupId)) return;
197
305
 
198
- posthog?.groupIdentify({
199
- groupKey: groupId,
200
- groupType: 'tenant',
201
- properties: traits,
202
- distinctId: userId,
306
+ const cid = traits?.billingCustomerId || traits?.hyperlineCustomerId;
307
+ const intercomCompany = await intercom?.companies.create({
308
+ name: traits?.name,
309
+ company_id: groupId,
310
+ plan: traits?.plan,
311
+ remote_created_at: traits?.createdAt
312
+ ? new Date(traits.createdAt).getTime() / 1000
313
+ : undefined,
314
+ monthly_spend: traits?.mrr,
315
+ custom_attributes: {
316
+ teamId: groupId,
317
+ team: traits?.name,
318
+ type: traits?.type,
319
+ status: traits?.status,
320
+ pms: traits?.pms,
321
+ accountingSoftware: traits?.accountingSoftware,
322
+ activeListings: traits?.activeListings,
323
+ paymentMethodType: traits?.paymentMethodType,
324
+ partnerName: traits?.partner || traits?.accountingPartner,
325
+ billingPortalUrl: cid
326
+ ? `https://billing.vrplatform.app/portal/${cid}`
327
+ : undefined,
328
+ billingStatus: traits?.billingSubscriptionStatus,
329
+ billingPartner:
330
+ traits?.billingPartner ||
331
+ traits?.partner ||
332
+ traits?.accountingPartner,
333
+ },
203
334
  });
204
- if (anonymousId)
205
- juneso?.group({ anonymousId, groupId, traits }, (err) =>
206
- console.error(err)
335
+
336
+ if (anonymousId) {
337
+ posthog?.groupIdentify({
338
+ groupKey: groupId,
339
+ groupType: 'tenant',
340
+ properties: convertKeysToSnakeCase(traits),
341
+ distinctId: anonymousId,
342
+ });
343
+
344
+ june?.group({ anonymousId, groupId, traits, timestamp }, (err) =>
345
+ err ? console.error(err) : {}
207
346
  );
208
- else if (userId)
209
- juneso?.group({ userId, groupId, traits }, (err) => {
210
- if (err) console.error(err);
347
+ } else if (userId) {
348
+ posthog?.groupIdentify({
349
+ groupKey: groupId,
350
+ groupType: 'tenant',
351
+ properties: convertKeysToSnakeCase(traits),
352
+ distinctId: userId,
211
353
  });
354
+
355
+ june?.group({ userId, groupId, traits, timestamp }, (err) =>
356
+ err ? console.error(err) : {}
357
+ );
358
+
359
+ // attach intercom user to intercom company
360
+ const intercomUser = (
361
+ await intercom?.contacts.search({
362
+ query: {
363
+ field: 'external_id',
364
+ operator: Intercom.SingleFilterSearchRequestOperator.Equals,
365
+ value: userId,
366
+ },
367
+ })
368
+ )?.data.at(0);
369
+ if (intercomUser?.id && intercomCompany?.id)
370
+ intercom?.companies.attachContact(intercomUser?.id, {
371
+ id: intercomCompany?.id,
372
+ });
373
+ }
212
374
  },
213
375
  shutdown: async () =>
214
- Promise.all([
215
- posthog?.shutdown(),
216
- juneso?.closeAndFlush(),
217
- axiom?.flush(),
218
- ]),
219
- // Posthog specific
220
- alias: posthog?.alias,
221
- isFeatureEnabled: posthog?.isFeatureEnabled,
222
- // export intercom and axiom
376
+ Promise.all([posthog?.shutdown(), june?.closeAndFlush(), log?.flush()]),
377
+ // export dependencies
223
378
  intercom,
224
379
  posthog,
225
- june: juneso,
226
- log: axiom,
380
+ june,
381
+ log,
227
382
  };
228
383
  };