@croct/sdk 0.13.0 → 0.15.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/activeRecord.js.map +1 -1
- package/apiKey.d.ts +18 -0
- package/apiKey.js +89 -0
- package/apiKey.js.map +1 -0
- package/cache/cache.d.ts +3 -0
- package/cache/cache.js +9 -0
- package/cache/cache.js.map +1 -1
- package/cache/cookieCache.d.ts +19 -0
- package/cache/cookieCache.js +54 -0
- package/cache/cookieCache.js.map +1 -0
- package/cache/fallbackCache.js.map +1 -1
- package/cache/localStorageCache.js.map +1 -1
- package/channel/beaconSocketChannel.js.map +1 -1
- package/channel/guaranteedChannel.js.map +1 -1
- package/channel/queuedChannel.js.map +1 -1
- package/channel/retryChannel.js.map +1 -1
- package/channel/sandboxChannel.js.map +1 -1
- package/channel/socketChannel.js.map +1 -1
- package/cid/cachedAssigner.js.map +1 -1
- package/cid/remoteAssigner.js.map +1 -1
- package/constants.d.ts +2 -2
- package/constants.js +1 -1
- package/container.d.ts +8 -1
- package/container.js +21 -7
- package/container.js.map +1 -1
- package/contentFetcher.d.ts +9 -1
- package/contentFetcher.js +24 -6
- package/contentFetcher.js.map +1 -1
- package/context.d.ts +4 -4
- package/context.js +4 -1
- package/context.js.map +1 -1
- package/error.js.map +1 -1
- package/evaluator.d.ts +9 -1
- package/evaluator.js +27 -9
- package/evaluator.js.map +1 -1
- package/eventManager.js.map +1 -1
- package/eventSubjectProcessor.d.ts +9 -0
- package/eventSubjectProcessor.js +67 -0
- package/eventSubjectProcessor.js.map +1 -0
- package/facade/contentFetcherFacade.d.ts +6 -1
- package/facade/contentFetcherFacade.js +5 -2
- package/facade/contentFetcherFacade.js.map +1 -1
- package/facade/evaluatorFacade.js.map +1 -1
- package/facade/sdkFacade.d.ts +11 -1
- package/facade/sdkFacade.js +9 -3
- package/facade/sdkFacade.js.map +1 -1
- package/facade/sessionPatch.js.map +1 -1
- package/facade/trackerFacade.js.map +1 -1
- package/facade/userPatch.js.map +1 -1
- package/logging/consoleLogger.js.map +1 -1
- package/namespacedStorage.js.map +1 -1
- package/package.json +5 -4
- package/queue/capacityRestrictedQueue.js.map +1 -1
- package/queue/inMemoryQueue.js.map +1 -1
- package/queue/monitoredQueue.js.map +1 -1
- package/queue/persistentQueue.js.map +1 -1
- package/retry/arbitraryPolicy.js.map +1 -1
- package/retry/backoffPolicy.js.map +1 -1
- package/retry/maxAttemptsPolicy.js.map +1 -1
- package/schema/sdkFacadeSchemas.js +9 -0
- package/schema/sdkFacadeSchemas.js.map +1 -1
- package/schema/sdkSchemas.d.ts +1 -0
- package/schema/sdkSchemas.js +30 -1
- package/schema/sdkSchemas.js.map +1 -1
- package/sdk.d.ts +8 -1
- package/sdk.js +1 -2
- package/sdk.js.map +1 -1
- package/sourceLocation.js.map +1 -1
- package/src/apiKey.ts +110 -0
- package/src/cache/cache.ts +7 -0
- package/src/cache/cookieCache.ts +77 -0
- package/src/container.ts +24 -5
- package/src/contentFetcher.ts +39 -8
- package/src/context.ts +7 -5
- package/src/evaluator.ts +39 -9
- package/src/eventSubjectProcessor.ts +85 -0
- package/src/facade/contentFetcherFacade.ts +11 -2
- package/src/facade/sdkFacade.ts +21 -3
- package/src/schema/sdkFacadeSchemas.ts +10 -1
- package/src/schema/sdkSchemas.ts +30 -0
- package/src/sdk.ts +8 -4
- package/src/token/token.ts +100 -18
- package/src/tracker.ts +59 -15
- package/tab.js.map +1 -1
- package/token/cachedTokenStore.js.map +1 -1
- package/token/token.d.ts +19 -2
- package/token/token.js +79 -16
- package/token/token.js.map +1 -1
- package/tracker.d.ts +9 -1
- package/tracker.js +37 -12
- package/tracker.js.map +1 -1
- package/uuid.js.map +1 -1
- package/validation/arrayType.js.map +1 -1
- package/validation/booleanType.js.map +1 -1
- package/validation/functionType.js.map +1 -1
- package/validation/jsonType.js.map +1 -1
- package/validation/nullType.js.map +1 -1
- package/validation/numberType.js.map +1 -1
- package/validation/objectType.js.map +1 -1
- package/validation/stringType.js.map +1 -1
- package/validation/unionType.js.map +1 -1
- package/validation/violation.js.map +1 -1
- package/base64Url.d.ts +0 -2
- package/base64Url.js +0 -28
- package/base64Url.js.map +0 -1
- package/src/base64Url.ts +0 -36
package/src/contentFetcher.ts
CHANGED
|
@@ -3,6 +3,8 @@ import {EvaluationContext} from './evaluator';
|
|
|
3
3
|
import {Token} from './token';
|
|
4
4
|
import {BASE_ENDPOINT_URL, CLIENT_LIBRARY} from './constants';
|
|
5
5
|
import {formatMessage} from './error';
|
|
6
|
+
import {Logger, NullLogger} from './logging';
|
|
7
|
+
import {ApiKey} from './apiKey';
|
|
6
8
|
|
|
7
9
|
export type ErrorResponse = {
|
|
8
10
|
type: string,
|
|
@@ -51,6 +53,10 @@ export type DynamicContentOptions = BasicOptions & {
|
|
|
51
53
|
static?: false,
|
|
52
54
|
clientId?: string,
|
|
53
55
|
clientIp?: string,
|
|
56
|
+
clientAgent?: string,
|
|
57
|
+
/**
|
|
58
|
+
* @deprecated Use `clientAgent` instead. This option will be removed in future releases.
|
|
59
|
+
*/
|
|
54
60
|
userAgent?: string,
|
|
55
61
|
userToken?: Token|string,
|
|
56
62
|
previewToken?: Token|string,
|
|
@@ -71,25 +77,34 @@ export type FetchResponse<P extends JsonObject = JsonObject> = {
|
|
|
71
77
|
|
|
72
78
|
export type Configuration = {
|
|
73
79
|
appId?: string,
|
|
74
|
-
apiKey?: string,
|
|
80
|
+
apiKey?: string|ApiKey,
|
|
75
81
|
baseEndpointUrl?: string,
|
|
82
|
+
logger?: Logger,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
type InternalConfiguration = {
|
|
86
|
+
appId?: string,
|
|
87
|
+
apiKey?: ApiKey,
|
|
76
88
|
};
|
|
77
89
|
|
|
78
90
|
export class ContentFetcher {
|
|
79
|
-
private readonly configuration:
|
|
91
|
+
private readonly configuration: InternalConfiguration;
|
|
80
92
|
|
|
81
93
|
private readonly dynamicEndpoint: string;
|
|
82
94
|
|
|
83
95
|
private readonly staticEndpoint: string;
|
|
84
96
|
|
|
97
|
+
private readonly logger: Logger;
|
|
98
|
+
|
|
85
99
|
public constructor(configuration: Configuration) {
|
|
86
100
|
if ((configuration.appId === undefined) === (configuration.apiKey === undefined)) {
|
|
87
101
|
throw new Error('Either the application ID or the API key must be provided.');
|
|
88
102
|
}
|
|
89
103
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
const {baseEndpointUrl} = configuration;
|
|
105
|
+
const apiKey = configuration.apiKey !== undefined
|
|
106
|
+
? ApiKey.from(configuration.apiKey)
|
|
107
|
+
: undefined;
|
|
93
108
|
|
|
94
109
|
// eslint-disable-next-line prefer-template -- Better readability
|
|
95
110
|
const baseEndpoint = (baseEndpointUrl ?? BASE_ENDPOINT_URL).replace(/\/+$/, '')
|
|
@@ -98,6 +113,11 @@ export class ContentFetcher {
|
|
|
98
113
|
|
|
99
114
|
this.dynamicEndpoint = `${baseEndpoint}/content`;
|
|
100
115
|
this.staticEndpoint = `${baseEndpoint}/static-content`;
|
|
116
|
+
this.logger = configuration.logger ?? new NullLogger();
|
|
117
|
+
this.configuration = {
|
|
118
|
+
appId: configuration.appId,
|
|
119
|
+
apiKey: apiKey,
|
|
120
|
+
};
|
|
101
121
|
}
|
|
102
122
|
|
|
103
123
|
public fetch<P extends JsonObject>(slotId: string, options: FetchOptions = {}): Promise<FetchResponse<P>> {
|
|
@@ -173,7 +193,7 @@ export class ContentFetcher {
|
|
|
173
193
|
}
|
|
174
194
|
|
|
175
195
|
if (apiKey !== undefined) {
|
|
176
|
-
headers['X-Api-Key'] = apiKey;
|
|
196
|
+
headers['X-Api-Key'] = apiKey.getIdentifier();
|
|
177
197
|
}
|
|
178
198
|
|
|
179
199
|
const payload: FetchPayload = {
|
|
@@ -191,6 +211,15 @@ export class ContentFetcher {
|
|
|
191
211
|
const dynamic = ContentFetcher.isDynamicContent(options);
|
|
192
212
|
|
|
193
213
|
if (dynamic) {
|
|
214
|
+
if (options.userAgent !== undefined) {
|
|
215
|
+
this.logger.warn(
|
|
216
|
+
'The `userAgent` option is deprecated and '
|
|
217
|
+
+ 'will be removed in future releases. '
|
|
218
|
+
+ 'Please update the part of your code calling the `fetch` method '
|
|
219
|
+
+ 'to use the `clientAgent` option instead.',
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
194
223
|
if (options.clientId !== undefined) {
|
|
195
224
|
headers['X-Client-Id'] = options.clientId;
|
|
196
225
|
}
|
|
@@ -203,8 +232,10 @@ export class ContentFetcher {
|
|
|
203
232
|
headers['X-Token'] = options.userToken.toString();
|
|
204
233
|
}
|
|
205
234
|
|
|
206
|
-
|
|
207
|
-
|
|
235
|
+
const clientAgent = options.clientAgent ?? options.userAgent;
|
|
236
|
+
|
|
237
|
+
if (clientAgent !== undefined) {
|
|
238
|
+
headers['X-Client-Agent'] = clientAgent;
|
|
208
239
|
}
|
|
209
240
|
|
|
210
241
|
if (options.context !== undefined) {
|
package/src/context.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {Tab, UrlSanitizer} from './tab';
|
|
|
3
3
|
import {uuid4} from './uuid';
|
|
4
4
|
import {EventDispatcher} from './eventManager';
|
|
5
5
|
import {SdkEventMap} from './sdkEvents';
|
|
6
|
-
import {
|
|
6
|
+
import {Cache, ObservableCache} from './cache';
|
|
7
7
|
|
|
8
8
|
export type TokenScope = 'isolated' | 'global' | 'contextual';
|
|
9
9
|
|
|
@@ -12,9 +12,9 @@ export type Configuration = {
|
|
|
12
12
|
urlSanitizer?: UrlSanitizer,
|
|
13
13
|
eventDispatcher: ContextEventDispatcher,
|
|
14
14
|
cache: {
|
|
15
|
-
tabId:
|
|
16
|
-
tabToken:
|
|
17
|
-
browserToken:
|
|
15
|
+
tabId: Cache,
|
|
16
|
+
tabToken: Cache,
|
|
17
|
+
browserToken: Cache,
|
|
18
18
|
},
|
|
19
19
|
};
|
|
20
20
|
|
|
@@ -63,7 +63,9 @@ export class Context {
|
|
|
63
63
|
case 'global': {
|
|
64
64
|
const context = new Context(tab, new CachedTokenStore(cache.browserToken), eventDispatcher);
|
|
65
65
|
|
|
66
|
-
cache.browserToken
|
|
66
|
+
if (ObservableCache.isObservable(cache.browserToken)) {
|
|
67
|
+
cache.browserToken.addListener(context.syncToken);
|
|
68
|
+
}
|
|
67
69
|
|
|
68
70
|
return context;
|
|
69
71
|
}
|
package/src/evaluator.ts
CHANGED
|
@@ -3,6 +3,8 @@ import {Token} from './token';
|
|
|
3
3
|
import {BASE_ENDPOINT_URL, CLIENT_LIBRARY, MAX_QUERY_LENGTH} from './constants';
|
|
4
4
|
import {formatMessage} from './error';
|
|
5
5
|
import {getLength, getLocation, Location} from './sourceLocation';
|
|
6
|
+
import {Logger, NullLogger} from './logging';
|
|
7
|
+
import {ApiKey} from './apiKey';
|
|
6
8
|
|
|
7
9
|
export type Campaign = {
|
|
8
10
|
name?: string,
|
|
@@ -34,6 +36,10 @@ type ExtraFetchOptions<T extends keyof RequestInit = AllowedFetchOptions> = Pick
|
|
|
34
36
|
export type EvaluationOptions = {
|
|
35
37
|
clientId?: string,
|
|
36
38
|
clientIp?: string,
|
|
39
|
+
clientAgent?: string,
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated Use `clientAgent` instead. This option will be removed in future releases.
|
|
42
|
+
*/
|
|
37
43
|
userAgent?: string,
|
|
38
44
|
userToken?: Token|string,
|
|
39
45
|
timeout?: number,
|
|
@@ -89,30 +95,44 @@ export class QueryError extends EvaluationError<QueryErrorResponse> {
|
|
|
89
95
|
|
|
90
96
|
export type Configuration = {
|
|
91
97
|
appId?: string,
|
|
92
|
-
apiKey?: string,
|
|
98
|
+
apiKey?: string|ApiKey,
|
|
93
99
|
baseEndpointUrl?: string,
|
|
100
|
+
logger?: Logger,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
type InternalConfiguration = {
|
|
104
|
+
appId?: string,
|
|
105
|
+
apiKey?: ApiKey,
|
|
94
106
|
};
|
|
95
107
|
|
|
96
108
|
export class Evaluator {
|
|
97
109
|
public static readonly MAX_QUERY_LENGTH = MAX_QUERY_LENGTH;
|
|
98
110
|
|
|
99
|
-
private readonly configuration:
|
|
111
|
+
private readonly configuration: InternalConfiguration;
|
|
100
112
|
|
|
101
113
|
private readonly endpoint: string;
|
|
102
114
|
|
|
115
|
+
private readonly logger: Logger;
|
|
116
|
+
|
|
103
117
|
public constructor(configuration: Configuration) {
|
|
104
118
|
if ((configuration.appId === undefined) === (configuration.apiKey === undefined)) {
|
|
105
119
|
throw new Error('Either the application ID or the API key must be provided.');
|
|
106
120
|
}
|
|
107
121
|
|
|
108
|
-
const {baseEndpointUrl
|
|
122
|
+
const {baseEndpointUrl} = configuration;
|
|
123
|
+
const apiKey = configuration.apiKey !== undefined
|
|
124
|
+
? ApiKey.from(configuration.apiKey)
|
|
125
|
+
: undefined;
|
|
109
126
|
|
|
110
127
|
// eslint-disable-next-line prefer-template -- Better readability
|
|
111
128
|
this.endpoint = (baseEndpointUrl ?? BASE_ENDPOINT_URL).replace(/\/+$/, '')
|
|
112
129
|
+ (apiKey === undefined ? '/client' : '/external')
|
|
113
130
|
+ '/web/evaluate';
|
|
114
|
-
|
|
115
|
-
this.configuration =
|
|
131
|
+
this.logger = configuration.logger ?? new NullLogger();
|
|
132
|
+
this.configuration = {
|
|
133
|
+
appId: configuration.appId,
|
|
134
|
+
apiKey: apiKey,
|
|
135
|
+
};
|
|
116
136
|
}
|
|
117
137
|
|
|
118
138
|
public evaluate(query: string, options: EvaluationOptions = {}): Promise<JsonValue> {
|
|
@@ -215,7 +235,17 @@ export class Evaluator {
|
|
|
215
235
|
|
|
216
236
|
private fetch(body: JsonObject, signal: AbortSignal, options: EvaluationOptions): Promise<Response> {
|
|
217
237
|
const {appId, apiKey} = this.configuration;
|
|
218
|
-
const {clientId, clientIp,
|
|
238
|
+
const {clientId, clientIp, userToken} = options;
|
|
239
|
+
const clientAgent = options.clientAgent ?? options.userAgent;
|
|
240
|
+
|
|
241
|
+
if (options.userAgent !== undefined) {
|
|
242
|
+
this.logger.warn(
|
|
243
|
+
'The `userAgent` option is deprecated and '
|
|
244
|
+
+ 'will be removed in future releases. '
|
|
245
|
+
+ 'Please update the part of your code calling the `evaluate` method '
|
|
246
|
+
+ 'to use the `clientAgent` option instead.',
|
|
247
|
+
);
|
|
248
|
+
}
|
|
219
249
|
|
|
220
250
|
const headers: Record<string, string> = {
|
|
221
251
|
'Content-Type': 'application/json',
|
|
@@ -224,7 +254,7 @@ export class Evaluator {
|
|
|
224
254
|
headers['X-Client-Library'] = CLIENT_LIBRARY;
|
|
225
255
|
|
|
226
256
|
if (apiKey !== undefined) {
|
|
227
|
-
headers['X-Api-Key'] = apiKey;
|
|
257
|
+
headers['X-Api-Key'] = apiKey.getIdentifier();
|
|
228
258
|
} else if (appId !== undefined) {
|
|
229
259
|
headers['X-App-Id'] = appId;
|
|
230
260
|
}
|
|
@@ -241,8 +271,8 @@ export class Evaluator {
|
|
|
241
271
|
headers['X-Token'] = userToken.toString();
|
|
242
272
|
}
|
|
243
273
|
|
|
244
|
-
if (
|
|
245
|
-
headers['
|
|
274
|
+
if (clientAgent !== undefined) {
|
|
275
|
+
headers['X-Client-Agent'] = clientAgent;
|
|
246
276
|
}
|
|
247
277
|
|
|
248
278
|
return fetch(this.endpoint, {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {QueuedEventInfo, TrackingEventProcessor} from './tracker';
|
|
2
|
+
import {Token} from './token';
|
|
3
|
+
import {Logger} from './logging';
|
|
4
|
+
import {TrackingEvent} from './trackingEvents';
|
|
5
|
+
|
|
6
|
+
export class EventSubjectProcessor implements TrackingEventProcessor {
|
|
7
|
+
private currentToken?: Token|null;
|
|
8
|
+
|
|
9
|
+
private logger: Logger;
|
|
10
|
+
|
|
11
|
+
public constructor(logger: Logger) {
|
|
12
|
+
this.logger = logger;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public process(event: QueuedEventInfo): QueuedEventInfo[] {
|
|
16
|
+
const {currentToken} = this;
|
|
17
|
+
|
|
18
|
+
this.currentToken = event.userToken ?? null;
|
|
19
|
+
|
|
20
|
+
if (currentToken === undefined) {
|
|
21
|
+
// This is the first event, no subject to compare.
|
|
22
|
+
// If the user is already identified at this point,
|
|
23
|
+
// assume that the event was previously tracked.
|
|
24
|
+
return [event];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (EventSubjectProcessor.isIdentificationEvent(event.event)) {
|
|
28
|
+
return [event];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const currentSubject = currentToken?.getSubject() ?? null;
|
|
32
|
+
const newSubject = event.userToken?.getSubject() ?? null;
|
|
33
|
+
|
|
34
|
+
if (newSubject === currentSubject) {
|
|
35
|
+
// No change in subject
|
|
36
|
+
return [event];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const events: QueuedEventInfo[] = [];
|
|
40
|
+
|
|
41
|
+
if (currentToken !== null && currentSubject !== null) {
|
|
42
|
+
this.logger.info('External user sign out automatically tracked');
|
|
43
|
+
|
|
44
|
+
events.push({
|
|
45
|
+
timestamp: event.timestamp,
|
|
46
|
+
context: event.context,
|
|
47
|
+
userToken: currentToken,
|
|
48
|
+
event: {
|
|
49
|
+
type: 'userSignedOut',
|
|
50
|
+
userId: currentSubject,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (newSubject !== null) {
|
|
56
|
+
this.logger.info('External user sign in automatically tracked');
|
|
57
|
+
|
|
58
|
+
events.push({
|
|
59
|
+
timestamp: event.timestamp,
|
|
60
|
+
context: event.context,
|
|
61
|
+
userToken: event.userToken,
|
|
62
|
+
event: {
|
|
63
|
+
type: 'userSignedIn',
|
|
64
|
+
userId: newSubject,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
events.push(event);
|
|
70
|
+
|
|
71
|
+
return events;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private static isIdentificationEvent(event: TrackingEvent): boolean {
|
|
75
|
+
switch (event.type) {
|
|
76
|
+
case 'userSignedIn':
|
|
77
|
+
case 'userSignedUp':
|
|
78
|
+
case 'userSignedOut':
|
|
79
|
+
return true;
|
|
80
|
+
|
|
81
|
+
default:
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -21,7 +21,11 @@ function validate(options: unknown): asserts options is FetchOptions {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
type Options = {
|
|
25
|
+
preferredLocale?: string,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type Configuration = Options & {
|
|
25
29
|
contentFetcher: ContentFetcher,
|
|
26
30
|
contextFactory: ContextFactory,
|
|
27
31
|
previewTokenProvider: TokenProvider,
|
|
@@ -40,12 +44,17 @@ export class ContentFetcherFacade {
|
|
|
40
44
|
|
|
41
45
|
private readonly cidAssigner: CidAssigner;
|
|
42
46
|
|
|
47
|
+
private readonly options: Options;
|
|
48
|
+
|
|
43
49
|
public constructor(configuration: Configuration) {
|
|
44
50
|
this.fetcher = configuration.contentFetcher;
|
|
45
51
|
this.previewTokenProvider = configuration.previewTokenProvider;
|
|
46
52
|
this.userTokenProvider = configuration.userTokenProvider;
|
|
47
53
|
this.cidAssigner = configuration.cidAssigner;
|
|
48
54
|
this.contextFactory = configuration.contextFactory;
|
|
55
|
+
this.options = {
|
|
56
|
+
preferredLocale: configuration.preferredLocale,
|
|
57
|
+
};
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
public async fetch<P extends JsonObject>(slotId: string, options: FetchOptions = {}): Promise<FetchResponse<P>> {
|
|
@@ -61,9 +70,9 @@ export class ContentFetcherFacade {
|
|
|
61
70
|
userToken: this.userTokenProvider.getToken() ?? undefined,
|
|
62
71
|
previewToken: this.previewTokenProvider.getToken() ?? undefined,
|
|
63
72
|
version: options.version,
|
|
64
|
-
preferredLocale: options.preferredLocale,
|
|
65
73
|
context: this.contextFactory.createContext(options.attributes),
|
|
66
74
|
timeout: options.timeout,
|
|
75
|
+
preferredLocale: options.preferredLocale ?? this.options.preferredLocale,
|
|
67
76
|
});
|
|
68
77
|
}
|
|
69
78
|
}
|
package/src/facade/sdkFacade.ts
CHANGED
|
@@ -14,8 +14,14 @@ import {CidAssigner} from '../cid';
|
|
|
14
14
|
import {PartialTrackingEvent} from '../trackingEvents';
|
|
15
15
|
import {UrlSanitizer} from '../tab';
|
|
16
16
|
import {ContentFetcherFacade} from './contentFetcherFacade';
|
|
17
|
+
import {CookieCacheConfiguration} from '../cache/cookieCache';
|
|
18
|
+
import {EventSubjectProcessor} from '../eventSubjectProcessor';
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
type Options = {
|
|
21
|
+
preferredLocale?: string,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type Configuration = Options & {
|
|
19
25
|
appId: string,
|
|
20
26
|
tokenScope?: TokenScope,
|
|
21
27
|
debug?: boolean,
|
|
@@ -30,6 +36,10 @@ export type Configuration = {
|
|
|
30
36
|
baseEndpointUrl?: string,
|
|
31
37
|
disableCidMirroring?: boolean,
|
|
32
38
|
cidAssignerEndpointUrl?: string,
|
|
39
|
+
cookie?: {
|
|
40
|
+
clientId?: CookieCacheConfiguration,
|
|
41
|
+
userToken?: CookieCacheConfiguration,
|
|
42
|
+
},
|
|
33
43
|
};
|
|
34
44
|
|
|
35
45
|
function validateConfiguration(configuration: unknown): asserts configuration is Configuration {
|
|
@@ -53,14 +63,17 @@ export class SdkFacade {
|
|
|
53
63
|
|
|
54
64
|
private contentFetcherFacade?: ContentFetcherFacade;
|
|
55
65
|
|
|
56
|
-
private
|
|
66
|
+
private readonly options: Options;
|
|
67
|
+
|
|
68
|
+
private constructor(sdk: Sdk, options: Options = {}) {
|
|
57
69
|
this.sdk = sdk;
|
|
70
|
+
this.options = options;
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
public static init(configuration: Configuration): SdkFacade {
|
|
61
74
|
validateConfiguration(configuration);
|
|
62
75
|
|
|
63
|
-
const {track = true, userId, token, ...containerConfiguration} = configuration;
|
|
76
|
+
const {track = true, userId, token, preferredLocale, ...containerConfiguration} = configuration;
|
|
64
77
|
|
|
65
78
|
if (userId !== undefined && token !== undefined) {
|
|
66
79
|
throw new Error('Either the user ID or token can be specified, but not both.');
|
|
@@ -73,7 +86,11 @@ export class SdkFacade {
|
|
|
73
86
|
debug: containerConfiguration.debug ?? false,
|
|
74
87
|
test: containerConfiguration.test ?? false,
|
|
75
88
|
disableCidMirroring: containerConfiguration.disableCidMirroring ?? false,
|
|
89
|
+
eventProcessor: container => new EventSubjectProcessor(container.getLogger('EventSubjectProcessor')),
|
|
76
90
|
}),
|
|
91
|
+
{
|
|
92
|
+
preferredLocale: preferredLocale,
|
|
93
|
+
},
|
|
77
94
|
);
|
|
78
95
|
|
|
79
96
|
if (userId !== undefined) {
|
|
@@ -166,6 +183,7 @@ export class SdkFacade {
|
|
|
166
183
|
cidAssigner: this.sdk.cidAssigner,
|
|
167
184
|
previewTokenProvider: this.sdk.previewTokenStore,
|
|
168
185
|
userTokenProvider: this.sdk.userTokenStore,
|
|
186
|
+
preferredLocale: this.options.preferredLocale,
|
|
169
187
|
});
|
|
170
188
|
}
|
|
171
189
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ObjectType, StringType, BooleanType, UnionType, NullType, FunctionType} from '../validation';
|
|
2
2
|
import {tokenScopeSchema} from './contextSchemas';
|
|
3
|
-
import {eventMetadataSchema} from './sdkSchemas';
|
|
3
|
+
import {cookieOptionsSchema, eventMetadataSchema} from './sdkSchemas';
|
|
4
4
|
import {loggerSchema} from './loggerSchema';
|
|
5
5
|
|
|
6
6
|
export const sdkFacadeConfigurationSchema = new ObjectType({
|
|
@@ -38,5 +38,14 @@ export const sdkFacadeConfigurationSchema = new ObjectType({
|
|
|
38
38
|
cidAssignerEndpointUrl: new StringType({
|
|
39
39
|
format: 'url',
|
|
40
40
|
}),
|
|
41
|
+
cookie: new ObjectType({
|
|
42
|
+
properties: {
|
|
43
|
+
clientId: cookieOptionsSchema,
|
|
44
|
+
userToken: cookieOptionsSchema,
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
preferredLocale: new StringType({
|
|
48
|
+
pattern: /^[a-z]{2,3}([-_][a-z]{2,3})?$/i,
|
|
49
|
+
}),
|
|
41
50
|
},
|
|
42
51
|
});
|
package/src/schema/sdkSchemas.ts
CHANGED
|
@@ -14,6 +14,29 @@ export const eventMetadataSchema = new ObjectType({
|
|
|
14
14
|
}),
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
+
export const cookieOptionsSchema = new ObjectType({
|
|
18
|
+
required: ['name'],
|
|
19
|
+
properties: {
|
|
20
|
+
name: new StringType({
|
|
21
|
+
minLength: 1,
|
|
22
|
+
}),
|
|
23
|
+
domain: new StringType({
|
|
24
|
+
minLength: 1,
|
|
25
|
+
}),
|
|
26
|
+
path: new StringType({
|
|
27
|
+
minLength: 1,
|
|
28
|
+
}),
|
|
29
|
+
secure: new BooleanType(),
|
|
30
|
+
sameSite: new StringType({
|
|
31
|
+
enumeration: ['strict', 'lax', 'none'],
|
|
32
|
+
}),
|
|
33
|
+
maxAge: new NumberType({
|
|
34
|
+
minimum: 0,
|
|
35
|
+
integer: true,
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
17
40
|
export const sdkConfigurationSchema = new ObjectType({
|
|
18
41
|
required: ['appId', 'tokenScope', 'disableCidMirroring', 'debug', 'test'],
|
|
19
42
|
properties: {
|
|
@@ -35,10 +58,17 @@ export const sdkConfigurationSchema = new ObjectType({
|
|
|
35
58
|
integer: true,
|
|
36
59
|
}),
|
|
37
60
|
disableCidMirroring: new BooleanType(),
|
|
61
|
+
cookie: new ObjectType({
|
|
62
|
+
properties: {
|
|
63
|
+
clientId: cookieOptionsSchema,
|
|
64
|
+
userToken: cookieOptionsSchema,
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
38
67
|
debug: new BooleanType(),
|
|
39
68
|
test: new BooleanType(),
|
|
40
69
|
logger: loggerSchema,
|
|
41
70
|
urlSanitizer: new FunctionType(),
|
|
42
71
|
eventMetadata: eventMetadataSchema,
|
|
72
|
+
eventProcessor: new FunctionType(),
|
|
43
73
|
},
|
|
44
74
|
});
|
package/src/sdk.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {Container} from './container';
|
|
1
|
+
import {Container, DependencyResolver} from './container';
|
|
2
2
|
import {Context, TokenScope} from './context';
|
|
3
3
|
import {Logger} from './logging';
|
|
4
4
|
import {BASE_ENDPOINT_URL, VERSION} from './constants';
|
|
5
5
|
import {sdkConfigurationSchema} from './schema';
|
|
6
6
|
import {formatCause} from './error';
|
|
7
|
-
import {Tracker} from './tracker';
|
|
7
|
+
import {Tracker, TrackingEventProcessor} from './tracker';
|
|
8
8
|
import {Evaluator} from './evaluator';
|
|
9
9
|
import {SdkEventMap} from './sdkEvents';
|
|
10
10
|
import {EventManager} from './eventManager';
|
|
@@ -12,6 +12,7 @@ import {CidAssigner} from './cid';
|
|
|
12
12
|
import {UrlSanitizer} from './tab';
|
|
13
13
|
import {ContentFetcher} from './contentFetcher';
|
|
14
14
|
import {TokenStore} from './token';
|
|
15
|
+
import {CookieCacheConfiguration} from './cache/cookieCache';
|
|
15
16
|
|
|
16
17
|
export type Configuration = {
|
|
17
18
|
appId: string,
|
|
@@ -26,6 +27,11 @@ export type Configuration = {
|
|
|
26
27
|
urlSanitizer?: UrlSanitizer,
|
|
27
28
|
logger?: Logger,
|
|
28
29
|
eventMetadata?: {[key: string]: string},
|
|
30
|
+
cookie?: {
|
|
31
|
+
clientId?: CookieCacheConfiguration,
|
|
32
|
+
userToken?: CookieCacheConfiguration,
|
|
33
|
+
},
|
|
34
|
+
eventProcessor?: DependencyResolver<TrackingEventProcessor>,
|
|
29
35
|
};
|
|
30
36
|
|
|
31
37
|
function validateConfiguration(configuration: unknown): asserts configuration is Configuration {
|
|
@@ -53,7 +59,6 @@ export class Sdk {
|
|
|
53
59
|
validateConfiguration(configuration);
|
|
54
60
|
|
|
55
61
|
const {
|
|
56
|
-
disableCidMirroring,
|
|
57
62
|
eventMetadata: customMetadata = {},
|
|
58
63
|
baseEndpointUrl = BASE_ENDPOINT_URL,
|
|
59
64
|
cidAssignerEndpointUrl,
|
|
@@ -73,7 +78,6 @@ export class Sdk {
|
|
|
73
78
|
|
|
74
79
|
const container = new Container({
|
|
75
80
|
...containerConfiguration,
|
|
76
|
-
disableCidMirroring: disableCidMirroring,
|
|
77
81
|
evaluationBaseEndpointUrl: baseHttpEndpoint,
|
|
78
82
|
contentBaseEndpointUrl: baseHttpEndpoint,
|
|
79
83
|
trackerEndpointUrl: `${baseWsEndpoint}/client/web/connect`,
|