@itwin/core-mobile 3.0.0-dev.98 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -1
- package/LICENSE.md +1 -1
- package/lib/cjs/backend/MobileAuthorizationBackend.d.ts +47 -5
- package/lib/cjs/backend/MobileAuthorizationBackend.d.ts.map +1 -1
- package/lib/cjs/backend/MobileAuthorizationBackend.js +56 -9
- package/lib/cjs/backend/MobileAuthorizationBackend.js.map +1 -1
- package/lib/cjs/backend/MobileFileHandler.d.ts +28 -3
- package/lib/cjs/backend/MobileFileHandler.d.ts.map +1 -1
- package/lib/cjs/backend/MobileFileHandler.js +39 -8
- package/lib/cjs/backend/MobileFileHandler.js.map +1 -1
- package/lib/cjs/backend/MobileHost.d.ts +7 -6
- package/lib/cjs/backend/MobileHost.d.ts.map +1 -1
- package/lib/cjs/backend/MobileHost.js +3 -3
- package/lib/cjs/backend/MobileHost.js.map +1 -1
- package/lib/cjs/backend/Request.d.ts +150 -0
- package/lib/cjs/backend/Request.d.ts.map +1 -0
- package/lib/cjs/backend/Request.js +268 -0
- package/lib/cjs/backend/Request.js.map +1 -0
- package/package.json +26 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,96 @@
|
|
|
1
1
|
# Change Log - @itwin/core-mobile
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 3.0.0
|
|
6
|
+
Mon, 24 Jan 2022 14:00:52 GMT
|
|
7
|
+
|
|
8
|
+
### Updates
|
|
9
|
+
|
|
10
|
+
- Upgrade target to ES2019
|
|
11
|
+
- use new @itwin package names
|
|
12
|
+
- rename to @itwin/core-mobile
|
|
13
|
+
- remove ClientRequestContext and its subclasses
|
|
14
|
+
- Removed config.app usage
|
|
15
|
+
- remove ClientRequestContext.current
|
|
16
|
+
- Flattened MobileAuthorizationClient heirarchy
|
|
17
|
+
- Bumped dotenv and removed deprecated @types/dotenv
|
|
18
|
+
- Removed references to the deleted config-loader package
|
|
19
|
+
|
|
20
|
+
## 2.19.28
|
|
21
|
+
Wed, 12 Jan 2022 14:52:38 GMT
|
|
22
|
+
|
|
23
|
+
_Version update only_
|
|
24
|
+
|
|
25
|
+
## 2.19.27
|
|
26
|
+
Wed, 05 Jan 2022 20:07:20 GMT
|
|
27
|
+
|
|
28
|
+
_Version update only_
|
|
29
|
+
|
|
30
|
+
## 2.19.26
|
|
31
|
+
Wed, 08 Dec 2021 20:54:53 GMT
|
|
32
|
+
|
|
33
|
+
_Version update only_
|
|
34
|
+
|
|
35
|
+
## 2.19.25
|
|
36
|
+
Fri, 03 Dec 2021 20:05:49 GMT
|
|
37
|
+
|
|
38
|
+
_Version update only_
|
|
39
|
+
|
|
40
|
+
## 2.19.24
|
|
41
|
+
Mon, 29 Nov 2021 18:44:31 GMT
|
|
42
|
+
|
|
43
|
+
_Version update only_
|
|
44
|
+
|
|
45
|
+
## 2.19.23
|
|
46
|
+
Mon, 22 Nov 2021 20:41:40 GMT
|
|
47
|
+
|
|
48
|
+
_Version update only_
|
|
49
|
+
|
|
50
|
+
## 2.19.22
|
|
51
|
+
Wed, 17 Nov 2021 01:23:26 GMT
|
|
52
|
+
|
|
53
|
+
_Version update only_
|
|
54
|
+
|
|
55
|
+
## 2.19.21
|
|
56
|
+
Wed, 10 Nov 2021 10:58:24 GMT
|
|
57
|
+
|
|
58
|
+
_Version update only_
|
|
59
|
+
|
|
60
|
+
## 2.19.20
|
|
61
|
+
Fri, 29 Oct 2021 16:14:22 GMT
|
|
62
|
+
|
|
63
|
+
_Version update only_
|
|
64
|
+
|
|
65
|
+
## 2.19.19
|
|
66
|
+
Mon, 25 Oct 2021 16:16:25 GMT
|
|
67
|
+
|
|
68
|
+
_Version update only_
|
|
69
|
+
|
|
70
|
+
## 2.19.18
|
|
71
|
+
Thu, 21 Oct 2021 20:59:44 GMT
|
|
72
|
+
|
|
73
|
+
_Version update only_
|
|
74
|
+
|
|
75
|
+
## 2.19.17
|
|
76
|
+
Thu, 14 Oct 2021 21:19:43 GMT
|
|
77
|
+
|
|
78
|
+
_Version update only_
|
|
79
|
+
|
|
80
|
+
## 2.19.16
|
|
81
|
+
Mon, 11 Oct 2021 17:37:46 GMT
|
|
82
|
+
|
|
83
|
+
_Version update only_
|
|
84
|
+
|
|
85
|
+
## 2.19.15
|
|
86
|
+
Fri, 08 Oct 2021 16:44:23 GMT
|
|
87
|
+
|
|
88
|
+
_Version update only_
|
|
89
|
+
|
|
90
|
+
## 2.19.14
|
|
91
|
+
Fri, 01 Oct 2021 13:07:03 GMT
|
|
92
|
+
|
|
93
|
+
_Version update only_
|
|
4
94
|
|
|
5
95
|
## 2.19.13
|
|
6
96
|
Tue, 21 Sep 2021 21:06:40 GMT
|
package/LICENSE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
|
|
3
|
-
Copyright © 2017-
|
|
3
|
+
Copyright © 2017-2022 Bentley Systems, Incorporated. All rights reserved.
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
6
|
|
|
@@ -2,22 +2,64 @@
|
|
|
2
2
|
* @module OIDC
|
|
3
3
|
*/
|
|
4
4
|
import { AccessToken } from "@itwin/core-bentley";
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { AuthorizationClient } from "@itwin/core-common";
|
|
6
|
+
/**
|
|
7
|
+
* Client configuration to generate OIDC/OAuth tokens for mobile applications
|
|
8
|
+
* @beta
|
|
9
|
+
*/
|
|
10
|
+
export interface MobileAppAuthorizationConfiguration {
|
|
11
|
+
/**
|
|
12
|
+
* The OAuth token issuer URL. Defaults to Bentley's auth URL if undefined.
|
|
13
|
+
*/
|
|
14
|
+
issuerUrl?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Upon signing in, the client application receives a response from the Bentley IMS OIDC/OAuth2 provider at this URI
|
|
17
|
+
* For mobile/desktop applications, must start with `http://localhost:${redirectPort}` or `https://localhost:${redirectPort}`
|
|
18
|
+
*/
|
|
19
|
+
readonly redirectUri?: string;
|
|
20
|
+
/** Client application's identifier as registered with the OIDC/OAuth2 provider. */
|
|
21
|
+
readonly clientId: string;
|
|
22
|
+
/** List of space separated scopes to request access to various resources. */
|
|
23
|
+
readonly scope: string;
|
|
24
|
+
/**
|
|
25
|
+
* Time in seconds that's used as a buffer to check the token for validity/expiry.
|
|
26
|
+
* The checks for authorization, and refreshing access tokens all use this buffer - i.e., the token is considered expired if the current time is within the specified
|
|
27
|
+
* time of the actual expiry.
|
|
28
|
+
* @note If unspecified this defaults to 10 minutes.
|
|
29
|
+
*/
|
|
30
|
+
readonly expiryBuffer?: number;
|
|
31
|
+
}
|
|
7
32
|
/** Utility to provide OIDC/OAuth tokens from native ios app to frontend
|
|
8
33
|
* @internal
|
|
9
34
|
*/
|
|
10
|
-
export declare class MobileAuthorizationBackend
|
|
35
|
+
export declare class MobileAuthorizationBackend implements AuthorizationClient {
|
|
36
|
+
protected _accessToken?: AccessToken;
|
|
37
|
+
config?: MobileAppAuthorizationConfiguration;
|
|
38
|
+
expireSafety: number;
|
|
39
|
+
issuerUrl?: string;
|
|
11
40
|
static defaultRedirectUri: string;
|
|
12
41
|
get redirectUri(): string;
|
|
13
|
-
|
|
42
|
+
protected _baseUrl: string;
|
|
43
|
+
protected _url?: string;
|
|
44
|
+
constructor(config?: MobileAppAuthorizationConfiguration);
|
|
14
45
|
/** Used to initialize the client - must be awaited before any other methods are called */
|
|
15
|
-
initialize(config?:
|
|
46
|
+
initialize(config?: MobileAppAuthorizationConfiguration): Promise<void>;
|
|
16
47
|
/** Start the sign-in process */
|
|
17
48
|
signIn(): Promise<void>;
|
|
18
49
|
/** Start the sign-out process */
|
|
19
50
|
signOut(): Promise<void>;
|
|
51
|
+
setAccessToken(token?: AccessToken): void;
|
|
52
|
+
getAccessToken(): Promise<AccessToken>;
|
|
20
53
|
/** return accessToken */
|
|
21
54
|
refreshToken(): Promise<AccessToken>;
|
|
55
|
+
/**
|
|
56
|
+
* Gets the URL of the service. Uses the default URL provided by client implementations.
|
|
57
|
+
* If defined, the value of `IMJS_URL_PREFIX` will be used as a prefix to all urls provided
|
|
58
|
+
* by the client implementations.
|
|
59
|
+
*
|
|
60
|
+
* Note that for consistency sake, the URL is stripped of any trailing "/".
|
|
61
|
+
* @returns URL for the service
|
|
62
|
+
*/
|
|
63
|
+
private getUrl;
|
|
22
64
|
}
|
|
23
65
|
//# sourceMappingURL=MobileAuthorizationBackend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileAuthorizationBackend.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileAuthorizationBackend.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"MobileAuthorizationBackend.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileAuthorizationBackend.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAsB,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAe,MAAM,oBAAoB,CAAC;AAGtE;;;GAGG;AACH,MAAM,WAAW,mCAAmC;IAClD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,qBAAa,0BAA2B,YAAW,mBAAmB;IACpE,SAAS,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC;IAC9B,MAAM,CAAC,EAAE,mCAAmC,CAAC;IAC7C,YAAY,SAAW;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAc,kBAAkB,SAAoC;IACpE,IAAW,WAAW,WAAwF;IAC9G,SAAS,CAAC,QAAQ,SAA6B;IAC/C,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEL,MAAM,CAAC,EAAE,mCAAmC;IAI/D,0FAA0F;IAC7E,UAAU,CAAC,MAAM,CAAC,EAAE,mCAAmC,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BpF,gCAAgC;IACnB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAYpC,iCAAiC;IACpB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B,cAAc,CAAC,KAAK,CAAC,EAAE,WAAW;IAM5B,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAMnD,yBAAyB;IACZ,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAWjD;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM;CAiBf"}
|
|
@@ -9,22 +9,31 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.MobileAuthorizationBackend = void 0;
|
|
11
11
|
const core_bentley_1 = require("@itwin/core-bentley");
|
|
12
|
-
const
|
|
12
|
+
const core_common_1 = require("@itwin/core-common");
|
|
13
13
|
const MobileHost_1 = require("./MobileHost");
|
|
14
14
|
/** Utility to provide OIDC/OAuth tokens from native ios app to frontend
|
|
15
15
|
* @internal
|
|
16
16
|
*/
|
|
17
|
-
class MobileAuthorizationBackend
|
|
17
|
+
class MobileAuthorizationBackend {
|
|
18
18
|
constructor(config) {
|
|
19
|
-
|
|
19
|
+
this.expireSafety = 60 * 10; // refresh token 10 minutes before real expiration time
|
|
20
|
+
this._baseUrl = "https://ims.bentley.com";
|
|
21
|
+
this.config = config;
|
|
20
22
|
}
|
|
21
23
|
get redirectUri() { var _a, _b; return (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.redirectUri) !== null && _b !== void 0 ? _b : MobileAuthorizationBackend.defaultRedirectUri; }
|
|
22
24
|
/** Used to initialize the client - must be awaited before any other methods are called */
|
|
23
25
|
async initialize(config) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
var _a;
|
|
27
|
+
this.config = config !== null && config !== void 0 ? config : this.config;
|
|
28
|
+
if (!this.config)
|
|
29
|
+
throw new core_common_1.IModelError(core_bentley_1.AuthStatus.Error, "Must specify a valid configuration when initializing authorization");
|
|
30
|
+
if (this.config.expiryBuffer)
|
|
31
|
+
this.expireSafety = this.config.expiryBuffer;
|
|
32
|
+
this.issuerUrl = (_a = this.config.issuerUrl) !== null && _a !== void 0 ? _a : this.getUrl();
|
|
33
|
+
if (!this.issuerUrl)
|
|
34
|
+
throw new core_common_1.IModelError(core_bentley_1.AuthStatus.Error, "The URL of the authorization provider was not initialized");
|
|
26
35
|
MobileHost_1.MobileHost.device.authStateChanged = (tokenString) => {
|
|
27
|
-
this.setAccessToken(tokenString
|
|
36
|
+
this.setAccessToken(tokenString);
|
|
28
37
|
};
|
|
29
38
|
return new Promise((resolve, reject) => {
|
|
30
39
|
(0, core_bentley_1.assert)(this.config !== undefined);
|
|
@@ -64,14 +73,52 @@ class MobileAuthorizationBackend extends core_backend_1.NativeAppAuthorizationBa
|
|
|
64
73
|
});
|
|
65
74
|
});
|
|
66
75
|
}
|
|
76
|
+
setAccessToken(token) {
|
|
77
|
+
if (token === this._accessToken)
|
|
78
|
+
return;
|
|
79
|
+
this._accessToken = token;
|
|
80
|
+
}
|
|
81
|
+
async getAccessToken() {
|
|
82
|
+
var _a;
|
|
83
|
+
if (!this._accessToken)
|
|
84
|
+
this.setAccessToken(await this.refreshToken());
|
|
85
|
+
return (_a = this._accessToken) !== null && _a !== void 0 ? _a : "";
|
|
86
|
+
}
|
|
67
87
|
/** return accessToken */
|
|
68
88
|
async refreshToken() {
|
|
69
|
-
return new Promise((resolve) => {
|
|
70
|
-
MobileHost_1.MobileHost.device.authGetAccessToken((tokenStringJson) => {
|
|
71
|
-
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
MobileHost_1.MobileHost.device.authGetAccessToken((tokenStringJson, err) => {
|
|
91
|
+
if (!err && tokenStringJson) {
|
|
92
|
+
resolve(tokenStringJson);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
reject(new Error(err));
|
|
96
|
+
}
|
|
72
97
|
});
|
|
73
98
|
});
|
|
74
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Gets the URL of the service. Uses the default URL provided by client implementations.
|
|
102
|
+
* If defined, the value of `IMJS_URL_PREFIX` will be used as a prefix to all urls provided
|
|
103
|
+
* by the client implementations.
|
|
104
|
+
*
|
|
105
|
+
* Note that for consistency sake, the URL is stripped of any trailing "/".
|
|
106
|
+
* @returns URL for the service
|
|
107
|
+
*/
|
|
108
|
+
getUrl() {
|
|
109
|
+
var _a, _b, _c;
|
|
110
|
+
if (this._url)
|
|
111
|
+
return this._url;
|
|
112
|
+
if (!this._baseUrl) {
|
|
113
|
+
throw new Error("The client is missing a default url.");
|
|
114
|
+
}
|
|
115
|
+
const prefix = process.env.IMJS_URL_PREFIX;
|
|
116
|
+
const authority = new URL((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.issuerUrl) !== null && _b !== void 0 ? _b : this._baseUrl);
|
|
117
|
+
if (prefix && !((_c = this.config) === null || _c === void 0 ? void 0 : _c.issuerUrl))
|
|
118
|
+
authority.hostname = prefix + authority.hostname;
|
|
119
|
+
this._url = authority.href.replace(/\/$/, "");
|
|
120
|
+
return this._url;
|
|
121
|
+
}
|
|
75
122
|
}
|
|
76
123
|
exports.MobileAuthorizationBackend = MobileAuthorizationBackend;
|
|
77
124
|
MobileAuthorizationBackend.defaultRedirectUri = "imodeljs://app/signin-callback";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileAuthorizationBackend.js","sourceRoot":"","sources":["../../../src/backend/MobileAuthorizationBackend.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,
|
|
1
|
+
{"version":3,"file":"MobileAuthorizationBackend.js","sourceRoot":"","sources":["../../../src/backend/MobileAuthorizationBackend.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 OIDC\r\n */\r\n\r\nimport { AccessToken, assert, AuthStatus } from \"@itwin/core-bentley\";\r\nimport { AuthorizationClient, IModelError } from \"@itwin/core-common\";\r\nimport { MobileHost } from \"./MobileHost\";\r\n\r\n/**\r\n * Client configuration to generate OIDC/OAuth tokens for mobile applications\r\n * @beta\r\n */\r\nexport interface MobileAppAuthorizationConfiguration {\r\n /**\r\n * The OAuth token issuer URL. Defaults to Bentley's auth URL if undefined.\r\n */\r\n issuerUrl?: string;\r\n\r\n /**\r\n * Upon signing in, the client application receives a response from the Bentley IMS OIDC/OAuth2 provider at this URI\r\n * For mobile/desktop applications, must start with `http://localhost:${redirectPort}` or `https://localhost:${redirectPort}`\r\n */\r\n readonly redirectUri?: string;\r\n\r\n /** Client application's identifier as registered with the OIDC/OAuth2 provider. */\r\n readonly clientId: string;\r\n\r\n /** List of space separated scopes to request access to various resources. */\r\n readonly scope: string;\r\n\r\n /**\r\n * Time in seconds that's used as a buffer to check the token for validity/expiry.\r\n * The checks for authorization, and refreshing access tokens all use this buffer - i.e., the token is considered expired if the current time is within the specified\r\n * time of the actual expiry.\r\n * @note If unspecified this defaults to 10 minutes.\r\n */\r\n readonly expiryBuffer?: number;\r\n}\r\n\r\n/** Utility to provide OIDC/OAuth tokens from native ios app to frontend\r\n * @internal\r\n */\r\nexport class MobileAuthorizationBackend implements AuthorizationClient {\r\n protected _accessToken?: AccessToken;\r\n public config?: MobileAppAuthorizationConfiguration;\r\n public expireSafety = 60 * 10; // refresh token 10 minutes before real expiration time\r\n public issuerUrl?: string;\r\n public static defaultRedirectUri = \"imodeljs://app/signin-callback\";\r\n public get redirectUri() { return this.config?.redirectUri ?? MobileAuthorizationBackend.defaultRedirectUri; }\r\n protected _baseUrl = \"https://ims.bentley.com\";\r\n protected _url?: string;\r\n\r\n public constructor(config?: MobileAppAuthorizationConfiguration) {\r\n this.config = config;\r\n }\r\n\r\n /** Used to initialize the client - must be awaited before any other methods are called */\r\n public async initialize(config?: MobileAppAuthorizationConfiguration): Promise<void> {\r\n this.config = config ?? this.config;\r\n if (!this.config)\r\n throw new IModelError(AuthStatus.Error, \"Must specify a valid configuration when initializing authorization\");\r\n if (this.config.expiryBuffer)\r\n this.expireSafety = this.config.expiryBuffer;\r\n this.issuerUrl = this.config.issuerUrl ?? this.getUrl();\r\n if (!this.issuerUrl)\r\n throw new IModelError(AuthStatus.Error, \"The URL of the authorization provider was not initialized\");\r\n\r\n MobileHost.device.authStateChanged = (tokenString?: AccessToken) => {\r\n this.setAccessToken(tokenString);\r\n };\r\n\r\n return new Promise<void>((resolve, reject) => {\r\n assert(this.config !== undefined);\r\n MobileHost.device.authInit({ ...this.config, issuerUrl: this.issuerUrl }, (err?: string) => {\r\n if (!err) {\r\n resolve();\r\n } else {\r\n reject(new Error(err));\r\n }\r\n });\r\n });\r\n }\r\n\r\n /** Start the sign-in process */\r\n public async signIn(): Promise<void> {\r\n return new Promise<void>((resolve, reject) => {\r\n MobileHost.device.authSignIn((err?: string) => {\r\n if (!err) {\r\n resolve();\r\n } else {\r\n reject(new Error(err));\r\n }\r\n });\r\n });\r\n }\r\n\r\n /** Start the sign-out process */\r\n public async signOut(): Promise<void> {\r\n return new Promise<void>((resolve, reject) => {\r\n MobileHost.device.authSignOut((err?: string) => {\r\n if (!err) {\r\n resolve();\r\n } else {\r\n reject(new Error(err));\r\n }\r\n });\r\n });\r\n }\r\n\r\n public setAccessToken(token?: AccessToken) {\r\n if (token === this._accessToken)\r\n return;\r\n this._accessToken = token;\r\n }\r\n\r\n public async getAccessToken(): Promise<AccessToken> {\r\n if (!this._accessToken)\r\n this.setAccessToken(await this.refreshToken());\r\n return this._accessToken ?? \"\";\r\n }\r\n\r\n /** return accessToken */\r\n public async refreshToken(): Promise<AccessToken> {\r\n return new Promise<AccessToken>((resolve, reject) => {\r\n MobileHost.device.authGetAccessToken((tokenStringJson?: AccessToken, err?: string) => {\r\n if (!err && tokenStringJson) {\r\n resolve(tokenStringJson);\r\n } else {\r\n reject(new Error(err));\r\n }\r\n });\r\n });\r\n }\r\n /**\r\n * Gets the URL of the service. Uses the default URL provided by client implementations.\r\n * If defined, the value of `IMJS_URL_PREFIX` will be used as a prefix to all urls provided\r\n * by the client implementations.\r\n *\r\n * Note that for consistency sake, the URL is stripped of any trailing \"/\".\r\n * @returns URL for the service\r\n */\r\n private getUrl(): string {\r\n if (this._url)\r\n return this._url;\r\n\r\n if (!this._baseUrl) {\r\n throw new Error(\"The client is missing a default url.\");\r\n }\r\n\r\n const prefix = process.env.IMJS_URL_PREFIX;\r\n const authority = new URL(this.config?.issuerUrl ?? this._baseUrl);\r\n\r\n if (prefix && !this.config?.issuerUrl)\r\n authority.hostname = prefix + authority.hostname;\r\n this._url = authority.href.replace(/\\/$/, \"\");\r\n\r\n return this._url;\r\n }\r\n}\r\n"]}
|
|
@@ -3,13 +3,38 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/// <reference types="node" />
|
|
5
5
|
import * as https from "https";
|
|
6
|
-
import { AccessToken } from "@itwin/core-bentley";
|
|
7
|
-
import {
|
|
6
|
+
import { AccessToken, BentleyError, GetMetaDataFunction } from "@itwin/core-bentley";
|
|
7
|
+
import { ProgressCallback } from "./Request";
|
|
8
|
+
/** Interface to cancel a request
|
|
9
|
+
* @beta
|
|
10
|
+
*/
|
|
11
|
+
export interface CancelRequest {
|
|
12
|
+
/** Returns true if cancel request was acknowledged */
|
|
13
|
+
cancel: () => boolean;
|
|
14
|
+
}
|
|
15
|
+
/** Error thrown when user cancelled operation
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export declare class UserCancelledError extends BentleyError {
|
|
19
|
+
constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction);
|
|
20
|
+
}
|
|
21
|
+
/** Error thrown fail to download file. ErrorNumber will correspond to HTTP error code.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export declare class DownloadFailed extends BentleyError {
|
|
25
|
+
constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction);
|
|
26
|
+
}
|
|
27
|
+
/** Error thrown when sas-url provided for download has expired
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export declare class SasUrlExpired extends BentleyError {
|
|
31
|
+
constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction);
|
|
32
|
+
}
|
|
8
33
|
/**
|
|
9
34
|
* Provides methods to work with the file system and azure storage. An instance of this class has to be provided to [[IModelClient]] for file upload/download methods to work.
|
|
10
35
|
* @internal
|
|
11
36
|
*/
|
|
12
|
-
export declare class MobileFileHandler
|
|
37
|
+
export declare class MobileFileHandler {
|
|
13
38
|
/** @internal */
|
|
14
39
|
agent?: https.Agent;
|
|
15
40
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileFileHandler.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileFileHandler.ts"],"names":[],"mappings":"AAIA;;GAEG;;AAGH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAU,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"MobileFileHandler.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileFileHandler.ts"],"names":[],"mappings":"AAIA;;GAEG;;AAGH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,mBAAmB,EAAU,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAyC,MAAM,WAAW,CAAC;AAWpF;;IAEI;AACJ,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,MAAM,EAAE,MAAM,OAAO,CAAC;CACvB;AAED;;IAEI;AACJ,qBAAa,kBAAmB,SAAQ,YAAY;gBAC/B,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,mBAAmB;CAI3F;AAED;;IAEI;AACJ,qBAAa,cAAe,SAAQ,YAAY;gBAC3B,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,mBAAmB;CAI3F;AAED;;IAEI;AACJ,qBAAa,aAAc,SAAQ,YAAY;gBAC1B,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,mBAAmB;CAI3F;AAED;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,gBAAgB;IACT,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;IAE3B;;OAEG;;IAIH,wEAAwE;IACxE,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAQrC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IASnC;;;;OAIG;WACW,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAehF;;;;;;;OAOG;IACU,YAAY,CAAC,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkC3M,4CAA4C;IAC5C,OAAO,CAAC,UAAU;YAIJ,WAAW;IA0BzB;;;;;;OAMG;IACU,UAAU,CAAC,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6C1J;;;;OAIG;IACI,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAI5C;;;;OAIG;IACI,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI7C;;;;OAIG;IACI,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIxC;;;OAGG;IACI,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIrC;;;;OAIG;IACI,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAIzC;;;;OAIG;IACI,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM;CAGxC"}
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* @module iModelHub
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.MobileFileHandler = void 0;
|
|
10
|
+
exports.MobileFileHandler = exports.SasUrlExpired = exports.DownloadFailed = exports.UserCancelledError = void 0;
|
|
11
11
|
const fs = require("fs");
|
|
12
12
|
const path = require("path");
|
|
13
13
|
const core_bentley_1 = require("@itwin/core-bentley");
|
|
14
|
-
const
|
|
14
|
+
const Request_1 = require("./Request");
|
|
15
15
|
const MobileHost_1 = require("./MobileHost");
|
|
16
16
|
const js_base64_1 = require("js-base64");
|
|
17
17
|
const loggerCategory = "mobile.filehandler";
|
|
@@ -19,6 +19,36 @@ const defined = (argumentName, argument, allowEmpty = false) => {
|
|
|
19
19
|
if (argument === undefined || argument === null || (argument === "" && !allowEmpty))
|
|
20
20
|
throw Error(`Argument ${argumentName} is null or undefined`);
|
|
21
21
|
};
|
|
22
|
+
/** Error thrown when user cancelled operation
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
class UserCancelledError extends core_bentley_1.BentleyError {
|
|
26
|
+
constructor(errorNumber, message, getMetaData) {
|
|
27
|
+
super(errorNumber, message, getMetaData);
|
|
28
|
+
this.name = "User cancelled operation";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.UserCancelledError = UserCancelledError;
|
|
32
|
+
/** Error thrown fail to download file. ErrorNumber will correspond to HTTP error code.
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
class DownloadFailed extends core_bentley_1.BentleyError {
|
|
36
|
+
constructor(errorNumber, message, getMetaData) {
|
|
37
|
+
super(errorNumber, message, getMetaData);
|
|
38
|
+
this.name = "Fail to download file";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.DownloadFailed = DownloadFailed;
|
|
42
|
+
/** Error thrown when sas-url provided for download has expired
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
class SasUrlExpired extends core_bentley_1.BentleyError {
|
|
46
|
+
constructor(errorNumber, message, getMetaData) {
|
|
47
|
+
super(errorNumber, message, getMetaData);
|
|
48
|
+
this.name = "SaS url has expired";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.SasUrlExpired = SasUrlExpired;
|
|
22
52
|
/**
|
|
23
53
|
* Provides methods to work with the file system and azure storage. An instance of this class has to be provided to [[IModelClient]] for file upload/download methods to work.
|
|
24
54
|
* @internal
|
|
@@ -83,7 +113,7 @@ class MobileFileHandler {
|
|
|
83
113
|
defined("downloadToPathname", downloadToPathname);
|
|
84
114
|
if (MobileFileHandler.isUrlExpired(downloadUrl)) {
|
|
85
115
|
core_bentley_1.Logger.logError(loggerCategory, `Sas url has expired ${safeToLogUrl}`);
|
|
86
|
-
throw new
|
|
116
|
+
throw new SasUrlExpired(403, "Download URL has expired");
|
|
87
117
|
}
|
|
88
118
|
if (fs.existsSync(downloadToPathname))
|
|
89
119
|
fs.unlinkSync(downloadToPathname);
|
|
@@ -94,7 +124,7 @@ class MobileFileHandler {
|
|
|
94
124
|
catch (err) {
|
|
95
125
|
if (fs.existsSync(downloadToPathname))
|
|
96
126
|
fs.unlinkSync(downloadToPathname); // Just in case there was a partial download, delete the file
|
|
97
|
-
if (!(err instanceof
|
|
127
|
+
if (!(err instanceof UserCancelledError))
|
|
98
128
|
core_bentley_1.Logger.logError(loggerCategory, `Error downloading file`);
|
|
99
129
|
throw err;
|
|
100
130
|
}
|
|
@@ -102,7 +132,7 @@ class MobileFileHandler {
|
|
|
102
132
|
if (fs.lstatSync(downloadToPathname).size !== fileSize) {
|
|
103
133
|
fs.unlinkSync(downloadToPathname);
|
|
104
134
|
core_bentley_1.Logger.logError(loggerCategory, `Downloaded file is of incorrect size ${safeToLogUrl}`);
|
|
105
|
-
throw new
|
|
135
|
+
throw new DownloadFailed(403, "Download failed. Expected filesize does not match");
|
|
106
136
|
}
|
|
107
137
|
}
|
|
108
138
|
core_bentley_1.Logger.logTrace(loggerCategory, `Downloaded file from ${safeToLogUrl}`);
|
|
@@ -132,7 +162,7 @@ class MobileFileHandler {
|
|
|
132
162
|
},
|
|
133
163
|
};
|
|
134
164
|
const uploadUrl = `${uploadUrlString}&comp=block&blockid=${this.getBlockId(blockId)}`;
|
|
135
|
-
await (0,
|
|
165
|
+
await (0, Request_1.request)(uploadUrl, options);
|
|
136
166
|
}
|
|
137
167
|
/**
|
|
138
168
|
* Upload a file to AzureBlobStorage for iModelHub.
|
|
@@ -154,7 +184,8 @@ class MobileFileHandler {
|
|
|
154
184
|
let i = 0;
|
|
155
185
|
const callback = (progress) => {
|
|
156
186
|
const uploaded = i * chunkSize + progress.loaded;
|
|
157
|
-
progressCallback
|
|
187
|
+
if (progressCallback)
|
|
188
|
+
progressCallback({ loaded: uploaded, percent: uploaded / fileSize, total: fileSize });
|
|
158
189
|
};
|
|
159
190
|
for (; i * chunkSize < fileSize; ++i) {
|
|
160
191
|
await this.uploadChunk(accessToken, uploadUrlString, file, i, progressCallback ? callback : undefined);
|
|
@@ -175,7 +206,7 @@ class MobileFileHandler {
|
|
|
175
206
|
},
|
|
176
207
|
};
|
|
177
208
|
const uploadUrl = `${uploadUrlString}&comp=blocklist`;
|
|
178
|
-
await (0,
|
|
209
|
+
await (0, Request_1.request)(uploadUrl, options);
|
|
179
210
|
}
|
|
180
211
|
finally {
|
|
181
212
|
fs.closeSync(file);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileFileHandler.js","sourceRoot":"","sources":["../../../src/backend/MobileFileHandler.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 iModelHub\r\n */\r\n\r\nimport * as fs from \"fs\";\r\nimport * as https from \"https\";\r\nimport * as path from \"path\";\r\nimport { AccessToken, Logger } from \"@itwin/core-bentley\";\r\nimport {\r\n CancelRequest, DownloadFailed, FileHandler, ProgressCallback, ProgressInfo, request, RequestOptions, SasUrlExpired,\r\n UserCancelledError,\r\n} from \"@bentley/itwin-client\";\r\nimport { MobileHost } from \"./MobileHost\";\r\nimport { Base64 } from \"js-base64\";\r\n\r\nconst loggerCategory: string = \"mobile.filehandler\";\r\n\r\nconst defined = (argumentName: string, argument?: any, allowEmpty: boolean = false) => {\r\n if (argument === undefined || argument === null || (argument === \"\" && !allowEmpty))\r\n throw Error(`Argument ${argumentName} is null or undefined`);\r\n};\r\n\r\n/**\r\n * Provides methods to work with the file system and azure storage. An instance of this class has to be provided to [[IModelClient]] for file upload/download methods to work.\r\n * @internal\r\n */\r\nexport class MobileFileHandler implements FileHandler {\r\n /** @internal */\r\n public agent?: https.Agent;\r\n\r\n /**\r\n * Constructor for MobileFileHandler.\r\n */\r\n constructor() {\r\n }\r\n\r\n /** Create a directory, recursively setting up the path as necessary. */\r\n private static makeDirectoryRecursive(dirPath: string) {\r\n if (fs.existsSync(dirPath))\r\n return;\r\n\r\n MobileFileHandler.makeDirectoryRecursive(path.dirname(dirPath));\r\n fs.mkdirSync(dirPath);\r\n }\r\n\r\n /**\r\n * Make url safe for logging by removing sensitive information\r\n * @param url input url that will be strip of search and query parameters and replace them by ... for security reason\r\n */\r\n private static getSafeUrlForLogging(url: string): string {\r\n const safeToLogDownloadUrl = new URL(url);\r\n if (safeToLogDownloadUrl.search && safeToLogDownloadUrl.search.length > 0)\r\n safeToLogDownloadUrl.search = \"...\";\r\n if (safeToLogDownloadUrl.hash && safeToLogDownloadUrl.hash.length > 0)\r\n safeToLogDownloadUrl.hash = \"...\";\r\n return safeToLogDownloadUrl.toString();\r\n }\r\n\r\n /**\r\n * Check if sas url has expired\r\n * @param download sas url for download\r\n * @param futureSeconds should be valid in future for given seconds.\r\n */\r\n public static isUrlExpired(downloadUrl: string, futureSeconds?: number): boolean {\r\n const sasUrl = new URL(downloadUrl);\r\n const se = sasUrl.searchParams.get(\"se\");\r\n if (se) {\r\n const expiryUTC = new Date(se);\r\n const now = new Date();\r\n const currentUTC = new Date(now.toUTCString());\r\n if (futureSeconds) {\r\n currentUTC.setSeconds(futureSeconds + currentUTC.getSeconds());\r\n }\r\n return expiryUTC <= currentUTC;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Download a file from AzureBlobStorage for iModelHub. Creates the directory containing the file if necessary. If there is an error in the operation, incomplete file is deleted from disk.\r\n * @param downloadUrl URL to download file from.\r\n * @param downloadToPathname Pathname to download the file to.\r\n * @param fileSize Size of the file that's being downloaded.\r\n * @param progressCallback Callback for tracking progress.\r\n * @throws [[IModelHubClientError]] with [IModelHubStatus.UndefinedArgumentError]($bentley) if one of the arguments is undefined or empty.\r\n */\r\n public async downloadFile(_accessToken: AccessToken, downloadUrl: string, downloadToPathname: string, fileSize?: number, progressCallback?: ProgressCallback, cancelRequest?: CancelRequest): Promise<void> {\r\n // strip search and hash parameters from download Url for logging purpose\r\n const safeToLogUrl = MobileFileHandler.getSafeUrlForLogging(downloadUrl);\r\n Logger.logInfo(loggerCategory, `Downloading file from ${safeToLogUrl}`);\r\n\r\n defined(\"downloadUrl\", downloadUrl);\r\n defined(\"downloadToPathname\", downloadToPathname);\r\n if (MobileFileHandler.isUrlExpired(downloadUrl)) {\r\n Logger.logError(loggerCategory, `Sas url has expired ${safeToLogUrl}`);\r\n throw new SasUrlExpired(403, \"Download URL has expired\");\r\n }\r\n if (fs.existsSync(downloadToPathname))\r\n fs.unlinkSync(downloadToPathname);\r\n\r\n MobileFileHandler.makeDirectoryRecursive(path.dirname(downloadToPathname));\r\n try {\r\n await MobileHost.downloadFile(downloadUrl, downloadToPathname, progressCallback, cancelRequest);\r\n } catch (err) {\r\n if (fs.existsSync(downloadToPathname))\r\n fs.unlinkSync(downloadToPathname); // Just in case there was a partial download, delete the file\r\n\r\n if (!(err instanceof UserCancelledError))\r\n Logger.logError(loggerCategory, `Error downloading file`);\r\n throw err;\r\n }\r\n if (fileSize && fs.existsSync(downloadToPathname)) {\r\n if (fs.lstatSync(downloadToPathname).size !== fileSize) {\r\n fs.unlinkSync(downloadToPathname);\r\n Logger.logError(loggerCategory, `Downloaded file is of incorrect size ${safeToLogUrl}`);\r\n throw new DownloadFailed(403, \"Download failed. Expected filesize does not match\");\r\n }\r\n }\r\n Logger.logTrace(loggerCategory, `Downloaded file from ${safeToLogUrl}`);\r\n }\r\n /** Get encoded block id from its number. */\r\n private getBlockId(blockId: number) {\r\n return Base64.encode(blockId.toString(16).padStart(5, \"0\"));\r\n }\r\n\r\n private async uploadChunk(_accessToken: AccessToken, uploadUrlString: string, fileDescriptor: number, blockId: number, callback?: ProgressCallback) {\r\n const chunkSize = 4 * 1024 * 1024;\r\n let buffer = Buffer.alloc(chunkSize);\r\n const bytesRead = fs.readSync(fileDescriptor, buffer, 0, chunkSize, chunkSize * blockId);\r\n buffer = buffer.slice(0, bytesRead);\r\n\r\n const options: RequestOptions = {\r\n method: \"PUT\",\r\n headers: {\r\n \"x-ms-blob-type\": \"BlockBlob\",\r\n \"Content-Type\": \"application/octet-stream\", // eslint-disable-line @typescript-eslint/naming-convention\r\n \"Content-Length\": buffer.length, // eslint-disable-line @typescript-eslint/naming-convention\r\n },\r\n body: buffer,\r\n progressCallback: callback,\r\n agent: this.agent,\r\n timeout: {\r\n deadline: 60000,\r\n response: 60000,\r\n },\r\n };\r\n\r\n const uploadUrl = `${uploadUrlString}&comp=block&blockid=${this.getBlockId(blockId)}`;\r\n await request(uploadUrl, options);\r\n }\r\n\r\n /**\r\n * Upload a file to AzureBlobStorage for iModelHub.\r\n * @param uploadUrl URL to upload the file to.\r\n * @param uploadFromPathname Pathname to upload the file from.\r\n * @param progressCallback Callback for tracking progress.\r\n * @throws [[IModelHubClientError]] with [IModelHubStatus.UndefinedArgumentError]($bentley) if one of the arguments is undefined or empty.\r\n */\r\n public async uploadFile(accessToken: AccessToken, uploadUrlString: string, uploadFromPathname: string, progressCallback?: ProgressCallback): Promise<void> {\r\n const safeToLogUrl = MobileFileHandler.getSafeUrlForLogging(uploadUrlString);\r\n Logger.logTrace(loggerCategory, `Uploading file to ${safeToLogUrl}`);\r\n defined(\"uploadUrlString\", uploadUrlString);\r\n defined(\"uploadFromPathname\", uploadFromPathname);\r\n\r\n const fileSize = this.getFileSize(uploadFromPathname);\r\n const file = fs.openSync(uploadFromPathname, \"r\");\r\n const chunkSize = 4 * 1024 * 1024;\r\n\r\n try {\r\n let blockList = '<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><BlockList>';\r\n let i = 0;\r\n const callback: ProgressCallback = (progress: ProgressInfo) => {\r\n const uploaded = i * chunkSize + progress.loaded;\r\n progressCallback!({ loaded: uploaded, percent: uploaded / fileSize, total: fileSize });\r\n };\r\n for (; i * chunkSize < fileSize; ++i) {\r\n await this.uploadChunk(accessToken, uploadUrlString, file, i, progressCallback ? callback : undefined);\r\n blockList += `<Latest>${this.getBlockId(i)}</Latest>`;\r\n }\r\n blockList += \"</BlockList>\";\r\n\r\n const options: RequestOptions = {\r\n method: \"PUT\",\r\n headers: {\r\n \"Content-Type\": \"application/xml\", // eslint-disable-line @typescript-eslint/naming-convention\r\n \"Content-Length\": blockList.length, // eslint-disable-line @typescript-eslint/naming-convention\r\n },\r\n body: blockList,\r\n agent: this.agent,\r\n timeout: {\r\n response: 5000,\r\n deadline: 60000,\r\n },\r\n };\r\n\r\n const uploadUrl = `${uploadUrlString}&comp=blocklist`;\r\n await request(uploadUrl, options);\r\n } finally {\r\n fs.closeSync(file);\r\n }\r\n }\r\n\r\n /**\r\n * Get size of a file.\r\n * @param filePath Path of the file.\r\n * @returns Size of the file.\r\n */\r\n public getFileSize(filePath: string): number {\r\n return fs.statSync(filePath).size;\r\n }\r\n\r\n /**\r\n * Check if path is a directory.\r\n * @param filePath Path of the file.\r\n * @returns True if path is directory.\r\n */\r\n public isDirectory(filePath: string): boolean {\r\n return fs.statSync(filePath).isDirectory();\r\n }\r\n\r\n /**\r\n * Check if path exists.\r\n * @param filePath Path of the file.\r\n * @returns True if path exists.\r\n */\r\n public exists(filePath: string): boolean {\r\n return fs.existsSync(filePath);\r\n }\r\n\r\n /**\r\n * Deletes file.\r\n * @param filePath Path of the file.\r\n */\r\n public unlink(filePath: string): void {\r\n fs.unlinkSync(filePath);\r\n }\r\n\r\n /**\r\n * Get file name from the path.\r\n * @param filePath Path of the file.\r\n * @returns File name.\r\n */\r\n public basename(filePath: string): string {\r\n return path.basename(filePath);\r\n }\r\n\r\n /**\r\n * Join multiple strings into a single path.\r\n * @param paths Strings to join.\r\n * @returns Joined path.\r\n */\r\n public join(...paths: string[]): string {\r\n return path.join(...paths);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"MobileFileHandler.js","sourceRoot":"","sources":["../../../src/backend/MobileFileHandler.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 iModelHub\r\n */\r\n\r\nimport * as fs from \"fs\";\r\nimport * as https from \"https\";\r\nimport * as path from \"path\";\r\nimport { AccessToken, BentleyError, GetMetaDataFunction, Logger } from \"@itwin/core-bentley\";\r\nimport { ProgressCallback, ProgressInfo, request, RequestOptions } from \"./Request\";\r\nimport { MobileHost } from \"./MobileHost\";\r\nimport { Base64 } from \"js-base64\";\r\n\r\nconst loggerCategory: string = \"mobile.filehandler\";\r\n\r\nconst defined = (argumentName: string, argument?: any, allowEmpty: boolean = false) => {\r\n if (argument === undefined || argument === null || (argument === \"\" && !allowEmpty))\r\n throw Error(`Argument ${argumentName} is null or undefined`);\r\n};\r\n\r\n/** Interface to cancel a request\r\n * @beta\r\n */\r\nexport interface CancelRequest {\r\n /** Returns true if cancel request was acknowledged */\r\n cancel: () => boolean;\r\n}\r\n\r\n/** Error thrown when user cancelled operation\r\n * @internal\r\n */\r\nexport class UserCancelledError extends BentleyError {\r\n public constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction) {\r\n super(errorNumber, message, getMetaData);\r\n this.name = \"User cancelled operation\";\r\n }\r\n}\r\n\r\n/** Error thrown fail to download file. ErrorNumber will correspond to HTTP error code.\r\n * @internal\r\n */\r\nexport class DownloadFailed extends BentleyError {\r\n public constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction) {\r\n super(errorNumber, message, getMetaData);\r\n this.name = \"Fail to download file\";\r\n }\r\n}\r\n\r\n/** Error thrown when sas-url provided for download has expired\r\n * @internal\r\n */\r\nexport class SasUrlExpired extends BentleyError {\r\n public constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction) {\r\n super(errorNumber, message, getMetaData);\r\n this.name = \"SaS url has expired\";\r\n }\r\n}\r\n\r\n/**\r\n * Provides methods to work with the file system and azure storage. An instance of this class has to be provided to [[IModelClient]] for file upload/download methods to work.\r\n * @internal\r\n */\r\nexport class MobileFileHandler {\r\n /** @internal */\r\n public agent?: https.Agent;\r\n\r\n /**\r\n * Constructor for MobileFileHandler.\r\n */\r\n constructor() {\r\n }\r\n\r\n /** Create a directory, recursively setting up the path as necessary. */\r\n private static makeDirectoryRecursive(dirPath: string) {\r\n if (fs.existsSync(dirPath))\r\n return;\r\n\r\n MobileFileHandler.makeDirectoryRecursive(path.dirname(dirPath));\r\n fs.mkdirSync(dirPath);\r\n }\r\n\r\n /**\r\n * Make url safe for logging by removing sensitive information\r\n * @param url input url that will be strip of search and query parameters and replace them by ... for security reason\r\n */\r\n private static getSafeUrlForLogging(url: string): string {\r\n const safeToLogDownloadUrl = new URL(url);\r\n if (safeToLogDownloadUrl.search && safeToLogDownloadUrl.search.length > 0)\r\n safeToLogDownloadUrl.search = \"...\";\r\n if (safeToLogDownloadUrl.hash && safeToLogDownloadUrl.hash.length > 0)\r\n safeToLogDownloadUrl.hash = \"...\";\r\n return safeToLogDownloadUrl.toString();\r\n }\r\n\r\n /**\r\n * Check if sas url has expired\r\n * @param download sas url for download\r\n * @param futureSeconds should be valid in future for given seconds.\r\n */\r\n public static isUrlExpired(downloadUrl: string, futureSeconds?: number): boolean {\r\n const sasUrl = new URL(downloadUrl);\r\n const se = sasUrl.searchParams.get(\"se\");\r\n if (se) {\r\n const expiryUTC = new Date(se);\r\n const now = new Date();\r\n const currentUTC = new Date(now.toUTCString());\r\n if (futureSeconds) {\r\n currentUTC.setSeconds(futureSeconds + currentUTC.getSeconds());\r\n }\r\n return expiryUTC <= currentUTC;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Download a file from AzureBlobStorage for iModelHub. Creates the directory containing the file if necessary. If there is an error in the operation, incomplete file is deleted from disk.\r\n * @param downloadUrl URL to download file from.\r\n * @param downloadToPathname Pathname to download the file to.\r\n * @param fileSize Size of the file that's being downloaded.\r\n * @param progressCallback Callback for tracking progress.\r\n * @throws [[IModelHubClientError]] with [IModelHubStatus.UndefinedArgumentError]($bentley) if one of the arguments is undefined or empty.\r\n */\r\n public async downloadFile(_accessToken: AccessToken, downloadUrl: string, downloadToPathname: string, fileSize?: number, progressCallback?: ProgressCallback, cancelRequest?: CancelRequest): Promise<void> {\r\n // strip search and hash parameters from download Url for logging purpose\r\n const safeToLogUrl = MobileFileHandler.getSafeUrlForLogging(downloadUrl);\r\n Logger.logInfo(loggerCategory, `Downloading file from ${safeToLogUrl}`);\r\n\r\n defined(\"downloadUrl\", downloadUrl);\r\n defined(\"downloadToPathname\", downloadToPathname);\r\n if (MobileFileHandler.isUrlExpired(downloadUrl)) {\r\n Logger.logError(loggerCategory, `Sas url has expired ${safeToLogUrl}`);\r\n throw new SasUrlExpired(403, \"Download URL has expired\");\r\n }\r\n if (fs.existsSync(downloadToPathname))\r\n fs.unlinkSync(downloadToPathname);\r\n\r\n MobileFileHandler.makeDirectoryRecursive(path.dirname(downloadToPathname));\r\n try {\r\n await MobileHost.downloadFile(downloadUrl, downloadToPathname, progressCallback, cancelRequest);\r\n } catch (err) {\r\n if (fs.existsSync(downloadToPathname))\r\n fs.unlinkSync(downloadToPathname); // Just in case there was a partial download, delete the file\r\n\r\n if (!(err instanceof UserCancelledError))\r\n Logger.logError(loggerCategory, `Error downloading file`);\r\n throw err;\r\n }\r\n if (fileSize && fs.existsSync(downloadToPathname)) {\r\n if (fs.lstatSync(downloadToPathname).size !== fileSize) {\r\n fs.unlinkSync(downloadToPathname);\r\n Logger.logError(loggerCategory, `Downloaded file is of incorrect size ${safeToLogUrl}`);\r\n throw new DownloadFailed(403, \"Download failed. Expected filesize does not match\");\r\n }\r\n }\r\n Logger.logTrace(loggerCategory, `Downloaded file from ${safeToLogUrl}`);\r\n }\r\n /** Get encoded block id from its number. */\r\n private getBlockId(blockId: number) {\r\n return Base64.encode(blockId.toString(16).padStart(5, \"0\"));\r\n }\r\n\r\n private async uploadChunk(_accessToken: AccessToken, uploadUrlString: string, fileDescriptor: number, blockId: number, callback?: ProgressCallback) {\r\n const chunkSize = 4 * 1024 * 1024;\r\n let buffer = Buffer.alloc(chunkSize);\r\n const bytesRead = fs.readSync(fileDescriptor, buffer, 0, chunkSize, chunkSize * blockId);\r\n buffer = buffer.slice(0, bytesRead);\r\n\r\n const options: RequestOptions = {\r\n method: \"PUT\",\r\n headers: {\r\n \"x-ms-blob-type\": \"BlockBlob\",\r\n \"Content-Type\": \"application/octet-stream\", // eslint-disable-line @typescript-eslint/naming-convention\r\n \"Content-Length\": buffer.length, // eslint-disable-line @typescript-eslint/naming-convention\r\n },\r\n body: buffer,\r\n progressCallback: callback,\r\n agent: this.agent,\r\n timeout: {\r\n deadline: 60000,\r\n response: 60000,\r\n },\r\n };\r\n\r\n const uploadUrl = `${uploadUrlString}&comp=block&blockid=${this.getBlockId(blockId)}`;\r\n await request(uploadUrl, options);\r\n }\r\n\r\n /**\r\n * Upload a file to AzureBlobStorage for iModelHub.\r\n * @param uploadUrl URL to upload the file to.\r\n * @param uploadFromPathname Pathname to upload the file from.\r\n * @param progressCallback Callback for tracking progress.\r\n * @throws [[IModelHubClientError]] with [IModelHubStatus.UndefinedArgumentError]($bentley) if one of the arguments is undefined or empty.\r\n */\r\n public async uploadFile(accessToken: AccessToken, uploadUrlString: string, uploadFromPathname: string, progressCallback?: ProgressCallback): Promise<void> {\r\n const safeToLogUrl = MobileFileHandler.getSafeUrlForLogging(uploadUrlString);\r\n Logger.logTrace(loggerCategory, `Uploading file to ${safeToLogUrl}`);\r\n defined(\"uploadUrlString\", uploadUrlString);\r\n defined(\"uploadFromPathname\", uploadFromPathname);\r\n\r\n const fileSize = this.getFileSize(uploadFromPathname);\r\n const file = fs.openSync(uploadFromPathname, \"r\");\r\n const chunkSize = 4 * 1024 * 1024;\r\n\r\n try {\r\n let blockList = '<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><BlockList>';\r\n let i = 0;\r\n const callback: ProgressCallback = (progress: ProgressInfo) => {\r\n const uploaded = i * chunkSize + progress.loaded;\r\n if (progressCallback)\r\n progressCallback({ loaded: uploaded, percent: uploaded / fileSize, total: fileSize });\r\n };\r\n for (; i * chunkSize < fileSize; ++i) {\r\n await this.uploadChunk(accessToken, uploadUrlString, file, i, progressCallback ? callback : undefined);\r\n blockList += `<Latest>${this.getBlockId(i)}</Latest>`;\r\n }\r\n blockList += \"</BlockList>\";\r\n\r\n const options: RequestOptions = {\r\n method: \"PUT\",\r\n headers: {\r\n \"Content-Type\": \"application/xml\", // eslint-disable-line @typescript-eslint/naming-convention\r\n \"Content-Length\": blockList.length, // eslint-disable-line @typescript-eslint/naming-convention\r\n },\r\n body: blockList,\r\n agent: this.agent,\r\n timeout: {\r\n response: 5000,\r\n deadline: 60000,\r\n },\r\n };\r\n\r\n const uploadUrl = `${uploadUrlString}&comp=blocklist`;\r\n await request(uploadUrl, options);\r\n } finally {\r\n fs.closeSync(file);\r\n }\r\n }\r\n\r\n /**\r\n * Get size of a file.\r\n * @param filePath Path of the file.\r\n * @returns Size of the file.\r\n */\r\n public getFileSize(filePath: string): number {\r\n return fs.statSync(filePath).size;\r\n }\r\n\r\n /**\r\n * Check if path is a directory.\r\n * @param filePath Path of the file.\r\n * @returns True if path is directory.\r\n */\r\n public isDirectory(filePath: string): boolean {\r\n return fs.statSync(filePath).isDirectory();\r\n }\r\n\r\n /**\r\n * Check if path exists.\r\n * @param filePath Path of the file.\r\n * @returns True if path exists.\r\n */\r\n public exists(filePath: string): boolean {\r\n return fs.existsSync(filePath);\r\n }\r\n\r\n /**\r\n * Deletes file.\r\n * @param filePath Path of the file.\r\n */\r\n public unlink(filePath: string): void {\r\n fs.unlinkSync(filePath);\r\n }\r\n\r\n /**\r\n * Get file name from the path.\r\n * @param filePath Path of the file.\r\n * @returns File name.\r\n */\r\n public basename(filePath: string): string {\r\n return path.basename(filePath);\r\n }\r\n\r\n /**\r\n * Join multiple strings into a single path.\r\n * @param paths Strings to join.\r\n * @returns Joined path.\r\n */\r\n public join(...paths: string[]): string {\r\n return path.join(...paths);\r\n }\r\n}\r\n"]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { BeEvent } from "@itwin/core-bentley";
|
|
2
2
|
import { NativeHostOpts } from "@itwin/core-backend";
|
|
3
|
-
import {
|
|
4
|
-
import { CancelRequest
|
|
3
|
+
import { RpcInterfaceDefinition } from "@itwin/core-common";
|
|
4
|
+
import { CancelRequest } from "./MobileFileHandler";
|
|
5
|
+
import { ProgressCallback } from "./Request";
|
|
5
6
|
import { BatteryState, DeviceEvents, Orientation } from "../common/MobileAppProps";
|
|
6
|
-
import { MobileAuthorizationBackend } from "./MobileAuthorizationBackend";
|
|
7
|
+
import { MobileAppAuthorizationConfiguration, MobileAuthorizationBackend } from "./MobileAuthorizationBackend";
|
|
7
8
|
/** @beta */
|
|
8
9
|
export declare type MobileCompletionCallback = (downloadUrl: string, downloadFileUrl: string, cancelled: boolean, err?: string) => void;
|
|
9
10
|
/** @beta */
|
|
@@ -39,7 +40,7 @@ export declare abstract class MobileDevice {
|
|
|
39
40
|
abstract authSignIn(callback: (err?: string) => void): void;
|
|
40
41
|
abstract authSignOut(callback: (err?: string) => void): void;
|
|
41
42
|
abstract authGetAccessToken(callback: (accessToken?: string, err?: string) => void): void;
|
|
42
|
-
authInit(_config:
|
|
43
|
+
authInit(_config: MobileAppAuthorizationConfiguration, callback: (err?: string) => void): void;
|
|
43
44
|
abstract authStateChanged(accessToken?: string, err?: string): void;
|
|
44
45
|
}
|
|
45
46
|
/** @beta */
|
|
@@ -48,8 +49,8 @@ export interface MobileHostOpts extends NativeHostOpts {
|
|
|
48
49
|
device?: MobileDevice;
|
|
49
50
|
/** list of RPC interface definitions to register */
|
|
50
51
|
rpcInterfaces?: RpcInterfaceDefinition[];
|
|
51
|
-
/** if present, [[NativeHost.authorizationClient]] will be set to an instance of
|
|
52
|
-
authConfig?:
|
|
52
|
+
/** if present, [[NativeHost.authorizationClient]] will be set to an instance of MobileAppAuthorizationConfiguration and will be initialized. */
|
|
53
|
+
authConfig?: MobileAppAuthorizationConfiguration;
|
|
53
54
|
/** if true, do not attempt to initialize AuthorizationClient on startup */
|
|
54
55
|
noInitializeAuthClient?: boolean;
|
|
55
56
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileHost.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileHost.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAmB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAA+C,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAClG,OAAO,EACuE,
|
|
1
|
+
{"version":3,"file":"MobileHost.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileHost.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ exports.MobileHost = exports.MobileDevice = void 0;
|
|
|
8
8
|
const core_bentley_1 = require("@itwin/core-bentley");
|
|
9
9
|
const core_backend_1 = require("@itwin/core-backend");
|
|
10
10
|
const core_common_1 = require("@itwin/core-common");
|
|
11
|
-
const
|
|
11
|
+
const MobileFileHandler_1 = require("./MobileFileHandler");
|
|
12
12
|
const presentation_common_1 = require("@itwin/presentation-common");
|
|
13
13
|
const MobileAppProps_1 = require("../common/MobileAppProps");
|
|
14
14
|
const MobileRpcManager_1 = require("../common/MobileRpcManager");
|
|
@@ -76,9 +76,9 @@ class MobileHost {
|
|
|
76
76
|
}
|
|
77
77
|
const requestId = this.device.createDownloadTask(downloadUrl, false, downloadTo, (_downloadUrl, _downloadFileUrl, cancelled, err) => {
|
|
78
78
|
if (cancelled)
|
|
79
|
-
reject(new
|
|
79
|
+
reject(new MobileFileHandler_1.UserCancelledError(core_bentley_1.BriefcaseStatus.DownloadCancelled, "User cancelled download"));
|
|
80
80
|
else if (err)
|
|
81
|
-
reject(new
|
|
81
|
+
reject(new MobileFileHandler_1.DownloadFailed(400, "Download failed"));
|
|
82
82
|
else
|
|
83
83
|
resolve();
|
|
84
84
|
}, progressCb);
|
|
@@ -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 { BeEvent, BriefcaseStatus } from \"@itwin/core-bentley\";\r\nimport { IModelHost, IpcHandler, IpcHost, NativeHost, NativeHostOpts } from \"@itwin/core-backend\";\r\nimport {\r\n IModelReadRpcInterface, IModelTileRpcInterface, InternetConnectivityStatus, NativeAppAuthorizationConfiguration, RpcInterfaceDefinition,\r\n SnapshotIModelRpcInterface,\r\n} from \"@itwin/core-common\";\r\nimport { CancelRequest, DownloadFailed, ProgressCallback, UserCancelledError } from \"@bentley/itwin-client\";\r\nimport { PresentationRpcInterface } from \"@itwin/presentation-common\";\r\nimport { BatteryState, DeviceEvents, mobileAppChannel, MobileAppFunctions, 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); break;\r\n case \"orientationChanged\":\r\n MobileHost.onOrientationChanged.raiseEvent(...args); break;\r\n case \"enterForeground\":\r\n MobileHost.onEnterForeground.raiseEvent(...args); break;\r\n case \"enterBackground\":\r\n MobileHost.onEnterBackground.raiseEvent(...args); break;\r\n case \"willTerminate\":\r\n MobileHost.onWillTerminate.raiseEvent(...args); 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 authSignIn(callback: (err?: string) => void): void;\r\n public abstract authSignOut(callback: (err?: string) => void): void;\r\n public abstract authGetAccessToken(callback: (accessToken?: string, err?: string) => void): void;\r\n public authInit(_config: NativeAppAuthorizationConfiguration, callback: (err?: string) => void): void { callback(); }\r\n public abstract authStateChanged(accessToken?: string, err?: string): void;\r\n}\r\n\r\nclass MobileAppHandler extends IpcHandler implements MobileAppFunctions {\r\n public get channelName() { return mobileAppChannel; }\r\n public async reconnect(connection: number) {\r\n MobileHost.reconnect(connection);\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 /** if present, [[NativeHost.authorizationClient]] will be set to an instance of NativeAppAuthorizationBackend and will be initialized. */\r\n authConfig?: NativeAppAuthorizationConfiguration;\r\n /** if true, do not attempt to initialize AuthorizationClient on startup */\r\n noInitializeAuthClient?: boolean;\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() { return this._device!; }\r\n public static readonly onMemoryWarning = new BeEvent();\r\n public static readonly onOrientationChanged = new BeEvent();\r\n public static readonly onEnterForeground = new BeEvent();\r\n public static readonly onEnterBackground = new BeEvent();\r\n public static readonly onWillTerminate = new BeEvent();\r\n\r\n /** @internal */\r\n public static get authorization() { return IModelHost.authorizationClient as MobileAuthorizationBackend; }\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 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 // eslint-disable-next-line @typescript-eslint/unbound-method\r\n cancelRequest.cancel = () => { return 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 if (!this.isValid) {\r\n this._device = opt?.mobileHost?.device ?? new (MobileDevice as any)();\r\n // set global device interface.\r\n (global as any).__iTwinJsNativeBridge = this._device;\r\n // following will provide impl for device specific api.\r\n setupMobileRpc();\r\n }\r\n\r\n await NativeHost.startup(opt);\r\n if (IpcHost.isValid)\r\n MobileAppHandler.register();\r\n\r\n const rpcInterfaces = opt?.mobileHost?.rpcInterfaces ?? [\r\n IModelReadRpcInterface,\r\n IModelTileRpcInterface,\r\n SnapshotIModelRpcInterface,\r\n PresentationRpcInterface,\r\n ];\r\n\r\n MobileRpcManager.initializeImpl(rpcInterfaces);\r\n\r\n const authorizationBackend = new MobileAuthorizationBackend(opt?.mobileHost?.authConfig);\r\n const connectivityStatus = NativeHost.checkInternetConnectivity();\r\n if (opt?.mobileHost?.authConfig && true !== opt?.mobileHost?.noInitializeAuthClient && connectivityStatus === InternetConnectivityStatus.Online) {\r\n await authorizationBackend.initialize(opt?.mobileHost?.authConfig);\r\n }\r\n IModelHost.authorizationClient = authorizationBackend;\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 { BeEvent, BriefcaseStatus } from \"@itwin/core-bentley\";\r\nimport { IModelHost, IpcHandler, IpcHost, NativeHost, NativeHostOpts } from \"@itwin/core-backend\";\r\nimport {\r\n IModelReadRpcInterface, IModelTileRpcInterface, InternetConnectivityStatus, RpcInterfaceDefinition,\r\n SnapshotIModelRpcInterface,\r\n} from \"@itwin/core-common\";\r\nimport { CancelRequest, DownloadFailed, UserCancelledError } from \"./MobileFileHandler\";\r\nimport { ProgressCallback } from \"./Request\";\r\nimport { PresentationRpcInterface } from \"@itwin/presentation-common\";\r\nimport { BatteryState, DeviceEvents, mobileAppChannel, MobileAppFunctions, Orientation } from \"../common/MobileAppProps\";\r\nimport { MobileRpcManager } from \"../common/MobileRpcManager\";\r\nimport { MobileAppAuthorizationConfiguration, 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); break;\r\n case \"orientationChanged\":\r\n MobileHost.onOrientationChanged.raiseEvent(...args); break;\r\n case \"enterForeground\":\r\n MobileHost.onEnterForeground.raiseEvent(...args); break;\r\n case \"enterBackground\":\r\n MobileHost.onEnterBackground.raiseEvent(...args); break;\r\n case \"willTerminate\":\r\n MobileHost.onWillTerminate.raiseEvent(...args); 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 authSignIn(callback: (err?: string) => void): void;\r\n public abstract authSignOut(callback: (err?: string) => void): void;\r\n public abstract authGetAccessToken(callback: (accessToken?: string, err?: string) => void): void;\r\n public authInit(_config: MobileAppAuthorizationConfiguration, callback: (err?: string) => void): void { callback(); }\r\n public abstract authStateChanged(accessToken?: string, err?: string): void;\r\n}\r\n\r\nclass MobileAppHandler extends IpcHandler implements MobileAppFunctions {\r\n public get channelName() { return mobileAppChannel; }\r\n public async reconnect(connection: number) {\r\n MobileHost.reconnect(connection);\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 /** if present, [[NativeHost.authorizationClient]] will be set to an instance of MobileAppAuthorizationConfiguration and will be initialized. */\r\n authConfig?: MobileAppAuthorizationConfiguration;\r\n /** if true, do not attempt to initialize AuthorizationClient on startup */\r\n noInitializeAuthClient?: boolean;\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() { return this._device!; }\r\n public static readonly onMemoryWarning = new BeEvent();\r\n public static readonly onOrientationChanged = new BeEvent();\r\n public static readonly onEnterForeground = new BeEvent();\r\n public static readonly onEnterBackground = new BeEvent();\r\n public static readonly onWillTerminate = new BeEvent();\r\n\r\n /** @internal */\r\n public static get authorization() { return IModelHost.authorizationClient as MobileAuthorizationBackend; }\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 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 // eslint-disable-next-line @typescript-eslint/unbound-method\r\n cancelRequest.cancel = () => { return 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 if (!this.isValid) {\r\n this._device = opt?.mobileHost?.device ?? new (MobileDevice as any)();\r\n // set global device interface.\r\n (global as any).__iTwinJsNativeBridge = this._device;\r\n // following will provide impl for device specific api.\r\n setupMobileRpc();\r\n }\r\n\r\n await NativeHost.startup(opt);\r\n if (IpcHost.isValid)\r\n MobileAppHandler.register();\r\n\r\n const rpcInterfaces = opt?.mobileHost?.rpcInterfaces ?? [\r\n IModelReadRpcInterface,\r\n IModelTileRpcInterface,\r\n SnapshotIModelRpcInterface,\r\n PresentationRpcInterface,\r\n ];\r\n\r\n MobileRpcManager.initializeImpl(rpcInterfaces);\r\n\r\n const authorizationBackend = new MobileAuthorizationBackend(opt?.mobileHost?.authConfig);\r\n const connectivityStatus = NativeHost.checkInternetConnectivity();\r\n if (opt?.mobileHost?.authConfig && true !== opt?.mobileHost?.noInitializeAuthClient && connectivityStatus === InternetConnectivityStatus.Online) {\r\n await authorizationBackend.initialize(opt?.mobileHost?.authConfig);\r\n }\r\n IModelHost.authorizationClient = authorizationBackend;\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import * as https from "https";
|
|
3
|
+
import { BentleyError, GetMetaDataFunction, HttpStatus } from "@itwin/core-bentley";
|
|
4
|
+
/** @internal */
|
|
5
|
+
export declare const requestIdHeaderName = "X-Correlation-Id";
|
|
6
|
+
/** Typical option to query REST API. Note that services may not quite support these fields,
|
|
7
|
+
* and the interface is only provided as a hint.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export interface RequestQueryOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Select string used by the query (use the mapped EC property names, and not TypeScript property names)
|
|
13
|
+
* Example: "Name,Size,Description"
|
|
14
|
+
*/
|
|
15
|
+
$select?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Filter string used by the query (use the mapped EC property names, and not TypeScript property names)
|
|
18
|
+
* Example: "Name like '*.pdf' and Size lt 1000"
|
|
19
|
+
*/
|
|
20
|
+
$filter?: string;
|
|
21
|
+
/** Sets the limit on the number of entries to be returned by the query */
|
|
22
|
+
$top?: number;
|
|
23
|
+
/** Sets the number of entries to be skipped */
|
|
24
|
+
$skip?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Orders the return values (use the mapped EC property names, and not TypeScript property names)
|
|
27
|
+
* Example: "Size desc"
|
|
28
|
+
*/
|
|
29
|
+
$orderby?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Sets the limit on the number of entries to be returned by a single response.
|
|
32
|
+
* Can be used with a Top option. For example if Top is set to 1000 and PageSize
|
|
33
|
+
* is set to 100 then 10 requests will be performed to get result.
|
|
34
|
+
*/
|
|
35
|
+
$pageSize?: number;
|
|
36
|
+
}
|
|
37
|
+
/** @internal */
|
|
38
|
+
export interface RequestQueryStringifyOptions {
|
|
39
|
+
delimiter?: string;
|
|
40
|
+
encode?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Option to control the time outs
|
|
43
|
+
* Use a short response timeout to detect unresponsive networks quickly, and a long deadline to give time for downloads on slow,
|
|
44
|
+
* but reliable, networks. Note that both of these timers limit how long uploads of attached files are allowed to take. Use long
|
|
45
|
+
* timeouts if you're uploading files.
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
export interface RequestTimeoutOptions {
|
|
49
|
+
/** Sets a deadline (in milliseconds) for the entire request (including all uploads, redirects, server processing time) to complete.
|
|
50
|
+
* If the response isn't fully downloaded within that time, the request will be aborted
|
|
51
|
+
*/
|
|
52
|
+
deadline?: number;
|
|
53
|
+
/** Sets maximum time (in milliseconds) to wait for the first byte to arrive from the server, but it does not limit how long the entire
|
|
54
|
+
* download can take. Response timeout should be at least few seconds longer than just the time it takes the server to respond, because
|
|
55
|
+
* it also includes time to make DNS lookup, TCP/IP and TLS connections, and time to upload request data.
|
|
56
|
+
*/
|
|
57
|
+
response?: number;
|
|
58
|
+
}
|
|
59
|
+
/** @internal */
|
|
60
|
+
export interface RequestOptions {
|
|
61
|
+
method: string;
|
|
62
|
+
headers?: any;
|
|
63
|
+
body?: any;
|
|
64
|
+
qs?: any | RequestQueryOptions;
|
|
65
|
+
responseType?: string;
|
|
66
|
+
timeout?: RequestTimeoutOptions;
|
|
67
|
+
stream?: any;
|
|
68
|
+
readStream?: any;
|
|
69
|
+
buffer?: any;
|
|
70
|
+
parser?: any;
|
|
71
|
+
accept?: string;
|
|
72
|
+
redirects?: number;
|
|
73
|
+
errorCallback?: (response: any) => ResponseError;
|
|
74
|
+
retryCallback?: (error: any, response: any) => boolean;
|
|
75
|
+
progressCallback?: ProgressCallback;
|
|
76
|
+
agent?: https.Agent;
|
|
77
|
+
retries?: number;
|
|
78
|
+
useCorsProxy?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/** Response object if the request was successful. Note that the status within the range of 200-299 are considered as a success.
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
export interface Response {
|
|
84
|
+
body: any;
|
|
85
|
+
text: string | undefined;
|
|
86
|
+
header: any;
|
|
87
|
+
status: number;
|
|
88
|
+
}
|
|
89
|
+
/** @internal */
|
|
90
|
+
export interface ProgressInfo {
|
|
91
|
+
percent?: number;
|
|
92
|
+
total?: number;
|
|
93
|
+
loaded: number;
|
|
94
|
+
}
|
|
95
|
+
/** @internal */
|
|
96
|
+
export declare type ProgressCallback = (progress: ProgressInfo) => void;
|
|
97
|
+
/** Error object that's thrown/rejected if the Request fails due to a network error, or if the status is *not* in the range of 200-299 (inclusive)
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
100
|
+
export declare class ResponseError extends BentleyError {
|
|
101
|
+
protected _data?: any;
|
|
102
|
+
status?: number;
|
|
103
|
+
description?: string;
|
|
104
|
+
constructor(errorNumber: number | HttpStatus, message?: string, getMetaData?: GetMetaDataFunction);
|
|
105
|
+
/**
|
|
106
|
+
* Parses error from server's response
|
|
107
|
+
* @param response Http response from the server.
|
|
108
|
+
* @returns Parsed error.
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
111
|
+
static parse(response: any, log?: boolean): ResponseError;
|
|
112
|
+
/**
|
|
113
|
+
* Decides whether request should be retried or not
|
|
114
|
+
* @param error Error returned by request
|
|
115
|
+
* @param response Response returned by request
|
|
116
|
+
* @internal
|
|
117
|
+
*/
|
|
118
|
+
static shouldRetry(error: any, response: any): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
static parseHttpStatus(statusType: number): HttpStatus;
|
|
123
|
+
/**
|
|
124
|
+
* @internal
|
|
125
|
+
*/
|
|
126
|
+
logMessage(): string;
|
|
127
|
+
/**
|
|
128
|
+
* Logs this error
|
|
129
|
+
* @internal
|
|
130
|
+
*/
|
|
131
|
+
log(): void;
|
|
132
|
+
}
|
|
133
|
+
/** Wrapper around making HTTP requests with the specific options.
|
|
134
|
+
*
|
|
135
|
+
* Usable in both a browser and node based environment.
|
|
136
|
+
*
|
|
137
|
+
* @param url Server URL to address the request
|
|
138
|
+
* @param options Options to pass to the request
|
|
139
|
+
* @returns Resolves to the response from the server
|
|
140
|
+
* @throws ResponseError if the request fails due to network issues, or if the returned status is *outside* the range of 200-299 (inclusive)
|
|
141
|
+
* @internal
|
|
142
|
+
*/
|
|
143
|
+
export declare function request(url: string, options: RequestOptions): Promise<Response>;
|
|
144
|
+
/**
|
|
145
|
+
* fetch json from HTTP request
|
|
146
|
+
* @param url server URL to address the request
|
|
147
|
+
* @internal
|
|
148
|
+
*/
|
|
149
|
+
export declare function getJson(url: string): Promise<any>;
|
|
150
|
+
//# sourceMappingURL=Request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Request.d.ts","sourceRoot":"","sources":["../../../src/backend/Request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getJson = exports.request = exports.ResponseError = exports.requestIdHeaderName = void 0;
|
|
4
|
+
/*---------------------------------------------------------------------------------------------
|
|
5
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
6
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
7
|
+
*--------------------------------------------------------------------------------------------*/
|
|
8
|
+
/** @packageDocumentation
|
|
9
|
+
* @module iTwinServiceClients
|
|
10
|
+
*/
|
|
11
|
+
const deepAssign = require("deep-assign");
|
|
12
|
+
const qs_1 = require("qs");
|
|
13
|
+
const sarequest = require("superagent");
|
|
14
|
+
const core_bentley_1 = require("@itwin/core-bentley");
|
|
15
|
+
const loggerCategory = "core-mobile-backend.Request";
|
|
16
|
+
/** @internal */
|
|
17
|
+
exports.requestIdHeaderName = "X-Correlation-Id";
|
|
18
|
+
/** Error object that's thrown/rejected if the Request fails due to a network error, or if the status is *not* in the range of 200-299 (inclusive)
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
class ResponseError extends core_bentley_1.BentleyError {
|
|
22
|
+
constructor(errorNumber, message, getMetaData) {
|
|
23
|
+
super(errorNumber, message, getMetaData);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parses error from server's response
|
|
27
|
+
* @param response Http response from the server.
|
|
28
|
+
* @returns Parsed error.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
static parse(response, log = true) {
|
|
32
|
+
const error = new ResponseError(ResponseError.parseHttpStatus(response.statusType));
|
|
33
|
+
if (!response) {
|
|
34
|
+
error.message = "Couldn't get response object.";
|
|
35
|
+
return error;
|
|
36
|
+
}
|
|
37
|
+
if (response.response) {
|
|
38
|
+
if (response.response.error) {
|
|
39
|
+
error.name = response.response.error.name || error.name;
|
|
40
|
+
error.description = response.response.error.message;
|
|
41
|
+
}
|
|
42
|
+
if (response.response.res) {
|
|
43
|
+
error.message = response.response.res.statusMessage;
|
|
44
|
+
}
|
|
45
|
+
if (response.response.body && Object.keys(response.response.body).length > 0) {
|
|
46
|
+
error._data = {};
|
|
47
|
+
deepAssign(error._data, response.response.body);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
error._data = response.response.text;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
error.status = response.status || response.statusCode;
|
|
54
|
+
error.name = response.code || response.name || error.name;
|
|
55
|
+
error.message = error.message || response.message || response.statusMessage;
|
|
56
|
+
if (log)
|
|
57
|
+
error.log();
|
|
58
|
+
return error;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Decides whether request should be retried or not
|
|
62
|
+
* @param error Error returned by request
|
|
63
|
+
* @param response Response returned by request
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
static shouldRetry(error, response) {
|
|
67
|
+
if (error !== undefined && error !== null) {
|
|
68
|
+
if ((error.status === undefined || error.status === null) && (error.res === undefined || error.res === null)) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return (response !== undefined && response.statusType === core_bentley_1.HttpStatus.ServerError);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @internal
|
|
76
|
+
*/
|
|
77
|
+
static parseHttpStatus(statusType) {
|
|
78
|
+
switch (statusType) {
|
|
79
|
+
case 1:
|
|
80
|
+
return core_bentley_1.HttpStatus.Info;
|
|
81
|
+
case 2:
|
|
82
|
+
return core_bentley_1.HttpStatus.Success;
|
|
83
|
+
case 3:
|
|
84
|
+
return core_bentley_1.HttpStatus.Redirection;
|
|
85
|
+
case 4:
|
|
86
|
+
return core_bentley_1.HttpStatus.ClientError;
|
|
87
|
+
case 5:
|
|
88
|
+
return core_bentley_1.HttpStatus.ServerError;
|
|
89
|
+
default:
|
|
90
|
+
return core_bentley_1.HttpStatus.Success;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
logMessage() {
|
|
97
|
+
return `${this.status} ${this.name}: ${this.message}`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Logs this error
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
log() {
|
|
104
|
+
core_bentley_1.Logger.logError(loggerCategory, this.logMessage(), () => this.getMetaData());
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.ResponseError = ResponseError;
|
|
108
|
+
const logResponse = (req, startTime) => (res) => {
|
|
109
|
+
const elapsed = new Date().getTime() - startTime;
|
|
110
|
+
const elapsedTime = `${elapsed}ms`;
|
|
111
|
+
core_bentley_1.Logger.logTrace(loggerCategory, `${req.method.toUpperCase()} ${res.status} ${req.url} (${elapsedTime})`);
|
|
112
|
+
};
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
114
|
+
const logRequest = (req) => {
|
|
115
|
+
const startTime = new Date().getTime();
|
|
116
|
+
return req.on("response", logResponse(req, startTime));
|
|
117
|
+
};
|
|
118
|
+
/** Wrapper around making HTTP requests with the specific options.
|
|
119
|
+
*
|
|
120
|
+
* Usable in both a browser and node based environment.
|
|
121
|
+
*
|
|
122
|
+
* @param url Server URL to address the request
|
|
123
|
+
* @param options Options to pass to the request
|
|
124
|
+
* @returns Resolves to the response from the server
|
|
125
|
+
* @throws ResponseError if the request fails due to network issues, or if the returned status is *outside* the range of 200-299 (inclusive)
|
|
126
|
+
* @internal
|
|
127
|
+
*/
|
|
128
|
+
async function request(url, options) {
|
|
129
|
+
let sareq = sarequest(options.method, url);
|
|
130
|
+
if (options.retries)
|
|
131
|
+
sareq = sareq.retry(options.retries, options.retryCallback);
|
|
132
|
+
if (core_bentley_1.Logger.isEnabled(loggerCategory, core_bentley_1.LogLevel.Trace))
|
|
133
|
+
sareq = sareq.use(logRequest);
|
|
134
|
+
if (options.headers)
|
|
135
|
+
sareq = sareq.set(options.headers);
|
|
136
|
+
let queryStr = "";
|
|
137
|
+
let fullUrl = "";
|
|
138
|
+
if (options.qs && Object.keys(options.qs).length > 0) {
|
|
139
|
+
const stringifyOptions = { delimiter: "&", encode: false };
|
|
140
|
+
queryStr = (0, qs_1.stringify)(options.qs, stringifyOptions);
|
|
141
|
+
sareq = sareq.query(queryStr);
|
|
142
|
+
fullUrl = `${url}?${queryStr}`;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
fullUrl = url;
|
|
146
|
+
}
|
|
147
|
+
core_bentley_1.Logger.logInfo(loggerCategory, fullUrl);
|
|
148
|
+
if (options.accept)
|
|
149
|
+
sareq = sareq.accept(options.accept);
|
|
150
|
+
if (options.body)
|
|
151
|
+
sareq = sareq.send(options.body);
|
|
152
|
+
if (options.timeout)
|
|
153
|
+
sareq = sareq.timeout(options.timeout);
|
|
154
|
+
if (options.responseType)
|
|
155
|
+
sareq = sareq.responseType(options.responseType);
|
|
156
|
+
if (options.redirects)
|
|
157
|
+
sareq = sareq.redirects(options.redirects);
|
|
158
|
+
else
|
|
159
|
+
sareq = sareq.redirects(0);
|
|
160
|
+
if (options.buffer)
|
|
161
|
+
sareq = sareq.buffer(options.buffer);
|
|
162
|
+
if (options.parser)
|
|
163
|
+
sareq = sareq.parse(options.parser);
|
|
164
|
+
/** Default to any globally supplied proxy, unless an agent is specified in this call */
|
|
165
|
+
if (options.agent)
|
|
166
|
+
sareq = sareq.agent(options.agent);
|
|
167
|
+
if (options.progressCallback) {
|
|
168
|
+
sareq = sareq.on("progress", (event) => {
|
|
169
|
+
if (event) {
|
|
170
|
+
options.progressCallback({
|
|
171
|
+
loaded: event.loaded,
|
|
172
|
+
total: event.total,
|
|
173
|
+
percent: event.percent,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
const errorCallback = options.errorCallback ? options.errorCallback : ResponseError.parse;
|
|
179
|
+
if (options.readStream) {
|
|
180
|
+
if (typeof window !== "undefined")
|
|
181
|
+
throw new Error("This option is not supported on browsers");
|
|
182
|
+
return new Promise((resolve, reject) => {
|
|
183
|
+
sareq = sareq.type("blob");
|
|
184
|
+
options
|
|
185
|
+
.readStream
|
|
186
|
+
.pipe(sareq)
|
|
187
|
+
.on("error", (error) => {
|
|
188
|
+
const parsedError = errorCallback(error);
|
|
189
|
+
reject(parsedError);
|
|
190
|
+
})
|
|
191
|
+
.on("end", () => {
|
|
192
|
+
const retResponse = {
|
|
193
|
+
status: 201,
|
|
194
|
+
header: undefined,
|
|
195
|
+
body: undefined,
|
|
196
|
+
text: undefined,
|
|
197
|
+
};
|
|
198
|
+
resolve(retResponse);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
if (options.stream) {
|
|
203
|
+
if (typeof window !== "undefined")
|
|
204
|
+
throw new Error("This option is not supported on browsers");
|
|
205
|
+
return new Promise((resolve, reject) => {
|
|
206
|
+
sareq
|
|
207
|
+
.on("response", (res) => {
|
|
208
|
+
if (res.statusCode !== 200) {
|
|
209
|
+
const parsedError = errorCallback(res);
|
|
210
|
+
reject(parsedError);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
.pipe(options.stream)
|
|
215
|
+
.on("error", (error) => {
|
|
216
|
+
const parsedError = errorCallback(error);
|
|
217
|
+
reject(parsedError);
|
|
218
|
+
})
|
|
219
|
+
.on("finish", () => {
|
|
220
|
+
const retResponse = {
|
|
221
|
+
status: 200,
|
|
222
|
+
header: undefined,
|
|
223
|
+
body: undefined,
|
|
224
|
+
text: undefined,
|
|
225
|
+
};
|
|
226
|
+
resolve(retResponse);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
// console.log("%s %s %s", url, options.method, queryStr);
|
|
231
|
+
/**
|
|
232
|
+
* Note:
|
|
233
|
+
* Javascript's fetch returns status.OK if error is between 200-299 inclusive, and doesn't reject in this case.
|
|
234
|
+
* Fetch only rejects if there's some network issue (permissions issue or similar)
|
|
235
|
+
* Superagent rejects network issues, and errors outside the range of 200-299. We are currently using
|
|
236
|
+
* superagent, but may eventually switch to JavaScript's fetch library.
|
|
237
|
+
*/
|
|
238
|
+
try {
|
|
239
|
+
const response = await sareq;
|
|
240
|
+
const retResponse = {
|
|
241
|
+
body: response.body,
|
|
242
|
+
text: response.text,
|
|
243
|
+
header: response.header,
|
|
244
|
+
status: response.status,
|
|
245
|
+
};
|
|
246
|
+
return retResponse;
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
const parsedError = errorCallback(error);
|
|
250
|
+
throw parsedError;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
exports.request = request;
|
|
254
|
+
/**
|
|
255
|
+
* fetch json from HTTP request
|
|
256
|
+
* @param url server URL to address the request
|
|
257
|
+
* @internal
|
|
258
|
+
*/
|
|
259
|
+
async function getJson(url) {
|
|
260
|
+
const options = {
|
|
261
|
+
method: "GET",
|
|
262
|
+
responseType: "json",
|
|
263
|
+
};
|
|
264
|
+
const data = await request(url, options);
|
|
265
|
+
return data.body;
|
|
266
|
+
}
|
|
267
|
+
exports.getJson = getJson;
|
|
268
|
+
//# sourceMappingURL=Request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Request.js","sourceRoot":"","sources":["../../../src/backend/Request.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 iTwinServiceClients\r\n */\r\nimport * as deepAssign from \"deep-assign\";\r\nimport * as _ from \"lodash\";\r\nimport * as https from \"https\";\r\nimport { IStringifyOptions, stringify } from \"qs\";\r\nimport * as sarequest from \"superagent\";\r\nimport { BentleyError, GetMetaDataFunction, HttpStatus, Logger, LogLevel } from \"@itwin/core-bentley\";\r\n\r\nconst loggerCategory: string = \"core-mobile-backend.Request\";\r\n\r\n/** @internal */\r\nexport const requestIdHeaderName = \"X-Correlation-Id\";\r\n\r\n/** Typical option to query REST API. Note that services may not quite support these fields,\r\n * and the interface is only provided as a hint.\r\n * @internal\r\n */\r\nexport interface RequestQueryOptions {\r\n /**\r\n * Select string used by the query (use the mapped EC property names, and not TypeScript property names)\r\n * Example: \"Name,Size,Description\"\r\n */\r\n $select?: string;\r\n\r\n /**\r\n * Filter string used by the query (use the mapped EC property names, and not TypeScript property names)\r\n * Example: \"Name like '*.pdf' and Size lt 1000\"\r\n */\r\n $filter?: string;\r\n\r\n /** Sets the limit on the number of entries to be returned by the query */\r\n $top?: number;\r\n\r\n /** Sets the number of entries to be skipped */\r\n $skip?: number;\r\n\r\n /**\r\n * Orders the return values (use the mapped EC property names, and not TypeScript property names)\r\n * Example: \"Size desc\"\r\n */\r\n $orderby?: string;\r\n\r\n /**\r\n * Sets the limit on the number of entries to be returned by a single response.\r\n * Can be used with a Top option. For example if Top is set to 1000 and PageSize\r\n * is set to 100 then 10 requests will be performed to get result.\r\n */\r\n $pageSize?: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface RequestQueryStringifyOptions {\r\n delimiter?: string;\r\n encode?: boolean;\r\n}\r\n\r\n/** Option to control the time outs\r\n * Use a short response timeout to detect unresponsive networks quickly, and a long deadline to give time for downloads on slow,\r\n * but reliable, networks. Note that both of these timers limit how long uploads of attached files are allowed to take. Use long\r\n * timeouts if you're uploading files.\r\n * @internal\r\n */\r\nexport interface RequestTimeoutOptions {\r\n /** Sets a deadline (in milliseconds) for the entire request (including all uploads, redirects, server processing time) to complete.\r\n * If the response isn't fully downloaded within that time, the request will be aborted\r\n */\r\n deadline?: number;\r\n\r\n /** Sets maximum time (in milliseconds) to wait for the first byte to arrive from the server, but it does not limit how long the entire\r\n * download can take. Response timeout should be at least few seconds longer than just the time it takes the server to respond, because\r\n * it also includes time to make DNS lookup, TCP/IP and TLS connections, and time to upload request data.\r\n */\r\n response?: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface RequestOptions {\r\n method: string;\r\n headers?: any; // {Mas-App-Guid, Mas-UUid, User-Agent}\r\n body?: any;\r\n qs?: any | RequestQueryOptions;\r\n responseType?: string;\r\n timeout?: RequestTimeoutOptions; // Optional timeouts. If unspecified, an arbitrary default is setup.\r\n stream?: any; // Optional stream to read the response to/from (only for NodeJs applications)\r\n readStream?: any; // Optional stream to read input from (only for NodeJs applications)\r\n buffer?: any;\r\n parser?: any;\r\n accept?: string;\r\n redirects?: number;\r\n errorCallback?: (response: any) => ResponseError;\r\n retryCallback?: (error: any, response: any) => boolean;\r\n progressCallback?: ProgressCallback;\r\n agent?: https.Agent;\r\n retries?: number;\r\n useCorsProxy?: boolean;\r\n}\r\n\r\n/** Response object if the request was successful. Note that the status within the range of 200-299 are considered as a success.\r\n * @internal\r\n */\r\nexport interface Response {\r\n body: any; // Parsed body of response\r\n text: string | undefined; // Returned for responseType:text\r\n header: any; // Parsed headers of response\r\n status: number; // Status code of response\r\n}\r\n\r\n/** @internal */\r\nexport interface ProgressInfo {\r\n percent?: number;\r\n total?: number;\r\n loaded: number;\r\n}\r\n\r\n/** @internal */\r\nexport type ProgressCallback = (progress: ProgressInfo) => void;\r\n\r\n/** Error object that's thrown/rejected if the Request fails due to a network error, or if the status is *not* in the range of 200-299 (inclusive)\r\n * @internal\r\n */\r\nexport class ResponseError extends BentleyError {\r\n protected _data?: any;\r\n public status?: number;\r\n public description?: string;\r\n public constructor(errorNumber: number | HttpStatus, message?: string, getMetaData?: GetMetaDataFunction) {\r\n super(errorNumber, message, getMetaData);\r\n }\r\n\r\n /**\r\n * Parses error from server's response\r\n * @param response Http response from the server.\r\n * @returns Parsed error.\r\n * @internal\r\n */\r\n public static parse(response: any, log = true): ResponseError {\r\n const error = new ResponseError(ResponseError.parseHttpStatus(response.statusType));\r\n if (!response) {\r\n error.message = \"Couldn't get response object.\";\r\n return error;\r\n }\r\n\r\n if (response.response) {\r\n if (response.response.error) {\r\n error.name = response.response.error.name || error.name;\r\n error.description = response.response.error.message;\r\n }\r\n if (response.response.res) {\r\n error.message = response.response.res.statusMessage;\r\n }\r\n if (response.response.body && Object.keys(response.response.body).length > 0) {\r\n error._data = {};\r\n deepAssign(error._data, response.response.body);\r\n } else {\r\n error._data = response.response.text;\r\n }\r\n }\r\n\r\n error.status = response.status || response.statusCode;\r\n error.name = response.code || response.name || error.name;\r\n error.message = error.message || response.message || response.statusMessage;\r\n\r\n if (log)\r\n error.log();\r\n\r\n return error;\r\n }\r\n\r\n /**\r\n * Decides whether request should be retried or not\r\n * @param error Error returned by request\r\n * @param response Response returned by request\r\n * @internal\r\n */\r\n public static shouldRetry(error: any, response: any): boolean {\r\n if (error !== undefined && error !== null) {\r\n if ((error.status === undefined || error.status === null) && (error.res === undefined || error.res === null)) {\r\n return true;\r\n }\r\n }\r\n return (response !== undefined && response.statusType === HttpStatus.ServerError);\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n public static parseHttpStatus(statusType: number): HttpStatus {\r\n switch (statusType) {\r\n case 1:\r\n return HttpStatus.Info;\r\n case 2:\r\n return HttpStatus.Success;\r\n case 3:\r\n return HttpStatus.Redirection;\r\n case 4:\r\n return HttpStatus.ClientError;\r\n case 5:\r\n return HttpStatus.ServerError;\r\n default:\r\n return HttpStatus.Success;\r\n }\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n public logMessage(): string {\r\n return `${this.status} ${this.name}: ${this.message}`;\r\n }\r\n\r\n /**\r\n * Logs this error\r\n * @internal\r\n */\r\n public log(): void {\r\n Logger.logError(loggerCategory, this.logMessage(), () => this.getMetaData());\r\n }\r\n}\r\n\r\nconst logResponse = (req: sarequest.SuperAgentRequest, startTime: number) => (res: sarequest.Response) => {\r\n const elapsed = new Date().getTime() - startTime;\r\n const elapsedTime = `${elapsed}ms`;\r\n Logger.logTrace(loggerCategory, `${req.method.toUpperCase()} ${res.status} ${req.url} (${elapsedTime})`);\r\n};\r\n\r\n// eslint-disable-next-line @typescript-eslint/promise-function-async\r\nconst logRequest = (req: sarequest.SuperAgentRequest): sarequest.SuperAgentRequest => {\r\n const startTime = new Date().getTime();\r\n return req.on(\"response\", logResponse(req, startTime));\r\n};\r\n\r\n/** Wrapper around making HTTP requests with the specific options.\r\n *\r\n * Usable in both a browser and node based environment.\r\n *\r\n * @param url Server URL to address the request\r\n * @param options Options to pass to the request\r\n * @returns Resolves to the response from the server\r\n * @throws ResponseError if the request fails due to network issues, or if the returned status is *outside* the range of 200-299 (inclusive)\r\n * @internal\r\n */\r\nexport async function request(url: string, options: RequestOptions): Promise<Response> {\r\n let sareq: sarequest.SuperAgentRequest = sarequest(options.method, url);\r\n if (options.retries)\r\n sareq = sareq.retry(options.retries, options.retryCallback);\r\n\r\n if (Logger.isEnabled(loggerCategory, LogLevel.Trace))\r\n sareq = sareq.use(logRequest);\r\n\r\n if (options.headers)\r\n sareq = sareq.set(options.headers);\r\n\r\n let queryStr: string = \"\";\r\n let fullUrl: string = \"\";\r\n if (options.qs && Object.keys(options.qs).length > 0) {\r\n const stringifyOptions: IStringifyOptions = { delimiter: \"&\", encode: false };\r\n queryStr = stringify(options.qs, stringifyOptions);\r\n sareq = sareq.query(queryStr);\r\n fullUrl = `${url}?${queryStr}`;\r\n } else {\r\n fullUrl = url;\r\n }\r\n\r\n Logger.logInfo(loggerCategory, fullUrl);\r\n\r\n if (options.accept)\r\n sareq = sareq.accept(options.accept);\r\n\r\n if (options.body)\r\n sareq = sareq.send(options.body);\r\n\r\n if (options.timeout)\r\n sareq = sareq.timeout(options.timeout);\r\n\r\n if (options.responseType)\r\n sareq = sareq.responseType(options.responseType);\r\n\r\n if (options.redirects)\r\n sareq = sareq.redirects(options.redirects);\r\n else\r\n sareq = sareq.redirects(0);\r\n\r\n if (options.buffer)\r\n sareq = sareq.buffer(options.buffer);\r\n\r\n if (options.parser)\r\n sareq = sareq.parse(options.parser);\r\n\r\n /** Default to any globally supplied proxy, unless an agent is specified in this call */\r\n if (options.agent)\r\n sareq = sareq.agent(options.agent);\r\n\r\n if (options.progressCallback) {\r\n sareq = sareq.on(\"progress\", (event: sarequest.ProgressEvent) => {\r\n if (event) {\r\n options.progressCallback!({\r\n loaded: event.loaded,\r\n total: event.total,\r\n percent: event.percent,\r\n });\r\n }\r\n });\r\n }\r\n\r\n const errorCallback = options.errorCallback ? options.errorCallback : ResponseError.parse;\r\n\r\n if (options.readStream) {\r\n if (typeof window !== \"undefined\")\r\n throw new Error(\"This option is not supported on browsers\");\r\n\r\n return new Promise<Response>((resolve, reject) => {\r\n sareq = sareq.type(\"blob\");\r\n options\r\n .readStream\r\n .pipe(sareq)\r\n .on(\"error\", (error: any) => {\r\n const parsedError = errorCallback(error);\r\n reject(parsedError);\r\n })\r\n .on(\"end\", () => {\r\n const retResponse: Response = {\r\n status: 201,\r\n header: undefined,\r\n body: undefined,\r\n text: undefined,\r\n };\r\n resolve(retResponse);\r\n });\r\n });\r\n }\r\n\r\n if (options.stream) {\r\n if (typeof window !== \"undefined\")\r\n throw new Error(\"This option is not supported on browsers\");\r\n\r\n return new Promise<Response>((resolve, reject) => {\r\n sareq\r\n .on(\"response\", (res: any) => {\r\n if (res.statusCode !== 200) {\r\n const parsedError = errorCallback(res);\r\n reject(parsedError);\r\n return;\r\n }\r\n })\r\n .pipe(options.stream)\r\n .on(\"error\", (error: any) => {\r\n const parsedError = errorCallback(error);\r\n reject(parsedError);\r\n })\r\n .on(\"finish\", () => {\r\n const retResponse: Response = {\r\n status: 200,\r\n header: undefined,\r\n body: undefined,\r\n text: undefined,\r\n };\r\n resolve(retResponse);\r\n });\r\n });\r\n }\r\n\r\n // console.log(\"%s %s %s\", url, options.method, queryStr);\r\n\r\n /**\r\n * Note:\r\n * Javascript's fetch returns status.OK if error is between 200-299 inclusive, and doesn't reject in this case.\r\n * Fetch only rejects if there's some network issue (permissions issue or similar)\r\n * Superagent rejects network issues, and errors outside the range of 200-299. We are currently using\r\n * superagent, but may eventually switch to JavaScript's fetch library.\r\n */\r\n try {\r\n const response = await sareq;\r\n const retResponse: Response = {\r\n body: response.body,\r\n text: response.text,\r\n header: response.header,\r\n status: response.status,\r\n };\r\n return retResponse;\r\n } catch (error) {\r\n const parsedError = errorCallback(error);\r\n throw parsedError;\r\n }\r\n}\r\n\r\n/**\r\n * fetch json from HTTP request\r\n * @param url server URL to address the request\r\n * @internal\r\n */\r\nexport async function getJson(url: string): Promise<any> {\r\n const options: RequestOptions = {\r\n method: \"GET\",\r\n responseType: \"json\",\r\n };\r\n const data = await request(url, options);\r\n return data.body;\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itwin/core-mobile",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "iTwin.js MobileHost and MobileApp",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "https://github.com/
|
|
11
|
+
"url": "https://github.com/iTwin/itwinjs-core/tree/master/core/core-mobile"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"Bentley",
|
|
@@ -21,32 +21,39 @@
|
|
|
21
21
|
"url": "http://www.bentley.com"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@itwin/core-
|
|
25
|
-
"@itwin/core-
|
|
26
|
-
"@itwin/core-common": "^3.0.0
|
|
27
|
-
"@itwin/core-frontend": "^3.0.0
|
|
28
|
-
"@
|
|
29
|
-
|
|
24
|
+
"@itwin/core-backend": "^3.0.0",
|
|
25
|
+
"@itwin/core-bentley": "^3.0.0",
|
|
26
|
+
"@itwin/core-common": "^3.0.0",
|
|
27
|
+
"@itwin/core-frontend": "^3.0.0",
|
|
28
|
+
"@itwin/presentation-common": "^3.0.0"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"deep-assign": "^2.0.0",
|
|
32
|
+
"lodash": "^4.17.10",
|
|
30
33
|
"js-base64": "^3.6.1",
|
|
34
|
+
"qs": "^6.5.1",
|
|
35
|
+
"superagent": "^7.0.1",
|
|
31
36
|
"ws": "^7.5.3"
|
|
32
37
|
},
|
|
33
38
|
"devDependencies": {
|
|
34
|
-
"@itwin/
|
|
35
|
-
"@itwin/
|
|
36
|
-
"@itwin/
|
|
37
|
-
"@
|
|
38
|
-
"@itwin/core-
|
|
39
|
-
"@itwin/
|
|
40
|
-
"@itwin/
|
|
41
|
-
"@itwin/presentation-common": "3.0.0-dev.98",
|
|
39
|
+
"@itwin/build-tools": "3.0.0",
|
|
40
|
+
"@itwin/core-backend": "3.0.0",
|
|
41
|
+
"@itwin/core-bentley": "3.0.0",
|
|
42
|
+
"@itwin/core-common": "3.0.0",
|
|
43
|
+
"@itwin/core-frontend": "3.0.0",
|
|
44
|
+
"@itwin/eslint-plugin": "3.0.0",
|
|
45
|
+
"@itwin/presentation-common": "3.0.0",
|
|
42
46
|
"@types/chai": "^4.1.4",
|
|
47
|
+
"@types/deep-assign": "^0.1.0",
|
|
43
48
|
"@types/fs-extra": "^4.0.7",
|
|
49
|
+
"@types/lodash": "^4.14.0",
|
|
44
50
|
"@types/mocha": "^8.2.2",
|
|
45
51
|
"@types/node": "14.14.31",
|
|
52
|
+
"@types/qs": "^6.5.0",
|
|
53
|
+
"@types/superagent": "^4.1.14",
|
|
46
54
|
"@types/ws": "^6.0.4",
|
|
47
55
|
"chai": "^4.1.2",
|
|
48
56
|
"chai-as-promised": "^7",
|
|
49
|
-
"cpx": "^1.5.0",
|
|
50
57
|
"dotenv": "^10.0.0",
|
|
51
58
|
"dotenv-expand": "^5.1.0",
|
|
52
59
|
"eslint": "^7.11.0",
|
|
@@ -72,5 +79,6 @@
|
|
|
72
79
|
"lint": "eslint -f visualstudio \"./src/**/*.ts\" 1>&2",
|
|
73
80
|
"test": "",
|
|
74
81
|
"cover": ""
|
|
75
|
-
}
|
|
82
|
+
},
|
|
83
|
+
"readme": "# @itwin/core-mobile\r\n\r\nCopyright © Bentley Systems, Incorporated. All rights reserved. See LICENSE.md for license terms and full copyright notice. See LICENSE.md in the project root for license terms and full copyright notice.\r\n\r\n## Description\r\n\r\nThe __@itwin/core-electron__ package contains the electron utilities to write an iTwin.js application based on Electron.\r\n\r\n## Documentation\r\n\r\nSee the [iTwin.js](https://www.itwinjs.org) documentation for more information.\r\n"
|
|
76
84
|
}
|