@nascentdigital/funnel-services 4.4.18
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/README.md +7 -0
- package/dist/analytics/Analytics.d.ts +11 -0
- package/dist/analytics/Analytics.js +48 -0
- package/dist/analytics/GoogleAnalytics.d.ts +16 -0
- package/dist/analytics/GoogleAnalytics.js +92 -0
- package/dist/analytics/index.d.ts +2 -0
- package/dist/analytics/index.js +18 -0
- package/dist/api/ApiClient.d.ts +18 -0
- package/dist/api/ApiClient.js +43 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +17 -0
- package/dist/captcha/MockHumanVerification.d.ts +4 -0
- package/dist/captcha/MockHumanVerification.js +11 -0
- package/dist/captcha/RecaptchaAdapter.d.ts +18 -0
- package/dist/captcha/RecaptchaAdapter.js +43 -0
- package/dist/captcha/errors/CaptchaError.d.ts +12 -0
- package/dist/captcha/errors/CaptchaError.js +19 -0
- package/dist/captcha/errors/CaptchaErrors.d.ts +8 -0
- package/dist/captcha/errors/CaptchaErrors.js +31 -0
- package/dist/captcha/errors/CaptchaVerificationError.d.ts +5 -0
- package/dist/captcha/errors/CaptchaVerificationError.js +11 -0
- package/dist/captcha/errors/index.d.ts +3 -0
- package/dist/captcha/errors/index.js +24 -0
- package/dist/captcha/index.d.ts +3 -0
- package/dist/captcha/index.js +19 -0
- package/dist/consent/ConsentActions.d.ts +5 -0
- package/dist/consent/ConsentActions.js +41 -0
- package/dist/consent/ConsentData.d.ts +13 -0
- package/dist/consent/ConsentData.js +35 -0
- package/dist/consent/CookieConsent.d.ts +19 -0
- package/dist/consent/CookieConsent.js +161 -0
- package/dist/consent/index.d.ts +2 -0
- package/dist/consent/index.js +18 -0
- package/dist/identity/actions.d.ts +4 -0
- package/dist/identity/actions.js +22 -0
- package/dist/identity/api/Identity.d.ts +11 -0
- package/dist/identity/api/Identity.js +2 -0
- package/dist/identity/api/IdentityService.d.ts +9 -0
- package/dist/identity/api/IdentityService.js +27 -0
- package/dist/identity/api/Profile.d.ts +10 -0
- package/dist/identity/api/Profile.js +2 -0
- package/dist/identity/api/ProfileService.d.ts +12 -0
- package/dist/identity/api/ProfileService.js +27 -0
- package/dist/identity/api/index.d.ts +4 -0
- package/dist/identity/api/index.js +20 -0
- package/dist/identity/auth0/Auth0IdentityService.d.ts +9 -0
- package/dist/identity/auth0/Auth0IdentityService.js +27 -0
- package/dist/identity/auth0/Auth0Profile.d.ts +30 -0
- package/dist/identity/auth0/Auth0Profile.js +57 -0
- package/dist/identity/auth0/Auth0ProfileService.d.ts +21 -0
- package/dist/identity/auth0/Auth0ProfileService.js +69 -0
- package/dist/identity/auth0/index.d.ts +2 -0
- package/dist/identity/auth0/index.js +18 -0
- package/dist/identity/client/ClientProfile.d.ts +27 -0
- package/dist/identity/client/ClientProfile.js +31 -0
- package/dist/identity/client/IdentityContainer.d.ts +12 -0
- package/dist/identity/client/IdentityContainer.js +23 -0
- package/dist/identity/client/IdentityContext.d.ts +8 -0
- package/dist/identity/client/IdentityContext.js +6 -0
- package/dist/identity/client/index.d.ts +3 -0
- package/dist/identity/client/index.js +19 -0
- package/dist/identity/client/useIdentity.d.ts +2 -0
- package/dist/identity/client/useIdentity.js +9 -0
- package/dist/identity/client/useProfile.d.ts +2 -0
- package/dist/identity/client/useProfile.js +9 -0
- package/dist/identity/index.d.ts +3 -0
- package/dist/identity/index.js +19 -0
- package/dist/identity/server/IdentityProvider.d.ts +5 -0
- package/dist/identity/server/IdentityProvider.js +29 -0
- package/dist/identity/server/index.d.ts +1 -0
- package/dist/identity/server/index.js +17 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/ip/index.d.ts +1 -0
- package/dist/ip/index.js +17 -0
- package/dist/ip/useIpAddress.d.ts +1 -0
- package/dist/ip/useIpAddress.js +69 -0
- package/dist/leadgen/AbstractPipeDriveAdapter.d.ts +27 -0
- package/dist/leadgen/AbstractPipeDriveAdapter.js +43 -0
- package/dist/leadgen/ConfigPipeDriveAdapter.d.ts +18 -0
- package/dist/leadgen/ConfigPipeDriveAdapter.js +60 -0
- package/dist/leadgen/MockPipedrive.d.ts +16 -0
- package/dist/leadgen/MockPipedrive.js +32 -0
- package/dist/leadgen/PipedriveClient.d.ts +40 -0
- package/dist/leadgen/PipedriveClient.js +223 -0
- package/dist/leadgen/index.d.ts +4 -0
- package/dist/leadgen/index.js +20 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +20 -0
- package/package.json +52 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PipedriveClient = void 0;
|
|
4
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
// class
|
|
6
|
+
class PipedriveClient {
|
|
7
|
+
constructor({ apiKey, marketingStatusEnabled = false }) {
|
|
8
|
+
// initialize instance variables
|
|
9
|
+
this._apiKey = apiKey;
|
|
10
|
+
this._marketingStatusEnabled = marketingStatusEnabled;
|
|
11
|
+
}
|
|
12
|
+
async upsertPerson(data) {
|
|
13
|
+
var _a, _b, _c, _d;
|
|
14
|
+
console.debug('[Pipedrive.ts] upsert person');
|
|
15
|
+
// lookup person
|
|
16
|
+
const searchResponse = await this.send({
|
|
17
|
+
path: '/persons/search',
|
|
18
|
+
method: 'GET',
|
|
19
|
+
params: {
|
|
20
|
+
fields: 'email',
|
|
21
|
+
term: data.email,
|
|
22
|
+
exact_match: true
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
// fail if there request failed
|
|
26
|
+
if (!searchResponse.success) {
|
|
27
|
+
console.error('[Pipedrive.ts] error: Failed to lookup person');
|
|
28
|
+
throw new funnel_core_1.DependencyError('Failed to lookup person');
|
|
29
|
+
}
|
|
30
|
+
// update if person exists
|
|
31
|
+
const { item: existingPerson } = (_c = ((_b = (_a = searchResponse.data) === null || _a === void 0 ? void 0 : _a.items) !== null && _b !== void 0 ? _b : [])[0]) !== null && _c !== void 0 ? _c : {};
|
|
32
|
+
if (existingPerson && existingPerson.id) {
|
|
33
|
+
// get person's details (needed for marketing_status and current labels)
|
|
34
|
+
console.debug('[Pipedrive.ts] Getting person details');
|
|
35
|
+
const personDetails = await this.send({
|
|
36
|
+
path: `/persons/${existingPerson.id}`,
|
|
37
|
+
method: 'GET',
|
|
38
|
+
// only fetch marketingStatus if its enabled
|
|
39
|
+
params: this._marketingStatusEnabled ? { include_fields: 'marketing_status' } : {}
|
|
40
|
+
});
|
|
41
|
+
if (!personDetails.success) {
|
|
42
|
+
console.error('[Pipedrive.ts] Error: Failed to get person details');
|
|
43
|
+
throw new funnel_core_1.DependencyError(`Failed to get details of person "${existingPerson.id}" for account ${data.email}`);
|
|
44
|
+
}
|
|
45
|
+
// extract some existing data on person
|
|
46
|
+
const { label_ids, marketing_status: currentMarketingStatus } = personDetails.data;
|
|
47
|
+
// determine updated marketing status
|
|
48
|
+
// pipedrive's marketing status is a state machine,
|
|
49
|
+
// so you need to know the person's previous state
|
|
50
|
+
const updatedMarketingStatus = data.marketingStatus === 'subscribed' ? 'subscribed'
|
|
51
|
+
: currentMarketingStatus === 'subscribed' ? 'unsubscribed'
|
|
52
|
+
: undefined;
|
|
53
|
+
// dont include duplicate label ids
|
|
54
|
+
const newLabelIds = ((_d = data.label_ids) !== null && _d !== void 0 ? _d : []).filter((labelId) => !label_ids.includes(labelId));
|
|
55
|
+
// update labels if there is any
|
|
56
|
+
const customData = Object.assign({}, data.customData);
|
|
57
|
+
// finally do update request
|
|
58
|
+
console.debug('[Pipedrive.ts] Updating new person');
|
|
59
|
+
const updateResponse = await this.send({
|
|
60
|
+
path: `/persons/${existingPerson.id}`,
|
|
61
|
+
method: 'PATCH',
|
|
62
|
+
body: Object.assign({ emails: [{ value: data.email, primary: true }], 'marketing_status': updatedMarketingStatus, 'label_ids': [...label_ids, ...newLabelIds], 'owner_id': data.ownerId }, customData)
|
|
63
|
+
});
|
|
64
|
+
// fail if the add didn't take
|
|
65
|
+
if (!updateResponse.success) {
|
|
66
|
+
console.error('[Pipedrive.ts] Failed to update person');
|
|
67
|
+
throw new funnel_core_1.DependencyError(`Failed to update existing person "${existingPerson.id}" for account ${data.email}`);
|
|
68
|
+
}
|
|
69
|
+
console.debug('[Pipedrive.ts] person is updated');
|
|
70
|
+
return updateResponse;
|
|
71
|
+
}
|
|
72
|
+
// or add person
|
|
73
|
+
else {
|
|
74
|
+
console.debug('[Pipedrive.ts] Adding new person');
|
|
75
|
+
// only responsible for opting into marketing, not opting out, when adding a person
|
|
76
|
+
const marketingStatus = data.marketingStatus === 'subscribed' ? 'subscribed' : undefined;
|
|
77
|
+
const body = Object.assign({ emails: [{ value: data.email, primary: true }], phones: data.phones, 'marketing_status': marketingStatus, 'label_ids': data.label_ids, 'owner_id': data.ownerId }, data.customData);
|
|
78
|
+
const addResponse = await this.send({
|
|
79
|
+
path: '/persons',
|
|
80
|
+
method: 'POST',
|
|
81
|
+
body
|
|
82
|
+
});
|
|
83
|
+
// fail if the add didn't take
|
|
84
|
+
if (!addResponse.success) {
|
|
85
|
+
console.error('[Pipedrive.ts] Failed add update person');
|
|
86
|
+
throw new funnel_core_1.DependencyError('Failed to add new person');
|
|
87
|
+
}
|
|
88
|
+
return addResponse;
|
|
89
|
+
}
|
|
90
|
+
console.debug('[Pipedrive.ts] Upserting new person complete');
|
|
91
|
+
}
|
|
92
|
+
async captureNote(personId, content) {
|
|
93
|
+
console.debug('[PipedriveClient] capturing note', content);
|
|
94
|
+
// build body
|
|
95
|
+
const body = {
|
|
96
|
+
content,
|
|
97
|
+
person_id: personId
|
|
98
|
+
};
|
|
99
|
+
// capture note
|
|
100
|
+
const captureResponse = await this.send({
|
|
101
|
+
path: '/notes',
|
|
102
|
+
method: 'POST',
|
|
103
|
+
body,
|
|
104
|
+
version: 'v1'
|
|
105
|
+
});
|
|
106
|
+
// fail if the capturing note didn't take
|
|
107
|
+
if (!captureResponse.success) {
|
|
108
|
+
console.error('[Pipedrive.ts] Failed tp capture note');
|
|
109
|
+
throw new funnel_core_1.DependencyError('Failed to capture note');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async captureOrganization(personId, organizationName) {
|
|
113
|
+
var _a, _b, _c;
|
|
114
|
+
let orgId;
|
|
115
|
+
// check if org already exists
|
|
116
|
+
const searchResponse = await this.send({
|
|
117
|
+
path: '/organizations/search',
|
|
118
|
+
method: 'GET',
|
|
119
|
+
params: {
|
|
120
|
+
fields: 'name',
|
|
121
|
+
term: organizationName,
|
|
122
|
+
exact_match: true
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
// throw if org lookup fails
|
|
126
|
+
if (!searchResponse.success) {
|
|
127
|
+
console.error('[Pipedrive.ts] error: Failed to lookup organization');
|
|
128
|
+
throw new funnel_core_1.DependencyError('Failed to lookup organization');
|
|
129
|
+
}
|
|
130
|
+
// if org does not exist, create and use newly created id
|
|
131
|
+
const { item: existingOrg } = (_c = ((_b = (_a = searchResponse.data) === null || _a === void 0 ? void 0 : _a.items) !== null && _b !== void 0 ? _b : [])[0]) !== null && _c !== void 0 ? _c : {};
|
|
132
|
+
if (!existingOrg) {
|
|
133
|
+
const addResponse = await this.send({
|
|
134
|
+
path: '/organizations',
|
|
135
|
+
method: 'POST',
|
|
136
|
+
body: {
|
|
137
|
+
name: organizationName
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
// throw if adding org fails
|
|
141
|
+
if (!addResponse.success) {
|
|
142
|
+
console.error('[Pipedrive.ts] error: Failed to add organization');
|
|
143
|
+
throw new funnel_core_1.DependencyError('Failed to lookup organization');
|
|
144
|
+
}
|
|
145
|
+
orgId = addResponse.data.id;
|
|
146
|
+
}
|
|
147
|
+
// otherwise use existing org
|
|
148
|
+
else {
|
|
149
|
+
orgId = existingOrg.id;
|
|
150
|
+
}
|
|
151
|
+
// append organization to person by id
|
|
152
|
+
const updateResponse = await this.send({
|
|
153
|
+
path: `/persons/${personId}`,
|
|
154
|
+
method: 'PATCH',
|
|
155
|
+
body: {
|
|
156
|
+
'org_id': orgId,
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
// throw if update fails
|
|
160
|
+
if (!updateResponse.success) {
|
|
161
|
+
console.error('[Pipedrive.ts] error: Failed to update person with organization');
|
|
162
|
+
throw new funnel_core_1.DependencyError('Failed to lookup organization');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async send({ path, method, params = {}, body, version = 'v2' }) {
|
|
166
|
+
var _a;
|
|
167
|
+
// create url
|
|
168
|
+
const url = new URL(`/api/${version}${path}`, 'https://api.pipedrive.com');
|
|
169
|
+
const urlParams = url.searchParams;
|
|
170
|
+
urlParams.set('api_token', this._apiKey);
|
|
171
|
+
Object.entries(params).forEach(([name, value]) => urlParams.set(name, serializeParamValue(value)));
|
|
172
|
+
console.debug(`[Pipedrive.ts] sending [${method}] `, { url: url.href });
|
|
173
|
+
// send request
|
|
174
|
+
let response;
|
|
175
|
+
try {
|
|
176
|
+
response = await fetch(url.href, {
|
|
177
|
+
method,
|
|
178
|
+
headers: {
|
|
179
|
+
'Accept': 'application/json',
|
|
180
|
+
'Content-Type': 'application/json'
|
|
181
|
+
},
|
|
182
|
+
body: body ? JSON.stringify(body) : undefined
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
console.error(`[Pipedrive.ts] Error: ${e}`);
|
|
187
|
+
}
|
|
188
|
+
if (response) {
|
|
189
|
+
// throw on failure
|
|
190
|
+
if (!response.ok) {
|
|
191
|
+
console.error('Pipedrive error', await response.json());
|
|
192
|
+
throw new funnel_core_1.DependencyError(`Pipedrive request failed: ${response.status}/${(_a = response.statusText) !== null && _a !== void 0 ? _a : 'unknown'}`);
|
|
193
|
+
}
|
|
194
|
+
// parse response
|
|
195
|
+
const json = await response.json();
|
|
196
|
+
// failed if response has no success
|
|
197
|
+
if (json.success !== true) {
|
|
198
|
+
throw new funnel_core_1.DependencyError('Pipedrive request failed');
|
|
199
|
+
}
|
|
200
|
+
// otherwise, return data
|
|
201
|
+
console.debug(`[Pipedrive.ts] Successful request [${method}] `, { url: url.href });
|
|
202
|
+
return json;
|
|
203
|
+
}
|
|
204
|
+
throw new funnel_core_1.DependencyError('Unknown pipedrive error');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
exports.PipedriveClient = PipedriveClient;
|
|
208
|
+
function serializeParamValue(param) {
|
|
209
|
+
// recurse for arrays
|
|
210
|
+
if (Array.isArray(param)) {
|
|
211
|
+
return param.map(serializeParamValue)
|
|
212
|
+
.filter(funnel_core_1.Value.isDefined)
|
|
213
|
+
.join(',');
|
|
214
|
+
}
|
|
215
|
+
// handle date
|
|
216
|
+
else if (funnel_core_1.Value.isDate(param)) {
|
|
217
|
+
return param.toISOString();
|
|
218
|
+
}
|
|
219
|
+
// or handle raw value
|
|
220
|
+
else {
|
|
221
|
+
return String(param);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./AbstractPipeDriveAdapter"), exports);
|
|
18
|
+
__exportStar(require("./ConfigPipeDriveAdapter"), exports);
|
|
19
|
+
__exportStar(require("./MockPipedrive"), exports);
|
|
20
|
+
__exportStar(require("./PipedriveClient"), exports);
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./captcha"), exports);
|
|
18
|
+
__exportStar(require("./consent/ConsentActions"), exports);
|
|
19
|
+
__exportStar(require("./identity"), exports);
|
|
20
|
+
__exportStar(require("./leadgen"), exports);
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nascentdigital/funnel-services",
|
|
3
|
+
"version": "4.4.18",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"registry": "https://registry.npmjs.org/",
|
|
6
|
+
"access": "restricted"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "git+https://github.com/nascentdigital/funnel.git",
|
|
10
|
+
"directory": "libs/services"
|
|
11
|
+
},
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./dist/index.js",
|
|
15
|
+
"./server": "./dist/server.js"
|
|
16
|
+
},
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=22.0.0"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -P tsconfig.build.json",
|
|
26
|
+
"clean": "rimraf -I dist"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@nascentdigital/funnel-core": "*",
|
|
30
|
+
"@nascentdigital/funnel-ui": "*",
|
|
31
|
+
"next": "^15",
|
|
32
|
+
"react": "^19",
|
|
33
|
+
"react-dom": "^19"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@auth0/nextjs-auth0": "^4.15.0",
|
|
37
|
+
"auth0": "^5.3.1",
|
|
38
|
+
"rxjs": "^7",
|
|
39
|
+
"server-only": "^0",
|
|
40
|
+
"vanilla-cookieconsent": "^3",
|
|
41
|
+
"web-push": "^3"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/request-ip": "^0",
|
|
45
|
+
"@types/web-push": "^3",
|
|
46
|
+
"next": "^15",
|
|
47
|
+
"react": "^19",
|
|
48
|
+
"react-dom": "^19",
|
|
49
|
+
"type-fest": "^4"
|
|
50
|
+
},
|
|
51
|
+
"gitHead": "d1bfd4468426b7326bd9662cd169242867025f5e"
|
|
52
|
+
}
|