@chainlink/external-adapter-framework 0.0.46 → 0.0.56

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 (139) hide show
  1. package/adapter.d.ts +18 -1
  2. package/adapter.js +69 -3
  3. package/adapter.js.map +1 -0
  4. package/background-executor.js +31 -0
  5. package/background-executor.js.map +1 -0
  6. package/cache/factory.d.ts +2 -2
  7. package/cache/factory.js +11 -46
  8. package/cache/factory.js.map +1 -0
  9. package/cache/index.js +3 -2
  10. package/cache/index.js.map +1 -0
  11. package/cache/local.js.map +1 -0
  12. package/cache/metrics.js.map +1 -0
  13. package/cache/redis.js.map +1 -0
  14. package/config/index.d.ts +34 -0
  15. package/config/index.js +40 -62
  16. package/config/index.js.map +1 -0
  17. package/config/provider-limits.js.map +1 -0
  18. package/examples/bank-frick/accounts.d.ts +15 -1
  19. package/examples/bank-frick/accounts.js.map +1 -0
  20. package/examples/bank-frick/config/index.d.ts +15 -2
  21. package/examples/bank-frick/config/index.js.map +1 -0
  22. package/examples/bank-frick/index.d.ts +15 -1
  23. package/examples/bank-frick/index.js.map +1 -0
  24. package/examples/bank-frick/util.js.map +1 -0
  25. package/examples/coingecko/batch-warming.d.ts +7 -0
  26. package/examples/coingecko/batch-warming.js +54 -0
  27. package/examples/coingecko/batch-warming.js.map +1 -0
  28. package/examples/coingecko/index.d.ts +2 -0
  29. package/examples/coingecko/index.js +12 -0
  30. package/examples/coingecko/index.js.map +1 -0
  31. package/examples/coingecko/rest.d.ts +12 -0
  32. package/examples/coingecko/rest.js +55 -0
  33. package/examples/coingecko/rest.js.map +1 -0
  34. package/examples/coingecko/src/config/index.js.map +1 -0
  35. package/examples/coingecko/src/crypto-utils.d.ts +31 -0
  36. package/examples/coingecko/src/crypto-utils.js +60 -0
  37. package/examples/coingecko/src/crypto-utils.js.map +1 -0
  38. package/examples/coingecko/src/endpoint/coins.js +3 -1
  39. package/examples/coingecko/src/endpoint/coins.js.map +1 -0
  40. package/examples/coingecko/src/endpoint/crypto-marketcap.d.ts +1 -1
  41. package/examples/coingecko/src/endpoint/crypto-marketcap.js +4 -4
  42. package/examples/coingecko/src/endpoint/crypto-marketcap.js.map +1 -0
  43. package/examples/coingecko/src/endpoint/crypto-volume.d.ts +1 -1
  44. package/examples/coingecko/src/endpoint/crypto-volume.js +4 -4
  45. package/examples/coingecko/src/endpoint/crypto-volume.js.map +1 -0
  46. package/examples/coingecko/src/endpoint/crypto.d.ts +1 -1
  47. package/examples/coingecko/src/endpoint/crypto.js +4 -4
  48. package/examples/coingecko/src/endpoint/crypto.js.map +1 -0
  49. package/examples/coingecko/src/endpoint/dominance.d.ts +1 -1
  50. package/examples/coingecko/src/endpoint/dominance.js +4 -4
  51. package/examples/coingecko/src/endpoint/dominance.js.map +1 -0
  52. package/examples/coingecko/src/endpoint/global-marketcap.d.ts +1 -1
  53. package/examples/coingecko/src/endpoint/global-marketcap.js +4 -4
  54. package/examples/coingecko/src/endpoint/global-marketcap.js.map +1 -0
  55. package/examples/coingecko/src/endpoint/index.js.map +1 -0
  56. package/examples/coingecko/src/global-utils.d.ts +27 -0
  57. package/examples/coingecko/src/global-utils.js +46 -0
  58. package/examples/coingecko/src/global-utils.js.map +1 -0
  59. package/examples/coingecko/src/index.d.ts +1 -1
  60. package/examples/coingecko/src/index.js.map +1 -0
  61. package/examples/coingecko-old/batch-warming.js.map +1 -0
  62. package/examples/coingecko-old/index.js.map +1 -0
  63. package/examples/coingecko-old/rest.js +4 -1
  64. package/examples/coingecko-old/rest.js.map +1 -0
  65. package/examples/genesis/config/index.d.ts +7 -0
  66. package/examples/genesis/config/index.js +10 -0
  67. package/examples/genesis/config/index.js.map +1 -0
  68. package/examples/genesis/index.d.ts +2 -0
  69. package/examples/genesis/index.js +12 -0
  70. package/examples/genesis/index.js.map +1 -0
  71. package/examples/genesis/sseStream.d.ts +16 -0
  72. package/examples/genesis/sseStream.js +141 -0
  73. package/examples/genesis/sseStream.js.map +1 -0
  74. package/examples/ncfx/config/index.js.map +1 -0
  75. package/examples/ncfx/index.js.map +1 -0
  76. package/examples/ncfx/websocket.js.map +1 -0
  77. package/index.js.map +1 -0
  78. package/metrics/constants.js.map +1 -0
  79. package/metrics/index.d.ts +2 -0
  80. package/metrics/index.js +12 -1
  81. package/metrics/index.js.map +1 -0
  82. package/metrics/util.js.map +1 -0
  83. package/package.json +7 -5
  84. package/rate-limiting/background/fixed-frequency.js +0 -3
  85. package/rate-limiting/background/fixed-frequency.js.map +1 -0
  86. package/rate-limiting/index.d.ts +1 -0
  87. package/rate-limiting/index.js +3 -2
  88. package/rate-limiting/index.js.map +1 -0
  89. package/rate-limiting/metrics.js.map +1 -0
  90. package/rate-limiting/request/simple-counting.js.map +1 -0
  91. package/transports/batch-warming.d.ts +2 -2
  92. package/transports/batch-warming.js +13 -6
  93. package/transports/batch-warming.js.map +1 -0
  94. package/transports/index.d.ts +2 -1
  95. package/transports/index.js +27 -0
  96. package/transports/index.js.map +1 -0
  97. package/transports/metrics.d.ts +3 -0
  98. package/transports/metrics.js +17 -1
  99. package/transports/metrics.js.map +1 -0
  100. package/transports/rest.d.ts +8 -2
  101. package/transports/rest.js +13 -13
  102. package/transports/rest.js.map +1 -0
  103. package/transports/sse.d.ts +41 -0
  104. package/transports/sse.js +95 -0
  105. package/transports/sse.js.map +1 -0
  106. package/transports/util.js.map +1 -0
  107. package/transports/websocket.d.ts +2 -2
  108. package/transports/websocket.js +12 -11
  109. package/transports/websocket.js.map +1 -0
  110. package/util/censor/censor-list.d.ts +9 -0
  111. package/util/censor/censor-list.js +12 -0
  112. package/util/censor/censor-list.js.map +1 -0
  113. package/util/index.d.ts +1 -0
  114. package/util/index.js +3 -1
  115. package/util/index.js.map +1 -0
  116. package/util/logger.d.ts +3 -0
  117. package/util/logger.js +20 -1
  118. package/util/logger.js.map +1 -0
  119. package/util/request.d.ts +52 -6
  120. package/util/request.js.map +1 -0
  121. package/util/subscription-set/expiring-sorted-set.d.ts +0 -1
  122. package/util/subscription-set/expiring-sorted-set.js +0 -12
  123. package/util/subscription-set/expiring-sorted-set.js.map +1 -0
  124. package/util/subscription-set/redis-sorted-set.d.ts +9 -0
  125. package/util/subscription-set/redis-sorted-set.js +28 -0
  126. package/util/subscription-set/redis-sorted-set.js.map +1 -0
  127. package/util/subscription-set/subscription-set.d.ts +5 -4
  128. package/util/subscription-set/subscription-set.js +13 -5
  129. package/util/subscription-set/subscription-set.js.map +1 -0
  130. package/util/test-payload-loader.js.map +1 -0
  131. package/validation/error.js.map +1 -0
  132. package/validation/index.js +10 -9
  133. package/validation/index.js.map +1 -0
  134. package/validation/input-params.d.ts +1 -1
  135. package/validation/input-params.js.map +1 -0
  136. package/validation/input-validator.d.ts +16 -0
  137. package/validation/input-validator.js +123 -0
  138. package/validation/input-validator.js.map +1 -0
  139. package/validation/override-functions.js.map +1 -0
