@croct/sdk 0.9.1 → 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.
Files changed (122) hide show
  1. package/activeRecord.js +32 -36
  2. package/cache/fallbackCache.js +15 -32
  3. package/cache/inMemoryCache.js +9 -10
  4. package/cache/index.js +1 -1
  5. package/cache/localStorageCache.js +24 -25
  6. package/channel/beaconSocketChannel.d.ts +1 -1
  7. package/channel/beaconSocketChannel.js +49 -79
  8. package/channel/channel.d.ts +1 -1
  9. package/channel/encodedChannel.js +8 -10
  10. package/channel/guaranteedChannel.d.ts +4 -4
  11. package/channel/guaranteedChannel.js +41 -43
  12. package/channel/index.js +1 -1
  13. package/channel/queuedChannel.js +35 -64
  14. package/channel/retryChannel.d.ts +1 -1
  15. package/channel/retryChannel.js +44 -77
  16. package/channel/sandboxChannel.js +17 -18
  17. package/channel/socketChannel.d.ts +4 -4
  18. package/channel/socketChannel.js +77 -79
  19. package/cid/cachedAssigner.js +15 -27
  20. package/cid/fixedAssigner.js +5 -6
  21. package/cid/index.js +1 -1
  22. package/cid/remoteAssigner.js +23 -36
  23. package/constants.d.ts +3 -2
  24. package/constants.js +6 -5
  25. package/container.d.ts +13 -6
  26. package/container.js +152 -168
  27. package/contentFetcher.d.ts +59 -0
  28. package/contentFetcher.js +129 -0
  29. package/context.d.ts +3 -3
  30. package/context.js +36 -38
  31. package/error.js +2 -2
  32. package/evaluator.d.ts +33 -24
  33. package/evaluator.js +126 -117
  34. package/eventManager.d.ts +1 -1
  35. package/eventManager.js +14 -15
  36. package/facade/contentFetcherFacade.d.ts +27 -0
  37. package/facade/contentFetcherFacade.js +40 -0
  38. package/facade/evaluatorFacade.d.ts +13 -3
  39. package/facade/evaluatorFacade.js +57 -72
  40. package/facade/sdkFacade.d.ts +10 -3
  41. package/facade/sdkFacade.js +129 -141
  42. package/facade/sessionFacade.js +6 -7
  43. package/facade/sessionPatch.js +9 -13
  44. package/facade/trackerFacade.js +32 -38
  45. package/facade/userFacade.js +10 -11
  46. package/facade/userPatch.js +9 -13
  47. package/index.js +2 -2
  48. package/logging/consoleLogger.js +18 -35
  49. package/logging/index.js +1 -1
  50. package/logging/namespacedLogger.js +14 -15
  51. package/logging/nullLogger.js +10 -13
  52. package/namespacedStorage.js +30 -47
  53. package/package.json +13 -16
  54. package/patch.d.ts +1 -1
  55. package/queue/capacityRestrictedQueue.js +17 -18
  56. package/queue/inMemoryQueue.js +22 -28
  57. package/queue/index.js +1 -1
  58. package/queue/monitoredQueue.d.ts +2 -2
  59. package/queue/monitoredQueue.js +39 -40
  60. package/queue/persistentQueue.js +33 -38
  61. package/retry/arbitraryPolicy.js +8 -10
  62. package/retry/backoffPolicy.d.ts +1 -1
  63. package/retry/backoffPolicy.js +11 -13
  64. package/retry/index.js +1 -1
  65. package/retry/maxAttemptsPolicy.js +7 -8
  66. package/retry/neverPolicy.js +6 -9
  67. package/schema/attributeSchema.js +1 -1
  68. package/schema/contentFetcherSchemas.d.ts +2 -0
  69. package/schema/contentFetcherSchemas.js +22 -0
  70. package/schema/contentSchemas.js +1 -1
  71. package/schema/contextSchemas.js +1 -1
  72. package/schema/ecommerceSchemas.js +1 -1
  73. package/schema/evaluatorSchemas.d.ts +2 -0
  74. package/schema/{evaluationSchemas.js → evaluatorSchemas.js} +3 -3
  75. package/schema/eventSchemas.js +8 -9
  76. package/schema/index.d.ts +2 -1
  77. package/schema/index.js +3 -2
  78. package/schema/loggerSchema.js +1 -1
  79. package/schema/operationSchemas.js +8 -8
  80. package/schema/sdkFacadeSchemas.js +9 -6
  81. package/schema/sdkSchemas.js +8 -5
  82. package/schema/tokenSchema.js +5 -4
  83. package/schema/userSchema.js +2 -2
  84. package/sdk.d.ts +9 -3
  85. package/sdk.js +81 -127
  86. package/sdkEvents.d.ts +3 -3
  87. package/sourceLocation.d.ts +3 -3
  88. package/sourceLocation.js +13 -14
  89. package/tab.d.ts +5 -5
  90. package/tab.js +50 -80
  91. package/token/cachedTokenStore.js +9 -10
  92. package/token/inMemoryTokenStore.js +7 -8
  93. package/token/index.js +1 -1
  94. package/token/replicatedTokenStore.js +7 -8
  95. package/token/token.d.ts +9 -5
  96. package/token/token.js +63 -57
  97. package/tracker.d.ts +4 -4
  98. package/tracker.js +145 -122
  99. package/trackingEvents.d.ts +36 -36
  100. package/trackingEvents.js +12 -6
  101. package/transformer.js +1 -1
  102. package/utilityTypes.d.ts +2 -2
  103. package/uuid.js +9 -7
  104. package/validation/arrayType.d.ts +2 -2
  105. package/validation/arrayType.js +29 -27
  106. package/validation/booleanType.js +11 -15
  107. package/validation/functionType.js +11 -15
  108. package/validation/index.js +1 -1
  109. package/validation/jsonType.d.ts +2 -2
  110. package/validation/jsonType.js +61 -80
  111. package/validation/mixedSchema.js +4 -7
  112. package/validation/nullType.js +11 -15
  113. package/validation/numberType.d.ts +1 -1
  114. package/validation/numberType.js +23 -22
  115. package/validation/objectType.d.ts +1 -1
  116. package/validation/objectType.js +61 -73
  117. package/validation/schema.js +6 -10
  118. package/validation/stringType.d.ts +1 -1
  119. package/validation/stringType.js +36 -47
  120. package/validation/unionType.js +27 -77
  121. package/validation/violation.js +1 -2
  122. package/schema/evaluationSchemas.d.ts +0 -2
