@itwin/core-mobile 5.15.0-dev.2 → 5.15.0-dev.20
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/CHANGELOG.md +38 -1
- package/lib/cjs/backend/MobileHost.d.ts +8 -0
- package/lib/cjs/backend/MobileHost.d.ts.map +1 -1
- package/lib/cjs/backend/MobileHost.js +13 -0
- package/lib/cjs/backend/MobileHost.js.map +1 -1
- package/lib/cjs/backend/MobileRpcServer.d.ts +2 -0
- package/lib/cjs/backend/MobileRpcServer.d.ts.map +1 -1
- package/lib/cjs/backend/MobileRpcServer.js +15 -2
- package/lib/cjs/backend/MobileRpcServer.js.map +1 -1
- package/lib/cjs/common/MobileRpcProtocol.d.ts +2 -0
- package/lib/cjs/common/MobileRpcProtocol.d.ts.map +1 -1
- package/lib/cjs/common/MobileRpcProtocol.js +10 -2
- package/lib/cjs/common/MobileRpcProtocol.js.map +1 -1
- package/package.json +20 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
# Change Log - @itwin/core-mobile
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Wed, 04 Nov 2026 17:35:57 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 5.14.6
|
|
6
|
+
Wed, 04 Nov 2026 17:35:14 GMT
|
|
7
|
+
|
|
8
|
+
_Version update only_
|
|
9
|
+
|
|
10
|
+
## 5.14.5
|
|
11
|
+
Tue, 27 Oct 2026 12:19:48 GMT
|
|
12
|
+
|
|
13
|
+
_Version update only_
|
|
14
|
+
|
|
15
|
+
## 5.14.4
|
|
16
|
+
Fri, 23 Oct 2026 19:58:24 GMT
|
|
17
|
+
|
|
18
|
+
_Version update only_
|
|
19
|
+
|
|
20
|
+
## 5.14.3
|
|
21
|
+
Mon, 12 Oct 2026 17:37:54 GMT
|
|
22
|
+
|
|
23
|
+
### Updates
|
|
24
|
+
|
|
25
|
+
- Authenticate mobile RPC WebSocket connections with a per-launch secret to reject unauthorized on-device clients. Requires an updated mobile native runtime.
|
|
26
|
+
|
|
27
|
+
## 5.14.2
|
|
28
|
+
Tue, 06 Oct 2026 19:48:29 GMT
|
|
29
|
+
|
|
30
|
+
_Version update only_
|
|
31
|
+
|
|
32
|
+
## 5.14.1
|
|
33
|
+
Tue, 06 Oct 2026 14:00:55 GMT
|
|
34
|
+
|
|
35
|
+
_Version update only_
|
|
36
|
+
|
|
37
|
+
## 5.14.0
|
|
38
|
+
Fri, 02 Oct 2026 14:55:04 GMT
|
|
39
|
+
|
|
40
|
+
_Version update only_
|
|
4
41
|
|
|
5
42
|
## 5.13.7
|
|
6
43
|
Thu, 01 Oct 2026 15:15:30 GMT
|
|
@@ -25,8 +25,11 @@ export interface DownloadTask {
|
|
|
25
25
|
toForeground: () => boolean;
|
|
26
26
|
}
|
|
27
27
|
/** @beta */
|
|
28
|
+
export type NativeQueryHandler = (name: string, message: string) => Promise<string>;
|
|
29
|
+
/** @beta */
|
|
28
30
|
export declare abstract class MobileDevice {
|
|
29
31
|
emit(eventName: DeviceEvents, ...args: any[]): void;
|
|
32
|
+
handleNativeQuery(name: string, message: string): Promise<string>;
|
|
30
33
|
abstract getOrientation(): Orientation;
|
|
31
34
|
abstract getBatteryState(): BatteryState;
|
|
32
35
|
abstract getBatteryLevel(): number;
|
|
@@ -37,6 +40,7 @@ export declare abstract class MobileDevice {
|
|
|
37
40
|
abstract resumeDownloadInBackground(requestId: number): boolean;
|
|
38
41
|
abstract reconnect(connection: number): void;
|
|
39
42
|
abstract authGetAccessToken(callback: (accessToken?: string, expirationDate?: string, err?: string) => void): void;
|
|
43
|
+
abstract sendQueryToNative(name: string, message: string, callback: (response?: string, err?: string) => void): void;
|
|
40
44
|
}
|
|
41
45
|
/** @beta */
|
|
42
46
|
export interface MobileHostOpts extends NativeHostOpts {
|
|
@@ -52,6 +56,9 @@ export interface MobileHostOpts extends NativeHostOpts {
|
|
|
52
56
|
export declare class MobileHost {
|
|
53
57
|
private static _device?;
|
|
54
58
|
static get device(): MobileDevice;
|
|
59
|
+
private static _nativeQueryHandler;
|
|
60
|
+
static get nativeQueryHandler(): NativeQueryHandler;
|
|
61
|
+
static set nativeQueryHandler(handler: NativeQueryHandler);
|
|
55
62
|
/**
|
|
56
63
|
* Raised when the mobile OS informs a mobile app that it is running low on memory.
|
|
57
64
|
*
|
|
@@ -93,6 +100,7 @@ export declare class MobileHost {
|
|
|
93
100
|
static authGetAccessToken(): Promise<[string, string]>;
|
|
94
101
|
/** @internal */
|
|
95
102
|
static downloadFile(downloadUrl: string, downloadTo: string, progress?: ProgressCallback, cancelRequest?: CancelRequest): Promise<void>;
|
|
103
|
+
static handleNativeQuery(name: string, message: string): Promise<string>;
|
|
96
104
|
static get isValid(): boolean;
|
|
97
105
|
/** Start the backend of a mobile app. */
|
|
98
106
|
static startup(opt?: MobileHostOpts): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileHost.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileHost.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,OAAO,EAAkC,MAAM,qBAAqB,CAAC;AAC3F,OAAO,EAAmC,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAiE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC3H,OAAO,EAAE,aAAa,EAAsC,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAsB,mBAAmB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAK5H,YAAY;AACZ,MAAM,MAAM,wBAAwB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAChI,YAAY;AACZ,MAAM,MAAM,sBAAsB,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,yBAAyB,EAAE,MAAM,KAAK,IAAI,CAAC;AAClI,YAAY;AACZ,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC;AAEjD,YAAY;AACZ,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B,YAAY,EAAE,MAAM,OAAO,CAAC;CAC7B;AAED,YAAY;AACZ,8BAAsB,YAAY;IACzB,IAAI,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"MobileHost.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileHost.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,6 +43,9 @@ class MobileDevice {
|
|
|
43
43
|
break;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
async handleNativeQuery(name, message) {
|
|
47
|
+
return MobileHost.handleNativeQuery(name, message);
|
|
48
|
+
}
|
|
46
49
|
}
|
|
47
50
|
exports.MobileDevice = MobileDevice;
|
|
48
51
|
class MobileAppHandler extends core_backend_1.IpcHandler {
|
|
@@ -62,6 +65,13 @@ class MobileHost {
|
|
|
62
65
|
static get device() {
|
|
63
66
|
return (0, core_bentley_1.expectDefined)(this._device, "Mobile device is not initialized.");
|
|
64
67
|
}
|
|
68
|
+
static _nativeQueryHandler = async () => { throw Error("MobileHost query handler not registered."); };
|
|
69
|
+
static get nativeQueryHandler() {
|
|
70
|
+
return MobileHost._nativeQueryHandler;
|
|
71
|
+
}
|
|
72
|
+
static set nativeQueryHandler(handler) {
|
|
73
|
+
MobileHost._nativeQueryHandler = handler;
|
|
74
|
+
}
|
|
65
75
|
/**
|
|
66
76
|
* Raised when the mobile OS informs a mobile app that it is running low on memory.
|
|
67
77
|
*
|
|
@@ -148,6 +158,9 @@ class MobileHost {
|
|
|
148
158
|
}
|
|
149
159
|
});
|
|
150
160
|
}
|
|
161
|
+
static async handleNativeQuery(name, message) {
|
|
162
|
+
return MobileHost._nativeQueryHandler(name, message);
|
|
163
|
+
}
|
|
151
164
|
static get isValid() { return undefined !== this._device; }
|
|
152
165
|
/** Start the backend of a mobile app. */
|
|
153
166
|
static async startup(opt) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileHost.js","sourceRoot":"","sources":["../../../src/backend/MobileHost.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\nimport { AccessToken, BeEvent, BriefcaseStatus, expectDefined } from \"@itwin/core-bentley\";\r\nimport { IpcHandler, IpcHost, NativeHost, NativeHostOpts } from \"@itwin/core-backend\";\r\nimport { InternetConnectivityStatus, IpcWebSocketBackend, OverriddenBy, RpcInterfaceDefinition } from \"@itwin/core-common\";\r\nimport { CancelRequest, DownloadFailed, UserCancelledError } from \"./MobileFileHandler\";\r\nimport { ProgressCallback } from \"./Request\";\r\nimport { mobileAppStrings } from \"../common/MobileAppChannel\";\r\nimport { BatteryState, DeviceEvents, MobileAppFunctions, MobileNotifications, Orientation } from \"../common/MobileAppProps\";\r\nimport { MobileRpcManager } from \"../common/MobileRpcManager\";\r\nimport { MobileAuthorizationBackend } from \"./MobileAuthorizationBackend\";\r\nimport { setupMobileRpc } from \"./MobileRpcServer\";\r\n\r\n/** @beta */\r\nexport type MobileCompletionCallback = (downloadUrl: string, downloadFileUrl: string, cancelled: boolean, err?: string) => void;\r\n/** @beta */\r\nexport type MobileProgressCallback = (bytesWritten: number, totalBytesWritten: number, totalBytesExpectedToWrite: number) => void;\r\n/** @beta */\r\nexport type MobileCancelCallback = () => boolean;\r\n\r\n/** @beta */\r\nexport interface DownloadTask {\r\n url: string;\r\n downloadPath: string;\r\n isDetached: boolean;\r\n isRunning: boolean;\r\n totalBytes?: number;\r\n doneBytes?: number;\r\n cancelId?: number;\r\n isBackground?: boolean;\r\n cancel?: MobileCancelCallback;\r\n toBackground: () => boolean;\r\n toForeground: () => boolean;\r\n}\r\n\r\n/** @beta */\r\nexport abstract class MobileDevice {\r\n public emit(eventName: DeviceEvents, ...args: any[]) {\r\n switch (eventName) {\r\n case \"memoryWarning\":\r\n MobileHost.onMemoryWarning.raiseEvent(...args);\r\n break;\r\n case \"orientationChanged\":\r\n MobileHost.onOrientationChanged.raiseEvent(...args);\r\n break;\r\n case \"enterForeground\":\r\n MobileHost.onEnterForeground.raiseEvent(...args);\r\n break;\r\n case \"enterBackground\":\r\n MobileHost.onEnterBackground.raiseEvent(...args);\r\n break;\r\n case \"willTerminate\":\r\n MobileHost.onWillTerminate.raiseEvent(...args);\r\n break;\r\n case \"authAccessTokenChanged\":\r\n MobileHost.onAuthAccessTokenChanged.raiseEvent(args[0], args[1]);\r\n break;\r\n case \"online\":\r\n NativeHost.overrideInternetConnectivity(OverriddenBy.Browser, InternetConnectivityStatus.Online);\r\n break;\r\n case \"offline\":\r\n NativeHost.overrideInternetConnectivity(OverriddenBy.Browser, InternetConnectivityStatus.Offline);\r\n break;\r\n }\r\n }\r\n\r\n public abstract getOrientation(): Orientation;\r\n public abstract getBatteryState(): BatteryState;\r\n public abstract getBatteryLevel(): number;\r\n public abstract createDownloadTask(downloadUrl: string, isBackground: boolean, downloadTo: string, completion: MobileCompletionCallback, progress?: MobileProgressCallback): number;\r\n public abstract cancelDownloadTask(cancelId: number): boolean;\r\n public abstract getDownloadTasks(): DownloadTask[];\r\n public abstract resumeDownloadInForeground(requestId: number): boolean;\r\n public abstract resumeDownloadInBackground(requestId: number): boolean;\r\n public abstract reconnect(connection: number): void;\r\n public abstract authGetAccessToken(callback: (accessToken?: string, expirationDate?: string, err?: string) => void): void;\r\n}\r\n\r\nclass MobileAppHandler extends IpcHandler implements MobileAppFunctions {\r\n public get channelName() { return mobileAppStrings.mobileAppChannel; }\r\n public async reconnect(connection: number) {\r\n MobileHost.reconnect(connection);\r\n }\r\n public async getAccessToken() {\r\n return MobileHost.authGetAccessToken();\r\n }\r\n}\r\n\r\n/** @beta */\r\nexport interface MobileHostOpts extends NativeHostOpts {\r\n mobileHost?: {\r\n device?: MobileDevice;\r\n /** list of RPC interface definitions to register */\r\n rpcInterfaces?: RpcInterfaceDefinition[];\r\n };\r\n}\r\n\r\n/**\r\n * @beta\r\n */\r\nexport class MobileHost {\r\n private static _device?: MobileDevice;\r\n public static get device() {\r\n return expectDefined(this._device, \"Mobile device is not initialized.\");\r\n }\r\n /**\r\n * Raised when the mobile OS informs a mobile app that it is running low on memory.\r\n *\r\n * @note iOS and iPadOS send this warning so often as to make it not very useful.\r\n */\r\n public static readonly onMemoryWarning = new BeEvent();\r\n /**\r\n * Raised when the device orientation changes on a device running a mobile app.\r\n */\r\n public static readonly onOrientationChanged = new BeEvent();\r\n /**\r\n * Raised after a mobile app returns to the foreground.\r\n */\r\n public static readonly onEnterForeground = new BeEvent();\r\n /**\r\n * Raised when a mobile app is about to enter the background.\r\n */\r\n public static readonly onEnterBackground = new BeEvent();\r\n /**\r\n * Raised after a mobile backend connects to the mobile frontend.\r\n *\r\n * @note this will be raised at startup, and it will also be raised every time the app returns\r\n * to the foreground from the background.\r\n */\r\n public static readonly onConnected = new BeEvent();\r\n /**\r\n * Raised when a mobile app is about to be terminated by the mobile OS.\r\n */\r\n public static readonly onWillTerminate = new BeEvent();\r\n /**\r\n * Raised when the native auth client informs the mobile host that the access token has changed.\r\n */\r\n public static readonly onAuthAccessTokenChanged = new BeEvent<(accessToken: string | undefined, expirationDate: string | undefined) => void>();\r\n\r\n /** Send a notification to the MobileApp connected to this MobileHost. */\r\n public static notifyMobileFrontend<T extends keyof MobileNotifications>(methodName: T, ...args: Parameters<MobileNotifications[T]>) {\r\n return IpcHost.send(mobileAppStrings.mobileAppNotify, methodName, ...args);\r\n }\r\n\r\n /** @internal */\r\n public static reconnect(connection: number) {\r\n this.device.reconnect(connection);\r\n }\r\n\r\n /** @internal */\r\n public static async authGetAccessToken() {\r\n return new Promise<[AccessToken, string]>((resolve, reject) => {\r\n this.device.authGetAccessToken((tokenString?: AccessToken, expirationDate?: string, error?: string) => {\r\n if (error) {\r\n reject(new Error(error));\r\n } else {\r\n resolve([tokenString ?? \"\", expirationDate ?? \"\"]);\r\n }\r\n });\r\n });\r\n }\r\n\r\n /** @internal */\r\n public static async downloadFile(downloadUrl: string, downloadTo: string, progress?: ProgressCallback, cancelRequest?: CancelRequest): Promise<void> {\r\n return new Promise<void>((resolve, reject) => {\r\n\r\n let progressCb: MobileProgressCallback | undefined;\r\n let lastReportedOn = Date.now();\r\n const minTimeBeforeReportingProgress = 1000;\r\n if (progress) {\r\n progressCb = (_bytesWritten: number, totalBytesWritten: number, totalBytesExpectedToWrite: number) => {\r\n const currentTime = Date.now();\r\n const timeSinceLastEvent = currentTime - lastReportedOn;\r\n // report all event for last 5 Mbs so we never miss 100% progress event\r\n const lastEvent = (totalBytesExpectedToWrite - totalBytesWritten) < 1024 * 1024 * 5;\r\n if (timeSinceLastEvent < minTimeBeforeReportingProgress && !lastEvent)\r\n return;\r\n\r\n lastReportedOn = currentTime;\r\n const percent = Number((100 * (totalBytesWritten / totalBytesExpectedToWrite)).toFixed(2));\r\n progress({ total: totalBytesExpectedToWrite, loaded: totalBytesWritten, percent });\r\n };\r\n }\r\n const requestId = this.device.createDownloadTask(downloadUrl, false, downloadTo, (_downloadUrl: string, _downloadFileUrl: string, cancelled: boolean, err?: string) => {\r\n if (cancelled)\r\n reject(new UserCancelledError(BriefcaseStatus.DownloadCancelled, \"User cancelled download\"));\r\n else if (err)\r\n reject(new DownloadFailed(400, \"Download failed\"));\r\n else\r\n resolve();\r\n }, progressCb);\r\n if (cancelRequest) {\r\n cancelRequest.cancel = () => this.device.cancelDownloadTask(requestId);\r\n }\r\n });\r\n }\r\n\r\n public static get isValid() { return undefined !== this._device; }\r\n\r\n /** Start the backend of a mobile app. */\r\n public static async startup(opt?: MobileHostOpts): Promise<void> {\r\n const authorizationClient = new MobileAuthorizationBackend();\r\n if (!this.isValid) {\r\n this._device = opt?.mobileHost?.device ?? new (MobileDevice as any)();\r\n // set global device interface.\r\n // NOTE: __iTwinJsNativeBridge is used by backend native code.\r\n (global as any).__iTwinJsNativeBridge = this._device;\r\n this.onMemoryWarning.addListener(() => {\r\n MobileHost.notifyMobileFrontend(\"notifyMemoryWarning\");\r\n });\r\n this.onOrientationChanged.addListener(() => {\r\n try {\r\n MobileHost.notifyMobileFrontend(\"notifyOrientationChanged\");\r\n } catch { } // Ignore: frontend is not currently connected\r\n });\r\n this.onWillTerminate.addListener(() => {\r\n MobileHost.notifyMobileFrontend(\"notifyWillTerminate\");\r\n });\r\n this.onAuthAccessTokenChanged.addListener((accessToken: string | undefined, expirationDate: string | undefined) => {\r\n authorizationClient.setAccessToken(accessToken, expirationDate);\r\n MobileHost.notifyMobileFrontend(\"notifyAuthAccessTokenChanged\", accessToken, expirationDate);\r\n });\r\n\r\n // following will provide impl for device specific api.\r\n setupMobileRpc();\r\n }\r\n\r\n const socket = opt?.ipcHost?.socket ?? new IpcWebSocketBackend();\r\n opt = { ...opt, mobileHost: { ...opt?.mobileHost }, ipcHost: { ...opt?.ipcHost, socket } };\r\n\r\n const iModelHost = opt?.iModelHost ?? {};\r\n iModelHost.authorizationClient = authorizationClient;\r\n await NativeHost.startup({ ...opt, iModelHost });\r\n\r\n if (IpcHost.isValid)\r\n MobileAppHandler.register();\r\n\r\n const rpcInterfaces = opt?.mobileHost?.rpcInterfaces ?? [];\r\n\r\n MobileRpcManager.initializeImpl(rpcInterfaces);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"MobileHost.js","sourceRoot":"","sources":["../../../src/backend/MobileHost.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\nimport { AccessToken, BeEvent, BriefcaseStatus, expectDefined } from \"@itwin/core-bentley\";\r\nimport { IpcHandler, IpcHost, NativeHost, NativeHostOpts } from \"@itwin/core-backend\";\r\nimport { InternetConnectivityStatus, IpcWebSocketBackend, OverriddenBy, RpcInterfaceDefinition } from \"@itwin/core-common\";\r\nimport { CancelRequest, DownloadFailed, UserCancelledError } from \"./MobileFileHandler\";\r\nimport { ProgressCallback } from \"./Request\";\r\nimport { mobileAppStrings } from \"../common/MobileAppChannel\";\r\nimport { BatteryState, DeviceEvents, MobileAppFunctions, MobileNotifications, Orientation } from \"../common/MobileAppProps\";\r\nimport { MobileRpcManager } from \"../common/MobileRpcManager\";\r\nimport { MobileAuthorizationBackend } from \"./MobileAuthorizationBackend\";\r\nimport { setupMobileRpc } from \"./MobileRpcServer\";\r\n\r\n/** @beta */\r\nexport type MobileCompletionCallback = (downloadUrl: string, downloadFileUrl: string, cancelled: boolean, err?: string) => void;\r\n/** @beta */\r\nexport type MobileProgressCallback = (bytesWritten: number, totalBytesWritten: number, totalBytesExpectedToWrite: number) => void;\r\n/** @beta */\r\nexport type MobileCancelCallback = () => boolean;\r\n\r\n/** @beta */\r\nexport interface DownloadTask {\r\n url: string;\r\n downloadPath: string;\r\n isDetached: boolean;\r\n isRunning: boolean;\r\n totalBytes?: number;\r\n doneBytes?: number;\r\n cancelId?: number;\r\n isBackground?: boolean;\r\n cancel?: MobileCancelCallback;\r\n toBackground: () => boolean;\r\n toForeground: () => boolean;\r\n}\r\n\r\n/** @beta */\r\nexport type NativeQueryHandler = (name: string, message: string) => Promise<string>\r\n\r\n/** @beta */\r\nexport abstract class MobileDevice {\r\n public emit(eventName: DeviceEvents, ...args: any[]) {\r\n switch (eventName) {\r\n case \"memoryWarning\":\r\n MobileHost.onMemoryWarning.raiseEvent(...args);\r\n break;\r\n case \"orientationChanged\":\r\n MobileHost.onOrientationChanged.raiseEvent(...args);\r\n break;\r\n case \"enterForeground\":\r\n MobileHost.onEnterForeground.raiseEvent(...args);\r\n break;\r\n case \"enterBackground\":\r\n MobileHost.onEnterBackground.raiseEvent(...args);\r\n break;\r\n case \"willTerminate\":\r\n MobileHost.onWillTerminate.raiseEvent(...args);\r\n break;\r\n case \"authAccessTokenChanged\":\r\n MobileHost.onAuthAccessTokenChanged.raiseEvent(args[0], args[1]);\r\n break;\r\n case \"online\":\r\n NativeHost.overrideInternetConnectivity(OverriddenBy.Browser, InternetConnectivityStatus.Online);\r\n break;\r\n case \"offline\":\r\n NativeHost.overrideInternetConnectivity(OverriddenBy.Browser, InternetConnectivityStatus.Offline);\r\n break;\r\n }\r\n }\r\n\r\n public async handleNativeQuery(name: string, message: string): Promise<string> {\r\n return MobileHost.handleNativeQuery(name, message);\r\n }\r\n\r\n public abstract getOrientation(): Orientation;\r\n public abstract getBatteryState(): BatteryState;\r\n public abstract getBatteryLevel(): number;\r\n public abstract createDownloadTask(downloadUrl: string, isBackground: boolean, downloadTo: string, completion: MobileCompletionCallback, progress?: MobileProgressCallback): number;\r\n public abstract cancelDownloadTask(cancelId: number): boolean;\r\n public abstract getDownloadTasks(): DownloadTask[];\r\n public abstract resumeDownloadInForeground(requestId: number): boolean;\r\n public abstract resumeDownloadInBackground(requestId: number): boolean;\r\n public abstract reconnect(connection: number): void;\r\n public abstract authGetAccessToken(callback: (accessToken?: string, expirationDate?: string, err?: string) => void): void;\r\n public abstract sendQueryToNative(name: string, message: string, callback: (response?: string, err?: string) => void): void;\r\n}\r\n\r\nclass MobileAppHandler extends IpcHandler implements MobileAppFunctions {\r\n public get channelName() { return mobileAppStrings.mobileAppChannel; }\r\n public async reconnect(connection: number) {\r\n MobileHost.reconnect(connection);\r\n }\r\n public async getAccessToken() {\r\n return MobileHost.authGetAccessToken();\r\n }\r\n}\r\n\r\n/** @beta */\r\nexport interface MobileHostOpts extends NativeHostOpts {\r\n mobileHost?: {\r\n device?: MobileDevice;\r\n /** list of RPC interface definitions to register */\r\n rpcInterfaces?: RpcInterfaceDefinition[];\r\n };\r\n}\r\n\r\n/**\r\n * @beta\r\n */\r\nexport class MobileHost {\r\n private static _device?: MobileDevice;\r\n public static get device() {\r\n return expectDefined(this._device, \"Mobile device is not initialized.\");\r\n }\r\n\r\n private static _nativeQueryHandler: NativeQueryHandler = async () => { throw Error(\"MobileHost query handler not registered.\"); };\r\n public static get nativeQueryHandler(): NativeQueryHandler {\r\n return MobileHost._nativeQueryHandler;\r\n }\r\n public static set nativeQueryHandler(handler: NativeQueryHandler) {\r\n MobileHost._nativeQueryHandler = handler;\r\n }\r\n\r\n /**\r\n * Raised when the mobile OS informs a mobile app that it is running low on memory.\r\n *\r\n * @note iOS and iPadOS send this warning so often as to make it not very useful.\r\n */\r\n public static readonly onMemoryWarning = new BeEvent();\r\n /**\r\n * Raised when the device orientation changes on a device running a mobile app.\r\n */\r\n public static readonly onOrientationChanged = new BeEvent();\r\n /**\r\n * Raised after a mobile app returns to the foreground.\r\n */\r\n public static readonly onEnterForeground = new BeEvent();\r\n /**\r\n * Raised when a mobile app is about to enter the background.\r\n */\r\n public static readonly onEnterBackground = new BeEvent();\r\n /**\r\n * Raised after a mobile backend connects to the mobile frontend.\r\n *\r\n * @note this will be raised at startup, and it will also be raised every time the app returns\r\n * to the foreground from the background.\r\n */\r\n public static readonly onConnected = new BeEvent();\r\n /**\r\n * Raised when a mobile app is about to be terminated by the mobile OS.\r\n */\r\n public static readonly onWillTerminate = new BeEvent();\r\n /**\r\n * Raised when the native auth client informs the mobile host that the access token has changed.\r\n */\r\n public static readonly onAuthAccessTokenChanged = new BeEvent<(accessToken: string | undefined, expirationDate: string | undefined) => void>();\r\n\r\n /** Send a notification to the MobileApp connected to this MobileHost. */\r\n public static notifyMobileFrontend<T extends keyof MobileNotifications>(methodName: T, ...args: Parameters<MobileNotifications[T]>) {\r\n return IpcHost.send(mobileAppStrings.mobileAppNotify, methodName, ...args);\r\n }\r\n\r\n /** @internal */\r\n public static reconnect(connection: number) {\r\n this.device.reconnect(connection);\r\n }\r\n\r\n /** @internal */\r\n public static async authGetAccessToken() {\r\n return new Promise<[AccessToken, string]>((resolve, reject) => {\r\n this.device.authGetAccessToken((tokenString?: AccessToken, expirationDate?: string, error?: string) => {\r\n if (error) {\r\n reject(new Error(error));\r\n } else {\r\n resolve([tokenString ?? \"\", expirationDate ?? \"\"]);\r\n }\r\n });\r\n });\r\n }\r\n\r\n /** @internal */\r\n public static async downloadFile(downloadUrl: string, downloadTo: string, progress?: ProgressCallback, cancelRequest?: CancelRequest): Promise<void> {\r\n return new Promise<void>((resolve, reject) => {\r\n\r\n let progressCb: MobileProgressCallback | undefined;\r\n let lastReportedOn = Date.now();\r\n const minTimeBeforeReportingProgress = 1000;\r\n if (progress) {\r\n progressCb = (_bytesWritten: number, totalBytesWritten: number, totalBytesExpectedToWrite: number) => {\r\n const currentTime = Date.now();\r\n const timeSinceLastEvent = currentTime - lastReportedOn;\r\n // report all event for last 5 Mbs so we never miss 100% progress event\r\n const lastEvent = (totalBytesExpectedToWrite - totalBytesWritten) < 1024 * 1024 * 5;\r\n if (timeSinceLastEvent < minTimeBeforeReportingProgress && !lastEvent)\r\n return;\r\n\r\n lastReportedOn = currentTime;\r\n const percent = Number((100 * (totalBytesWritten / totalBytesExpectedToWrite)).toFixed(2));\r\n progress({ total: totalBytesExpectedToWrite, loaded: totalBytesWritten, percent });\r\n };\r\n }\r\n const requestId = this.device.createDownloadTask(downloadUrl, false, downloadTo, (_downloadUrl: string, _downloadFileUrl: string, cancelled: boolean, err?: string) => {\r\n if (cancelled)\r\n reject(new UserCancelledError(BriefcaseStatus.DownloadCancelled, \"User cancelled download\"));\r\n else if (err)\r\n reject(new DownloadFailed(400, \"Download failed\"));\r\n else\r\n resolve();\r\n }, progressCb);\r\n if (cancelRequest) {\r\n cancelRequest.cancel = () => this.device.cancelDownloadTask(requestId);\r\n }\r\n });\r\n }\r\n\r\n public static async handleNativeQuery(name: string, message: string): Promise<string> {\r\n return MobileHost._nativeQueryHandler(name, message);\r\n }\r\n\r\n public static get isValid() { return undefined !== this._device; }\r\n\r\n /** Start the backend of a mobile app. */\r\n public static async startup(opt?: MobileHostOpts): Promise<void> {\r\n const authorizationClient = new MobileAuthorizationBackend();\r\n if (!this.isValid) {\r\n this._device = opt?.mobileHost?.device ?? new (MobileDevice as any)();\r\n // set global device interface.\r\n // NOTE: __iTwinJsNativeBridge is used by backend native code.\r\n (global as any).__iTwinJsNativeBridge = this._device;\r\n this.onMemoryWarning.addListener(() => {\r\n MobileHost.notifyMobileFrontend(\"notifyMemoryWarning\");\r\n });\r\n this.onOrientationChanged.addListener(() => {\r\n try {\r\n MobileHost.notifyMobileFrontend(\"notifyOrientationChanged\");\r\n } catch { } // Ignore: frontend is not currently connected\r\n });\r\n this.onWillTerminate.addListener(() => {\r\n MobileHost.notifyMobileFrontend(\"notifyWillTerminate\");\r\n });\r\n this.onAuthAccessTokenChanged.addListener((accessToken: string | undefined, expirationDate: string | undefined) => {\r\n authorizationClient.setAccessToken(accessToken, expirationDate);\r\n MobileHost.notifyMobileFrontend(\"notifyAuthAccessTokenChanged\", accessToken, expirationDate);\r\n });\r\n\r\n // following will provide impl for device specific api.\r\n setupMobileRpc();\r\n }\r\n\r\n const socket = opt?.ipcHost?.socket ?? new IpcWebSocketBackend();\r\n opt = { ...opt, mobileHost: { ...opt?.mobileHost }, ipcHost: { ...opt?.ipcHost, socket } };\r\n\r\n const iModelHost = opt?.iModelHost ?? {};\r\n iModelHost.authorizationClient = authorizationClient;\r\n await NativeHost.startup({ ...opt, iModelHost });\r\n\r\n if (IpcHost.isValid)\r\n MobileAppHandler.register();\r\n\r\n const rpcInterfaces = opt?.mobileHost?.rpcInterfaces ?? [];\r\n\r\n MobileRpcManager.initializeImpl(rpcInterfaces);\r\n }\r\n}\r\n"]}
|
|
@@ -3,6 +3,8 @@ import { MobileRpcGateway } from "../common/MobileRpcProtocol";
|
|
|
3
3
|
export declare class MobileRpcServer {
|
|
4
4
|
private _pendingMessages;
|
|
5
5
|
private static _nextId;
|
|
6
|
+
private static readonly _rpcToken;
|
|
7
|
+
static get rpcToken(): string;
|
|
6
8
|
static interop: MobileRpcGateway;
|
|
7
9
|
private _server;
|
|
8
10
|
private _connection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileRpcServer.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileRpcServer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MobileRpcServer.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileRpcServer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,6BAA6B,CAAC;AAYlF,gBAAgB;AAChB,qBAAa,eAAe;IAmBP,OAAO,CAAC,gBAAgB;IAlB3C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAM;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAEpE,WAAkB,QAAQ,WAA6B;IAEvD,OAAc,OAAO,EAAE,gBAAgB,CAMrC;IAEF,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAiB;gBACR,gBAAgB,GAAE,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,SAAqB;IA8B/F,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,oBAAoB;IAiBrB,CAAC,MAAM,CAAC,OAAO,CAAC;CAUxB;AAKD,wBAAgB,cAAc,SAoE7B"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.MobileRpcServer = void 0;
|
|
8
8
|
exports.setupMobileRpc = setupMobileRpc;
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
9
10
|
const ws = require("ws");
|
|
10
11
|
const core_common_1 = require("@itwin/core-common");
|
|
11
12
|
const MobileRpcProtocol_1 = require("../common/MobileRpcProtocol");
|
|
@@ -17,6 +18,8 @@ let addon;
|
|
|
17
18
|
class MobileRpcServer {
|
|
18
19
|
_pendingMessages;
|
|
19
20
|
static _nextId = -1;
|
|
21
|
+
static _rpcToken = (0, node_crypto_1.randomBytes)(32).toString("hex");
|
|
22
|
+
static get rpcToken() { return this._rpcToken; }
|
|
20
23
|
static interop = {
|
|
21
24
|
handler: (_payload) => { throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Not implemented."); },
|
|
22
25
|
sendString: (_message, _connectionId) => { throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "No connection."); },
|
|
@@ -42,7 +45,17 @@ class MobileRpcServer {
|
|
|
42
45
|
*/
|
|
43
46
|
this._pingTimer = setInterval(() => { }, 5);
|
|
44
47
|
this._port = MobileRpcManager_1.MobileRpcConfiguration.setup.obtainPort();
|
|
45
|
-
this._server = new ws.Server({
|
|
48
|
+
this._server = new ws.Server({
|
|
49
|
+
host: "127.0.0.1", port: this._port,
|
|
50
|
+
verifyClient: (info) => {
|
|
51
|
+
const protocol = info.req.headers["sec-websocket-protocol"];
|
|
52
|
+
const expected = Buffer.from(`itwin-rpc.${MobileRpcServer._rpcToken}`);
|
|
53
|
+
if (typeof protocol !== "string")
|
|
54
|
+
return false;
|
|
55
|
+
const supplied = Buffer.from(protocol);
|
|
56
|
+
return supplied.length === expected.length && (0, node_crypto_1.timingSafeEqual)(supplied, expected);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
46
59
|
this._connectionId = ++MobileRpcServer._nextId;
|
|
47
60
|
MobileRpcServer.interop.connectionId = this._connectionId;
|
|
48
61
|
this._onListening();
|
|
@@ -59,7 +72,7 @@ class MobileRpcServer {
|
|
|
59
72
|
_notifyListening() {
|
|
60
73
|
MobileRpcServer.interop.port = this._port;
|
|
61
74
|
if (addon) {
|
|
62
|
-
addon.notifyListening(this._port);
|
|
75
|
+
addon.notifyListening(this._port, MobileRpcServer._rpcToken);
|
|
63
76
|
}
|
|
64
77
|
if (this._connectionId !== 0) {
|
|
65
78
|
MobileHost_1.MobileHost.reconnect(this._port);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileRpcServer.js","sourceRoot":"","sources":["../../../src/backend/MobileRpcServer.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\nimport * as ws from \"ws\";\r\nimport { IModelError } from \"@itwin/core-common\";\r\nimport { MobileRpcGateway, MobileRpcProtocol } from \"../common/MobileRpcProtocol\";\r\nimport { MobileRpcConfiguration } from \"../common/MobileRpcManager\";\r\nimport { MobileHost } from \"./MobileHost\";\r\nimport { BentleyStatus, expectDefined, ProcessDetector } from \"@itwin/core-bentley\";\r\n\r\ninterface MobileAddon {\r\n notifyListening: (port: number) => void;\r\n registerDeviceImpl: () => void;\r\n}\r\n\r\nlet addon: MobileAddon | undefined;\r\n\r\n/** @internal */\r\nexport class MobileRpcServer {\r\n private static _nextId = -1;\r\n\r\n public static interop: MobileRpcGateway = {\r\n handler: (_payload: ArrayBuffer | string) => { throw new IModelError(BentleyStatus.ERROR, \"Not implemented.\"); },\r\n sendString: (_message: string, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, \"No connection.\"); },\r\n sendBinary: (_message: Uint8Array, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, \"No connection.\"); },\r\n port: 0,\r\n connectionId: 0,\r\n };\r\n\r\n private _server: ws.Server;\r\n private _connection: ws | undefined;\r\n private _port: number;\r\n private _connectionId: number;\r\n private _pingTimer: NodeJS.Timeout;\r\n public constructor(private _pendingMessages: Array<string | Uint8Array> | undefined = undefined) {\r\n /* _pingTime is a fix for ios/mobile case where when the app moves into foreground from\r\n * background backend restart ws.Server and then notify frontend to reconnect. But ws.Server\r\n * listening event is not fired as node yield to kevent and wait for some io event to happen.\r\n * This causes a delay in reconnection which may be as long a 40 secs. To solve the issue we\r\n * create _pingTimer which causes kevent to yield back to uv poll so timer event can be fired.\r\n * This allow listening event to go through quickly (max 5ms). Once the listening event occur we\r\n * clear the timer. Here we use setInterval() just to make sure otherwise setTimeout() could equally\r\n * be effective\r\n */\r\n this._pingTimer = setInterval(() => { }, 5);\r\n this._port = MobileRpcConfiguration.setup.obtainPort();\r\n this._server = new ws.Server({ host: \"127.0.0.1\", port: this._port });\r\n this._connectionId = ++MobileRpcServer._nextId;\r\n MobileRpcServer.interop.connectionId = this._connectionId;\r\n this._onListening();\r\n this._onConnection();\r\n }\r\n\r\n private _onListening() {\r\n this._server.on(\"listening\", () => {\r\n const address = this._server.address() as ws.AddressInfo;\r\n this._port = address.port;\r\n clearInterval(this._pingTimer);\r\n this._notifyListening();\r\n });\r\n }\r\n\r\n private _notifyListening() {\r\n MobileRpcServer.interop.port = this._port;\r\n\r\n if (addon) {\r\n addon.notifyListening(this._port);\r\n }\r\n\r\n if (this._connectionId !== 0) {\r\n MobileHost.reconnect(this._port);\r\n }\r\n }\r\n\r\n private _onConnection() {\r\n this._server.on(\"connection\", (connection) => {\r\n this._connection = connection;\r\n this._connection.on(\"message\", (data) => this._onConnectionMessage(data));\r\n this._createSender();\r\n this._sendPending();\r\n (global as any).__iTwinJsRpcReady = true;\r\n MobileHost.onConnected.raiseEvent();\r\n });\r\n }\r\n\r\n private _createSender() {\r\n const sender = (message: string | Uint8Array, connectionId: number) => {\r\n if (connectionId !== this._connectionId) {\r\n return;\r\n }\r\n\r\n const connection = expectDefined(this._connection, \"No connection.\");\r\n connection.send(message, (err) => {\r\n if (err) {\r\n throw err;\r\n }\r\n });\r\n };\r\n\r\n MobileRpcServer.interop.sendString = sender;\r\n MobileRpcServer.interop.sendBinary = sender;\r\n }\r\n\r\n private _sendPending() {\r\n if (this._pendingMessages === undefined)\r\n return;\r\n\r\n const connection = expectDefined(this._connection, \"No connection.\");\r\n for (const message of this._pendingMessages) {\r\n connection.send(message, (err) => {\r\n if (err) {\r\n throw err;\r\n }\r\n });\r\n }\r\n this._pendingMessages.length = 0;\r\n }\r\n\r\n private _onConnectionMessage(data: ws.Data) {\r\n let message = data;\r\n if (Array.isArray(message)) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Unsupported data type\");\r\n }\r\n\r\n if (Buffer.isBuffer(message)) {\r\n if (message.byteOffset !== 0 || message.byteLength !== message.buffer.byteLength) {\r\n message = new Uint8Array(message.buffer, message.byteOffset, message.byteLength);\r\n } else {\r\n message = message.buffer;\r\n }\r\n }\r\n\r\n MobileRpcServer.interop.handler(message, this._connectionId);\r\n }\r\n\r\n public [Symbol.dispose]() {\r\n clearInterval(this._pingTimer);\r\n if (this._connection) {\r\n MobileRpcServer.interop.sendString = () => { };\r\n MobileRpcServer.interop.sendBinary = () => { };\r\n this._connection.close();\r\n }\r\n\r\n this._server.close();\r\n }\r\n}\r\n\r\nlet mobileReady = false;\r\nlet hasSuspended = false;\r\n\r\nexport function setupMobileRpc() {\r\n if (mobileReady) {\r\n return;\r\n }\r\n\r\n if (ProcessDetector.isMobileAppBackend) {\r\n addon = (process as any)._linkedBinding(\"iModelJsMobile\");\r\n addon?.registerDeviceImpl();\r\n }\r\n\r\n let server: MobileRpcServer | null = new MobileRpcServer();\r\n\r\n /* The UV event loop (internal to node) is retained by handles,\r\n such as those created for setInterval/setTimeout and client/server connections.\r\n In a simple app, the RPC server may be the only handle retaining the UV loop.\r\n Thus, we install a temporary timer on suspend to prevent the loop from exiting prematurely.\r\n */\r\n let retainUvLoop: NodeJS.Timeout | undefined;\r\n const pendingMessages: Array<string | Uint8Array> = [];\r\n\r\n function usePendingSender() {\r\n const sender = (message: string | Uint8Array, _connectionId: number) => {\r\n pendingMessages.push(message);\r\n };\r\n MobileRpcServer.interop.sendString = sender;\r\n MobileRpcServer.interop.sendBinary = sender;\r\n }\r\n\r\n MobileHost.onEnterBackground.addListener(() => {\r\n hasSuspended = true;\r\n\r\n if (server === null) {\r\n return;\r\n }\r\n\r\n retainUvLoop = setInterval(() => { }, 1000);\r\n server[Symbol.dispose]();\r\n usePendingSender();\r\n server = null;\r\n (global as any).__iTwinJsRpcReady = false;\r\n });\r\n\r\n MobileHost.onEnterForeground.addListener(() => {\r\n if (!hasSuspended) {\r\n return;\r\n }\r\n\r\n server = new MobileRpcServer(pendingMessages);\r\n clearInterval(retainUvLoop);\r\n retainUvLoop = undefined;\r\n });\r\n\r\n MobileHost.onWillTerminate.addListener(() => {\r\n if (typeof (retainUvLoop) !== \"undefined\") {\r\n clearInterval(retainUvLoop);\r\n retainUvLoop = undefined;\r\n }\r\n\r\n if (server === null) {\r\n return;\r\n }\r\n\r\n server[Symbol.dispose]();\r\n server = null;\r\n });\r\n\r\n MobileRpcProtocol.obtainInterop = () => MobileRpcServer.interop;\r\n mobileReady = true;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"MobileRpcServer.js","sourceRoot":"","sources":["../../../src/backend/MobileRpcServer.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\nimport { randomBytes, timingSafeEqual } from \"node:crypto\";\r\nimport * as ws from \"ws\";\r\nimport { IModelError } from \"@itwin/core-common\";\r\nimport { MobileRpcGateway, MobileRpcProtocol } from \"../common/MobileRpcProtocol\";\r\nimport { MobileRpcConfiguration } from \"../common/MobileRpcManager\";\r\nimport { MobileHost } from \"./MobileHost\";\r\nimport { BentleyStatus, expectDefined, ProcessDetector } from \"@itwin/core-bentley\";\r\n\r\ninterface MobileAddon {\r\n notifyListening: (port: number, rpcToken: string) => void;\r\n registerDeviceImpl: () => void;\r\n}\r\n\r\nlet addon: MobileAddon | undefined;\r\n\r\n/** @internal */\r\nexport class MobileRpcServer {\r\n private static _nextId = -1;\r\n private static readonly _rpcToken = randomBytes(32).toString(\"hex\");\r\n\r\n public static get rpcToken() { return this._rpcToken; }\r\n\r\n public static interop: MobileRpcGateway = {\r\n handler: (_payload: ArrayBuffer | string) => { throw new IModelError(BentleyStatus.ERROR, \"Not implemented.\"); },\r\n sendString: (_message: string, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, \"No connection.\"); },\r\n sendBinary: (_message: Uint8Array, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, \"No connection.\"); },\r\n port: 0,\r\n connectionId: 0,\r\n };\r\n\r\n private _server: ws.Server;\r\n private _connection: ws | undefined;\r\n private _port: number;\r\n private _connectionId: number;\r\n private _pingTimer: NodeJS.Timeout;\r\n public constructor(private _pendingMessages: Array<string | Uint8Array> | undefined = undefined) {\r\n /* _pingTime is a fix for ios/mobile case where when the app moves into foreground from\r\n * background backend restart ws.Server and then notify frontend to reconnect. But ws.Server\r\n * listening event is not fired as node yield to kevent and wait for some io event to happen.\r\n * This causes a delay in reconnection which may be as long a 40 secs. To solve the issue we\r\n * create _pingTimer which causes kevent to yield back to uv poll so timer event can be fired.\r\n * This allow listening event to go through quickly (max 5ms). Once the listening event occur we\r\n * clear the timer. Here we use setInterval() just to make sure otherwise setTimeout() could equally\r\n * be effective\r\n */\r\n this._pingTimer = setInterval(() => { }, 5);\r\n this._port = MobileRpcConfiguration.setup.obtainPort();\r\n this._server = new ws.Server({\r\n host: \"127.0.0.1\", port: this._port,\r\n verifyClient: (info: Parameters<ws.VerifyClientCallbackSync>[0]) => {\r\n const protocol = info.req.headers[\"sec-websocket-protocol\"];\r\n const expected = Buffer.from(`itwin-rpc.${MobileRpcServer._rpcToken}`);\r\n if (typeof protocol !== \"string\")\r\n return false;\r\n\r\n const supplied = Buffer.from(protocol);\r\n return supplied.length === expected.length && timingSafeEqual(supplied, expected);\r\n },\r\n });\r\n this._connectionId = ++MobileRpcServer._nextId;\r\n MobileRpcServer.interop.connectionId = this._connectionId;\r\n this._onListening();\r\n this._onConnection();\r\n }\r\n\r\n private _onListening() {\r\n this._server.on(\"listening\", () => {\r\n const address = this._server.address() as ws.AddressInfo;\r\n this._port = address.port;\r\n clearInterval(this._pingTimer);\r\n this._notifyListening();\r\n });\r\n }\r\n\r\n private _notifyListening() {\r\n MobileRpcServer.interop.port = this._port;\r\n\r\n if (addon) {\r\n addon.notifyListening(this._port, MobileRpcServer._rpcToken);\r\n }\r\n\r\n if (this._connectionId !== 0) {\r\n MobileHost.reconnect(this._port);\r\n }\r\n }\r\n\r\n private _onConnection() {\r\n this._server.on(\"connection\", (connection) => {\r\n this._connection = connection;\r\n this._connection.on(\"message\", (data) => this._onConnectionMessage(data));\r\n this._createSender();\r\n this._sendPending();\r\n (global as any).__iTwinJsRpcReady = true;\r\n MobileHost.onConnected.raiseEvent();\r\n });\r\n }\r\n\r\n private _createSender() {\r\n const sender = (message: string | Uint8Array, connectionId: number) => {\r\n if (connectionId !== this._connectionId) {\r\n return;\r\n }\r\n\r\n const connection = expectDefined(this._connection, \"No connection.\");\r\n connection.send(message, (err) => {\r\n if (err) {\r\n throw err;\r\n }\r\n });\r\n };\r\n\r\n MobileRpcServer.interop.sendString = sender;\r\n MobileRpcServer.interop.sendBinary = sender;\r\n }\r\n\r\n private _sendPending() {\r\n if (this._pendingMessages === undefined)\r\n return;\r\n\r\n const connection = expectDefined(this._connection, \"No connection.\");\r\n for (const message of this._pendingMessages) {\r\n connection.send(message, (err) => {\r\n if (err) {\r\n throw err;\r\n }\r\n });\r\n }\r\n this._pendingMessages.length = 0;\r\n }\r\n\r\n private _onConnectionMessage(data: ws.Data) {\r\n let message = data;\r\n if (Array.isArray(message)) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Unsupported data type\");\r\n }\r\n\r\n if (Buffer.isBuffer(message)) {\r\n if (message.byteOffset !== 0 || message.byteLength !== message.buffer.byteLength) {\r\n message = new Uint8Array(message.buffer, message.byteOffset, message.byteLength);\r\n } else {\r\n message = message.buffer;\r\n }\r\n }\r\n\r\n MobileRpcServer.interop.handler(message, this._connectionId);\r\n }\r\n\r\n public [Symbol.dispose]() {\r\n clearInterval(this._pingTimer);\r\n if (this._connection) {\r\n MobileRpcServer.interop.sendString = () => { };\r\n MobileRpcServer.interop.sendBinary = () => { };\r\n this._connection.close();\r\n }\r\n\r\n this._server.close();\r\n }\r\n}\r\n\r\nlet mobileReady = false;\r\nlet hasSuspended = false;\r\n\r\nexport function setupMobileRpc() {\r\n if (mobileReady) {\r\n return;\r\n }\r\n\r\n if (ProcessDetector.isMobileAppBackend) {\r\n addon = (process as any)._linkedBinding(\"iModelJsMobile\");\r\n addon?.registerDeviceImpl();\r\n }\r\n\r\n let server: MobileRpcServer | null = new MobileRpcServer();\r\n\r\n /* The UV event loop (internal to node) is retained by handles,\r\n such as those created for setInterval/setTimeout and client/server connections.\r\n In a simple app, the RPC server may be the only handle retaining the UV loop.\r\n Thus, we install a temporary timer on suspend to prevent the loop from exiting prematurely.\r\n */\r\n let retainUvLoop: NodeJS.Timeout | undefined;\r\n const pendingMessages: Array<string | Uint8Array> = [];\r\n\r\n function usePendingSender() {\r\n const sender = (message: string | Uint8Array, _connectionId: number) => {\r\n pendingMessages.push(message);\r\n };\r\n MobileRpcServer.interop.sendString = sender;\r\n MobileRpcServer.interop.sendBinary = sender;\r\n }\r\n\r\n MobileHost.onEnterBackground.addListener(() => {\r\n hasSuspended = true;\r\n\r\n if (server === null) {\r\n return;\r\n }\r\n\r\n retainUvLoop = setInterval(() => { }, 1000);\r\n server[Symbol.dispose]();\r\n usePendingSender();\r\n server = null;\r\n (global as any).__iTwinJsRpcReady = false;\r\n });\r\n\r\n MobileHost.onEnterForeground.addListener(() => {\r\n if (!hasSuspended) {\r\n return;\r\n }\r\n\r\n server = new MobileRpcServer(pendingMessages);\r\n clearInterval(retainUvLoop);\r\n retainUvLoop = undefined;\r\n });\r\n\r\n MobileHost.onWillTerminate.addListener(() => {\r\n if (typeof (retainUvLoop) !== \"undefined\") {\r\n clearInterval(retainUvLoop);\r\n retainUvLoop = undefined;\r\n }\r\n\r\n if (server === null) {\r\n return;\r\n }\r\n\r\n server[Symbol.dispose]();\r\n server = null;\r\n });\r\n\r\n MobileRpcProtocol.obtainInterop = () => MobileRpcServer.interop;\r\n mobileReady = true;\r\n}\r\n"]}
|
|
@@ -29,6 +29,7 @@ export declare class MobileRpcProtocol extends RpcProtocol {
|
|
|
29
29
|
private _partialFulfillment;
|
|
30
30
|
private _partialData;
|
|
31
31
|
private _port;
|
|
32
|
+
private _rpcToken;
|
|
32
33
|
private _transport?;
|
|
33
34
|
private _ipc;
|
|
34
35
|
static obtainInterop(): MobileRpcGateway;
|
|
@@ -36,6 +37,7 @@ export declare class MobileRpcProtocol extends RpcProtocol {
|
|
|
36
37
|
static encodeResponse(fulfillment: RpcRequestFulfillment): MobileRpcChunks;
|
|
37
38
|
constructor(configuration: MobileRpcConfiguration, endPoint: RpcEndpoint);
|
|
38
39
|
private initializeFrontend;
|
|
40
|
+
private setRpcToken;
|
|
39
41
|
private connect;
|
|
40
42
|
private connectMessageHandler;
|
|
41
43
|
private connectOpenHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileRpcProtocol.d.ts","sourceRoot":"","sources":["../../../src/common/MobileRpcProtocol.ts"],"names":[],"mappings":"AAIA;;GAEG;AAGH,OAAO,EACsB,WAAW,EAAE,WAAW,EAAiD,qBAAqB,EAE1H,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,gBAAgB;AAChB,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;AAEzD,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,UAAU,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IACzC,MAAM,EAAE,SAAS,CAAsB;IACvC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAa;IAC3D,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,oBAAoB,CAAwB;IACpD,SAAgB,WAAW,0BAAoB;IAC/C,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,mBAAmB,CAAgD;IAC3E,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,UAAU,CAAC,CAAsB;IACzC,OAAO,CAAC,IAAI,CAAqB;WACnB,aAAa,IAAI,gBAAgB;WAE3B,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;WAOxE,cAAc,CAAC,WAAW,EAAE,qBAAqB,GAAG,eAAe;gBAUrE,aAAa,EAAE,sBAAsB,EAAE,QAAQ,EAAE,WAAW;IAaxE,OAAO,CAAC,kBAAkB;
|
|
1
|
+
{"version":3,"file":"MobileRpcProtocol.d.ts","sourceRoot":"","sources":["../../../src/common/MobileRpcProtocol.ts"],"names":[],"mappings":"AAIA;;GAEG;AAGH,OAAO,EACsB,WAAW,EAAE,WAAW,EAAiD,qBAAqB,EAE1H,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,gBAAgB;AAChB,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;AAEzD,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,UAAU,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IACzC,MAAM,EAAE,SAAS,CAAsB;IACvC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAa;IAC3D,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,oBAAoB,CAAwB;IACpD,SAAgB,WAAW,0BAAoB;IAC/C,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,mBAAmB,CAAgD;IAC3E,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,UAAU,CAAC,CAAsB;IACzC,OAAO,CAAC,IAAI,CAAqB;WACnB,aAAa,IAAI,gBAAgB;WAE3B,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;WAOxE,cAAc,CAAC,WAAW,EAAE,qBAAqB,GAAG,eAAe;gBAUrE,aAAa,EAAE,sBAAsB,EAAE,QAAQ,EAAE,WAAW;IAaxE,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,KAAK;IAcb,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,OAAO;IAmBf,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,wBAAwB;YAYlB,aAAa;IAqBpB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAK7C,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;CAW3E"}
|
|
@@ -30,6 +30,7 @@ class MobileRpcProtocol extends core_common_1.RpcProtocol {
|
|
|
30
30
|
_partialFulfillment = undefined;
|
|
31
31
|
_partialData = [];
|
|
32
32
|
_port = 0;
|
|
33
|
+
_rpcToken = "";
|
|
33
34
|
_transport;
|
|
34
35
|
_ipc;
|
|
35
36
|
static obtainInterop() { throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Not implemented."); }
|
|
@@ -67,8 +68,10 @@ class MobileRpcProtocol extends core_common_1.RpcProtocol {
|
|
|
67
68
|
throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "MobileRpcProtocol require 'port' parameter");
|
|
68
69
|
}
|
|
69
70
|
this._port = MobileRpcManager_1.MobileRpcConfiguration.args.port;
|
|
71
|
+
this.setRpcToken(window.__iTwinJsRpcToken ?? MobileRpcManager_1.MobileRpcConfiguration.args.rpcToken);
|
|
70
72
|
this.connect(this._port, false);
|
|
71
|
-
window._imodeljs_rpc_reconnect = (port) => {
|
|
73
|
+
window._imodeljs_rpc_reconnect = (port, rpcToken) => {
|
|
74
|
+
this.setRpcToken(rpcToken);
|
|
72
75
|
this.socket.close();
|
|
73
76
|
window.location.hash = window.location.hash.replace(`port=${this._port}`, `port=${port}`);
|
|
74
77
|
this._port = port;
|
|
@@ -78,8 +81,13 @@ class MobileRpcProtocol extends core_common_1.RpcProtocol {
|
|
|
78
81
|
this._transport = transport;
|
|
79
82
|
core_common_1.RpcPushChannel.setup(transport);
|
|
80
83
|
}
|
|
84
|
+
setRpcToken(rpcToken) {
|
|
85
|
+
if (typeof rpcToken !== "string" || !/^[0-9a-f]{64}$/.test(rpcToken))
|
|
86
|
+
throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "MobileRpcProtocol requires a native RPC authentication token. Update the mobile native runtime and startup configuration.");
|
|
87
|
+
this._rpcToken = rpcToken;
|
|
88
|
+
}
|
|
81
89
|
connect(port, reset) {
|
|
82
|
-
const socket = new WebSocket(`ws://127.0.0.1:${port}`);
|
|
90
|
+
const socket = new WebSocket(`ws://127.0.0.1:${port}`, `itwin-rpc.${this._rpcToken}`);
|
|
83
91
|
socket.binaryType = "arraybuffer";
|
|
84
92
|
this.connectMessageHandler(socket);
|
|
85
93
|
this.connectOpenHandler(socket, reset);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileRpcProtocol.js","sourceRoot":"","sources":["../../../src/common/MobileRpcProtocol.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module RpcInterface\r\n */\r\n\r\nimport { BentleyStatus, expectDefined } from \"@itwin/core-bentley\";\r\nimport {\r\n IModelError, IpcWebSocket, RpcEndpoint, RpcProtocol, RpcPushChannel, RpcPushConnection, RpcRequest, RpcRequestFulfillment, RpcSerializedValue,\r\n SerializedRpcRequest,\r\n} from \"@itwin/core-common\";\r\nimport { MobileEventLoop } from \"./MobileEventLoop\";\r\nimport { MobileIpcTransport } from \"./MobileIpc\";\r\nimport { MobilePushConnection, MobilePushTransport } from \"./MobilePush\";\r\nimport { MobileRpcConfiguration } from \"./MobileRpcManager\";\r\nimport { MobileRpcRequest } from \"./MobileRpcRequest\";\r\n\r\n/* eslint-disable @typescript-eslint/no-deprecated */\r\n\r\n/** @internal */\r\nexport type MobileRpcChunks = Array<string | Uint8Array>;\r\n\r\n/** @internal */\r\nexport interface MobileRpcGateway {\r\n handler: (payload: ArrayBuffer | string, connectionId: number) => void;\r\n sendString: (message: string, connectionId: number) => void;\r\n sendBinary: (message: Uint8Array, connectionId: number) => void;\r\n port: number;\r\n connectionId: number;\r\n}\r\n\r\n/** RPC interface protocol for an Mobile-based application.\r\n * @internal\r\n */\r\nexport class MobileRpcProtocol extends RpcProtocol {\r\n public socket: WebSocket = (undefined as any);\r\n public requests: Map<string, MobileRpcRequest> = new Map();\r\n private _pending: MobileRpcChunks[] = [];\r\n private _capacity: number = Number.MAX_SAFE_INTEGER;\r\n private _sendInterval: number | undefined = undefined;\r\n private _sendIntervalHandler = () => this.trySend();\r\n public readonly requestType = MobileRpcRequest;\r\n private _partialRequest: SerializedRpcRequest | undefined = undefined;\r\n private _partialFulfillment: RpcRequestFulfillment | undefined = undefined;\r\n private _partialData: Uint8Array[] = [];\r\n private _port: number = 0;\r\n private _transport?: MobilePushTransport;\r\n private _ipc: MobileIpcTransport;\r\n public static obtainInterop(): MobileRpcGateway { throw new IModelError(BentleyStatus.ERROR, \"Not implemented.\"); }\r\n\r\n public static async encodeRequest(request: MobileRpcRequest): Promise<MobileRpcChunks> {\r\n const serialized = await request.protocol.serialize(request);\r\n const data = serialized.parameters.data;\r\n serialized.parameters.data = data.map((v) => v.byteLength) as any[];\r\n return [JSON.stringify(serialized), ...data];\r\n }\r\n\r\n public static encodeResponse(fulfillment: RpcRequestFulfillment): MobileRpcChunks {\r\n const data = fulfillment.result.data;\r\n fulfillment.result.data = data.map((v) => v.byteLength) as any[];\r\n const raw = fulfillment.rawResult;\r\n fulfillment.rawResult = undefined;\r\n const encoded = [JSON.stringify(fulfillment), ...data];\r\n fulfillment.rawResult = raw;\r\n return encoded;\r\n }\r\n\r\n constructor(configuration: MobileRpcConfiguration, endPoint: RpcEndpoint) {\r\n super(configuration);\r\n\r\n if (endPoint === RpcEndpoint.Frontend) {\r\n this.initializeFrontend();\r\n } else if (endPoint === RpcEndpoint.Backend) {\r\n this.initializeBackend();\r\n }\r\n\r\n this._ipc = new MobileIpcTransport(this);\r\n IpcWebSocket.transport = this._ipc;\r\n }\r\n\r\n private initializeFrontend() {\r\n if (typeof (WebSocket) === \"undefined\") {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol on frontend require websocket to work\");\r\n }\r\n if (!MobileRpcConfiguration.args.port) {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol require 'port' parameter\");\r\n }\r\n\r\n this._port = MobileRpcConfiguration.args.port;\r\n this.connect(this._port, false);\r\n\r\n (window as any)._imodeljs_rpc_reconnect = (port: number) => {\r\n this.socket.close();\r\n window.location.hash = window.location.hash.replace(`port=${this._port}`, `port=${port}`);\r\n this._port = port;\r\n this.connect(port, true);\r\n };\r\n\r\n const transport = new MobilePushTransport(this);\r\n this._transport = transport;\r\n RpcPushChannel.setup(transport);\r\n }\r\n\r\n private connect(port: number, reset: boolean) {\r\n const socket = new WebSocket(`ws://127.0.0.1:${port}`);\r\n socket.binaryType = \"arraybuffer\";\r\n this.connectMessageHandler(socket);\r\n this.connectOpenHandler(socket, reset);\r\n this.connectErrorHandler(socket);\r\n this.socket = socket;\r\n }\r\n\r\n private connectMessageHandler(socket: WebSocket) {\r\n socket.addEventListener(\"message\", async (event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n this.handleMessageFromBackend(event.data);\r\n });\r\n }\r\n\r\n private connectOpenHandler(socket: WebSocket, reset: boolean) {\r\n socket.addEventListener(\"open\", (_event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n if (reset) {\r\n this.reset();\r\n\r\n const requests = new Map(RpcRequest.activeRequests);\r\n requests.forEach((req) => {\r\n req.cancel();\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n req.submit();\r\n });\r\n }\r\n\r\n this.scheduleSend();\r\n });\r\n }\r\n\r\n private connectErrorHandler(socket: WebSocket) {\r\n socket.addEventListener(\"error\", (_event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n throw new IModelError(BentleyStatus.ERROR, \"Socket error.\");\r\n });\r\n }\r\n\r\n private reset() {\r\n this.requests.clear();\r\n this._capacity = Number.MAX_SAFE_INTEGER;\r\n\r\n if (typeof (this._sendInterval) !== \"undefined\") {\r\n window.clearInterval(this._sendInterval);\r\n this._sendInterval = undefined;\r\n }\r\n\r\n this._partialRequest = undefined;\r\n this._partialFulfillment = undefined;\r\n this._partialData.length = 0;\r\n }\r\n\r\n private scheduleSend() {\r\n if (!this._pending.length) {\r\n return;\r\n }\r\n\r\n this.trySend();\r\n\r\n if (this._pending.length && typeof (this._sendInterval) === \"undefined\") {\r\n this._sendInterval = window.setInterval(this._sendIntervalHandler, 0);\r\n }\r\n }\r\n\r\n private trySend() {\r\n if (this.socket.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n while (this._capacity !== 0 && this._pending.length) {\r\n --this._capacity;\r\n const next = expectDefined(this._pending.shift(), \"Expected pending RPC chunk after queue length check.\");\r\n for (const chunk of next) {\r\n this.socket.send(chunk);\r\n }\r\n }\r\n\r\n if (!this._pending.length && typeof (this._sendInterval) !== \"undefined\") {\r\n window.clearInterval(this._sendInterval);\r\n this._sendInterval = undefined;\r\n }\r\n }\r\n\r\n private handleMessageFromBackend(data: string | ArrayBuffer) {\r\n if (typeof (data) === \"string\") {\r\n this.handleStringFromBackend(data);\r\n } else {\r\n this.handleBinaryFromBackend(data);\r\n }\r\n }\r\n\r\n private handleStringFromBackend(data: string) {\r\n if (this._partialFulfillment) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (already receiving response).\");\r\n }\r\n\r\n const response = JSON.parse(data) as RpcRequestFulfillment;\r\n this._partialFulfillment = response;\r\n\r\n if (!response.result.data.length) {\r\n this.notifyResponse();\r\n }\r\n }\r\n\r\n private handleBinaryFromBackend(data: ArrayBuffer) {\r\n const fulfillment = this._partialFulfillment;\r\n if (!fulfillment) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no response received).\");\r\n }\r\n\r\n this._partialData.push(new Uint8Array(data));\r\n if (this._partialData.length === fulfillment.result.data.length) {\r\n this.notifyResponse();\r\n }\r\n }\r\n\r\n private notifyResponse() {\r\n const response = this._partialFulfillment;\r\n if (!response) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no response exists).\");\r\n }\r\n\r\n ++this._capacity;\r\n this.consumePartialData(response.result);\r\n this._partialFulfillment = undefined;\r\n\r\n if (this._transport && this._transport.consume(response)) {\r\n return;\r\n }\r\n\r\n if (this._ipc.consumeResponse(response)) {\r\n return;\r\n }\r\n\r\n const request = this.requests.get(response.id) as MobileRpcRequest;\r\n this.requests.delete(response.id);\r\n request.notifyResponse(response);\r\n }\r\n\r\n private consumePartialData(value: RpcSerializedValue) {\r\n for (let i = 0, l = value.data.length; i !== l; ++i) {\r\n value.data[i] = this._partialData[i];\r\n }\r\n\r\n this._partialData.length = 0;\r\n }\r\n\r\n private initializeBackend() {\r\n const mobilegateway = MobileRpcProtocol.obtainInterop();\r\n if (mobilegateway === undefined || mobilegateway == null) {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol on backend require native bridge to be setup\");\r\n }\r\n\r\n mobilegateway.handler = (payload, connectionId) => this.handleMessageFromFrontend(payload, connectionId);\r\n RpcPushConnection.for = (channel, client) => new MobilePushConnection(channel, client, this);\r\n RpcPushChannel.enabled = true;\r\n }\r\n\r\n private handleMessageFromFrontend(data: string | ArrayBuffer, connectionId: number) {\r\n if (typeof (data) === \"string\") {\r\n this.handleStringFromFrontend(data, connectionId);\r\n } else {\r\n this.handleBinaryFromFrontend(data, connectionId);\r\n }\r\n }\r\n\r\n private handleStringFromFrontend(data: string, connection: number) {\r\n if (this._partialRequest) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (already receiving request).\");\r\n }\r\n\r\n const request = JSON.parse(data) as SerializedRpcRequest;\r\n this._partialRequest = request;\r\n\r\n if (!request.parameters.data.length) {\r\n this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n\r\n private handleBinaryFromFrontend(data: ArrayBuffer, connection: number) {\r\n const request = this._partialRequest;\r\n if (!request) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no request received).\");\r\n }\r\n\r\n this._partialData.push(new Uint8Array(data));\r\n if (this._partialData.length === request.parameters.data.length) {\r\n this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n\r\n private async notifyRequest(connection: number) {\r\n const request = this._partialRequest;\r\n if (!request) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no request exists).\");\r\n }\r\n\r\n this.consumePartialData(request.parameters);\r\n this._partialRequest = undefined;\r\n\r\n if (this._ipc.consumeRequest(request)) {\r\n return;\r\n }\r\n\r\n MobileEventLoop.addTask();\r\n const fulfillment = await this.fulfill(request);\r\n MobileEventLoop.removeTask();\r\n\r\n const response = MobileRpcProtocol.encodeResponse(fulfillment);\r\n this.sendToFrontend(response, connection);\r\n }\r\n\r\n public sendToBackend(message: MobileRpcChunks): void {\r\n this._pending.push(message);\r\n this.scheduleSend();\r\n }\r\n\r\n public sendToFrontend(message: MobileRpcChunks, connection?: number): void {\r\n const mobilegateway = MobileRpcProtocol.obtainInterop();\r\n\r\n for (const chunk of message) {\r\n if (typeof (chunk) === \"string\") {\r\n mobilegateway.sendString(chunk, connection || mobilegateway.connectionId);\r\n } else {\r\n mobilegateway.sendBinary(chunk, connection || mobilegateway.connectionId);\r\n }\r\n }\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"MobileRpcProtocol.js","sourceRoot":"","sources":["../../../src/common/MobileRpcProtocol.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,sDAAmE;AACnE,oDAG4B;AAC5B,uDAAoD;AACpD,2CAAiD;AACjD,6CAAyE;AACzE,yDAA4D;AAC5D,yDAAsD;AAgBtD;;GAEG;AACH,MAAa,iBAAkB,SAAQ,yBAAW;IACzC,MAAM,GAAe,SAAiB,CAAC;IACvC,QAAQ,GAAkC,IAAI,GAAG,EAAE,CAAC;IACnD,QAAQ,GAAsB,EAAE,CAAC;IACjC,SAAS,GAAW,MAAM,CAAC,gBAAgB,CAAC;IAC5C,aAAa,GAAuB,SAAS,CAAC;IAC9C,oBAAoB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IACpC,WAAW,GAAG,mCAAgB,CAAC;IACvC,eAAe,GAAqC,SAAS,CAAC;IAC9D,mBAAmB,GAAsC,SAAS,CAAC;IACnE,YAAY,GAAiB,EAAE,CAAC;IAChC,KAAK,GAAW,CAAC,CAAC;IAClB,SAAS,GAAW,EAAE,CAAC;IACvB,UAAU,CAAuB;IACjC,IAAI,CAAqB;IAC1B,MAAM,CAAC,aAAa,KAAuB,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAE5G,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAyB;QACzD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC;QACxC,UAAU,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAU,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC/C,CAAC;IAEM,MAAM,CAAC,cAAc,CAAC,WAAkC;QAC7D,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC;QACrC,WAAW,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAU,CAAC;QACjE,MAAM,GAAG,GAAG,WAAW,CAAC,SAAS,CAAC;QAClC,WAAW,CAAC,SAAS,GAAG,SAAS,CAAC;QAClC,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QACvD,WAAW,CAAC,SAAS,GAAG,GAAG,CAAC;QAC5B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,YAAY,aAAqC,EAAE,QAAqB;QACtE,KAAK,CAAC,aAAa,CAAC,CAAC;QAErB,IAAI,QAAQ,KAAK,yBAAW,CAAC,QAAQ,EAAE,CAAC;YACtC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC;aAAM,IAAI,QAAQ,KAAK,yBAAW,CAAC,OAAO,EAAE,CAAC;YAC5C,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,IAAI,GAAG,IAAI,8BAAkB,CAAC,IAAI,CAAC,CAAC;QACzC,0BAAY,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC;IACrC,CAAC;IAEO,kBAAkB;QACxB,IAAI,OAAO,CAAC,SAAS,CAAC,KAAK,WAAW,EAAE,CAAC;YACvC,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,yDAAyD,CAAC,CAAC;QACxG,CAAC;QACD,IAAI,CAAC,yCAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACtC,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,4CAA4C,CAAC,CAAC;QAC3F,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,yCAAsB,CAAC,IAAI,CAAC,IAAI,CAAC;QAC9C,IAAI,CAAC,WAAW,CAAE,MAAc,CAAC,iBAAiB,IAAI,yCAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAE/B,MAAc,CAAC,uBAAuB,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAE;YAC3E,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,KAAK,EAAE,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC;YAC1F,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC3B,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,gCAAmB,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,4BAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAEO,WAAW,CAAC,QAAiB;QACnC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC;YAClE,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,2HAA2H,CAAC,CAAC;QAE1K,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAEO,OAAO,CAAC,IAAY,EAAE,KAAc;QAC1C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,kBAAkB,IAAI,EAAE,EAAE,aAAa,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QACtF,MAAM,CAAC,UAAU,GAAG,aAAa,CAAC;QAClC,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAEO,qBAAqB,CAAC,MAAiB;QAC7C,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACjD,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,kBAAkB,CAAC,MAAiB,EAAE,KAAc;QAC1D,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;YACzC,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,KAAK,EAAE,CAAC;gBAEb,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,wBAAU,CAAC,cAAc,CAAC,CAAC;gBACpD,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;oBACvB,GAAG,CAAC,MAAM,EAAE,CAAC;oBACb,mEAAmE;oBACnE,GAAG,CAAC,MAAM,EAAE,CAAC;gBACf,CAAC,CAAC,CAAC;YACL,CAAC;YAED,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,mBAAmB,CAAC,MAAiB;QAC3C,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE;YAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,gBAAgB,CAAC;QAEzC,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,WAAW,EAAE,CAAC;YAChD,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACzC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;QACrC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IAEO,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,WAAW,EAAE,CAAC;YACxE,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAEO,OAAO;QACb,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpD,EAAE,IAAI,CAAC,SAAS,CAAC;YACjB,MAAM,IAAI,GAAG,IAAA,4BAAa,EAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,sDAAsD,CAAC,CAAC;YAC1G,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;gBACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,WAAW,EAAE,CAAC;YACzE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACzC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QACjC,CAAC;IACH,CAAC;IAEO,wBAAwB,CAAC,IAA0B;QACzD,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAEO,uBAAuB,CAAC,IAAY;QAC1C,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,6CAA6C,CAAC,CAAC;QAC5F,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA0B,CAAC;QAC3D,IAAI,CAAC,mBAAmB,GAAG,QAAQ,CAAC;QAEpC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjC,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,uBAAuB,CAAC,IAAiB;QAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,mBAAmB,CAAC;QAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,uCAAuC,CAAC,CAAC;QACtF,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAChE,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC;QAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,qCAAqC,CAAC,CAAC;QACpF,CAAC;QAED,EAAE,IAAI,CAAC,SAAS,CAAC;QACjB,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;QAErC,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzD,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxC,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAqB,CAAC;QACnE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAClC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAEO,kBAAkB,CAAC,KAAyB;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IAEO,iBAAiB;QACvB,MAAM,aAAa,GAAG,iBAAiB,CAAC,aAAa,EAAE,CAAC;QACxD,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YACzD,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,gEAAgE,CAAC,CAAC;QAC/G,CAAC;QAED,aAAa,CAAC,OAAO,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,CAAC,IAAI,CAAC,yBAAyB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACzG,+BAAiB,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,iCAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAC7F,4BAAc,CAAC,OAAO,GAAG,IAAI,CAAC;IAChC,CAAC;IAEO,yBAAyB,CAAC,IAA0B,EAAE,YAAoB;QAChF,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAEO,wBAAwB,CAAC,IAAY,EAAE,UAAkB;QAC/D,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,4CAA4C,CAAC,CAAC;QAC3F,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyB,CAAC;QACzD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC;QAE/B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,8DAA8D;QAChG,CAAC;IACH,CAAC;IAEO,wBAAwB,CAAC,IAAiB,EAAE,UAAkB;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC;QACrC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,sCAAsC,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAChE,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,8DAA8D;QAChG,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,UAAkB;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC;QACrC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,yBAAW,CAAC,4BAAa,CAAC,KAAK,EAAE,oCAAoC,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QAEjC,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QAED,iCAAe,CAAC,OAAO,EAAE,CAAC;QAC1B,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAChD,iCAAe,CAAC,UAAU,EAAE,CAAC;QAE7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC/D,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC5C,CAAC;IAEM,aAAa,CAAC,OAAwB;QAC3C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAEM,cAAc,CAAC,OAAwB,EAAE,UAAmB;QACjE,MAAM,aAAa,GAAG,iBAAiB,CAAC,aAAa,EAAE,CAAC;QAExD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAChC,aAAa,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC;YAC5E,CAAC;iBAAM,CAAC;gBACN,aAAa,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;IACH,CAAC;CACF;AA/TD,8CA+TC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module RpcInterface\r\n */\r\n\r\nimport { BentleyStatus, expectDefined } from \"@itwin/core-bentley\";\r\nimport {\r\n IModelError, IpcWebSocket, RpcEndpoint, RpcProtocol, RpcPushChannel, RpcPushConnection, RpcRequest, RpcRequestFulfillment, RpcSerializedValue,\r\n SerializedRpcRequest,\r\n} from \"@itwin/core-common\";\r\nimport { MobileEventLoop } from \"./MobileEventLoop\";\r\nimport { MobileIpcTransport } from \"./MobileIpc\";\r\nimport { MobilePushConnection, MobilePushTransport } from \"./MobilePush\";\r\nimport { MobileRpcConfiguration } from \"./MobileRpcManager\";\r\nimport { MobileRpcRequest } from \"./MobileRpcRequest\";\r\n\r\n/* eslint-disable @typescript-eslint/no-deprecated */\r\n\r\n/** @internal */\r\nexport type MobileRpcChunks = Array<string | Uint8Array>;\r\n\r\n/** @internal */\r\nexport interface MobileRpcGateway {\r\n handler: (payload: ArrayBuffer | string, connectionId: number) => void;\r\n sendString: (message: string, connectionId: number) => void;\r\n sendBinary: (message: Uint8Array, connectionId: number) => void;\r\n port: number;\r\n connectionId: number;\r\n}\r\n\r\n/** RPC interface protocol for an Mobile-based application.\r\n * @internal\r\n */\r\nexport class MobileRpcProtocol extends RpcProtocol {\r\n public socket: WebSocket = (undefined as any);\r\n public requests: Map<string, MobileRpcRequest> = new Map();\r\n private _pending: MobileRpcChunks[] = [];\r\n private _capacity: number = Number.MAX_SAFE_INTEGER;\r\n private _sendInterval: number | undefined = undefined;\r\n private _sendIntervalHandler = () => this.trySend();\r\n public readonly requestType = MobileRpcRequest;\r\n private _partialRequest: SerializedRpcRequest | undefined = undefined;\r\n private _partialFulfillment: RpcRequestFulfillment | undefined = undefined;\r\n private _partialData: Uint8Array[] = [];\r\n private _port: number = 0;\r\n private _rpcToken: string = \"\";\r\n private _transport?: MobilePushTransport;\r\n private _ipc: MobileIpcTransport;\r\n public static obtainInterop(): MobileRpcGateway { throw new IModelError(BentleyStatus.ERROR, \"Not implemented.\"); }\r\n\r\n public static async encodeRequest(request: MobileRpcRequest): Promise<MobileRpcChunks> {\r\n const serialized = await request.protocol.serialize(request);\r\n const data = serialized.parameters.data;\r\n serialized.parameters.data = data.map((v) => v.byteLength) as any[];\r\n return [JSON.stringify(serialized), ...data];\r\n }\r\n\r\n public static encodeResponse(fulfillment: RpcRequestFulfillment): MobileRpcChunks {\r\n const data = fulfillment.result.data;\r\n fulfillment.result.data = data.map((v) => v.byteLength) as any[];\r\n const raw = fulfillment.rawResult;\r\n fulfillment.rawResult = undefined;\r\n const encoded = [JSON.stringify(fulfillment), ...data];\r\n fulfillment.rawResult = raw;\r\n return encoded;\r\n }\r\n\r\n constructor(configuration: MobileRpcConfiguration, endPoint: RpcEndpoint) {\r\n super(configuration);\r\n\r\n if (endPoint === RpcEndpoint.Frontend) {\r\n this.initializeFrontend();\r\n } else if (endPoint === RpcEndpoint.Backend) {\r\n this.initializeBackend();\r\n }\r\n\r\n this._ipc = new MobileIpcTransport(this);\r\n IpcWebSocket.transport = this._ipc;\r\n }\r\n\r\n private initializeFrontend() {\r\n if (typeof (WebSocket) === \"undefined\") {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol on frontend require websocket to work\");\r\n }\r\n if (!MobileRpcConfiguration.args.port) {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol require 'port' parameter\");\r\n }\r\n\r\n this._port = MobileRpcConfiguration.args.port;\r\n this.setRpcToken((window as any).__iTwinJsRpcToken ?? MobileRpcConfiguration.args.rpcToken);\r\n this.connect(this._port, false);\r\n\r\n (window as any)._imodeljs_rpc_reconnect = (port: number, rpcToken: string) => {\r\n this.setRpcToken(rpcToken);\r\n this.socket.close();\r\n window.location.hash = window.location.hash.replace(`port=${this._port}`, `port=${port}`);\r\n this._port = port;\r\n this.connect(port, true);\r\n };\r\n\r\n const transport = new MobilePushTransport(this);\r\n this._transport = transport;\r\n RpcPushChannel.setup(transport);\r\n }\r\n\r\n private setRpcToken(rpcToken: unknown) {\r\n if (typeof rpcToken !== \"string\" || !/^[0-9a-f]{64}$/.test(rpcToken))\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol requires a native RPC authentication token. Update the mobile native runtime and startup configuration.\");\r\n\r\n this._rpcToken = rpcToken;\r\n }\r\n\r\n private connect(port: number, reset: boolean) {\r\n const socket = new WebSocket(`ws://127.0.0.1:${port}`, `itwin-rpc.${this._rpcToken}`);\r\n socket.binaryType = \"arraybuffer\";\r\n this.connectMessageHandler(socket);\r\n this.connectOpenHandler(socket, reset);\r\n this.connectErrorHandler(socket);\r\n this.socket = socket;\r\n }\r\n\r\n private connectMessageHandler(socket: WebSocket) {\r\n socket.addEventListener(\"message\", async (event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n this.handleMessageFromBackend(event.data);\r\n });\r\n }\r\n\r\n private connectOpenHandler(socket: WebSocket, reset: boolean) {\r\n socket.addEventListener(\"open\", (_event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n if (reset) {\r\n this.reset();\r\n\r\n const requests = new Map(RpcRequest.activeRequests);\r\n requests.forEach((req) => {\r\n req.cancel();\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n req.submit();\r\n });\r\n }\r\n\r\n this.scheduleSend();\r\n });\r\n }\r\n\r\n private connectErrorHandler(socket: WebSocket) {\r\n socket.addEventListener(\"error\", (_event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n throw new IModelError(BentleyStatus.ERROR, \"Socket error.\");\r\n });\r\n }\r\n\r\n private reset() {\r\n this.requests.clear();\r\n this._capacity = Number.MAX_SAFE_INTEGER;\r\n\r\n if (typeof (this._sendInterval) !== \"undefined\") {\r\n window.clearInterval(this._sendInterval);\r\n this._sendInterval = undefined;\r\n }\r\n\r\n this._partialRequest = undefined;\r\n this._partialFulfillment = undefined;\r\n this._partialData.length = 0;\r\n }\r\n\r\n private scheduleSend() {\r\n if (!this._pending.length) {\r\n return;\r\n }\r\n\r\n this.trySend();\r\n\r\n if (this._pending.length && typeof (this._sendInterval) === \"undefined\") {\r\n this._sendInterval = window.setInterval(this._sendIntervalHandler, 0);\r\n }\r\n }\r\n\r\n private trySend() {\r\n if (this.socket.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n while (this._capacity !== 0 && this._pending.length) {\r\n --this._capacity;\r\n const next = expectDefined(this._pending.shift(), \"Expected pending RPC chunk after queue length check.\");\r\n for (const chunk of next) {\r\n this.socket.send(chunk);\r\n }\r\n }\r\n\r\n if (!this._pending.length && typeof (this._sendInterval) !== \"undefined\") {\r\n window.clearInterval(this._sendInterval);\r\n this._sendInterval = undefined;\r\n }\r\n }\r\n\r\n private handleMessageFromBackend(data: string | ArrayBuffer) {\r\n if (typeof (data) === \"string\") {\r\n this.handleStringFromBackend(data);\r\n } else {\r\n this.handleBinaryFromBackend(data);\r\n }\r\n }\r\n\r\n private handleStringFromBackend(data: string) {\r\n if (this._partialFulfillment) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (already receiving response).\");\r\n }\r\n\r\n const response = JSON.parse(data) as RpcRequestFulfillment;\r\n this._partialFulfillment = response;\r\n\r\n if (!response.result.data.length) {\r\n this.notifyResponse();\r\n }\r\n }\r\n\r\n private handleBinaryFromBackend(data: ArrayBuffer) {\r\n const fulfillment = this._partialFulfillment;\r\n if (!fulfillment) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no response received).\");\r\n }\r\n\r\n this._partialData.push(new Uint8Array(data));\r\n if (this._partialData.length === fulfillment.result.data.length) {\r\n this.notifyResponse();\r\n }\r\n }\r\n\r\n private notifyResponse() {\r\n const response = this._partialFulfillment;\r\n if (!response) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no response exists).\");\r\n }\r\n\r\n ++this._capacity;\r\n this.consumePartialData(response.result);\r\n this._partialFulfillment = undefined;\r\n\r\n if (this._transport && this._transport.consume(response)) {\r\n return;\r\n }\r\n\r\n if (this._ipc.consumeResponse(response)) {\r\n return;\r\n }\r\n\r\n const request = this.requests.get(response.id) as MobileRpcRequest;\r\n this.requests.delete(response.id);\r\n request.notifyResponse(response);\r\n }\r\n\r\n private consumePartialData(value: RpcSerializedValue) {\r\n for (let i = 0, l = value.data.length; i !== l; ++i) {\r\n value.data[i] = this._partialData[i];\r\n }\r\n\r\n this._partialData.length = 0;\r\n }\r\n\r\n private initializeBackend() {\r\n const mobilegateway = MobileRpcProtocol.obtainInterop();\r\n if (mobilegateway === undefined || mobilegateway == null) {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol on backend require native bridge to be setup\");\r\n }\r\n\r\n mobilegateway.handler = (payload, connectionId) => this.handleMessageFromFrontend(payload, connectionId);\r\n RpcPushConnection.for = (channel, client) => new MobilePushConnection(channel, client, this);\r\n RpcPushChannel.enabled = true;\r\n }\r\n\r\n private handleMessageFromFrontend(data: string | ArrayBuffer, connectionId: number) {\r\n if (typeof (data) === \"string\") {\r\n this.handleStringFromFrontend(data, connectionId);\r\n } else {\r\n this.handleBinaryFromFrontend(data, connectionId);\r\n }\r\n }\r\n\r\n private handleStringFromFrontend(data: string, connection: number) {\r\n if (this._partialRequest) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (already receiving request).\");\r\n }\r\n\r\n const request = JSON.parse(data) as SerializedRpcRequest;\r\n this._partialRequest = request;\r\n\r\n if (!request.parameters.data.length) {\r\n this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n\r\n private handleBinaryFromFrontend(data: ArrayBuffer, connection: number) {\r\n const request = this._partialRequest;\r\n if (!request) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no request received).\");\r\n }\r\n\r\n this._partialData.push(new Uint8Array(data));\r\n if (this._partialData.length === request.parameters.data.length) {\r\n this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n\r\n private async notifyRequest(connection: number) {\r\n const request = this._partialRequest;\r\n if (!request) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no request exists).\");\r\n }\r\n\r\n this.consumePartialData(request.parameters);\r\n this._partialRequest = undefined;\r\n\r\n if (this._ipc.consumeRequest(request)) {\r\n return;\r\n }\r\n\r\n MobileEventLoop.addTask();\r\n const fulfillment = await this.fulfill(request);\r\n MobileEventLoop.removeTask();\r\n\r\n const response = MobileRpcProtocol.encodeResponse(fulfillment);\r\n this.sendToFrontend(response, connection);\r\n }\r\n\r\n public sendToBackend(message: MobileRpcChunks): void {\r\n this._pending.push(message);\r\n this.scheduleSend();\r\n }\r\n\r\n public sendToFrontend(message: MobileRpcChunks, connection?: number): void {\r\n const mobilegateway = MobileRpcProtocol.obtainInterop();\r\n\r\n for (const chunk of message) {\r\n if (typeof (chunk) === \"string\") {\r\n mobilegateway.sendString(chunk, connection || mobilegateway.connectionId);\r\n } else {\r\n mobilegateway.sendBinary(chunk, connection || mobilegateway.connectionId);\r\n }\r\n }\r\n }\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itwin/core-mobile",
|
|
3
|
-
"version": "5.15.0-dev.
|
|
3
|
+
"version": "5.15.0-dev.20",
|
|
4
4
|
"description": "iTwin.js MobileHost and MobileApp",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"url": "http://www.bentley.com"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@itwin/core-backend": "5.15.0-dev.
|
|
26
|
-
"@itwin/core-
|
|
27
|
-
"@itwin/core-
|
|
28
|
-
"@itwin/core-
|
|
25
|
+
"@itwin/core-backend": "5.15.0-dev.20",
|
|
26
|
+
"@itwin/core-frontend": "5.15.0-dev.20",
|
|
27
|
+
"@itwin/core-bentley": "5.15.0-dev.20",
|
|
28
|
+
"@itwin/core-common": "5.15.0-dev.20"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"lodash": "^4.18.0",
|
|
@@ -34,18 +34,26 @@
|
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@itwin/eslint-plugin": "^6.0.0",
|
|
37
|
+
"@types/chai": "4.3.1",
|
|
37
38
|
"@types/lodash": "^4.14.202",
|
|
39
|
+
"@types/mocha": "^10.0.6",
|
|
38
40
|
"@types/node": "~20.17.0",
|
|
39
41
|
"@types/superagent": "^8.1.6",
|
|
40
42
|
"@types/ws": "^7.0.0",
|
|
43
|
+
"chai": "^4.3.10",
|
|
41
44
|
"eslint": "^9.31.0",
|
|
45
|
+
"mocha": "^11.1.0",
|
|
46
|
+
"nyc": "^17.1.0",
|
|
42
47
|
"rimraf": "^6.0.1",
|
|
43
48
|
"typescript": "~5.6.2",
|
|
44
|
-
"@itwin/build-tools": "5.15.0-dev.
|
|
45
|
-
"@itwin/core-common": "5.15.0-dev.
|
|
46
|
-
"@itwin/core-backend": "5.15.0-dev.
|
|
47
|
-
"@itwin/core-bentley": "5.15.0-dev.
|
|
48
|
-
"@itwin/core-frontend": "5.15.0-dev.
|
|
49
|
+
"@itwin/build-tools": "5.15.0-dev.20",
|
|
50
|
+
"@itwin/core-common": "5.15.0-dev.20",
|
|
51
|
+
"@itwin/core-backend": "5.15.0-dev.20",
|
|
52
|
+
"@itwin/core-bentley": "5.15.0-dev.20",
|
|
53
|
+
"@itwin/core-frontend": "5.15.0-dev.20"
|
|
54
|
+
},
|
|
55
|
+
"nyc": {
|
|
56
|
+
"extends": "./node_modules/@itwin/build-tools/.nycrc"
|
|
49
57
|
},
|
|
50
58
|
"scripts": {
|
|
51
59
|
"build": "npm run -s build:cjs",
|
|
@@ -55,7 +63,7 @@
|
|
|
55
63
|
"extract-api": "betools extract-api --entry=core-mobile",
|
|
56
64
|
"lint": "eslint \"./src/**/*.ts\" 1>&2",
|
|
57
65
|
"lint-deprecation": "eslint --fix -f visualstudio --no-inline-config -c ../../common/config/eslint/eslint.config.deprecation-policy.js \"./src/**/*.ts\"",
|
|
58
|
-
"test": "",
|
|
59
|
-
"cover": ""
|
|
66
|
+
"test": "mocha",
|
|
67
|
+
"cover": "nyc npm -s test"
|
|
60
68
|
}
|
|
61
69
|
}
|