@memberjunction/integration-connectors 5.11.0 → 5.12.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/dist/HubSpotConnector.d.ts +38 -2
- package/dist/HubSpotConnector.d.ts.map +1 -1
- package/dist/HubSpotConnector.js +78 -18
- package/dist/HubSpotConnector.js.map +1 -1
- package/dist/RasaConnector.d.ts +133 -0
- package/dist/RasaConnector.d.ts.map +1 -0
- package/dist/RasaConnector.js +596 -0
- package/dist/RasaConnector.js.map +1 -0
- package/dist/WicketConnector.d.ts +240 -0
- package/dist/WicketConnector.d.ts.map +1 -0
- package/dist/WicketConnector.js +861 -0
- package/dist/WicketConnector.js.map +1 -0
- package/dist/YourMembershipConnector.d.ts +58 -12
- package/dist/YourMembershipConnector.d.ts.map +1 -1
- package/dist/YourMembershipConnector.js +135 -57
- package/dist/YourMembershipConnector.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
8
|
+
import { Metadata } from '@memberjunction/core';
|
|
9
|
+
import { BaseIntegrationConnector, BaseRESTIntegrationConnector, } from '@memberjunction/integration-engine';
|
|
10
|
+
// ─── Constants ───────────────────────────────────────────────────────
|
|
11
|
+
/** Rasa.io API base URL */
|
|
12
|
+
const RASA_API_BASE = 'https://api.rasa.io/v1';
|
|
13
|
+
/** JWT tokens are refreshed every 50 minutes (tokens last ~60 min) */
|
|
14
|
+
const TOKEN_TTL_MS = 50 * 60 * 1000;
|
|
15
|
+
/** Maximum retries for rate-limited or failed requests */
|
|
16
|
+
const MAX_RETRIES = 3;
|
|
17
|
+
/** HTTP request timeout in milliseconds */
|
|
18
|
+
const REQUEST_TIMEOUT_MS = 60000;
|
|
19
|
+
/** Minimum milliseconds between API requests */
|
|
20
|
+
const MIN_REQUEST_INTERVAL_MS = 200;
|
|
21
|
+
/** Default page size for Rasa.io API calls */
|
|
22
|
+
const DEFAULT_PAGE_SIZE = 50;
|
|
23
|
+
// ─── Connector Implementation ────────────────────────────────────────
|
|
24
|
+
/**
|
|
25
|
+
* Connector for the Rasa.io newsletter platform REST API.
|
|
26
|
+
*
|
|
27
|
+
* Extends BaseRESTIntegrationConnector to leverage metadata-driven object/field
|
|
28
|
+
* discovery from IntegrationEngineBase cache and generic pagination handling.
|
|
29
|
+
*
|
|
30
|
+
* Auth flow:
|
|
31
|
+
* 1. POST /v1/tokens with Basic auth header + { "key": "<API-key>" } body
|
|
32
|
+
* 2. Receive JWT token in response
|
|
33
|
+
* 3. Pass JWT as rasa-token header on all data requests
|
|
34
|
+
*
|
|
35
|
+
* Pagination:
|
|
36
|
+
* - persons/posts: offset-based (skip/limit), supports updated_since watermark
|
|
37
|
+
* - insights/actions: cursor-based (base64 skip token from next_link), supports created_since watermark
|
|
38
|
+
* - insights/topics: no pagination, full replace on each sync
|
|
39
|
+
*
|
|
40
|
+
* Response envelope: { code, metadata: { next_link, record_count }, results: [...] }
|
|
41
|
+
*/
|
|
42
|
+
let RasaConnector = class RasaConnector extends BaseRESTIntegrationConnector {
|
|
43
|
+
constructor() {
|
|
44
|
+
super(...arguments);
|
|
45
|
+
/** Cached JWT token */
|
|
46
|
+
this.cachedToken = null;
|
|
47
|
+
/** When the cached token was obtained */
|
|
48
|
+
this.tokenObtainedAt = 0;
|
|
49
|
+
/** Timestamp of the last API request, used for throttling */
|
|
50
|
+
this.lastRequestTime = 0;
|
|
51
|
+
/** Running count of records fetched for the current object in this sync run */
|
|
52
|
+
this._runningFetchTotal = 0;
|
|
53
|
+
/** Tracks all ExternalIDs seen per object in this sync run to detect API wrap-around */
|
|
54
|
+
this._seenIDs = new Map();
|
|
55
|
+
/** Last fetched URL path, used for per-page logging */
|
|
56
|
+
this._lastFetchedPath = '';
|
|
57
|
+
/** Watermark value for the current FetchChanges call — used in BuildPaginatedURL */
|
|
58
|
+
this._currentWatermark = undefined;
|
|
59
|
+
/** Object name for the current FetchChanges call — used in NormalizeResponse and BuildPaginatedURL */
|
|
60
|
+
this._currentObjectName = '';
|
|
61
|
+
/**
|
|
62
|
+
* Buffer for non-paginated objects that return more records than BatchSize in one shot.
|
|
63
|
+
* Keyed by object name. Records are spliced out as they're served to the engine.
|
|
64
|
+
*/
|
|
65
|
+
this._batchBuffer = new Map();
|
|
66
|
+
/**
|
|
67
|
+
* Watermark values pre-computed from the full result set when buffering.
|
|
68
|
+
* Stored so the final buffer batch can still advance the watermark correctly.
|
|
69
|
+
*/
|
|
70
|
+
this._batchBufferWatermarks = new Map();
|
|
71
|
+
}
|
|
72
|
+
// ─── Abstract method implementations ─────────────────────────────
|
|
73
|
+
async Authenticate(companyIntegration, contextUser) {
|
|
74
|
+
console.log(`[Rasa.io] Authenticating...`);
|
|
75
|
+
const config = await this.ParseConfig(companyIntegration, contextUser);
|
|
76
|
+
const token = await this.GetToken(config);
|
|
77
|
+
console.log(`[Rasa.io] Authenticated successfully, token length: ${token.length}`);
|
|
78
|
+
const auth = { Token: token, Config: config };
|
|
79
|
+
return auth;
|
|
80
|
+
}
|
|
81
|
+
BuildHeaders(auth) {
|
|
82
|
+
return {
|
|
83
|
+
'rasa-token': auth.Token,
|
|
84
|
+
'Accept': 'application/json',
|
|
85
|
+
'Content-Type': 'application/json',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async MakeHTTPRequest(auth, url, method, headers, body) {
|
|
89
|
+
const rasaAuth = auth;
|
|
90
|
+
// Throttle requests
|
|
91
|
+
const elapsed = Date.now() - this.lastRequestTime;
|
|
92
|
+
if (elapsed < MIN_REQUEST_INTERVAL_MS) {
|
|
93
|
+
await this.Sleep(MIN_REQUEST_INTERVAL_MS - elapsed);
|
|
94
|
+
}
|
|
95
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
96
|
+
const fetchOptions = {
|
|
97
|
+
method,
|
|
98
|
+
headers,
|
|
99
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
100
|
+
};
|
|
101
|
+
if (body && method !== 'GET') {
|
|
102
|
+
fetchOptions.body = JSON.stringify(body);
|
|
103
|
+
}
|
|
104
|
+
let response;
|
|
105
|
+
try {
|
|
106
|
+
response = await fetch(url, fetchOptions);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
if (attempt < MAX_RETRIES && this.IsTimeoutOrNetworkError(err)) {
|
|
110
|
+
console.warn(`Rasa.io timeout on ${url}, retrying (attempt ${attempt + 1}/${MAX_RETRIES})`);
|
|
111
|
+
await this.Sleep(1000 * (attempt + 1));
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
if (response.status === 401 && attempt < MAX_RETRIES) {
|
|
117
|
+
// Token expired, refresh and retry
|
|
118
|
+
console.warn('Rasa.io 401, refreshing token');
|
|
119
|
+
this.cachedToken = null;
|
|
120
|
+
const newToken = await this.GetToken(rasaAuth.Config);
|
|
121
|
+
rasaAuth.Token = newToken;
|
|
122
|
+
headers['rasa-token'] = newToken;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (response.status === 429 && attempt < MAX_RETRIES) {
|
|
126
|
+
const delayMs = 2000 * Math.pow(2, attempt);
|
|
127
|
+
console.warn(`Rasa.io rate limited (429), retrying in ${delayMs}ms`);
|
|
128
|
+
await this.Sleep(delayMs);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
this.lastRequestTime = Date.now();
|
|
132
|
+
const responseBody = await response.json();
|
|
133
|
+
const responseHeaders = {};
|
|
134
|
+
response.headers.forEach((value, key) => {
|
|
135
|
+
responseHeaders[key.toLowerCase()] = value;
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
Status: response.status,
|
|
139
|
+
Body: responseBody,
|
|
140
|
+
Headers: responseHeaders,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
throw new Error(`Rasa.io request failed after ${MAX_RETRIES} retries: ${url}`);
|
|
144
|
+
}
|
|
145
|
+
NormalizeResponse(rawBody, responseDataKey) {
|
|
146
|
+
const body = rawBody;
|
|
147
|
+
if (body.results && Array.isArray(body.results)) {
|
|
148
|
+
const rawResults = body.results;
|
|
149
|
+
// insights/topics: flatten nested topics[] per person into individual rows
|
|
150
|
+
if (this._currentObjectName.toLowerCase() === 'insights-topics') {
|
|
151
|
+
return this.FlattenInsightsTopics(rawResults);
|
|
152
|
+
}
|
|
153
|
+
// Standard envelope: each item may wrap actual record under 'data' key — unwrap it
|
|
154
|
+
const records = rawResults.map(item => {
|
|
155
|
+
const inner = item['data'];
|
|
156
|
+
return (inner && typeof inner === 'object' && !Array.isArray(inner))
|
|
157
|
+
? inner
|
|
158
|
+
: item;
|
|
159
|
+
});
|
|
160
|
+
this._runningFetchTotal += records.length;
|
|
161
|
+
const pathLabel = this._lastFetchedPath || 'unknown';
|
|
162
|
+
console.log(`[Rasa.io] Fetched ${records.length} records (running total: ${this._runningFetchTotal}) from ${pathLabel}`);
|
|
163
|
+
return records;
|
|
164
|
+
}
|
|
165
|
+
// If responseDataKey is specified, use it
|
|
166
|
+
if (responseDataKey && body[responseDataKey]) {
|
|
167
|
+
const data = body[responseDataKey];
|
|
168
|
+
return Array.isArray(data) ? data : [data];
|
|
169
|
+
}
|
|
170
|
+
// Fallback: if body itself is an array
|
|
171
|
+
if (Array.isArray(body)) {
|
|
172
|
+
return body;
|
|
173
|
+
}
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
ExtractPaginationInfo(rawBody, _paginationType, _currentPage, currentOffset, pageSize) {
|
|
177
|
+
const body = rawBody;
|
|
178
|
+
const metadata = body.metadata;
|
|
179
|
+
if (!metadata) {
|
|
180
|
+
return { HasMore: false };
|
|
181
|
+
}
|
|
182
|
+
const totalRecords = metadata.record_count;
|
|
183
|
+
const nextLink = metadata.next_link;
|
|
184
|
+
// Count actual records returned in this page
|
|
185
|
+
const results = body.results;
|
|
186
|
+
const returnedCount = Array.isArray(results) ? results.length : 0;
|
|
187
|
+
// If the API returned fewer records than the page size, this is the last page.
|
|
188
|
+
// The Rasa API returns next_link even past the end of the dataset, so we cannot
|
|
189
|
+
// rely on next_link alone. Fewer records than requested = no more data.
|
|
190
|
+
if (returnedCount < pageSize) {
|
|
191
|
+
return { HasMore: false, TotalRecords: totalRecords };
|
|
192
|
+
}
|
|
193
|
+
const hasMore = !!nextLink && nextLink.length > 0;
|
|
194
|
+
if (!hasMore) {
|
|
195
|
+
return { HasMore: false, TotalRecords: totalRecords };
|
|
196
|
+
}
|
|
197
|
+
// Determine cursor vs offset by inspecting the skip param in next_link
|
|
198
|
+
let nextCursor;
|
|
199
|
+
let nextOffset;
|
|
200
|
+
try {
|
|
201
|
+
const url = new URL(nextLink);
|
|
202
|
+
const skipParam = url.searchParams.get('skip');
|
|
203
|
+
if (skipParam && isNaN(Number(skipParam))) {
|
|
204
|
+
// Non-numeric skip param = base64 cursor token (insights/actions)
|
|
205
|
+
nextCursor = skipParam;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
nextOffset = currentOffset + returnedCount;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
nextOffset = currentOffset + pageSize;
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
HasMore: true,
|
|
216
|
+
NextOffset: nextOffset,
|
|
217
|
+
NextCursor: nextCursor,
|
|
218
|
+
TotalRecords: totalRecords,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
GetBaseURL(_companyIntegration) {
|
|
222
|
+
return RASA_API_BASE;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Builds paginated URL with:
|
|
226
|
+
* - Watermark filter params (updated_since / created_since) sent server-side
|
|
227
|
+
* - Offset-based skip/limit for persons and posts
|
|
228
|
+
* - Cursor-based skip token for insights/actions
|
|
229
|
+
* - No pagination params for insights/topics
|
|
230
|
+
*/
|
|
231
|
+
BuildPaginatedURL(basePath, obj, _page, offset, cursor, effectivePageSize) {
|
|
232
|
+
try {
|
|
233
|
+
this._lastFetchedPath = new URL(basePath).pathname;
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
this._lastFetchedPath = basePath;
|
|
237
|
+
}
|
|
238
|
+
const objectName = (obj.Name ?? '').toLowerCase();
|
|
239
|
+
const limit = effectivePageSize ?? obj.DefaultPageSize ?? DEFAULT_PAGE_SIZE;
|
|
240
|
+
const params = new URLSearchParams();
|
|
241
|
+
// Pass watermark filter to API so it only returns changed records
|
|
242
|
+
if (this._currentWatermark) {
|
|
243
|
+
if (objectName === 'persons' || objectName === 'posts') {
|
|
244
|
+
params.set('updated_since', this._currentWatermark);
|
|
245
|
+
}
|
|
246
|
+
else if (objectName === 'insights-actions') {
|
|
247
|
+
params.set('created_since', this._currentWatermark);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Pagination params — insights/topics has no pagination
|
|
251
|
+
if (objectName !== 'insights-topics') {
|
|
252
|
+
if (objectName === 'insights-actions' && cursor) {
|
|
253
|
+
// Cursor-based: cursor is the base64 skip token extracted from previous next_link
|
|
254
|
+
params.set('skip', cursor);
|
|
255
|
+
}
|
|
256
|
+
else if (offset > 0) {
|
|
257
|
+
// Offset-based
|
|
258
|
+
params.set('skip', String(offset));
|
|
259
|
+
}
|
|
260
|
+
params.set('limit', String(limit));
|
|
261
|
+
}
|
|
262
|
+
const queryString = params.toString();
|
|
263
|
+
return queryString ? `${basePath}?${queryString}` : basePath;
|
|
264
|
+
}
|
|
265
|
+
// ─── TestConnection ──────────────────────────────────────────────
|
|
266
|
+
async TestConnection(companyIntegration, contextUser) {
|
|
267
|
+
try {
|
|
268
|
+
const config = await this.ParseConfig(companyIntegration, contextUser);
|
|
269
|
+
const token = await this.GetToken(config);
|
|
270
|
+
// Verify token works by listing communities
|
|
271
|
+
const response = await fetch(`${RASA_API_BASE}/communities`, {
|
|
272
|
+
method: 'GET',
|
|
273
|
+
headers: { 'rasa-token': token, 'Accept': 'application/json' },
|
|
274
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
275
|
+
});
|
|
276
|
+
if (!response.ok) {
|
|
277
|
+
return {
|
|
278
|
+
Success: false,
|
|
279
|
+
Message: `Connection failed: HTTP ${response.status} from communities endpoint`,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
const body = await response.json();
|
|
283
|
+
const results = body.results;
|
|
284
|
+
const communityCount = results?.length ?? 0;
|
|
285
|
+
return {
|
|
286
|
+
Success: true,
|
|
287
|
+
Message: `Connected to Rasa.io — ${communityCount} community(ies) accessible`,
|
|
288
|
+
ServerVersion: 'Rasa.io API v1',
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
catch (err) {
|
|
292
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
293
|
+
return { Success: false, Message: `Connection failed: ${message}` };
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// ─── Default Configuration ───────────────────────────────────────
|
|
297
|
+
GetDefaultConfiguration() {
|
|
298
|
+
return {
|
|
299
|
+
DefaultSchemaName: 'RasaIO',
|
|
300
|
+
DefaultObjects: [],
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
GetDefaultFieldMappings(objectName, _entityName) {
|
|
304
|
+
const lowerName = objectName.toLowerCase();
|
|
305
|
+
if (lowerName === 'persons' || lowerName === 'contacts') {
|
|
306
|
+
return [
|
|
307
|
+
{ SourceFieldName: 'id', DestinationFieldName: 'ExternalID', IsKeyField: true },
|
|
308
|
+
{ SourceFieldName: 'email', DestinationFieldName: 'Email' },
|
|
309
|
+
{ SourceFieldName: 'first_name', DestinationFieldName: 'FirstName' },
|
|
310
|
+
{ SourceFieldName: 'last_name', DestinationFieldName: 'LastName' },
|
|
311
|
+
{ SourceFieldName: 'external_id', DestinationFieldName: 'SourceExternalID' },
|
|
312
|
+
{ SourceFieldName: 'is_active', DestinationFieldName: 'IsActive' },
|
|
313
|
+
{ SourceFieldName: 'is_subscribed', DestinationFieldName: 'IsSubscribed' },
|
|
314
|
+
{ SourceFieldName: 'created', DestinationFieldName: 'CreatedAt' },
|
|
315
|
+
{ SourceFieldName: 'updated', DestinationFieldName: 'UpdatedAt' },
|
|
316
|
+
];
|
|
317
|
+
}
|
|
318
|
+
if (lowerName === 'posts' || lowerName === 'content') {
|
|
319
|
+
return [
|
|
320
|
+
{ SourceFieldName: 'id', DestinationFieldName: 'ExternalID', IsKeyField: true },
|
|
321
|
+
{ SourceFieldName: 'url', DestinationFieldName: 'URL' },
|
|
322
|
+
{ SourceFieldName: 'title', DestinationFieldName: 'Title' },
|
|
323
|
+
{ SourceFieldName: 'description', DestinationFieldName: 'Description' },
|
|
324
|
+
{ SourceFieldName: 'source_url', DestinationFieldName: 'SourceURL' },
|
|
325
|
+
{ SourceFieldName: 'image_url', DestinationFieldName: 'ImageURL' },
|
|
326
|
+
{ SourceFieldName: 'quality_score', DestinationFieldName: 'QualityScore' },
|
|
327
|
+
{ SourceFieldName: 'is_active', DestinationFieldName: 'IsActive' },
|
|
328
|
+
{ SourceFieldName: 'created', DestinationFieldName: 'CreatedAt' },
|
|
329
|
+
{ SourceFieldName: 'updated', DestinationFieldName: 'UpdatedAt' },
|
|
330
|
+
];
|
|
331
|
+
}
|
|
332
|
+
return [];
|
|
333
|
+
}
|
|
334
|
+
// ─── FetchChanges Override ────────────────────────────────────────
|
|
335
|
+
/**
|
|
336
|
+
* Override FetchChanges to:
|
|
337
|
+
* 1. Store watermark and object name for use in BuildPaginatedURL/NormalizeResponse
|
|
338
|
+
* 2. Advance watermark on final batch using latest record timestamp
|
|
339
|
+
*
|
|
340
|
+
* Watermark filtering is done server-side via updated_since/created_since params
|
|
341
|
+
* (set in BuildPaginatedURL), so no client-side filtering is needed here.
|
|
342
|
+
*/
|
|
343
|
+
async FetchChanges(ctx) {
|
|
344
|
+
console.log(`[Rasa.io] FetchChanges called for '${ctx.ObjectName}' (batchSize=${ctx.BatchSize}, watermark=${ctx.WatermarkValue ?? 'none'}, offset=${ctx.CurrentOffset ?? 'none'}, cursor=${ctx.CurrentCursor ?? 'none'})`);
|
|
345
|
+
// Reset counter and seen-IDs on the first page. Don't reset when serving from buffer
|
|
346
|
+
// (buffer calls also have no offset/cursor but the buffer key will be present).
|
|
347
|
+
const isFirstCall = !ctx.CurrentOffset && !ctx.CurrentPage && !ctx.CurrentCursor;
|
|
348
|
+
if (isFirstCall && !this._batchBuffer.has(ctx.ObjectName)) {
|
|
349
|
+
this._runningFetchTotal = 0;
|
|
350
|
+
this._seenIDs.set(ctx.ObjectName, new Set());
|
|
351
|
+
}
|
|
352
|
+
// Store for use in BuildPaginatedURL and NormalizeResponse
|
|
353
|
+
this._currentWatermark = ctx.WatermarkValue ?? undefined;
|
|
354
|
+
this._currentObjectName = ctx.ObjectName ?? '';
|
|
355
|
+
// Serve from buffer if a previous call left unconsumed records
|
|
356
|
+
const buffered = this._batchBuffer.get(ctx.ObjectName);
|
|
357
|
+
if (buffered && buffered.length > 0) {
|
|
358
|
+
return this.ServeBufferedRecords(ctx.ObjectName, buffered, ctx.BatchSize);
|
|
359
|
+
}
|
|
360
|
+
const result = await super.FetchChanges(ctx);
|
|
361
|
+
// Detect API wrap-around: track all seen IDs, stop when entire batch is duplicates
|
|
362
|
+
const seen = this._seenIDs.get(ctx.ObjectName);
|
|
363
|
+
if (seen && result.Records.length > 0) {
|
|
364
|
+
const dupeCount = result.Records.filter(r => seen.has(r.ExternalID)).length;
|
|
365
|
+
for (const r of result.Records)
|
|
366
|
+
seen.add(r.ExternalID);
|
|
367
|
+
if (dupeCount === result.Records.length) {
|
|
368
|
+
return {
|
|
369
|
+
Records: [],
|
|
370
|
+
HasMore: false,
|
|
371
|
+
NewWatermarkValue: this.FindLatestTimestamp(result.Records) ?? ctx.WatermarkValue ?? undefined,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// When a non-paginated endpoint returns more than BatchSize in one shot,
|
|
376
|
+
// buffer the full set and serve it in chunks so no records are silently dropped.
|
|
377
|
+
if (!result.HasMore && result.Records.length > ctx.BatchSize) {
|
|
378
|
+
const watermark = this.FindLatestTimestamp(result.Records);
|
|
379
|
+
this._batchBuffer.set(ctx.ObjectName, result.Records);
|
|
380
|
+
this._batchBufferWatermarks.set(ctx.ObjectName, watermark);
|
|
381
|
+
return this.ServeBufferedRecords(ctx.ObjectName, result.Records, ctx.BatchSize);
|
|
382
|
+
}
|
|
383
|
+
const isFinalBatch = !result.HasMore;
|
|
384
|
+
const latestTimestamp = isFinalBatch ? this.FindLatestTimestamp(result.Records) : null;
|
|
385
|
+
return {
|
|
386
|
+
...result,
|
|
387
|
+
NewWatermarkValue: isFinalBatch ? (latestTimestamp ?? ctx.WatermarkValue ?? undefined) : undefined,
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Serves records from the internal buffer in BatchSize-sized chunks.
|
|
392
|
+
* Splices consumed records from the buffer array so subsequent calls advance correctly.
|
|
393
|
+
* Emits NewWatermarkValue only on the final chunk.
|
|
394
|
+
*/
|
|
395
|
+
ServeBufferedRecords(objectName, buffer, batchSize) {
|
|
396
|
+
const batch = buffer.splice(0, batchSize);
|
|
397
|
+
const hasMore = buffer.length > 0;
|
|
398
|
+
let newWatermarkValue;
|
|
399
|
+
if (!hasMore) {
|
|
400
|
+
const stored = this._batchBufferWatermarks.get(objectName);
|
|
401
|
+
newWatermarkValue = stored ?? undefined;
|
|
402
|
+
this._batchBuffer.delete(objectName);
|
|
403
|
+
this._batchBufferWatermarks.delete(objectName);
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
Records: batch,
|
|
407
|
+
HasMore: hasMore,
|
|
408
|
+
NewWatermarkValue: newWatermarkValue,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
// ─── Private Helpers ─────────────────────────────────────────────
|
|
412
|
+
/**
|
|
413
|
+
* Flattens the nested insights/topics response structure.
|
|
414
|
+
* API returns one item per person with a topics[] array; we emit one row per (person, topic).
|
|
415
|
+
*/
|
|
416
|
+
FlattenInsightsTopics(rawResults) {
|
|
417
|
+
const rows = [];
|
|
418
|
+
for (const item of rawResults) {
|
|
419
|
+
// Unwrap 'data' envelope if present
|
|
420
|
+
const record = (item['data'] && typeof item['data'] === 'object' && !Array.isArray(item['data']))
|
|
421
|
+
? item['data']
|
|
422
|
+
: item;
|
|
423
|
+
const personId = record['id'] ?? record['person_id'];
|
|
424
|
+
const externalId = record['external_id'];
|
|
425
|
+
const email = record['email'];
|
|
426
|
+
const topics = record['topics'];
|
|
427
|
+
if (!Array.isArray(topics))
|
|
428
|
+
continue;
|
|
429
|
+
for (const topicEntry of topics) {
|
|
430
|
+
rows.push({
|
|
431
|
+
person_id: personId,
|
|
432
|
+
external_id: externalId,
|
|
433
|
+
email,
|
|
434
|
+
topic: topicEntry['topic'],
|
|
435
|
+
first_click: topicEntry['first_click'],
|
|
436
|
+
last_click: topicEntry['last_click'],
|
|
437
|
+
weight: topicEntry['weight'],
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
this._runningFetchTotal += rows.length;
|
|
442
|
+
console.log(`[Rasa.io] Flattened ${rows.length} insights/topics rows from ${rawResults.length} persons`);
|
|
443
|
+
return rows;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Parses connection config from CompanyIntegration credentials.
|
|
447
|
+
* Tries CredentialID first (MJ: Credentials entity), then Configuration JSON.
|
|
448
|
+
*/
|
|
449
|
+
async ParseConfig(companyIntegration, contextUser) {
|
|
450
|
+
// Try CredentialID first
|
|
451
|
+
if (companyIntegration.CredentialID) {
|
|
452
|
+
return this.ParseConfigFromCredential(companyIntegration.CredentialID, contextUser);
|
|
453
|
+
}
|
|
454
|
+
// Fallback to Configuration JSON
|
|
455
|
+
if (companyIntegration.Configuration) {
|
|
456
|
+
return this.ParseConfigFromJSON(companyIntegration.Configuration);
|
|
457
|
+
}
|
|
458
|
+
throw new Error('Rasa.io connector requires either CredentialID or Configuration JSON');
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Loads credentials from the MJ: Credentials entity.
|
|
462
|
+
*/
|
|
463
|
+
async ParseConfigFromCredential(credentialID, contextUser) {
|
|
464
|
+
const md = new Metadata();
|
|
465
|
+
const credEntity = await md.GetEntityObject('MJ: Credentials', contextUser);
|
|
466
|
+
await credEntity.Load(credentialID);
|
|
467
|
+
const valuesJSON = credEntity.Values;
|
|
468
|
+
if (!valuesJSON) {
|
|
469
|
+
throw new Error('Credential record has no Values JSON');
|
|
470
|
+
}
|
|
471
|
+
const values = JSON.parse(valuesJSON);
|
|
472
|
+
return this.ExtractConfigFields(values);
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Parses config from the CompanyIntegration.Configuration JSON string.
|
|
476
|
+
*/
|
|
477
|
+
ParseConfigFromJSON(configJSON) {
|
|
478
|
+
const parsed = JSON.parse(configJSON);
|
|
479
|
+
return this.ExtractConfigFields(parsed);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Extracts config fields with case-insensitive key matching.
|
|
483
|
+
*/
|
|
484
|
+
ExtractConfigFields(values) {
|
|
485
|
+
const get = (key) => {
|
|
486
|
+
const lower = key.toLowerCase();
|
|
487
|
+
for (const [k, v] of Object.entries(values)) {
|
|
488
|
+
if (k.toLowerCase() === lower)
|
|
489
|
+
return v;
|
|
490
|
+
}
|
|
491
|
+
return undefined;
|
|
492
|
+
};
|
|
493
|
+
const apiKey = get('apikey') ?? get('api_key') ?? get('key');
|
|
494
|
+
const username = get('username') ?? get('email') ?? get('user');
|
|
495
|
+
const password = get('password') ?? get('pass');
|
|
496
|
+
const communityIdentifier = get('communityidentifier') ?? get('community_identifier') ?? get('community');
|
|
497
|
+
if (!apiKey) {
|
|
498
|
+
throw new Error('Rasa.io configuration missing required field: APIKey');
|
|
499
|
+
}
|
|
500
|
+
if (!username || !password) {
|
|
501
|
+
throw new Error('Rasa.io configuration missing required fields: Username and Password (for Basic auth)');
|
|
502
|
+
}
|
|
503
|
+
return {
|
|
504
|
+
APIKey: apiKey,
|
|
505
|
+
Username: username,
|
|
506
|
+
Password: password,
|
|
507
|
+
CommunityIdentifier: communityIdentifier,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Obtains a JWT token from Rasa.io, using cache if still valid.
|
|
512
|
+
*/
|
|
513
|
+
async GetToken(config) {
|
|
514
|
+
// Return cached token if still fresh
|
|
515
|
+
if (this.cachedToken && (Date.now() - this.tokenObtainedAt) < TOKEN_TTL_MS) {
|
|
516
|
+
return this.cachedToken;
|
|
517
|
+
}
|
|
518
|
+
const basicAuth = Buffer.from(`${config.Username}:${config.Password}`).toString('base64');
|
|
519
|
+
const response = await fetch(`${RASA_API_BASE}/tokens`, {
|
|
520
|
+
method: 'POST',
|
|
521
|
+
headers: {
|
|
522
|
+
'Authorization': `Basic ${basicAuth}`,
|
|
523
|
+
'Content-Type': 'application/json',
|
|
524
|
+
'Accept': 'application/json',
|
|
525
|
+
},
|
|
526
|
+
body: JSON.stringify({ key: config.APIKey }),
|
|
527
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
528
|
+
});
|
|
529
|
+
if (!response.ok) {
|
|
530
|
+
const body = await response.text();
|
|
531
|
+
throw new Error(`Rasa.io token request failed (HTTP ${response.status}): ${body.slice(0, 500)}`);
|
|
532
|
+
}
|
|
533
|
+
const body = await response.json();
|
|
534
|
+
// Token could be in results array or directly in response
|
|
535
|
+
let token;
|
|
536
|
+
if (body.results && Array.isArray(body.results) && body.results.length > 0) {
|
|
537
|
+
const firstResult = body.results[0];
|
|
538
|
+
token = (firstResult.token ?? firstResult['rasa-token'] ?? firstResult.jwt);
|
|
539
|
+
}
|
|
540
|
+
if (!token && typeof body.token === 'string') {
|
|
541
|
+
token = body.token;
|
|
542
|
+
}
|
|
543
|
+
if (!token && typeof body['rasa-token'] === 'string') {
|
|
544
|
+
token = body['rasa-token'];
|
|
545
|
+
}
|
|
546
|
+
if (!token) {
|
|
547
|
+
throw new Error('Rasa.io token response did not contain a token');
|
|
548
|
+
}
|
|
549
|
+
this.cachedToken = token;
|
|
550
|
+
this.tokenObtainedAt = Date.now();
|
|
551
|
+
return token;
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Finds the latest timestamp from records for watermark advancement.
|
|
555
|
+
* Uses 'created' for insights/actions (its only timestamp field); 'updated' for everything else.
|
|
556
|
+
*/
|
|
557
|
+
FindLatestTimestamp(records) {
|
|
558
|
+
const objectName = this._currentObjectName.toLowerCase();
|
|
559
|
+
const primaryField = objectName.includes('action') ? 'created' : 'updated';
|
|
560
|
+
const fallbackField = primaryField === 'updated' ? 'created' : 'updated';
|
|
561
|
+
let latest = null;
|
|
562
|
+
for (const record of records) {
|
|
563
|
+
const dateStr = (record.Fields[primaryField] ?? record.Fields[fallbackField]);
|
|
564
|
+
if (!dateStr)
|
|
565
|
+
continue;
|
|
566
|
+
const date = new Date(dateStr);
|
|
567
|
+
if (!isNaN(date.getTime()) && (latest === null || date > latest)) {
|
|
568
|
+
latest = date;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return latest ? latest.toISOString() : null;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Checks if an error is a timeout or network error.
|
|
575
|
+
*/
|
|
576
|
+
IsTimeoutOrNetworkError(err) {
|
|
577
|
+
if (err instanceof Error) {
|
|
578
|
+
const msg = err.message.toLowerCase();
|
|
579
|
+
return msg.includes('timeout') || msg.includes('abort') ||
|
|
580
|
+
msg.includes('econnreset') || msg.includes('econnrefused') ||
|
|
581
|
+
msg.includes('fetch failed');
|
|
582
|
+
}
|
|
583
|
+
return false;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Sleeps for the specified number of milliseconds.
|
|
587
|
+
*/
|
|
588
|
+
Sleep(ms) {
|
|
589
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
RasaConnector = __decorate([
|
|
593
|
+
RegisterClass(BaseIntegrationConnector, 'RasaConnector')
|
|
594
|
+
], RasaConnector);
|
|
595
|
+
export { RasaConnector };
|
|
596
|
+
//# sourceMappingURL=RasaConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RasaConnector.js","sourceRoot":"","sources":["../src/RasaConnector.ts"],"names":[],"mappings":"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"}
|