@croct/sdk 0.19.0 → 0.20.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 CHANGED
@@ -16,7 +16,6 @@
16
16
  <p align="center">
17
17
  <a href="https://www.npmjs.com/package/@croct/sdk"><img alt="Version" src="https://img.shields.io/npm/v/@croct/sdk"/></a>
18
18
  <a href="https://github.com/croct-tech/sdk-js/actions?query=workflow%3AValidations"><img alt="Build" src="https://github.com/croct-tech/sdk-js/workflows/Validations/badge.svg"/></a>
19
- <a href="https://codeclimate.com/repos/5e7251b3172af05fe9000e27/test_coverage"><img alt="Coverage" src="https://api.codeclimate.com/v1/badges/c44df78a3ed891af11bb/test_coverage"/></a>
20
19
  </p>
21
20
 
22
21
  ## Installation
@@ -56,6 +56,11 @@ class HttpBeaconChannel {
56
56
  keepalive: true
57
57
  }).then(async (response) => {
58
58
  if (response.ok) {
59
+ if (response.status === 202) {
60
+ this.logger.warn(
61
+ "Event tracking is currently suspended for this application, check the workspace settings. For help, see https://croct.help/sdk/javascript/suspended-service"
62
+ );
63
+ }
59
64
  this.notify(receiptId);
60
65
  return;
61
66
  }
@@ -34,6 +34,11 @@ class HttpBeaconChannel {
34
34
  keepalive: true
35
35
  }).then(async (response) => {
36
36
  if (response.ok) {
37
+ if (response.status === 202) {
38
+ this.logger.warn(
39
+ "Event tracking is currently suspended for this application, check the workspace settings. For help, see https://croct.help/sdk/javascript/suspended-service"
40
+ );
41
+ }
37
42
  this.notify(receiptId);
38
43
  return;
39
44
  }
package/constants.cjs CHANGED
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
  const BASE_ENDPOINT_URL = "https://api.croct.io";
27
27
  const MAX_QUERY_LENGTH = parseInt("<@maxQueryLength@>", 10);
28
- const VERSION = "0.19.0";
28
+ const VERSION = "0.20.0";
29
29
  const CLIENT_LIBRARY = `Croct SDK JS v${VERSION}`;
30
30
  // Annotate the CommonJS export names for ESM import in node:
31
31
  0 && (module.exports = {
package/constants.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  declare const BASE_ENDPOINT_URL = "https://api.croct.io";
2
2
  declare const MAX_QUERY_LENGTH: number;
3
- declare const VERSION = "0.19.0";
4
- declare const CLIENT_LIBRARY = "Croct SDK JS v0.19.0";
3
+ declare const VERSION = "0.20.0";
4
+ declare const CLIENT_LIBRARY = "Croct SDK JS v0.20.0";
5
5
 
6
6
  export { BASE_ENDPOINT_URL, CLIENT_LIBRARY, MAX_QUERY_LENGTH, VERSION };
package/constants.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  declare const BASE_ENDPOINT_URL = "https://api.croct.io";
2
2
  declare const MAX_QUERY_LENGTH: number;
3
- declare const VERSION = "0.19.0";
4
- declare const CLIENT_LIBRARY = "Croct SDK JS v0.19.0";
3
+ declare const VERSION = "0.20.0";
4
+ declare const CLIENT_LIBRARY = "Croct SDK JS v0.20.0";
5
5
 
6
6
  export { BASE_ENDPOINT_URL, CLIENT_LIBRARY, MAX_QUERY_LENGTH, VERSION };
package/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const BASE_ENDPOINT_URL = "https://api.croct.io";
2
2
  const MAX_QUERY_LENGTH = parseInt("<@maxQueryLength@>", 10);
3
- const VERSION = "0.19.0";
3
+ const VERSION = "0.20.0";
4
4
  const CLIENT_LIBRARY = `Croct SDK JS v${VERSION}`;
5
5
  export {
6
6
  BASE_ENDPOINT_URL,
package/container.cjs CHANGED
@@ -38,6 +38,7 @@ var import_contentFetcher = require('./contentFetcher.cjs');
38
38
  var import_cookieCache = require('./cache/cookieCache.cjs');
39
39
  var import_filteredLogger = require('./logging/filteredLogger.cjs');
40
40
  var import_httpBeaconChannel = require('./channel/httpBeaconChannel.cjs');
41
+ var import_deduplicatedLogger = require('./logging/deduplicatedLogger.cjs');
41
42
  const _Container = class _Container {
42
43
  constructor(configuration) {
43
44
  this.eventManager = new import_eventManager.SynchronousEventManager();
@@ -230,7 +231,7 @@ const _Container = class _Container {
230
231
  if (this.configuration.debug) {
231
232
  return new import_logging.ConsoleLogger(prefix);
232
233
  }
233
- return import_filteredLogger.FilteredLogger.include(new import_logging.ConsoleLogger(), ["error", "warn"]);
234
+ return new import_deduplicatedLogger.DeduplicatedLogger(import_filteredLogger.FilteredLogger.include(new import_logging.ConsoleLogger(prefix), ["error", "warn"]));
234
235
  }
235
236
  getTabStorage(namespace, ...subnamespace) {
236
237
  return this.getGlobalTabStorage("external", namespace, ...subnamespace);
package/container.d.cts CHANGED
@@ -20,6 +20,7 @@ import './trackingEvents.cjs';
20
20
  import './patch.cjs';
21
21
  import './utilityTypes.cjs';
22
22
  import './sourceLocation.cjs';
23
+ import '@croct/content-model/definition';
23
24
 
24
25
  type DependencyResolver<T> = (container: Container) => T;
25
26
  type Configuration = {
package/container.d.ts CHANGED
@@ -20,6 +20,7 @@ import './trackingEvents.js';
20
20
  import './patch.js';
21
21
  import './utilityTypes.js';
22
22
  import './sourceLocation.js';
23
+ import '@croct/content-model/definition';
23
24
 
24
25
  type DependencyResolver<T> = (container: Container) => T;
25
26
  type Configuration = {
package/container.js CHANGED
@@ -22,6 +22,7 @@ import { ContentFetcher } from "./contentFetcher.js";
22
22
  import { CookieCache } from "./cache/cookieCache.js";
23
23
  import { FilteredLogger } from "./logging/filteredLogger.js";
24
24
  import { HttpBeaconChannel } from "./channel/httpBeaconChannel.js";
25
+ import { DeduplicatedLogger } from "./logging/deduplicatedLogger.js";
25
26
  const _Container = class _Container {
26
27
  constructor(configuration) {
27
28
  this.eventManager = new SynchronousEventManager();
@@ -214,7 +215,7 @@ const _Container = class _Container {
214
215
  if (this.configuration.debug) {
215
216
  return new ConsoleLogger(prefix);
216
217
  }
217
- return FilteredLogger.include(new ConsoleLogger(), ["error", "warn"]);
218
+ return new DeduplicatedLogger(FilteredLogger.include(new ConsoleLogger(prefix), ["error", "warn"]));
218
219
  }
219
220
  getTabStorage(namespace, ...subnamespace) {
220
221
  return this.getGlobalTabStorage("external", namespace, ...subnamespace);
@@ -28,8 +28,9 @@ var import_logging = require('./logging/index.cjs');
28
28
  var import_apiKey = require('./apiKey.cjs');
29
29
  var import_help = require('./help.cjs');
30
30
  var ContentErrorType = /* @__PURE__ */ ((ContentErrorType2) => {
31
- ContentErrorType2["TIMEOUT"] = "https://croct.help/api/content#timeout";
32
- ContentErrorType2["UNEXPECTED_ERROR"] = "https://croct.help/api/content#unexpected-error";
31
+ ContentErrorType2["TIMEOUT"] = "https://croct.help/sdk/javascript/request-timeout";
32
+ ContentErrorType2["UNEXPECTED_ERROR"] = "https://croct.help/sdk/javascript/unexpected-error";
33
+ ContentErrorType2["SUSPENDED_SERVICE"] = "https://croct.help/sdk/javascript/suspended-service";
33
34
  return ContentErrorType2;
34
35
  })(ContentErrorType || {});
35
36
  class ContentError extends Error {
@@ -56,20 +57,20 @@ class ContentFetcher {
56
57
  defaultPreferredLocale: configuration.defaultPreferredLocale
57
58
  };
58
59
  }
59
- fetch(slotId, options = {}) {
60
- if (options.static === true && this.configuration.apiKey === void 0) {
60
+ fetch(slotId, options) {
61
+ if (options?.static === true && this.configuration.apiKey === void 0) {
61
62
  throw new Error("The API key must be provided to fetch static content.");
62
63
  }
63
64
  return new Promise((resolve, reject) => {
64
65
  const abortController = new AbortController();
65
- const timeout = options.timeout ?? this.configuration.defaultTimeout;
66
+ const timeout = options?.timeout ?? this.configuration.defaultTimeout;
66
67
  let timer;
67
68
  if (timeout !== void 0) {
68
69
  timer = setTimeout(
69
70
  () => {
70
71
  const response = {
71
72
  title: `Content could not be loaded in time for slot '${slotId}'.`,
72
- type: "https://croct.help/api/content#timeout" /* TIMEOUT */,
73
+ type: "https://croct.help/sdk/javascript/request-timeout" /* TIMEOUT */,
73
74
  detail: `The content took more than ${timeout}ms to load.`,
74
75
  status: 408
75
76
  // Request Timeout
@@ -81,10 +82,18 @@ class ContentFetcher {
81
82
  timeout
82
83
  );
83
84
  }
84
- this.load(slotId, abortController.signal, options).finally(() => clearTimeout(timer)).then((response) => {
85
+ this.load(slotId, abortController.signal, options ?? {}).finally(() => clearTimeout(timer)).then((response) => {
85
86
  const region = response.headers.get("X-Croct-Region");
86
87
  const timing = response.headers.get("X-Croct-Timing");
87
88
  this.logger.debug(`Content for slot '${slotId}' processed by region ${region} in ${timing}.`);
89
+ if (response.status === 202) {
90
+ return reject(new ContentError({
91
+ status: 202,
92
+ title: "Service is suspended.",
93
+ type: "https://croct.help/sdk/javascript/suspended-service" /* SUSPENDED_SERVICE */,
94
+ detail: import_help.Help.forStatusCode(202)
95
+ }));
96
+ }
88
97
  return response.json().then((body) => {
89
98
  if (response.ok) {
90
99
  return resolve(body);
@@ -102,7 +111,7 @@ class ContentFetcher {
102
111
  reject(
103
112
  new ContentError({
104
113
  title: (0, import_error.formatMessage)(error),
105
- type: "https://croct.help/api/content#unexpected-error" /* UNEXPECTED_ERROR */,
114
+ type: "https://croct.help/sdk/javascript/unexpected-error" /* UNEXPECTED_ERROR */,
106
115
  detail: "Please try again or contact Croct support if the error persists.",
107
116
  status: 500
108
117
  // Internal Server Error
@@ -127,6 +136,9 @@ class ContentFetcher {
127
136
  const payload = {
128
137
  slotId
129
138
  };
139
+ if (options.includeSchema === true) {
140
+ payload.includeSchema = true;
141
+ }
130
142
  if (options.version !== void 0) {
131
143
  payload.version = `${options.version}`;
132
144
  }
@@ -1,4 +1,5 @@
1
1
  import { JsonObject } from '@croct/json';
2
+ import { ContentDefinitionBundle } from '@croct/content-model/definition';
2
3
  import { EvaluationContext } from './evaluator.cjs';
3
4
  import { Token } from './token/token.cjs';
4
5
  import { Logger } from './logging/logger.cjs';
@@ -12,14 +13,18 @@ type ErrorResponse = {
12
13
  detail?: string;
13
14
  };
14
15
  declare enum ContentErrorType {
15
- TIMEOUT = "https://croct.help/api/content#timeout",
16
- UNEXPECTED_ERROR = "https://croct.help/api/content#unexpected-error"
16
+ TIMEOUT = "https://croct.help/sdk/javascript/request-timeout",
17
+ UNEXPECTED_ERROR = "https://croct.help/sdk/javascript/unexpected-error",
18
+ SUSPENDED_SERVICE = "https://croct.help/sdk/javascript/suspended-service"
17
19
  }
18
20
  declare class ContentError<T extends ErrorResponse = ErrorResponse> extends Error {
19
21
  readonly response: T;
20
22
  constructor(response: T);
21
23
  }
22
- type BasicOptions = {
24
+ type FetchResponseOptions = {
25
+ includeSchema?: boolean;
26
+ };
27
+ type BasicOptions = FetchResponseOptions & {
23
28
  version?: `${number}` | number;
24
29
  preferredLocale?: string;
25
30
  timeout?: number;
@@ -42,7 +47,25 @@ type ExtraFetchOptions<T extends keyof RequestInit = AllowedFetchOptions> = Pick
42
47
  [key in Exclude<keyof RequestInit, T>]?: never;
43
48
  } & Record<string, any>;
44
49
  type FetchOptions = StaticContentOptions | DynamicContentOptions;
45
- type FetchResponse<P extends JsonObject = JsonObject> = {
50
+ type With<T, K extends keyof T> = T & {
51
+ [P in K]-?: T[P];
52
+ };
53
+ type SlotMetadata = {
54
+ version: string;
55
+ schema?: ContentDefinitionBundle;
56
+ experience?: {
57
+ experienceId: string;
58
+ audienceId: string;
59
+ experiment?: {
60
+ experimentId: string;
61
+ variantId: string;
62
+ };
63
+ };
64
+ };
65
+ type FetchResponse<P = JsonObject, O = FetchResponseOptions> = {
66
+ metadata: With<SlotMetadata, O extends {
67
+ includeSchema: true;
68
+ } ? 'schema' : never>;
46
69
  content: P;
47
70
  };
48
71
  type Configuration = {
@@ -59,11 +82,11 @@ declare class ContentFetcher {
59
82
  private readonly staticEndpoint;
60
83
  private readonly logger;
61
84
  constructor(configuration: Configuration);
62
- fetch<P extends JsonObject>(slotId: string, options?: FetchOptions): Promise<FetchResponse<P>>;
85
+ fetch<P extends JsonObject, O extends FetchResponseOptions>(slotId: string, options?: O & FetchOptions): Promise<FetchResponse<P, O>>;
63
86
  private load;
64
87
  private logHelp;
65
88
  private static isDynamicContent;
66
89
  toJSON(): never;
67
90
  }
68
91
 
69
- export { type Configuration, ContentError, ContentErrorType, ContentFetcher, type DynamicContentOptions, type ErrorResponse, type FetchOptions, type FetchResponse, type StaticContentOptions };
92
+ export { type Configuration, ContentError, ContentErrorType, ContentFetcher, type DynamicContentOptions, type ErrorResponse, type FetchOptions, type FetchResponse, type FetchResponseOptions, type SlotMetadata, type StaticContentOptions };
@@ -1,4 +1,5 @@
1
1
  import { JsonObject } from '@croct/json';
2
+ import { ContentDefinitionBundle } from '@croct/content-model/definition';
2
3
  import { EvaluationContext } from './evaluator.js';
3
4
  import { Token } from './token/token.js';
4
5
  import { Logger } from './logging/logger.js';
@@ -12,14 +13,18 @@ type ErrorResponse = {
12
13
  detail?: string;
13
14
  };
14
15
  declare enum ContentErrorType {
15
- TIMEOUT = "https://croct.help/api/content#timeout",
16
- UNEXPECTED_ERROR = "https://croct.help/api/content#unexpected-error"
16
+ TIMEOUT = "https://croct.help/sdk/javascript/request-timeout",
17
+ UNEXPECTED_ERROR = "https://croct.help/sdk/javascript/unexpected-error",
18
+ SUSPENDED_SERVICE = "https://croct.help/sdk/javascript/suspended-service"
17
19
  }
18
20
  declare class ContentError<T extends ErrorResponse = ErrorResponse> extends Error {
19
21
  readonly response: T;
20
22
  constructor(response: T);
21
23
  }
22
- type BasicOptions = {
24
+ type FetchResponseOptions = {
25
+ includeSchema?: boolean;
26
+ };
27
+ type BasicOptions = FetchResponseOptions & {
23
28
  version?: `${number}` | number;
24
29
  preferredLocale?: string;
25
30
  timeout?: number;
@@ -42,7 +47,25 @@ type ExtraFetchOptions<T extends keyof RequestInit = AllowedFetchOptions> = Pick
42
47
  [key in Exclude<keyof RequestInit, T>]?: never;
43
48
  } & Record<string, any>;
44
49
  type FetchOptions = StaticContentOptions | DynamicContentOptions;
45
- type FetchResponse<P extends JsonObject = JsonObject> = {
50
+ type With<T, K extends keyof T> = T & {
51
+ [P in K]-?: T[P];
52
+ };
53
+ type SlotMetadata = {
54
+ version: string;
55
+ schema?: ContentDefinitionBundle;
56
+ experience?: {
57
+ experienceId: string;
58
+ audienceId: string;
59
+ experiment?: {
60
+ experimentId: string;
61
+ variantId: string;
62
+ };
63
+ };
64
+ };
65
+ type FetchResponse<P = JsonObject, O = FetchResponseOptions> = {
66
+ metadata: With<SlotMetadata, O extends {
67
+ includeSchema: true;
68
+ } ? 'schema' : never>;
46
69
  content: P;
47
70
  };
48
71
  type Configuration = {
@@ -59,11 +82,11 @@ declare class ContentFetcher {
59
82
  private readonly staticEndpoint;
60
83
  private readonly logger;
61
84
  constructor(configuration: Configuration);
62
- fetch<P extends JsonObject>(slotId: string, options?: FetchOptions): Promise<FetchResponse<P>>;
85
+ fetch<P extends JsonObject, O extends FetchResponseOptions>(slotId: string, options?: O & FetchOptions): Promise<FetchResponse<P, O>>;
63
86
  private load;
64
87
  private logHelp;
65
88
  private static isDynamicContent;
66
89
  toJSON(): never;
67
90
  }
68
91
 
69
- export { type Configuration, ContentError, ContentErrorType, ContentFetcher, type DynamicContentOptions, type ErrorResponse, type FetchOptions, type FetchResponse, type StaticContentOptions };
92
+ export { type Configuration, ContentError, ContentErrorType, ContentFetcher, type DynamicContentOptions, type ErrorResponse, type FetchOptions, type FetchResponse, type FetchResponseOptions, type SlotMetadata, type StaticContentOptions };
package/contentFetcher.js CHANGED
@@ -4,8 +4,9 @@ import { NullLogger } from "./logging/index.js";
4
4
  import { ApiKey } from "./apiKey.js";
5
5
  import { Help } from "./help.js";
6
6
  var ContentErrorType = /* @__PURE__ */ ((ContentErrorType2) => {
7
- ContentErrorType2["TIMEOUT"] = "https://croct.help/api/content#timeout";
8
- ContentErrorType2["UNEXPECTED_ERROR"] = "https://croct.help/api/content#unexpected-error";
7
+ ContentErrorType2["TIMEOUT"] = "https://croct.help/sdk/javascript/request-timeout";
8
+ ContentErrorType2["UNEXPECTED_ERROR"] = "https://croct.help/sdk/javascript/unexpected-error";
9
+ ContentErrorType2["SUSPENDED_SERVICE"] = "https://croct.help/sdk/javascript/suspended-service";
9
10
  return ContentErrorType2;
10
11
  })(ContentErrorType || {});
11
12
  class ContentError extends Error {
@@ -32,20 +33,20 @@ class ContentFetcher {
32
33
  defaultPreferredLocale: configuration.defaultPreferredLocale
33
34
  };
34
35
  }
35
- fetch(slotId, options = {}) {
36
- if (options.static === true && this.configuration.apiKey === void 0) {
36
+ fetch(slotId, options) {
37
+ if (options?.static === true && this.configuration.apiKey === void 0) {
37
38
  throw new Error("The API key must be provided to fetch static content.");
38
39
  }
39
40
  return new Promise((resolve, reject) => {
40
41
  const abortController = new AbortController();
41
- const timeout = options.timeout ?? this.configuration.defaultTimeout;
42
+ const timeout = options?.timeout ?? this.configuration.defaultTimeout;
42
43
  let timer;
43
44
  if (timeout !== void 0) {
44
45
  timer = setTimeout(
45
46
  () => {
46
47
  const response = {
47
48
  title: `Content could not be loaded in time for slot '${slotId}'.`,
48
- type: "https://croct.help/api/content#timeout" /* TIMEOUT */,
49
+ type: "https://croct.help/sdk/javascript/request-timeout" /* TIMEOUT */,
49
50
  detail: `The content took more than ${timeout}ms to load.`,
50
51
  status: 408
51
52
  // Request Timeout
@@ -57,10 +58,18 @@ class ContentFetcher {
57
58
  timeout
58
59
  );
59
60
  }
60
- this.load(slotId, abortController.signal, options).finally(() => clearTimeout(timer)).then((response) => {
61
+ this.load(slotId, abortController.signal, options ?? {}).finally(() => clearTimeout(timer)).then((response) => {
61
62
  const region = response.headers.get("X-Croct-Region");
62
63
  const timing = response.headers.get("X-Croct-Timing");
63
64
  this.logger.debug(`Content for slot '${slotId}' processed by region ${region} in ${timing}.`);
65
+ if (response.status === 202) {
66
+ return reject(new ContentError({
67
+ status: 202,
68
+ title: "Service is suspended.",
69
+ type: "https://croct.help/sdk/javascript/suspended-service" /* SUSPENDED_SERVICE */,
70
+ detail: Help.forStatusCode(202)
71
+ }));
72
+ }
64
73
  return response.json().then((body) => {
65
74
  if (response.ok) {
66
75
  return resolve(body);
@@ -78,7 +87,7 @@ class ContentFetcher {
78
87
  reject(
79
88
  new ContentError({
80
89
  title: formatMessage(error),
81
- type: "https://croct.help/api/content#unexpected-error" /* UNEXPECTED_ERROR */,
90
+ type: "https://croct.help/sdk/javascript/unexpected-error" /* UNEXPECTED_ERROR */,
82
91
  detail: "Please try again or contact Croct support if the error persists.",
83
92
  status: 500
84
93
  // Internal Server Error
@@ -103,6 +112,9 @@ class ContentFetcher {
103
112
  const payload = {
104
113
  slotId
105
114
  };
115
+ if (options.includeSchema === true) {
116
+ payload.includeSchema = true;
117
+ }
106
118
  if (options.version !== void 0) {
107
119
  payload.version = `${options.version}`;
108
120
  }
package/evaluator.cjs CHANGED
@@ -30,13 +30,14 @@ var import_logging = require('./logging/index.cjs');
30
30
  var import_apiKey = require('./apiKey.cjs');
31
31
  var import_help = require('./help.cjs');
32
32
  var EvaluationErrorType = /* @__PURE__ */ ((EvaluationErrorType2) => {
33
- EvaluationErrorType2["TIMEOUT"] = "https://croct.help/api/evaluation#timeout";
34
- EvaluationErrorType2["UNEXPECTED_ERROR"] = "https://croct.help/api/evaluation#unexpected-error";
35
- EvaluationErrorType2["INVALID_QUERY"] = "https://croct.help/api/evaluation#invalid-query";
36
- EvaluationErrorType2["TOO_COMPLEX_QUERY"] = "https://croct.help/api/evaluation#too-complex-query";
37
- EvaluationErrorType2["EVALUATION_FAILED"] = "https://croct.help/api/evaluation#evaluation-failed";
38
- EvaluationErrorType2["UNALLOWED_RESULT"] = "https://croct.help/api/evaluation#unallowed-result";
39
- EvaluationErrorType2["UNSERIALIZABLE_RESULT"] = "https://croct.help/api/evaluation#unserializable-result";
33
+ EvaluationErrorType2["TIMEOUT"] = "https://croct.help/sdk/javascript/request-timeout";
34
+ EvaluationErrorType2["UNEXPECTED_ERROR"] = "https://croct.help/sdk/javascript/unexpected-error";
35
+ EvaluationErrorType2["INVALID_QUERY"] = "https://croct.help/sdk/javascript/invalid-query";
36
+ EvaluationErrorType2["TOO_COMPLEX_QUERY"] = "https://croct.help/sdk/javascript/too-complex-query";
37
+ EvaluationErrorType2["EVALUATION_FAILED"] = "https://croct.help/sdk/javascript/evaluation-failed";
38
+ EvaluationErrorType2["UNALLOWED_RESULT"] = "https://croct.help/sdk/javascript/unallowed-result";
39
+ EvaluationErrorType2["SUSPENDED_SERVICE"] = "https://croct.help/sdk/javascript/suspended-service";
40
+ EvaluationErrorType2["UNSERIALIZABLE_RESULT"] = "https://croct.help/sdk/javascript/unserializable-result";
40
41
  return EvaluationErrorType2;
41
42
  })(EvaluationErrorType || {});
42
43
  class EvaluationError extends Error {
@@ -74,7 +75,7 @@ const _Evaluator = class _Evaluator {
74
75
  title: "The query is too complex.",
75
76
  status: 422,
76
77
  // Unprocessable Entity
77
- type: "https://croct.help/api/evaluation#too-complex-query" /* TOO_COMPLEX_QUERY */,
78
+ type: "https://croct.help/sdk/javascript/too-complex-query" /* TOO_COMPLEX_QUERY */,
78
79
  detail: `The query "${reference}" must be at most ${_Evaluator.MAX_QUERY_LENGTH} characters long, but it is ${length} characters long.`,
79
80
  errors: [{
80
81
  cause: "The query is longer than expected.",
@@ -98,7 +99,7 @@ const _Evaluator = class _Evaluator {
98
99
  () => {
99
100
  const response = {
100
101
  title: `Evaluation could not be completed in time for query "${reference}".`,
101
- type: "https://croct.help/api/evaluation#timeout" /* TIMEOUT */,
102
+ type: "https://croct.help/sdk/javascript/request-timeout" /* TIMEOUT */,
102
103
  detail: `The evaluation took more than ${timeout}ms to complete.`,
103
104
  status: 408
104
105
  // Request Timeout
@@ -117,6 +118,14 @@ const _Evaluator = class _Evaluator {
117
118
  this.logger.debug(
118
119
  `Evaluation of the query "${reference}" processed by region ${region} in ${timing}.`
119
120
  );
121
+ if (response.status === 202) {
122
+ return reject(new EvaluationError({
123
+ status: 202,
124
+ type: "https://croct.help/sdk/javascript/suspended-service" /* SUSPENDED_SERVICE */,
125
+ title: "Service is suspended.",
126
+ detail: import_help.Help.forStatusCode(202)
127
+ }));
128
+ }
120
129
  return response.json().then((body) => {
121
130
  if (response.ok) {
122
131
  return resolve(body);
@@ -124,9 +133,9 @@ const _Evaluator = class _Evaluator {
124
133
  this.logHelp(response.status);
125
134
  const problem = body;
126
135
  switch (problem.type) {
127
- case "https://croct.help/api/evaluation#invalid-query" /* INVALID_QUERY */:
128
- case "https://croct.help/api/evaluation#evaluation-failed" /* EVALUATION_FAILED */:
129
- case "https://croct.help/api/evaluation#too-complex-query" /* TOO_COMPLEX_QUERY */:
136
+ case "https://croct.help/sdk/javascript/invalid-query" /* INVALID_QUERY */:
137
+ case "https://croct.help/sdk/javascript/evaluation-failed" /* EVALUATION_FAILED */:
138
+ case "https://croct.help/sdk/javascript/too-complex-query" /* TOO_COMPLEX_QUERY */:
130
139
  reject(new QueryError(problem));
131
140
  break;
132
141
  default:
@@ -146,7 +155,7 @@ const _Evaluator = class _Evaluator {
146
155
  reject(
147
156
  new EvaluationError({
148
157
  title: (0, import_error.formatMessage)(error),
149
- type: "https://croct.help/api/evaluation#unexpected-error" /* UNEXPECTED_ERROR */,
158
+ type: "https://croct.help/sdk/javascript/unexpected-error" /* UNEXPECTED_ERROR */,
150
159
  detail: "Please try again or contact Croct support if the error persists.",
151
160
  status: 500
152
161
  // Internal Server Error
package/evaluator.d.cts CHANGED
@@ -36,13 +36,14 @@ type EvaluationOptions = {
36
36
  extra?: ExtraFetchOptions;
37
37
  };
38
38
  declare enum EvaluationErrorType {
39
- TIMEOUT = "https://croct.help/api/evaluation#timeout",
40
- UNEXPECTED_ERROR = "https://croct.help/api/evaluation#unexpected-error",
41
- INVALID_QUERY = "https://croct.help/api/evaluation#invalid-query",
42
- TOO_COMPLEX_QUERY = "https://croct.help/api/evaluation#too-complex-query",
43
- EVALUATION_FAILED = "https://croct.help/api/evaluation#evaluation-failed",
44
- UNALLOWED_RESULT = "https://croct.help/api/evaluation#unallowed-result",
45
- UNSERIALIZABLE_RESULT = "https://croct.help/api/evaluation#unserializable-result"
39
+ TIMEOUT = "https://croct.help/sdk/javascript/request-timeout",
40
+ UNEXPECTED_ERROR = "https://croct.help/sdk/javascript/unexpected-error",
41
+ INVALID_QUERY = "https://croct.help/sdk/javascript/invalid-query",
42
+ TOO_COMPLEX_QUERY = "https://croct.help/sdk/javascript/too-complex-query",
43
+ EVALUATION_FAILED = "https://croct.help/sdk/javascript/evaluation-failed",
44
+ UNALLOWED_RESULT = "https://croct.help/sdk/javascript/unallowed-result",
45
+ SUSPENDED_SERVICE = "https://croct.help/sdk/javascript/suspended-service",
46
+ UNSERIALIZABLE_RESULT = "https://croct.help/sdk/javascript/unserializable-result"
46
47
  }
47
48
  type ErrorResponse = {
48
49
  type: EvaluationErrorType;
package/evaluator.d.ts CHANGED
@@ -36,13 +36,14 @@ type EvaluationOptions = {
36
36
  extra?: ExtraFetchOptions;
37
37
  };
38
38
  declare enum EvaluationErrorType {
39
- TIMEOUT = "https://croct.help/api/evaluation#timeout",
40
- UNEXPECTED_ERROR = "https://croct.help/api/evaluation#unexpected-error",
41
- INVALID_QUERY = "https://croct.help/api/evaluation#invalid-query",
42
- TOO_COMPLEX_QUERY = "https://croct.help/api/evaluation#too-complex-query",
43
- EVALUATION_FAILED = "https://croct.help/api/evaluation#evaluation-failed",
44
- UNALLOWED_RESULT = "https://croct.help/api/evaluation#unallowed-result",
45
- UNSERIALIZABLE_RESULT = "https://croct.help/api/evaluation#unserializable-result"
39
+ TIMEOUT = "https://croct.help/sdk/javascript/request-timeout",
40
+ UNEXPECTED_ERROR = "https://croct.help/sdk/javascript/unexpected-error",
41
+ INVALID_QUERY = "https://croct.help/sdk/javascript/invalid-query",
42
+ TOO_COMPLEX_QUERY = "https://croct.help/sdk/javascript/too-complex-query",
43
+ EVALUATION_FAILED = "https://croct.help/sdk/javascript/evaluation-failed",
44
+ UNALLOWED_RESULT = "https://croct.help/sdk/javascript/unallowed-result",
45
+ SUSPENDED_SERVICE = "https://croct.help/sdk/javascript/suspended-service",
46
+ UNSERIALIZABLE_RESULT = "https://croct.help/sdk/javascript/unserializable-result"
46
47
  }
47
48
  type ErrorResponse = {
48
49
  type: EvaluationErrorType;
package/evaluator.js CHANGED
@@ -5,13 +5,14 @@ import { NullLogger } from "./logging/index.js";
5
5
  import { ApiKey } from "./apiKey.js";
6
6
  import { Help } from "./help.js";
7
7
  var EvaluationErrorType = /* @__PURE__ */ ((EvaluationErrorType2) => {
8
- EvaluationErrorType2["TIMEOUT"] = "https://croct.help/api/evaluation#timeout";
9
- EvaluationErrorType2["UNEXPECTED_ERROR"] = "https://croct.help/api/evaluation#unexpected-error";
10
- EvaluationErrorType2["INVALID_QUERY"] = "https://croct.help/api/evaluation#invalid-query";
11
- EvaluationErrorType2["TOO_COMPLEX_QUERY"] = "https://croct.help/api/evaluation#too-complex-query";
12
- EvaluationErrorType2["EVALUATION_FAILED"] = "https://croct.help/api/evaluation#evaluation-failed";
13
- EvaluationErrorType2["UNALLOWED_RESULT"] = "https://croct.help/api/evaluation#unallowed-result";
14
- EvaluationErrorType2["UNSERIALIZABLE_RESULT"] = "https://croct.help/api/evaluation#unserializable-result";
8
+ EvaluationErrorType2["TIMEOUT"] = "https://croct.help/sdk/javascript/request-timeout";
9
+ EvaluationErrorType2["UNEXPECTED_ERROR"] = "https://croct.help/sdk/javascript/unexpected-error";
10
+ EvaluationErrorType2["INVALID_QUERY"] = "https://croct.help/sdk/javascript/invalid-query";
11
+ EvaluationErrorType2["TOO_COMPLEX_QUERY"] = "https://croct.help/sdk/javascript/too-complex-query";
12
+ EvaluationErrorType2["EVALUATION_FAILED"] = "https://croct.help/sdk/javascript/evaluation-failed";
13
+ EvaluationErrorType2["UNALLOWED_RESULT"] = "https://croct.help/sdk/javascript/unallowed-result";
14
+ EvaluationErrorType2["SUSPENDED_SERVICE"] = "https://croct.help/sdk/javascript/suspended-service";
15
+ EvaluationErrorType2["UNSERIALIZABLE_RESULT"] = "https://croct.help/sdk/javascript/unserializable-result";
15
16
  return EvaluationErrorType2;
16
17
  })(EvaluationErrorType || {});
17
18
  class EvaluationError extends Error {
@@ -49,7 +50,7 @@ const _Evaluator = class _Evaluator {
49
50
  title: "The query is too complex.",
50
51
  status: 422,
51
52
  // Unprocessable Entity
52
- type: "https://croct.help/api/evaluation#too-complex-query" /* TOO_COMPLEX_QUERY */,
53
+ type: "https://croct.help/sdk/javascript/too-complex-query" /* TOO_COMPLEX_QUERY */,
53
54
  detail: `The query "${reference}" must be at most ${_Evaluator.MAX_QUERY_LENGTH} characters long, but it is ${length} characters long.`,
54
55
  errors: [{
55
56
  cause: "The query is longer than expected.",
@@ -73,7 +74,7 @@ const _Evaluator = class _Evaluator {
73
74
  () => {
74
75
  const response = {
75
76
  title: `Evaluation could not be completed in time for query "${reference}".`,
76
- type: "https://croct.help/api/evaluation#timeout" /* TIMEOUT */,
77
+ type: "https://croct.help/sdk/javascript/request-timeout" /* TIMEOUT */,
77
78
  detail: `The evaluation took more than ${timeout}ms to complete.`,
78
79
  status: 408
79
80
  // Request Timeout
@@ -92,6 +93,14 @@ const _Evaluator = class _Evaluator {
92
93
  this.logger.debug(
93
94
  `Evaluation of the query "${reference}" processed by region ${region} in ${timing}.`
94
95
  );
96
+ if (response.status === 202) {
97
+ return reject(new EvaluationError({
98
+ status: 202,
99
+ type: "https://croct.help/sdk/javascript/suspended-service" /* SUSPENDED_SERVICE */,
100
+ title: "Service is suspended.",
101
+ detail: Help.forStatusCode(202)
102
+ }));
103
+ }
95
104
  return response.json().then((body) => {
96
105
  if (response.ok) {
97
106
  return resolve(body);
@@ -99,9 +108,9 @@ const _Evaluator = class _Evaluator {
99
108
  this.logHelp(response.status);
100
109
  const problem = body;
101
110
  switch (problem.type) {
102
- case "https://croct.help/api/evaluation#invalid-query" /* INVALID_QUERY */:
103
- case "https://croct.help/api/evaluation#evaluation-failed" /* EVALUATION_FAILED */:
104
- case "https://croct.help/api/evaluation#too-complex-query" /* TOO_COMPLEX_QUERY */:
111
+ case "https://croct.help/sdk/javascript/invalid-query" /* INVALID_QUERY */:
112
+ case "https://croct.help/sdk/javascript/evaluation-failed" /* EVALUATION_FAILED */:
113
+ case "https://croct.help/sdk/javascript/too-complex-query" /* TOO_COMPLEX_QUERY */:
105
114
  reject(new QueryError(problem));
106
115
  break;
107
116
  default:
@@ -121,7 +130,7 @@ const _Evaluator = class _Evaluator {
121
130
  reject(
122
131
  new EvaluationError({
123
132
  title: formatMessage(error),
124
- type: "https://croct.help/api/evaluation#unexpected-error" /* UNEXPECTED_ERROR */,
133
+ type: "https://croct.help/sdk/javascript/unexpected-error" /* UNEXPECTED_ERROR */,
125
134
  detail: "Please try again or contact Croct support if the error persists.",
126
135
  status: 500
127
136
  // Internal Server Error
@@ -37,20 +37,23 @@ class ContentFetcherFacade {
37
37
  this.cidAssigner = configuration.cidAssigner;
38
38
  this.contextFactory = configuration.contextFactory;
39
39
  }
40
- async fetch(slotId, options = {}) {
40
+ async fetch(slotId, options) {
41
41
  if (typeof slotId !== "string" || slotId.length === 0) {
42
42
  throw new Error("The slot ID must be a non-empty string.");
43
43
  }
44
- validate(options);
44
+ if (options !== void 0) {
45
+ validate(options);
46
+ }
45
47
  return this.fetcher.fetch(slotId, {
46
48
  static: false,
47
49
  clientId: await this.cidAssigner.assignCid(),
48
50
  userToken: this.userTokenProvider.getToken() ?? void 0,
49
51
  previewToken: this.previewTokenProvider.getToken() ?? void 0,
50
- version: options.version,
51
- context: this.contextFactory.createContext(options.attributes),
52
- timeout: options.timeout,
53
- preferredLocale: options.preferredLocale
52
+ version: options?.version,
53
+ context: this.contextFactory.createContext(options?.attributes),
54
+ timeout: options?.timeout,
55
+ preferredLocale: options?.preferredLocale,
56
+ includeSchema: options?.includeSchema
54
57
  });
55
58
  }
56
59
  }
@@ -1,8 +1,9 @@
1
1
  import { JsonObject } from '@croct/json';
2
- import { ContentFetcher, FetchResponse } from '../contentFetcher.cjs';
2
+ import { FetchResponseOptions, ContentFetcher, FetchResponse } from '../contentFetcher.cjs';
3
3
  import { ContextFactory } from './evaluatorFacade.cjs';
4
4
  import { TokenProvider } from '../token/token.cjs';
5
5
  import { CidAssigner } from '../cid/assigner.cjs';
6
+ import '@croct/content-model/definition';
6
7
  import '../evaluator.cjs';
7
8
  import '../sourceLocation.cjs';
8
9
  import '../logging/logger.cjs';
@@ -10,7 +11,7 @@ import '../apiKey.cjs';
10
11
  import '../tab.cjs';
11
12
  import '../eventManager.cjs';
12
13
 
13
- type FetchOptions = {
14
+ type FetchOptions = FetchResponseOptions & {
14
15
  version?: `${number}` | number;
15
16
  preferredLocale?: string;
16
17
  timeout?: number;
@@ -30,7 +31,7 @@ declare class ContentFetcherFacade {
30
31
  private readonly userTokenProvider;
31
32
  private readonly cidAssigner;
32
33
  constructor(configuration: Configuration);
33
- fetch<P extends JsonObject>(slotId: string, options?: FetchOptions): Promise<FetchResponse<P>>;
34
+ fetch<P extends JsonObject, O extends FetchResponseOptions>(slotId: string, options?: O & FetchOptions): Promise<FetchResponse<P, O>>;
34
35
  }
35
36
 
36
37
  export { type Configuration, ContentFetcherFacade, type FetchOptions };
@@ -1,8 +1,9 @@
1
1
  import { JsonObject } from '@croct/json';
2
- import { ContentFetcher, FetchResponse } from '../contentFetcher.js';
2
+ import { FetchResponseOptions, ContentFetcher, FetchResponse } from '../contentFetcher.js';
3
3
  import { ContextFactory } from './evaluatorFacade.js';
4
4
  import { TokenProvider } from '../token/token.js';
5
5
  import { CidAssigner } from '../cid/assigner.js';
6
+ import '@croct/content-model/definition';
6
7
  import '../evaluator.js';
7
8
  import '../sourceLocation.js';
8
9
  import '../logging/logger.js';
@@ -10,7 +11,7 @@ import '../apiKey.js';
10
11
  import '../tab.js';
11
12
  import '../eventManager.js';
12
13
 
13
- type FetchOptions = {
14
+ type FetchOptions = FetchResponseOptions & {
14
15
  version?: `${number}` | number;
15
16
  preferredLocale?: string;
16
17
  timeout?: number;
@@ -30,7 +31,7 @@ declare class ContentFetcherFacade {
30
31
  private readonly userTokenProvider;
31
32
  private readonly cidAssigner;
32
33
  constructor(configuration: Configuration);
33
- fetch<P extends JsonObject>(slotId: string, options?: FetchOptions): Promise<FetchResponse<P>>;
34
+ fetch<P extends JsonObject, O extends FetchResponseOptions>(slotId: string, options?: O & FetchOptions): Promise<FetchResponse<P, O>>;
34
35
  }
35
36
 
36
37
  export { type Configuration, ContentFetcherFacade, type FetchOptions };
@@ -15,20 +15,23 @@ class ContentFetcherFacade {
15
15
  this.cidAssigner = configuration.cidAssigner;
16
16
  this.contextFactory = configuration.contextFactory;
17
17
  }
18
- async fetch(slotId, options = {}) {
18
+ async fetch(slotId, options) {
19
19
  if (typeof slotId !== "string" || slotId.length === 0) {
20
20
  throw new Error("The slot ID must be a non-empty string.");
21
21
  }
22
- validate(options);
22
+ if (options !== void 0) {
23
+ validate(options);
24
+ }
23
25
  return this.fetcher.fetch(slotId, {
24
26
  static: false,
25
27
  clientId: await this.cidAssigner.assignCid(),
26
28
  userToken: this.userTokenProvider.getToken() ?? void 0,
27
29
  previewToken: this.previewTokenProvider.getToken() ?? void 0,
28
- version: options.version,
29
- context: this.contextFactory.createContext(options.attributes),
30
- timeout: options.timeout,
31
- preferredLocale: options.preferredLocale
30
+ version: options?.version,
31
+ context: this.contextFactory.createContext(options?.attributes),
32
+ timeout: options?.timeout,
33
+ preferredLocale: options?.preferredLocale,
34
+ includeSchema: options?.includeSchema
32
35
  });
33
36
  }
34
37
  }
@@ -19,6 +19,7 @@ import '../cache/cache.cjs';
19
19
  import '../sdkEvents.cjs';
20
20
  import './contentFetcherFacade.cjs';
21
21
  import '../contentFetcher.cjs';
22
+ import '@croct/content-model/definition';
22
23
  import '../cache/cookieCache.cjs';
23
24
  import '../trackingEvents.cjs';
24
25
  import '../patch.cjs';
package/facade/index.d.ts CHANGED
@@ -19,6 +19,7 @@ import '../cache/cache.js';
19
19
  import '../sdkEvents.js';
20
20
  import './contentFetcherFacade.js';
21
21
  import '../contentFetcher.js';
22
+ import '@croct/content-model/definition';
22
23
  import '../cache/cookieCache.js';
23
24
  import '../trackingEvents.js';
24
25
  import '../patch.js';
@@ -26,6 +26,7 @@ import '../retry/policy.cjs';
26
26
  import '../cache/cache.cjs';
27
27
  import '../activeRecord.cjs';
28
28
  import '../contentFetcher.cjs';
29
+ import '@croct/content-model/definition';
29
30
 
30
31
  type Configuration = {
31
32
  appId: string;
@@ -26,6 +26,7 @@ import '../retry/policy.js';
26
26
  import '../cache/cache.js';
27
27
  import '../activeRecord.js';
28
28
  import '../contentFetcher.js';
29
+ import '@croct/content-model/definition';
29
30
 
30
31
  type Configuration = {
31
32
  appId: string;
package/help.cjs CHANGED
@@ -24,6 +24,8 @@ var Help;
24
24
  ((Help2) => {
25
25
  function forStatusCode(statusCode) {
26
26
  switch (statusCode) {
27
+ case 202:
28
+ return "The service is temporarily suspended. For help, see https://croct.help/sdk/javascript/suspended-service";
27
29
  case 401:
28
30
  return "The request was not authorized, most likely due to invalid credentials. For help, see https://croct.help/sdk/javascript/invalid-credentials";
29
31
  case 403:
package/help.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  declare namespace Help {
2
+ function forStatusCode(statusCode: 204 | 401 | 403 | 408 | 423): string;
2
3
  function forStatusCode(statusCode: number): string | undefined;
3
4
  }
4
5
 
package/help.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  declare namespace Help {
2
+ function forStatusCode(statusCode: 204 | 401 | 403 | 408 | 423): string;
2
3
  function forStatusCode(statusCode: number): string | undefined;
3
4
  }
4
5
 
package/help.js CHANGED
@@ -2,6 +2,8 @@ var Help;
2
2
  ((Help2) => {
3
3
  function forStatusCode(statusCode) {
4
4
  switch (statusCode) {
5
+ case 202:
6
+ return "The service is temporarily suspended. For help, see https://croct.help/sdk/javascript/suspended-service";
5
7
  case 401:
6
8
  return "The request was not authorized, most likely due to invalid credentials. For help, see https://croct.help/sdk/javascript/invalid-credentials";
7
9
  case 403:
package/index.d.cts CHANGED
@@ -22,4 +22,5 @@ import './evaluator.cjs';
22
22
  import './sourceLocation.cjs';
23
23
  import './cid/assigner.cjs';
24
24
  import './contentFetcher.cjs';
25
+ import '@croct/content-model/definition';
25
26
  import './cache/cookieCache.cjs';
package/index.d.ts CHANGED
@@ -22,4 +22,5 @@ import './evaluator.js';
22
22
  import './sourceLocation.js';
23
23
  import './cid/assigner.js';
24
24
  import './contentFetcher.js';
25
+ import '@croct/content-model/definition';
25
26
  import './cache/cookieCache.js';
@@ -0,0 +1,70 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var deduplicatedLogger_exports = {};
19
+ __export(deduplicatedLogger_exports, {
20
+ DeduplicatedLogger: () => DeduplicatedLogger
21
+ });
22
+ module.exports = __toCommonJS(deduplicatedLogger_exports);
23
+ class DeduplicatedLogger {
24
+ constructor(logger, maxSize = 100) {
25
+ this.recentMessages = /* @__PURE__ */ new Set();
26
+ this.logger = logger;
27
+ this.maxSize = maxSize;
28
+ if (maxSize <= 0 || !Number.isInteger(maxSize)) {
29
+ throw new Error("maxSize must be greater than 0");
30
+ }
31
+ }
32
+ debug(message) {
33
+ if (this.isDuplicated("debug", message)) {
34
+ this.logger.debug(message);
35
+ }
36
+ }
37
+ info(message) {
38
+ if (this.isDuplicated("info", message)) {
39
+ this.logger.info(message);
40
+ }
41
+ }
42
+ warn(message) {
43
+ if (this.isDuplicated("warn", message)) {
44
+ this.logger.warn(message);
45
+ }
46
+ }
47
+ error(message) {
48
+ if (this.isDuplicated("error", message)) {
49
+ this.logger.error(message);
50
+ }
51
+ }
52
+ isDuplicated(level, message) {
53
+ const key = `${level}:${message}`;
54
+ if (this.recentMessages.has(key)) {
55
+ this.recentMessages.delete(key);
56
+ this.recentMessages.add(key);
57
+ return false;
58
+ }
59
+ if (this.recentMessages.size >= this.maxSize) {
60
+ const oldest = this.recentMessages.values().next().value;
61
+ this.recentMessages.delete(oldest);
62
+ }
63
+ this.recentMessages.add(key);
64
+ return true;
65
+ }
66
+ }
67
+ // Annotate the CommonJS export names for ESM import in node:
68
+ 0 && (module.exports = {
69
+ DeduplicatedLogger
70
+ });
@@ -0,0 +1,15 @@
1
+ import { Logger } from './logger.cjs';
2
+
3
+ declare class DeduplicatedLogger implements Logger {
4
+ private readonly logger;
5
+ private readonly recentMessages;
6
+ private readonly maxSize;
7
+ constructor(logger: Logger, maxSize?: number);
8
+ debug(message: string): void;
9
+ info(message: string): void;
10
+ warn(message: string): void;
11
+ error(message: string): void;
12
+ private isDuplicated;
13
+ }
14
+
15
+ export { DeduplicatedLogger };
@@ -0,0 +1,15 @@
1
+ import { Logger } from './logger.js';
2
+
3
+ declare class DeduplicatedLogger implements Logger {
4
+ private readonly logger;
5
+ private readonly recentMessages;
6
+ private readonly maxSize;
7
+ constructor(logger: Logger, maxSize?: number);
8
+ debug(message: string): void;
9
+ info(message: string): void;
10
+ warn(message: string): void;
11
+ error(message: string): void;
12
+ private isDuplicated;
13
+ }
14
+
15
+ export { DeduplicatedLogger };
@@ -0,0 +1,47 @@
1
+ class DeduplicatedLogger {
2
+ constructor(logger, maxSize = 100) {
3
+ this.recentMessages = /* @__PURE__ */ new Set();
4
+ this.logger = logger;
5
+ this.maxSize = maxSize;
6
+ if (maxSize <= 0 || !Number.isInteger(maxSize)) {
7
+ throw new Error("maxSize must be greater than 0");
8
+ }
9
+ }
10
+ debug(message) {
11
+ if (this.isDuplicated("debug", message)) {
12
+ this.logger.debug(message);
13
+ }
14
+ }
15
+ info(message) {
16
+ if (this.isDuplicated("info", message)) {
17
+ this.logger.info(message);
18
+ }
19
+ }
20
+ warn(message) {
21
+ if (this.isDuplicated("warn", message)) {
22
+ this.logger.warn(message);
23
+ }
24
+ }
25
+ error(message) {
26
+ if (this.isDuplicated("error", message)) {
27
+ this.logger.error(message);
28
+ }
29
+ }
30
+ isDuplicated(level, message) {
31
+ const key = `${level}:${message}`;
32
+ if (this.recentMessages.has(key)) {
33
+ this.recentMessages.delete(key);
34
+ this.recentMessages.add(key);
35
+ return false;
36
+ }
37
+ if (this.recentMessages.size >= this.maxSize) {
38
+ const oldest = this.recentMessages.values().next().value;
39
+ this.recentMessages.delete(oldest);
40
+ }
41
+ this.recentMessages.add(key);
42
+ return true;
43
+ }
44
+ }
45
+ export {
46
+ DeduplicatedLogger
47
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@croct/sdk",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "Croct SDK for JavaScript.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -81,6 +81,7 @@
81
81
  },
82
82
  "dependencies": {
83
83
  "@croct/json": "^2.0.1",
84
+ "@croct/content-model": "^0.21.1",
84
85
  "tslib": "^2.5.0"
85
86
  },
86
87
  "devDependencies": {
@@ -39,6 +39,7 @@ const fetchOptionsSchema = new import_validation.ObjectType({
39
39
  preferredLocale: new import_validation.StringType({
40
40
  pattern: /^[a-z]{2,3}([-_][a-z]{2,3})?$/i
41
41
  }),
42
+ includeSchema: new import_validation.BooleanType(),
42
43
  attributes: new import_validation.JsonObjectType()
43
44
  }
44
45
  });
@@ -1,4 +1,4 @@
1
- import { ObjectType, NumberType, JsonObjectType, StringType, UnionType } from "../validation/index.js";
1
+ import { ObjectType, NumberType, JsonObjectType, StringType, UnionType, BooleanType } from "../validation/index.js";
2
2
  const fetchOptionsSchema = new ObjectType({
3
3
  properties: {
4
4
  timeout: new NumberType({
@@ -17,6 +17,7 @@ const fetchOptionsSchema = new ObjectType({
17
17
  preferredLocale: new StringType({
18
18
  pattern: /^[a-z]{2,3}([-_][a-z]{2,3})?$/i
19
19
  }),
20
+ includeSchema: new BooleanType(),
20
21
  attributes: new JsonObjectType()
21
22
  }
22
23
  });
package/sdk.d.cts CHANGED
@@ -21,6 +21,7 @@ import '@croct/json';
21
21
  import './utilityTypes.cjs';
22
22
  import './sourceLocation.cjs';
23
23
  import './apiKey.cjs';
24
+ import '@croct/content-model/definition';
24
25
 
25
26
  type Configuration = {
26
27
  appId: string;
package/sdk.d.ts CHANGED
@@ -21,6 +21,7 @@ import '@croct/json';
21
21
  import './utilityTypes.js';
22
22
  import './sourceLocation.js';
23
23
  import './apiKey.js';
24
+ import '@croct/content-model/definition';
24
25
 
25
26
  type Configuration = {
26
27
  appId: string;