@purespectrum1/purescore-client 0.7.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/README.md +55 -0
- package/lib/application/auto-init.d.ts +44 -0
- package/lib/application/auto-init.js +245 -0
- package/lib/application/device-identifier.d.ts +116 -0
- package/lib/application/device-identifier.js +169 -0
- package/lib/domain/models/crosscutting/device-intelligence.d.ts +11 -0
- package/lib/domain/models/crosscutting/device-intelligence.js +18 -0
- package/lib/domain/models/crosscutting/index.d.ts +1 -0
- package/lib/domain/models/crosscutting/index.js +17 -0
- package/lib/domain/protocols/cache/get-storage.d.ts +8 -0
- package/lib/domain/protocols/cache/get-storage.js +2 -0
- package/lib/domain/protocols/cache/index.d.ts +3 -0
- package/lib/domain/protocols/cache/index.js +19 -0
- package/lib/domain/protocols/cache/remove-storage.d.ts +6 -0
- package/lib/domain/protocols/cache/remove-storage.js +2 -0
- package/lib/domain/protocols/cache/set-storage.d.ts +7 -0
- package/lib/domain/protocols/cache/set-storage.js +2 -0
- package/lib/domain/protocols/http/http-client.d.ts +23 -0
- package/lib/domain/protocols/http/http-client.js +13 -0
- package/lib/domain/protocols/services/behavioural-biometrics/cursor-behavior.d.ts +63 -0
- package/lib/domain/protocols/services/behavioural-biometrics/cursor-behavior.js +2 -0
- package/lib/domain/protocols/services/behavioural-biometrics/index.d.ts +3 -0
- package/lib/domain/protocols/services/behavioural-biometrics/index.js +19 -0
- package/lib/domain/protocols/services/behavioural-biometrics/keystorke-metrics.d.ts +35 -0
- package/lib/domain/protocols/services/behavioural-biometrics/keystorke-metrics.js +2 -0
- package/lib/domain/protocols/services/behavioural-biometrics/touch-behavior.d.ts +88 -0
- package/lib/domain/protocols/services/behavioural-biometrics/touch-behavior.js +2 -0
- package/lib/domain/protocols/services/device-fingerprint/display.d.ts +22 -0
- package/lib/domain/protocols/services/device-fingerprint/display.js +2 -0
- package/lib/domain/protocols/services/device-fingerprint/index.d.ts +3 -0
- package/lib/domain/protocols/services/device-fingerprint/index.js +19 -0
- package/lib/domain/protocols/services/device-fingerprint/navigator.d.ts +63 -0
- package/lib/domain/protocols/services/device-fingerprint/navigator.js +2 -0
- package/lib/domain/protocols/services/device-fingerprint/utils.d.ts +40 -0
- package/lib/domain/protocols/services/device-fingerprint/utils.js +2 -0
- package/lib/domain/protocols/services/device-identifier.d.ts +96 -0
- package/lib/domain/protocols/services/device-identifier.js +2 -0
- package/lib/domain/protocols/services/device-intelligence.d.ts +5 -0
- package/lib/domain/protocols/services/device-intelligence.js +2 -0
- package/lib/domain/protocols/services/listeners.d.ts +9 -0
- package/lib/domain/protocols/services/listeners.js +2 -0
- package/lib/domain/protocols/services/single-script-injection/auto-init.d.ts +120 -0
- package/lib/domain/protocols/services/single-script-injection/auto-init.js +2 -0
- package/lib/domain/protocols/services/single-script-injection/index.d.ts +1 -0
- package/lib/domain/protocols/services/single-script-injection/index.js +17 -0
- package/lib/domain/services/behavioural-biometrics/collector.d.ts +94 -0
- package/lib/domain/services/behavioural-biometrics/collector.js +229 -0
- package/lib/domain/services/behavioural-biometrics/cursor-behavior.d.ts +87 -0
- package/lib/domain/services/behavioural-biometrics/cursor-behavior.js +369 -0
- package/lib/domain/services/behavioural-biometrics/index.d.ts +4 -0
- package/lib/domain/services/behavioural-biometrics/index.js +20 -0
- package/lib/domain/services/behavioural-biometrics/keystroke-metrics.d.ts +60 -0
- package/lib/domain/services/behavioural-biometrics/keystroke-metrics.js +213 -0
- package/lib/domain/services/behavioural-biometrics/touch-behavior.d.ts +125 -0
- package/lib/domain/services/behavioural-biometrics/touch-behavior.js +413 -0
- package/lib/domain/services/device-fingerprint/audio.d.ts +14 -0
- package/lib/domain/services/device-fingerprint/audio.js +109 -0
- package/lib/domain/services/device-fingerprint/canvas.d.ts +10 -0
- package/lib/domain/services/device-fingerprint/canvas.js +33 -0
- package/lib/domain/services/device-fingerprint/display.d.ts +49 -0
- package/lib/domain/services/device-fingerprint/display.js +88 -0
- package/lib/domain/services/device-fingerprint/hash.d.ts +14 -0
- package/lib/domain/services/device-fingerprint/hash.js +60 -0
- package/lib/domain/services/device-fingerprint/index.d.ts +8 -0
- package/lib/domain/services/device-fingerprint/index.js +24 -0
- package/lib/domain/services/device-fingerprint/navigator.d.ts +110 -0
- package/lib/domain/services/device-fingerprint/navigator.js +213 -0
- package/lib/domain/services/device-fingerprint/pointer-capability.d.ts +14 -0
- package/lib/domain/services/device-fingerprint/pointer-capability.js +42 -0
- package/lib/domain/services/device-fingerprint/storage.d.ts +44 -0
- package/lib/domain/services/device-fingerprint/storage.js +64 -0
- package/lib/domain/services/device-fingerprint/utils.d.ts +42 -0
- package/lib/domain/services/device-fingerprint/utils.js +95 -0
- package/lib/domain/services/device-intelligence.d.ts +10 -0
- package/lib/domain/services/device-intelligence.js +59 -0
- package/lib/domain/services/single-script-injection/checkpoint-scheduler.d.ts +37 -0
- package/lib/domain/services/single-script-injection/checkpoint-scheduler.js +94 -0
- package/lib/domain/services/single-script-injection/index.d.ts +3 -0
- package/lib/domain/services/single-script-injection/index.js +19 -0
- package/lib/domain/services/single-script-injection/response-delivery.d.ts +47 -0
- package/lib/domain/services/single-script-injection/response-delivery.js +115 -0
- package/lib/domain/services/single-script-injection/schedule-store.d.ts +69 -0
- package/lib/domain/services/single-script-injection/schedule-store.js +146 -0
- package/lib/domain/services/snapshot-store.d.ts +19 -0
- package/lib/domain/services/snapshot-store.js +36 -0
- package/lib/domain/services/spa-navigation.d.ts +15 -0
- package/lib/domain/services/spa-navigation.js +40 -0
- package/lib/index.d.ts +19 -0
- package/lib/index.js +27 -0
- package/lib/infra/cache/index.d.ts +3 -0
- package/lib/infra/cache/index.js +19 -0
- package/lib/infra/cache/local-storage-adapter.d.ts +8 -0
- package/lib/infra/cache/local-storage-adapter.js +14 -0
- package/lib/infra/cache/session-storage-adapter.d.ts +8 -0
- package/lib/infra/cache/session-storage-adapter.js +14 -0
- package/lib/infra/cache/web-storage-adapter.d.ts +13 -0
- package/lib/infra/cache/web-storage-adapter.js +33 -0
- package/lib/infra/http/axios-http-client.d.ts +4 -0
- package/lib/infra/http/axios-http-client.js +39 -0
- package/lib/validation/builder.d.ts +43 -0
- package/lib/validation/builder.js +85 -0
- package/lib/validation/composite.d.ts +13 -0
- package/lib/validation/composite.js +23 -0
- package/lib/validation/errors/index.d.ts +2 -0
- package/lib/validation/errors/index.js +18 -0
- package/lib/validation/errors/invalid-field-error.d.ts +7 -0
- package/lib/validation/errors/invalid-field-error.js +14 -0
- package/lib/validation/errors/required-field-error.d.ts +3 -0
- package/lib/validation/errors/required-field-error.js +10 -0
- package/lib/validation/index.d.ts +5 -0
- package/lib/validation/index.js +21 -0
- package/lib/validation/protocols/index.d.ts +1 -0
- package/lib/validation/protocols/index.js +17 -0
- package/lib/validation/protocols/validator.d.ts +11 -0
- package/lib/validation/protocols/validator.js +2 -0
- package/lib/validation/validators/behavioural-signal.d.ts +27 -0
- package/lib/validation/validators/behavioural-signal.js +56 -0
- package/lib/validation/validators/country-code.d.ts +14 -0
- package/lib/validation/validators/country-code.js +24 -0
- package/lib/validation/validators/global-function.d.ts +14 -0
- package/lib/validation/validators/global-function.js +29 -0
- package/lib/validation/validators/index.d.ts +9 -0
- package/lib/validation/validators/index.js +25 -0
- package/lib/validation/validators/interpolated-template.d.ts +14 -0
- package/lib/validation/validators/interpolated-template.js +28 -0
- package/lib/validation/validators/json-object.d.ts +14 -0
- package/lib/validation/validators/json-object.js +33 -0
- package/lib/validation/validators/language-code.d.ts +13 -0
- package/lib/validation/validators/language-code.js +23 -0
- package/lib/validation/validators/positive-number.d.ts +13 -0
- package/lib/validation/validators/positive-number.js +24 -0
- package/lib/validation/validators/required-string.d.ts +10 -0
- package/lib/validation/validators/required-string.js +19 -0
- package/lib/validation/validators/schedule-record.d.ts +26 -0
- package/lib/validation/validators/schedule-record.js +33 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Purescore Identifier
|
|
2
|
+
|
|
3
|
+
`@purespectrum1/purescore-client` generates a stable, unique device ID from
|
|
4
|
+
device- and browser-level signals (fingerprinting). It ships as both a Node/TypeScript
|
|
5
|
+
library and a standalone UMD browser bundle, so the same identification logic can run
|
|
6
|
+
in a service or be dropped into a page with a `<script>` tag.
|
|
7
|
+
|
|
8
|
+
> **Status:** project scaffolding. Build, test, lint and release pipelines are in place;
|
|
9
|
+
> the `src/` implementation is still being added, so the public API below is not final.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
| | |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| Node.js | 20.15.0 (the version CI builds against) |
|
|
16
|
+
| TypeScript | 5.9+ (bundled as a dev dependency) |
|
|
17
|
+
| Browsers | ES5-compatible output, so old browsers are supported |
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm install @purespectrum1/purescore-client
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The package is published to the public npm registry. Because CI installs with
|
|
26
|
+
`--legacy-peer-deps`, use the same flag if you hit peer-dependency conflicts.
|
|
27
|
+
|
|
28
|
+
### Browser bundle
|
|
29
|
+
|
|
30
|
+
Browser builds are published to S3 (`purescore-client-package/dist`) as a UMD bundle
|
|
31
|
+
that exposes the global `ps_purescore_identifier`:
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<script src="https://<cdn-host>/dist/bundle.js"></script>
|
|
35
|
+
<script>
|
|
36
|
+
// window.ps_purescore_identifier
|
|
37
|
+
</script>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Each release also uploads a version-pinned file (`bundle.<version>.js`) alongside the
|
|
41
|
+
floating `bundle.js`. Pin the versioned file in production so a new release cannot
|
|
42
|
+
change behaviour under you.
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import identifier from '@purespectrum1/purescore-client';
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The module entry point is `lib/index.js`, with type declarations emitted next to it.
|
|
51
|
+
Concrete API examples will be added here as the implementation lands.
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
ISC. Maintained by the Data Stars squad.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AutoInitConfig } from '../domain/protocols/services/single-script-injection/auto-init';
|
|
2
|
+
import { CreateTransaction, TrackDetails } from '../domain/protocols/services/device-identifier';
|
|
3
|
+
/**
|
|
4
|
+
* Guard flag on `window`: a second tag on the same page is a no-op.
|
|
5
|
+
*/
|
|
6
|
+
export declare const INIT_FLAG = "__purescoreIdentifierInitialized";
|
|
7
|
+
export declare const TRANSACTION_CREATION_ATTEMPTS = 3;
|
|
8
|
+
export declare const TRANSACTION_RETRY_DELAY_MS = 1000;
|
|
9
|
+
/**
|
|
10
|
+
* Finds the script tag that loaded this bundle.
|
|
11
|
+
*
|
|
12
|
+
* `document.currentScript` is the direct answer while the tag is executing; the
|
|
13
|
+
* `data-auto-init` + `data-token` lookup covers dynamically-injected and module
|
|
14
|
+
* contexts where `currentScript` is null.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveScriptTag(): HTMLScriptElement | null;
|
|
17
|
+
/**
|
|
18
|
+
* Reads the bootstrap configuration off the tag's `data-*` attributes, or
|
|
19
|
+
* returns null when a required one is missing or unusable.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readAutoInitConfig(tag: HTMLScriptElement): AutoInitConfig | null;
|
|
22
|
+
/**
|
|
23
|
+
* Bootstraps the Device-Identifier straight from the script tag: no constructor
|
|
24
|
+
* call and no `trackDetails` call on the buyer side.
|
|
25
|
+
*
|
|
26
|
+
* Strictly opt-in — it does nothing unless `data-auto-init="true"` is on the tag
|
|
27
|
+
* — so every existing integration keeps working exactly as it does today.
|
|
28
|
+
*/
|
|
29
|
+
export declare class AutoInitService {
|
|
30
|
+
private readonly createDeviceIdentifier;
|
|
31
|
+
constructor(createDeviceIdentifier: (config: AutoInitConfig) => TrackDetails & CreateTransaction);
|
|
32
|
+
/**
|
|
33
|
+
* Runs the bootstrap. Returns true when auto-init took over the calls for this
|
|
34
|
+
* page, false when the tag opted out or the configuration was unusable.
|
|
35
|
+
*/
|
|
36
|
+
run(): boolean;
|
|
37
|
+
private bootstrap;
|
|
38
|
+
private resolveTransactionId;
|
|
39
|
+
/**
|
|
40
|
+
* Registers the transaction, trying up to `TRANSACTION_CREATION_ATTEMPTS` times.
|
|
41
|
+
* Resolves with undefined when every attempt failed.
|
|
42
|
+
*/
|
|
43
|
+
private createTransaction;
|
|
44
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AutoInitService = exports.TRANSACTION_RETRY_DELAY_MS = exports.TRANSACTION_CREATION_ATTEMPTS = exports.INIT_FLAG = void 0;
|
|
13
|
+
exports.resolveScriptTag = resolveScriptTag;
|
|
14
|
+
exports.readAutoInitConfig = readAutoInitConfig;
|
|
15
|
+
const validation_1 = require("../validation");
|
|
16
|
+
const single_script_injection_1 = require("../domain/services/single-script-injection");
|
|
17
|
+
const cache_1 = require("../infra/cache");
|
|
18
|
+
/**
|
|
19
|
+
* Guard flag on `window`: a second tag on the same page is a no-op.
|
|
20
|
+
*/
|
|
21
|
+
exports.INIT_FLAG = '__purescoreIdentifierInitialized';
|
|
22
|
+
exports.TRANSACTION_CREATION_ATTEMPTS = 3;
|
|
23
|
+
exports.TRANSACTION_RETRY_DELAY_MS = 1000;
|
|
24
|
+
/**
|
|
25
|
+
* Finds the script tag that loaded this bundle.
|
|
26
|
+
*
|
|
27
|
+
* `document.currentScript` is the direct answer while the tag is executing; the
|
|
28
|
+
* `data-auto-init` + `data-token` lookup covers dynamically-injected and module
|
|
29
|
+
* contexts where `currentScript` is null.
|
|
30
|
+
*/
|
|
31
|
+
function resolveScriptTag() {
|
|
32
|
+
var _a;
|
|
33
|
+
if (typeof document === 'undefined')
|
|
34
|
+
return null;
|
|
35
|
+
const current = document.currentScript;
|
|
36
|
+
if ((_a = current === null || current === void 0 ? void 0 : current.dataset) === null || _a === void 0 ? void 0 : _a.token)
|
|
37
|
+
return current;
|
|
38
|
+
return document.querySelector('script[data-auto-init][data-token]');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Reads the bootstrap configuration off the tag's `data-*` attributes, or
|
|
42
|
+
* returns null when a required one is missing or unusable.
|
|
43
|
+
*/
|
|
44
|
+
function readAutoInitConfig(tag) {
|
|
45
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
46
|
+
const data = tag.dataset;
|
|
47
|
+
const errors = [
|
|
48
|
+
validation_1.ValidationBuilder.of({ value: data.token, fieldName: 'data-token' })
|
|
49
|
+
.required(),
|
|
50
|
+
validation_1.ValidationBuilder.of({ value: data.surveyId, fieldName: 'data-survey-id' })
|
|
51
|
+
.required()
|
|
52
|
+
.interpolated(),
|
|
53
|
+
validation_1.ValidationBuilder.of({ value: data.expectedSurveyLoi, fieldName: 'data-expected-survey-loi' })
|
|
54
|
+
.required()
|
|
55
|
+
.interpolated()
|
|
56
|
+
.positiveNumber(),
|
|
57
|
+
validation_1.ValidationBuilder.of({ value: data.surveyCountry, fieldName: 'data-survey-country' })
|
|
58
|
+
.required()
|
|
59
|
+
.interpolated()
|
|
60
|
+
.countryCode(),
|
|
61
|
+
validation_1.ValidationBuilder.of({ value: data.surveyLanguage, fieldName: 'data-survey-language' })
|
|
62
|
+
.required()
|
|
63
|
+
.interpolated()
|
|
64
|
+
.languageCode(),
|
|
65
|
+
].map(rules => rules.validate()).filter((error) => error !== undefined);
|
|
66
|
+
if (errors.length) {
|
|
67
|
+
console.error(`Device-Identifier auto-init: ${errors.map(e => e.message).join('; ')}`);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const config = {
|
|
71
|
+
token: ((_a = data.token) !== null && _a !== void 0 ? _a : '').trim(),
|
|
72
|
+
env: ((_b = data.env) === null || _b === void 0 ? void 0 : _b.trim().toLowerCase()) === 'production' ? 'production' : 'staging',
|
|
73
|
+
callbackName: ((_c = data.callback) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
74
|
+
metadata: parseMetadataAttribute(data.metadata),
|
|
75
|
+
surveyId: ((_d = data.surveyId) !== null && _d !== void 0 ? _d : '').trim(),
|
|
76
|
+
expectedSurveyLOI: Number(data.expectedSurveyLoi),
|
|
77
|
+
surveyCountry: ((_e = data.surveyCountry) !== null && _e !== void 0 ? _e : '').trim().toUpperCase(),
|
|
78
|
+
surveyLanguage: ((_f = data.surveyLanguage) !== null && _f !== void 0 ? _f : '').trim().toLowerCase(),
|
|
79
|
+
};
|
|
80
|
+
const buyerId = optionalField(data.buyerId, 'data-buyer-id');
|
|
81
|
+
if (buyerId)
|
|
82
|
+
config.metadata.buyer_id = buyerId;
|
|
83
|
+
assignDefined(config, {
|
|
84
|
+
supplierId: optionalField(data.supplierId, 'data-supplier-id'),
|
|
85
|
+
supplierMemberId: optionalField(data.supplierMemberId, 'data-supplier-member-id'),
|
|
86
|
+
emailHash: ((_g = data.emailHash) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
|
|
87
|
+
});
|
|
88
|
+
const demographics = {};
|
|
89
|
+
assignDefined(demographics, {
|
|
90
|
+
age: optionalField(data.demographicsAge, 'data-demographics-age', rules => rules.positiveNumber(), Number),
|
|
91
|
+
gender: optionalField(data.demographicsGender, 'data-demographics-gender'),
|
|
92
|
+
zip: optionalField(data.demographicsZip, 'data-demographics-zip'),
|
|
93
|
+
});
|
|
94
|
+
if (Object.keys(demographics).length)
|
|
95
|
+
config.demographics = demographics;
|
|
96
|
+
return config;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Reads an optional attribute. An absent one is simply left out; one that is
|
|
100
|
+
* present but unusable is reported and dropped rather than treated as fatal,
|
|
101
|
+
* since the transaction does not depend on it.
|
|
102
|
+
*/
|
|
103
|
+
function optionalField(raw, fieldName, rules = builder => builder, convert = value => value) {
|
|
104
|
+
const error = rules(validation_1.ValidationBuilder.of({ value: raw, fieldName }).optional().interpolated()).validate();
|
|
105
|
+
if (error) {
|
|
106
|
+
console.error(`Device-Identifier auto-init: ${error.message}, ignoring it`);
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
const value = raw === null || raw === void 0 ? void 0 : raw.trim();
|
|
110
|
+
return value ? convert(value) : undefined;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Unusable metadata is reported and dropped rather than treated as fatal: the
|
|
114
|
+
* attribute is optional, so a malformed blob is no reason to abandon the
|
|
115
|
+
* transaction.
|
|
116
|
+
*/
|
|
117
|
+
function parseMetadataAttribute(raw) {
|
|
118
|
+
const error = validation_1.ValidationBuilder.of({ value: raw, fieldName: 'data-metadata' }).jsonObject().validate();
|
|
119
|
+
if (error) {
|
|
120
|
+
console.error(`Device-Identifier auto-init: ${error.message}, ignoring it`);
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
return (raw === null || raw === void 0 ? void 0 : raw.trim()) ? JSON.parse(raw) : {};
|
|
124
|
+
}
|
|
125
|
+
/** Copies over only the values that are set, so absent fields stay absent. */
|
|
126
|
+
function assignDefined(target, values) {
|
|
127
|
+
Object.keys(values).forEach(key => {
|
|
128
|
+
if (values[key] !== undefined)
|
|
129
|
+
target[key] = values[key];
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Bootstraps the Device-Identifier straight from the script tag: no constructor
|
|
134
|
+
* call and no `trackDetails` call on the buyer side.
|
|
135
|
+
*
|
|
136
|
+
* Strictly opt-in — it does nothing unless `data-auto-init="true"` is on the tag
|
|
137
|
+
* — so every existing integration keeps working exactly as it does today.
|
|
138
|
+
*/
|
|
139
|
+
class AutoInitService {
|
|
140
|
+
constructor(createDeviceIdentifier) {
|
|
141
|
+
this.createDeviceIdentifier = createDeviceIdentifier;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Runs the bootstrap. Returns true when auto-init took over the calls for this
|
|
145
|
+
* page, false when the tag opted out or the configuration was unusable.
|
|
146
|
+
*/
|
|
147
|
+
run() {
|
|
148
|
+
var _a;
|
|
149
|
+
if (typeof window === 'undefined')
|
|
150
|
+
return false;
|
|
151
|
+
if (window[exports.INIT_FLAG])
|
|
152
|
+
return false;
|
|
153
|
+
const tag = resolveScriptTag();
|
|
154
|
+
if (!tag)
|
|
155
|
+
return false;
|
|
156
|
+
if (((_a = tag.dataset.autoInit) !== null && _a !== void 0 ? _a : '').trim().toLowerCase() !== 'true')
|
|
157
|
+
return false;
|
|
158
|
+
const config = readAutoInitConfig(tag);
|
|
159
|
+
if (!config)
|
|
160
|
+
return false;
|
|
161
|
+
window[exports.INIT_FLAG] = true;
|
|
162
|
+
this.bootstrap(config);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
bootstrap(config) {
|
|
166
|
+
var _a;
|
|
167
|
+
const deviceIdentifier = this.createDeviceIdentifier(config);
|
|
168
|
+
const delivery = new single_script_injection_1.ResponseDeliveryService(config.callbackName);
|
|
169
|
+
const store = new single_script_injection_1.ScheduleStore(config.surveyId, new cache_1.LocalStorageAdapter());
|
|
170
|
+
const credentials = { token: config.token, env: config.env };
|
|
171
|
+
// Re-emit the verdict from an earlier page before the schedule resumes, so a
|
|
172
|
+
// page that only now registers a listener still receives the current one.
|
|
173
|
+
const buffered = (_a = store.read()) === null || _a === void 0 ? void 0 : _a.lastResponse;
|
|
174
|
+
if (buffered)
|
|
175
|
+
delivery.replay(buffered);
|
|
176
|
+
// The LOI comes off the tag, so every checkpoint is known up front. On a
|
|
177
|
+
// later page the record already carries it, and `applyLoi` leaves it alone.
|
|
178
|
+
store.resumeOrCreate();
|
|
179
|
+
store.applyLoi(config.expectedSurveyLOI);
|
|
180
|
+
const transactionReady = this.resolveTransactionId(store, deviceIdentifier, config, credentials);
|
|
181
|
+
const scheduler = new single_script_injection_1.CheckpointScheduler(store, () => __awaiter(this, void 0, void 0, function* () {
|
|
182
|
+
const transactionId = yield transactionReady;
|
|
183
|
+
if (!transactionId)
|
|
184
|
+
throw new Error('no transaction id to send the checkpoint for');
|
|
185
|
+
const response = yield deviceIdentifier.trackDetails(transactionId, config.metadata, credentials, { surveyId: config.surveyId });
|
|
186
|
+
store.storeResponse(response);
|
|
187
|
+
delivery.deliver(response);
|
|
188
|
+
}));
|
|
189
|
+
scheduler.start();
|
|
190
|
+
transactionReady.then(transactionId => {
|
|
191
|
+
if (!transactionId)
|
|
192
|
+
scheduler.stop();
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
resolveTransactionId(store, deviceIdentifier, config, credentials) {
|
|
196
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
197
|
+
var _a;
|
|
198
|
+
const stored = (_a = store.read()) === null || _a === void 0 ? void 0 : _a.transactionId;
|
|
199
|
+
if (stored)
|
|
200
|
+
return stored;
|
|
201
|
+
const transactionId = yield this.createTransaction(deviceIdentifier, config, credentials);
|
|
202
|
+
if (transactionId)
|
|
203
|
+
store.storeTransactionId(transactionId);
|
|
204
|
+
return transactionId;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Registers the transaction, trying up to `TRANSACTION_CREATION_ATTEMPTS` times.
|
|
209
|
+
* Resolves with undefined when every attempt failed.
|
|
210
|
+
*/
|
|
211
|
+
createTransaction(deviceIdentifier, config, credentials) {
|
|
212
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
213
|
+
const delay = (ms) => {
|
|
214
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
215
|
+
};
|
|
216
|
+
const details = {
|
|
217
|
+
surveyId: config.surveyId,
|
|
218
|
+
expectedSurveyLOI: config.expectedSurveyLOI,
|
|
219
|
+
surveyCountry: config.surveyCountry,
|
|
220
|
+
surveyLanguage: config.surveyLanguage,
|
|
221
|
+
};
|
|
222
|
+
assignDefined(details, {
|
|
223
|
+
supplierId: config.supplierId,
|
|
224
|
+
supplierMemberId: config.supplierMemberId,
|
|
225
|
+
emailHash: config.emailHash,
|
|
226
|
+
demographics: config.demographics,
|
|
227
|
+
});
|
|
228
|
+
for (let attempt = 1; attempt <= exports.TRANSACTION_CREATION_ATTEMPTS; attempt++) {
|
|
229
|
+
try {
|
|
230
|
+
const transactionId = yield deviceIdentifier.createTransaction(details, credentials);
|
|
231
|
+
if (transactionId)
|
|
232
|
+
return transactionId;
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
console.error(`Error creating Device-Intelligence transaction (attempt ${attempt}):`, error);
|
|
236
|
+
}
|
|
237
|
+
if (attempt < exports.TRANSACTION_CREATION_ATTEMPTS)
|
|
238
|
+
yield delay(exports.TRANSACTION_RETRY_DELAY_MS);
|
|
239
|
+
}
|
|
240
|
+
console.error(`Device-Identifier auto-init: could not create the transaction after ${exports.TRANSACTION_CREATION_ATTEMPTS} attempts`);
|
|
241
|
+
return undefined;
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
exports.AutoInitService = AutoInitService;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { DeviceIdentifierOptions, DeviceIdentifierConfig, DeviceIdentifierMetadata, BehaviouralBiometricsOptions, BehaviorBiometricsParams, CreateTransaction, TrackDetails, TrackDetailsContext, TransactionDetails } from '../domain/protocols/services/device-identifier';
|
|
2
|
+
/**
|
|
3
|
+
* DeviceIdentifier class for generating a unique identifier for a browser.
|
|
4
|
+
*/
|
|
5
|
+
export declare class DeviceIdentifier implements TrackDetails, CreateTransaction {
|
|
6
|
+
/**
|
|
7
|
+
* Custom hash function.
|
|
8
|
+
*
|
|
9
|
+
* If provided, this function will be used to generate the hash instead of the default murmurhash3_32_gc.
|
|
10
|
+
*/
|
|
11
|
+
private hasher?;
|
|
12
|
+
/**
|
|
13
|
+
* Token used to authenticate with the Purescore Intelligence service.
|
|
14
|
+
*/
|
|
15
|
+
private token;
|
|
16
|
+
/**
|
|
17
|
+
* Base URL for the Purescore Identifier service.
|
|
18
|
+
*/
|
|
19
|
+
private baseUrl;
|
|
20
|
+
/**
|
|
21
|
+
* Options stored from the last activateBehavioralBiometricsDetection call,
|
|
22
|
+
* reused when restarting the collection cycle after each trackDetails flush.
|
|
23
|
+
*/
|
|
24
|
+
private behaviouralBiometricsOptions?;
|
|
25
|
+
/**
|
|
26
|
+
* Service responsible for performing API requests to the Purescore Intelligence service.
|
|
27
|
+
*/
|
|
28
|
+
private deviceIntelligenceService;
|
|
29
|
+
private singleScriptInjection?;
|
|
30
|
+
private screen_resolution?;
|
|
31
|
+
private screen_orientation?;
|
|
32
|
+
private canvas?;
|
|
33
|
+
/**
|
|
34
|
+
* Constructor for the DeviceIdentifier class.
|
|
35
|
+
*
|
|
36
|
+
* @param options - Optional options for customizing the DeviceIdentifier generation.
|
|
37
|
+
*/
|
|
38
|
+
constructor(options?: DeviceIdentifierOptions | ((value: string, seed: number) => number), config?: DeviceIdentifierConfig);
|
|
39
|
+
/**
|
|
40
|
+
* Generates the fingerprint data for the browser.
|
|
41
|
+
*
|
|
42
|
+
* @returns An object containing the fingerprint data.
|
|
43
|
+
*/
|
|
44
|
+
getDetails(): Promise<{
|
|
45
|
+
hash: number;
|
|
46
|
+
canvas: string;
|
|
47
|
+
cookieEnabled: string | boolean;
|
|
48
|
+
display: {} | import("..").DisplayChecksInput;
|
|
49
|
+
javaEnabled: string | boolean;
|
|
50
|
+
tzOffset: number;
|
|
51
|
+
touchEnabled: boolean;
|
|
52
|
+
userAgent: string;
|
|
53
|
+
platform: string;
|
|
54
|
+
languages: import("..").Language;
|
|
55
|
+
displayChecks: import("..").DisplayChecks;
|
|
56
|
+
networkPerformance: import("..").NetworkTimes;
|
|
57
|
+
isWebCrawler: boolean;
|
|
58
|
+
audioFingerprint: number;
|
|
59
|
+
userAgentClientHints: {
|
|
60
|
+
model: string | undefined;
|
|
61
|
+
};
|
|
62
|
+
webdriverEnabled: boolean;
|
|
63
|
+
estimatedRoundTripTime: number;
|
|
64
|
+
ua: string;
|
|
65
|
+
browser: {
|
|
66
|
+
name?: string;
|
|
67
|
+
version?: string;
|
|
68
|
+
major?: string;
|
|
69
|
+
};
|
|
70
|
+
engine: {
|
|
71
|
+
name?: string;
|
|
72
|
+
version?: string;
|
|
73
|
+
};
|
|
74
|
+
os: {
|
|
75
|
+
name?: string;
|
|
76
|
+
version?: string;
|
|
77
|
+
};
|
|
78
|
+
device: {
|
|
79
|
+
vendor?: string;
|
|
80
|
+
model?: string;
|
|
81
|
+
type?: string;
|
|
82
|
+
};
|
|
83
|
+
cpu: {
|
|
84
|
+
architecture?: string;
|
|
85
|
+
};
|
|
86
|
+
isMobile: boolean;
|
|
87
|
+
isTablet: boolean;
|
|
88
|
+
isDesktop: boolean;
|
|
89
|
+
}>;
|
|
90
|
+
/**
|
|
91
|
+
* Generates a unique hash from browser and system properties (navigator, screen,
|
|
92
|
+
* storage, and more), using the provided hasher or murmurhash3_32_gc as a fallback.
|
|
93
|
+
*
|
|
94
|
+
* @param {string} [canvasFingerprint] - Precomputed canvas fingerprint to reuse
|
|
95
|
+
* instead of recomputing. Only used when the `canvas` option is enabled.
|
|
96
|
+
* @returns {number} A unique hash representing the user's browser and system.
|
|
97
|
+
*/
|
|
98
|
+
getIdentity(canvasFingerprint?: string): number;
|
|
99
|
+
/**
|
|
100
|
+
* Activates behavioral biometrics detection by starting event listeners for
|
|
101
|
+
* touch, cursor, and keyboard interactions.
|
|
102
|
+
*
|
|
103
|
+
* @param options - Optional configuration for BB detection, such as max data
|
|
104
|
+
* points for cursor and keystroke tracking.
|
|
105
|
+
*/
|
|
106
|
+
activateBehavioralBiometricsDetection(options?: BehaviouralBiometricsOptions): void;
|
|
107
|
+
/**
|
|
108
|
+
* Deactivates behavioral biometrics detection by stopping all event listeners
|
|
109
|
+
* for touch, cursor, and keyboard interactions, and marking the detection
|
|
110
|
+
* as inactive.
|
|
111
|
+
*/
|
|
112
|
+
deactivateBehavioralBiometricsDetection(): void;
|
|
113
|
+
createTransaction(details: TransactionDetails, config?: DeviceIdentifierConfig): Promise<string | undefined>;
|
|
114
|
+
trackDetails(transactionId: string, metadata?: DeviceIdentifierMetadata, config?: DeviceIdentifierConfig, context?: TrackDetailsContext): Promise<Record<string, any>>;
|
|
115
|
+
sendBehaviorBiometrics(transactionId: string, params: BehaviorBiometricsParams, config?: DeviceIdentifierConfig): Promise<any>;
|
|
116
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DeviceIdentifier = void 0;
|
|
13
|
+
const device_fingerprint_1 = require("../domain/services/device-fingerprint");
|
|
14
|
+
const behavioural_biometrics_1 = require("../domain/services/behavioural-biometrics");
|
|
15
|
+
const device_intelligence_1 = require("../domain/services/device-intelligence");
|
|
16
|
+
const crosscutting_1 = require("../domain/models/crosscutting");
|
|
17
|
+
const spa_navigation_1 = require("../domain/services/spa-navigation");
|
|
18
|
+
const axios_http_client_1 = require("../infra/http/axios-http-client");
|
|
19
|
+
const cache_1 = require("../infra/cache");
|
|
20
|
+
const hash = new device_fingerprint_1.Hash();
|
|
21
|
+
const storage = new device_fingerprint_1.Storage();
|
|
22
|
+
const display = new device_fingerprint_1.Display();
|
|
23
|
+
const navigatior = new device_fingerprint_1.Navigatior();
|
|
24
|
+
const canvas = new device_fingerprint_1.Canvas();
|
|
25
|
+
const utils = new device_fingerprint_1.Utils();
|
|
26
|
+
const audioFingerprint = new device_fingerprint_1.AudioFingerprint();
|
|
27
|
+
const pointerCapability = new device_fingerprint_1.PointerCapabilityDetector();
|
|
28
|
+
// One collector shared for the lifetime of the page. It owns the trackers, which
|
|
29
|
+
// is what makes behavioural data survive a DeviceIdentifier being re-instantiated.
|
|
30
|
+
const behaviouralBiometrics = new behavioural_biometrics_1.BehaviouralBiometricsCollector(new behavioural_biometrics_1.TouchBehavior(), new behavioural_biometrics_1.CursorBehavior(), new behavioural_biometrics_1.KeyboardMetrics(), new cache_1.SessionStorageAdapter(), new spa_navigation_1.SpaNavigationDetector());
|
|
31
|
+
/**
|
|
32
|
+
* DeviceIdentifier class for generating a unique identifier for a browser.
|
|
33
|
+
*/
|
|
34
|
+
class DeviceIdentifier {
|
|
35
|
+
/**
|
|
36
|
+
* Constructor for the DeviceIdentifier class.
|
|
37
|
+
*
|
|
38
|
+
* @param options - Optional options for customizing the DeviceIdentifier generation.
|
|
39
|
+
*/
|
|
40
|
+
constructor(options, config = {}) {
|
|
41
|
+
if (typeof options === 'object') {
|
|
42
|
+
this.hasher = options.hasher;
|
|
43
|
+
this.screen_resolution = options.screen_resolution;
|
|
44
|
+
this.screen_orientation = options.screen_orientation;
|
|
45
|
+
this.canvas = options.canvas;
|
|
46
|
+
this.singleScriptInjection = options.singleScriptInjection;
|
|
47
|
+
}
|
|
48
|
+
else if (typeof options === 'function') {
|
|
49
|
+
this.hasher = options;
|
|
50
|
+
}
|
|
51
|
+
const { token = '', env = 'staging' } = config;
|
|
52
|
+
this.token = token;
|
|
53
|
+
this.baseUrl = (0, crosscutting_1.resolveDeviceIntelligenceBaseUrl)(env);
|
|
54
|
+
this.deviceIntelligenceService = new device_intelligence_1.DeviceIntelligenceService(new axios_http_client_1.AxiosHttpClient(), this.baseUrl, this.token);
|
|
55
|
+
this.activateBehavioralBiometricsDetection();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Generates the fingerprint data for the browser.
|
|
59
|
+
*
|
|
60
|
+
* @returns An object containing the fingerprint data.
|
|
61
|
+
*/
|
|
62
|
+
getDetails() {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const parsedData = navigatior.getDeviceType();
|
|
65
|
+
const [audioFingerprintResponse, highEntropyClientHints] = yield Promise.all([
|
|
66
|
+
audioFingerprint.getAudioFingerprint(),
|
|
67
|
+
navigatior.getHighEntropyClientHints(['model']),
|
|
68
|
+
]);
|
|
69
|
+
const canvasFingerprint = canvas.getCanvasFingerprint();
|
|
70
|
+
const hash = this.getIdentity(canvasFingerprint);
|
|
71
|
+
return Object.assign(Object.assign({}, parsedData), { hash, canvas: canvasFingerprint, cookieEnabled: navigatior.isCookieEnabled(), display: display.getDisplayDetails(), javaEnabled: navigatior.isJavaEnabled(), tzOffset: utils.getTimezoneOffset(), touchEnabled: utils.getTouchSupport() || pointerCapability.hasTouchOrPen(), userAgent: navigatior.getUserAgent(), platform: navigatior.getPlatform(), languages: navigatior.getLanguages(), displayChecks: display.displayChecks(), networkPerformance: utils.getNetworkTime(), isWebCrawler: navigatior.isCrawler(), audioFingerprint: audioFingerprintResponse, userAgentClientHints: {
|
|
72
|
+
model: highEntropyClientHints === null || highEntropyClientHints === void 0 ? void 0 : highEntropyClientHints.model
|
|
73
|
+
}, webdriverEnabled: navigatior.isWebDriverEnabled(), estimatedRoundTripTime: navigatior.getEstimatedRoundTripTime() });
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Generates a unique hash from browser and system properties (navigator, screen,
|
|
78
|
+
* storage, and more), using the provided hasher or murmurhash3_32_gc as a fallback.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} [canvasFingerprint] - Precomputed canvas fingerprint to reuse
|
|
81
|
+
* instead of recomputing. Only used when the `canvas` option is enabled.
|
|
82
|
+
* @returns {number} A unique hash representing the user's browser and system.
|
|
83
|
+
*/
|
|
84
|
+
getIdentity(canvasFingerprint) {
|
|
85
|
+
// Initialize an array to store the properties that will be used to generate the hash.
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
|
+
const keys = [];
|
|
88
|
+
const navigatorProperties = navigatior.getNavigatorProperties();
|
|
89
|
+
const screenProperties = display.getScreenProperties(this.screen_resolution, this.screen_orientation);
|
|
90
|
+
const storageProperties = storage.getStorageProperties();
|
|
91
|
+
keys.push(navigatorProperties.userAgent);
|
|
92
|
+
keys.push(navigatorProperties.language);
|
|
93
|
+
keys.push(screenProperties.colorDepth);
|
|
94
|
+
if (screenProperties.resolution) {
|
|
95
|
+
keys.push(screenProperties.resolution.join('x'));
|
|
96
|
+
}
|
|
97
|
+
keys.push(new Date().getTimezoneOffset());
|
|
98
|
+
keys.push(storageProperties.sessionStorage);
|
|
99
|
+
keys.push(storageProperties.localStorage);
|
|
100
|
+
keys.push(storageProperties.indexedDB);
|
|
101
|
+
keys.push(navigatorProperties.platform);
|
|
102
|
+
keys.push(navigatorProperties.doNotTrack);
|
|
103
|
+
if (this.canvas) {
|
|
104
|
+
keys.push(canvasFingerprint !== null && canvasFingerprint !== void 0 ? canvasFingerprint : canvas.getCanvasFingerprint());
|
|
105
|
+
}
|
|
106
|
+
const keyString = keys.join('###');
|
|
107
|
+
return this.hasher ? this.hasher(keyString, 31) : hash.murmurhash3_32_gc(keyString, 31);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Activates behavioral biometrics detection by starting event listeners for
|
|
111
|
+
* touch, cursor, and keyboard interactions.
|
|
112
|
+
*
|
|
113
|
+
* @param options - Optional configuration for BB detection, such as max data
|
|
114
|
+
* points for cursor and keystroke tracking.
|
|
115
|
+
*/
|
|
116
|
+
activateBehavioralBiometricsDetection(options) {
|
|
117
|
+
if (typeof window === 'undefined')
|
|
118
|
+
return;
|
|
119
|
+
this.behaviouralBiometricsOptions = options;
|
|
120
|
+
behaviouralBiometrics.startCycle(options);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Deactivates behavioral biometrics detection by stopping all event listeners
|
|
124
|
+
* for touch, cursor, and keyboard interactions, and marking the detection
|
|
125
|
+
* as inactive.
|
|
126
|
+
*/
|
|
127
|
+
deactivateBehavioralBiometricsDetection() {
|
|
128
|
+
behaviouralBiometrics.deactivate();
|
|
129
|
+
}
|
|
130
|
+
createTransaction(details_1) {
|
|
131
|
+
return __awaiter(this, arguments, void 0, function* (details, config = {}) {
|
|
132
|
+
var _a;
|
|
133
|
+
const response = yield this.deviceIntelligenceService.performRequest('/v1/transaction', 'post', config, details);
|
|
134
|
+
const transactionId = (_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.transactionId;
|
|
135
|
+
const succeeded = typeof (response === null || response === void 0 ? void 0 : response.statusCode) === 'number'
|
|
136
|
+
&& response.statusCode < 400
|
|
137
|
+
&& typeof transactionId === 'string'
|
|
138
|
+
&& transactionId.length > 0;
|
|
139
|
+
return succeeded ? transactionId : undefined;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
trackDetails(transactionId_1) {
|
|
143
|
+
return __awaiter(this, arguments, void 0, function* (transactionId, metadata = {}, config = {}, context = {}) {
|
|
144
|
+
var _a;
|
|
145
|
+
behaviouralBiometrics.pauseWindow();
|
|
146
|
+
const bbParams = context.surveyId ? Object.assign(Object.assign({}, metadata), { survey_id: context.surveyId }) : metadata;
|
|
147
|
+
const bbResponse = yield this.sendBehaviorBiometrics(transactionId, bbParams, config);
|
|
148
|
+
if (bbResponse.statusCode >= 400) {
|
|
149
|
+
this.deactivateBehavioralBiometricsDetection();
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
behaviouralBiometrics.startCycle(this.behaviouralBiometricsOptions);
|
|
153
|
+
}
|
|
154
|
+
const payload = Object.assign(Object.assign({ metadata }, yield this.getDetails()), { transactionId });
|
|
155
|
+
const response = yield this.deviceIntelligenceService.performRequest(`/v1/respondent/${transactionId}`, 'patch', config, payload);
|
|
156
|
+
return (_a = response.body) !== null && _a !== void 0 ? _a : response;
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
sendBehaviorBiometrics(transactionId_1, params_1) {
|
|
160
|
+
return __awaiter(this, arguments, void 0, function* (transactionId, params, config = {}) {
|
|
161
|
+
const { metrics, collectionDuration } = behaviouralBiometrics.snapshot();
|
|
162
|
+
return this.deviceIntelligenceService.performRequest(`/v1/respondent/${transactionId}/biometrics`, 'post', config, Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, params), metrics), { device: navigatior.getDeviceType().device, collectionDuration }), (this.singleScriptInjection ? { singleScriptInjection: true } : {})), { transactionId })).then(response => {
|
|
163
|
+
behaviouralBiometrics.reset();
|
|
164
|
+
return response;
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.DeviceIdentifier = DeviceIdentifier;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOTE: these endpoints are going to be changed to a new domain
|
|
3
|
+
*/
|
|
4
|
+
/** Device-Intelligence API, per environment. */
|
|
5
|
+
export declare const PURESCORE_INTELLIGENCE_BASE_URL: {
|
|
6
|
+
readonly production: "https://purescore.spectrumsurveys.com";
|
|
7
|
+
readonly staging: "https://purescore-staging.spectrumsurveys.com";
|
|
8
|
+
};
|
|
9
|
+
export type DeviceIntelligenceEnv = keyof typeof PURESCORE_INTELLIGENCE_BASE_URL;
|
|
10
|
+
/** Anything other than an explicit `production` resolves to staging. */
|
|
11
|
+
export declare function resolveDeviceIntelligenceBaseUrl(env?: string): string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PURESCORE_INTELLIGENCE_BASE_URL = void 0;
|
|
4
|
+
exports.resolveDeviceIntelligenceBaseUrl = resolveDeviceIntelligenceBaseUrl;
|
|
5
|
+
/**
|
|
6
|
+
* NOTE: these endpoints are going to be changed to a new domain
|
|
7
|
+
*/
|
|
8
|
+
/** Device-Intelligence API, per environment. */
|
|
9
|
+
exports.PURESCORE_INTELLIGENCE_BASE_URL = {
|
|
10
|
+
production: 'https://purescore.spectrumsurveys.com',
|
|
11
|
+
staging: 'https://purescore-staging.spectrumsurveys.com',
|
|
12
|
+
};
|
|
13
|
+
/** Anything other than an explicit `production` resolves to staging. */
|
|
14
|
+
function resolveDeviceIntelligenceBaseUrl(env) {
|
|
15
|
+
return (env === null || env === void 0 ? void 0 : env.toLowerCase()) === 'production'
|
|
16
|
+
? exports.PURESCORE_INTELLIGENCE_BASE_URL.production
|
|
17
|
+
: exports.PURESCORE_INTELLIGENCE_BASE_URL.staging;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './device-intelligence';
|