react-native-my-survey-sdk 2.2.24 → 2.2.26
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/package.json
CHANGED
|
@@ -39,6 +39,57 @@ export function buildFeedbackBaseURL(resolvedZone: string, environment: XeboEnvi
|
|
|
39
39
|
: `https://${resolvedZone}-feedback-api.xebo.ai`;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
export function buildVerifyURL(environment: XeboEnvironment): string {
|
|
43
|
+
return environment === 'uat'
|
|
44
|
+
? 'https://uat-api.xebo.ai/api/v1/api-key/verify'
|
|
45
|
+
: 'https://api.xebo.ai/api/v1/api-key/verify';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ─── Step 0: API key verification → bearer token ─────────────────────────────
|
|
49
|
+
|
|
50
|
+
export async function verifyApiKey(
|
|
51
|
+
verifyURL: string,
|
|
52
|
+
zone: string,
|
|
53
|
+
apiKey: string,
|
|
54
|
+
): Promise<string> {
|
|
55
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
56
|
+
console.log('[Xebo Step 0] Verifying API key');
|
|
57
|
+
console.log('URL:', verifyURL);
|
|
58
|
+
|
|
59
|
+
const res = await fetch(verifyURL, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: { 'Content-Type': 'application/json' },
|
|
62
|
+
body: JSON.stringify({ zone, apiKey }),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const json = await res.json();
|
|
66
|
+
console.log('[Xebo] Verify response status:', res.status);
|
|
67
|
+
console.log('[Xebo] Verify response:', JSON.stringify(json));
|
|
68
|
+
|
|
69
|
+
if (!res.ok) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`[Xebo] verifyApiKey failed — HTTP ${res.status}: ${JSON.stringify(json)}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const token: string | undefined =
|
|
76
|
+
json?.token ??
|
|
77
|
+
json?.data?.token ??
|
|
78
|
+
json?.access_token ??
|
|
79
|
+
json?.bearerToken ??
|
|
80
|
+
json?.data?.access_token;
|
|
81
|
+
|
|
82
|
+
if (!token) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`[Xebo] verifyApiKey — bearer token not found in response: ${JSON.stringify(json)}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log('[Xebo] Bearer token obtained successfully');
|
|
89
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
90
|
+
return token;
|
|
91
|
+
}
|
|
92
|
+
|
|
42
93
|
// ─── HTML stripping ───────────────────────────────────────────────────────────
|
|
43
94
|
|
|
44
95
|
export function stripHTML(raw: string | undefined): string {
|
|
@@ -261,7 +312,7 @@ export interface CollectorInfo {
|
|
|
261
312
|
export async function fetchCollector(
|
|
262
313
|
baseURL: string,
|
|
263
314
|
collectorId: string,
|
|
264
|
-
|
|
315
|
+
bearerToken: string,
|
|
265
316
|
): Promise<CollectorInfo> {
|
|
266
317
|
const url = `${baseURL}/v3/collectors/collect/${collectorId}`;
|
|
267
318
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
@@ -269,7 +320,7 @@ export async function fetchCollector(
|
|
|
269
320
|
console.log('URL:', url);
|
|
270
321
|
console.log('Collector ID:', collectorId);
|
|
271
322
|
|
|
272
|
-
const res = await fetch(url, { headers: { '
|
|
323
|
+
const res = await fetch(url, { headers: { 'Authorization': `Bearer ${bearerToken}` } });
|
|
273
324
|
const json: APICollectorResponse = await res.json();
|
|
274
325
|
|
|
275
326
|
// The API may return the collector object directly at the root OR wrapped in a `data` key
|
|
@@ -299,14 +350,14 @@ export async function fetchCollector(
|
|
|
299
350
|
export async function fetchSurvey(
|
|
300
351
|
baseURL: string,
|
|
301
352
|
surveyId: string,
|
|
302
|
-
|
|
353
|
+
bearerToken: string,
|
|
303
354
|
): Promise<XeboSurvey> {
|
|
304
355
|
const url = `${baseURL}/v3/survey-management/surveys/${surveyId}`;
|
|
305
356
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
306
357
|
console.log('[Xebo Step 2] Fetching survey');
|
|
307
358
|
console.log('URL:', url);
|
|
308
359
|
|
|
309
|
-
const res = await fetch(url, { headers: { '
|
|
360
|
+
const res = await fetch(url, { headers: { 'Authorization': `Bearer ${bearerToken}` } });
|
|
310
361
|
const json: APISurveyResponse = await res.json();
|
|
311
362
|
|
|
312
363
|
console.log('[Xebo] Survey HTTP status:', res.status);
|
|
@@ -346,7 +397,7 @@ export async function submitResponse(
|
|
|
346
397
|
feedbackBaseURL: string,
|
|
347
398
|
surveyId: string,
|
|
348
399
|
collectorUUID: string,
|
|
349
|
-
|
|
400
|
+
bearerToken: string,
|
|
350
401
|
answers: XeboAnswer[],
|
|
351
402
|
meta?: SubmitMeta,
|
|
352
403
|
): Promise<SubmitResult> {
|
|
@@ -373,7 +424,9 @@ export async function submitResponse(
|
|
|
373
424
|
|
|
374
425
|
const payload: Record<string, unknown> = {
|
|
375
426
|
collector_id: collectorUUID,
|
|
376
|
-
...(meta?.
|
|
427
|
+
...(meta?.qualityFlags && { qualityFlags: meta.qualityFlags }),
|
|
428
|
+
...(meta?.deviceInfo && { deviceInfo: meta.deviceInfo }),
|
|
429
|
+
...(meta?.geolocation && { geoLocation: meta.geolocation }),
|
|
377
430
|
responses: [
|
|
378
431
|
{
|
|
379
432
|
response_status: 'complete',
|
|
@@ -387,9 +440,6 @@ export async function submitResponse(
|
|
|
387
440
|
text: v.text || null,
|
|
388
441
|
})),
|
|
389
442
|
})),
|
|
390
|
-
...(meta?.qualityFlags && { qualityFlags: meta.qualityFlags }),
|
|
391
|
-
...(meta?.deviceInfo && { deviceInfo: meta.deviceInfo }),
|
|
392
|
-
...(meta?.geolocation && { geoLocation: meta.geolocation }),
|
|
393
443
|
},
|
|
394
444
|
],
|
|
395
445
|
};
|
|
@@ -412,7 +462,7 @@ export async function submitResponse(
|
|
|
412
462
|
const res = await fetch(url, {
|
|
413
463
|
method: 'POST',
|
|
414
464
|
headers: {
|
|
415
|
-
'
|
|
465
|
+
'Authorization': `Bearer ${bearerToken}`,
|
|
416
466
|
'Content-Type': 'application/json',
|
|
417
467
|
'User-Agent': userAgent,
|
|
418
468
|
},
|
|
@@ -47,6 +47,8 @@ import {
|
|
|
47
47
|
resolveZoneAndEnv,
|
|
48
48
|
buildBaseURL,
|
|
49
49
|
buildFeedbackBaseURL,
|
|
50
|
+
buildVerifyURL,
|
|
51
|
+
verifyApiKey,
|
|
50
52
|
fetchCollector,
|
|
51
53
|
fetchSurvey,
|
|
52
54
|
submitResponse,
|
|
@@ -73,6 +75,8 @@ class XeboSurveyManagerClass extends SimpleEventEmitter {
|
|
|
73
75
|
private environment: XeboEnvironment = 'production';
|
|
74
76
|
private baseURL = '';
|
|
75
77
|
private feedbackBaseURL = '';
|
|
78
|
+
private verifyURL = '';
|
|
79
|
+
private bearerToken = '';
|
|
76
80
|
|
|
77
81
|
// User / eData
|
|
78
82
|
private userData: XeboUserData | null = null;
|
|
@@ -108,6 +112,7 @@ class XeboSurveyManagerClass extends SimpleEventEmitter {
|
|
|
108
112
|
this.environment = environment;
|
|
109
113
|
this.baseURL = buildBaseURL(this.resolvedZone, this.environment);
|
|
110
114
|
this.feedbackBaseURL = buildFeedbackBaseURL(this.resolvedZone, this.environment);
|
|
115
|
+
this.verifyURL = buildVerifyURL(this.environment);
|
|
111
116
|
|
|
112
117
|
// Capture device info once at configure time
|
|
113
118
|
this.deviceModel = `${DeviceInfo.getModel()} (${DeviceInfo.getSystemName()})`;
|
|
@@ -151,15 +156,22 @@ class XeboSurveyManagerClass extends SimpleEventEmitter {
|
|
|
151
156
|
});
|
|
152
157
|
}
|
|
153
158
|
|
|
159
|
+
// ─── Step 0: Verify API key → bearer token ────────────────────────────────
|
|
160
|
+
|
|
161
|
+
private async _verifyAndGetToken(): Promise<void> {
|
|
162
|
+
this.bearerToken = await verifyApiKey(this.verifyURL, this.resolvedZone, this.apiKey);
|
|
163
|
+
}
|
|
164
|
+
|
|
154
165
|
// ─── Background pre-fetch ──────────────────────────────────────────────────
|
|
155
166
|
|
|
156
167
|
private async _prefetchSurvey(): Promise<void> {
|
|
157
168
|
try {
|
|
158
169
|
console.log('[Xebo] Pre-fetching survey in background...');
|
|
159
|
-
|
|
170
|
+
await this._verifyAndGetToken();
|
|
171
|
+
const collector = await fetchCollector(this.baseURL, this.collectorId, this.bearerToken);
|
|
160
172
|
this.resolvedCollectorUUID = collector.uuid;
|
|
161
173
|
this.resolvedCollectorMongoId = collector.mongoId;
|
|
162
|
-
const survey = await fetchSurvey(this.baseURL, collector.surveyId, this.
|
|
174
|
+
const survey = await fetchSurvey(this.baseURL, collector.surveyId, this.bearerToken);
|
|
163
175
|
this.survey = survey;
|
|
164
176
|
this.emit(XEBO_EVENTS.SURVEY_LOADED, survey);
|
|
165
177
|
console.log('[Xebo] Pre-fetch done —', survey.questions.length, 'questions ready');
|
|
@@ -187,14 +199,17 @@ class XeboSurveyManagerClass extends SimpleEventEmitter {
|
|
|
187
199
|
return;
|
|
188
200
|
}
|
|
189
201
|
|
|
190
|
-
// Not cached yet — fetch now
|
|
202
|
+
// Not cached yet — verify + fetch now
|
|
203
|
+
console.log('[Xebo] Step 0: verifyApiKey');
|
|
204
|
+
await this._verifyAndGetToken();
|
|
205
|
+
|
|
191
206
|
console.log('[Xebo] Step 1: fetchCollector');
|
|
192
|
-
const collector = await fetchCollector(this.baseURL, this.collectorId, this.
|
|
207
|
+
const collector = await fetchCollector(this.baseURL, this.collectorId, this.bearerToken);
|
|
193
208
|
this.resolvedCollectorUUID = collector.uuid;
|
|
194
209
|
this.resolvedCollectorMongoId = collector.mongoId;
|
|
195
210
|
|
|
196
211
|
console.log('[Xebo] Step 2: fetchSurvey');
|
|
197
|
-
const survey = await fetchSurvey(this.baseURL, collector.surveyId, this.
|
|
212
|
+
const survey = await fetchSurvey(this.baseURL, collector.surveyId, this.bearerToken);
|
|
198
213
|
this.survey = survey;
|
|
199
214
|
this.currentAnswers = [];
|
|
200
215
|
this.currentQuestionIndex = 0;
|
|
@@ -299,7 +314,7 @@ class XeboSurveyManagerClass extends SimpleEventEmitter {
|
|
|
299
314
|
this.feedbackBaseURL,
|
|
300
315
|
this.survey.id,
|
|
301
316
|
this.resolvedCollectorUUID,
|
|
302
|
-
this.
|
|
317
|
+
this.bearerToken,
|
|
303
318
|
this.currentAnswers,
|
|
304
319
|
{
|
|
305
320
|
userData: this.userData ?? undefined,
|
|
@@ -370,7 +385,7 @@ class XeboSurveyManagerClass extends SimpleEventEmitter {
|
|
|
370
385
|
this.feedbackBaseURL,
|
|
371
386
|
queued.surveyId,
|
|
372
387
|
queued.collectorUUID,
|
|
373
|
-
this.
|
|
388
|
+
this.bearerToken,
|
|
374
389
|
queued.answers,
|
|
375
390
|
{
|
|
376
391
|
userData: queued.userData,
|