@itwin/core-mobile 3.0.0-dev.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +263 -0
  2. package/LICENSE.md +9 -0
  3. package/README.md +11 -0
  4. package/lib/cjs/MobileBackend.d.ts +7 -0
  5. package/lib/cjs/MobileBackend.d.ts.map +1 -0
  6. package/lib/cjs/MobileBackend.js +24 -0
  7. package/lib/cjs/MobileBackend.js.map +1 -0
  8. package/lib/cjs/MobileFrontend.d.ts +5 -0
  9. package/lib/cjs/MobileFrontend.d.ts.map +1 -0
  10. package/lib/cjs/MobileFrontend.js +21 -0
  11. package/lib/cjs/MobileFrontend.js.map +1 -0
  12. package/lib/cjs/__DOC_ONLY__.d.ts +9 -0
  13. package/lib/cjs/__DOC_ONLY__.d.ts.map +1 -0
  14. package/lib/cjs/__DOC_ONLY__.js +28 -0
  15. package/lib/cjs/__DOC_ONLY__.js.map +1 -0
  16. package/lib/cjs/backend/AndroidHost.d.ts +11 -0
  17. package/lib/cjs/backend/AndroidHost.d.ts.map +1 -0
  18. package/lib/cjs/backend/AndroidHost.js +23 -0
  19. package/lib/cjs/backend/AndroidHost.js.map +1 -0
  20. package/lib/cjs/backend/MobileAuthorizationBackend.d.ts +23 -0
  21. package/lib/cjs/backend/MobileAuthorizationBackend.d.ts.map +1 -0
  22. package/lib/cjs/backend/MobileAuthorizationBackend.js +78 -0
  23. package/lib/cjs/backend/MobileAuthorizationBackend.js.map +1 -0
  24. package/lib/cjs/backend/MobileFileHandler.d.ts +88 -0
  25. package/lib/cjs/backend/MobileFileHandler.d.ts.map +1 -0
  26. package/lib/cjs/backend/MobileFileHandler.js +233 -0
  27. package/lib/cjs/backend/MobileFileHandler.js.map +1 -0
  28. package/lib/cjs/backend/MobileHost.d.ts +78 -0
  29. package/lib/cjs/backend/MobileHost.d.ts.map +1 -0
  30. package/lib/cjs/backend/MobileHost.js +126 -0
  31. package/lib/cjs/backend/MobileHost.js.map +1 -0
  32. package/lib/cjs/backend/MobileRpcServer.d.ts +19 -0
  33. package/lib/cjs/backend/MobileRpcServer.d.ts.map +1 -0
  34. package/lib/cjs/backend/MobileRpcServer.js +136 -0
  35. package/lib/cjs/backend/MobileRpcServer.js.map +1 -0
  36. package/lib/cjs/backend/iOSHost.d.ts +11 -0
  37. package/lib/cjs/backend/iOSHost.d.ts.map +1 -0
  38. package/lib/cjs/backend/iOSHost.js +23 -0
  39. package/lib/cjs/backend/iOSHost.js.map +1 -0
  40. package/lib/cjs/common/MobileAppProps.d.ts +35 -0
  41. package/lib/cjs/common/MobileAppProps.d.ts.map +1 -0
  42. package/lib/cjs/common/MobileAppProps.js +29 -0
  43. package/lib/cjs/common/MobileAppProps.js.map +1 -0
  44. package/lib/cjs/common/MobileEventLoop.d.ts +12 -0
  45. package/lib/cjs/common/MobileEventLoop.d.ts.map +1 -0
  46. package/lib/cjs/common/MobileEventLoop.js +31 -0
  47. package/lib/cjs/common/MobileEventLoop.js.map +1 -0
  48. package/lib/cjs/common/MobileIpc.d.ts +18 -0
  49. package/lib/cjs/common/MobileIpc.d.ts.map +1 -0
  50. package/lib/cjs/common/MobileIpc.js +71 -0
  51. package/lib/cjs/common/MobileIpc.js.map +1 -0
  52. package/lib/cjs/common/MobilePush.d.ts +21 -0
  53. package/lib/cjs/common/MobilePush.d.ts.map +1 -0
  54. package/lib/cjs/common/MobilePush.js +53 -0
  55. package/lib/cjs/common/MobilePush.js.map +1 -0
  56. package/lib/cjs/common/MobileRpcManager.d.ts +41 -0
  57. package/lib/cjs/common/MobileRpcManager.d.ts.map +1 -0
  58. package/lib/cjs/common/MobileRpcManager.js +110 -0
  59. package/lib/cjs/common/MobileRpcManager.js.map +1 -0
  60. package/lib/cjs/common/MobileRpcProtocol.d.ts +59 -0
  61. package/lib/cjs/common/MobileRpcProtocol.d.ts.map +1 -0
  62. package/lib/cjs/common/MobileRpcProtocol.js +279 -0
  63. package/lib/cjs/common/MobileRpcProtocol.js.map +1 -0
  64. package/lib/cjs/common/MobileRpcRequest.d.ts +21 -0
  65. package/lib/cjs/common/MobileRpcRequest.d.ts.map +1 -0
  66. package/lib/cjs/common/MobileRpcRequest.js +48 -0
  67. package/lib/cjs/common/MobileRpcRequest.js.map +1 -0
  68. package/lib/cjs/frontend/AndroidApp.d.ts +14 -0
  69. package/lib/cjs/frontend/AndroidApp.d.ts.map +1 -0
  70. package/lib/cjs/frontend/AndroidApp.js +17 -0
  71. package/lib/cjs/frontend/AndroidApp.js.map +1 -0
  72. package/lib/cjs/frontend/IOSApp.d.ts +10 -0
  73. package/lib/cjs/frontend/IOSApp.d.ts.map +1 -0
  74. package/lib/cjs/frontend/IOSApp.js +21 -0
  75. package/lib/cjs/frontend/IOSApp.js.map +1 -0
  76. package/lib/cjs/frontend/MobileApp.d.ts +20 -0
  77. package/lib/cjs/frontend/MobileApp.d.ts.map +1 -0
  78. package/lib/cjs/frontend/MobileApp.js +57 -0
  79. package/lib/cjs/frontend/MobileApp.js.map +1 -0
  80. package/lib/cjs/test/ios/MobilePlatform.test.d.ts +2 -0
  81. package/lib/cjs/test/ios/MobilePlatform.test.d.ts.map +1 -0
  82. package/lib/cjs/test/ios/MobilePlatform.test.js +85 -0
  83. package/lib/cjs/test/ios/MobilePlatform.test.js.map +1 -0
  84. package/package.json +76 -0
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.MobileRpcManager = exports.MobileRpcConfiguration = exports.RpcMobilePlatform = void 0;
8
+ const core_common_1 = require("@itwin/core-common");
9
+ const MobileRpcProtocol_1 = require("./MobileRpcProtocol");
10
+ /** RPC supported mobile platforms.
11
+ * @beta
12
+ */
13
+ var RpcMobilePlatform;
14
+ (function (RpcMobilePlatform) {
15
+ RpcMobilePlatform[RpcMobilePlatform["Unknown"] = 0] = "Unknown";
16
+ RpcMobilePlatform[RpcMobilePlatform["Android"] = 1] = "Android";
17
+ RpcMobilePlatform[RpcMobilePlatform["iOS"] = 2] = "iOS";
18
+ })(RpcMobilePlatform = exports.RpcMobilePlatform || (exports.RpcMobilePlatform = {}));
19
+ /** Holds configuration for the RpcInterfaces used by the application.
20
+ * @beta
21
+ */
22
+ class MobileRpcConfiguration extends core_common_1.RpcConfiguration {
23
+ static getArgs() {
24
+ if (typeof window !== "object" || typeof window.location !== "object" || typeof window.location.hash !== "string") {
25
+ return Object.freeze({});
26
+ }
27
+ const queryArgs = {};
28
+ try {
29
+ const matches = window.location.hash.match(/([^#=&]+)(=([^&]*))?/g);
30
+ if (matches) {
31
+ for (const comp of matches) {
32
+ const array = comp.split("=");
33
+ if (array.length === 2) {
34
+ const key = decodeURIComponent(array[0]);
35
+ const val = decodeURIComponent(array[1]);
36
+ queryArgs[key] = val;
37
+ }
38
+ }
39
+ }
40
+ }
41
+ catch { }
42
+ return Object.freeze(queryArgs);
43
+ }
44
+ static getMobilePlatform() {
45
+ if (!MobileRpcConfiguration.args.platform)
46
+ return RpcMobilePlatform.Unknown;
47
+ const win = window;
48
+ if (/android/i.test(MobileRpcConfiguration.args.platform)) {
49
+ return RpcMobilePlatform.Android;
50
+ }
51
+ if (/iOS|iPadOS/i.test(MobileRpcConfiguration.args.platform) && !win.MSStream) {
52
+ return RpcMobilePlatform.iOS;
53
+ }
54
+ return RpcMobilePlatform.Unknown;
55
+ }
56
+ /** Read the mobile rpc args */
57
+ static get args() {
58
+ if (!this._args) {
59
+ this._args = MobileRpcConfiguration.getArgs();
60
+ }
61
+ return this._args;
62
+ }
63
+ /** Return type of mobile platform using browser userAgent */
64
+ static get platform() { return MobileRpcConfiguration.getMobilePlatform(); }
65
+ }
66
+ exports.MobileRpcConfiguration = MobileRpcConfiguration;
67
+ /** @internal */
68
+ MobileRpcConfiguration.setup = {
69
+ obtainPort: () => 0,
70
+ checkPlatform: () => typeof (process) !== "undefined" && process.platform === "ios",
71
+ };
72
+ /** Coordinates usage of RPC interfaces for an Mobile-based application.
73
+ * @beta
74
+ */
75
+ class MobileRpcManager {
76
+ /** @internal */
77
+ static async ready() {
78
+ return new Promise(async (resolve) => {
79
+ while (!global.__iTwinJsRpcReady) {
80
+ await new Promise((r) => setTimeout(r));
81
+ }
82
+ resolve();
83
+ });
84
+ }
85
+ static performInitialization(interfaces, endPoint) {
86
+ const config = class extends MobileRpcConfiguration {
87
+ constructor() {
88
+ super(...arguments);
89
+ this.interfaces = () => interfaces;
90
+ this.protocol = new MobileRpcProtocol_1.MobileRpcProtocol(this, endPoint);
91
+ }
92
+ };
93
+ for (const def of interfaces) {
94
+ core_common_1.RpcConfiguration.assign(def, () => config);
95
+ }
96
+ const instance = core_common_1.RpcConfiguration.obtain(config);
97
+ core_common_1.RpcConfiguration.initializeInterfaces(instance);
98
+ return instance;
99
+ }
100
+ /** Initializes MobileRpcManager for the frontend of an application. */
101
+ static initializeClient(interfaces) {
102
+ return MobileRpcManager.performInitialization(interfaces, core_common_1.RpcEndpoint.Frontend);
103
+ }
104
+ /** Initializes MobileRpcManager for the backend of an application. */
105
+ static initializeImpl(interfaces) {
106
+ return MobileRpcManager.performInitialization(interfaces, core_common_1.RpcEndpoint.Backend);
107
+ }
108
+ }
109
+ exports.MobileRpcManager = MobileRpcManager;
110
+ //# sourceMappingURL=MobileRpcManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MobileRpcManager.js","sourceRoot":"","sources":["../../../src/common/MobileRpcManager.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 { RpcConfiguration, RpcEndpoint, RpcInterfaceDefinition } from \"@itwin/core-common\";\r\nimport { MobileRpcProtocol } from \"./MobileRpcProtocol\";\r\n\r\n/** RPC supported mobile platforms.\r\n * @beta\r\n */\r\nexport enum RpcMobilePlatform {\r\n Unknown,\r\n Android,\r\n iOS,\r\n}\r\n\r\n/** Holds configuration for the RpcInterfaces used by the application.\r\n * @beta\r\n */\r\nexport abstract class MobileRpcConfiguration extends RpcConfiguration {\r\n /** @internal */\r\n public static setup = {\r\n obtainPort: () => 0,\r\n checkPlatform: () => typeof (process) !== \"undefined\" && (process.platform as any) === \"ios\",\r\n };\r\n\r\n public abstract override protocol: MobileRpcProtocol;\r\n private static _args: any;\r\n private static getArgs(): any {\r\n if (typeof window !== \"object\" || typeof window.location !== \"object\" || typeof window.location.hash !== \"string\") {\r\n return Object.freeze({});\r\n }\r\n const queryArgs: any = {};\r\n try {\r\n const matches = window.location.hash.match(/([^#=&]+)(=([^&]*))?/g);\r\n if (matches) {\r\n for (const comp of matches) {\r\n const array = comp.split(\"=\");\r\n if (array.length === 2) {\r\n const key = decodeURIComponent(array[0]);\r\n const val = decodeURIComponent(array[1]);\r\n queryArgs[key] = val;\r\n }\r\n }\r\n }\r\n } catch { }\r\n return Object.freeze(queryArgs);\r\n }\r\n private static getMobilePlatform(): RpcMobilePlatform {\r\n if (!MobileRpcConfiguration.args.platform)\r\n return RpcMobilePlatform.Unknown;\r\n\r\n const win: any = window;\r\n if (/android/i.test(MobileRpcConfiguration.args.platform)) {\r\n return RpcMobilePlatform.Android;\r\n }\r\n\r\n if (/iOS|iPadOS/i.test(MobileRpcConfiguration.args.platform) && !win.MSStream) {\r\n return RpcMobilePlatform.iOS;\r\n }\r\n\r\n return RpcMobilePlatform.Unknown;\r\n }\r\n /** Read the mobile rpc args */\r\n public static get args(): any {\r\n if (!this._args) {\r\n this._args = MobileRpcConfiguration.getArgs();\r\n }\r\n return this._args;\r\n }\r\n\r\n /** Return type of mobile platform using browser userAgent */\r\n public static get platform(): RpcMobilePlatform { return MobileRpcConfiguration.getMobilePlatform(); }\r\n}\r\n\r\n/** Coordinates usage of RPC interfaces for an Mobile-based application.\r\n * @beta\r\n */\r\nexport class MobileRpcManager {\r\n /** @internal */\r\n public static async ready() {\r\n return new Promise<void>(async (resolve) => {\r\n while (!(global as any).__iTwinJsRpcReady) {\r\n await new Promise((r) => setTimeout(r));\r\n }\r\n\r\n resolve();\r\n });\r\n }\r\n\r\n private static performInitialization(interfaces: RpcInterfaceDefinition[], endPoint: RpcEndpoint): MobileRpcConfiguration {\r\n const config = class extends MobileRpcConfiguration {\r\n public interfaces = () => interfaces;\r\n public protocol: MobileRpcProtocol = new MobileRpcProtocol(this, endPoint);\r\n };\r\n\r\n for (const def of interfaces) {\r\n RpcConfiguration.assign(def, () => config);\r\n }\r\n\r\n const instance = RpcConfiguration.obtain(config);\r\n RpcConfiguration.initializeInterfaces(instance);\r\n\r\n return instance;\r\n }\r\n\r\n /** Initializes MobileRpcManager for the frontend of an application. */\r\n public static initializeClient(interfaces: RpcInterfaceDefinition[]): MobileRpcConfiguration {\r\n return MobileRpcManager.performInitialization(interfaces, RpcEndpoint.Frontend);\r\n }\r\n /** Initializes MobileRpcManager for the backend of an application. */\r\n public static initializeImpl(interfaces: RpcInterfaceDefinition[]): MobileRpcConfiguration {\r\n return MobileRpcManager.performInitialization(interfaces, RpcEndpoint.Backend);\r\n }\r\n}\r\n\r\n"]}
@@ -0,0 +1,59 @@
1
+ /** @packageDocumentation
2
+ * @module RpcInterface
3
+ */
4
+ import { RpcEndpoint, RpcProtocol, RpcRequestFulfillment } from "@itwin/core-common";
5
+ import { MobileRpcConfiguration } from "./MobileRpcManager";
6
+ import { MobileRpcRequest } from "./MobileRpcRequest";
7
+ /** @beta */
8
+ export declare type MobileRpcChunks = Array<string | Uint8Array>;
9
+ /** @beta */
10
+ export interface MobileRpcGateway {
11
+ handler: (payload: ArrayBuffer | string, connectionId: number) => void;
12
+ sendString: (message: string, connectionId: number) => void;
13
+ sendBinary: (message: Uint8Array, connectionId: number) => void;
14
+ port: number;
15
+ connectionId: number;
16
+ }
17
+ /** RPC interface protocol for an Mobile-based application.
18
+ * @beta
19
+ */
20
+ export declare class MobileRpcProtocol extends RpcProtocol {
21
+ socket: WebSocket;
22
+ requests: Map<string, MobileRpcRequest>;
23
+ private _pending;
24
+ private _capacity;
25
+ private _sendInterval;
26
+ private _sendIntervalHandler;
27
+ readonly requestType: typeof MobileRpcRequest;
28
+ private _partialRequest;
29
+ private _partialFulfillment;
30
+ private _partialData;
31
+ private _port;
32
+ private _transport?;
33
+ private _ipc;
34
+ static obtainInterop(): MobileRpcGateway;
35
+ static encodeRequest(request: MobileRpcRequest): Promise<MobileRpcChunks>;
36
+ static encodeResponse(fulfillment: RpcRequestFulfillment): MobileRpcChunks;
37
+ constructor(configuration: MobileRpcConfiguration, endPoint: RpcEndpoint);
38
+ private initializeFrontend;
39
+ private connect;
40
+ private connectMessageHandler;
41
+ private connectOpenHandler;
42
+ private connectErrorHandler;
43
+ private reset;
44
+ private scheduleSend;
45
+ private trySend;
46
+ private handleMessageFromBackend;
47
+ private handleStringFromBackend;
48
+ private handleBinaryFromBackend;
49
+ private notifyResponse;
50
+ private consumePartialData;
51
+ private initializeBackend;
52
+ private handleMessageFromFrontend;
53
+ private handleStringFromFrontend;
54
+ private handleBinaryFromFrontend;
55
+ private notifyRequest;
56
+ sendToBackend(message: MobileRpcChunks): void;
57
+ sendToFrontend(message: MobileRpcChunks, connection?: number): void;
58
+ }
59
+ //# sourceMappingURL=MobileRpcProtocol.d.ts.map
@@ -0,0 +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;AAEtD,YAAY;AACZ,oBAAY,eAAe,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;AAEzD,YAAY;AACZ,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;IAuB1B,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,KAAK;IAeb,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"}
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ /** @packageDocumentation
7
+ * @module RpcInterface
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MobileRpcProtocol = void 0;
11
+ const core_bentley_1 = require("@itwin/core-bentley");
12
+ const core_common_1 = require("@itwin/core-common");
13
+ const MobileEventLoop_1 = require("./MobileEventLoop");
14
+ const MobileIpc_1 = require("./MobileIpc");
15
+ const MobilePush_1 = require("./MobilePush");
16
+ const MobileRpcManager_1 = require("./MobileRpcManager");
17
+ const MobileRpcRequest_1 = require("./MobileRpcRequest");
18
+ /** RPC interface protocol for an Mobile-based application.
19
+ * @beta
20
+ */
21
+ class MobileRpcProtocol extends core_common_1.RpcProtocol {
22
+ constructor(configuration, endPoint) {
23
+ super(configuration);
24
+ this.socket = undefined;
25
+ this.requests = new Map();
26
+ this._pending = [];
27
+ this._capacity = Number.MAX_SAFE_INTEGER;
28
+ this._sendInterval = undefined;
29
+ this._sendIntervalHandler = () => this.trySend();
30
+ this.requestType = MobileRpcRequest_1.MobileRpcRequest;
31
+ this._partialRequest = undefined;
32
+ this._partialFulfillment = undefined;
33
+ this._partialData = [];
34
+ this._port = 0;
35
+ if (endPoint === core_common_1.RpcEndpoint.Frontend) {
36
+ this.initializeFrontend();
37
+ }
38
+ else if (endPoint === core_common_1.RpcEndpoint.Backend) {
39
+ this.initializeBackend();
40
+ }
41
+ this._ipc = new MobileIpc_1.MobileIpcTransport(this);
42
+ core_common_1.IpcWebSocket.transport = this._ipc;
43
+ }
44
+ static obtainInterop() { throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Not implemented."); }
45
+ static async encodeRequest(request) {
46
+ const serialized = await request.protocol.serialize(request);
47
+ const data = serialized.parameters.data;
48
+ serialized.parameters.data = data.map((v) => v.byteLength);
49
+ return [JSON.stringify(serialized), ...data];
50
+ }
51
+ static encodeResponse(fulfillment) {
52
+ const data = fulfillment.result.data;
53
+ fulfillment.result.data = data.map((v) => v.byteLength);
54
+ const raw = fulfillment.rawResult;
55
+ fulfillment.rawResult = undefined;
56
+ const encoded = [JSON.stringify(fulfillment), ...data];
57
+ fulfillment.rawResult = raw;
58
+ return encoded;
59
+ }
60
+ initializeFrontend() {
61
+ if (typeof (WebSocket) === "undefined") {
62
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "MobileRpcProtocol on frontend require websocket to work");
63
+ }
64
+ if (!MobileRpcManager_1.MobileRpcConfiguration.args.port) {
65
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "MobileRpcProtocol require 'port' parameter");
66
+ }
67
+ this._port = MobileRpcManager_1.MobileRpcConfiguration.args.port;
68
+ this.connect(this._port, false);
69
+ window._imodeljs_rpc_reconnect = (port) => {
70
+ this.socket.close();
71
+ window.location.hash = window.location.hash.replace(`port=${this._port}`, `port=${port}`);
72
+ this._port = port;
73
+ this.connect(port, true);
74
+ };
75
+ const transport = new MobilePush_1.MobilePushTransport(this);
76
+ this._transport = transport;
77
+ core_common_1.RpcPushChannel.setup(transport);
78
+ }
79
+ connect(port, reset) {
80
+ const socket = new WebSocket(`ws://localhost:${port}`);
81
+ socket.binaryType = "arraybuffer";
82
+ this.connectMessageHandler(socket);
83
+ this.connectOpenHandler(socket, reset);
84
+ this.connectErrorHandler(socket);
85
+ this.socket = socket;
86
+ }
87
+ connectMessageHandler(socket) {
88
+ socket.addEventListener("message", async (event) => {
89
+ if (this.socket !== socket) {
90
+ return;
91
+ }
92
+ this.handleMessageFromBackend(event.data);
93
+ });
94
+ }
95
+ connectOpenHandler(socket, reset) {
96
+ socket.addEventListener("open", (_event) => {
97
+ if (this.socket !== socket) {
98
+ return;
99
+ }
100
+ if (reset) {
101
+ this.reset();
102
+ const requests = new Map(core_common_1.RpcRequest.activeRequests);
103
+ requests.forEach((req) => {
104
+ req.cancel();
105
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
106
+ req.submit();
107
+ });
108
+ }
109
+ this.scheduleSend();
110
+ });
111
+ }
112
+ connectErrorHandler(socket) {
113
+ socket.addEventListener("error", (_event) => {
114
+ if (this.socket !== socket) {
115
+ return;
116
+ }
117
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Socket error.");
118
+ });
119
+ }
120
+ reset() {
121
+ this.requests.clear();
122
+ this._pending.length = 0;
123
+ this._capacity = Number.MAX_SAFE_INTEGER;
124
+ if (typeof (this._sendInterval) !== "undefined") {
125
+ window.clearInterval(this._sendInterval);
126
+ this._sendInterval = undefined;
127
+ }
128
+ this._partialRequest = undefined;
129
+ this._partialFulfillment = undefined;
130
+ this._partialData.length = 0;
131
+ }
132
+ scheduleSend() {
133
+ if (!this._pending.length) {
134
+ return;
135
+ }
136
+ this.trySend();
137
+ if (this._pending.length && typeof (this._sendInterval) === "undefined") {
138
+ this._sendInterval = window.setInterval(this._sendIntervalHandler, 0);
139
+ }
140
+ }
141
+ trySend() {
142
+ if (this.socket.readyState !== WebSocket.OPEN) {
143
+ return;
144
+ }
145
+ while (this._capacity !== 0 && this._pending.length) {
146
+ --this._capacity;
147
+ const next = this._pending.shift();
148
+ for (const chunk of next) {
149
+ this.socket.send(chunk);
150
+ }
151
+ }
152
+ if (!this._pending.length && typeof (this._sendInterval) !== "undefined") {
153
+ window.clearInterval(this._sendInterval);
154
+ this._sendInterval = undefined;
155
+ }
156
+ }
157
+ handleMessageFromBackend(data) {
158
+ if (typeof (data) === "string") {
159
+ this.handleStringFromBackend(data);
160
+ }
161
+ else {
162
+ this.handleBinaryFromBackend(data);
163
+ }
164
+ }
165
+ handleStringFromBackend(data) {
166
+ if (this._partialFulfillment) {
167
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Invalid state (already receiving response).");
168
+ }
169
+ const response = JSON.parse(data);
170
+ this._partialFulfillment = response;
171
+ if (!response.result.data.length) {
172
+ this.notifyResponse();
173
+ }
174
+ }
175
+ handleBinaryFromBackend(data) {
176
+ const fulfillment = this._partialFulfillment;
177
+ if (!fulfillment) {
178
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Invalid state (no response received).");
179
+ }
180
+ this._partialData.push(new Uint8Array(data));
181
+ if (this._partialData.length === fulfillment.result.data.length) {
182
+ this.notifyResponse();
183
+ }
184
+ }
185
+ notifyResponse() {
186
+ const response = this._partialFulfillment;
187
+ if (!response) {
188
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Invalid state (no response exists).");
189
+ }
190
+ ++this._capacity;
191
+ this.consumePartialData(response.result);
192
+ this._partialFulfillment = undefined;
193
+ if (this._transport && this._transport.consume(response)) {
194
+ return;
195
+ }
196
+ if (this._ipc.consumeResponse(response)) {
197
+ return;
198
+ }
199
+ const request = this.requests.get(response.id);
200
+ this.requests.delete(response.id);
201
+ request.notifyResponse(response);
202
+ }
203
+ consumePartialData(value) {
204
+ for (let i = 0, l = value.data.length; i !== l; ++i) {
205
+ value.data[i] = this._partialData[i];
206
+ }
207
+ this._partialData.length = 0;
208
+ }
209
+ initializeBackend() {
210
+ const mobilegateway = MobileRpcProtocol.obtainInterop();
211
+ if (mobilegateway === undefined || mobilegateway == null) {
212
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "MobileRpcProtocol on backend require native bridge to be setup");
213
+ }
214
+ mobilegateway.handler = (payload, connectionId) => this.handleMessageFromFrontend(payload, connectionId);
215
+ core_common_1.RpcPushConnection.for = (channel, client) => new MobilePush_1.MobilePushConnection(channel, client, this);
216
+ core_common_1.RpcPushChannel.enabled = true;
217
+ }
218
+ handleMessageFromFrontend(data, connectionId) {
219
+ if (typeof (data) === "string") {
220
+ this.handleStringFromFrontend(data, connectionId);
221
+ }
222
+ else {
223
+ this.handleBinaryFromFrontend(data, connectionId);
224
+ }
225
+ }
226
+ handleStringFromFrontend(data, connection) {
227
+ if (this._partialRequest) {
228
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Invalid state (already receiving request).");
229
+ }
230
+ const request = JSON.parse(data);
231
+ this._partialRequest = request;
232
+ if (!request.parameters.data.length) {
233
+ this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises
234
+ }
235
+ }
236
+ handleBinaryFromFrontend(data, connection) {
237
+ const request = this._partialRequest;
238
+ if (!request) {
239
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Invalid state (no request received).");
240
+ }
241
+ this._partialData.push(new Uint8Array(data));
242
+ if (this._partialData.length === request.parameters.data.length) {
243
+ this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises
244
+ }
245
+ }
246
+ async notifyRequest(connection) {
247
+ const request = this._partialRequest;
248
+ if (!request) {
249
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Invalid state (no request exists).");
250
+ }
251
+ this.consumePartialData(request.parameters);
252
+ this._partialRequest = undefined;
253
+ if (this._ipc.consumeRequest(request)) {
254
+ return;
255
+ }
256
+ MobileEventLoop_1.MobileEventLoop.addTask();
257
+ const fulfillment = await this.fulfill(request);
258
+ MobileEventLoop_1.MobileEventLoop.removeTask();
259
+ const response = MobileRpcProtocol.encodeResponse(fulfillment);
260
+ this.sendToFrontend(response, connection);
261
+ }
262
+ sendToBackend(message) {
263
+ this._pending.push(message);
264
+ this.scheduleSend();
265
+ }
266
+ sendToFrontend(message, connection) {
267
+ const mobilegateway = MobileRpcProtocol.obtainInterop();
268
+ for (const chunk of message) {
269
+ if (typeof (chunk) === "string") {
270
+ mobilegateway.sendString(chunk, connection || mobilegateway.connectionId);
271
+ }
272
+ else {
273
+ mobilegateway.sendBinary(chunk, connection || mobilegateway.connectionId);
274
+ }
275
+ }
276
+ }
277
+ }
278
+ exports.MobileRpcProtocol = MobileRpcProtocol;
279
+ //# sourceMappingURL=MobileRpcProtocol.js.map
@@ -0,0 +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 } 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/** @beta */\r\nexport type MobileRpcChunks = Array<string | Uint8Array>;\r\n\r\n/** @beta */\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 * @beta\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://localhost:${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._pending.length = 0;\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 = this._pending.shift()!;\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"]}
@@ -0,0 +1,21 @@
1
+ /** @packageDocumentation
2
+ * @module RpcInterface
3
+ */
4
+ import { RpcRequest, RpcRequestFulfillment, RpcSerializedValue } from "@itwin/core-common";
5
+ import { MobileRpcProtocol } from "./MobileRpcProtocol";
6
+ /** @beta */
7
+ export declare class MobileRpcRequest extends RpcRequest {
8
+ private _res;
9
+ private _fulfillment;
10
+ /** Convenience access to the protocol of this request. */
11
+ readonly protocol: MobileRpcProtocol;
12
+ /** Sends the request. */
13
+ protected send(): Promise<number>;
14
+ /** Loads the request. */
15
+ protected load(): Promise<RpcSerializedValue>;
16
+ /** Sets request header values. */
17
+ protected setHeader(_name: string, _value: string): void;
18
+ /** @internal */
19
+ notifyResponse(fulfillment: RpcRequestFulfillment): void;
20
+ }
21
+ //# sourceMappingURL=MobileRpcRequest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MobileRpcRequest.d.ts","sourceRoot":"","sources":["../../../src/common/MobileRpcRequest.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,YAAY;AACZ,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,OAAO,CAAC,IAAI,CAA4C;IACxD,OAAO,CAAC,YAAY,CAAgD;IAEpE,0DAA0D;IAC1D,SAAyB,QAAQ,EAAE,iBAAiB,CAA6C;IAEjG,yBAAyB;cACT,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAOvC,yBAAyB;cACT,IAAI,IAAI,OAAO,CAAC,kBAAkB,CAAC;IASnD,kCAAkC;IAClC,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIxD,gBAAgB;IACT,cAAc,CAAC,WAAW,EAAE,qBAAqB;CAIzD"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ /** @packageDocumentation
7
+ * @module RpcInterface
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MobileRpcRequest = void 0;
11
+ const core_common_1 = require("@itwin/core-common");
12
+ const MobileRpcProtocol_1 = require("./MobileRpcProtocol");
13
+ /** @beta */
14
+ class MobileRpcRequest extends core_common_1.RpcRequest {
15
+ constructor() {
16
+ super(...arguments);
17
+ this._res = () => undefined;
18
+ this._fulfillment = undefined;
19
+ /** Convenience access to the protocol of this request. */
20
+ this.protocol = this.client.configuration.protocol;
21
+ }
22
+ /** Sends the request. */
23
+ async send() {
24
+ this.protocol.requests.set(this.id, this);
25
+ const parts = await MobileRpcProtocol_1.MobileRpcProtocol.encodeRequest(this);
26
+ this.protocol.sendToBackend(parts);
27
+ return new Promise((resolve) => { this._res = resolve; });
28
+ }
29
+ /** Loads the request. */
30
+ async load() {
31
+ const fulfillment = this._fulfillment;
32
+ if (!fulfillment) {
33
+ throw new Error("No request fulfillment available.");
34
+ }
35
+ return fulfillment.result;
36
+ }
37
+ /** Sets request header values. */
38
+ setHeader(_name, _value) {
39
+ // No implementation
40
+ }
41
+ /** @internal */
42
+ notifyResponse(fulfillment) {
43
+ this._fulfillment = fulfillment;
44
+ this._res(fulfillment.status);
45
+ }
46
+ }
47
+ exports.MobileRpcRequest = MobileRpcRequest;
48
+ //# sourceMappingURL=MobileRpcRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MobileRpcRequest.js","sourceRoot":"","sources":["../../../src/common/MobileRpcRequest.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,oDAA2F;AAC3F,2DAAwD;AAExD,YAAY;AACZ,MAAa,gBAAiB,SAAQ,wBAAU;IAAhD;;QACU,SAAI,GAA4B,GAAG,EAAE,CAAC,SAAS,CAAC;QAChD,iBAAY,GAAsC,SAAS,CAAC;QAEpE,0DAA0D;QACjC,aAAQ,GAAsB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAe,CAAC;IA8BnG,CAAC;IA5BC,yBAAyB;IACf,KAAK,CAAC,IAAI;QAClB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,qCAAiB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACnC,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,yBAAyB;IACf,KAAK,CAAC,IAAI;QAClB,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC;QACtC,IAAI,CAAC,WAAW,EAAE;YAChB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;SACtD;QAED,OAAO,WAAW,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,kCAAkC;IACxB,SAAS,CAAC,KAAa,EAAE,MAAc;QAC/C,oBAAoB;IACtB,CAAC;IAED,gBAAgB;IACT,cAAc,CAAC,WAAkC;QACtD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;CACF;AAnCD,4CAmCC","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 { RpcRequest, RpcRequestFulfillment, RpcSerializedValue } from \"@itwin/core-common\";\r\nimport { MobileRpcProtocol } from \"./MobileRpcProtocol\";\r\n\r\n/** @beta */\r\nexport class MobileRpcRequest extends RpcRequest {\r\n private _res: (value: number) => void = () => undefined;\r\n private _fulfillment: RpcRequestFulfillment | undefined = undefined;\r\n\r\n /** Convenience access to the protocol of this request. */\r\n public override readonly protocol: MobileRpcProtocol = this.client.configuration.protocol as any;\r\n\r\n /** Sends the request. */\r\n protected async send(): Promise<number> {\r\n this.protocol.requests.set(this.id, this);\r\n const parts = await MobileRpcProtocol.encodeRequest(this);\r\n this.protocol.sendToBackend(parts);\r\n return new Promise<number>((resolve) => { this._res = resolve; });\r\n }\r\n\r\n /** Loads the request. */\r\n protected async load(): Promise<RpcSerializedValue> {\r\n const fulfillment = this._fulfillment;\r\n if (!fulfillment) {\r\n throw new Error(\"No request fulfillment available.\");\r\n }\r\n\r\n return fulfillment.result;\r\n }\r\n\r\n /** Sets request header values. */\r\n protected setHeader(_name: string, _value: string): void {\r\n // No implementation\r\n }\r\n\r\n /** @internal */\r\n public notifyResponse(fulfillment: RpcRequestFulfillment) {\r\n this._fulfillment = fulfillment;\r\n this._res(fulfillment.status);\r\n }\r\n}\r\n"]}
@@ -0,0 +1,14 @@
1
+ import { RpcInterfaceDefinition } from "@itwin/core-common";
2
+ import { IModelAppOptions } from "@itwin/core-frontend";
3
+ /** @beta */
4
+ export declare class AndroidApp {
5
+ private static _isValid;
6
+ static get isValid(): boolean;
7
+ static startup(opts?: {
8
+ mobileApp?: {
9
+ rpcInterfaces?: RpcInterfaceDefinition[];
10
+ };
11
+ iModelApp?: IModelAppOptions;
12
+ }): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=AndroidApp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AndroidApp.d.ts","sourceRoot":"","sources":["../../../src/frontend/AndroidApp.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,YAAY;AACZ,qBAAa,UAAU;IAErB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,WAAkB,OAAO,YAA4B;WACjC,OAAO,CAAC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE;YAAE,aAAa,CAAC,EAAE,sBAAsB,EAAE,CAAA;SAAE,CAAC;QAAC,SAAS,CAAC,EAAE,gBAAgB,CAAA;KAAE;CAM9H"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AndroidApp = void 0;
4
+ const MobileApp_1 = require("./MobileApp");
5
+ /** @beta */
6
+ class AndroidApp {
7
+ static get isValid() { return this._isValid; }
8
+ static async startup(opts) {
9
+ if (!this._isValid) {
10
+ this._isValid = true;
11
+ }
12
+ await MobileApp_1.MobileApp.startup(opts);
13
+ }
14
+ }
15
+ exports.AndroidApp = AndroidApp;
16
+ AndroidApp._isValid = false;
17
+ //# sourceMappingURL=AndroidApp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AndroidApp.js","sourceRoot":"","sources":["../../../src/frontend/AndroidApp.ts"],"names":[],"mappings":";;;AAMA,2CAAwC;AAExC,YAAY;AACZ,MAAa,UAAU;IAGd,MAAM,KAAK,OAAO,KAAK,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAiG;QAC3H,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;SACtB;QACD,MAAM,qBAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;;AATH,gCAUC;AARgB,mBAAQ,GAAG,KAAK,CAAC","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\nimport { RpcInterfaceDefinition } from \"@itwin/core-common\";\r\nimport { IModelAppOptions } from \"@itwin/core-frontend\";\r\nimport { MobileApp } from \"./MobileApp\";\r\n\r\n/** @beta */\r\nexport class AndroidApp {\r\n\r\n private static _isValid = false;\r\n public static get isValid() { return this._isValid; }\r\n public static async startup(opts?: { mobileApp?: { rpcInterfaces?: RpcInterfaceDefinition[] }, iModelApp?: IModelAppOptions }) {\r\n if (!this._isValid) {\r\n this._isValid = true;\r\n }\r\n await MobileApp.startup(opts);\r\n }\r\n}\r\n"]}