@mparticle/web-sdk 2.66.0 → 2.67.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/mparticle.common.js +116 -67
- package/dist/mparticle.esm.js +116 -67
- package/dist/mparticle.js +353 -128
- package/dist/types/src/identity/search.d.ts +64 -0
- package/dist/types/src/identity-utils.d.ts +17 -1
- package/dist/types/src/identity.interfaces.d.ts +37 -1
- package/dist/types/src/public-types.d.ts +1 -1
- package/dist/types/src/stub/mparticle.stub.d.ts +1 -0
- package/package.json +1 -1
- package/src/identity/search.ts +233 -0
- package/src/identity-utils.ts +81 -1
- package/src/identity.interfaces.ts +46 -0
- package/src/identity.js +27 -0
- package/src/mparticle-instance-manager.ts +7 -0
- package/src/public-types.ts +4 -0
- package/src/stub/mparticle.stub.js +1 -0
package/dist/mparticle.js
CHANGED
|
@@ -203,7 +203,7 @@ var mParticle = (function () {
|
|
|
203
203
|
Base64: Base64$1
|
|
204
204
|
};
|
|
205
205
|
|
|
206
|
-
var version = "2.
|
|
206
|
+
var version = "2.67.0";
|
|
207
207
|
|
|
208
208
|
var Constants = {
|
|
209
209
|
sdkVersion: version,
|
|
@@ -417,6 +417,7 @@ var mParticle = (function () {
|
|
|
417
417
|
var HTTP_OK = 200;
|
|
418
418
|
var HTTP_ACCEPTED = 202;
|
|
419
419
|
var HTTP_BAD_REQUEST = 400;
|
|
420
|
+
var HTTP_NOT_FOUND = 404;
|
|
420
421
|
var HTTP_SERVER_ERROR = 500;
|
|
421
422
|
|
|
422
423
|
function _typeof$1(o) {
|
|
@@ -524,7 +525,7 @@ var mParticle = (function () {
|
|
|
524
525
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
525
526
|
};
|
|
526
527
|
|
|
527
|
-
var Messages$
|
|
528
|
+
var Messages$a = Constants.Messages;
|
|
528
529
|
var createCookieString = function createCookieString(value) {
|
|
529
530
|
return replaceCommasWithPipes(replaceQuotesWithApostrophes(value));
|
|
530
531
|
};
|
|
@@ -560,12 +561,12 @@ var mParticle = (function () {
|
|
|
560
561
|
var generateDeprecationMessage = function generateDeprecationMessage(methodName, isDeprecated, alternateMethod, docsUrl) {
|
|
561
562
|
var messageArray = [methodName];
|
|
562
563
|
if (isDeprecated) {
|
|
563
|
-
messageArray.push(Messages$
|
|
564
|
+
messageArray.push(Messages$a.DeprecationMessages.MethodHasBeenDeprecated);
|
|
564
565
|
} else {
|
|
565
|
-
messageArray.push(Messages$
|
|
566
|
+
messageArray.push(Messages$a.DeprecationMessages.MethodMarkedForDeprecationPostfix);
|
|
566
567
|
}
|
|
567
568
|
if (alternateMethod) {
|
|
568
|
-
messageArray.push(Messages$
|
|
569
|
+
messageArray.push(Messages$a.DeprecationMessages.AlternativeMethodPrefix);
|
|
569
570
|
messageArray.push(alternateMethod + ".");
|
|
570
571
|
}
|
|
571
572
|
if (docsUrl) {
|
|
@@ -3118,11 +3119,278 @@ var mParticle = (function () {
|
|
|
3118
3119
|
return BatchUploader;
|
|
3119
3120
|
}();
|
|
3120
3121
|
|
|
3122
|
+
var ErrorCodes = {
|
|
3123
|
+
UNKNOWN_ERROR: 'UNKNOWN_ERROR',
|
|
3124
|
+
UNHANDLED_EXCEPTION: 'UNHANDLED_EXCEPTION',
|
|
3125
|
+
IDENTITY_REQUEST: 'IDENTITY_REQUEST',
|
|
3126
|
+
IDENTITY_MISMATCH: 'IDENTITY_MISMATCH',
|
|
3127
|
+
ROKT_KIT_ATTACHED: 'ROKT_KIT_ATTACHED'
|
|
3128
|
+
};
|
|
3129
|
+
var WSDKErrorSeverity = {
|
|
3130
|
+
ERROR: 'ERROR',
|
|
3131
|
+
INFO: 'INFO',
|
|
3132
|
+
WARNING: 'WARNING'
|
|
3133
|
+
};
|
|
3134
|
+
|
|
3135
|
+
var Modify$4 = Constants.IdentityMethods.Modify;
|
|
3136
|
+
var Validators = {
|
|
3137
|
+
// From ./utils
|
|
3138
|
+
// Utility Functions for backwards compatability
|
|
3139
|
+
isNumber: isNumber,
|
|
3140
|
+
isFunction: isFunction,
|
|
3141
|
+
isStringOrNumber: isStringOrNumber,
|
|
3142
|
+
// Validator Functions
|
|
3143
|
+
isValidAttributeValue: isValidAttributeValue,
|
|
3144
|
+
// Validator Functions
|
|
3145
|
+
// Neither null nor undefined can be a valid Key
|
|
3146
|
+
isValidKeyValue: function isValidKeyValue(key) {
|
|
3147
|
+
return Boolean(key && !isObject(key) && !Array.isArray(key) && !this.isFunction(key));
|
|
3148
|
+
},
|
|
3149
|
+
removeFalsyIdentityValues: function removeFalsyIdentityValues(identityApiData, logger) {
|
|
3150
|
+
if (!identityApiData || !identityApiData.userIdentities) {
|
|
3151
|
+
return identityApiData;
|
|
3152
|
+
}
|
|
3153
|
+
var cleanedData = {};
|
|
3154
|
+
var cleanedUserIdentities = __assign({}, identityApiData.userIdentities);
|
|
3155
|
+
for (var identityType in identityApiData.userIdentities) {
|
|
3156
|
+
if (identityApiData.userIdentities.hasOwnProperty(identityType)) {
|
|
3157
|
+
var value = identityApiData.userIdentities[identityType];
|
|
3158
|
+
// Check if value is falsy (undefined, false, 0, '', etc.) but not null
|
|
3159
|
+
if (value !== null && !value) {
|
|
3160
|
+
logger.warning("Identity value for '".concat(identityType, "' is falsy (").concat(value, "). This value will be removed from the request."));
|
|
3161
|
+
delete cleanedUserIdentities[identityType];
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
cleanedData.userIdentities = cleanedUserIdentities;
|
|
3166
|
+
return cleanedData;
|
|
3167
|
+
},
|
|
3168
|
+
validateIdentities: function validateIdentities(identityApiData, method) {
|
|
3169
|
+
var validIdentityRequestKeys = {
|
|
3170
|
+
userIdentities: 1,
|
|
3171
|
+
onUserAlias: 1,
|
|
3172
|
+
copyUserAttributes: 1
|
|
3173
|
+
};
|
|
3174
|
+
if (identityApiData) {
|
|
3175
|
+
if (method === Modify$4) {
|
|
3176
|
+
if (isObject(identityApiData.userIdentities) && !Object.keys(identityApiData.userIdentities).length || !isObject(identityApiData.userIdentities)) {
|
|
3177
|
+
return {
|
|
3178
|
+
valid: false,
|
|
3179
|
+
error: Constants.Messages.ValidationMessages.ModifyIdentityRequestUserIdentitiesPresent
|
|
3180
|
+
};
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
for (var key in identityApiData) {
|
|
3184
|
+
if (identityApiData.hasOwnProperty(key)) {
|
|
3185
|
+
if (!validIdentityRequestKeys[key]) {
|
|
3186
|
+
return {
|
|
3187
|
+
valid: false,
|
|
3188
|
+
error: Constants.Messages.ValidationMessages.IdentityRequesetInvalidKey
|
|
3189
|
+
};
|
|
3190
|
+
}
|
|
3191
|
+
if (key === 'onUserAlias' && !Validators.isFunction(identityApiData[key])) {
|
|
3192
|
+
return {
|
|
3193
|
+
valid: false,
|
|
3194
|
+
error: Constants.Messages.ValidationMessages.OnUserAliasType
|
|
3195
|
+
};
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
if (Object.keys(identityApiData).length === 0) {
|
|
3200
|
+
return {
|
|
3201
|
+
valid: true
|
|
3202
|
+
};
|
|
3203
|
+
} else {
|
|
3204
|
+
// identityApiData.userIdentities can't be undefined
|
|
3205
|
+
if (identityApiData.userIdentities === undefined) {
|
|
3206
|
+
return {
|
|
3207
|
+
valid: false,
|
|
3208
|
+
error: Constants.Messages.ValidationMessages.UserIdentities
|
|
3209
|
+
};
|
|
3210
|
+
// identityApiData.userIdentities can be null, but if it isn't null or undefined (above conditional), it must be an object
|
|
3211
|
+
} else if (identityApiData.userIdentities !== null && !isObject(identityApiData.userIdentities)) {
|
|
3212
|
+
return {
|
|
3213
|
+
valid: false,
|
|
3214
|
+
error: Constants.Messages.ValidationMessages.UserIdentities
|
|
3215
|
+
};
|
|
3216
|
+
}
|
|
3217
|
+
if (isObject(identityApiData.userIdentities) && Object.keys(identityApiData.userIdentities).length) {
|
|
3218
|
+
for (var identityType in identityApiData.userIdentities) {
|
|
3219
|
+
if (identityApiData.userIdentities.hasOwnProperty(identityType)) {
|
|
3220
|
+
if (Types.IdentityType.getIdentityType(identityType) === false) {
|
|
3221
|
+
return {
|
|
3222
|
+
valid: false,
|
|
3223
|
+
error: Constants.Messages.ValidationMessages.UserIdentitiesInvalidKey
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
if (!(typeof identityApiData.userIdentities[identityType] === 'string' || identityApiData.userIdentities[identityType] === null)) {
|
|
3227
|
+
return {
|
|
3228
|
+
valid: false,
|
|
3229
|
+
error: Constants.Messages.ValidationMessages.UserIdentitiesInvalidValues
|
|
3230
|
+
};
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
return {
|
|
3238
|
+
valid: true
|
|
3239
|
+
};
|
|
3240
|
+
}
|
|
3241
|
+
};
|
|
3242
|
+
|
|
3243
|
+
var HTTPCodes$4 = Constants.HTTPCodes;
|
|
3244
|
+
/**
|
|
3245
|
+
* Sends a POST to mParticle's IDSync Search endpoint and invokes `callback`
|
|
3246
|
+
* with the HTTP status and parsed body.
|
|
3247
|
+
*
|
|
3248
|
+
* Defensive contract:
|
|
3249
|
+
* - No identifier with a non-empty string value -> callback with
|
|
3250
|
+
* `{ httpCode: noHttpCoverage }`, no network call.
|
|
3251
|
+
* - Missing `apiKey` -> callback with `{ httpCode: noHttpCoverage }`,
|
|
3252
|
+
* no network call.
|
|
3253
|
+
* - Network/JSON-parse errors are caught and surfaced via the callback,
|
|
3254
|
+
* never thrown. Network errors are also reported through the optional
|
|
3255
|
+
* `errorReporter` so any registered IErrorReportingService can observe
|
|
3256
|
+
* them (matches the pattern used by identifyRequest in identityApiClient).
|
|
3257
|
+
*/
|
|
3258
|
+
var sendSearchRequest = function sendSearchRequest(knownIdentities, apiKey, requestBuilder, searchUrl, callback, logger, uploader, errorReporter) {
|
|
3259
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
3260
|
+
var safeInvoke, cleanedKnownIdentities, requestEnvelope, requestBody, fetchPayload, api, response, body, xhrLike, e_2, message, reportMessage;
|
|
3261
|
+
return __generator(this, function (_a) {
|
|
3262
|
+
switch (_a.label) {
|
|
3263
|
+
case 0:
|
|
3264
|
+
// Validate the callback up front. If it isn't a function we have nowhere
|
|
3265
|
+
// to deliver a result to, so log and bail out without invoking anything.
|
|
3266
|
+
if (!isFunction(callback)) {
|
|
3267
|
+
logger.error('search called without a callback function; skipping request.');
|
|
3268
|
+
return [2 /*return*/];
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
safeInvoke = function safeInvoke(result) {
|
|
3272
|
+
try {
|
|
3273
|
+
callback(result);
|
|
3274
|
+
} catch (e) {
|
|
3275
|
+
logger.error('Error invoking search callback: ' + ((e === null || e === void 0 ? void 0 : e.message) || String(e)));
|
|
3276
|
+
}
|
|
3277
|
+
};
|
|
3278
|
+
cleanedKnownIdentities = Validators.removeFalsyIdentityValues({
|
|
3279
|
+
userIdentities: knownIdentities !== null && knownIdentities !== void 0 ? knownIdentities : {}
|
|
3280
|
+
}, logger).userIdentities;
|
|
3281
|
+
// No usable identifier -> deliver httpCode: noHttpCoverage so callers
|
|
3282
|
+
// waiting on the callback (e.g. to clear a loading state) don't hang.
|
|
3283
|
+
if (!Object.values(cleanedKnownIdentities !== null && cleanedKnownIdentities !== void 0 ? cleanedKnownIdentities : {}).some(function (v) {
|
|
3284
|
+
return typeof v === 'string' && v.length > 0;
|
|
3285
|
+
})) {
|
|
3286
|
+
logger.verbose('Identity search called with empty identifiers; skipping request.');
|
|
3287
|
+
safeInvoke({
|
|
3288
|
+
httpCode: HTTPCodes$4.noHttpCoverage
|
|
3289
|
+
});
|
|
3290
|
+
return [2 /*return*/];
|
|
3291
|
+
}
|
|
3292
|
+
// No API key -> same: deliver noHttpCoverage rather than hanging.
|
|
3293
|
+
if (!apiKey) {
|
|
3294
|
+
logger.verbose('search called without a workspace API key; skipping request.');
|
|
3295
|
+
safeInvoke({
|
|
3296
|
+
httpCode: HTTPCodes$4.noHttpCoverage
|
|
3297
|
+
});
|
|
3298
|
+
return [2 /*return*/];
|
|
3299
|
+
}
|
|
3300
|
+
|
|
3301
|
+
_a.label = 1;
|
|
3302
|
+
case 1:
|
|
3303
|
+
_a.trys.push([1, 9,, 10]);
|
|
3304
|
+
requestEnvelope = requestBuilder();
|
|
3305
|
+
requestBody = __assign(__assign({}, requestEnvelope), {
|
|
3306
|
+
known_identities: __assign({}, cleanedKnownIdentities)
|
|
3307
|
+
});
|
|
3308
|
+
fetchPayload = {
|
|
3309
|
+
method: 'post',
|
|
3310
|
+
headers: {
|
|
3311
|
+
Accept: 'application/json',
|
|
3312
|
+
'Content-Type': 'application/json',
|
|
3313
|
+
'x-mp-key': apiKey
|
|
3314
|
+
},
|
|
3315
|
+
body: JSON.stringify(requestBody)
|
|
3316
|
+
};
|
|
3317
|
+
api = uploader || (window.fetch ? new FetchUploader(searchUrl) : new XHRUploader(searchUrl));
|
|
3318
|
+
logger.verbose('Sending search request to ' + searchUrl);
|
|
3319
|
+
return [4 /*yield*/, api.upload(fetchPayload, searchUrl)];
|
|
3320
|
+
case 2:
|
|
3321
|
+
response = _a.sent();
|
|
3322
|
+
body = void 0;
|
|
3323
|
+
if (!isFunction(response.json)) return [3 /*break*/, 7];
|
|
3324
|
+
_a.label = 3;
|
|
3325
|
+
case 3:
|
|
3326
|
+
_a.trys.push([3, 5,, 6]);
|
|
3327
|
+
return [4 /*yield*/, response.json()];
|
|
3328
|
+
case 4:
|
|
3329
|
+
body = _a.sent();
|
|
3330
|
+
return [3 /*break*/, 6];
|
|
3331
|
+
case 5:
|
|
3332
|
+
_a.sent();
|
|
3333
|
+
logger.verbose('search response had no parseable JSON body.');
|
|
3334
|
+
return [3 /*break*/, 6];
|
|
3335
|
+
case 6:
|
|
3336
|
+
return [3 /*break*/, 8];
|
|
3337
|
+
case 7:
|
|
3338
|
+
xhrLike = response;
|
|
3339
|
+
if (xhrLike === null || xhrLike === void 0 ? void 0 : xhrLike.responseText) {
|
|
3340
|
+
try {
|
|
3341
|
+
body = JSON.parse(xhrLike.responseText);
|
|
3342
|
+
} catch (e) {
|
|
3343
|
+
logger.verbose('search XHR response was not valid JSON.');
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
_a.label = 8;
|
|
3347
|
+
case 8:
|
|
3348
|
+
if (response.status === HTTP_OK) {
|
|
3349
|
+
logger.verbose('search received 200 OK.');
|
|
3350
|
+
} else if (response.status === HTTP_NOT_FOUND) {
|
|
3351
|
+
// 404 NOT_FOUND_ERROR is an expected steady-state outcome and is
|
|
3352
|
+
// intentionally not logged as an error.
|
|
3353
|
+
logger.verbose('search received 404 (no match).');
|
|
3354
|
+
} else {
|
|
3355
|
+
logger.verbose('search received non-success status ' + response.status);
|
|
3356
|
+
}
|
|
3357
|
+
safeInvoke({
|
|
3358
|
+
httpCode: response.status,
|
|
3359
|
+
body: body
|
|
3360
|
+
});
|
|
3361
|
+
return [3 /*break*/, 10];
|
|
3362
|
+
case 9:
|
|
3363
|
+
e_2 = _a.sent();
|
|
3364
|
+
message = (e_2 === null || e_2 === void 0 ? void 0 : e_2.message) || String(e_2);
|
|
3365
|
+
reportMessage = 'Error sending search request: ' + message;
|
|
3366
|
+
logger.error(reportMessage);
|
|
3367
|
+
// Mirror the identity-route pattern in identityApiClient.ts: log to
|
|
3368
|
+
// console AND push a structured report through the dispatcher so any
|
|
3369
|
+
// registered IErrorReportingService (e.g. the Rokt kit's) can observe
|
|
3370
|
+
// the failure.
|
|
3371
|
+
errorReporter === null || errorReporter === void 0 ? void 0 : errorReporter.report({
|
|
3372
|
+
message: reportMessage,
|
|
3373
|
+
code: ErrorCodes.IDENTITY_REQUEST,
|
|
3374
|
+
severity: WSDKErrorSeverity.ERROR
|
|
3375
|
+
});
|
|
3376
|
+
safeInvoke({
|
|
3377
|
+
httpCode: HTTPCodes$4.noHttpCoverage
|
|
3378
|
+
});
|
|
3379
|
+
return [3 /*break*/, 10];
|
|
3380
|
+
case 10:
|
|
3381
|
+
return [2 /*return*/];
|
|
3382
|
+
}
|
|
3383
|
+
});
|
|
3384
|
+
});
|
|
3385
|
+
};
|
|
3386
|
+
|
|
3121
3387
|
var _a = Constants.IdentityMethods,
|
|
3122
3388
|
Identify$2 = _a.Identify,
|
|
3123
|
-
Modify$
|
|
3389
|
+
Modify$3 = _a.Modify,
|
|
3124
3390
|
Login$2 = _a.Login,
|
|
3125
3391
|
Logout$2 = _a.Logout;
|
|
3392
|
+
var HTTPCodes$3 = Constants.HTTPCodes,
|
|
3393
|
+
Messages$9 = Constants.Messages;
|
|
3126
3394
|
var CACHE_HEADER = 'x-mp-max-age';
|
|
3127
3395
|
var cacheOrClearIdCache = function cacheOrClearIdCache(method, knownIdentities, idCache, identityResponse, parsingCachedResponse) {
|
|
3128
3396
|
// when parsing a response that has already been cached, simply return instead of attempting another cache
|
|
@@ -3136,7 +3404,7 @@ var mParticle = (function () {
|
|
|
3136
3404
|
case Identify$2:
|
|
3137
3405
|
cacheIdentityRequest(method, knownIdentities, expireTimestamp, idCache, identityResponse);
|
|
3138
3406
|
break;
|
|
3139
|
-
case Modify$
|
|
3407
|
+
case Modify$3:
|
|
3140
3408
|
case Logout$2:
|
|
3141
3409
|
idCache.purge();
|
|
3142
3410
|
break;
|
|
@@ -3292,6 +3560,61 @@ var mParticle = (function () {
|
|
|
3292
3560
|
}
|
|
3293
3561
|
return !!((_c = store === null || store === void 0 ? void 0 : store.SDKConfig) === null || _c === void 0 ? void 0 : _c.deviceId);
|
|
3294
3562
|
};
|
|
3563
|
+
/**
|
|
3564
|
+
* Builds the /v1/identify-style envelope (client_sdk, environment,
|
|
3565
|
+
* request_id, request_timestamp_ms) used to correlate IDSync requests
|
|
3566
|
+
* across endpoints. `known_identities` is omitted so the caller can
|
|
3567
|
+
* fold in the search-specific identifiers alongside the envelope.
|
|
3568
|
+
*/
|
|
3569
|
+
var buildIdentitySearchEnvelope = function buildIdentitySearchEnvelope(environment) {
|
|
3570
|
+
return {
|
|
3571
|
+
client_sdk: {
|
|
3572
|
+
platform: Constants.platform,
|
|
3573
|
+
sdk_vendor: Constants.sdkVendor,
|
|
3574
|
+
sdk_version: Constants.sdkVersion
|
|
3575
|
+
},
|
|
3576
|
+
environment: environment,
|
|
3577
|
+
request_id: generateUniqueId(),
|
|
3578
|
+
request_timestamp_ms: Date.now()
|
|
3579
|
+
};
|
|
3580
|
+
};
|
|
3581
|
+
/**
|
|
3582
|
+
* Wires the SDK instance into `sendSearchRequest`: gates on `canLog`,
|
|
3583
|
+
* builds the `/v1/search` URL and request envelope, and dispatches.
|
|
3584
|
+
* Lives here so the SDK glue (URL building, opt-out gate, dispatcher
|
|
3585
|
+
* plumbing) is type-checked instead of being expressed in plain JS.
|
|
3586
|
+
*/
|
|
3587
|
+
var executeSearchRequest = function executeSearchRequest(mpInstance, workspaceApiKey, knownIdentities, callback) {
|
|
3588
|
+
var _Helpers = mpInstance._Helpers,
|
|
3589
|
+
_Store = mpInstance._Store,
|
|
3590
|
+
Logger = mpInstance.Logger,
|
|
3591
|
+
_ErrorReportingDispatcher = mpInstance._ErrorReportingDispatcher;
|
|
3592
|
+
var _a = _Store.SDKConfig,
|
|
3593
|
+
identityUrl = _a.identityUrl,
|
|
3594
|
+
isDevelopmentMode = _a.isDevelopmentMode;
|
|
3595
|
+
if (!_Helpers.canLog()) {
|
|
3596
|
+
Logger.verbose(Messages$9.InformationMessages.AbandonLogEvent);
|
|
3597
|
+
if (isFunction(callback)) {
|
|
3598
|
+
try {
|
|
3599
|
+
callback({
|
|
3600
|
+
httpCode: HTTPCodes$3.loggingDisabledOrMissingAPIKey
|
|
3601
|
+
});
|
|
3602
|
+
} catch (e) {
|
|
3603
|
+
Logger.error('Error invoking search callback: ' + ((e === null || e === void 0 ? void 0 : e.message) || String(e)));
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
return;
|
|
3607
|
+
}
|
|
3608
|
+
// The Search endpoint is colocated with /v1/identify under
|
|
3609
|
+
// identityUrl, so we reuse the same service URL builder. We do
|
|
3610
|
+
// NOT append the apiKey to the URL — auth is done via x-mp-key.
|
|
3611
|
+
var serviceUrl = _Helpers.createServiceUrl(identityUrl);
|
|
3612
|
+
var searchUrl = serviceUrl + 'search?cb=1';
|
|
3613
|
+
var environment = isDevelopmentMode ? 'development' : 'production';
|
|
3614
|
+
sendSearchRequest(knownIdentities, workspaceApiKey, function () {
|
|
3615
|
+
return buildIdentitySearchEnvelope(environment);
|
|
3616
|
+
}, searchUrl, callback, Logger, undefined, _ErrorReportingDispatcher);
|
|
3617
|
+
};
|
|
3295
3618
|
|
|
3296
3619
|
function APIClient(mpInstance, kitBlocker) {
|
|
3297
3620
|
this.uploader = null;
|
|
@@ -3454,114 +3777,6 @@ var mParticle = (function () {
|
|
|
3454
3777
|
};
|
|
3455
3778
|
}
|
|
3456
3779
|
|
|
3457
|
-
var Modify$3 = Constants.IdentityMethods.Modify;
|
|
3458
|
-
var Validators = {
|
|
3459
|
-
// From ./utils
|
|
3460
|
-
// Utility Functions for backwards compatability
|
|
3461
|
-
isNumber: isNumber,
|
|
3462
|
-
isFunction: isFunction,
|
|
3463
|
-
isStringOrNumber: isStringOrNumber,
|
|
3464
|
-
// Validator Functions
|
|
3465
|
-
isValidAttributeValue: isValidAttributeValue,
|
|
3466
|
-
// Validator Functions
|
|
3467
|
-
// Neither null nor undefined can be a valid Key
|
|
3468
|
-
isValidKeyValue: function isValidKeyValue(key) {
|
|
3469
|
-
return Boolean(key && !isObject(key) && !Array.isArray(key) && !this.isFunction(key));
|
|
3470
|
-
},
|
|
3471
|
-
removeFalsyIdentityValues: function removeFalsyIdentityValues(identityApiData, logger) {
|
|
3472
|
-
if (!identityApiData || !identityApiData.userIdentities) {
|
|
3473
|
-
return identityApiData;
|
|
3474
|
-
}
|
|
3475
|
-
var cleanedData = {};
|
|
3476
|
-
var cleanedUserIdentities = __assign({}, identityApiData.userIdentities);
|
|
3477
|
-
for (var identityType in identityApiData.userIdentities) {
|
|
3478
|
-
if (identityApiData.userIdentities.hasOwnProperty(identityType)) {
|
|
3479
|
-
var value = identityApiData.userIdentities[identityType];
|
|
3480
|
-
// Check if value is falsy (undefined, false, 0, '', etc.) but not null
|
|
3481
|
-
if (value !== null && !value) {
|
|
3482
|
-
logger.warning("Identity value for '".concat(identityType, "' is falsy (").concat(value, "). This value will be removed from the request."));
|
|
3483
|
-
delete cleanedUserIdentities[identityType];
|
|
3484
|
-
}
|
|
3485
|
-
}
|
|
3486
|
-
}
|
|
3487
|
-
cleanedData.userIdentities = cleanedUserIdentities;
|
|
3488
|
-
return cleanedData;
|
|
3489
|
-
},
|
|
3490
|
-
validateIdentities: function validateIdentities(identityApiData, method) {
|
|
3491
|
-
var validIdentityRequestKeys = {
|
|
3492
|
-
userIdentities: 1,
|
|
3493
|
-
onUserAlias: 1,
|
|
3494
|
-
copyUserAttributes: 1
|
|
3495
|
-
};
|
|
3496
|
-
if (identityApiData) {
|
|
3497
|
-
if (method === Modify$3) {
|
|
3498
|
-
if (isObject(identityApiData.userIdentities) && !Object.keys(identityApiData.userIdentities).length || !isObject(identityApiData.userIdentities)) {
|
|
3499
|
-
return {
|
|
3500
|
-
valid: false,
|
|
3501
|
-
error: Constants.Messages.ValidationMessages.ModifyIdentityRequestUserIdentitiesPresent
|
|
3502
|
-
};
|
|
3503
|
-
}
|
|
3504
|
-
}
|
|
3505
|
-
for (var key in identityApiData) {
|
|
3506
|
-
if (identityApiData.hasOwnProperty(key)) {
|
|
3507
|
-
if (!validIdentityRequestKeys[key]) {
|
|
3508
|
-
return {
|
|
3509
|
-
valid: false,
|
|
3510
|
-
error: Constants.Messages.ValidationMessages.IdentityRequesetInvalidKey
|
|
3511
|
-
};
|
|
3512
|
-
}
|
|
3513
|
-
if (key === 'onUserAlias' && !Validators.isFunction(identityApiData[key])) {
|
|
3514
|
-
return {
|
|
3515
|
-
valid: false,
|
|
3516
|
-
error: Constants.Messages.ValidationMessages.OnUserAliasType
|
|
3517
|
-
};
|
|
3518
|
-
}
|
|
3519
|
-
}
|
|
3520
|
-
}
|
|
3521
|
-
if (Object.keys(identityApiData).length === 0) {
|
|
3522
|
-
return {
|
|
3523
|
-
valid: true
|
|
3524
|
-
};
|
|
3525
|
-
} else {
|
|
3526
|
-
// identityApiData.userIdentities can't be undefined
|
|
3527
|
-
if (identityApiData.userIdentities === undefined) {
|
|
3528
|
-
return {
|
|
3529
|
-
valid: false,
|
|
3530
|
-
error: Constants.Messages.ValidationMessages.UserIdentities
|
|
3531
|
-
};
|
|
3532
|
-
// identityApiData.userIdentities can be null, but if it isn't null or undefined (above conditional), it must be an object
|
|
3533
|
-
} else if (identityApiData.userIdentities !== null && !isObject(identityApiData.userIdentities)) {
|
|
3534
|
-
return {
|
|
3535
|
-
valid: false,
|
|
3536
|
-
error: Constants.Messages.ValidationMessages.UserIdentities
|
|
3537
|
-
};
|
|
3538
|
-
}
|
|
3539
|
-
if (isObject(identityApiData.userIdentities) && Object.keys(identityApiData.userIdentities).length) {
|
|
3540
|
-
for (var identityType in identityApiData.userIdentities) {
|
|
3541
|
-
if (identityApiData.userIdentities.hasOwnProperty(identityType)) {
|
|
3542
|
-
if (Types.IdentityType.getIdentityType(identityType) === false) {
|
|
3543
|
-
return {
|
|
3544
|
-
valid: false,
|
|
3545
|
-
error: Constants.Messages.ValidationMessages.UserIdentitiesInvalidKey
|
|
3546
|
-
};
|
|
3547
|
-
}
|
|
3548
|
-
if (!(typeof identityApiData.userIdentities[identityType] === 'string' || identityApiData.userIdentities[identityType] === null)) {
|
|
3549
|
-
return {
|
|
3550
|
-
valid: false,
|
|
3551
|
-
error: Constants.Messages.ValidationMessages.UserIdentitiesInvalidValues
|
|
3552
|
-
};
|
|
3553
|
-
}
|
|
3554
|
-
}
|
|
3555
|
-
}
|
|
3556
|
-
}
|
|
3557
|
-
}
|
|
3558
|
-
}
|
|
3559
|
-
return {
|
|
3560
|
-
valid: true
|
|
3561
|
-
};
|
|
3562
|
-
}
|
|
3563
|
-
};
|
|
3564
|
-
|
|
3565
3780
|
var KitFilterHelper = /** @class */function () {
|
|
3566
3781
|
function KitFilterHelper() {}
|
|
3567
3782
|
KitFilterHelper.hashEventType = function (eventType) {
|
|
@@ -8130,6 +8345,26 @@ var mParticle = (function () {
|
|
|
8130
8345
|
mpInstance.Logger.verbose(Messages$2.InformationMessages.AbandonAliasUsers);
|
|
8131
8346
|
}
|
|
8132
8347
|
},
|
|
8348
|
+
/**
|
|
8349
|
+
* Search the IDSync Workspace endpoint for a known identity.
|
|
8350
|
+
*
|
|
8351
|
+
* POSTs to mParticle's `/v1/search` endpoint and invokes `callback`
|
|
8352
|
+
* with `{ httpCode, body? }`.
|
|
8353
|
+
*
|
|
8354
|
+
* The `workspaceApiKey` is a workspace-specific API key supplied by
|
|
8355
|
+
* the caller (passed in from a kit's settings). It is intentionally
|
|
8356
|
+
* NOT read from the SDK's own workspace token, so that workspace
|
|
8357
|
+
* searches can be authorised independently of the host SDK's
|
|
8358
|
+
* workspace.
|
|
8359
|
+
*
|
|
8360
|
+
* @method search
|
|
8361
|
+
* @param {String} workspaceApiKey Workspace API key (sent as x-mp-key).
|
|
8362
|
+
* @param {Object} knownIdentities A `UserIdentities` map.
|
|
8363
|
+
* @param {Function} callback Invoked with the `IIdentitySearchResult`.
|
|
8364
|
+
*/
|
|
8365
|
+
search: function search(workspaceApiKey, knownIdentities, callback) {
|
|
8366
|
+
executeSearchRequest(mpInstance, workspaceApiKey, knownIdentities, callback);
|
|
8367
|
+
},
|
|
8133
8368
|
/**
|
|
8134
8369
|
Create a default AliasRequest for 2 MParticleUsers. This will construct the request
|
|
8135
8370
|
using the sourceUser's firstSeenTime as the startTime, and its lastSeenTime as the endTime.
|
|
@@ -9599,19 +9834,6 @@ var mParticle = (function () {
|
|
|
9599
9834
|
};
|
|
9600
9835
|
}
|
|
9601
9836
|
|
|
9602
|
-
var ErrorCodes = {
|
|
9603
|
-
UNKNOWN_ERROR: 'UNKNOWN_ERROR',
|
|
9604
|
-
UNHANDLED_EXCEPTION: 'UNHANDLED_EXCEPTION',
|
|
9605
|
-
IDENTITY_REQUEST: 'IDENTITY_REQUEST',
|
|
9606
|
-
IDENTITY_MISMATCH: 'IDENTITY_MISMATCH',
|
|
9607
|
-
ROKT_KIT_ATTACHED: 'ROKT_KIT_ATTACHED'
|
|
9608
|
-
};
|
|
9609
|
-
var WSDKErrorSeverity = {
|
|
9610
|
-
ERROR: 'ERROR',
|
|
9611
|
-
INFO: 'INFO',
|
|
9612
|
-
WARNING: 'WARNING'
|
|
9613
|
-
};
|
|
9614
|
-
|
|
9615
9837
|
var HTTPCodes$1 = Constants.HTTPCodes,
|
|
9616
9838
|
Messages$1 = Constants.Messages,
|
|
9617
9839
|
IdentityMethods = Constants.IdentityMethods;
|
|
@@ -12446,6 +12668,9 @@ var mParticle = (function () {
|
|
|
12446
12668
|
},
|
|
12447
12669
|
modify: function modify(identityApiData, callback) {
|
|
12448
12670
|
self.getInstance().Identity.modify(identityApiData, callback);
|
|
12671
|
+
},
|
|
12672
|
+
search: function search(workspaceApiKey, knownIdentities, callback) {
|
|
12673
|
+
self.getInstance().Identity.search(workspaceApiKey, knownIdentities, callback);
|
|
12449
12674
|
}
|
|
12450
12675
|
};
|
|
12451
12676
|
this.sessionManager = {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { SDKLoggerApi } from '../sdkRuntimeModels';
|
|
2
|
+
import { Environment } from '../utils';
|
|
3
|
+
import { AsyncUploader } from '../uploaders';
|
|
4
|
+
import { IErrorReportingService } from '../reporting/types';
|
|
5
|
+
import { UserIdentities } from '@mparticle/web-sdk';
|
|
6
|
+
/**
|
|
7
|
+
* Body payload returned by the `/v1/search` endpoint, as parsed JSON.
|
|
8
|
+
*
|
|
9
|
+
* The shape mirrors `/v1/identify` responses. All fields are optional because
|
|
10
|
+
* non-200 responses (e.g. 404 NOT_FOUND_ERROR) may include partial or
|
|
11
|
+
* error-shaped bodies, and the consumer should only rely on body fields when
|
|
12
|
+
* `httpCode === 200`.
|
|
13
|
+
*/
|
|
14
|
+
export interface IIdentitySearchResponseBody {
|
|
15
|
+
context?: string | null;
|
|
16
|
+
mpid?: string;
|
|
17
|
+
matched_identities?: Record<string, string>;
|
|
18
|
+
is_ephemeral?: boolean;
|
|
19
|
+
is_logged_in?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Result delivered to the consumer's callback. `httpCode` is always present;
|
|
23
|
+
* `body` is present whenever the response had a parseable JSON body.
|
|
24
|
+
*
|
|
25
|
+
* For non-network errors (missing API key, validation failures, JSON parse
|
|
26
|
+
* errors) `httpCode` will be `HTTPCodes.noHttpCoverage` (-1) and `body` will
|
|
27
|
+
* be omitted. The consumer is expected to gate behaviour on
|
|
28
|
+
* `httpCode === 200`.
|
|
29
|
+
*/
|
|
30
|
+
export interface IIdentitySearchResult {
|
|
31
|
+
httpCode: number;
|
|
32
|
+
body?: IIdentitySearchResponseBody;
|
|
33
|
+
}
|
|
34
|
+
export type IdentitySearchCallback = (result: IIdentitySearchResult) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Body posted to `/v1/search`. Mirrors the `/v1/identify` request envelope so
|
|
37
|
+
* that the IDSync service can correlate requests across endpoints.
|
|
38
|
+
*/
|
|
39
|
+
export interface IIdentitySearchRequestBody {
|
|
40
|
+
client_sdk: {
|
|
41
|
+
platform: string;
|
|
42
|
+
sdk_vendor: string;
|
|
43
|
+
sdk_version: string;
|
|
44
|
+
};
|
|
45
|
+
environment: Environment;
|
|
46
|
+
request_id: string;
|
|
47
|
+
request_timestamp_ms: number;
|
|
48
|
+
known_identities: UserIdentities;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Sends a POST to mParticle's IDSync Search endpoint and invokes `callback`
|
|
52
|
+
* with the HTTP status and parsed body.
|
|
53
|
+
*
|
|
54
|
+
* Defensive contract:
|
|
55
|
+
* - No identifier with a non-empty string value -> callback with
|
|
56
|
+
* `{ httpCode: noHttpCoverage }`, no network call.
|
|
57
|
+
* - Missing `apiKey` -> callback with `{ httpCode: noHttpCoverage }`,
|
|
58
|
+
* no network call.
|
|
59
|
+
* - Network/JSON-parse errors are caught and surfaced via the callback,
|
|
60
|
+
* never thrown. Network errors are also reported through the optional
|
|
61
|
+
* `errorReporter` so any registered IErrorReportingService can observe
|
|
62
|
+
* them (matches the pattern used by identifyRequest in identityApiClient).
|
|
63
|
+
*/
|
|
64
|
+
export declare const sendSearchRequest: (knownIdentities: UserIdentities, apiKey: string, requestBuilder: () => Omit<IIdentitySearchRequestBody, 'known_identities'>, searchUrl: string, callback: IdentitySearchCallback, logger: SDKLoggerApi, uploader?: AsyncUploader, errorReporter?: IErrorReportingService) => Promise<void>;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Dictionary } from './utils';
|
|
1
|
+
import { Dictionary, Environment } from './utils';
|
|
2
2
|
import { BaseVault } from './vault';
|
|
3
3
|
import { IdentityApiData, UserIdentities, IdentityCallback } from '@mparticle/web-sdk';
|
|
4
4
|
import { IdentityAPIMethod } from './identity.interfaces';
|
|
5
5
|
import { IIdentityResponse, IMParticleUser } from './identity-user-interfaces';
|
|
6
6
|
import { IStore } from './store';
|
|
7
|
+
import type { IMParticleWebSDKInstance } from './mp-instance';
|
|
8
|
+
import { IIdentitySearchRequestBody, IdentitySearchCallback } from './identity/search';
|
|
7
9
|
export declare const CACHE_HEADER: "x-mp-max-age";
|
|
8
10
|
export type IdentityCache = BaseVault<Dictionary<ICachedIdentityCall>>;
|
|
9
11
|
export type IParseCachedIdentityResponse = (cachedIdentity: IIdentityResponse, mpid: string, callback: IdentityCallback, identityApiData: IdentityApiData, identityMethod: string, knownIdentities: IKnownIdentities, fromCachedIdentity: boolean) => void;
|
|
@@ -34,3 +36,17 @@ export declare const hasIdentityRequestChanged: (currentUser: IMParticleUser, ne
|
|
|
34
36
|
* @returns true if deviceId or other identifiers were explicitly provided in config, false otherwise
|
|
35
37
|
*/
|
|
36
38
|
export declare const hasExplicitIdentifier: (store: IStore | undefined | null) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Builds the /v1/identify-style envelope (client_sdk, environment,
|
|
41
|
+
* request_id, request_timestamp_ms) used to correlate IDSync requests
|
|
42
|
+
* across endpoints. `known_identities` is omitted so the caller can
|
|
43
|
+
* fold in the search-specific identifiers alongside the envelope.
|
|
44
|
+
*/
|
|
45
|
+
export declare const buildIdentitySearchEnvelope: (environment: Environment) => Omit<IIdentitySearchRequestBody, 'known_identities'>;
|
|
46
|
+
/**
|
|
47
|
+
* Wires the SDK instance into `sendSearchRequest`: gates on `canLog`,
|
|
48
|
+
* builds the `/v1/search` URL and request envelope, and dispatches.
|
|
49
|
+
* Lives here so the SDK glue (URL building, opt-out gate, dispatcher
|
|
50
|
+
* plumbing) is type-checked instead of being expressed in plain JS.
|
|
51
|
+
*/
|
|
52
|
+
export declare const executeSearchRequest: (mpInstance: IMParticleWebSDKInstance, workspaceApiKey: string, knownIdentities: UserIdentities, callback: IdentitySearchCallback) => void;
|