@@ -10,6 +10,18 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
13
25
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
26
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
27
  };
@@ -17,9 +29,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
29
  exports.buildTransportHandler = exports.buildCacheEntriesFromResults = void 0;
18
30
  const cache_1 = require("../cache");
19
31
  const util_1 = require("../util");
32
+ const transportMetrics = __importStar(require("./metrics"));
33
+ const client = __importStar(require("prom-client"));
20
34
  __exportStar(require("./batch-warming"), exports);
21
35
  __exportStar(require("./rest"), exports);
22
36
  __exportStar(require("./websocket"), exports);
37
+ __exportStar(require("./sse"), exports);
23
38
  const logger = (0, util_1.makeLogger)('Transport');
24
39
  /**
25
40
  * Helper method to build cache entries to set after getting a bunch of responses from a DP.
@@ -73,17 +88,29 @@ const buildTransportHandler = (adapter) => async (req, reply) => {
73
88
  return reply.send(immediateResponse);
74
89
  }
75
90
  }
91
+ // Observe the idle time taken for polling response
92
+ const metricsTimer = transportMetrics.transportPollingDurationSeconds
93
+ .labels({ endpoint: req.requestContext.endpointName })
94
+ .startTimer();
76
95
  logger.debug('Transport is set up, polling cache for response...');
77
96
  const response = await (0, cache_1.pollResponseFromCache)(adapter.dependencies.cache, req.requestContext.cacheKey, {
78
97
  maxRetries: adapter.config.CACHE_POLLING_MAX_RETRIES,
79
98
  sleep: adapter.config.CACHE_POLLING_SLEEP_MS,
80
99
  });
100
+ metricsTimer({ succeeded: String(!!response) });
81
101
  if (response) {
82
102
  logger.debug('Got a response from the cache, sending that back');
83
103
  return reply.send(response);
84
104
  }
105
+ // Record polling mechanism failure to return response
106
+ transportMetrics.transportPollingFailureCount
107
+ .labels({ endpoint: req.requestContext.endpointName })
108
+ .inc();
85
109
  logger.debug('Ran out of polling attempts, returning timeout');
86
110
  reply.statusCode = 504;
87
111
  return reply.send();
88
112
  };
89
113
  exports.buildTransportHandler = buildTransportHandler;
114
+ if (process.env['METRICS_ENABLED'] === 'false') {
115
+ client.register.clear();
116
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transports/index.ts"],"names":[],"mappings":"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"}
@@ -20,3 +20,6 @@ export declare const wsConnectionErrors: client.Counter<"message" | "url">;
20
20
  export declare const wsSubscriptionActive: client.Gauge<"feed_id" | "connection_url" | "subscription_key">;
21
21
  export declare const wsSubscriptionTotal: client.Counter<"feed_id" | "connection_url" | "subscription_key">;
22
22
  export declare const wsMessageTotal: client.Counter<"feed_id" | "subscription_key">;
23
+ export declare const bgExecuteSubscriptionSetCount: client.Gauge<"endpoint" | "transport_type">;
24
+ export declare const transportPollingFailureCount: client.Counter<"endpoint">;
25
+ export declare const transportPollingDurationSeconds: client.Gauge<"succeeded" | "endpoint">;
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.wsMessageTotal = exports.wsSubscriptionTotal = exports.wsSubscriptionActive = exports.wsConnectionErrors = exports.wsConnectionActive = exports.recordWsMessageMetrics = exports.messageSubsLabels = exports.connectionErrorLabels = exports.dataProviderRequestDurationSeconds = exports.dataProviderRequests = exports.dataProviderMetricsLabel = void 0;
26
+ exports.transportPollingDurationSeconds = exports.transportPollingFailureCount = exports.bgExecuteSubscriptionSetCount = exports.wsMessageTotal = exports.wsSubscriptionTotal = exports.wsSubscriptionActive = exports.wsConnectionErrors = exports.wsConnectionActive = exports.recordWsMessageMetrics = exports.messageSubsLabels = exports.connectionErrorLabels = exports.dataProviderRequestDurationSeconds = exports.dataProviderRequests = exports.dataProviderMetricsLabel = void 0;
27
27
  const client = __importStar(require("prom-client"));
28
28
  const cache_1 = require("../cache");
29
29
  const constants_1 = require("../metrics/constants");
@@ -103,3 +103,19 @@ exports.wsMessageTotal = new client.Counter({
103
103
  help: 'The number of messages received in total',
104
104
  labelNames: ['feed_id', 'subscription_key'],
105
105
  });
106
+ // V3 specific metrics
107
+ exports.bgExecuteSubscriptionSetCount = new client.Gauge({
108
+ name: 'bg_execute_subscription_set_count',
109
+ help: 'The number of active subscriptions in background execute',
110
+ labelNames: ['endpoint', 'transport_type'],
111
+ });
112
+ exports.transportPollingFailureCount = new client.Counter({
113
+ name: 'transport_polling_failure_count',
114
+ help: 'The number of times the polling mechanism ran out of attempts and failed to return a response',
115
+ labelNames: ['endpoint'],
116
+ });
117
+ exports.transportPollingDurationSeconds = new client.Gauge({
118
+ name: 'transport_polling_duration_seconds',
119
+ help: 'A histogram bucket of the distribution of transport polling idle time durations',
120
+ labelNames: ['endpoint', 'succeeded'],
121
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/transports/metrics.ts"],"names":[],"mappings":"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"}
@@ -21,7 +21,10 @@ export declare class RestTransport<AdapterParams, ProviderRequestBody, ProviderR
21
21
  prepareRequest: (req: AdapterRequest<AdapterParams>, config: AdapterConfig<CustomSettings>) => AxiosRequestConfig<ProviderRequestBody> | Promise<AxiosRequestConfig<ProviderRequestBody>>;
22
22
  parseResponse: (req: AdapterRequest<AdapterParams>, res: AxiosResponse<ProviderResponseBody>, config: AdapterConfig<CustomSettings>) => AdapterResponse<ProviderResponseBody> | Promise<AdapterResponse<ProviderResponseBody>>;
23
23
  options: {
24
- coalescing: boolean;
24
+ requestCoalescing: {
25
+ enabled: boolean;
26
+ entropyMax?: number;
27
+ };
25
28
  };
26
29
  };
27
30
  inFlightPrefix: string;
@@ -31,7 +34,10 @@ export declare class RestTransport<AdapterParams, ProviderRequestBody, ProviderR
31
34
  prepareRequest: (req: AdapterRequest<AdapterParams>, config: AdapterConfig<CustomSettings>) => AxiosRequestConfig<ProviderRequestBody> | Promise<AxiosRequestConfig<ProviderRequestBody>>;
32
35
  parseResponse: (req: AdapterRequest<AdapterParams>, res: AxiosResponse<ProviderResponseBody>, config: AdapterConfig<CustomSettings>) => AdapterResponse<ProviderResponseBody> | Promise<AdapterResponse<ProviderResponseBody>>;
33
36
  options: {
34
- coalescing: boolean;
37
+ requestCoalescing: {
38
+ enabled: boolean;
39
+ entropyMax?: number;
40
+ };
35
41
  };
36
42
  });
37
43
  initialize(dependencies: AdapterDependencies, config: AdapterConfig): Promise<void>;
@@ -50,14 +50,17 @@ class RestTransport {
50
50
  this.cache = dependencies.cache;
51
51
  this.rateLimiter = dependencies.requestRateLimiter;
52
52
  // Allow enabling/disabling request coalescing through env var
53
- if (config.REQUEST_COALESCING_ENABLED !== undefined) {
54
- this.config.options.coalescing = config.REQUEST_COALESCING_ENABLED;
55
- }
53
+ this.config.options.requestCoalescing.enabled = config.REQUEST_COALESCING_ENABLED;
54
+ this.config.options.requestCoalescing.entropyMax = config.REQUEST_COALESCING_ENTROPY_MAX;
56
55
  }
57
56
  async hasBeenSetUp(req) {
58
- if (!this.config.options.coalescing) {
57
+ if (!this.config.options.requestCoalescing.enabled) {
59
58
  return false;
60
59
  }
60
+ // Add some entropy here because of possible scenario where the key won't be set before multiple
61
+ // other instances in a burst request try to access the coalescing key.
62
+ const randomMs = Math.random() * (this.config.options.requestCoalescing.entropyMax || 0);
63
+ await (0, util_1.sleep)(randomMs);
61
64
  // Check if request is in flight
62
65
  const inFlight = await this.cache.get(this.inFlightPrefix + req.requestContext.cacheKey);
63
66
  if (inFlight) {
@@ -85,12 +88,11 @@ class RestTransport {
85
88
  await this.waitUntilUnderRateLimit(options, retry + 1);
86
89
  }
87
90
  async setup(req, config) {
88
- if (this.config.options.coalescing) {
91
+ if (this.config.options.requestCoalescing.enabled) {
92
+ const ttl = config.REST_TRANSPORT_MAX_RATE_LIMIT_RETRIES *
93
+ config.REST_TRANSPORT_MS_BETWEEN_RATE_LIMIT_RETRIES;
89
94
  logger.debug('Setting up rest transport, setting request in flight in cache');
90
- // TODO: Should this use a separate cache?
91
- // TODO: Set viable ttl to approximate timeout from API
92
- // TODO: Make this ttl configurable
93
- await this.cache.set(this.inFlightPrefix + req.requestContext.cacheKey, true, 2000); // Can't use Infinity for things like Redis
95
+ await this.cache.set(this.inFlightPrefix + req.requestContext.cacheKey, true, ttl + 100); // Can't use Infinity for things like Redis
94
96
  }
95
97
  const request = await this.config.prepareRequest(req, config);
96
98
  logger.trace('Check if we are under rate limits to perform request');
@@ -100,13 +102,12 @@ class RestTransport {
100
102
  });
101
103
  logger.trace('Sending request to data provider...');
102
104
  const providerResponse = await (0, util_2.axiosRequest)(request, config);
103
- logger.debug(`Got response from provider, parsing (raw body: ${providerResponse.data})`); // TODO: Sensitive data?
105
+ logger.debug(`Got response from provider, parsing (raw body: ${providerResponse.data})`);
104
106
  const parsedResponse = await this.config.parseResponse(req, providerResponse, config);
105
107
  if (config.API_VERBOSE) {
106
108
  parsedResponse.data = providerResponse.data;
107
109
  }
108
110
  if (config.METRICS_ENABLED && config.EXPERIMENTAL_METRICS_ENABLED) {
109
- // TODO: Potentially create function to add all telemetry data
110
111
  parsedResponse.maxAge = Date.now() + config.CACHE_MAX_AGE;
111
112
  parsedResponse.meta = {
112
113
  metrics: { feedId: req.requestContext.meta?.metrics?.feedId || 'N/A' },
@@ -127,8 +128,7 @@ class RestTransport {
127
128
  ...req.requestContext.meta,
128
129
  metrics: { ...req.requestContext.meta?.metrics, cacheHit: false },
129
130
  };
130
- // TODO: move this to a try/catch/finally
131
- if (this.config.options.coalescing) {
131
+ if (this.config.options.requestCoalescing.enabled) {
132
132
  logger.debug('Set provider response in cache, removing in flight from cache');
133
133
  await this.cache.delete(this.inFlightPrefix);
134
134
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest.js","sourceRoot":"","sources":["../../../src/transports/rest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { Cache } from '../cache';
2
+ import EventSource from 'eventsource';
3
+ import { SettingsMap, AdapterConfig } from '../config';
4
+ import { AxiosRequestConfig } from 'axios';
5
+ import { SubscriptionSet } from '../util';
6
+ import { AdapterRequest, ProviderResult } from '../util/request';
7
+ import { Transport } from './';
8
+ import { AdapterContext, AdapterDependencies } from '../adapter';
9
+ export interface SSEConfig {
10
+ url: string;
11
+ eventSourceInitDict?: EventSource.EventSourceInitDict;
12
+ }
13
+ export declare class SSETransport<AdapterParams, ProviderRequestBody, ProviderResponseBody, CustomSettings extends SettingsMap> implements Transport<AdapterParams, ProviderResponseBody, CustomSettings> {
14
+ private config;
15
+ EventSource: typeof EventSource;
16
+ cache: Cache;
17
+ eventListeners: {
18
+ type: string;
19
+ parseResponse: (evt: MessageEvent) => ProviderResult<AdapterParams>;
20
+ }[];
21
+ sseConnection?: EventSource;
22
+ subscriptionSet: SubscriptionSet<AdapterParams>;
23
+ timeOfLastReq: number;
24
+ localSubscriptions: AdapterParams[];
25
+ constructor(config: {
26
+ prepareSSEConnectionConfig: (params: AdapterParams[], context: AdapterContext<CustomSettings>) => SSEConfig;
27
+ prepareKeepAliveRequest: (context: AdapterContext<CustomSettings>) => AxiosRequestConfig<ProviderRequestBody>;
28
+ prepareSubscriptionRequest: (params: AdapterParams[], context: AdapterContext<CustomSettings>) => AxiosRequestConfig<ProviderRequestBody>;
29
+ prepareUnsubscriptionRequest: (params: AdapterParams[], context: AdapterContext<CustomSettings>) => AxiosRequestConfig<ProviderRequestBody>;
30
+ eventListeners: {
31
+ type: string;
32
+ parseResponse: (evt: MessageEvent) => ProviderResult<AdapterParams>[];
33
+ }[];
34
+ keepaliveSleepMs?: number;
35
+ pollingSleepMs?: number;
36
+ });
37
+ initialize(dependencies: AdapterDependencies, config: AdapterConfig<SettingsMap>, endpointName: string): Promise<void>;
38
+ hasBeenSetUp(): Promise<boolean>;
39
+ setup(req: AdapterRequest<AdapterParams>, config: AdapterConfig<CustomSettings>): Promise<void>;
40
+ backgroundExecute(context: AdapterContext<CustomSettings>): Promise<number>;
41
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SSETransport = void 0;
7
+ const eventsource_1 = __importDefault(require("eventsource"));
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const util_1 = require("../util");
10
+ const _1 = require("./");
11
+ const logger = (0, util_1.makeLogger)('SSETransport');
12
+ class SSETransport {
13
+ constructor(config) {
14
+ this.config = config;
15
+ this.EventSource = eventsource_1.default;
16
+ this.timeOfLastReq = 0;
17
+ // The double sets serve to create a simple polling mechanism instead of needing a subscription
18
+ // This one would not; this is always local state
19
+ this.localSubscriptions = [];
20
+ }
21
+ async initialize(dependencies, config, endpointName) {
22
+ this.cache = dependencies.cache;
23
+ this.subscriptionSet = dependencies.subscriptionSetFactory.buildSet(endpointName);
24
+ if (dependencies.eventSource) {
25
+ this.EventSource = dependencies.eventSource;
26
+ }
27
+ }
28
+ async hasBeenSetUp() {
29
+ return false;
30
+ }
31
+ async setup(req, config) {
32
+ logger.debug(`Adding entry to subscription set: [${req.requestContext.cacheKey}] = ${req.requestContext.data}`);
33
+ await this.subscriptionSet.add(req.requestContext.cacheKey, req.requestContext.data, config.SSE_SUBSCRIPTION_TTL);
34
+ }
35
+ // Unlike cache warming, this execute will manage subscriptions
36
+ async backgroundExecute(context) {
37
+ logger.debug('Starting background execute, getting subscriptions from sorted set');
38
+ const desiredSubs = await this.subscriptionSet.getAll();
39
+ logger.debug('Generating delta (subscribes & unsubscribes)');
40
+ // TODO: More efficient algorithm, this is really easy to read, but high(er) time complexity
41
+ const subscribeParams = desiredSubs.filter((s) => !this.localSubscriptions.includes(s));
42
+ const unsubscribeParams = this.localSubscriptions.filter((s) => !desiredSubs.includes(s));
43
+ logger.debug(`${subscribeParams.length} new subscriptions; ${unsubscribeParams.length} to unsubscribe`);
44
+ if (subscribeParams.length) {
45
+ logger.trace(`Will subscribe to: ${subscribeParams}`);
46
+ }
47
+ if (unsubscribeParams.length) {
48
+ logger.trace(`Will unsubscribe to: ${unsubscribeParams}`);
49
+ }
50
+ if ((subscribeParams.length || unsubscribeParams.length) &&
51
+ (!this.sseConnection || this.sseConnection.readyState !== this.sseConnection.OPEN)) {
52
+ logger.debug('No established connection and new subscriptions available, connecting to SSE');
53
+ const sseConfig = this.config.prepareSSEConnectionConfig(subscribeParams, context);
54
+ this.sseConnection = new this.EventSource(sseConfig.url, sseConfig.eventSourceInitDict);
55
+ const eventHandlerGenerator = (listener) => {
56
+ return (e) => {
57
+ const providerResponses = listener.parseResponse(e);
58
+ const cacheEntries = (0, _1.buildCacheEntriesFromResults)(providerResponses, context);
59
+ this.cache.setMany(cacheEntries, context.adapterConfig.CACHE_MAX_AGE);
60
+ };
61
+ };
62
+ this.config.eventListeners.forEach((listener) => {
63
+ this.sseConnection?.addEventListener(listener.type, eventHandlerGenerator(listener));
64
+ });
65
+ }
66
+ const makeRequest = async (req) => {
67
+ try {
68
+ const res = await axios_1.default.request(req);
69
+ logger.debug(res.data, `response status ${res.statusText} from keepalive request`);
70
+ }
71
+ catch (err) {
72
+ logger.error(err, `Error on keepalive request`);
73
+ }
74
+ this.timeOfLastReq = Date.now();
75
+ };
76
+ if (subscribeParams.length) {
77
+ const subscribeRequest = this.config.prepareSubscriptionRequest(subscribeParams, context);
78
+ makeRequest(subscribeRequest);
79
+ }
80
+ if (unsubscribeParams.length) {
81
+ const unsubscribeRequest = this.config.prepareUnsubscriptionRequest(unsubscribeParams, context);
82
+ makeRequest(unsubscribeRequest);
83
+ }
84
+ if (desiredSubs.length &&
85
+ Date.now() - this.timeOfLastReq > context.adapterConfig.SSE_KEEPALIVE_SLEEP) {
86
+ const prepareKeepAliveRequest = this.config.prepareKeepAliveRequest(context);
87
+ makeRequest(prepareKeepAliveRequest);
88
+ }
89
+ logger.debug('Setting local state to cache value');
90
+ this.localSubscriptions = desiredSubs;
91
+ logger.debug('Background execute complete');
92
+ return context.adapterConfig.SSE_SUBSCRIPTION_UPDATE_SLEEP;
93
+ }
94
+ }
95
+ exports.SSETransport = SSETransport;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../../src/transports/sse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/transports/util.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAA4E;AAE5E,+CAK4B;AAC5B,4DAA6C;AAE7C;;;;;GAKG;AACI,KAAK,UAAU,YAAY,CAKhC,OAAgD,EAChD,MAAqC;IAErC,MAAM,aAAa,GAAG,gBAAgB,CAAC,kCAAkC,CAAC,UAAU,EAAE,CAAA;IACtF,IAAI,gBAAqD,CAAA;IACzD,IAAI;QACF,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,WAAW,CAAA;QACpC,gBAAgB,GAAG,MAAM,eAAK,CAAC,OAAO,CAAuB,OAAO,CAAC,CAAA;KACtE;IAAC,OAAO,CAAU,EAAE;QACnB,MAAM,KAAK,GAAG,CAAe,CAAA;QAC7B,gBAAgB;QAChB,IAAI,kBAAsC,CAAA;QAC1C,IAAI,YAA0B,CAAA;QAC9B,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE;YACjC,YAAY,GAAG,IAAI,2BAAmB,CAAC,EAAE,CAAC,CAAA;YAC1C,kBAAkB,GAAG,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAA;YACnD,YAAY,CAAC,IAAI,GAAG,qCAAqC,CAAA;SAC1D;aAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE;YAClC,YAAY,GAAG,IAAI,gCAAwB,CAAC,EAAE,CAAC,CAAA;YAC/C,kBAAkB,GAAG,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAA;SAC7C;aAAM;YACL,YAAY,GAAG,IAAI,8BAAsB,CAAC,EAAE,CAAC,CAAA;YAC7C,kBAAkB,GAAG,CAAC,CAAA,CAAC,wBAAwB;SAChD;QACD,+CAA+C;QAC/C,gBAAgB,CAAC,oBAAoB;aAClC,MAAM,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;aACrF,GAAG,EAAE,CAAA;QAER,YAAY,CAAC,UAAU,GAAG,GAAG,CAAA;QAC7B,YAAY,CAAC,kBAAkB,GAAG,kBAAkB,CAAA;QACpD,YAAY,CAAC,OAAO,GAAG,KAAK,EAAE,OAAO,CAAA;QACrC,YAAY,CAAC,KAAK,GAAG,KAAK,CAAA;QAC1B,YAAY,CAAC,aAAa,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAA;QAClD,YAAY,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;QAE9B,MAAM,YAAY,CAAA;KACnB;YAAS;QACR,qEAAqE;QACrE,aAAa,EAAE,CAAA;KAChB;IAED,oDAAoD;IACpD,gBAAgB,CAAC,oBAAoB;SAClC,MAAM,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;SAC1F,GAAG,EAAE,CAAA;IAER,OAAO,gBAAgB,CAAA;AACzB,CAAC;AArDD,oCAqDC"}
@@ -69,8 +69,8 @@ export declare class WebSocketTransport<AdapterParams, ProviderDataMessage, Cust
69
69
  localSubscriptions: AdapterParams[];
70
70
  wsConnection: WebSocket;
71
71
  constructor(config: WebSocketTransportConfig<AdapterParams, ProviderDataMessage, CustomSettings>);
72
- initialize(dependencies: AdapterDependencies): Promise<void>;
73
- hasBeenSetUp(req: AdapterRequest<AdapterParams>): Promise<boolean>;
72
+ initialize(dependencies: AdapterDependencies, _: AdapterConfig, endpointName: string): Promise<void>;
73
+ hasBeenSetUp(): Promise<boolean>;
74
74
  setup(req: AdapterRequest<AdapterParams>, config: AdapterConfig<CustomSettings>): Promise<void>;
75
75
  serializeMessage(payload: unknown): string;
76
76
  deserializeMessage(data: WebSocket.Data): ProviderDataMessage;
@@ -56,21 +56,19 @@ class WebSocketTransport {
56
56
  // This one would not; this is always local state
57
57
  this.localSubscriptions = [];
58
58
  }
59
- async initialize(dependencies) {
59
+ async initialize(dependencies, _, endpointName) {
60
60
  this.cache = dependencies.cache;
61
61
  this.rateLimiter = dependencies.backgroundExecuteRateLimiter;
62
- this.subscriptionSet = dependencies.subscriptionSetFactory.buildSet();
62
+ this.subscriptionSet = dependencies.subscriptionSetFactory.buildSet(endpointName);
63
63
  }
64
- async hasBeenSetUp(req) {
65
- return !!(await this.subscriptionSet.get(req.requestContext.cacheKey));
64
+ // This might need coalescing to avoid too frequent ttl updates
65
+ async hasBeenSetUp() {
66
+ return false;
66
67
  }
67
68
  async setup(req, config) {
68
69
  logger.debug(`Adding entry to subscription set: [${req.requestContext.cacheKey}] = ${req.requestContext.data}`);
69
70
  await this.subscriptionSet.add(req.requestContext.cacheKey, req.requestContext.data, config.WS_SUBSCRIPTION_TTL);
70
71
  }
71
- // TODO: Maybe we don't do this, and leave the preparation on the adapter's side?
72
- // TODO: Maybe we store adapter params pre-prepared? That would be more efficient
73
- // Assuming always JSON payloads for now, makes it all cleaner
74
72
  serializeMessage(payload) {
75
73
  return typeof payload === 'string' ? payload : JSON.stringify(payload);
76
74
  }
@@ -80,7 +78,8 @@ class WebSocketTransport {
80
78
  establishWsConnection(context) {
81
79
  return new Promise((resolve) => {
82
80
  const ctor = WebSocketClassProvider.get();
83
- this.wsConnection = new ctor(this.config.url);
81
+ const url = context.adapterConfig.WS_API_ENDPOINT || this.config.url;
82
+ this.wsConnection = new ctor(url);
84
83
  this.wsConnection.addEventListener('open', async (event) => {
85
84
  logger.debug(`Opened websocket connection. (event type ${event.type})`);
86
85
  await this.config.handlers.open(this.wsConnection, context);
@@ -91,7 +90,6 @@ class WebSocketTransport {
91
90
  resolve(true);
92
91
  });
93
92
  this.wsConnection.addEventListener('message', async (event) => {
94
- // TODO: Assuming JSON always, maybe use BSON also?
95
93
  const parsed = this.deserializeMessage(event.data);
96
94
  logger.trace(`Got ws message: ${parsed}`);
97
95
  const results = this.config.handlers.message(parsed, context);
@@ -102,6 +100,7 @@ class WebSocketTransport {
102
100
  }
103
101
  });
104
102
  this.wsConnection.addEventListener('error', async (event) => {
103
+ logger.debug(`Error occurred in web socket connection. Error: ${event.error} ; Message: ${event.message}`);
105
104
  // Record connection error count
106
105
  transportMetrics.wsConnectionErrors
107
106
  .labels(transportMetrics.connectionErrorLabels(event.message))
@@ -119,8 +118,11 @@ class WebSocketTransport {
119
118
  async backgroundExecute(context) {
120
119
  logger.debug('Starting background execute, getting subscriptions from sorted set');
121
120
  const desiredSubs = await this.subscriptionSet.getAll();
121
+ // Keep track of active subscriptions for background execute
122
+ transportMetrics.bgExecuteSubscriptionSetCount
123
+ .labels({ endpoint: context.adapterEndpoint.name, transport_type: 'websocket' })
124
+ .set(desiredSubs.length);
122
125
  logger.debug('Generating delta (subscribes & unsubscribes)');
123
- // TODO: More efficient algorithm, this is really easy to read, but high(er) time complexity
124
126
  const subscribeParams = desiredSubs.filter((s) => !this.localSubscriptions.includes(s));
125
127
  const subscribes = subscribeParams
126
128
  .map(this.config.builders.subscribeMessage)
@@ -148,7 +150,6 @@ class WebSocketTransport {
148
150
  logger.debug('No established connection and new subscriptions available, connecting to WS');
149
151
  await this.establishWsConnection(context);
150
152
  }
151
- // TODO: Close connection at some point?
152
153
  logger.debug('Sending subs/unsubs if there are any');
153
154
  const messages = unsubscribes.concat(subscribes);
154
155
  for (const message of messages) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../../src/transports/websocket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export default class CensorList {
2
+ static censorList: CensorKeyValue[];
3
+ static getAll(): CensorKeyValue[];
4
+ static set(censorList: CensorKeyValue[]): void;
5
+ }
6
+ export interface CensorKeyValue {
7
+ key: string;
8
+ value: RegExp;
9
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class CensorList {
4
+ static getAll() {
5
+ return this.censorList;
6
+ }
7
+ static set(censorList) {
8
+ this.censorList = censorList;
9
+ }
10
+ }
11
+ exports.default = CensorList;
12
+ CensorList.censorList = [];
@@ -0,0 +1 @@
1
+ {"version":3,"file":"censor-list.js","sourceRoot":"","sources":["../../../../src/util/censor/censor-list.ts"],"names":[],"mappings":";;AAAA,MAAqB,UAAU;IAE7B,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,UAA4B;QACrC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;;AAPH,6BAQC;AAPQ,qBAAU,GAAqB,EAAE,CAAA"}
package/util/index.d.ts CHANGED
@@ -9,4 +9,5 @@ export * from './subscription-set/subscription-set';
9
9
  export declare const sleep: (ms: number) => Promise<void>;
10
10
  export declare const isObject: (o: unknown) => boolean;
11
11
  export declare const isArray: (o: unknown) => boolean;
12
+ export declare const isEmpty: (o: unknown) => boolean;
12
13
  export declare type PromiseOrValue<T> = Promise<T> | T;
package/util/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.isArray = exports.isObject = exports.sleep = void 0;
17
+ exports.isEmpty = exports.isArray = exports.isObject = exports.sleep = void 0;
18
18
  __exportStar(require("./request"), exports);
19
19
  __exportStar(require("./logger"), exports);
20
20
  __exportStar(require("./subscription-set/subscription-set"), exports);
@@ -33,3 +33,5 @@ const isObject = (o) => o !== null && typeof o === 'object' && Array.isArray(o)
33
33
  exports.isObject = isObject;
34
34
  const isArray = (o) => o !== null && typeof o === 'object' && Array.isArray(o);
35
35
  exports.isArray = isArray;
36
+ const isEmpty = (o) => o === undefined || o === null || o === '';
37
+ exports.isEmpty = isEmpty;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/util/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,4CAAyB;AACzB,2CAAwB;AACxB,sEAAmD;AAEnD;;;;GAIG;AACI,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE;IACjD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAJY,QAAA,KAAK,SAIjB;AAEM,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAW,EAAE,CAC9C,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAA;AADtD,QAAA,QAAQ,YAC8C;AAE5D,MAAM,OAAO,GAAG,CAAC,CAAU,EAAW,EAAE,CAC7C,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AAD5C,QAAA,OAAO,WACqC;AAElD,MAAM,OAAO,GAAG,CAAC,CAAU,EAAW,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAA;AAA5E,QAAA,OAAO,WAAqE"}
package/util/logger.d.ts CHANGED
@@ -27,6 +27,9 @@ export declare type Store = {
27
27
  */
