@croct/sdk 0.10.0 → 0.11.0-alpha
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 +32 -36
- package/cache/fallbackCache.js +15 -32
- package/cache/inMemoryCache.js +9 -10
- package/cache/index.js +1 -1
- package/cache/localStorageCache.js +24 -25
- package/channel/beaconSocketChannel.d.ts +1 -1
- package/channel/beaconSocketChannel.js +49 -79
- package/channel/channel.d.ts +1 -1
- package/channel/encodedChannel.js +8 -10
- package/channel/guaranteedChannel.d.ts +4 -4
- package/channel/guaranteedChannel.js +41 -43
- package/channel/index.js +1 -1
- package/channel/queuedChannel.js +35 -64
- package/channel/retryChannel.d.ts +1 -1
- package/channel/retryChannel.js +44 -77
- package/channel/sandboxChannel.js +17 -18
- package/channel/socketChannel.d.ts +4 -4
- package/channel/socketChannel.js +77 -79
- package/cid/cachedAssigner.js +15 -27
- package/cid/fixedAssigner.js +5 -6
- package/cid/index.js +1 -1
- package/cid/remoteAssigner.js +23 -36
- package/constants.d.ts +3 -2
- package/constants.js +6 -5
- package/container.d.ts +13 -6
- package/container.js +152 -168
- package/contentFetcher.d.ts +59 -0
- package/contentFetcher.js +129 -0
- package/context.d.ts +3 -3
- package/context.js +36 -38
- package/error.js +2 -2
- package/evaluator.d.ts +33 -24
- package/evaluator.js +126 -117
- package/eventManager.d.ts +1 -1
- package/eventManager.js +14 -15
- package/facade/contentFetcherFacade.d.ts +27 -0
- package/facade/contentFetcherFacade.js +40 -0
- package/facade/evaluatorFacade.d.ts +13 -3
- package/facade/evaluatorFacade.js +57 -72
- package/facade/sdkFacade.d.ts +10 -3
- package/facade/sdkFacade.js +129 -141
- package/facade/sessionFacade.js +6 -7
- package/facade/sessionPatch.js +9 -13
- package/facade/trackerFacade.js +32 -38
- package/facade/userFacade.js +10 -11
- package/facade/userPatch.js +9 -13
- package/index.js +2 -2
- package/logging/consoleLogger.js +18 -35
- package/logging/index.js +1 -1
- package/logging/namespacedLogger.js +14 -15
- package/logging/nullLogger.js +10 -13
- package/namespacedStorage.js +30 -47
- package/package.json +13 -16
- package/patch.d.ts +1 -1
- package/queue/capacityRestrictedQueue.js +17 -18
- package/queue/inMemoryQueue.js +22 -28
- package/queue/index.js +1 -1
- package/queue/monitoredQueue.d.ts +2 -2
- package/queue/monitoredQueue.js +39 -40
- package/queue/persistentQueue.js +33 -38
- package/retry/arbitraryPolicy.js +8 -10
- package/retry/backoffPolicy.d.ts +1 -1
- package/retry/backoffPolicy.js +11 -13
- package/retry/index.js +1 -1
- package/retry/maxAttemptsPolicy.js +7 -8
- package/retry/neverPolicy.js +6 -9
- package/schema/attributeSchema.js +1 -1
- package/schema/contentFetcherSchemas.d.ts +2 -0
- package/schema/contentFetcherSchemas.js +22 -0
- package/schema/contentSchemas.js +1 -1
- package/schema/contextSchemas.js +1 -1
- package/schema/ecommerceSchemas.js +1 -1
- package/schema/evaluatorSchemas.d.ts +2 -0
- package/schema/{evaluationSchemas.js → evaluatorSchemas.js} +3 -3
- package/schema/eventSchemas.js +5 -7
- package/schema/index.d.ts +2 -1
- package/schema/index.js +3 -2
- package/schema/loggerSchema.js +1 -1
- package/schema/operationSchemas.js +8 -8
- package/schema/sdkFacadeSchemas.js +9 -6
- package/schema/sdkSchemas.js +8 -5
- package/schema/tokenSchema.js +5 -4
- package/schema/userSchema.js +2 -2
- package/sdk.d.ts +9 -3
- package/sdk.js +81 -127
- package/sdkEvents.d.ts +3 -3
- package/sourceLocation.d.ts +3 -3
- package/sourceLocation.js +13 -14
- package/tab.d.ts +5 -5
- package/tab.js +50 -80
- package/token/cachedTokenStore.js +9 -10
- package/token/inMemoryTokenStore.js +7 -8
- package/token/index.js +1 -1
- package/token/replicatedTokenStore.js +7 -8
- package/token/token.d.ts +9 -5
- package/token/token.js +63 -57
- package/tracker.d.ts +4 -4
- package/tracker.js +145 -122
- package/trackingEvents.d.ts +36 -36
- package/trackingEvents.js +12 -6
- package/transformer.js +1 -1
- package/utilityTypes.d.ts +2 -2
- package/uuid.js +9 -7
- package/validation/arrayType.d.ts +2 -2
- package/validation/arrayType.js +29 -27
- package/validation/booleanType.js +11 -15
- package/validation/functionType.js +11 -15
- package/validation/index.js +1 -1
- package/validation/jsonType.d.ts +2 -2
- package/validation/jsonType.js +61 -80
- package/validation/mixedSchema.js +4 -7
- package/validation/nullType.js +11 -15
- package/validation/numberType.d.ts +1 -1
- package/validation/numberType.js +23 -22
- package/validation/objectType.d.ts +1 -1
- package/validation/objectType.js +61 -72
- package/validation/schema.js +6 -10
- package/validation/stringType.d.ts +1 -1
- package/validation/stringType.js +36 -47
- package/validation/unionType.js +27 -77
- package/validation/violation.js +1 -2
- package/schema/evaluationSchemas.d.ts +0 -2
package/context.js
CHANGED
|
@@ -1,70 +1,69 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Context = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const token_1 = require("./token");
|
|
5
|
+
const tab_1 = require("./tab");
|
|
6
|
+
const uuid_1 = require("./uuid");
|
|
7
7
|
function tokenEquals(left, right) {
|
|
8
8
|
return left === right || (left !== null && right !== null && left.toString() === right.toString());
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
class Context {
|
|
11
|
+
constructor(tab, tokenStore, eventDispatcher) {
|
|
12
12
|
this.tab = tab;
|
|
13
13
|
this.tokenStore = tokenStore;
|
|
14
14
|
this.eventDispatcher = eventDispatcher;
|
|
15
15
|
this.lastToken = tokenStore.getToken();
|
|
16
16
|
this.syncToken = this.syncToken.bind(this);
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
var newTab = false;
|
|
18
|
+
static load({ cache, tokenScope, eventDispatcher, urlSanitizer }) {
|
|
19
|
+
let tabId = cache.tabId.get();
|
|
20
|
+
let newTab = false;
|
|
22
21
|
if (tabId === null) {
|
|
23
22
|
tabId = (0, uuid_1.uuid4)(true);
|
|
24
23
|
newTab = true;
|
|
25
24
|
}
|
|
26
|
-
|
|
25
|
+
const tab = new tab_1.Tab(tabId, newTab, urlSanitizer);
|
|
27
26
|
cache.tabId.clear();
|
|
28
|
-
tab.addListener('unload',
|
|
27
|
+
tab.addListener('unload', () => cache.tabId.put(tab.id));
|
|
29
28
|
switch (tokenScope) {
|
|
30
29
|
case 'isolated':
|
|
31
30
|
return new Context(tab, new token_1.InMemoryTokenStore(), eventDispatcher);
|
|
32
31
|
case 'global': {
|
|
33
|
-
|
|
32
|
+
const context = new Context(tab, new token_1.CachedTokenStore(cache.browserToken), eventDispatcher);
|
|
34
33
|
cache.browserToken.addListener(context.syncToken);
|
|
35
34
|
return context;
|
|
36
35
|
}
|
|
37
36
|
case 'contextual': {
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const primaryStorage = new token_1.CachedTokenStore(cache.tabToken);
|
|
38
|
+
const secondaryStorage = new token_1.CachedTokenStore(cache.browserToken);
|
|
40
39
|
if (tab.isNew) {
|
|
41
|
-
|
|
40
|
+
primaryStorage.setToken(secondaryStorage.getToken());
|
|
42
41
|
}
|
|
43
|
-
tab.addListener('visibilityChange',
|
|
42
|
+
tab.addListener('visibilityChange', event => {
|
|
44
43
|
if (event.detail.visible) {
|
|
45
|
-
|
|
44
|
+
secondaryStorage.setToken(primaryStorage.getToken());
|
|
46
45
|
}
|
|
47
46
|
});
|
|
48
|
-
return new Context(tab, new token_1.ReplicatedTokenStore(
|
|
47
|
+
return new Context(tab, new token_1.ReplicatedTokenStore(primaryStorage, secondaryStorage), eventDispatcher);
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
|
-
}
|
|
52
|
-
|
|
50
|
+
}
|
|
51
|
+
getTab() {
|
|
53
52
|
return this.tab;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
}
|
|
54
|
+
isAnonymous() {
|
|
55
|
+
const token = this.getToken();
|
|
57
56
|
return token == null || token.isAnonymous();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
}
|
|
58
|
+
getUser() {
|
|
59
|
+
const token = this.getToken();
|
|
61
60
|
return token == null ? null : token.getSubject();
|
|
62
|
-
}
|
|
63
|
-
|
|
61
|
+
}
|
|
62
|
+
getToken() {
|
|
64
63
|
return this.tokenStore.getToken();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
}
|
|
65
|
+
setToken(token) {
|
|
66
|
+
const oldToken = this.lastToken;
|
|
68
67
|
this.lastToken = token;
|
|
69
68
|
this.tokenStore.setToken(token);
|
|
70
69
|
if (!tokenEquals(oldToken, token)) {
|
|
@@ -73,10 +72,10 @@ var Context = /** @class */ (function () {
|
|
|
73
72
|
newToken: token,
|
|
74
73
|
});
|
|
75
74
|
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
}
|
|
76
|
+
syncToken() {
|
|
77
|
+
const newToken = this.tokenStore.getToken();
|
|
78
|
+
const oldToken = this.lastToken;
|
|
80
79
|
if (!tokenEquals(oldToken, newToken)) {
|
|
81
80
|
this.lastToken = newToken;
|
|
82
81
|
this.eventDispatcher.dispatch('tokenChanged', {
|
|
@@ -84,7 +83,6 @@ var Context = /** @class */ (function () {
|
|
|
84
83
|
newToken: newToken,
|
|
85
84
|
});
|
|
86
85
|
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
}());
|
|
86
|
+
}
|
|
87
|
+
}
|
|
90
88
|
exports.Context = Context;
|
package/error.js
CHANGED
|
@@ -11,7 +11,7 @@ function extractMessage(error) {
|
|
|
11
11
|
return 'unknown error';
|
|
12
12
|
}
|
|
13
13
|
function formatMessage(error) {
|
|
14
|
-
|
|
14
|
+
const message = extractMessage(error);
|
|
15
15
|
if (message.length === 0) {
|
|
16
16
|
return message;
|
|
17
17
|
}
|
|
@@ -19,7 +19,7 @@ function formatMessage(error) {
|
|
|
19
19
|
}
|
|
20
20
|
exports.formatMessage = formatMessage;
|
|
21
21
|
function formatCause(error) {
|
|
22
|
-
|
|
22
|
+
const message = formatMessage(error);
|
|
23
23
|
if (message.length === 0) {
|
|
24
24
|
return message;
|
|
25
25
|
}
|
package/evaluator.d.ts
CHANGED
|
@@ -1,45 +1,47 @@
|
|
|
1
1
|
import { JsonObject, JsonValue } from '@croct/json';
|
|
2
|
-
import {
|
|
2
|
+
import { Token } from './token';
|
|
3
3
|
import { Location } from './sourceLocation';
|
|
4
|
-
|
|
5
|
-
export declare type Configuration = {
|
|
6
|
-
appId: string;
|
|
7
|
-
endpointUrl?: string;
|
|
8
|
-
tokenProvider: TokenProvider;
|
|
9
|
-
cidAssigner: CidAssigner;
|
|
10
|
-
};
|
|
11
|
-
export declare type Campaign = {
|
|
4
|
+
export type Campaign = {
|
|
12
5
|
name?: string;
|
|
13
6
|
source?: string;
|
|
14
7
|
medium?: string;
|
|
15
8
|
term?: string;
|
|
16
9
|
content?: string;
|
|
17
10
|
};
|
|
18
|
-
export
|
|
19
|
-
title: string;
|
|
11
|
+
export type Page = {
|
|
20
12
|
url: string;
|
|
13
|
+
title?: string;
|
|
21
14
|
referrer?: string;
|
|
22
15
|
};
|
|
23
|
-
export
|
|
24
|
-
|
|
16
|
+
export type EvaluationContext = {
|
|
17
|
+
timeZone?: string;
|
|
25
18
|
campaign?: Campaign;
|
|
26
19
|
page?: Page;
|
|
27
20
|
attributes?: JsonObject;
|
|
28
21
|
};
|
|
29
|
-
|
|
22
|
+
type AllowedFetchOptions = Exclude<keyof RequestInit, 'method' | 'body' | 'headers' | 'signal'>;
|
|
23
|
+
type ExtraFetchOptions<T extends keyof RequestInit = AllowedFetchOptions> = Pick<RequestInit, T> & {
|
|
24
|
+
[key in Exclude<keyof RequestInit, T>]?: never;
|
|
25
|
+
} & Record<string, any>;
|
|
26
|
+
export type EvaluationOptions = {
|
|
27
|
+
clientId?: string;
|
|
28
|
+
clientIp?: string;
|
|
29
|
+
userAgent?: string;
|
|
30
|
+
userToken?: Token | string;
|
|
30
31
|
timeout?: number;
|
|
31
32
|
context?: EvaluationContext;
|
|
33
|
+
extra?: ExtraFetchOptions;
|
|
32
34
|
};
|
|
33
35
|
export declare enum EvaluationErrorType {
|
|
34
36
|
TIMEOUT = "https://croct.help/api/evaluation#timeout",
|
|
35
37
|
UNEXPECTED_ERROR = "https://croct.help/api/evaluation#unexpected-error",
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
INVALID_QUERY = "https://croct.help/api/evaluation#invalid-query",
|
|
39
|
+
TOO_COMPLEX_QUERY = "https://croct.help/api/evaluation#too-complex-query",
|
|
38
40
|
EVALUATION_FAILED = "https://croct.help/api/evaluation#evaluation-failed",
|
|
39
41
|
UNALLOWED_RESULT = "https://croct.help/api/evaluation#unallowed-result",
|
|
40
42
|
UNSERIALIZABLE_RESULT = "https://croct.help/api/evaluation#unserializable-result"
|
|
41
43
|
}
|
|
42
|
-
export
|
|
44
|
+
export type ErrorResponse = {
|
|
43
45
|
type: EvaluationErrorType;
|
|
44
46
|
title: string;
|
|
45
47
|
status: number;
|
|
@@ -49,21 +51,28 @@ export declare class EvaluationError<T extends ErrorResponse = ErrorResponse> ex
|
|
|
49
51
|
readonly response: T;
|
|
50
52
|
constructor(response: T);
|
|
51
53
|
}
|
|
52
|
-
|
|
54
|
+
type QueryErrorDetail = {
|
|
53
55
|
cause: string;
|
|
54
56
|
location: Location;
|
|
55
57
|
};
|
|
56
|
-
export
|
|
57
|
-
errors:
|
|
58
|
+
export type QueryErrorResponse = ErrorResponse & {
|
|
59
|
+
errors: QueryErrorDetail[];
|
|
58
60
|
};
|
|
59
|
-
export declare class
|
|
60
|
-
constructor(response:
|
|
61
|
+
export declare class QueryError extends EvaluationError<QueryErrorResponse> {
|
|
62
|
+
constructor(response: QueryErrorResponse);
|
|
61
63
|
}
|
|
64
|
+
export type Configuration = {
|
|
65
|
+
appId?: string;
|
|
66
|
+
apiKey?: string;
|
|
67
|
+
endpointUrl?: string;
|
|
68
|
+
};
|
|
62
69
|
export declare class Evaluator {
|
|
63
|
-
static readonly
|
|
70
|
+
static readonly MAX_QUERY_LENGTH: number;
|
|
64
71
|
private readonly configuration;
|
|
72
|
+
private readonly endpoint;
|
|
65
73
|
constructor(configuration: Configuration);
|
|
66
|
-
evaluate(
|
|
74
|
+
evaluate(query: string, options?: EvaluationOptions): Promise<JsonValue>;
|
|
67
75
|
private fetch;
|
|
76
|
+
toJSON(): never;
|
|
68
77
|
}
|
|
69
78
|
export {};
|
package/evaluator.js
CHANGED
|
@@ -1,138 +1,147 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Evaluator = exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
var sourceLocation_1 = require("./sourceLocation");
|
|
3
|
+
exports.Evaluator = exports.QueryError = exports.EvaluationError = exports.EvaluationErrorType = void 0;
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
const error_1 = require("./error");
|
|
6
|
+
const sourceLocation_1 = require("./sourceLocation");
|
|
8
7
|
var EvaluationErrorType;
|
|
9
8
|
(function (EvaluationErrorType) {
|
|
10
9
|
EvaluationErrorType["TIMEOUT"] = "https://croct.help/api/evaluation#timeout";
|
|
11
10
|
EvaluationErrorType["UNEXPECTED_ERROR"] = "https://croct.help/api/evaluation#unexpected-error";
|
|
12
|
-
EvaluationErrorType["
|
|
13
|
-
EvaluationErrorType["
|
|
11
|
+
EvaluationErrorType["INVALID_QUERY"] = "https://croct.help/api/evaluation#invalid-query";
|
|
12
|
+
EvaluationErrorType["TOO_COMPLEX_QUERY"] = "https://croct.help/api/evaluation#too-complex-query";
|
|
14
13
|
EvaluationErrorType["EVALUATION_FAILED"] = "https://croct.help/api/evaluation#evaluation-failed";
|
|
15
14
|
EvaluationErrorType["UNALLOWED_RESULT"] = "https://croct.help/api/evaluation#unallowed-result";
|
|
16
15
|
EvaluationErrorType["UNSERIALIZABLE_RESULT"] = "https://croct.help/api/evaluation#unserializable-result";
|
|
17
16
|
})(EvaluationErrorType = exports.EvaluationErrorType || (exports.EvaluationErrorType = {}));
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Object.setPrototypeOf(_this, EvaluationError.prototype);
|
|
24
|
-
return _this;
|
|
17
|
+
class EvaluationError extends Error {
|
|
18
|
+
constructor(response) {
|
|
19
|
+
super(response.title);
|
|
20
|
+
this.response = response;
|
|
21
|
+
Object.setPrototypeOf(this, EvaluationError.prototype);
|
|
25
22
|
}
|
|
26
|
-
|
|
27
|
-
}(Error));
|
|
23
|
+
}
|
|
28
24
|
exports.EvaluationError = EvaluationError;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Object.setPrototypeOf(_this, ExpressionError.prototype);
|
|
34
|
-
return _this;
|
|
25
|
+
class QueryError extends EvaluationError {
|
|
26
|
+
constructor(response) {
|
|
27
|
+
super(response);
|
|
28
|
+
Object.setPrototypeOf(this, QueryError.prototype);
|
|
35
29
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
}
|
|
31
|
+
exports.QueryError = QueryError;
|
|
32
|
+
class Evaluator {
|
|
33
|
+
constructor(configuration) {
|
|
34
|
+
if ((configuration.appId === undefined) === (configuration.apiKey === undefined)) {
|
|
35
|
+
throw new Error('Either the application ID or the API key must be provided.');
|
|
36
|
+
}
|
|
37
|
+
const { endpointUrl, apiKey } = configuration;
|
|
38
|
+
// eslint-disable-next-line prefer-template -- Better readability
|
|
39
|
+
this.endpoint = (endpointUrl !== null && endpointUrl !== void 0 ? endpointUrl : constants_1.EVALUATION_ENDPOINT_URL).replace(/\/+$/, '')
|
|
40
|
+
+ (apiKey === undefined ? '/client' : '/external')
|
|
41
|
+
+ '/web/evaluate';
|
|
42
|
+
this.configuration = configuration;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
44
|
+
evaluate(query, options = {}) {
|
|
45
|
+
const length = (0, sourceLocation_1.getLength)(query);
|
|
46
|
+
if (length > Evaluator.MAX_QUERY_LENGTH) {
|
|
47
|
+
const response = {
|
|
48
|
+
title: 'The query is too complex.',
|
|
49
|
+
status: 422,
|
|
50
|
+
type: EvaluationErrorType.TOO_COMPLEX_QUERY,
|
|
51
|
+
detail: `The query must be at most ${Evaluator.MAX_QUERY_LENGTH} characters long, `
|
|
52
|
+
+ `but it is ${length} characters long.`,
|
|
53
|
+
errors: [{
|
|
54
|
+
cause: 'The query is longer than expected.',
|
|
55
|
+
location: (0, sourceLocation_1.getLocation)(query, 0, Math.max(length - 1, 0)),
|
|
56
|
+
}],
|
|
57
|
+
};
|
|
58
|
+
return Promise.reject(new QueryError(response));
|
|
59
|
+
}
|
|
60
|
+
const body = {
|
|
61
|
+
query: query,
|
|
62
|
+
};
|
|
63
|
+
if (options.context !== undefined) {
|
|
64
|
+
body.context = options.context;
|
|
65
|
+
}
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const abortController = new AbortController();
|
|
68
|
+
if (options.timeout !== undefined) {
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
const response = {
|
|
71
|
+
title: 'Maximum evaluation timeout reached before evaluation could complete.',
|
|
72
|
+
type: EvaluationErrorType.TIMEOUT,
|
|
73
|
+
detail: `The evaluation took more than ${options.timeout}ms to complete.`,
|
|
74
|
+
status: 408, // Request Timeout
|
|
62
75
|
};
|
|
63
|
-
|
|
76
|
+
abortController.abort();
|
|
77
|
+
reject(new EvaluationError(response));
|
|
78
|
+
}, options.timeout);
|
|
79
|
+
}
|
|
80
|
+
const promise = this.fetch(body, abortController.signal, options);
|
|
81
|
+
promise.then(response => response.json()
|
|
82
|
+
.then(data => {
|
|
83
|
+
if (response.ok) {
|
|
84
|
+
return resolve(data);
|
|
64
85
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
86
|
+
const errorResponse = data;
|
|
87
|
+
switch (errorResponse.type) {
|
|
88
|
+
case EvaluationErrorType.INVALID_QUERY:
|
|
89
|
+
case EvaluationErrorType.EVALUATION_FAILED:
|
|
90
|
+
case EvaluationErrorType.TOO_COMPLEX_QUERY:
|
|
91
|
+
reject(new QueryError(errorResponse));
|
|
92
|
+
break;
|
|
93
|
+
default:
|
|
94
|
+
reject(new EvaluationError(errorResponse));
|
|
95
|
+
break;
|
|
69
96
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
reject(new EvaluationError(response));
|
|
80
|
-
}, options.timeout);
|
|
81
|
-
}
|
|
82
|
-
var promise = _this.fetch(endpoint.toString());
|
|
83
|
-
promise.then(function (response) {
|
|
84
|
-
if (response.ok) {
|
|
85
|
-
response.json().then(resolve);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
response.json().then(function (result) {
|
|
89
|
-
var errorResponse = result;
|
|
90
|
-
switch (errorResponse.type) {
|
|
91
|
-
case EvaluationErrorType.INVALID_EXPRESSION:
|
|
92
|
-
case EvaluationErrorType.EVALUATION_FAILED:
|
|
93
|
-
case EvaluationErrorType.TOO_COMPLEX_EXPRESSION:
|
|
94
|
-
reject(new ExpressionError(errorResponse));
|
|
95
|
-
break;
|
|
96
|
-
default:
|
|
97
|
-
reject(new EvaluationError(errorResponse));
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}, function (error) {
|
|
102
|
-
var errorResponse = {
|
|
103
|
-
title: (0, error_1.formatMessage)(error),
|
|
104
|
-
type: EvaluationErrorType.UNEXPECTED_ERROR,
|
|
105
|
-
detail: 'Please try again or contact Croct support if the error persists.',
|
|
106
|
-
status: 500, // Internal Server Error
|
|
107
|
-
};
|
|
108
|
-
reject(new EvaluationError(errorResponse));
|
|
109
|
-
});
|
|
110
|
-
})];
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
Evaluator.prototype.fetch = function (endpoint) {
|
|
115
|
-
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
116
|
-
var _a, tokenProvider, cidAssigner, appId, token, cid, headers;
|
|
117
|
-
return tslib_1.__generator(this, function (_b) {
|
|
118
|
-
switch (_b.label) {
|
|
119
|
-
case 0:
|
|
120
|
-
_a = this.configuration, tokenProvider = _a.tokenProvider, cidAssigner = _a.cidAssigner, appId = _a.appId;
|
|
121
|
-
token = tokenProvider.getToken();
|
|
122
|
-
return [4 /*yield*/, cidAssigner.assignCid()];
|
|
123
|
-
case 1:
|
|
124
|
-
cid = _b.sent();
|
|
125
|
-
headers = tslib_1.__assign({ 'X-App-Id': appId, 'X-Client-Id': cid }, (token !== null && { 'X-Token': token.toString() }));
|
|
126
|
-
return [2 /*return*/, window.fetch(endpoint.toString(), {
|
|
127
|
-
method: 'GET',
|
|
128
|
-
headers: headers,
|
|
129
|
-
credentials: 'include',
|
|
130
|
-
})];
|
|
97
|
+
}))
|
|
98
|
+
.catch(error => {
|
|
99
|
+
if (!abortController.signal.aborted) {
|
|
100
|
+
reject(new EvaluationError({
|
|
101
|
+
title: (0, error_1.formatMessage)(error),
|
|
102
|
+
type: EvaluationErrorType.UNEXPECTED_ERROR,
|
|
103
|
+
detail: 'Please try again or contact Croct support if the error persists.',
|
|
104
|
+
status: 500, // Internal Server Error
|
|
105
|
+
}));
|
|
131
106
|
}
|
|
132
107
|
});
|
|
133
108
|
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
109
|
+
}
|
|
110
|
+
fetch(body, signal, options) {
|
|
111
|
+
const { appId, apiKey } = this.configuration;
|
|
112
|
+
const { clientId, clientIp, userAgent, userToken } = options;
|
|
113
|
+
const headers = new Headers();
|
|
114
|
+
if (apiKey !== undefined) {
|
|
115
|
+
headers.set('X-Api-Key', apiKey);
|
|
116
|
+
}
|
|
117
|
+
else if (appId !== undefined) {
|
|
118
|
+
headers.set('X-App-Id', appId);
|
|
119
|
+
}
|
|
120
|
+
if (clientId !== undefined) {
|
|
121
|
+
headers.set('X-Client-Id', clientId);
|
|
122
|
+
}
|
|
123
|
+
if (clientIp !== undefined) {
|
|
124
|
+
headers.set('X-Client-Ip', clientIp);
|
|
125
|
+
}
|
|
126
|
+
if (userToken !== undefined) {
|
|
127
|
+
headers.set('X-Token', userToken.toString());
|
|
128
|
+
}
|
|
129
|
+
if (userAgent !== undefined) {
|
|
130
|
+
headers.set('User-Agent', userAgent);
|
|
131
|
+
}
|
|
132
|
+
return fetch(this.endpoint, {
|
|
133
|
+
credentials: 'omit',
|
|
134
|
+
...options.extra,
|
|
135
|
+
method: 'POST',
|
|
136
|
+
headers: headers,
|
|
137
|
+
signal: signal,
|
|
138
|
+
body: JSON.stringify(body),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
toJSON() {
|
|
142
|
+
// Prevent sensitive configuration from being serialized
|
|
143
|
+
throw new Error('Unserializable value.');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
138
146
|
exports.Evaluator = Evaluator;
|
|
147
|
+
Evaluator.MAX_QUERY_LENGTH = constants_1.MAX_QUERY_LENGTH;
|
package/eventManager.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export interface EventListener<T> {
|
|
2
2
|
(event: T): void;
|
|
3
3
|
}
|
|
4
|
-
export
|
|
4
|
+
export type EventMap = Record<string, Record<string, any>>;
|
|
5
5
|
export interface EventDispatcher<TEvents extends EventMap> {
|
|
6
6
|
dispatch<T extends keyof TEvents>(eventName: T, event: TEvents[T]): void;
|
|
7
7
|
}
|
package/eventManager.js
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SynchronousEventManager = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
class SynchronousEventManager {
|
|
5
|
+
constructor() {
|
|
6
6
|
this.listeners = {};
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
addListener(type, listener) {
|
|
9
9
|
var _a;
|
|
10
|
-
|
|
10
|
+
const listeners = (_a = this.listeners[type]) !== null && _a !== void 0 ? _a : [];
|
|
11
11
|
listeners.push(listener);
|
|
12
12
|
this.listeners[type] = listeners;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
}
|
|
14
|
+
removeListener(eventName, listener) {
|
|
15
|
+
const listeners = this.listeners[eventName];
|
|
16
16
|
if (listeners === undefined) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
const index = listeners.indexOf(listener);
|
|
20
20
|
if (index >= 0) {
|
|
21
21
|
listeners.splice(index, 1);
|
|
22
22
|
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
}
|
|
24
|
+
dispatch(eventName, event) {
|
|
25
|
+
const listeners = this.listeners[eventName];
|
|
26
26
|
if (listeners !== undefined) {
|
|
27
|
-
listeners.forEach(
|
|
27
|
+
listeners.forEach(listener => listener(event));
|
|
28
28
|
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
}());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
32
31
|
exports.SynchronousEventManager = SynchronousEventManager;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { JsonObject } from '@croct/json';
|
|
2
|
+
import { ContentFetcher, FetchResponse } from '../contentFetcher';
|
|
3
|
+
import { ContextFactory } from './evaluatorFacade';
|
|
4
|
+
import { TokenProvider } from '../token';
|
|
5
|
+
import { CidAssigner } from '../cid';
|
|
6
|
+
export type FetchOptions = {
|
|
7
|
+
version?: `${number}` | number;
|
|
8
|
+
preferredLocale?: string;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
attributes?: JsonObject;
|
|
11
|
+
};
|
|
12
|
+
export type Configuration = {
|
|
13
|
+
contentFetcher: ContentFetcher;
|
|
14
|
+
contextFactory: ContextFactory;
|
|
15
|
+
previewTokenProvider: TokenProvider;
|
|
16
|
+
userTokenProvider: TokenProvider;
|
|
17
|
+
cidAssigner: CidAssigner;
|
|
18
|
+
};
|
|
19
|
+
export declare class ContentFetcherFacade {
|
|
20
|
+
private readonly fetcher;
|
|
21
|
+
private readonly contextFactory;
|
|
22
|
+
private readonly previewTokenProvider;
|
|
23
|
+
private readonly userTokenProvider;
|
|
24
|
+
private readonly cidAssigner;
|
|
25
|
+
constructor(configuration: Configuration);
|
|
26
|
+
fetch<P extends JsonObject>(slotId: string, options?: FetchOptions): Promise<FetchResponse<P>>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentFetcherFacade = void 0;
|
|
4
|
+
const error_1 = require("../error");
|
|
5
|
+
const schema_1 = require("../schema");
|
|
6
|
+
function validate(options) {
|
|
7
|
+
try {
|
|
8
|
+
schema_1.fetchOptionsSchema.validate(options);
|
|
9
|
+
}
|
|
10
|
+
catch (violation) {
|
|
11
|
+
throw new Error(`Invalid options: ${(0, error_1.formatCause)(violation)}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
class ContentFetcherFacade {
|
|
15
|
+
constructor(configuration) {
|
|
16
|
+
this.fetcher = configuration.contentFetcher;
|
|
17
|
+
this.previewTokenProvider = configuration.previewTokenProvider;
|
|
18
|
+
this.userTokenProvider = configuration.userTokenProvider;
|
|
19
|
+
this.cidAssigner = configuration.cidAssigner;
|
|
20
|
+
this.contextFactory = configuration.contextFactory;
|
|
21
|
+
}
|
|
22
|
+
async fetch(slotId, options = {}) {
|
|
23
|
+
var _a, _b;
|
|
24
|
+
if (typeof slotId !== 'string' || slotId.length === 0) {
|
|
25
|
+
throw new Error('The slot ID must be a non-empty string.');
|
|
26
|
+
}
|
|
27
|
+
validate(options);
|
|
28
|
+
return this.fetcher.fetch(slotId, {
|
|
29
|
+
static: false,
|
|
30
|
+
clientId: await this.cidAssigner.assignCid(),
|
|
31
|
+
userToken: (_a = this.userTokenProvider.getToken()) !== null && _a !== void 0 ? _a : undefined,
|
|
32
|
+
previewToken: (_b = this.previewTokenProvider.getToken()) !== null && _b !== void 0 ? _b : undefined,
|
|
33
|
+
version: options.version,
|
|
34
|
+
preferredLocale: options.preferredLocale,
|
|
35
|
+
context: this.contextFactory.createContext(options.attributes),
|
|
36
|
+
timeout: options.timeout,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.ContentFetcherFacade = ContentFetcherFacade;
|