package/container.js CHANGED
@@ -1,82 +1,102 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Container = void 0;
4
- var tslib_1 = require("tslib");
5
- var logging_1 = require("./logging");
6
- var context_1 = require("./context");
7
- var namespacedStorage_1 = require("./namespacedStorage");
8
- var retry_1 = require("./retry");
9
- var queue_1 = require("./queue");
10
- var tracker_1 = require("./tracker");
11
- var evaluator_1 = require("./evaluator");
12
- var transformer_1 = require("./transformer");
13
- var cid_1 = require("./cid");
14
- var eventManager_1 = require("./eventManager");
15
- var cache_1 = require("./cache");
16
- var guaranteedChannel_1 = require("./channel/guaranteedChannel");
17
- var channel_1 = require("./channel");
18
- var Container = /** @class */ (function () {
19
- function Container(configuration) {
4
+ const logging_1 = require("./logging");
5
+ const context_1 = require("./context");
6
+ const namespacedStorage_1 = require("./namespacedStorage");
7
+ const retry_1 = require("./retry");
8
+ const queue_1 = require("./queue");
9
+ const token_1 = require("./token");
10
+ const tracker_1 = require("./tracker");
11
+ const evaluator_1 = require("./evaluator");
12
+ const transformer_1 = require("./transformer");
13
+ const cid_1 = require("./cid");
14
+ const eventManager_1 = require("./eventManager");
15
+ const cache_1 = require("./cache");
16
+ const guaranteedChannel_1 = require("./channel/guaranteedChannel");
17
+ const channel_1 = require("./channel");
18
+ const contentFetcher_1 = require("./contentFetcher");
19
+ class Container {
20
+ constructor(configuration) {
20
21
  this.eventManager = new eventManager_1.SynchronousEventManager();
21
22
  this.configuration = configuration;
22
23
  }
23
- Container.prototype.getConfiguration = function () {
24
+ getConfiguration() {
24
25
  return this.configuration;
25
- };
26
- Container.prototype.getEvaluator = function () {
26
+ }
27
+ getEvaluator() {
27
28
  if (this.evaluator === undefined) {
28
29
  this.evaluator = this.createEvaluator();
29
30
  }
30
31
  return this.evaluator;
31
- };
32
- Container.prototype.createEvaluator = function () {
32
+ }
33
+ createEvaluator() {
33
34
  return new evaluator_1.Evaluator({
34
35
  appId: this.configuration.appId,
35
36
  endpointUrl: this.configuration.evaluationEndpointUrl,
36
- tokenProvider: this.getTokenProvider(),
37
- cidAssigner: this.getCidAssigner(),
38
37
  });
39
- };
40
- Container.prototype.getTracker = function () {
38
+ }
39
+ getContentFetcher() {
40
+ if (this.contentFetcher === undefined) {
41
+ this.contentFetcher = this.createContentFetcher();
42
+ }
43
+ return this.contentFetcher;
44
+ }
45
+ createContentFetcher() {
46
+ return new contentFetcher_1.ContentFetcher({
47
+ appId: this.configuration.appId,
48
+ endpointUrl: this.configuration.contentEndpointUrl,
49
+ });
50
+ }
51
+ getPreviewTokenStore() {
52
+ if (this.previewTokenStore === undefined) {
53
+ this.previewTokenStore = new token_1.CachedTokenStore(new cache_1.LocalStorageCache(this.getGlobalBrowserStorage('preview'), 'token'));
54
+ }
55
+ return this.previewTokenStore;
56
+ }
57
+ getTracker() {
41
58
  if (this.tracker === undefined) {
42
59
  this.tracker = this.createTracker();
43
60
  }
44
61
  return this.tracker;
45
- };
46
- Container.prototype.createTracker = function () {
47
- var context = this.getContext();
48
- var tracker = new tracker_1.Tracker({
62
+ }
63
+ createTracker() {
64
+ const context = this.getContext();
65
+ const tracker = new tracker_1.Tracker({
49
66
  tab: context.getTab(),
50
- tokenProvider: this.getTokenProvider(),
67
+ tokenProvider: this.getUserTokenStore(),
51
68
  inactivityRetryPolicy: new retry_1.ArbitraryPolicy([30000, 30000, 120000, 120000, 300000, 300000, 900000]),
52
69
  logger: this.getLogger('Tracker'),
53
70
  channel: this.getBeaconChannel(),
54
- eventMetadata: this.configuration.eventMetadata || {},
71
+ eventMetadata: this.configuration.eventMetadata,
55
72
  });
56
- var queue = this.getBeaconQueue();
73
+ const queue = this.getBeaconQueue();
57
74
  queue.addCallback('halfEmpty', tracker.unsuspend);
58
75
  queue.addCallback('full', tracker.suspend);
59
76
  return tracker;
60
- };
61
- Container.prototype.getTokenProvider = function () {
62
- if (this.tokenProvider === undefined) {
63
- var context = this.getContext();
64
- this.tokenProvider = { getToken: context.getToken.bind(context) };
65
- }
66
- return this.tokenProvider;
67
- };
68
- Container.prototype.getContext = function () {
77
+ }
78
+ getUserTokenStore() {
79
+ if (this.userTokenProvider === undefined) {
80
+ const context = this.getContext();
81
+ this.userTokenProvider = {
82
+ getToken: context.getToken.bind(context),
83
+ setToken: context.setToken.bind(context),
84
+ };
85
+ }
86
+ return this.userTokenProvider;
87
+ }
88
+ getContext() {
69
89
  if (this.context === undefined) {
70
90
  this.context = this.createContext();
71
91
  }
72
92
  return this.context;
73
- };
74
- Container.prototype.createContext = function () {
75
- var tokenKey = this.resolveStorageNamespace('token');
76
- var tabKey = this.resolveStorageNamespace('tab');
77
- var browserStorage = this.getLocalStorage();
78
- var browserCache = new cache_1.LocalStorageCache(browserStorage, tokenKey);
79
- var tabStorage = this.getSessionStorage();
93
+ }
94
+ createContext() {
95
+ const tokenKey = this.resolveStorageNamespace('token');
96
+ const tabKey = this.resolveStorageNamespace('tab');
97
+ const browserStorage = this.getLocalStorage();
98
+ const browserCache = new cache_1.LocalStorageCache(browserStorage, tokenKey);
99
+ const tabStorage = this.getSessionStorage();
80
100
  this.removeTokenSyncListener = cache_1.LocalStorageCache.autoSync(browserCache);
81
101
  return context_1.Context.load({
82
102
  tokenScope: this.configuration.tokenScope,
@@ -88,27 +108,27 @@ var Container = /** @class */ (function () {
88
108
  browserToken: browserCache,
89
109
  },
90
110
  });
91
- };
92
- Container.prototype.getBeaconChannel = function () {
111
+ }
112
+ getBeaconChannel() {
93
113
  if (this.beaconChannel === undefined) {
94
114
  this.beaconChannel = this.createBeaconChannel();
95
115
  }
96
116
  return this.beaconChannel;
97
- };
98
- Container.prototype.createBeaconChannel = function () {
117
+ }
118
+ createBeaconChannel() {
99
119
  if (this.configuration.test) {
100
120
  return new channel_1.SandboxChannel();
101
121
  }
102
- var channelLogger = this.getLogger('BeaconChannel');
103
- var _a = this.configuration, appId = _a.appId, trackerEndpointUrl = _a.trackerEndpointUrl;
104
- var queuedChannel = new channel_1.QueuedChannel(new channel_1.RetryChannel({
122
+ const channelLogger = this.getLogger('BeaconChannel');
123
+ const { appId, trackerEndpointUrl } = this.configuration;
124
+ const queuedChannel = new channel_1.QueuedChannel(new channel_1.RetryChannel({
105
125
  channel: new channel_1.GuaranteedChannel({
106
126
  channel: new channel_1.BeaconSocketChannel({
107
- trackerEndpointUrl: "".concat(trackerEndpointUrl, "/").concat(appId),
127
+ trackerEndpointUrl: `${trackerEndpointUrl}/${appId}`,
108
128
  tokenParameter: 'token',
109
129
  loggerFactory: this.getLogger.bind(this),
110
130
  logger: channelLogger,
111
- channelFactory: function (url, logger) { return new channel_1.SocketChannel({ url: url, logger: logger }); },
131
+ channelFactory: (url, logger) => (new channel_1.SocketChannel({ url: url, logger: logger })),
112
132
  cidAssigner: this.getCidAssigner(),
113
133
  cidParameter: 'clientId',
114
134
  }),
@@ -124,44 +144,40 @@ var Container = /** @class */ (function () {
124
144
  }),
125
145
  logger: channelLogger,
126
146
  }), this.getBeaconQueue(), channelLogger);
127
- queuedChannel.flush().catch(function () {
147
+ queuedChannel.flush().catch(() => {
128
148
  // Suppress errors as they are already reported by the channel
129
149
  });
130
150
  return new channel_1.EncodedChannel(queuedChannel, transformer_1.encodeJson);
131
- };
132
- Container.prototype.getCidAssigner = function () {
151
+ }
152
+ getCidAssigner() {
133
153
  if (this.cidAssigner === undefined) {
134
154
  this.cidAssigner = this.createCidAssigner();
135
155
  }
136
156
  return this.cidAssigner;
137
- };
138
- Container.prototype.createCidAssigner = function () {
139
- if (this.configuration.cid !== undefined) {
140
- return new cid_1.FixedAssigner(this.configuration.cid);
157
+ }
158
+ createCidAssigner() {
159
+ if (this.configuration.clientId !== undefined) {
160
+ return new cid_1.FixedAssigner(this.configuration.clientId);
141
161
  }
142
162
  if (this.configuration.test) {
143
163
  return new cid_1.FixedAssigner('00000000-0000-0000-0000-000000000000');
144
164
  }
145
- var logger = this.getLogger('CidAssigner');
146
- return new cid_1.CachedAssigner(new cid_1.RemoteAssigner(this.configuration.bootstrapEndpointUrl, logger), new cache_1.LocalStorageCache(this.getLocalStorage(), 'croct.cid'), logger);
147
- };
148
- Container.prototype.getBeaconQueue = function () {
165
+ const logger = this.getLogger('CidAssigner');
166
+ return new cid_1.CachedAssigner(new cid_1.RemoteAssigner(this.configuration.cidAssignerEndpointUrl, logger), new cache_1.LocalStorageCache(this.getLocalStorage(), 'croct.cid'), logger);
167
+ }
168
+ getBeaconQueue() {
149
169
  if (this.beaconQueue === undefined) {
150
170
  this.beaconQueue = this.createBeaconQueue();
151
171
  }
152
172
  return this.beaconQueue;
153
- };
154
- Container.prototype.createBeaconQueue = function () {
155
- var context = this.getContext();
156
- var tab = context.getTab();
173
+ }
174
+ createBeaconQueue() {
175
+ const context = this.getContext();
176
+ const tab = context.getTab();
157
177
  return new queue_1.MonitoredQueue(new queue_1.CapacityRestrictedQueue(new queue_1.PersistentQueue(this.getGlobalTabStorage('queue'), tab.id), this.configuration.beaconQueueSize), this.getLogger('BeaconQueue'));
158
- };
159
- Container.prototype.getLogger = function () {
160
- var namespace = [];
161
- for (var _i = 0; _i < arguments.length; _i++) {
162
- namespace[_i] = arguments[_i];
163
- }
164
- var prefix = "Croct".concat(namespace.length === 0 ? '' : ":".concat(namespace.join(':')));
178
+ }
179
+ getLogger(...namespace) {
180
+ const prefix = `Croct${namespace.length === 0 ? '' : `:${namespace.join(':')}`}`;
165
181
  if (this.configuration.logger !== undefined) {
166
182
  return new logging_1.NamespacedLogger(this.configuration.logger, prefix);
167
183
  }
@@ -169,96 +185,64 @@ var Container = /** @class */ (function () {
169
185
  return new logging_1.ConsoleLogger(prefix);
170
186
  }
171
187
  return new logging_1.NullLogger();
172
- };
173
- Container.prototype.getTabStorage = function (namespace) {
174
- var subnamespace = [];
175
- for (var _i = 1; _i < arguments.length; _i++) {
176
- subnamespace[_i - 1] = arguments[_i];
177
- }
178
- return this.getGlobalTabStorage.apply(this, tslib_1.__spreadArray(['external', namespace], tslib_1.__read(subnamespace), false));
179
- };
180
- Container.prototype.getBrowserStorage = function (namespace) {
181
- var subnamespace = [];
182
- for (var _i = 1; _i < arguments.length; _i++) {
183
- subnamespace[_i - 1] = arguments[_i];
184
- }
185
- return this.getGlobalBrowserStorage.apply(this, tslib_1.__spreadArray(['external', namespace], tslib_1.__read(subnamespace), false));
186
- };
187
- Container.prototype.getGlobalTabStorage = function (namespace) {
188
- var subnamespace = [];
189
- for (var _i = 1; _i < arguments.length; _i++) {
190
- subnamespace[_i - 1] = arguments[_i];
191
- }
192
- return new namespacedStorage_1.NamespacedStorage(this.getSessionStorage(), this.resolveStorageNamespace.apply(this, tslib_1.__spreadArray([namespace], tslib_1.__read(subnamespace), false)));
193
- };
194
- Container.prototype.getGlobalBrowserStorage = function (namespace) {
195
- var subnamespace = [];
196
- for (var _i = 1; _i < arguments.length; _i++) {
197
- subnamespace[_i - 1] = arguments[_i];
198
- }
199
- return new namespacedStorage_1.NamespacedStorage(this.getLocalStorage(), this.resolveStorageNamespace.apply(this, tslib_1.__spreadArray([namespace], tslib_1.__read(subnamespace), false)));
200
- };
201
- Container.prototype.resolveStorageNamespace = function (namespace) {
202
- var subnamespace = [];
203
- for (var _i = 1; _i < arguments.length; _i++) {
204
- subnamespace[_i - 1] = arguments[_i];
205
- }
206
- return "croct[".concat(this.configuration.appId.toLowerCase(), "].").concat([namespace].concat(subnamespace).join('.'));
207
- };
208
- Container.prototype.getLocalStorage = function () {
188
+ }
189
+ getTabStorage(namespace, ...subnamespace) {
190
+ return this.getGlobalTabStorage('external', namespace, ...subnamespace);
191
+ }
192
+ getBrowserStorage(namespace, ...subnamespace) {
193
+ return this.getGlobalBrowserStorage('external', namespace, ...subnamespace);
194
+ }
195
+ getGlobalTabStorage(namespace, ...subnamespace) {
196
+ return new namespacedStorage_1.NamespacedStorage(this.getSessionStorage(), this.resolveStorageNamespace(namespace, ...subnamespace));
197
+ }
198
+ getGlobalBrowserStorage(namespace, ...subnamespace) {
199
+ return new namespacedStorage_1.NamespacedStorage(this.getLocalStorage(), this.resolveStorageNamespace(namespace, ...subnamespace));
200
+ }
201
+ resolveStorageNamespace(namespace, ...subnamespace) {
202
+ return `croct[${this.configuration
203
+ .appId
204
+ .toLowerCase()}].${[namespace].concat(subnamespace).join('.')}`;
205
+ }
206
+ getLocalStorage() {
209
207
  return localStorage;
210
- };
211
- Container.prototype.getSessionStorage = function () {
208
+ }
209
+ getSessionStorage() {
212
210
  return sessionStorage;
213
- };
214
- Container.prototype.getEventManager = function () {
211
+ }
212
+ getEventManager() {
215
213
  return this.eventManager;
216
- };
217
- Container.prototype.dispose = function () {
218
- return tslib_1.__awaiter(this, void 0, void 0, function () {
219
- var logger;
220
- return tslib_1.__generator(this, function (_a) {
221
- switch (_a.label) {
222
- case 0:
223
- logger = this.getLogger();
224
- if (!this.beaconChannel) return [3 /*break*/, 2];
225
- logger.debug('Closing beacon channel...');
226
- return [4 /*yield*/, this.beaconChannel.close()];
227
- case 1:
228
- _a.sent();
229
- _a.label = 2;
230
- case 2:
231
- if (this.removeTokenSyncListener) {
232
- logger.debug('Removing token sync listener...');
233
- this.removeTokenSyncListener();
234
- }
235
- if (!this.tracker) return [3 /*break*/, 4];
236
- if (this.beaconQueue) {
237
- logger.debug('Removing queue listeners...');
238
- this.beaconQueue.removeCallback('halfEmpty', this.tracker.unsuspend);
239
- this.beaconQueue.removeCallback('full', this.tracker.suspend);
240
- }
241
- logger.debug('Suspending tracker...');
242
- this.tracker.suspend();
243
- return [4 /*yield*/, this.tracker.flushed];
244
- case 3:
245
- _a.sent();
246
- _a.label = 4;
247
- case 4:
248
- delete this.context;
249
- delete this.tokenProvider;
250
- delete this.cidAssigner;
251
- delete this.tracker;
252
- delete this.evaluator;
253
- delete this.beaconChannel;
254
- delete this.beaconQueue;
255
- delete this.removeTokenSyncListener;
256
- logger.debug('Container resources released.');
257
- return [2 /*return*/];
258
- }
259
- });
260
- });
261
- };
262
- return Container;
263
- }());
214
+ }
215
+ async dispose() {
216
+ const logger = this.getLogger();
217
+ if (this.beaconChannel !== undefined) {
218
+ logger.debug('Closing beacon channel...');
219
+ await this.beaconChannel.close();
220
+ }
221
+ if (this.removeTokenSyncListener !== undefined) {
222
+ logger.debug('Removing token sync listener...');
223
+ this.removeTokenSyncListener();
224
+ }
225
+ if (this.tracker !== undefined) {
226
+ if (this.beaconQueue !== undefined) {
227
+ logger.debug('Removing queue listeners...');
228
+ this.beaconQueue.removeCallback('halfEmpty', this.tracker.unsuspend);
229
+ this.beaconQueue.removeCallback('full', this.tracker.suspend);
230
+ }
231
+ logger.debug('Suspending tracker...');
232
+ this.tracker.suspend();
233
+ await this.tracker.flushed;
234
+ }
235
+ delete this.context;
236
+ delete this.userTokenProvider;
237
+ delete this.previewTokenStore;
238
+ delete this.cidAssigner;
239
+ delete this.tracker;
240
+ delete this.evaluator;
241
+ delete this.contentFetcher;
242
+ delete this.beaconChannel;
243
+ delete this.beaconQueue;
244
+ delete this.removeTokenSyncListener;
245
+ logger.debug('Container resources released.');
246
+ }
247
+ }
264
248
  exports.Container = Container;
@@ -0,0 +1,59 @@
1
+ import { JsonObject } from '@croct/json';
2
+ import { EvaluationContext } from './evaluator';
3
+ import { Token } from './token';
4
+ export type ErrorResponse = {
5
+ type: string;
6
+ title: string;
7
+ status: number;
8
+ detail?: string;
9
+ };
10
+ export declare enum ContentErrorType {
11
+ TIMEOUT = "https://croct.help/api/content#timeout",
12
+ UNEXPECTED_ERROR = "https://croct.help/api/content#unexpected-error"
13
+ }
14
+ export declare class ContentError<T extends ErrorResponse = ErrorResponse> extends Error {
15
+ readonly response: T;
16
+ constructor(response: T);
17
+ }
18
+ type BasicOptions = {
19
+ version?: `${number}` | number;
20
+ preferredLocale?: string;
21
+ timeout?: number;
22
+ extra?: ExtraFetchOptions;
23
+ };
24
+ export type StaticContentOptions = BasicOptions & {
25
+ static: true;
26
+ };
27
+ export type DynamicContentOptions = BasicOptions & {
28
+ static?: false;
29
+ clientId?: string;
30
+ clientIp?: string;
31
+ userAgent?: string;
32
+ userToken?: Token | string;
33
+ previewToken?: Token | string;
34
+ context?: EvaluationContext;
35
+ };
36
+ type AllowedFetchOptions = Exclude<keyof RequestInit, 'method' | 'body' | 'headers' | 'signal'>;
37
+ type ExtraFetchOptions<T extends keyof RequestInit = AllowedFetchOptions> = Pick<RequestInit, T> & {
38
+ [key in Exclude<keyof RequestInit, T>]?: never;
39
+ } & Record<string, any>;
40
+ export type FetchOptions = StaticContentOptions | DynamicContentOptions;
41
+ export type FetchResponse<P extends JsonObject = JsonObject> = {
42
+ content: P;
43
+ };
44
+ export type Configuration = {
45
+ appId?: string;
46
+ apiKey?: string;
47
+ endpointUrl?: string;
48
+ };
49
+ export declare class ContentFetcher {
50
+ private readonly configuration;
51
+ private readonly dynamicEndpoint;
52
+ private readonly staticEndpoint;
53
+ constructor(configuration: Configuration);
54
+ fetch<P extends JsonObject>(slotId: string, options?: FetchOptions): Promise<FetchResponse<P>>;
55
+ private load;
56
+ private static isDynamicContent;
57
+ toJSON(): never;
58
+ }
59
+ export {};
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContentFetcher = exports.ContentError = exports.ContentErrorType = void 0;
4
+ const constants_1 = require("./constants");
5
+ const error_1 = require("./error");
6
+ var ContentErrorType;
7
+ (function (ContentErrorType) {
8
+ ContentErrorType["TIMEOUT"] = "https://croct.help/api/content#timeout";
9
+ ContentErrorType["UNEXPECTED_ERROR"] = "https://croct.help/api/content#unexpected-error";
10
+ })(ContentErrorType = exports.ContentErrorType || (exports.ContentErrorType = {}));
11
+ class ContentError extends Error {
12
+ constructor(response) {
13
+ super(response.title);
14
+ this.response = response;
15
+ Object.setPrototypeOf(this, ContentError.prototype);
16
+ }
17
+ }
18
+ exports.ContentError = ContentError;
19
+ class ContentFetcher {
20
+ constructor(configuration) {
21
+ if ((configuration.appId === undefined) === (configuration.apiKey === undefined)) {
22
+ throw new Error('Either the application ID or the API key must be provided.');
23
+ }
24
+ this.configuration = configuration;
25
+ const { apiKey, endpointUrl } = this.configuration;
26
+ // eslint-disable-next-line prefer-template -- Better readability
27
+ const baseEndpoint = (endpointUrl !== null && endpointUrl !== void 0 ? endpointUrl : constants_1.CONTENT_ENDPOINT_URL).replace(/\/+$/, '')
28
+ + (apiKey === undefined ? '/client' : '/external')
29
+ + '/web';
30
+ this.dynamicEndpoint = `${baseEndpoint}/content`;
31
+ this.staticEndpoint = `${baseEndpoint}/static-content`;
32
+ }
33
+ fetch(slotId, options = {}) {
34
+ if (options.static === true && this.configuration.apiKey === undefined) {
35
+ throw new Error('The API key must be provided to fetch static content.');
36
+ }
37
+ return new Promise((resolve, reject) => {
38
+ const abortController = new AbortController();
39
+ if (options.timeout !== undefined) {
40
+ setTimeout(() => {
41
+ const response = {
42
+ title: 'Maximum timeout reached before content could be loaded.',
43
+ type: ContentErrorType.TIMEOUT,
44
+ detail: `The content took more than ${options.timeout}ms to load.`,
45
+ status: 408, // Request Timeout
46
+ };
47
+ abortController.abort();
48
+ reject(new ContentError(response));
49
+ }, options.timeout);
50
+ }
51
+ this.load(slotId, abortController.signal, options)
52
+ .then(response => response.json()
53
+ .then(body => {
54
+ if (response.ok) {
55
+ resolve(body);
56
+ }
57
+ else {
58
+ reject(new ContentError(body));
59
+ }
60
+ }))
61
+ .catch(error => {
62
+ if (!abortController.signal.aborted) {
63
+ reject(new ContentError({
64
+ title: (0, error_1.formatMessage)(error),
65
+ type: ContentErrorType.UNEXPECTED_ERROR,
66
+ detail: 'Please try again or contact Croct support if the error persists.',
67
+ status: 500, // Internal Server Error
68
+ }));
69
+ }
70
+ });
71
+ });
72
+ }
73
+ load(slotId, signal, options) {
74
+ const payload = {
75
+ slotId: slotId,
76
+ };
77
+ const { apiKey, appId } = this.configuration;
78
+ const headers = new Headers();
79
+ if (appId !== undefined) {
80
+ headers.set('X-App-Id', appId);
81
+ }
82
+ if (apiKey !== undefined) {
83
+ headers.set('X-Api-Key', apiKey);
84
+ }
85
+ const dynamic = ContentFetcher.isDynamicContent(options);
86
+ if (dynamic) {
87
+ if (options.clientId !== undefined) {
88
+ headers.set('X-Client-Id', options.clientId);
89
+ }
90
+ if (options.clientIp !== undefined) {
91
+ headers.set('X-Client-Ip', options.clientIp);
92
+ }
93
+ if (options.userToken !== undefined) {
94
+ headers.set('X-Token', options.userToken.toString());
95
+ }
96
+ if (options.userAgent !== undefined) {
97
+ headers.set('User-Agent', options.userAgent);
98
+ }
99
+ if (options.version !== undefined) {
100
+ payload.version = `${options.version}`;
101
+ }
102
+ if (options.preferredLocale !== undefined) {
103
+ payload.preferredLocale = options.preferredLocale;
104
+ }
105
+ if (options.context !== undefined) {
106
+ payload.context = options.context;
107
+ }
108
+ if (options.previewToken !== undefined) {
109
+ payload.previewToken = `${options.previewToken}`;
110
+ }
111
+ }
112
+ return fetch(dynamic ? this.dynamicEndpoint : this.staticEndpoint, {
113
+ credentials: 'omit',
114
+ ...options.extra,
115
+ method: 'POST',
116
+ headers: headers,
117
+ signal: signal,
118
+ body: JSON.stringify(payload),
119
+ });
120
+ }
121
+ static isDynamicContent(options) {
122
+ return options.static !== true;
123
+ }
124
+ toJSON() {
125
+ // Prevent sensitive configuration from being serialized
126
+ throw new Error('Unserializable value.');
127
+ }
128
+ }
129
+ exports.ContentFetcher = ContentFetcher;
package/context.d.ts CHANGED
@@ -3,8 +3,8 @@ import { Tab, UrlSanitizer } from './tab';
3
3
  import { EventDispatcher } from './eventManager';
4
4
  import { SdkEventMap } from './sdkEvents';
5
5
  import { LocalStorageCache } from './cache';
6
- export declare type TokenScope = 'isolated' | 'global' | 'contextual';
7
- export declare type Configuration = {
6
+ export type TokenScope = 'isolated' | 'global' | 'contextual';
7
+ export type Configuration = {
8
8
  tokenScope: TokenScope;
9
9
  urlSanitizer?: UrlSanitizer;
10
10
  eventDispatcher: ContextEventDispatcher;
@@ -14,7 +14,7 @@ export declare type Configuration = {
14
14
  browserToken: LocalStorageCache;
15
15
  };
16
16
  };
17
- declare type ContextEventDispatcher = EventDispatcher<Pick<SdkEventMap, 'tokenChanged'>>;
17
+ type ContextEventDispatcher = EventDispatcher<Pick<SdkEventMap, 'tokenChanged'>>;
18
18
  export declare class Context {
19
19
  private readonly tab;
20
20
  private readonly tokenStore;