@sonisoft/now-sdk-ext-core 5.0.1 → 5.2.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/dist/PublicApi.d.ts +8 -0
- package/dist/PublicApi.js +7 -0
- package/dist/PublicApi.js.map +1 -1
- package/dist/auth/NowSDKAuthenticationHandler.js +17 -3
- package/dist/auth/NowSDKAuthenticationHandler.js.map +1 -1
- package/dist/comm/http/IRequestHandler.d.ts +20 -1
- package/dist/comm/http/RequestHandler.d.ts +31 -1
- package/dist/comm/http/RequestHandler.js +90 -5
- package/dist/comm/http/RequestHandler.js.map +1 -1
- package/dist/comm/http/ServiceNowRequest.d.ts +2 -0
- package/dist/comm/http/ServiceNowRequest.js +9 -0
- package/dist/comm/http/ServiceNowRequest.js.map +1 -1
- package/dist/comm/http/SessionManager.d.ts +10 -0
- package/dist/comm/http/SessionManager.js +43 -1
- package/dist/comm/http/SessionManager.js.map +1 -1
- package/dist/credentials/ensureShim.d.ts +34 -0
- package/dist/credentials/ensureShim.js +71 -0
- package/dist/credentials/ensureShim.js.map +1 -0
- package/dist/exception/StaleInstanceError.d.ts +50 -0
- package/dist/exception/StaleInstanceError.js +63 -0
- package/dist/exception/StaleInstanceError.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/sn/BackgroundScriptExecutor.js +4 -1
- package/dist/sn/BackgroundScriptExecutor.js.map +1 -1
- package/dist/sn/IServiceNowInstance.d.ts +10 -0
- package/dist/sn/SNRequestBase.d.ts +13 -0
- package/dist/sn/SNRequestBase.js +17 -0
- package/dist/sn/SNRequestBase.js.map +1 -1
- package/dist/sn/ServiceNowInstance.d.ts +9 -0
- package/dist/sn/ServiceNowInstance.js +25 -0
- package/dist/sn/ServiceNowInstance.js.map +1 -1
- package/dist/util/Logger.d.ts +13 -0
- package/dist/util/Logger.js +30 -1
- package/dist/util/Logger.js.map +1 -1
- package/dist/util/redact.d.ts +47 -0
- package/dist/util/redact.js +228 -0
- package/dist/util/redact.js.map +1 -0
- package/package.json +4 -1
package/dist/PublicApi.d.ts
CHANGED
|
@@ -41,3 +41,11 @@ export { MessageClientBuilder } from './sn/amb/MessageClientBuilder.js';
|
|
|
41
41
|
export type { SubscriptionCollection, Context } from './sn/amb/MessageClientBuilder.js';
|
|
42
42
|
export { Channel } from './sn/amb/Channel.js';
|
|
43
43
|
export { ChannelListener } from './sn/amb/ChannelListener.js';
|
|
44
|
+
/**
|
|
45
|
+
* Not in the generated barrel, on purpose. ctix exports whatever a directory's
|
|
46
|
+
* index.ts re-exports, and a credentials/index.ts would make importing this
|
|
47
|
+
* library enough to monkeypatch the SDK's credential storage. Installing the
|
|
48
|
+
* shim has to stay an explicit call.
|
|
49
|
+
*/
|
|
50
|
+
export { initCredentialStore } from './credentials/ensureShim.js';
|
|
51
|
+
export type { InitCredentialStoreResult } from './credentials/ensureShim.js';
|
package/dist/PublicApi.js
CHANGED
|
@@ -43,4 +43,11 @@ export { AMBClient } from './sn/amb/AMBClient.js';
|
|
|
43
43
|
export { MessageClientBuilder } from './sn/amb/MessageClientBuilder.js';
|
|
44
44
|
export { Channel } from './sn/amb/Channel.js';
|
|
45
45
|
export { ChannelListener } from './sn/amb/ChannelListener.js';
|
|
46
|
+
/**
|
|
47
|
+
* Not in the generated barrel, on purpose. ctix exports whatever a directory's
|
|
48
|
+
* index.ts re-exports, and a credentials/index.ts would make importing this
|
|
49
|
+
* library enough to monkeypatch the SDK's credential storage. Installing the
|
|
50
|
+
* shim has to stay an explicit call.
|
|
51
|
+
*/
|
|
52
|
+
export { initCredentialStore } from './credentials/ensureShim.js';
|
|
46
53
|
//# sourceMappingURL=PublicApi.js.map
|
package/dist/PublicApi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublicApi.js","sourceRoot":"","sources":["../src/PublicApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,+EAA+E;AAC/E,0EAA0E;AAC1E,qCAAqC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAExE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"PublicApi.js","sourceRoot":"","sources":["../src/PublicApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,+EAA+E;AAC/E,0EAA0E;AAC1E,qCAAqC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAExE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D;;;;;GAKG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Logger } from "../util/Logger.js";
|
|
2
2
|
import { getSafeUserSession } from "@servicenow/sdk-cli-core/dist/util/sessionToken.js";
|
|
3
|
+
import { stripSecretsFromError } from "../util/redact.js";
|
|
3
4
|
export class NowSDKAuthenticationHandler {
|
|
4
5
|
_requestHandler;
|
|
5
6
|
_isLoggedIn = false;
|
|
@@ -20,7 +21,16 @@ export class NowSDKAuthenticationHandler {
|
|
|
20
21
|
const auth = { credentials: this._instance.credential };
|
|
21
22
|
const session = await getSafeUserSession(auth, this._logger);
|
|
22
23
|
if (session) {
|
|
23
|
-
this
|
|
24
|
+
// Recording WHICH instance this session was minted for is the whole
|
|
25
|
+
// point: RequestHandler compares it against the instance it is bound to
|
|
26
|
+
// before every dispatch, which is where a mismatch is actually caught.
|
|
27
|
+
//
|
|
28
|
+
// There is deliberately no re-check of this._instance across the await.
|
|
29
|
+
// It is assigned once in the constructor and never reassigned, and
|
|
30
|
+
// AuthenticationHandlerFactory builds a fresh handler per instance, so
|
|
31
|
+
// such a check could not fire — it would only imply a protection that
|
|
32
|
+
// does not exist here.
|
|
33
|
+
this._requestHandler.setSession(session, this._instance);
|
|
24
34
|
this.setLoggedIn(true);
|
|
25
35
|
}
|
|
26
36
|
else {
|
|
@@ -30,8 +40,12 @@ export class NowSDKAuthenticationHandler {
|
|
|
30
40
|
return session;
|
|
31
41
|
}
|
|
32
42
|
catch (e) {
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
// Of every error in the codebase this is the one most likely to be carrying
|
|
44
|
+
// the credential it just failed to use, and it propagates out to consumers
|
|
45
|
+
// whose loggers have no redaction format of their own.
|
|
46
|
+
const safe = stripSecretsFromError(e);
|
|
47
|
+
this._logger.error("Error during login.", safe);
|
|
48
|
+
throw safe;
|
|
35
49
|
}
|
|
36
50
|
return null;
|
|
37
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NowSDKAuthenticationHandler.js","sourceRoot":"","sources":["../../src/auth/NowSDKAuthenticationHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAKxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;
|
|
1
|
+
{"version":3,"file":"NowSDKAuthenticationHandler.js","sourceRoot":"","sources":["../../src/auth/NowSDKAuthenticationHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAKxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGvD,MAAM,OAAO,2BAA2B;IAE5B,eAAe,CAAiB;IAEhC,WAAW,GAAW,KAAK,CAAC;IAE5B,QAAQ,CAAS;IAEjB,OAAO,CAAQ;IAEf,SAAS,CAAoB;IAErC,YAAmB,QAA2B;QAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,MAAM,CAAC,6BAA6B,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAEM,KAAK,CAAC,OAAO;QAChB,MAAM,OAAO,GAAY,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAC5C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAExB,OAAO,OAAO,CAAC;IACnB,CAAC;IAEO,KAAK,CAAC,KAAK;QAEf,IAAG,CAAC;YACA,MAAM,IAAI,GAAG,EAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAC,CAAC;YACtD,MAAM,OAAO,GAAa,MAAM,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACvE,IAAG,OAAO,EAAC,CAAC;gBACR,oEAAoE;gBACpE,wEAAwE;gBACxE,uEAAuE;gBACvE,EAAE;gBACF,wEAAwE;gBACxE,mEAAmE;gBACnE,uEAAuE;gBACvE,sEAAsE;gBACtE,uBAAuB;gBACvB,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBACzD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;iBAAI,CAAC;gBACF,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;YACxC,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC9C,OAAO,OAAO,CAAC;QACnB,CAAC;QAAA,OAAM,CAAC,EAAC,CAAC;YACN,4EAA4E;YAC5E,2EAA2E;YAC3E,uDAAuD;YACvD,MAAM,IAAI,GAAY,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;YAChD,MAAM,IAAI,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,iBAAiB;QACpB,OAAO,IAAI,CAAC,eAAe,CAAC;IAChC,CAAC;IAEM,iBAAiB,CAAC,cAA8B;QACnD,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;IAC1C,CAAC;IAEM,UAAU;QACb,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAEM,WAAW,CAAC,QAAgB;QAC/B,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC;IAChC,CAAC;IAEM,QAAQ;QACX,6DAA6D;QAC7D,OAAQ,IAAI,CAAC,QAAgB,CAAC,QAAQ,EAAY,CAAC;IACvD,CAAC;IAEM,UAAU;QACb,kGAAkG;QAClG,OAAQ,IAAI,CAAC,QAAgB,CAAC,UAAU,EAAE,CAAC;IAC/C,CAAC;IAEM,UAAU;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;CACJ"}
|
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
import { HTTPRequest } from "./HTTPRequest.js";
|
|
2
2
|
import { IHttpResponse } from "./IHttpResponse.js";
|
|
3
|
+
import { IServiceNowInstance } from "../../sn/IServiceNowInstance.js";
|
|
3
4
|
export interface IRequestHandler {
|
|
4
5
|
post<T>(request: HTTPRequest): Promise<IHttpResponse<T>>;
|
|
5
6
|
put<T>(request: HTTPRequest): Promise<IHttpResponse<T>>;
|
|
6
7
|
get<T>(request: HTTPRequest): Promise<IHttpResponse<T>>;
|
|
7
8
|
delete<T>(request: HTTPRequest): Promise<IHttpResponse<T>>;
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Records the session to use for outgoing requests, together with the instance
|
|
11
|
+
* it was minted for.
|
|
12
|
+
*
|
|
13
|
+
* `instance` is optional so existing callers keep compiling, but omitting it
|
|
14
|
+
* disables the cross-instance guard for this handler — pass it wherever the
|
|
15
|
+
* owning instance is known.
|
|
16
|
+
*/
|
|
17
|
+
setSession(session: any, instance?: IServiceNowInstance): any;
|
|
18
|
+
/**
|
|
19
|
+
* Declares which instance this handler serves. Set once, at construction.
|
|
20
|
+
* A session recorded for any other instance will be refused at dispatch.
|
|
21
|
+
*
|
|
22
|
+
* Optional so that adding it is not a breaking change for anyone implementing
|
|
23
|
+
* this interface outside the repo. A handler that does not implement it simply
|
|
24
|
+
* has no bound identity, and the dispatch guard stays permissive — the same
|
|
25
|
+
* behaviour as a handler built without an instance.
|
|
26
|
+
*/
|
|
27
|
+
bindInstance?(instance: IServiceNowInstance): any;
|
|
9
28
|
}
|
|
@@ -5,18 +5,48 @@ import { Cookie } from 'tough-cookie';
|
|
|
5
5
|
import { ICookieStore } from './ICookieStore.js';
|
|
6
6
|
import { IAuthenticationHandler } from '../../auth/IAuthenticationHandler.js';
|
|
7
7
|
import { Logger } from '../../util/Logger.js';
|
|
8
|
+
import { IServiceNowInstance } from '../../sn/IServiceNowInstance.js';
|
|
8
9
|
export declare class RequestHandler implements IRequestHandler {
|
|
9
10
|
_logger: Logger;
|
|
10
11
|
_cookies: Cookie[];
|
|
11
12
|
_cookieStore: ICookieStore;
|
|
12
13
|
_authHandler: IAuthenticationHandler;
|
|
13
14
|
_session: any;
|
|
15
|
+
/** Identity of the instance this handler serves. Set once, at construction. */
|
|
16
|
+
private _boundInstanceId;
|
|
17
|
+
/** Identity of the instance the current `_session` was minted for. Written with the session. */
|
|
18
|
+
private _sessionInstanceId;
|
|
14
19
|
/**
|
|
15
20
|
* The Singleton's constructor should always be private to prevent direct
|
|
16
21
|
* construction calls with the `new` operator.
|
|
17
22
|
*/
|
|
18
23
|
constructor(authHandler: IAuthenticationHandler);
|
|
19
|
-
setSession(session: any): void;
|
|
24
|
+
setSession(session: any, instance?: IServiceNowInstance): void;
|
|
25
|
+
bindInstance(instance: IServiceNowInstance): void;
|
|
26
|
+
/**
|
|
27
|
+
* Refuses to build a request whose session belongs to a different instance.
|
|
28
|
+
*
|
|
29
|
+
* Placed immediately before `this._session` is read into the outgoing config,
|
|
30
|
+
* because that is the one point every request passes through — both the
|
|
31
|
+
* SessionManager-managed handlers and the ~21 managers that construct their own
|
|
32
|
+
* ServiceNowRequest and never touch SessionManager at all.
|
|
33
|
+
*
|
|
34
|
+
* Permissive when either side is unknown. A handler built without an instance
|
|
35
|
+
* (ATFTestExecutor does this, then immediately replaces it) or a session set by
|
|
36
|
+
* a caller that predates the second parameter would otherwise start throwing on
|
|
37
|
+
* a path that was never actually unsafe.
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* Prepares a caught value for rethrowing.
|
|
41
|
+
*
|
|
42
|
+
* The original error is preserved rather than wrapped: `new Error(ex)` stringified
|
|
43
|
+
* the cause, discarded the stack, and flattened typed errors so `instanceof` failed
|
|
44
|
+
* at every call site — which would make StaleInstanceError unidentifiable. Secrets
|
|
45
|
+
* are stripped first, because the consumer's logger has no redaction format of its
|
|
46
|
+
* own.
|
|
47
|
+
*/
|
|
48
|
+
private toThrowable;
|
|
49
|
+
private assertSessionMatchesBoundInstance;
|
|
20
50
|
isValidXmlString(xmlString: any): boolean;
|
|
21
51
|
private doRequest;
|
|
22
52
|
post<T>(request: HTTPRequest): Promise<IHttpResponse<T>>;
|
|
@@ -2,6 +2,8 @@ import { HttpResponse } from './HttpResponse.js';
|
|
|
2
2
|
import { Logger } from '../../util/Logger.js';
|
|
3
3
|
import { makeRequest } from "@servicenow/sdk-cli-core/dist/http/index.js";
|
|
4
4
|
import { DOMParser } from '@xmldom/xmldom';
|
|
5
|
+
import { StaleInstanceError } from '../../exception/StaleInstanceError.js';
|
|
6
|
+
import { stripSecretsFromError, redactValue } from '../../util/redact.js';
|
|
5
7
|
//axios.defaults.withCredentials = true;
|
|
6
8
|
export class RequestHandler {
|
|
7
9
|
_logger = new Logger("RequestHandler");
|
|
@@ -11,6 +13,10 @@ export class RequestHandler {
|
|
|
11
13
|
_cookieStore;
|
|
12
14
|
_authHandler;
|
|
13
15
|
_session;
|
|
16
|
+
/** Identity of the instance this handler serves. Set once, at construction. */
|
|
17
|
+
_boundInstanceId;
|
|
18
|
+
/** Identity of the instance the current `_session` was minted for. Written with the session. */
|
|
19
|
+
_sessionInstanceId;
|
|
14
20
|
/**
|
|
15
21
|
* The Singleton's constructor should always be private to prevent direct
|
|
16
22
|
* construction calls with the `new` operator.
|
|
@@ -27,8 +33,83 @@ export class RequestHandler {
|
|
|
27
33
|
// });
|
|
28
34
|
// this.httpClient.defaults.maxRedirects = 0;
|
|
29
35
|
}
|
|
30
|
-
setSession(session) {
|
|
36
|
+
setSession(session, instance) {
|
|
37
|
+
const previous = this._sessionInstanceId;
|
|
31
38
|
this._session = session;
|
|
39
|
+
// Deliberately reset to undefined when no instance is supplied: the session
|
|
40
|
+
// changed and we no longer know whose it is, so the guard must go permissive
|
|
41
|
+
// rather than keep asserting against the previous owner's id.
|
|
42
|
+
this._sessionInstanceId = instance?.getInstanceId?.();
|
|
43
|
+
// Going from known to unknown silently disables the cross-instance guard for
|
|
44
|
+
// this handler. `instance` is optional and easy to forget, so say so out loud
|
|
45
|
+
// rather than only at debug level from inside the assertion.
|
|
46
|
+
if (previous !== undefined && this._sessionInstanceId === undefined) {
|
|
47
|
+
this._logger.warn("Session replaced without an owning instance; the cross-instance guard is now inactive for this handler.", { previousSessionInstanceId: previous });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
bindInstance(instance) {
|
|
51
|
+
this._boundInstanceId = instance?.getInstanceId?.();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Refuses to build a request whose session belongs to a different instance.
|
|
55
|
+
*
|
|
56
|
+
* Placed immediately before `this._session` is read into the outgoing config,
|
|
57
|
+
* because that is the one point every request passes through — both the
|
|
58
|
+
* SessionManager-managed handlers and the ~21 managers that construct their own
|
|
59
|
+
* ServiceNowRequest and never touch SessionManager at all.
|
|
60
|
+
*
|
|
61
|
+
* Permissive when either side is unknown. A handler built without an instance
|
|
62
|
+
* (ATFTestExecutor does this, then immediately replaces it) or a session set by
|
|
63
|
+
* a caller that predates the second parameter would otherwise start throwing on
|
|
64
|
+
* a path that was never actually unsafe.
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Prepares a caught value for rethrowing.
|
|
68
|
+
*
|
|
69
|
+
* The original error is preserved rather than wrapped: `new Error(ex)` stringified
|
|
70
|
+
* the cause, discarded the stack, and flattened typed errors so `instanceof` failed
|
|
71
|
+
* at every call site — which would make StaleInstanceError unidentifiable. Secrets
|
|
72
|
+
* are stripped first, because the consumer's logger has no redaction format of its
|
|
73
|
+
* own.
|
|
74
|
+
*/
|
|
75
|
+
toThrowable(ex) {
|
|
76
|
+
if (ex instanceof Error) {
|
|
77
|
+
return stripSecretsFromError(ex);
|
|
78
|
+
}
|
|
79
|
+
// A thrown non-Error still has to be described, and String() on an object
|
|
80
|
+
// yields "[object Object]" — useless in a log. Redact before serializing,
|
|
81
|
+
// since a thrown plain object can carry credentials just as easily.
|
|
82
|
+
if (typeof ex === "string") {
|
|
83
|
+
return new Error(ex);
|
|
84
|
+
}
|
|
85
|
+
// `Object.prototype.toString.call` is typed as returning `any`; the cast keeps
|
|
86
|
+
// the type-checked lint rules satisfied without loosening anything real.
|
|
87
|
+
const fallback = Object.prototype.toString.call(ex);
|
|
88
|
+
let described;
|
|
89
|
+
try {
|
|
90
|
+
described = JSON.stringify(redactValue(ex)) ?? fallback;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Cycles and throwing getters are already handled inside redactValue, but
|
|
94
|
+
// a hostile toJSON can still break stringify.
|
|
95
|
+
described = fallback;
|
|
96
|
+
}
|
|
97
|
+
return new Error(described);
|
|
98
|
+
}
|
|
99
|
+
assertSessionMatchesBoundInstance() {
|
|
100
|
+
const bound = this._boundInstanceId;
|
|
101
|
+
const forSession = this._sessionInstanceId;
|
|
102
|
+
if (bound === undefined || forSession === undefined) {
|
|
103
|
+
this._logger.debug("Instance binding not asserted; identity unknown on one side.", {
|
|
104
|
+
boundInstanceId: bound,
|
|
105
|
+
sessionInstanceId: forSession,
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (bound !== forSession) {
|
|
110
|
+
throw new StaleInstanceError(`Refusing to send a request for instance #${bound} using a session minted for instance #${forSession}.`, "The connection was replaced while this request was in flight. Retry the operation; " +
|
|
111
|
+
"a fresh session will be established for the correct instance.");
|
|
112
|
+
}
|
|
32
113
|
}
|
|
33
114
|
// public async request(config:AxiosRequestConfig):Promise<AxiosResponse<any,any>>{
|
|
34
115
|
// for(var prop in this._defaultHeaders){
|
|
@@ -147,7 +228,7 @@ export class RequestHandler {
|
|
|
147
228
|
}
|
|
148
229
|
catch (ex) {
|
|
149
230
|
this._logger.error("Error during POST request.", { error: ex, response: response, request: request });
|
|
150
|
-
throw
|
|
231
|
+
throw this.toThrowable(ex);
|
|
151
232
|
}
|
|
152
233
|
}
|
|
153
234
|
async put(request) {
|
|
@@ -169,7 +250,7 @@ export class RequestHandler {
|
|
|
169
250
|
}
|
|
170
251
|
catch (ex) {
|
|
171
252
|
this._logger.error("Error during PUT request.", { error: ex, response: response, request: request });
|
|
172
|
-
throw
|
|
253
|
+
throw this.toThrowable(ex);
|
|
173
254
|
}
|
|
174
255
|
}
|
|
175
256
|
async get(request) {
|
|
@@ -191,7 +272,7 @@ export class RequestHandler {
|
|
|
191
272
|
}
|
|
192
273
|
catch (ex) {
|
|
193
274
|
this._logger.error("Error during GET request.", { error: ex, response: response, request: request });
|
|
194
|
-
throw
|
|
275
|
+
throw this.toThrowable(ex);
|
|
195
276
|
}
|
|
196
277
|
}
|
|
197
278
|
async delete(request) {
|
|
@@ -212,10 +293,14 @@ export class RequestHandler {
|
|
|
212
293
|
}
|
|
213
294
|
catch (ex) {
|
|
214
295
|
this._logger.error("Error during DELETE request.", { error: ex, response: response, request: request });
|
|
215
|
-
throw
|
|
296
|
+
throw this.toThrowable(ex);
|
|
216
297
|
}
|
|
217
298
|
}
|
|
218
299
|
async getRequestConfig(request) {
|
|
300
|
+
// Before the session is bound into the request. makeRequest derives the
|
|
301
|
+
// destination host from auth.instanceUrl, so a mismatch here does not send a
|
|
302
|
+
// bad cookie to the right host — it sends a valid session to the wrong one.
|
|
303
|
+
this.assertSessionMatchesBoundInstance();
|
|
219
304
|
const config = {
|
|
220
305
|
auth: this._session,
|
|
221
306
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestHandler.js","sourceRoot":"","sources":["../../../src/comm/http/RequestHandler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAK9C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,wCAAwC;AAExC,MAAM,OAAO,cAAc;IAEvB,OAAO,GAAU,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC9C,yCAAyC;IACzC,2BAA2B;IAC3B,QAAQ,CAAW;IAEnB,YAAY,CAAc;IAC1B,YAAY,CAAwB;IAEpC,QAAQ,CAAM;IAEd;;;OAGG;IACH,YAAmB,WAAkC;QACjD,sDAAsD;QACvD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAE/B,gDAAgD;QAChD,2DAA2D;QAC3D,oCAAoC;QACpC,mCAAmC;QACnC,6BAA6B;QAC7B,2EAA2E;QAC3E,QAAQ;QAER,6CAA6C;IAEhD,CAAC;IAIK,UAAU,CAAC,OAAY;
|
|
1
|
+
{"version":3,"file":"RequestHandler.js","sourceRoot":"","sources":["../../../src/comm/http/RequestHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ export declare class ServiceNowRequest {
|
|
|
8
8
|
auth: IAuthenticationHandler;
|
|
9
9
|
private _instance;
|
|
10
10
|
constructor(instance?: ServiceNowInstance);
|
|
11
|
+
/** The instance this request is bound to. Fixed at construction. */
|
|
12
|
+
getInstance(): ServiceNowInstance;
|
|
11
13
|
executeRequest<T>(request: HTTPRequest): Promise<IHttpResponse<T>>;
|
|
12
14
|
put<T>(request: HTTPRequest): Promise<IHttpResponse<T>>;
|
|
13
15
|
post<T>(request: HTTPRequest): Promise<IHttpResponse<T>>;
|
|
@@ -12,6 +12,15 @@ export class ServiceNowRequest {
|
|
|
12
12
|
this.auth = AuthenticationHandlerFactory.createAuthHandler(this._instance);
|
|
13
13
|
this._requestHandler = RequestHandlerFactory.createRequestHandler(this.auth);
|
|
14
14
|
this.auth.setRequestHandler(this._requestHandler);
|
|
15
|
+
// Declare which instance this handler serves, so a session minted for any
|
|
16
|
+
// other instance is refused before it reaches the wire.
|
|
17
|
+
if (this._instance) {
|
|
18
|
+
this._requestHandler.bindInstance?.(this._instance);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** The instance this request is bound to. Fixed at construction. */
|
|
22
|
+
getInstance() {
|
|
23
|
+
return this._instance;
|
|
15
24
|
}
|
|
16
25
|
async executeRequest(request) {
|
|
17
26
|
let httpMethod = request.method;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceNowRequest.js","sourceRoot":"","sources":["../../../src/comm/http/ServiceNowRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AAMvF,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,MAAM,OAAO,iBAAiB;IAE1B,eAAe,CAAiB;IAChC,IAAI,CAAwB;IAEpB,SAAS,CAAoB;IAErC,YAAmB,WAA8B,IAAI;QAClD,qCAAqC;QAEpC,IAAI,QAAQ,EAAE,CAAC;YACX,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3E,IAAI,CAAC,eAAe,GAAG,qBAAqB,CAAC,oBAAoB,CAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ServiceNowRequest.js","sourceRoot":"","sources":["../../../src/comm/http/ServiceNowRequest.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,16 @@ export declare class SessionManager {
|
|
|
18
18
|
* Keyed by alias (falls back to host).
|
|
19
19
|
*/
|
|
20
20
|
getRequest(instance: ServiceNowInstance): ServiceNowRequest;
|
|
21
|
+
/**
|
|
22
|
+
* True when the cached request was built for exactly this instance.
|
|
23
|
+
*
|
|
24
|
+
* Answers "leave the cache alone" whenever identity cannot be established on
|
|
25
|
+
* either side — a request built without an instance, or a caller passing a
|
|
26
|
+
* duck-typed instance that predates getInstanceId(). Evicting on unknown
|
|
27
|
+
* identity would throw away a good session and force a fresh login on every
|
|
28
|
+
* single lookup, which is a worse failure than the one being guarded against.
|
|
29
|
+
*/
|
|
30
|
+
private isBoundTo;
|
|
21
31
|
/**
|
|
22
32
|
* Get or create a ServiceNowRequest and ensure it is authenticated.
|
|
23
33
|
* Uses an in-flight promise guard to prevent duplicate concurrent auth calls.
|
|
@@ -27,6 +27,17 @@ export class SessionManager {
|
|
|
27
27
|
getRequest(instance) {
|
|
28
28
|
const key = this.getKey(instance);
|
|
29
29
|
let request = this._sessions.get(key);
|
|
30
|
+
// The key is alias-or-host, which says nothing about *which* ServiceNowInstance
|
|
31
|
+
// object asked. A consumer that rebuilds its connection — now-sdk-ext-mcp evicts
|
|
32
|
+
// on a 30-minute TTL — passes a new instance under the same alias and would
|
|
33
|
+
// otherwise be handed the previous one's request, still holding the previous
|
|
34
|
+
// session. Recreate instead: this is recoverable, so self-heal rather than throw.
|
|
35
|
+
if (request && !this.isBoundTo(request, instance)) {
|
|
36
|
+
this._logger.debug(`Instance replaced for alias: ${key}; discarding the cached session.`);
|
|
37
|
+
this._sessions.delete(key);
|
|
38
|
+
this._authPromises.delete(key);
|
|
39
|
+
request = undefined;
|
|
40
|
+
}
|
|
30
41
|
if (!request) {
|
|
31
42
|
this._logger.debug(`Creating new session for alias: ${key}`);
|
|
32
43
|
request = new ServiceNowRequest(instance);
|
|
@@ -34,6 +45,27 @@ export class SessionManager {
|
|
|
34
45
|
}
|
|
35
46
|
return request;
|
|
36
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* True when the cached request was built for exactly this instance.
|
|
50
|
+
*
|
|
51
|
+
* Answers "leave the cache alone" whenever identity cannot be established on
|
|
52
|
+
* either side — a request built without an instance, or a caller passing a
|
|
53
|
+
* duck-typed instance that predates getInstanceId(). Evicting on unknown
|
|
54
|
+
* identity would throw away a good session and force a fresh login on every
|
|
55
|
+
* single lookup, which is a worse failure than the one being guarded against.
|
|
56
|
+
*/
|
|
57
|
+
isBoundTo(request, instance) {
|
|
58
|
+
const bound = request.getInstance?.();
|
|
59
|
+
if (!bound) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
const boundId = bound.getInstanceId?.();
|
|
63
|
+
const requestedId = instance?.getInstanceId?.();
|
|
64
|
+
if (boundId === undefined || requestedId === undefined) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return boundId === requestedId;
|
|
68
|
+
}
|
|
37
69
|
/**
|
|
38
70
|
* Get or create a ServiceNowRequest and ensure it is authenticated.
|
|
39
71
|
* Uses an in-flight promise guard to prevent duplicate concurrent auth calls.
|
|
@@ -56,7 +88,13 @@ export class SessionManager {
|
|
|
56
88
|
return request;
|
|
57
89
|
}
|
|
58
90
|
finally {
|
|
59
|
-
this
|
|
91
|
+
// Only clear our own entry. An instance swap on this alias evicts the
|
|
92
|
+
// map and a fresh caller can install a NEW promise under the same key
|
|
93
|
+
// while this one is still settling — an unconditional delete would
|
|
94
|
+
// remove theirs, costing a duplicate login.
|
|
95
|
+
if (this._authPromises.get(key) === authPromise) {
|
|
96
|
+
this._authPromises.delete(key);
|
|
97
|
+
}
|
|
60
98
|
}
|
|
61
99
|
})();
|
|
62
100
|
this._authPromises.set(key, authPromise);
|
|
@@ -68,6 +106,9 @@ export class SessionManager {
|
|
|
68
106
|
clearSession(alias) {
|
|
69
107
|
this._logger.debug(`Clearing session for alias: ${alias}`);
|
|
70
108
|
this._sessions.delete(alias);
|
|
109
|
+
// An auth started before the clear would otherwise resolve after it and hand
|
|
110
|
+
// the caller the request we just evicted.
|
|
111
|
+
this._authPromises.delete(alias);
|
|
71
112
|
}
|
|
72
113
|
/**
|
|
73
114
|
* Remove all cached sessions.
|
|
@@ -75,6 +116,7 @@ export class SessionManager {
|
|
|
75
116
|
clearAll() {
|
|
76
117
|
this._logger.debug(`Clearing all ${this._sessions.size} sessions`);
|
|
77
118
|
this._sessions.clear();
|
|
119
|
+
this._authPromises.clear();
|
|
78
120
|
}
|
|
79
121
|
/**
|
|
80
122
|
* Check if a session exists for a given alias.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../../src/comm/http/SessionManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C;;;GAGG;AACH,MAAM,OAAO,cAAc;IAEf,MAAM,CAAC,SAAS,GAA0B,IAAI,CAAC;IAC/C,SAAS,GAAmC,IAAI,GAAG,EAAE,CAAC;IACtD,aAAa,GAA4C,IAAI,GAAG,EAAE,CAAC;IACnE,OAAO,GAAW,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAEvD,gBAAuB,CAAC;IAExB,MAAM,CAAC,WAAW;QACd,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;YAC5B,cAAc,CAAC,SAAS,GAAG,IAAI,cAAc,EAAE,CAAC;QACpD,CAAC;QACD,OAAO,cAAc,CAAC,SAAS,CAAC;IACpC,CAAC;IAED,sEAAsE;IACtE,MAAM,CAAC,aAAa;QAChB,cAAc,CAAC,SAAS,GAAG,IAAI,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,QAA4B;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../../src/comm/http/SessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in headless credential storage for library consumers.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately NOT a module side effect and NOT in the ctix-generated barrel:
|
|
5
|
+
* `import { anything } from '@sonisoft/now-sdk-ext-core'` must never monkeypatch
|
|
6
|
+
* the ServiceNow SDK's credential storage as a consequence. A consumer that
|
|
7
|
+
* wants the shim asks for it by calling this.
|
|
8
|
+
*
|
|
9
|
+
* Applications that own their entry point (nex, the MCP server) import
|
|
10
|
+
* '@sonisoft/sn-credstore/register' there instead — earlier, and unconditional.
|
|
11
|
+
* This exists for embedders that do not control process startup.
|
|
12
|
+
*/
|
|
13
|
+
export interface InitCredentialStoreResult {
|
|
14
|
+
/** True once the SDK's KeyChain is reading the headless-safe store. */
|
|
15
|
+
active: boolean;
|
|
16
|
+
/** Why it is not active, when it is not. */
|
|
17
|
+
reason?: 'not-installed' | 'disabled';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Point the ServiceNow SDK's credential storage at a headless-safe store.
|
|
21
|
+
*
|
|
22
|
+
* Non-interactive sessions cannot unlock the OS keyring even as the same user,
|
|
23
|
+
* and `KeyChain.getPassword()` swallows that failure and returns null — so the
|
|
24
|
+
* SDK reports "Default Credential has not been set" rather than a keyring error.
|
|
25
|
+
*
|
|
26
|
+
* Idempotent, and safe to call when @sonisoft/sn-credstore is not installed: it
|
|
27
|
+
* reports `active: false` and leaves the SDK on its default keyring path. Callers
|
|
28
|
+
* that require the store should check the result rather than assume success.
|
|
29
|
+
*
|
|
30
|
+
* Throws only when the shim IS installed and fails to apply — continuing then
|
|
31
|
+
* would silently fall back to the keyring, and the SDK's next credential write
|
|
32
|
+
* reseeds from a failed read, wiping every other alias.
|
|
33
|
+
*/
|
|
34
|
+
export declare function initCredentialStore(): Promise<InitCredentialStoreResult>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in headless credential storage for library consumers.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately NOT a module side effect and NOT in the ctix-generated barrel:
|
|
5
|
+
* `import { anything } from '@sonisoft/now-sdk-ext-core'` must never monkeypatch
|
|
6
|
+
* the ServiceNow SDK's credential storage as a consequence. A consumer that
|
|
7
|
+
* wants the shim asks for it by calling this.
|
|
8
|
+
*
|
|
9
|
+
* Applications that own their entry point (nex, the MCP server) import
|
|
10
|
+
* '@sonisoft/sn-credstore/register' there instead — earlier, and unconditional.
|
|
11
|
+
* This exists for embedders that do not control process startup.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Absence is legitimate. A shim that loads and then fails is not.
|
|
15
|
+
*
|
|
16
|
+
* sn-credstore is an OPTIONAL dependency of this package, because core is a
|
|
17
|
+
* library: making it required would force a credential shim onto every consumer,
|
|
18
|
+
* including ones that never call initCredentialStore(). So it can genuinely be
|
|
19
|
+
* missing — `npm install --no-optional`, a pruned install, a bundler that dropped
|
|
20
|
+
* it — and that must degrade rather than throw.
|
|
21
|
+
*/
|
|
22
|
+
function isNotInstalled(error) {
|
|
23
|
+
const err = error;
|
|
24
|
+
return (err?.code === 'ERR_MODULE_NOT_FOUND' &&
|
|
25
|
+
// Only OUR specifier missing means "not installed". The same code from a
|
|
26
|
+
// broken import *inside* sn-credstore means it is installed and broken,
|
|
27
|
+
// which must not be mistaken for absence.
|
|
28
|
+
/@sonisoft[/\\]sn-credstore/.test(String(err.message)));
|
|
29
|
+
}
|
|
30
|
+
let cached;
|
|
31
|
+
/**
|
|
32
|
+
* Point the ServiceNow SDK's credential storage at a headless-safe store.
|
|
33
|
+
*
|
|
34
|
+
* Non-interactive sessions cannot unlock the OS keyring even as the same user,
|
|
35
|
+
* and `KeyChain.getPassword()` swallows that failure and returns null — so the
|
|
36
|
+
* SDK reports "Default Credential has not been set" rather than a keyring error.
|
|
37
|
+
*
|
|
38
|
+
* Idempotent, and safe to call when @sonisoft/sn-credstore is not installed: it
|
|
39
|
+
* reports `active: false` and leaves the SDK on its default keyring path. Callers
|
|
40
|
+
* that require the store should check the result rather than assume success.
|
|
41
|
+
*
|
|
42
|
+
* Throws only when the shim IS installed and fails to apply — continuing then
|
|
43
|
+
* would silently fall back to the keyring, and the SDK's next credential write
|
|
44
|
+
* reseeds from a failed read, wiping every other alias.
|
|
45
|
+
*/
|
|
46
|
+
export async function initCredentialStore() {
|
|
47
|
+
if (cached)
|
|
48
|
+
return cached;
|
|
49
|
+
if (process.env.SN_CRED_STORE_DISABLE) {
|
|
50
|
+
cached = { active: false, reason: 'disabled' };
|
|
51
|
+
return cached;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
// Held in a variable so TypeScript does not try to resolve it. This
|
|
55
|
+
// package still compiles with moduleResolution "node", which predates and
|
|
56
|
+
// ignores `exports` maps, so a literal specifier for the ./register
|
|
57
|
+
// subpath fails to type-check even though Node resolves it correctly at
|
|
58
|
+
// runtime. Switching core to Node16 resolution would fix it properly, but
|
|
59
|
+
// that is a change with a much wider blast radius than this file.
|
|
60
|
+
const specifier = '@sonisoft/sn-credstore/register';
|
|
61
|
+
await import(specifier);
|
|
62
|
+
cached = { active: true };
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (!isNotInstalled(error))
|
|
66
|
+
throw error;
|
|
67
|
+
cached = { active: false, reason: 'not-installed' };
|
|
68
|
+
}
|
|
69
|
+
return cached;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=ensureShim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensureShim.js","sourceRoot":"","sources":["../../src/credentials/ensureShim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;GAQG;AACH,SAAS,cAAc,CAAC,KAAc;IAClC,MAAM,GAAG,GAAG,KAA0C,CAAC;IACvD,OAAO,CACH,GAAG,EAAE,IAAI,KAAK,sBAAsB;QACpC,yEAAyE;QACzE,wEAAwE;QACxE,0CAA0C;QAC1C,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CACzD,CAAC;AACN,CAAC;AASD,IAAI,MAA6C,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACrC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACpC,MAAM,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAC/C,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACD,oEAAoE;QACpE,0EAA0E;QAC1E,oEAAoE;QACpE,wEAAwE;QACxE,0EAA0E;QAC1E,kEAAkE;QAClE,MAAM,SAAS,GAAG,iCAAiC,CAAC;QACpD,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;QACxB,MAAM,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;QACxC,MAAM,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IACxD,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
|