@decodo/mcp-server 1.2.6 → 1.3.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/build/auth/credential.js +4 -1
- package/build/auth/credential.js.map +1 -1
- package/build/clients/hosts.js +10 -0
- package/build/clients/hosts.js.map +1 -0
- package/build/clients/scraper-api-client.js +15 -5
- package/build/clients/scraper-api-client.js.map +1 -1
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/oauth/backend.js +3 -0
- package/build/oauth/backend.js.map +1 -0
- package/build/oauth/backends/decodo/index.js +71 -0
- package/build/oauth/backends/decodo/index.js.map +1 -0
- package/build/oauth/backends/decodo/request-jwt.js +62 -0
- package/build/oauth/backends/decodo/request-jwt.js.map +1 -0
- package/build/oauth/backends/decodo/token-exchange.js +88 -0
- package/build/oauth/backends/decodo/token-exchange.js.map +1 -0
- package/build/oauth/backends/mock/dashboard.js +84 -0
- package/build/oauth/backends/mock/dashboard.js.map +1 -0
- package/build/oauth/backends/mock/index.js +42 -0
- package/build/oauth/backends/mock/index.js.map +1 -0
- package/build/oauth/backends/mock/subscription-api.js +130 -0
- package/build/oauth/backends/mock/subscription-api.js.map +1 -0
- package/build/oauth/bounded-body.js +29 -0
- package/build/oauth/bounded-body.js.map +1 -0
- package/build/oauth/clients-store.js +142 -0
- package/build/oauth/clients-store.js.map +1 -0
- package/build/oauth/config.js +77 -0
- package/build/oauth/config.js.map +1 -0
- package/build/oauth/cookies.js +25 -0
- package/build/oauth/cookies.js.map +1 -0
- package/build/oauth/index.js +46 -0
- package/build/oauth/index.js.map +1 -0
- package/build/oauth/provider.js +172 -0
- package/build/oauth/provider.js.map +1 -0
- package/build/oauth/redirect-uris.js +17 -0
- package/build/oauth/redirect-uris.js.map +1 -0
- package/build/oauth/router.js +68 -0
- package/build/oauth/router.js.map +1 -0
- package/build/oauth/sealer.js +55 -0
- package/build/oauth/sealer.js.map +1 -0
- package/build/oauth/token-exchange.js +17 -0
- package/build/oauth/token-exchange.js.map +1 -0
- package/build/oauth/ttl-store.js +47 -0
- package/build/oauth/ttl-store.js.map +1 -0
- package/build/server/app.js +77 -0
- package/build/server/app.js.map +1 -0
- package/build/server/revoked-credentials.js +25 -0
- package/build/server/revoked-credentials.js.map +1 -0
- package/build/server/sapi-base-server.js +2 -2
- package/build/server/sapi-base-server.js.map +1 -1
- package/build/server/sapi-http-server.js +2 -2
- package/build/server/sapi-http-server.js.map +1 -1
- package/build/server/trust-proxy.js +19 -0
- package/build/server/trust-proxy.js.map +1 -0
- package/build/server.js +6 -44
- package/build/server.js.map +1 -1
- package/package.json +3 -9
package/build/auth/credential.js
CHANGED
|
@@ -21,7 +21,10 @@ const credentialFromAuthHeader = (header) => {
|
|
|
21
21
|
if (!scheme || !value || rest.length > 0) {
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
if (!TYPE_BY_SCHEME[scheme]) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
return toCredential((0, detect_credential_type_1.detectCredentialType)(value), value);
|
|
25
28
|
};
|
|
26
29
|
exports.credentialFromAuthHeader = credentialFromAuthHeader;
|
|
27
30
|
//# sourceMappingURL=credential.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../../src/auth/credential.ts"],"names":[],"mappings":";;;AAAA,2CAAqD;AACrD,qEAAgE;AAGhE,MAAM,cAAc,GAAyC;IAC3D,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,qBAAS,CAAC,KAAK;IACpC,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,qBAAS,CAAC,OAAO;CACxC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,IAA0B,EAAE,KAAa,EAA8B,EAAE;IAC7F,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC,CAAC;AAEK,MAAM,mBAAmB,GAAG,CAAC,KAAa,EAA8B,EAAE,CAC/E,YAAY,CAAC,IAAA,6CAAoB,EAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;AADtC,QAAA,mBAAmB,uBACmB;AAE5C,MAAM,wBAAwB,GAAG,CAAC,MAAc,EAA8B,EAAE;IACrF,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE5D,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,OAAO;IACT,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../../src/auth/credential.ts"],"names":[],"mappings":";;;AAAA,2CAAqD;AACrD,qEAAgE;AAGhE,MAAM,cAAc,GAAyC;IAC3D,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,qBAAS,CAAC,KAAK;IACpC,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,qBAAS,CAAC,OAAO;CACxC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,IAA0B,EAAE,KAAa,EAA8B,EAAE;IAC7F,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC,CAAC;AAEK,MAAM,mBAAmB,GAAG,CAAC,KAAa,EAA8B,EAAE,CAC/E,YAAY,CAAC,IAAA,6CAAoB,EAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;AADtC,QAAA,mBAAmB,uBACmB;AAE5C,MAAM,wBAAwB,GAAG,CAAC,MAAc,EAA8B,EAAE;IACrF,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE5D,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,OAAO,YAAY,CAAC,IAAA,6CAAoB,EAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;AAC1D,CAAC,CAAC;AAZW,QAAA,wBAAwB,4BAYnC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scrapingApiHostsFromEnv = void 0;
|
|
4
|
+
const hostFromEnv = (env, key) => { var _a; return ((_a = env[key]) === null || _a === void 0 ? void 0 : _a.trim()) || undefined; };
|
|
5
|
+
const scrapingApiHostsFromEnv = (env = process.env) => ({
|
|
6
|
+
scraperApi: hostFromEnv(env, 'DECODO_SAPI_HOST'),
|
|
7
|
+
dataApi: hostFromEnv(env, 'DECODO_DATA_API_HOST'),
|
|
8
|
+
});
|
|
9
|
+
exports.scrapingApiHostsFromEnv = scrapingApiHostsFromEnv;
|
|
10
|
+
//# sourceMappingURL=hosts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hosts.js","sourceRoot":"","sources":["../../src/clients/hosts.ts"],"names":[],"mappings":";;;AAOA,MAAM,WAAW,GAAG,CAAC,GAAQ,EAAE,GAAW,EAAsB,EAAE,WAAC,OAAA,CAAA,MAAA,GAAG,CAAC,GAAG,CAAC,0CAAE,IAAI,EAAE,KAAI,SAAS,CAAA,EAAA,CAAC;AAE1F,MAAM,uBAAuB,GAAG,CAAC,MAAW,OAAO,CAAC,GAAG,EAAoB,EAAE,CAAC,CAAC;IACpF,UAAU,EAAE,WAAW,CAAC,GAAG,EAAE,kBAAkB,CAAC;IAChD,OAAO,EAAE,WAAW,CAAC,GAAG,EAAE,sBAAsB,CAAC;CAClD,CAAC,CAAC;AAHU,QAAA,uBAAuB,2BAGjC"}
|
|
@@ -14,6 +14,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
14
14
|
exports.ScraperApiClient = void 0;
|
|
15
15
|
const sdk_ts_1 = require("@decodo/sdk-ts");
|
|
16
16
|
const auth_1 = require("../auth");
|
|
17
|
+
const hosts_1 = require("./hosts");
|
|
17
18
|
const utils_1 = require("../utils");
|
|
18
19
|
const logger_1 = require("../logger");
|
|
19
20
|
const retry_1 = require("./retry");
|
|
@@ -25,7 +26,7 @@ const API_PARAM_ALIASES = new Map([
|
|
|
25
26
|
['deliveryZip', 'delivery_zip'],
|
|
26
27
|
]);
|
|
27
28
|
class ScraperApiClient {
|
|
28
|
-
constructor({ maxRetries = retry_1.MAX_RETRIES, delayMs = retry_1.BASE_RETRY_DELAY_MS, } = {}) {
|
|
29
|
+
constructor({ maxRetries = retry_1.MAX_RETRIES, delayMs = retry_1.BASE_RETRY_DELAY_MS, onAuthenticationError, hosts = (0, hosts_1.scrapingApiHostsFromEnv)(), } = {}) {
|
|
29
30
|
this.transformScrapingParams = ({ scrapingParams, }) => {
|
|
30
31
|
var _a;
|
|
31
32
|
const { jsRender, headless, target } = scrapingParams, rest = __rest(scrapingParams, ["jsRender", "headless", "target"]);
|
|
@@ -45,11 +46,16 @@ class ScraperApiClient {
|
|
|
45
46
|
}
|
|
46
47
|
return { data: result.content };
|
|
47
48
|
};
|
|
48
|
-
this.sdkError = ({ error, target,
|
|
49
|
+
this.sdkError = ({ error, target, auth, startMs, }) => {
|
|
50
|
+
var _a;
|
|
49
51
|
const latencyMs = Date.now() - startMs;
|
|
52
|
+
const authType = auth.type;
|
|
50
53
|
const message = error instanceof Error ? error.message : String(error);
|
|
51
54
|
if (error instanceof sdk_ts_1.DecodoError) {
|
|
52
55
|
const sdkMessage = error instanceof sdk_ts_1.AuthenticationError ? 'Authentication failed.' : error.message;
|
|
56
|
+
if (error instanceof sdk_ts_1.AuthenticationError) {
|
|
57
|
+
(_a = this.onAuthenticationError) === null || _a === void 0 ? void 0 : _a.call(this, auth);
|
|
58
|
+
}
|
|
53
59
|
(0, logger_1.log)('error', 'tool_call', {
|
|
54
60
|
outcome: 'error',
|
|
55
61
|
target,
|
|
@@ -84,7 +90,9 @@ class ScraperApiClient {
|
|
|
84
90
|
});
|
|
85
91
|
return error;
|
|
86
92
|
};
|
|
87
|
-
this.
|
|
93
|
+
this.sdkTransport = (auth) => auth.type === auth_1.AUTH_TYPE.API_KEY
|
|
94
|
+
? { apiKey: auth.value, baseUrl: this.hosts.dataApi }
|
|
95
|
+
: { token: auth.value, baseUrl: this.hosts.scraperApi };
|
|
88
96
|
this.scrape = async ({ auth, scrapingParams, extra, }) => {
|
|
89
97
|
var _a, _b, _c, _d;
|
|
90
98
|
const notifier = new utils_1.ProgressNotifier(extra);
|
|
@@ -95,7 +103,7 @@ class ScraperApiClient {
|
|
|
95
103
|
const params = this.transformScrapingParams({ scrapingParams });
|
|
96
104
|
const { target } = params;
|
|
97
105
|
const { webScrapingApi } = new sdk_ts_1.DecodoClient({
|
|
98
|
-
webScrapingApi: Object.assign(Object.assign({}, this.
|
|
106
|
+
webScrapingApi: Object.assign(Object.assign({}, this.sdkTransport(auth)), { integrationHeader: INTEGRATION_HEADER }),
|
|
99
107
|
timeoutMs: REQUEST_TIMEOUT_MS,
|
|
100
108
|
});
|
|
101
109
|
let lastError;
|
|
@@ -138,7 +146,7 @@ class ScraperApiClient {
|
|
|
138
146
|
break;
|
|
139
147
|
}
|
|
140
148
|
}
|
|
141
|
-
throw this.sdkError({ error: lastError, target,
|
|
149
|
+
throw this.sdkError({ error: lastError, target, auth, startMs });
|
|
142
150
|
}
|
|
143
151
|
finally {
|
|
144
152
|
notifier.stopWaitingNotifications();
|
|
@@ -146,6 +154,8 @@ class ScraperApiClient {
|
|
|
146
154
|
};
|
|
147
155
|
this.maxRetries = maxRetries;
|
|
148
156
|
this.delayMs = delayMs;
|
|
157
|
+
this.onAuthenticationError = onAuthenticationError;
|
|
158
|
+
this.hosts = hosts;
|
|
149
159
|
}
|
|
150
160
|
}
|
|
151
161
|
exports.ScraperApiClient = ScraperApiClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scraper-api-client.js","sourceRoot":"","sources":["../../src/clients/scraper-api-client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,2CAMwB;AAGxB,kCAAoC;
|
|
1
|
+
{"version":3,"file":"scraper-api-client.js","sourceRoot":"","sources":["../../src/clients/scraper-api-client.ts"],"names":[],"mappings":"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"}
|
package/build/index.js
CHANGED
|
@@ -10,13 +10,13 @@ const parseEnvsOrExit = () => {
|
|
|
10
10
|
const envs = ['SCRAPER_API_TOKEN'];
|
|
11
11
|
for (const envKey of envs) {
|
|
12
12
|
if (!process.env[envKey]) {
|
|
13
|
-
console.error(`env ${envKey} missing`);
|
|
13
|
+
console.error(`env ${envKey} missing: set your API key or basic auth token`);
|
|
14
14
|
process.exit(1);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
const sapiAuth = (0, auth_1.credentialFromValue)(process.env['SCRAPER_API_TOKEN']);
|
|
18
18
|
if (!sapiAuth) {
|
|
19
|
-
console.error('env SCRAPER_API_TOKEN missing');
|
|
19
|
+
console.error('env SCRAPER_API_TOKEN missing: set your API key or basic auth token');
|
|
20
20
|
process.exit(1);
|
|
21
21
|
}
|
|
22
22
|
return { sapiAuth };
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yBAAuB;AAEvB,wEAAiF;AACjF,iCAA6C;AAC7C,kEAAmE;AACnE,mCAA0C;AAE1C,MAAM,eAAe,GAAG,GAAG,EAAE;IAC3B,MAAM,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAEnC,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,OAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yBAAuB;AAEvB,wEAAiF;AACjF,iCAA6C;AAC7C,kEAAmE;AACnE,mCAA0C;AAE1C,MAAM,eAAe,GAAG,GAAG,EAAE;IAC3B,MAAM,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAEnC,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,OAAO,MAAM,gDAAgD,CAAC,CAAC;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,IAAA,0BAAmB,EAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAW,CAAC,CAAC;IAEjF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;IACtB,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAE7C,4DAA4D;IAC5D,MAAM,EAAE,QAAQ,EAAE,GAAG,eAAe,EAAE,CAAC;IAEvC,MAAM,aAAa,GAAG,IAAI,yCAAqB,CAAC;QAC9C,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,IAAA,uBAAe,EAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;KAChD,CAAC,CAAC;IACH,MAAM,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEvC,OAAO,CAAC,KAAK,CAAC,sCAAsC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;AACxE,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/oauth/backend.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDecodoBackend = exports.DecodoBackend = exports.DASHBOARD_QUERY = void 0;
|
|
4
|
+
const errors_js_1 = require("@modelcontextprotocol/sdk/server/auth/errors.js");
|
|
5
|
+
const logger_1 = require("../../../logger");
|
|
6
|
+
const token_exchange_1 = require("../../token-exchange");
|
|
7
|
+
const request_jwt_1 = require("./request-jwt");
|
|
8
|
+
const token_exchange_2 = require("./token-exchange");
|
|
9
|
+
exports.DASHBOARD_QUERY = {
|
|
10
|
+
REQUEST_UUID: 'request_uuid',
|
|
11
|
+
};
|
|
12
|
+
class DecodoBackend {
|
|
13
|
+
constructor({ client, dashboardAuthorizeUrl, callbackUrl, issuer, fetch, }) {
|
|
14
|
+
this.client = client;
|
|
15
|
+
this.dashboardAuthorizeUrl = dashboardAuthorizeUrl;
|
|
16
|
+
this.callbackUrl = callbackUrl;
|
|
17
|
+
this.issuer = issuer;
|
|
18
|
+
this.tokenExchange = new token_exchange_2.HttpTokenExchange({ baseUrl: client.baseUrl, clientId: client.clientId, fetch });
|
|
19
|
+
if (client.privateKey && client.kid) {
|
|
20
|
+
this.privateKey = (0, request_jwt_1.parsePrivateKey)(client.privateKey);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
(0, logger_1.log)('warn', 'oauth.token_exchange_client_incomplete', {
|
|
24
|
+
message: 'TOKEN_EXCHANGE_PRIVATE_KEY and TOKEN_EXCHANGE_KID are required for sign-in',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async authorizationUrl({ state, codeChallenge }) {
|
|
29
|
+
if (!this.privateKey) {
|
|
30
|
+
throw new errors_js_1.ServerError('sign-in is not configured on this server');
|
|
31
|
+
}
|
|
32
|
+
const request = (0, request_jwt_1.signRequestJwt)({
|
|
33
|
+
privateKey: this.privateKey,
|
|
34
|
+
kid: this.client.kid,
|
|
35
|
+
claims: (0, request_jwt_1.requestJwtClaims)({
|
|
36
|
+
issuer: this.issuer,
|
|
37
|
+
clientId: this.client.clientId,
|
|
38
|
+
redirectUri: this.callbackUrl.href,
|
|
39
|
+
state,
|
|
40
|
+
codeChallenge,
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
let pending;
|
|
44
|
+
try {
|
|
45
|
+
pending = await this.tokenExchange.createRequest(request);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (error instanceof token_exchange_1.TokenExchangeError) {
|
|
49
|
+
(0, logger_1.log)('error', 'oauth.token_exchange.request_failed', { error: error.message });
|
|
50
|
+
throw new errors_js_1.ServerError('could not start sign-in with the Decodo backend');
|
|
51
|
+
}
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
const url = new URL(this.dashboardAuthorizeUrl);
|
|
55
|
+
url.searchParams.set(exports.DASHBOARD_QUERY.REQUEST_UUID, pending.uuid);
|
|
56
|
+
return url;
|
|
57
|
+
}
|
|
58
|
+
exchange(params) {
|
|
59
|
+
return this.tokenExchange.exchange(params);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.DecodoBackend = DecodoBackend;
|
|
63
|
+
const createDecodoBackend = (config, { callbackUrl, fetch }) => new DecodoBackend({
|
|
64
|
+
client: config.tokenExchange,
|
|
65
|
+
dashboardAuthorizeUrl: config.dashboardAuthorizeUrl,
|
|
66
|
+
callbackUrl,
|
|
67
|
+
issuer: config.publicUrl.host,
|
|
68
|
+
fetch,
|
|
69
|
+
});
|
|
70
|
+
exports.createDecodoBackend = createDecodoBackend;
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/oauth/backends/decodo/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verifyRequestJwt = exports.parsePrivateKey = exports.requestJwtClaims = exports.signRequestJwt = exports.REQUEST_JWT = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
exports.REQUEST_JWT = {
|
|
6
|
+
AUDIENCE: 'subscription-api',
|
|
7
|
+
SCOPE: 'sapi_token',
|
|
8
|
+
CODE_CHALLENGE_METHOD: 'S256',
|
|
9
|
+
LIFETIME_SECONDS: 120,
|
|
10
|
+
};
|
|
11
|
+
const base64url = (value) => Buffer.from(value).toString('base64url');
|
|
12
|
+
const signRequestJwt = ({ privateKey, kid, claims, }) => {
|
|
13
|
+
const header = { alg: 'RS256', typ: 'JWT', kid };
|
|
14
|
+
const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(claims))}`;
|
|
15
|
+
const signature = (0, node_crypto_1.sign)('sha256', Buffer.from(signingInput), privateKey);
|
|
16
|
+
return `${signingInput}.${base64url(signature)}`;
|
|
17
|
+
};
|
|
18
|
+
exports.signRequestJwt = signRequestJwt;
|
|
19
|
+
const requestJwtClaims = ({ issuer, clientId, redirectUri, state, codeChallenge, nowSeconds = Math.floor(Date.now() / 1000), }) => ({
|
|
20
|
+
iss: issuer,
|
|
21
|
+
aud: exports.REQUEST_JWT.AUDIENCE,
|
|
22
|
+
iat: nowSeconds,
|
|
23
|
+
exp: nowSeconds + exports.REQUEST_JWT.LIFETIME_SECONDS,
|
|
24
|
+
client_id: clientId,
|
|
25
|
+
redirect_uri: redirectUri,
|
|
26
|
+
state,
|
|
27
|
+
code_challenge: codeChallenge,
|
|
28
|
+
code_challenge_method: exports.REQUEST_JWT.CODE_CHALLENGE_METHOD,
|
|
29
|
+
scope: exports.REQUEST_JWT.SCOPE,
|
|
30
|
+
});
|
|
31
|
+
exports.requestJwtClaims = requestJwtClaims;
|
|
32
|
+
const parsePrivateKey = (pem) => {
|
|
33
|
+
try {
|
|
34
|
+
return (0, node_crypto_1.createPrivateKey)(pem);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
throw new Error(`TOKEN_EXCHANGE_PRIVATE_KEY is not a valid PEM private key: ${error.message}`, { cause: error });
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.parsePrivateKey = parsePrivateKey;
|
|
41
|
+
const verifyRequestJwt = (token, publicKey) => {
|
|
42
|
+
const [encodedHeader, encodedClaims, encodedSignature, ...rest] = token.split('.');
|
|
43
|
+
if (!encodedHeader || !encodedClaims || !encodedSignature || rest.length > 0) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const header = JSON.parse(Buffer.from(encodedHeader, 'base64url').toString('utf8'));
|
|
48
|
+
if (header.alg !== 'RS256') {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const valid = (0, node_crypto_1.verify)('sha256', Buffer.from(`${encodedHeader}.${encodedClaims}`), publicKey, Buffer.from(encodedSignature, 'base64url'));
|
|
52
|
+
if (!valid) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
return { header, claims: JSON.parse(Buffer.from(encodedClaims, 'base64url').toString('utf8')) };
|
|
56
|
+
}
|
|
57
|
+
catch (_a) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
exports.verifyRequestJwt = verifyRequestJwt;
|
|
62
|
+
//# sourceMappingURL=request-jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-jwt.js","sourceRoot":"","sources":["../../../../src/oauth/backends/decodo/request-jwt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpTokenExchange = void 0;
|
|
4
|
+
const token_exchange_1 = require("../../token-exchange");
|
|
5
|
+
const REQUEST_TIMEOUT_MS = 5000;
|
|
6
|
+
const STATUS_TO_ERROR = {
|
|
7
|
+
400: token_exchange_1.TOKEN_EXCHANGE_ERROR.INVALID_GRANT,
|
|
8
|
+
403: token_exchange_1.TOKEN_EXCHANGE_ERROR.INVALID_CLIENT,
|
|
9
|
+
};
|
|
10
|
+
const APP_CODES = new Set([token_exchange_1.TOKEN_EXCHANGE_ERROR.INVALID_GRANT, token_exchange_1.TOKEN_EXCHANGE_ERROR.INVALID_CLIENT]);
|
|
11
|
+
class HttpTokenExchange {
|
|
12
|
+
constructor({ baseUrl, clientId, fetch = globalThis.fetch }) {
|
|
13
|
+
const base = baseUrl.href.endsWith('/') ? baseUrl.href : `${baseUrl.href}/`;
|
|
14
|
+
this.requestUrl = new URL('request', base);
|
|
15
|
+
this.exchangeUrl = new URL('exchange', base);
|
|
16
|
+
this.clientId = clientId;
|
|
17
|
+
this.fetch = fetch;
|
|
18
|
+
}
|
|
19
|
+
async createRequest(requestJwt) {
|
|
20
|
+
const response = await this.post(this.requestUrl, { client_id: this.clientId, request: requestJwt });
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
throw new token_exchange_1.TokenExchangeError(token_exchange_1.TOKEN_EXCHANGE_ERROR.SERVER_ERROR, `token exchange request rejected with ${response.status}: ${await this.detail(response)}`);
|
|
23
|
+
}
|
|
24
|
+
const body = (await this.jsonBody(response));
|
|
25
|
+
if (typeof body.uuid !== 'string' || !body.uuid) {
|
|
26
|
+
throw new token_exchange_1.TokenExchangeError(token_exchange_1.TOKEN_EXCHANGE_ERROR.SERVER_ERROR, 'token exchange request response has no uuid');
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
uuid: body.uuid,
|
|
30
|
+
clientName: typeof body.client_name === 'string' ? body.client_name : '',
|
|
31
|
+
expiresAt: typeof body.expires_at === 'string' ? body.expires_at : '',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async exchange({ code, codeVerifier }) {
|
|
35
|
+
const response = await this.post(this.exchangeUrl, { client_id: this.clientId, code, code_verifier: codeVerifier });
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new token_exchange_1.TokenExchangeError(await this.errorCode(response), `token exchange responded with ${response.status}`);
|
|
38
|
+
}
|
|
39
|
+
const body = (await this.jsonBody(response));
|
|
40
|
+
if (typeof body.sapi_token !== 'string' || !body.sapi_token) {
|
|
41
|
+
throw new token_exchange_1.TokenExchangeError(token_exchange_1.TOKEN_EXCHANGE_ERROR.SERVER_ERROR, 'token exchange response has no sapi_token');
|
|
42
|
+
}
|
|
43
|
+
return body.sapi_token;
|
|
44
|
+
}
|
|
45
|
+
async post(url, body) {
|
|
46
|
+
try {
|
|
47
|
+
return await this.fetch(url, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
50
|
+
body: JSON.stringify(body),
|
|
51
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw new token_exchange_1.TokenExchangeError(token_exchange_1.TOKEN_EXCHANGE_ERROR.SERVER_ERROR, `token exchange call failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async jsonBody(response) {
|
|
59
|
+
try {
|
|
60
|
+
return await response.json();
|
|
61
|
+
}
|
|
62
|
+
catch (_a) {
|
|
63
|
+
throw new token_exchange_1.TokenExchangeError(token_exchange_1.TOKEN_EXCHANGE_ERROR.SERVER_ERROR, `token exchange responded ${response.status} with a non-JSON body`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async errorBody(response) {
|
|
67
|
+
try {
|
|
68
|
+
return (await response.json());
|
|
69
|
+
}
|
|
70
|
+
catch (_a) {
|
|
71
|
+
return {};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async detail(response) {
|
|
75
|
+
const body = await this.errorBody(response);
|
|
76
|
+
return typeof body.detail === 'string' ? body.detail : 'no detail';
|
|
77
|
+
}
|
|
78
|
+
async errorCode(response) {
|
|
79
|
+
var _a;
|
|
80
|
+
const body = await this.errorBody(response);
|
|
81
|
+
if (typeof body.app_code === 'string' && APP_CODES.has(body.app_code)) {
|
|
82
|
+
return body.app_code;
|
|
83
|
+
}
|
|
84
|
+
return (_a = STATUS_TO_ERROR[response.status]) !== null && _a !== void 0 ? _a : token_exchange_1.TOKEN_EXCHANGE_ERROR.SERVER_ERROR;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.HttpTokenExchange = HttpTokenExchange;
|
|
88
|
+
//# sourceMappingURL=token-exchange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-exchange.js","sourceRoot":"","sources":["../../../../src/oauth/backends/decodo/token-exchange.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
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.mockDashboardRouter = void 0;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const decodo_1 = require("../decodo");
|
|
9
|
+
const subscription_api_1 = require("./subscription-api");
|
|
10
|
+
const escapeHtml = (value) => value.replace(/[&<>"']/g, character => `&#${character.charCodeAt(0)};`);
|
|
11
|
+
const page = (body) => `<!doctype html>
|
|
12
|
+
<html lang="en">
|
|
13
|
+
<head>
|
|
14
|
+
<meta charset="utf-8">
|
|
15
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
16
|
+
<title>Decodo mock approval</title>
|
|
17
|
+
<style>
|
|
18
|
+
body { font-family: system-ui, sans-serif; max-width: 32rem; margin: 3rem auto; padding: 0 1rem; color: #1a1a1a; }
|
|
19
|
+
.banner { background: #fff3cd; border: 1px solid #ffe69c; padding: .75rem 1rem; border-radius: .5rem; margin-bottom: 1.5rem; }
|
|
20
|
+
label { display: block; margin: 1rem 0 .25rem; font-weight: 600; }
|
|
21
|
+
input { width: 100%; padding: .5rem; font: inherit; box-sizing: border-box; }
|
|
22
|
+
.actions { display: flex; gap: .75rem; margin-top: 1.5rem; }
|
|
23
|
+
button { padding: .6rem 1.2rem; font: inhe rit; border-radius: .4rem; border: 1px solid #999; background: #fff; cursor: pointer; }
|
|
24
|
+
button[value=approve] { background: #1a1a1a; color: #fff; border-color: #1a1a1a; }
|
|
25
|
+
</style>
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
${body}
|
|
29
|
+
</body>
|
|
30
|
+
</html>`;
|
|
31
|
+
const mockDashboardRouter = ({ api, defaultScraperApiKey, }) => {
|
|
32
|
+
const router = express_1.default.Router();
|
|
33
|
+
router.use(express_1.default.urlencoded({ extended: false }));
|
|
34
|
+
router.get('/authorize', (req, res) => {
|
|
35
|
+
const uuid = req.query[decodo_1.DASHBOARD_QUERY.REQUEST_UUID];
|
|
36
|
+
const pending = typeof uuid === 'string' ? api.pendingRequest(uuid) : undefined;
|
|
37
|
+
if (!pending) {
|
|
38
|
+
res.status(400).send(page('<h1>Invalid request</h1><p>This connection request is unknown or has expired.</p>'));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
res.status(200).send(page(`
|
|
42
|
+
<div class="banner">Mock consent page. The real one lives on dashboard.decodo.com.</div>
|
|
43
|
+
<h1>Allow <strong>${escapeHtml(pending.client_id)}</strong> to use your Scraping API key?</h1>
|
|
44
|
+
<form method="post" action="authorize/decision">
|
|
45
|
+
<input type="hidden" name="request_uuid" value="${escapeHtml(pending.uuid)}">
|
|
46
|
+
<label for="scraper_api_key">Scraping API key to release</label>
|
|
47
|
+
<input id="scraper_api_key" name="scraper_api_key" value="${escapeHtml(defaultScraperApiKey)}" placeholder="Paste a real key to make the tools work">
|
|
48
|
+
<div class="actions">
|
|
49
|
+
<button type="submit" name="decision" value="approve">Approve</button>
|
|
50
|
+
<button type="submit" name="decision" value="deny">Deny</button>
|
|
51
|
+
</div>
|
|
52
|
+
</form>`));
|
|
53
|
+
});
|
|
54
|
+
router.post('/authorize/decision', (req, res) => {
|
|
55
|
+
var _a;
|
|
56
|
+
const { request_uuid: uuid, decision, scraper_api_key: scraperApiKey } = (_a = req.body) !== null && _a !== void 0 ? _a : {};
|
|
57
|
+
if (typeof uuid !== 'string' || typeof decision !== 'string') {
|
|
58
|
+
res.status(400).send(page('<h1>Bad request</h1><p>Missing request_uuid or decision.</p>'));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const key = typeof scraperApiKey === 'string' && scraperApiKey.trim() ? scraperApiKey.trim() : defaultScraperApiKey;
|
|
62
|
+
let decided;
|
|
63
|
+
try {
|
|
64
|
+
decided = api.decide({ uuid, decision, scraperApiKey: key });
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
const detail = error instanceof subscription_api_1.MockRequestError ? error.message : 'unexpected error';
|
|
68
|
+
res.status(409).send(page(`<h1>Request can no longer be decided</h1><p>${escapeHtml(detail)}</p>`));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const redirect = new URL(decided.redirectUri);
|
|
72
|
+
redirect.searchParams.set('state', decided.state);
|
|
73
|
+
if (decided.code) {
|
|
74
|
+
redirect.searchParams.set('code', decided.code);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
redirect.searchParams.set('error', decided.error);
|
|
78
|
+
}
|
|
79
|
+
res.redirect(302, redirect.href);
|
|
80
|
+
});
|
|
81
|
+
return router;
|
|
82
|
+
};
|
|
83
|
+
exports.mockDashboardRouter = mockDashboardRouter;
|
|
84
|
+
//# sourceMappingURL=dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../../../src/oauth/backends/mock/dashboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
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.createMockBackend = exports.MOCK_PATH = void 0;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const express_1 = __importDefault(require("express"));
|
|
9
|
+
const logger_1 = require("../../../logger");
|
|
10
|
+
const decodo_1 = require("../decodo");
|
|
11
|
+
const dashboard_1 = require("./dashboard");
|
|
12
|
+
const subscription_api_1 = require("./subscription-api");
|
|
13
|
+
exports.MOCK_PATH = '/mock';
|
|
14
|
+
const MOCK_CLIENT = { clientId: 'mcp-mock', kid: 'mock-key' };
|
|
15
|
+
const createMockBackend = (config, { callbackUrl, fetch }) => {
|
|
16
|
+
const { privateKey, publicKey } = (0, node_crypto_1.generateKeyPairSync)('rsa', {
|
|
17
|
+
modulusLength: 2048,
|
|
18
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
|
|
19
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
20
|
+
});
|
|
21
|
+
const dashboardAuthorizeUrl = new URL(`${exports.MOCK_PATH}/dashboard/authorize`, config.publicUrl);
|
|
22
|
+
const baseUrl = new URL(`${exports.MOCK_PATH}/subscription-api/token-exchange`, config.publicUrl);
|
|
23
|
+
const api = new subscription_api_1.MockSubscriptionApi((0, node_crypto_1.createPublicKey)(publicKey), Object.assign(Object.assign({}, MOCK_CLIENT), { redirectUri: callbackUrl.href }));
|
|
24
|
+
const router = express_1.default.Router();
|
|
25
|
+
router.use(`${exports.MOCK_PATH}/dashboard`, (0, dashboard_1.mockDashboardRouter)({ api, defaultScraperApiKey: config.mockScraperApiKey }));
|
|
26
|
+
router.use(`${exports.MOCK_PATH}/subscription-api`, (0, subscription_api_1.mockSubscriptionApiRouter)(api));
|
|
27
|
+
const backend = new decodo_1.DecodoBackend({
|
|
28
|
+
client: Object.assign(Object.assign({}, MOCK_CLIENT), { privateKey, baseUrl }),
|
|
29
|
+
dashboardAuthorizeUrl,
|
|
30
|
+
callbackUrl,
|
|
31
|
+
issuer: config.publicUrl.host,
|
|
32
|
+
fetch,
|
|
33
|
+
});
|
|
34
|
+
(0, logger_1.log)('warn', 'oauth.mock_backend', { dashboardAuthorizeUrl: dashboardAuthorizeUrl.href });
|
|
35
|
+
return {
|
|
36
|
+
authorizationUrl: authorization => backend.authorizationUrl(authorization),
|
|
37
|
+
exchange: params => backend.exchange(params),
|
|
38
|
+
router,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
exports.createMockBackend = createMockBackend;
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/oauth/backends/mock/index.ts"],"names":[],"mappings":";;;;;;AAAA,6CAAmE;AACnE,sDAA8B;AAC9B,4CAAsC;AAEtC,sCAA0C;AAC1C,2CAAkD;AAClD,yDAAoF;AAEvE,QAAA,SAAS,GAAG,OAAO,CAAC;AAEjC,MAAM,WAAW,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;AAEvD,MAAM,iBAAiB,GAAwB,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE;IACvF,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAA,iCAAmB,EAAC,KAAK,EAAE;QAC3D,aAAa,EAAE,IAAI;QACnB,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;QACpD,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;KACnD,CAAC,CAAC;IAEH,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,GAAG,iBAAS,sBAAsB,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC5F,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,iBAAS,kCAAkC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAE1F,MAAM,GAAG,GAAG,IAAI,sCAAmB,CAAC,IAAA,6BAAe,EAAC,SAAS,CAAC,kCAAO,WAAW,KAAE,WAAW,EAAE,WAAW,CAAC,IAAI,IAAG,CAAC;IAEnH,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;IAChC,MAAM,CAAC,GAAG,CAAC,GAAG,iBAAS,YAAY,EAAE,IAAA,+BAAmB,EAAC,EAAE,GAAG,EAAE,oBAAoB,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;IACnH,MAAM,CAAC,GAAG,CAAC,GAAG,iBAAS,mBAAmB,EAAE,IAAA,4CAAyB,EAAC,GAAG,CAAC,CAAC,CAAC;IAE5E,MAAM,OAAO,GAAG,IAAI,sBAAa,CAAC;QAChC,MAAM,kCAAO,WAAW,KAAE,UAAU,EAAE,OAAO,GAAE;QAC/C,qBAAqB;QACrB,WAAW;QACX,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI;QAC7B,KAAK;KACN,CAAC,CAAC;IAEH,IAAA,YAAG,EAAC,MAAM,EAAE,oBAAoB,EAAE,EAAE,qBAAqB,EAAE,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC;IAEzF,OAAO;QACL,gBAAgB,EAAE,aAAa,CAAC,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,aAAa,CAAC;QAC1E,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC5C,MAAM;KACP,CAAC;AACJ,CAAC,CAAC;AA/BW,QAAA,iBAAiB,qBA+B5B"}
|