lexmount 0.2.6 → 0.5.1
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/index.d.mts +79 -2
- package/dist/index.d.ts +79 -2
- package/dist/index.js +202 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +202 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -106,6 +106,12 @@ interface LexmountConfig {
|
|
|
106
106
|
* Defaults to `https://api.lexmount.cn`.
|
|
107
107
|
*/
|
|
108
108
|
baseUrl?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Region ID to select from the public endpoint catalog.
|
|
111
|
+
*
|
|
112
|
+
* If omitted, the SDK uses the catalog default region when available.
|
|
113
|
+
*/
|
|
114
|
+
region?: string;
|
|
109
115
|
/**
|
|
110
116
|
* Request timeout in milliseconds.
|
|
111
117
|
*
|
|
@@ -117,6 +123,30 @@ interface LexmountConfig {
|
|
|
117
123
|
*/
|
|
118
124
|
logLevel?: LogLevel;
|
|
119
125
|
}
|
|
126
|
+
interface RegionCatalogEntry {
|
|
127
|
+
region_id: string;
|
|
128
|
+
display_name?: string;
|
|
129
|
+
default?: boolean;
|
|
130
|
+
host: string;
|
|
131
|
+
tags?: string[];
|
|
132
|
+
probe_path?: string;
|
|
133
|
+
}
|
|
134
|
+
interface RegionInfo {
|
|
135
|
+
requestedRegion?: string;
|
|
136
|
+
selectedRegion?: string;
|
|
137
|
+
baseUrl: string;
|
|
138
|
+
endpointBaseUrl?: string;
|
|
139
|
+
host?: string;
|
|
140
|
+
resolved: boolean;
|
|
141
|
+
usingRegion: boolean;
|
|
142
|
+
}
|
|
143
|
+
interface CatalogInfo {
|
|
144
|
+
baseUrl: string;
|
|
145
|
+
available: boolean;
|
|
146
|
+
statusCode?: number;
|
|
147
|
+
regions: RegionCatalogEntry[];
|
|
148
|
+
error?: string;
|
|
149
|
+
}
|
|
120
150
|
/**
|
|
121
151
|
* Session creation options.
|
|
122
152
|
*/
|
|
@@ -269,6 +299,19 @@ interface SessionDownloadsDeleteResponseShape {
|
|
|
269
299
|
status: string;
|
|
270
300
|
deletedCount: number;
|
|
271
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* Session target metadata returned by `/json`.
|
|
304
|
+
*/
|
|
305
|
+
interface SessionTargetInfoShape {
|
|
306
|
+
id: string;
|
|
307
|
+
title: string;
|
|
308
|
+
type: string;
|
|
309
|
+
url: string;
|
|
310
|
+
description: string;
|
|
311
|
+
inspectUrl: string | null;
|
|
312
|
+
webSocketDebuggerUrl: string | null;
|
|
313
|
+
webSocketDebuggerUrlTransformed: string | null;
|
|
314
|
+
}
|
|
272
315
|
/**
|
|
273
316
|
* Session pagination metadata.
|
|
274
317
|
*/
|
|
@@ -482,6 +525,20 @@ declare class SessionDownloadsDeleteResponse implements SessionDownloadsDeleteRe
|
|
|
482
525
|
readonly deletedCount: number;
|
|
483
526
|
constructor(shape: SessionDownloadsDeleteResponseShape);
|
|
484
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Session target metadata returned by `/json`.
|
|
530
|
+
*/
|
|
531
|
+
declare class SessionTargetInfo implements SessionTargetInfoShape {
|
|
532
|
+
readonly id: string;
|
|
533
|
+
readonly title: string;
|
|
534
|
+
readonly type: string;
|
|
535
|
+
readonly url: string;
|
|
536
|
+
readonly description: string;
|
|
537
|
+
readonly inspectUrl: string | null;
|
|
538
|
+
readonly webSocketDebuggerUrl: string | null;
|
|
539
|
+
readonly webSocketDebuggerUrlTransformed: string | null;
|
|
540
|
+
constructor(shape: SessionTargetInfoShape);
|
|
541
|
+
}
|
|
485
542
|
/**
|
|
486
543
|
* Session download operations.
|
|
487
544
|
*/
|
|
@@ -524,6 +581,10 @@ declare class SessionsResource {
|
|
|
524
581
|
* Delete a browser session.
|
|
525
582
|
*/
|
|
526
583
|
delete(options: SessionDeleteOptions): Promise<void>;
|
|
584
|
+
/**
|
|
585
|
+
* List target/page metadata for a session via `/json`.
|
|
586
|
+
*/
|
|
587
|
+
listTargets(sessionId: string): Promise<SessionTargetInfo[]>;
|
|
527
588
|
/**
|
|
528
589
|
* Fetch the debugger WebSocket URL for a session.
|
|
529
590
|
*
|
|
@@ -534,8 +595,10 @@ declare class SessionsResource {
|
|
|
534
595
|
private handleCreateError;
|
|
535
596
|
private handleGetError;
|
|
536
597
|
private handleListError;
|
|
598
|
+
private handleListTargetsError;
|
|
537
599
|
private handleDeleteError;
|
|
538
600
|
private mapSessionInfo;
|
|
601
|
+
private mapSessionTarget;
|
|
539
602
|
private _getCreatedSession;
|
|
540
603
|
}
|
|
541
604
|
|
|
@@ -559,6 +622,12 @@ declare class Lexmount {
|
|
|
559
622
|
* API base URL.
|
|
560
623
|
*/
|
|
561
624
|
readonly baseUrl: string;
|
|
625
|
+
readonly region?: string;
|
|
626
|
+
selectedRegion?: string;
|
|
627
|
+
private endpointBaseUrl?;
|
|
628
|
+
private selectedHost?;
|
|
629
|
+
private regionResolutionAttempted;
|
|
630
|
+
private regionResolutionPromise?;
|
|
562
631
|
/**
|
|
563
632
|
* Session operations.
|
|
564
633
|
*/
|
|
@@ -591,6 +660,8 @@ declare class Lexmount {
|
|
|
591
660
|
* @internal
|
|
592
661
|
*/
|
|
593
662
|
_delete<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
663
|
+
regionInfo(): Promise<RegionInfo>;
|
|
664
|
+
catalogInfo(): Promise<CatalogInfo>;
|
|
594
665
|
/**
|
|
595
666
|
* Close the client.
|
|
596
667
|
*
|
|
@@ -604,6 +675,12 @@ declare class Lexmount {
|
|
|
604
675
|
private request;
|
|
605
676
|
private normalizeRequestError;
|
|
606
677
|
private getDefaultHeaders;
|
|
678
|
+
private ensureRegionResolved;
|
|
679
|
+
private resolveRegion;
|
|
680
|
+
private selectCatalogRegion;
|
|
681
|
+
private probeRegionHost;
|
|
682
|
+
private isAllowedCatalogHost;
|
|
683
|
+
private rewriteUrl;
|
|
607
684
|
}
|
|
608
685
|
|
|
609
686
|
/**
|
|
@@ -671,6 +748,6 @@ declare class TimeoutError extends LexmountError {
|
|
|
671
748
|
/**
|
|
672
749
|
* Lexmount Node.js SDK.
|
|
673
750
|
*/
|
|
674
|
-
declare const VERSION = "0.
|
|
751
|
+
declare const VERSION = "0.5.1";
|
|
675
752
|
|
|
676
|
-
export { APIError, AuthenticationError, type BrowserMode, type ContextAccessMode, type ContextCreateOptions, ContextInfo, type ContextListOptions, ContextListResponse, ContextLockedError, type ContextMetadata, ContextNotFoundError, type ContextStatus, ContextsResource, ExtensionInfo, type ExtensionInfoShape, type ExtensionListOptions, type ExtensionUploadOptions, ExtensionsResource, type ForceReleaseResponse, Lexmount, type LexmountConfig, LexmountError, LexmountLogger, type LogLevel, NetworkError, PaginationInfo, type PaginationInfoShape, type SessionContext, type SessionCreateOptions, type SessionCreateResponse, type SessionDeleteOptions, SessionDownloadInfo, type SessionDownloadInfoShape, SessionDownloadsDeleteResponse, type SessionDownloadsDeleteResponseShape, SessionDownloadsListResponse, type SessionDownloadsListResponseShape, SessionDownloadsResource, SessionInfo, type SessionListOptions, SessionListResponse, SessionNotFoundError, type SessionProxyConfig, type SessionStatus, SessionsResource, TimeoutError, VERSION, ValidationError, Lexmount as default, disableLogging, enableLogging, getLogger, setLogLevel };
|
|
753
|
+
export { APIError, AuthenticationError, type BrowserMode, type CatalogInfo, type ContextAccessMode, type ContextCreateOptions, ContextInfo, type ContextListOptions, ContextListResponse, ContextLockedError, type ContextMetadata, ContextNotFoundError, type ContextStatus, ContextsResource, ExtensionInfo, type ExtensionInfoShape, type ExtensionListOptions, type ExtensionUploadOptions, ExtensionsResource, type ForceReleaseResponse, Lexmount, type LexmountConfig, LexmountError, LexmountLogger, type LogLevel, NetworkError, PaginationInfo, type PaginationInfoShape, type RegionCatalogEntry, type RegionInfo, type SessionContext, type SessionCreateOptions, type SessionCreateResponse, type SessionDeleteOptions, SessionDownloadInfo, type SessionDownloadInfoShape, SessionDownloadsDeleteResponse, type SessionDownloadsDeleteResponseShape, SessionDownloadsListResponse, type SessionDownloadsListResponseShape, SessionDownloadsResource, SessionInfo, type SessionListOptions, SessionListResponse, SessionNotFoundError, type SessionProxyConfig, type SessionStatus, SessionTargetInfo, type SessionTargetInfoShape, SessionsResource, TimeoutError, VERSION, ValidationError, Lexmount as default, disableLogging, enableLogging, getLogger, setLogLevel };
|
package/dist/index.d.ts
CHANGED
|
@@ -106,6 +106,12 @@ interface LexmountConfig {
|
|
|
106
106
|
* Defaults to `https://api.lexmount.cn`.
|
|
107
107
|
*/
|
|
108
108
|
baseUrl?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Region ID to select from the public endpoint catalog.
|
|
111
|
+
*
|
|
112
|
+
* If omitted, the SDK uses the catalog default region when available.
|
|
113
|
+
*/
|
|
114
|
+
region?: string;
|
|
109
115
|
/**
|
|
110
116
|
* Request timeout in milliseconds.
|
|
111
117
|
*
|
|
@@ -117,6 +123,30 @@ interface LexmountConfig {
|
|
|
117
123
|
*/
|
|
118
124
|
logLevel?: LogLevel;
|
|
119
125
|
}
|
|
126
|
+
interface RegionCatalogEntry {
|
|
127
|
+
region_id: string;
|
|
128
|
+
display_name?: string;
|
|
129
|
+
default?: boolean;
|
|
130
|
+
host: string;
|
|
131
|
+
tags?: string[];
|
|
132
|
+
probe_path?: string;
|
|
133
|
+
}
|
|
134
|
+
interface RegionInfo {
|
|
135
|
+
requestedRegion?: string;
|
|
136
|
+
selectedRegion?: string;
|
|
137
|
+
baseUrl: string;
|
|
138
|
+
endpointBaseUrl?: string;
|
|
139
|
+
host?: string;
|
|
140
|
+
resolved: boolean;
|
|
141
|
+
usingRegion: boolean;
|
|
142
|
+
}
|
|
143
|
+
interface CatalogInfo {
|
|
144
|
+
baseUrl: string;
|
|
145
|
+
available: boolean;
|
|
146
|
+
statusCode?: number;
|
|
147
|
+
regions: RegionCatalogEntry[];
|
|
148
|
+
error?: string;
|
|
149
|
+
}
|
|
120
150
|
/**
|
|
121
151
|
* Session creation options.
|
|
122
152
|
*/
|
|
@@ -269,6 +299,19 @@ interface SessionDownloadsDeleteResponseShape {
|
|
|
269
299
|
status: string;
|
|
270
300
|
deletedCount: number;
|
|
271
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* Session target metadata returned by `/json`.
|
|
304
|
+
*/
|
|
305
|
+
interface SessionTargetInfoShape {
|
|
306
|
+
id: string;
|
|
307
|
+
title: string;
|
|
308
|
+
type: string;
|
|
309
|
+
url: string;
|
|
310
|
+
description: string;
|
|
311
|
+
inspectUrl: string | null;
|
|
312
|
+
webSocketDebuggerUrl: string | null;
|
|
313
|
+
webSocketDebuggerUrlTransformed: string | null;
|
|
314
|
+
}
|
|
272
315
|
/**
|
|
273
316
|
* Session pagination metadata.
|
|
274
317
|
*/
|
|
@@ -482,6 +525,20 @@ declare class SessionDownloadsDeleteResponse implements SessionDownloadsDeleteRe
|
|
|
482
525
|
readonly deletedCount: number;
|
|
483
526
|
constructor(shape: SessionDownloadsDeleteResponseShape);
|
|
484
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Session target metadata returned by `/json`.
|
|
530
|
+
*/
|
|
531
|
+
declare class SessionTargetInfo implements SessionTargetInfoShape {
|
|
532
|
+
readonly id: string;
|
|
533
|
+
readonly title: string;
|
|
534
|
+
readonly type: string;
|
|
535
|
+
readonly url: string;
|
|
536
|
+
readonly description: string;
|
|
537
|
+
readonly inspectUrl: string | null;
|
|
538
|
+
readonly webSocketDebuggerUrl: string | null;
|
|
539
|
+
readonly webSocketDebuggerUrlTransformed: string | null;
|
|
540
|
+
constructor(shape: SessionTargetInfoShape);
|
|
541
|
+
}
|
|
485
542
|
/**
|
|
486
543
|
* Session download operations.
|
|
487
544
|
*/
|
|
@@ -524,6 +581,10 @@ declare class SessionsResource {
|
|
|
524
581
|
* Delete a browser session.
|
|
525
582
|
*/
|
|
526
583
|
delete(options: SessionDeleteOptions): Promise<void>;
|
|
584
|
+
/**
|
|
585
|
+
* List target/page metadata for a session via `/json`.
|
|
586
|
+
*/
|
|
587
|
+
listTargets(sessionId: string): Promise<SessionTargetInfo[]>;
|
|
527
588
|
/**
|
|
528
589
|
* Fetch the debugger WebSocket URL for a session.
|
|
529
590
|
*
|
|
@@ -534,8 +595,10 @@ declare class SessionsResource {
|
|
|
534
595
|
private handleCreateError;
|
|
535
596
|
private handleGetError;
|
|
536
597
|
private handleListError;
|
|
598
|
+
private handleListTargetsError;
|
|
537
599
|
private handleDeleteError;
|
|
538
600
|
private mapSessionInfo;
|
|
601
|
+
private mapSessionTarget;
|
|
539
602
|
private _getCreatedSession;
|
|
540
603
|
}
|
|
541
604
|
|
|
@@ -559,6 +622,12 @@ declare class Lexmount {
|
|
|
559
622
|
* API base URL.
|
|
560
623
|
*/
|
|
561
624
|
readonly baseUrl: string;
|
|
625
|
+
readonly region?: string;
|
|
626
|
+
selectedRegion?: string;
|
|
627
|
+
private endpointBaseUrl?;
|
|
628
|
+
private selectedHost?;
|
|
629
|
+
private regionResolutionAttempted;
|
|
630
|
+
private regionResolutionPromise?;
|
|
562
631
|
/**
|
|
563
632
|
* Session operations.
|
|
564
633
|
*/
|
|
@@ -591,6 +660,8 @@ declare class Lexmount {
|
|
|
591
660
|
* @internal
|
|
592
661
|
*/
|
|
593
662
|
_delete<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
|
|
663
|
+
regionInfo(): Promise<RegionInfo>;
|
|
664
|
+
catalogInfo(): Promise<CatalogInfo>;
|
|
594
665
|
/**
|
|
595
666
|
* Close the client.
|
|
596
667
|
*
|
|
@@ -604,6 +675,12 @@ declare class Lexmount {
|
|
|
604
675
|
private request;
|
|
605
676
|
private normalizeRequestError;
|
|
606
677
|
private getDefaultHeaders;
|
|
678
|
+
private ensureRegionResolved;
|
|
679
|
+
private resolveRegion;
|
|
680
|
+
private selectCatalogRegion;
|
|
681
|
+
private probeRegionHost;
|
|
682
|
+
private isAllowedCatalogHost;
|
|
683
|
+
private rewriteUrl;
|
|
607
684
|
}
|
|
608
685
|
|
|
609
686
|
/**
|
|
@@ -671,6 +748,6 @@ declare class TimeoutError extends LexmountError {
|
|
|
671
748
|
/**
|
|
672
749
|
* Lexmount Node.js SDK.
|
|
673
750
|
*/
|
|
674
|
-
declare const VERSION = "0.
|
|
751
|
+
declare const VERSION = "0.5.1";
|
|
675
752
|
|
|
676
|
-
export { APIError, AuthenticationError, type BrowserMode, type ContextAccessMode, type ContextCreateOptions, ContextInfo, type ContextListOptions, ContextListResponse, ContextLockedError, type ContextMetadata, ContextNotFoundError, type ContextStatus, ContextsResource, ExtensionInfo, type ExtensionInfoShape, type ExtensionListOptions, type ExtensionUploadOptions, ExtensionsResource, type ForceReleaseResponse, Lexmount, type LexmountConfig, LexmountError, LexmountLogger, type LogLevel, NetworkError, PaginationInfo, type PaginationInfoShape, type SessionContext, type SessionCreateOptions, type SessionCreateResponse, type SessionDeleteOptions, SessionDownloadInfo, type SessionDownloadInfoShape, SessionDownloadsDeleteResponse, type SessionDownloadsDeleteResponseShape, SessionDownloadsListResponse, type SessionDownloadsListResponseShape, SessionDownloadsResource, SessionInfo, type SessionListOptions, SessionListResponse, SessionNotFoundError, type SessionProxyConfig, type SessionStatus, SessionsResource, TimeoutError, VERSION, ValidationError, Lexmount as default, disableLogging, enableLogging, getLogger, setLogLevel };
|
|
753
|
+
export { APIError, AuthenticationError, type BrowserMode, type CatalogInfo, type ContextAccessMode, type ContextCreateOptions, ContextInfo, type ContextListOptions, ContextListResponse, ContextLockedError, type ContextMetadata, ContextNotFoundError, type ContextStatus, ContextsResource, ExtensionInfo, type ExtensionInfoShape, type ExtensionListOptions, type ExtensionUploadOptions, ExtensionsResource, type ForceReleaseResponse, Lexmount, type LexmountConfig, LexmountError, LexmountLogger, type LogLevel, NetworkError, PaginationInfo, type PaginationInfoShape, type RegionCatalogEntry, type RegionInfo, type SessionContext, type SessionCreateOptions, type SessionCreateResponse, type SessionDeleteOptions, SessionDownloadInfo, type SessionDownloadInfoShape, SessionDownloadsDeleteResponse, type SessionDownloadsDeleteResponseShape, SessionDownloadsListResponse, type SessionDownloadsListResponseShape, SessionDownloadsResource, SessionInfo, type SessionListOptions, SessionListResponse, SessionNotFoundError, type SessionProxyConfig, type SessionStatus, SessionTargetInfo, type SessionTargetInfoShape, SessionsResource, TimeoutError, VERSION, ValidationError, Lexmount as default, disableLogging, enableLogging, getLogger, setLogLevel };
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ __export(index_exports, {
|
|
|
51
51
|
SessionInfo: () => SessionInfo,
|
|
52
52
|
SessionListResponse: () => SessionListResponse,
|
|
53
53
|
SessionNotFoundError: () => SessionNotFoundError,
|
|
54
|
+
SessionTargetInfo: () => SessionTargetInfo,
|
|
54
55
|
SessionsResource: () => SessionsResource,
|
|
55
56
|
TimeoutError: () => TimeoutError,
|
|
56
57
|
VERSION: () => VERSION,
|
|
@@ -728,6 +729,18 @@ var SessionDownloadsDeleteResponse = class {
|
|
|
728
729
|
this.deletedCount = shape.deletedCount;
|
|
729
730
|
}
|
|
730
731
|
};
|
|
732
|
+
var SessionTargetInfo = class {
|
|
733
|
+
constructor(shape) {
|
|
734
|
+
this.id = shape.id;
|
|
735
|
+
this.title = shape.title;
|
|
736
|
+
this.type = shape.type;
|
|
737
|
+
this.url = shape.url;
|
|
738
|
+
this.description = shape.description;
|
|
739
|
+
this.inspectUrl = shape.inspectUrl;
|
|
740
|
+
this.webSocketDebuggerUrl = shape.webSocketDebuggerUrl;
|
|
741
|
+
this.webSocketDebuggerUrlTransformed = shape.webSocketDebuggerUrlTransformed;
|
|
742
|
+
}
|
|
743
|
+
};
|
|
731
744
|
var SessionDownloadsResource = class {
|
|
732
745
|
constructor(client) {
|
|
733
746
|
this.client = client;
|
|
@@ -958,6 +971,19 @@ var SessionsResource = class {
|
|
|
958
971
|
}
|
|
959
972
|
getLogger().info(`Session deleted successfully: ${options.sessionId}`);
|
|
960
973
|
}
|
|
974
|
+
/**
|
|
975
|
+
* List target/page metadata for a session via `/json`.
|
|
976
|
+
*/
|
|
977
|
+
async listTargets(sessionId) {
|
|
978
|
+
const response = await this.client._get(`${this.client.baseUrl}/json`, {
|
|
979
|
+
session_id: sessionId
|
|
980
|
+
});
|
|
981
|
+
if (response.status >= 400) {
|
|
982
|
+
this.handleListTargetsError(response, sessionId);
|
|
983
|
+
}
|
|
984
|
+
const result = Array.isArray(response.data) ? response.data : [];
|
|
985
|
+
return result.map((item) => this.mapSessionTarget(asRecord3(item)));
|
|
986
|
+
}
|
|
961
987
|
/**
|
|
962
988
|
* Fetch the debugger WebSocket URL for a session.
|
|
963
989
|
*
|
|
@@ -1053,6 +1079,24 @@ var SessionsResource = class {
|
|
|
1053
1079
|
response: response.data
|
|
1054
1080
|
});
|
|
1055
1081
|
}
|
|
1082
|
+
handleListTargetsError(response, sessionId) {
|
|
1083
|
+
const errorData = asRecord3(response.data);
|
|
1084
|
+
const errorMessage = getString3(errorData.error) ?? getString3(errorData.message) ?? "Unknown error";
|
|
1085
|
+
if (response.status === 401) {
|
|
1086
|
+
throw new AuthenticationError(
|
|
1087
|
+
`Authentication failed: ${errorMessage}. Please check your API key and project ID.`
|
|
1088
|
+
);
|
|
1089
|
+
}
|
|
1090
|
+
if (response.status === 404) {
|
|
1091
|
+
throw new SessionNotFoundError(
|
|
1092
|
+
`Session not found: ${errorMessage}. Session ID '${sessionId}' may not exist in this project.`
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
throw new APIError(`Failed to list session targets: ${errorMessage}`, {
|
|
1096
|
+
statusCode: response.status,
|
|
1097
|
+
response: response.data
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1056
1100
|
handleDeleteError(response, sessionId) {
|
|
1057
1101
|
const errorData = asRecord3(response.data);
|
|
1058
1102
|
const errorMessage = getString3(errorData.error) ?? getString3(errorData.message) ?? "Unknown error";
|
|
@@ -1086,6 +1130,18 @@ var SessionsResource = class {
|
|
|
1086
1130
|
client: this.client
|
|
1087
1131
|
});
|
|
1088
1132
|
}
|
|
1133
|
+
mapSessionTarget(raw) {
|
|
1134
|
+
return new SessionTargetInfo({
|
|
1135
|
+
id: getString3(raw.id) ?? "",
|
|
1136
|
+
title: getString3(raw.title) ?? "",
|
|
1137
|
+
type: getString3(raw.type) ?? "",
|
|
1138
|
+
url: getString3(raw.url) ?? "",
|
|
1139
|
+
description: getString3(raw.description) ?? "",
|
|
1140
|
+
inspectUrl: getString3(raw.inspectUrl) ?? getString3(raw.inspect_url) ?? null,
|
|
1141
|
+
webSocketDebuggerUrl: getString3(raw.webSocketDebuggerUrl) ?? getString3(raw.web_socket_debugger_url) ?? null,
|
|
1142
|
+
webSocketDebuggerUrlTransformed: getString3(raw.webSocketDebuggerUrlTransformed) ?? getString3(raw.web_socket_debugger_url_transformed) ?? null
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1089
1145
|
async _getCreatedSession(sessionId, projectId) {
|
|
1090
1146
|
try {
|
|
1091
1147
|
return await this.get(sessionId, projectId);
|
|
@@ -1103,6 +1159,7 @@ var SessionsResource = class {
|
|
|
1103
1159
|
dotenv.config();
|
|
1104
1160
|
var Lexmount = class {
|
|
1105
1161
|
constructor(config2 = {}) {
|
|
1162
|
+
this.regionResolutionAttempted = false;
|
|
1106
1163
|
this.apiKey = config2.apiKey ?? process.env.LEXMOUNT_API_KEY ?? "";
|
|
1107
1164
|
if (!this.apiKey) {
|
|
1108
1165
|
throw new ValidationError(
|
|
@@ -1116,6 +1173,7 @@ var Lexmount = class {
|
|
|
1116
1173
|
);
|
|
1117
1174
|
}
|
|
1118
1175
|
this.baseUrl = (config2.baseUrl ?? process.env.LEXMOUNT_BASE_URL ?? "https://api.lexmount.cn").replace(/\/$/, "");
|
|
1176
|
+
this.region = config2.region;
|
|
1119
1177
|
if (config2.logLevel) {
|
|
1120
1178
|
setLogLevel(config2.logLevel);
|
|
1121
1179
|
}
|
|
@@ -1133,6 +1191,7 @@ var Lexmount = class {
|
|
|
1133
1191
|
* @internal
|
|
1134
1192
|
*/
|
|
1135
1193
|
async _post(url, data, config2 = {}) {
|
|
1194
|
+
await this.ensureRegionResolved();
|
|
1136
1195
|
return this.request("POST", url, { ...config2, data });
|
|
1137
1196
|
}
|
|
1138
1197
|
/**
|
|
@@ -1141,6 +1200,7 @@ var Lexmount = class {
|
|
|
1141
1200
|
* @internal
|
|
1142
1201
|
*/
|
|
1143
1202
|
async _get(url, params, config2 = {}) {
|
|
1203
|
+
await this.ensureRegionResolved();
|
|
1144
1204
|
return this.request("GET", url, { ...config2, params });
|
|
1145
1205
|
}
|
|
1146
1206
|
/**
|
|
@@ -1149,8 +1209,51 @@ var Lexmount = class {
|
|
|
1149
1209
|
* @internal
|
|
1150
1210
|
*/
|
|
1151
1211
|
async _delete(url, data, config2 = {}) {
|
|
1212
|
+
await this.ensureRegionResolved();
|
|
1152
1213
|
return this.request("DELETE", url, { ...config2, data });
|
|
1153
1214
|
}
|
|
1215
|
+
async regionInfo() {
|
|
1216
|
+
await this.ensureRegionResolved();
|
|
1217
|
+
return {
|
|
1218
|
+
requestedRegion: this.region,
|
|
1219
|
+
selectedRegion: this.selectedRegion,
|
|
1220
|
+
baseUrl: this.baseUrl,
|
|
1221
|
+
endpointBaseUrl: this.endpointBaseUrl,
|
|
1222
|
+
host: this.selectedHost,
|
|
1223
|
+
resolved: this.regionResolutionAttempted,
|
|
1224
|
+
usingRegion: this.selectedRegion !== void 0
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
async catalogInfo() {
|
|
1228
|
+
try {
|
|
1229
|
+
const response = await this.httpClient.get(
|
|
1230
|
+
`${this.baseUrl}/v1/regions/catalog`
|
|
1231
|
+
);
|
|
1232
|
+
if (response.status !== 200) {
|
|
1233
|
+
return {
|
|
1234
|
+
baseUrl: this.baseUrl,
|
|
1235
|
+
available: false,
|
|
1236
|
+
statusCode: response.status,
|
|
1237
|
+
regions: []
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
const regions = Array.isArray(response.data?.regions) ? response.data.regions : [];
|
|
1241
|
+
return {
|
|
1242
|
+
baseUrl: this.baseUrl,
|
|
1243
|
+
available: Array.isArray(response.data?.regions),
|
|
1244
|
+
statusCode: response.status,
|
|
1245
|
+
regions,
|
|
1246
|
+
error: Array.isArray(response.data?.regions) ? void 0 : "invalid catalog regions"
|
|
1247
|
+
};
|
|
1248
|
+
} catch (error) {
|
|
1249
|
+
return {
|
|
1250
|
+
baseUrl: this.baseUrl,
|
|
1251
|
+
available: false,
|
|
1252
|
+
regions: [],
|
|
1253
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1154
1257
|
/**
|
|
1155
1258
|
* Close the client.
|
|
1156
1259
|
*
|
|
@@ -1168,7 +1271,8 @@ var Lexmount = class {
|
|
|
1168
1271
|
async request(method, url, config2) {
|
|
1169
1272
|
const logger2 = getLogger();
|
|
1170
1273
|
const startTime = Date.now();
|
|
1171
|
-
|
|
1274
|
+
const requestUrl = this.rewriteUrl(url);
|
|
1275
|
+
logger2.debug(`${method} request to ${requestUrl}`);
|
|
1172
1276
|
try {
|
|
1173
1277
|
const headers = {
|
|
1174
1278
|
api_key: this.apiKey,
|
|
@@ -1178,12 +1282,14 @@ var Lexmount = class {
|
|
|
1178
1282
|
};
|
|
1179
1283
|
const response = await this.httpClient.request({
|
|
1180
1284
|
method,
|
|
1181
|
-
url,
|
|
1285
|
+
url: requestUrl,
|
|
1182
1286
|
...config2,
|
|
1183
1287
|
headers
|
|
1184
1288
|
});
|
|
1185
1289
|
const elapsed = Date.now() - startTime;
|
|
1186
|
-
logger2.debug(
|
|
1290
|
+
logger2.debug(
|
|
1291
|
+
`${method} response: status=${response.status}, duration=${elapsed.toFixed(2)}ms`
|
|
1292
|
+
);
|
|
1187
1293
|
return response;
|
|
1188
1294
|
} catch (error) {
|
|
1189
1295
|
const elapsed = Date.now() - startTime;
|
|
@@ -1222,10 +1328,101 @@ var Lexmount = class {
|
|
|
1222
1328
|
"Content-Type": "application/json"
|
|
1223
1329
|
};
|
|
1224
1330
|
}
|
|
1331
|
+
async ensureRegionResolved() {
|
|
1332
|
+
if (this.regionResolutionAttempted) {
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
if (!this.regionResolutionPromise) {
|
|
1336
|
+
this.regionResolutionPromise = this.resolveRegion().finally(() => {
|
|
1337
|
+
this.regionResolutionAttempted = true;
|
|
1338
|
+
this.regionResolutionPromise = void 0;
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
await this.regionResolutionPromise;
|
|
1342
|
+
}
|
|
1343
|
+
async resolveRegion() {
|
|
1344
|
+
const logger2 = getLogger();
|
|
1345
|
+
try {
|
|
1346
|
+
const response = await this.httpClient.get(
|
|
1347
|
+
`${this.baseUrl}/v1/regions/catalog`
|
|
1348
|
+
);
|
|
1349
|
+
if (response.status !== 200 || !Array.isArray(response.data?.regions)) {
|
|
1350
|
+
logger2.debug(
|
|
1351
|
+
`Region catalog unavailable, falling back to baseUrl: status=${response.status}`
|
|
1352
|
+
);
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
const selected = this.selectCatalogRegion(response.data.regions);
|
|
1356
|
+
if (!selected) {
|
|
1357
|
+
if (this.region) {
|
|
1358
|
+
logger2.warn(`Requested region not found in catalog: ${this.region}`);
|
|
1359
|
+
} else {
|
|
1360
|
+
logger2.debug("No default catalog region, falling back to baseUrl");
|
|
1361
|
+
}
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
const endpointBaseUrl = await this.probeRegionHost(selected);
|
|
1365
|
+
if (!endpointBaseUrl) {
|
|
1366
|
+
logger2.debug("Region probe failed, falling back to baseUrl");
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
this.selectedRegion = selected.region_id;
|
|
1370
|
+
this.selectedHost = selected.host;
|
|
1371
|
+
this.endpointBaseUrl = endpointBaseUrl;
|
|
1372
|
+
} catch (error) {
|
|
1373
|
+
logger2.debug("Region resolution failed, falling back to baseUrl:", error);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
selectCatalogRegion(regions) {
|
|
1377
|
+
if (this.region) {
|
|
1378
|
+
return regions.find((region) => region.region_id === this.region);
|
|
1379
|
+
}
|
|
1380
|
+
const defaultRegions = regions.filter((region) => region.default === true);
|
|
1381
|
+
return defaultRegions.length === 1 ? defaultRegions[0] : void 0;
|
|
1382
|
+
}
|
|
1383
|
+
async probeRegionHost(region) {
|
|
1384
|
+
const logger2 = getLogger();
|
|
1385
|
+
const host = String(region.host || "").trim();
|
|
1386
|
+
if (!host) {
|
|
1387
|
+
return void 0;
|
|
1388
|
+
}
|
|
1389
|
+
if (!this.isAllowedCatalogHost(host)) {
|
|
1390
|
+
logger2.warn(`Ignoring invalid region catalog host: ${host}`);
|
|
1391
|
+
return void 0;
|
|
1392
|
+
}
|
|
1393
|
+
const endpointBaseUrl = `https://${host}`;
|
|
1394
|
+
const probePath = String(region.probe_path || "/v1/region/probe").replace(/^(?!\/)/, "/");
|
|
1395
|
+
try {
|
|
1396
|
+
const response = await this.httpClient.get(`${endpointBaseUrl}${probePath}`);
|
|
1397
|
+
return response.status === 200 ? endpointBaseUrl : void 0;
|
|
1398
|
+
} catch {
|
|
1399
|
+
return void 0;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
isAllowedCatalogHost(host) {
|
|
1403
|
+
let parsed;
|
|
1404
|
+
try {
|
|
1405
|
+
parsed = new URL(`https://${host}`);
|
|
1406
|
+
} catch {
|
|
1407
|
+
return false;
|
|
1408
|
+
}
|
|
1409
|
+
if (parsed.username || parsed.password || parsed.port || parsed.pathname !== "/" || parsed.search || parsed.hash) {
|
|
1410
|
+
return false;
|
|
1411
|
+
}
|
|
1412
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
1413
|
+
const allowedDomains = ["lexmount.cn", "lexmount.com", "lexmount.net"];
|
|
1414
|
+
return allowedDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`));
|
|
1415
|
+
}
|
|
1416
|
+
rewriteUrl(url) {
|
|
1417
|
+
if (!this.endpointBaseUrl || !url.startsWith(this.baseUrl)) {
|
|
1418
|
+
return url;
|
|
1419
|
+
}
|
|
1420
|
+
return `${this.endpointBaseUrl}${url.slice(this.baseUrl.length)}`;
|
|
1421
|
+
}
|
|
1225
1422
|
};
|
|
1226
1423
|
|
|
1227
1424
|
// src/index.ts
|
|
1228
|
-
var VERSION = "0.
|
|
1425
|
+
var VERSION = "0.5.1";
|
|
1229
1426
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1230
1427
|
0 && (module.exports = {
|
|
1231
1428
|
APIError,
|
|
@@ -1249,6 +1446,7 @@ var VERSION = "0.2.5";
|
|
|
1249
1446
|
SessionInfo,
|
|
1250
1447
|
SessionListResponse,
|
|
1251
1448
|
SessionNotFoundError,
|
|
1449
|
+
SessionTargetInfo,
|
|
1252
1450
|
SessionsResource,
|
|
1253
1451
|
TimeoutError,
|
|
1254
1452
|
VERSION,
|