@skillswaveca/nova-shared-libraries 4.25.0 → 4.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.yaml +2 -0
- package/docs-base/package-info.js +5 -5
- package/package.json +1 -1
- package/packages/drivers/README.md +1 -1
- package/packages/drivers/package-lock.json +3906 -0
- package/packages/drivers/package.json +7 -4
- package/packages/drivers/src/hubspot.js +14 -13
- package/packages/nova-middleware/package.json +1 -1
- package/packages/nova-model/package.json +1 -1
- package/packages/nova-router/package.json +1 -1
- package/packages/nova-utils/package-lock.json +2 -2
- package/packages/nova-utils/package.json +1 -1
- package/packages/nova-utils/src/event-definitions.js +134 -6
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "@skillswaveca/nova-drivers",
|
|
4
4
|
"description": "Some helper drivers for AWS services",
|
|
5
5
|
"repository": "https://github.com/SkillsWave/nova-shared-libraries",
|
|
6
|
-
"version": "4.
|
|
6
|
+
"version": "4.27.0",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"pre-release": "pnpm run create-index",
|
|
@@ -16,17 +16,20 @@
|
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"chai": "^5.1.0",
|
|
18
18
|
"eslint": "^9.0.0",
|
|
19
|
-
"mocha": "^10.4.0"
|
|
19
|
+
"mocha": "^10.4.0",
|
|
20
|
+
"sinon": "^21.0.0",
|
|
21
|
+
"sinon-chai": "^4.0.0"
|
|
20
22
|
},
|
|
21
23
|
"dependencies": {
|
|
22
|
-
"simple-oauth2": "^5.0.0",
|
|
23
24
|
"@aws-sdk/client-dynamodb": "^3.572.0",
|
|
24
25
|
"@aws-sdk/client-secrets-manager": "^3.572.0",
|
|
25
26
|
"@aws-sdk/client-sqs": "^3.572.0",
|
|
26
27
|
"@aws-sdk/lib-dynamodb": "^3.572.0",
|
|
28
|
+
"@hubspot/api-client": "^13.0.0",
|
|
27
29
|
"aws-xray-sdk-core": "^3.6.0",
|
|
28
30
|
"lodash.chunk": "^4.2.0",
|
|
29
31
|
"node-fetch": "^3.1.0",
|
|
30
|
-
"pino": "^9.0.0"
|
|
32
|
+
"pino": "^9.0.0",
|
|
33
|
+
"simple-oauth2": "^5.0.0"
|
|
31
34
|
}
|
|
32
35
|
}
|
|
@@ -113,8 +113,8 @@ export class HubSpotDriver extends NovaDriver {
|
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* Updates a HubSpot deal with the given properties.
|
|
116
|
-
* @param {string} dealId
|
|
117
|
-
* @param {object} properties
|
|
116
|
+
* @param {string} dealId
|
|
117
|
+
* @param {object} properties
|
|
118
118
|
* @returns The updated deal object.
|
|
119
119
|
*/
|
|
120
120
|
async updateDeal(dealId, properties) {
|
|
@@ -123,7 +123,7 @@ export class HubSpotDriver extends NovaDriver {
|
|
|
123
123
|
|
|
124
124
|
/**
|
|
125
125
|
* Looks up a HubSpot contact ID for a given user. May return multiple IDs.
|
|
126
|
-
* @param {Object} user
|
|
126
|
+
* @param {Object} user
|
|
127
127
|
* @returns {Promise<string[]|null>} An array of HubSpot contact IDs or null if no contact is found.
|
|
128
128
|
*/
|
|
129
129
|
async lookupUserContactId(user) {
|
|
@@ -152,7 +152,7 @@ export class HubSpotDriver extends NovaDriver {
|
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
154
|
* Creates or updates a HubSpot contact. If the provided user has a `hubSpotContactId`, it will update the existing contact; otherwise, it will create a new one.
|
|
155
|
-
* @param {object} user
|
|
155
|
+
* @param {object} user
|
|
156
156
|
* @returns {object} The created/updated HubSpot user.
|
|
157
157
|
*/
|
|
158
158
|
async upsertUser(user) {
|
|
@@ -169,7 +169,7 @@ export class HubSpotDriver extends NovaDriver {
|
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
171
|
* Deletes a HubSpot user.
|
|
172
|
-
* @param {object} user
|
|
172
|
+
* @param {object} user
|
|
173
173
|
* @returns {Promise<void>}
|
|
174
174
|
*/
|
|
175
175
|
async deleteUser(user) {
|
|
@@ -184,7 +184,7 @@ export class HubSpotDriver extends NovaDriver {
|
|
|
184
184
|
/**
|
|
185
185
|
* Sends a custom event to HubSpot using the event definitions.
|
|
186
186
|
* This method validates the event data against the predefined schema before sending.
|
|
187
|
-
*
|
|
187
|
+
*
|
|
188
188
|
* @param {string} eventName - The name of the event to send
|
|
189
189
|
* @param {object} eventData - The event data to send
|
|
190
190
|
* @returns {Promise<object>} The response from HubSpot API
|
|
@@ -192,6 +192,7 @@ export class HubSpotDriver extends NovaDriver {
|
|
|
192
192
|
*/
|
|
193
193
|
async sendEvent(eventName, eventData) {
|
|
194
194
|
try {
|
|
195
|
+
log.error({ eventName, eventData }, 'Sending event to HubSpot');
|
|
195
196
|
// Validate the event exists and get its definition
|
|
196
197
|
const eventDefinition = getEventDefinition(eventName);
|
|
197
198
|
if (!eventDefinition) {
|
|
@@ -204,7 +205,7 @@ export class HubSpotDriver extends NovaDriver {
|
|
|
204
205
|
const eventMetadata = await getEventMetadata(eventName, validatedData);
|
|
205
206
|
|
|
206
207
|
const response = await this._callHubSpot('events.send.basicApi.send', {
|
|
207
|
-
eventName: `pe${this.accountId}_${
|
|
208
|
+
eventName: `pe${this.accountId}_${eventDefinition.name}`,
|
|
208
209
|
properties: validatedData,
|
|
209
210
|
occurredAt: new Date(),
|
|
210
211
|
...eventMetadata,
|
|
@@ -213,14 +214,14 @@ export class HubSpotDriver extends NovaDriver {
|
|
|
213
214
|
log.debug({ eventName, response }, 'Event sent to HubSpot successfully');
|
|
214
215
|
return response;
|
|
215
216
|
} catch (error) {
|
|
216
|
-
log.error({
|
|
217
|
-
eventName,
|
|
218
|
-
eventData,
|
|
217
|
+
log.error({
|
|
218
|
+
eventName,
|
|
219
|
+
eventData,
|
|
219
220
|
error: error.message,
|
|
220
|
-
stack: error.stack
|
|
221
|
+
stack: error.stack
|
|
221
222
|
}, 'Unexpected error while sending event');
|
|
222
|
-
|
|
223
|
+
|
|
223
224
|
throw error;
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
|
-
}
|
|
227
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "@skillswaveca/nova-middleware",
|
|
4
4
|
"description": "A collection of middleware used by nova projects",
|
|
5
5
|
"repository": "https://github.com/SkillsWave/nova-shared-libraries",
|
|
6
|
-
"version": "4.
|
|
6
|
+
"version": "4.27.0",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"pre-release": "pnpm run create-index",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "@skillswaveca/nova-model",
|
|
4
4
|
"description": "Nova model stuff",
|
|
5
5
|
"repository": "https://github.com/SkillsWave/nova-shared-libraries",
|
|
6
|
-
"version": "4.
|
|
6
|
+
"version": "4.27.0",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"pre-release": "pnpm run create-index",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "@skillswaveca/nova-router",
|
|
4
4
|
"description": "An extended Koa router that enables better validation",
|
|
5
5
|
"repository": "https://github.com/SkillsWave/nova-shared-libraries",
|
|
6
|
-
"version": "4.
|
|
6
|
+
"version": "4.27.0",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"pre-release": "pnpm run create-index",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skillswaveca/nova-utils",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.25.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@skillswaveca/nova-utils",
|
|
9
|
-
"version": "4.
|
|
9
|
+
"version": "4.25.0",
|
|
10
10
|
"license": "UNLICENSED",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"yup": "^1.4.0"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "@skillswaveca/nova-utils",
|
|
4
4
|
"description": "A collection of random utils used in nova repos",
|
|
5
5
|
"repository": "https://github.com/SkillsWave/nova-shared-libraries",
|
|
6
|
-
"version": "4.
|
|
6
|
+
"version": "4.27.0",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"pre-release": "pnpm run create-index",
|
|
@@ -11,10 +11,37 @@ import * as yup from 'yup';
|
|
|
11
11
|
* - validator: Yup validation schema for the event data
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const TENANT_PROPERTIES = {
|
|
15
|
+
tenant_id: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
required: true,
|
|
18
|
+
description: 'The ID of the tenant',
|
|
19
|
+
},
|
|
20
|
+
tenant_name: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
required: true,
|
|
23
|
+
description: 'The name of the tenant',
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const TENANT_PROPERTIES_VALIDATOR = {
|
|
28
|
+
tenant_id: yup.string().required('Tenant ID is required'),
|
|
29
|
+
tenant_name: yup.string().required('Tenant name is required'),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const TENANT_METADATA_PROPERTIES = data => {
|
|
33
|
+
return {
|
|
34
|
+
tenant_id: data.tenant_id,
|
|
35
|
+
tenant_name: data.tenant_name,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const clientOnboardingCompletedEventDefinition = {
|
|
40
|
+
key: 'clientOnboardingCompleted',
|
|
41
|
+
name: 'client_onboarding_completed',
|
|
42
|
+
description: 'Client has finished PLG onboarding and pressed "create workspace."',
|
|
17
43
|
properties: {
|
|
44
|
+
...TENANT_PROPERTIES,
|
|
18
45
|
email: {
|
|
19
46
|
type: 'string',
|
|
20
47
|
required: true,
|
|
@@ -22,10 +49,108 @@ const testEventDefinition = {
|
|
|
22
49
|
},
|
|
23
50
|
},
|
|
24
51
|
validator: yup.object({
|
|
52
|
+
...TENANT_PROPERTIES_VALIDATOR,
|
|
25
53
|
email: yup.string().email('Must be a valid email').required('Email is required'),
|
|
26
54
|
}),
|
|
27
55
|
getMetadata: eventData => {
|
|
28
56
|
return {
|
|
57
|
+
...TENANT_METADATA_PROPERTIES(eventData),
|
|
58
|
+
email: eventData.email,
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const usersInvitedEventDefinition = {
|
|
64
|
+
key: 'usersInvited',
|
|
65
|
+
name: 'users_invited',
|
|
66
|
+
description: 'PLG Admin has invited one or more users to their workspace.',
|
|
67
|
+
properties: {
|
|
68
|
+
...TENANT_PROPERTIES,
|
|
69
|
+
email: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
required: true,
|
|
72
|
+
description: 'Email address of the user',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
validator: yup.object({
|
|
76
|
+
...TENANT_PROPERTIES_VALIDATOR,
|
|
77
|
+
email: yup.string().email('Must be a valid email').required('Email is required'),
|
|
78
|
+
}),
|
|
79
|
+
getMetadata: eventData => {
|
|
80
|
+
return {
|
|
81
|
+
...TENANT_METADATA_PROPERTIES(eventData),
|
|
82
|
+
email: eventData.email,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const creditCardEventDefinition = {
|
|
88
|
+
key: 'creditCardAdded',
|
|
89
|
+
name: 'credit_card_added',
|
|
90
|
+
description: 'PLG Admin added a credit card in Stripe.',
|
|
91
|
+
properties: {
|
|
92
|
+
...TENANT_PROPERTIES,
|
|
93
|
+
email: {
|
|
94
|
+
type: 'string',
|
|
95
|
+
required: true,
|
|
96
|
+
description: 'Email address of the user',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
validator: yup.object({
|
|
100
|
+
...TENANT_PROPERTIES_VALIDATOR,
|
|
101
|
+
email: yup.string().email('Must be a valid email').required('Email is required'),
|
|
102
|
+
}),
|
|
103
|
+
getMetadata: eventData => {
|
|
104
|
+
return {
|
|
105
|
+
...TENANT_METADATA_PROPERTIES(eventData),
|
|
106
|
+
email: eventData.email,
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const firstRequestSubmittedEventDefinition = {
|
|
112
|
+
key: 'firstRequestSubmitted',
|
|
113
|
+
name: 'first_request_submitted',
|
|
114
|
+
description: 'A user in the PLG workspace has submitted the first request.',
|
|
115
|
+
properties: {
|
|
116
|
+
...TENANT_PROPERTIES,
|
|
117
|
+
email: {
|
|
118
|
+
type: 'string',
|
|
119
|
+
required: true,
|
|
120
|
+
description: 'Email address of the user',
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
validator: yup.object({
|
|
124
|
+
...TENANT_PROPERTIES_VALIDATOR,
|
|
125
|
+
email: yup.string().email('Must be a valid email').required('Email is required'),
|
|
126
|
+
}),
|
|
127
|
+
getMetadata: eventData => {
|
|
128
|
+
return {
|
|
129
|
+
...TENANT_METADATA_PROPERTIES(eventData),
|
|
130
|
+
email: eventData.email,
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const transactionsThresholdMetEventDefinition = {
|
|
136
|
+
key: 'transactionsThresholdMet',
|
|
137
|
+
name: 'transactions_threshold_met',
|
|
138
|
+
description: 'The PLG tenant has completed a specified number of transactions.',
|
|
139
|
+
properties: {
|
|
140
|
+
...TENANT_PROPERTIES,
|
|
141
|
+
email: {
|
|
142
|
+
type: 'string',
|
|
143
|
+
required: true,
|
|
144
|
+
description: 'Email address of the user',
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
validator: yup.object({
|
|
148
|
+
...TENANT_PROPERTIES_VALIDATOR,
|
|
149
|
+
email: yup.string().email('Must be a valid email').required('Email is required'),
|
|
150
|
+
}),
|
|
151
|
+
getMetadata: eventData => {
|
|
152
|
+
return {
|
|
153
|
+
...TENANT_METADATA_PROPERTIES(eventData),
|
|
29
154
|
email: eventData.email,
|
|
30
155
|
};
|
|
31
156
|
},
|
|
@@ -36,9 +161,12 @@ const testEventDefinition = {
|
|
|
36
161
|
* Key: event name, Value: event definition object
|
|
37
162
|
*/
|
|
38
163
|
export const eventDefinitions = {
|
|
39
|
-
[
|
|
164
|
+
[clientOnboardingCompletedEventDefinition.key]: clientOnboardingCompletedEventDefinition,
|
|
165
|
+
[usersInvitedEventDefinition.key]: usersInvitedEventDefinition,
|
|
166
|
+
[creditCardEventDefinition.key]: creditCardEventDefinition,
|
|
167
|
+
[firstRequestSubmittedEventDefinition.key]: firstRequestSubmittedEventDefinition,
|
|
168
|
+
[transactionsThresholdMetEventDefinition.key]: transactionsThresholdMetEventDefinition,
|
|
40
169
|
};
|
|
41
|
-
|
|
42
170
|
/**
|
|
43
171
|
* Get event definition by name
|
|
44
172
|
* @param {string} eventName - The name of the event
|
|
@@ -84,7 +212,7 @@ export const validateEvent = async(eventName, eventData) => {
|
|
|
84
212
|
* @returns {boolean} True if the event exists, false otherwise
|
|
85
213
|
*/
|
|
86
214
|
export const isValidEventName = eventName => {
|
|
87
|
-
return
|
|
215
|
+
return Object.hasOwn(eventDefinitions, eventName);
|
|
88
216
|
};
|
|
89
217
|
|
|
90
218
|
/**
|