28
28
  export declare const makeLogger: (layer: string) => pino.Logger<{
29
29
  level: string;
30
+ hooks: {
31
+ logMethod(this: pino.Logger<pino.LoggerOptions>, inputArgs: [msg: string, ...args: any[]], method: pino.LogFn): void;
32
+ };
30
33
  mixin(): {};
31
34
  transport: {
32
35
  target: string;
package/util/logger.js CHANGED
@@ -8,6 +8,7 @@ const pino_1 = __importDefault(require("pino"));
8
8
  const config_1 = require("../config");
9
9
  const crypto_1 = require("crypto");
10
10
  const node_async_hooks_1 = require("node:async_hooks");
11
+ const censor_list_1 = __importDefault(require("./censor/censor-list"));
11
12
  exports.asyncLocalStorage = new node_async_hooks_1.AsyncLocalStorage();
12
13
  const debugTransport = {
13
14
  target: 'pino-pretty',
@@ -22,6 +23,13 @@ const debugTransport = {
22
23
  // Base logger, shouldn't be used because we want layers to be specified
23
24
  const baseLogger = (0, pino_1.default)({
24
25
  level: process.env['LOG_LEVEL']?.toLowerCase() || config_1.BaseSettings.LOG_LEVEL.default,
26
+ hooks: {
27
+ logMethod(inputArgs, method) {
28
+ // Censor each argument of logger
29
+ const censorList = censor_list_1.default.getAll();
30
+ return method.apply(this, inputArgs.map((arg) => censor(arg, censorList)));
31
+ },
32
+ },
25
33
  mixin() {
26
34
  if (process.env['CORRELATION_ID_ENABLED'] === 'true') {
27
35
  const store = exports.asyncLocalStorage.getStore();
@@ -31,7 +39,9 @@ const baseLogger = (0, pino_1.default)({
31
39
  }
32
40
  return {};
33
41
  },
34
- transport: process.env['DEBUG'] === 'true' ? debugTransport : undefined,
42
+ transport: process.env['DEBUG'] === 'true' || process.env['NODE_ENV'] === 'development'
43
+ ? debugTransport
44
+ : undefined,
35
45
  });
36
46
  /**
37
47
  * Instead of using a global logger instance, we want to force using a child logger
@@ -60,3 +70,12 @@ const loggingContextMiddleware = (req, res, done) => {
60
70
  });
61
71
  };
62
72
  exports.loggingContextMiddleware = loggingContextMiddleware;
73
+ // Obj is typed as "any" because it could be a variety of structures in the logger
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
+ function censor(obj, censorList) {
76
+ let stringified = JSON.stringify(obj);
77
+ censorList.forEach((entry) => {
78
+ stringified = stringified.replace(entry.value, `[${entry.key} REDACTED]`);
79
+ });
80
+ return stringified;
81
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/util/logger.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAuB;AACvB,sCAAwC;AAGxC,mCAAmC;AACnC,uDAAoD;AACpD,uEAAiE;AAEpD,QAAA,iBAAiB,GAAG,IAAI,oCAAiB,EAAE,CAAA;AAMxD,MAAM,cAAc,GAAG;IACrB,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE;QACP,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,OAAO;QACnB,MAAM,EAAE,oBAAoB;QAC5B,aAAa,EAAE,kCAAkC;QACjD,aAAa,EAAE,uBAAuB;KACvC;CACF,CAAA;AAED,wEAAwE;AACxE,MAAM,UAAU,GAAG,IAAA,cAAI,EAAC;IACtB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE,IAAI,qBAAY,CAAC,SAAS,CAAC,OAAO;IAChF,KAAK,EAAE;QACL,SAAS,CAAC,SAAS,EAAE,MAAM;YACzB,iCAAiC;YACjC,MAAM,UAAU,GAAG,qBAAU,CAAC,MAAM,EAAE,CAAA;YACtC,OAAO,MAAM,CAAC,KAAK,CACjB,IAAI,EACJ,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,CAA2B,CAC1E,CAAA;QACH,CAAC;KACF;IACD,KAAK;QACH,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,KAAK,MAAM,EAAE;YACpD,MAAM,KAAK,GAAG,yBAAiB,CAAC,QAAQ,EAAW,CAAA;YACnD,IAAI,KAAK,EAAE;gBACT,OAAO,KAAK,CAAA;aACb;SACF;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IACD,SAAS,EACP,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,aAAa;QAC1E,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,SAAS;CAChB,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACI,MAAM,UAAU,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AAA3D,QAAA,UAAU,cAAiD;AAEjE,MAAM,wBAAwB,GAAG,CACtC,GAAmB,EACnB,GAAiB,EACjB,IAA6B,EAC7B,EAAE;IACF,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,IAAA,mBAAU,GAAE,CAAA;IACrE,yBAAiB,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE;QAC3D,IAAI,EAAE,CAAA;IACR,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AATY,QAAA,wBAAwB,4BASpC;AAED,kFAAkF;AAClF,8DAA8D;AAC9D,SAAS,MAAM,CAAC,GAAQ,EAAE,UAA4B;IACpD,IAAI,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IACrC,UAAU,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,GAAG,YAAY,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IACF,OAAO,WAAW,CAAA;AACpB,CAAC"}