@alfalab/bridge-to-native 1.4.1-beta.52a0437 → 1.4.1-beta.720f0f8
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/client/bridge-to-native.d.ts +4 -3
- package/client/bridge-to-native.js +4 -4
- package/client/services-and-utils/external-links-service.d.ts +3 -3
- package/client/services-and-utils/external-links-service.js +38 -8
- package/client/services-and-utils/native-log-service.d.ts +27 -0
- package/client/services-and-utils/native-log-service.js +50 -0
- package/client/services-and-utils/native-navigation-and-title-service.d.ts +3 -3
- package/client/services-and-utils/native-navigation-and-title-service.js +4 -5
- package/client/services-and-utils/native-params-service.d.ts +3 -1
- package/client/services-and-utils/native-params-service.js +10 -3
- package/client/types.d.ts +4 -5
- package/package.json +1 -1
- package/query-and-headers-keys.js +2 -0
- package/server/is-webview-env.js +11 -13
- package/server/prepare-native-app-details-for-client.d.ts +2 -2
- package/server/prepare-native-app-details-for-client.js +5 -3
- package/server/utils.js +9 -0
- package/types.d.ts +6 -0
- package/client/services-and-utils/native-execute-service.d.ts +0 -7
- package/client/services-and-utils/native-execute-service.js +0 -17
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import { type
|
|
2
|
+
import { type NoopOptions } from '../types';
|
|
3
|
+
import { type BrowserHistoryApiWrappers, type HistoryPushStateParams, type HistoryReplaceStateParams, type LocationAssignParam, type LogError, type NativeFeatureKey, type PdfType } from './types';
|
|
3
4
|
/**
|
|
4
5
|
* Сервис, предоставляет методы для WA, работающего внутри NA.
|
|
5
6
|
*/
|
|
@@ -21,7 +22,7 @@ export declare class BridgeToNative {
|
|
|
21
22
|
noop?: NoopOptions;
|
|
22
23
|
} | undefined);
|
|
23
24
|
private nativeParamsService;
|
|
24
|
-
private
|
|
25
|
+
private nativeLogService;
|
|
25
26
|
private externalLinksService;
|
|
26
27
|
private nativeNavigationAndTitleService;
|
|
27
28
|
/**
|
|
@@ -35,7 +36,7 @@ export declare class BridgeToNative {
|
|
|
35
36
|
/**
|
|
36
37
|
* Платформа, в окружении которой работает NA и WA.
|
|
37
38
|
*/
|
|
38
|
-
get environment(): import("
|
|
39
|
+
get environment(): import("../types").Environment;
|
|
39
40
|
/**
|
|
40
41
|
* Индикатор проблемы чтения данных о NA. Если `true`, используются умолчания,
|
|
41
42
|
* возможно ошибочные (например, версия будет `0.0.0`).
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.BridgeToNative = void 0;
|
|
5
5
|
const external_links_service_1 = require("./services-and-utils/external-links-service");
|
|
6
|
-
const
|
|
6
|
+
const native_log_service_1 = require("./services-and-utils/native-log-service");
|
|
7
7
|
const native_navigation_and_title_service_1 = require("./services-and-utils/native-navigation-and-title-service");
|
|
8
8
|
const native_params_service_1 = require("./services-and-utils/native-params-service");
|
|
9
9
|
/**
|
|
@@ -24,9 +24,9 @@ class BridgeToNative {
|
|
|
24
24
|
var _a, _b, _c, _d, _e, _f;
|
|
25
25
|
this.options = options;
|
|
26
26
|
this.nativeParamsService = new native_params_service_1.NativeParamsService((_a = this.options) === null || _a === void 0 ? void 0 : _a.noop, (_b = this.options) === null || _b === void 0 ? void 0 : _b.logError);
|
|
27
|
-
this.
|
|
28
|
-
this.externalLinksService = new external_links_service_1.ExternalLinksService(this.nativeParamsService, this.
|
|
29
|
-
this.nativeNavigationAndTitleService = new native_navigation_and_title_service_1.NativeNavigationAndTitleService(this.nativeParamsService, this.
|
|
27
|
+
this.nativeLogService = new native_log_service_1.NativeLogService(this.nativeParamsService.environment, this.nativeParamsService.appVersion, (_d = (_c = this.options) === null || _c === void 0 ? void 0 : _c.noop) === null || _d === void 0 ? void 0 : _d.enabled);
|
|
28
|
+
this.externalLinksService = new external_links_service_1.ExternalLinksService(this.nativeParamsService, this.nativeLogService);
|
|
29
|
+
this.nativeNavigationAndTitleService = new native_navigation_and_title_service_1.NativeNavigationAndTitleService(this.nativeParamsService, this.nativeLogService, (_e = this.options) === null || _e === void 0 ? void 0 : _e.browserHistoryApiWrappers, (_f = this.options) === null || _f === void 0 ? void 0 : _f.logError);
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Схема NA.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type PdfType } from '../types';
|
|
2
|
-
import { type
|
|
2
|
+
import { type NativeLogService } from './native-log-service';
|
|
3
3
|
import { type NativeParamsService } from './native-params-service';
|
|
4
4
|
/**
|
|
5
5
|
* Сервис, предоставляющий методы для открытия внешних для текущего WA экранов
|
|
@@ -7,9 +7,9 @@ import { type NativeParamsService } from './native-params-service';
|
|
|
7
7
|
*/
|
|
8
8
|
export declare class ExternalLinksService {
|
|
9
9
|
private nativeParamsService;
|
|
10
|
-
private
|
|
10
|
+
private nativeLogService;
|
|
11
11
|
private navigationByNativeAppInProgress;
|
|
12
|
-
constructor(nativeParamsService: NativeParamsService,
|
|
12
|
+
constructor(nativeParamsService: NativeParamsService, nativeLogService: NativeLogService);
|
|
13
13
|
handleNativeDeeplink(deeplink: string, closeWebviewBeforeCallNativeDeeplinkHandler?: boolean): void;
|
|
14
14
|
getHrefToOpenInBrowser(link: string): string;
|
|
15
15
|
openInBrowser(link: string): void;
|
|
@@ -12,9 +12,9 @@ const QUERY_OPEN_IN_BROWSER_VALUE = 'true';
|
|
|
12
12
|
* и связанных с этим действий.
|
|
13
13
|
*/
|
|
14
14
|
class ExternalLinksService {
|
|
15
|
-
constructor(nativeParamsService,
|
|
15
|
+
constructor(nativeParamsService, nativeLogService) {
|
|
16
16
|
this.nativeParamsService = nativeParamsService;
|
|
17
|
-
this.
|
|
17
|
+
this.nativeLogService = nativeLogService;
|
|
18
18
|
this.navigationByNativeAppInProgress = false;
|
|
19
19
|
}
|
|
20
20
|
handleNativeDeeplink(deeplink, closeWebviewBeforeCallNativeDeeplinkHandler = false) {
|
|
@@ -28,18 +28,37 @@ class ExternalLinksService {
|
|
|
28
28
|
: originalNativeUrl;
|
|
29
29
|
if (closeWebviewBeforeCallNativeDeeplinkHandler &&
|
|
30
30
|
this.nativeParamsService.canUseNativeFeature('savedBackStack')) {
|
|
31
|
-
this.
|
|
31
|
+
this.nativeLogService.execute('closeWebview', () => (0, utils_1.closeWebviewUtil)());
|
|
32
32
|
// Проверено, ОС получает диплинк и передаёт его NA, не смотря на то,
|
|
33
33
|
// что это происходит в следующей макрозадаче после команды на закрытие WV.
|
|
34
|
-
this.
|
|
34
|
+
this.nativeLogService.execute('nativeDeeplink', () => {
|
|
35
35
|
setTimeout(() => window.location.replace(preparedNativeUrl), 0);
|
|
36
|
-
}, { deeplink: preparedNativeUrl });
|
|
36
|
+
}, { payload: { deeplink: preparedNativeUrl } });
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
let featureContext = null;
|
|
40
|
+
const { fromVersion } = constants_1.NATIVE_FEATURES_FROM_VERSION[this.nativeParamsService.environment].savedBackStack;
|
|
41
|
+
if (this.nativeParamsService.environment === 'android' &&
|
|
42
|
+
!this.nativeParamsService.isCurrentVersionHigherOrEqual(fromVersion)) {
|
|
43
|
+
featureContext = {
|
|
44
|
+
feature: 'savedBackStack',
|
|
45
|
+
fallbackReason: 'Открытие нового webview в Android приведет к закрытию текущего',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
this.nativeLogService.execute('nativeDeeplink', () => this.navigateByNativeApp(preparedNativeUrl), {
|
|
49
|
+
payload: { deeplink: preparedNativeUrl },
|
|
50
|
+
featureContext: featureContext !== null && featureContext !== void 0 ? featureContext : null,
|
|
51
|
+
});
|
|
40
52
|
}
|
|
41
53
|
getHrefToOpenInBrowser(link) {
|
|
42
54
|
if (!this.nativeParamsService.canUseNativeFeature('linksInBrowser')) {
|
|
55
|
+
if ((this, this.nativeParamsService.environment === 'android')) {
|
|
56
|
+
this.nativeLogService.logFeatureFallback({
|
|
57
|
+
feature: 'linksInBrowser',
|
|
58
|
+
fallbackReason: 'Открытие в браузере технически недоступно, будет открыто в новом webview',
|
|
59
|
+
payload: { link },
|
|
60
|
+
});
|
|
61
|
+
}
|
|
43
62
|
return `${this.nativeParamsService.appId}://webFeature?type=recommendation&url=${encodeURIComponent(link)}`;
|
|
44
63
|
}
|
|
45
64
|
const url = new URL(link);
|
|
@@ -51,12 +70,21 @@ class ExternalLinksService {
|
|
|
51
70
|
return;
|
|
52
71
|
}
|
|
53
72
|
if (!this.nativeParamsService.canUseNativeFeature('linksInBrowser')) {
|
|
73
|
+
if ((this, this.nativeParamsService.environment === 'android')) {
|
|
74
|
+
this.nativeLogService.logFeatureFallback({
|
|
75
|
+
feature: 'linksInBrowser',
|
|
76
|
+
fallbackReason: 'Открытие в браузере технически недоступно, будет открыто в новом webview',
|
|
77
|
+
payload: { link },
|
|
78
|
+
});
|
|
79
|
+
}
|
|
54
80
|
this.openInNewWebview(link);
|
|
55
81
|
return;
|
|
56
82
|
}
|
|
57
83
|
const url = new URL(link);
|
|
58
84
|
url.searchParams.append(QUERY_OPEN_IN_BROWSER_KEY, QUERY_OPEN_IN_BROWSER_VALUE);
|
|
59
|
-
this.
|
|
85
|
+
this.nativeLogService.execute('openInBrowser', () => this.navigateByNativeApp(url.href), {
|
|
86
|
+
payload: { url: url.href },
|
|
87
|
+
});
|
|
60
88
|
}
|
|
61
89
|
openInNewWebview(link, nativeTitle = '', closeCurrentWebview = false) {
|
|
62
90
|
const url = new URL(link);
|
|
@@ -84,7 +112,9 @@ class ExternalLinksService {
|
|
|
84
112
|
this.nativeParamsService.environment === 'ios'
|
|
85
113
|
? (0, utils_1.appendFromCurrentQueryParamForIos)(replaceUrl)
|
|
86
114
|
: replaceUrl;
|
|
87
|
-
this.
|
|
115
|
+
this.nativeLogService.execute('openPdf ', () => this.navigateByNativeApp(replaceUrl), {
|
|
116
|
+
payload: { replaceUrl },
|
|
117
|
+
});
|
|
88
118
|
}
|
|
89
119
|
navigateByNativeApp(url) {
|
|
90
120
|
this.navigationByNativeAppInProgress = true;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Environment, type NoopOptions } from '../../types';
|
|
2
|
+
import { type NativeFeatureContext, type NativeFeatureKey } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Обёртка для выполнения нативных вызовов с noop-режимом и логированием версионных фич
|
|
5
|
+
*/
|
|
6
|
+
export declare class NativeLogService {
|
|
7
|
+
private environment;
|
|
8
|
+
private appVersion;
|
|
9
|
+
private isNoop?;
|
|
10
|
+
constructor(environment: Environment, appVersion: string, isNoop?: NoopOptions["enabled"] | undefined);
|
|
11
|
+
/**
|
|
12
|
+
* Метод для вывода в консоль информации о недоступности фич,
|
|
13
|
+
* перечисленных в `NATIVE_FEATURES_FROM_VERSION` src/client/constants.ts
|
|
14
|
+
*/
|
|
15
|
+
logFeatureFallback(params: {
|
|
16
|
+
feature: NativeFeatureKey;
|
|
17
|
+
fallbackReason: string;
|
|
18
|
+
payload?: unknown;
|
|
19
|
+
}): void;
|
|
20
|
+
/**
|
|
21
|
+
* Метод подменяющий нативный вызов и логирующий его, для работы в noop режиме
|
|
22
|
+
*/
|
|
23
|
+
execute(action: string, fn: () => void, meta?: {
|
|
24
|
+
featureContext?: NativeFeatureContext | null;
|
|
25
|
+
payload?: unknown;
|
|
26
|
+
}): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NativeLogService = void 0;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
/**
|
|
6
|
+
* Обёртка для выполнения нативных вызовов с noop-режимом и логированием версионных фич
|
|
7
|
+
*/
|
|
8
|
+
class NativeLogService {
|
|
9
|
+
constructor(environment, appVersion, isNoop) {
|
|
10
|
+
this.environment = environment;
|
|
11
|
+
this.appVersion = appVersion;
|
|
12
|
+
this.isNoop = isNoop;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Метод для вывода в консоль информации о недоступности фич,
|
|
16
|
+
* перечисленных в `NATIVE_FEATURES_FROM_VERSION` src/client/constants.ts
|
|
17
|
+
*/
|
|
18
|
+
logFeatureFallback(params) {
|
|
19
|
+
if (!this.isNoop)
|
|
20
|
+
return;
|
|
21
|
+
const { fromVersion } = constants_1.NATIVE_FEATURES_FROM_VERSION[this.environment][params.feature];
|
|
22
|
+
console.info([
|
|
23
|
+
`[B2N noop][${this.environment}][v${this.appVersion}]`,
|
|
24
|
+
`Feature: ${params.feature}`,
|
|
25
|
+
`${params.fallbackReason}`,
|
|
26
|
+
`Будет исправлено в версии: ${fromVersion}`,
|
|
27
|
+
].join('\n'), params.payload);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Метод подменяющий нативный вызов и логирующий его, для работы в noop режиме
|
|
31
|
+
*/
|
|
32
|
+
execute(action, fn, meta) {
|
|
33
|
+
var _a;
|
|
34
|
+
if (this.isNoop) {
|
|
35
|
+
if (meta === null || meta === void 0 ? void 0 : meta.featureContext) {
|
|
36
|
+
this.logFeatureFallback({
|
|
37
|
+
feature: meta.featureContext.feature,
|
|
38
|
+
fallbackReason: (_a = meta.featureContext.fallbackReason) !== null && _a !== void 0 ? _a : '',
|
|
39
|
+
payload: meta.payload,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.info(`[B2N noop][${this.environment}][v${this.appVersion}] ${action}`, ...((meta === null || meta === void 0 ? void 0 : meta.payload) !== undefined ? [meta.payload] : []));
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
fn();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.NativeLogService = NativeLogService;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type BrowserHistoryApiWrappers, type HistoryPushStateParams, type LocationAssignParam, type LogError } from '../types';
|
|
2
|
-
import { type
|
|
2
|
+
import { type NativeLogService } from './native-log-service';
|
|
3
3
|
import { type NativeParamsService } from './native-params-service';
|
|
4
4
|
/**
|
|
5
5
|
* Сервис, отвечающий за взаимодействие WA с WV компонентами NA —
|
|
@@ -10,7 +10,7 @@ import { type NativeParamsService } from './native-params-service';
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class NativeNavigationAndTitleService {
|
|
12
12
|
private nativeParamsService;
|
|
13
|
-
private
|
|
13
|
+
private nativeLogService;
|
|
14
14
|
private browserHistoryApiWrappers?;
|
|
15
15
|
private logError?;
|
|
16
16
|
private lastSetPageSettingsParams;
|
|
@@ -18,7 +18,7 @@ export declare class NativeNavigationAndTitleService {
|
|
|
18
18
|
private numOfBackSteps;
|
|
19
19
|
private isGoBackLocked;
|
|
20
20
|
private isNavigateServerSideLocked;
|
|
21
|
-
constructor(nativeParamsService: NativeParamsService,
|
|
21
|
+
constructor(nativeParamsService: NativeParamsService, nativeLogService: NativeLogService, browserHistoryApiWrappers?: BrowserHistoryApiWrappers | undefined, logError?: LogError | undefined);
|
|
22
22
|
closeWebview(): void;
|
|
23
23
|
goBack(): void;
|
|
24
24
|
goBackAFewSteps(stepsNumber: number, autoCloseWebview?: boolean): void;
|
|
@@ -13,9 +13,9 @@ const NativeHistoryStackStub = 0;
|
|
|
13
13
|
* см. в документе {@link ./NAVIGATION_SCENARIOS.md}.
|
|
14
14
|
*/
|
|
15
15
|
class NativeNavigationAndTitleService {
|
|
16
|
-
constructor(nativeParamsService,
|
|
16
|
+
constructor(nativeParamsService, nativeLogService, browserHistoryApiWrappers, logError) {
|
|
17
17
|
this.nativeParamsService = nativeParamsService;
|
|
18
|
-
this.
|
|
18
|
+
this.nativeLogService = nativeLogService;
|
|
19
19
|
this.browserHistoryApiWrappers = browserHistoryApiWrappers;
|
|
20
20
|
this.logError = logError;
|
|
21
21
|
// Здесь сохраняются параметры, которые в последний раз были отправлены
|
|
@@ -272,13 +272,12 @@ class NativeNavigationAndTitleService {
|
|
|
272
272
|
* с `nativeHistoryStack`.
|
|
273
273
|
*/
|
|
274
274
|
syncHistoryWithNative() {
|
|
275
|
-
var _a;
|
|
276
275
|
const { pageId, pageTitle } = this.getNativePageIdAndTitle();
|
|
277
276
|
if (this.nativeParamsService.environment === 'android') {
|
|
278
277
|
const narrowedPageId = pageId !== null && pageId !== void 0 ? pageId : 1;
|
|
279
278
|
const paramsToSend = JSON.stringify({ pageId: narrowedPageId, pageTitle });
|
|
280
279
|
if (this.lastSetPageSettingsParams !== paramsToSend) {
|
|
281
|
-
this.
|
|
280
|
+
this.nativeLogService.execute('syncHistoryWithNative', () => { var _a; return (_a = this.nativeParamsService.AndroidBridge) === null || _a === void 0 ? void 0 : _a.setPageSettings(paramsToSend); }, { payload: paramsToSend });
|
|
282
281
|
this.lastSetPageSettingsParams = paramsToSend;
|
|
283
282
|
}
|
|
284
283
|
}
|
|
@@ -287,7 +286,7 @@ class NativeNavigationAndTitleService {
|
|
|
287
286
|
const pageIdStr = pageId ? `&pageId=${pageId}` : '';
|
|
288
287
|
const paramsToSend = `ios:setPageSettings/${pageTitleStr + pageIdStr}`;
|
|
289
288
|
if (this.lastSetPageSettingsParams !== paramsToSend) {
|
|
290
|
-
|
|
289
|
+
this.nativeLogService.execute('syncHistoryWithNative', () => window.location.replace(paramsToSend), { payload: paramsToSend });
|
|
291
290
|
this.lastSetPageSettingsParams = paramsToSend;
|
|
292
291
|
}
|
|
293
292
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type Environment, type
|
|
1
|
+
import { type Environment, type NoopOptions } from '../../types';
|
|
2
|
+
import { type LogError, type NativeFeatureKey, type Theme } from '../types';
|
|
2
3
|
/**
|
|
3
4
|
* Сервис, аккумулирующий детали о NA и предоставляющий методы, связанные с этим.
|
|
4
5
|
*/
|
|
@@ -24,4 +25,5 @@ export declare class NativeParamsService {
|
|
|
24
25
|
private getAppId;
|
|
25
26
|
private readNativeParamsCookie;
|
|
26
27
|
private resolveEnvironment;
|
|
28
|
+
private resolveAppVersion;
|
|
27
29
|
}
|
|
@@ -14,9 +14,7 @@ class NativeParamsService {
|
|
|
14
14
|
this.nativeParamsReadErrorFlag = false;
|
|
15
15
|
const nativeParams = this.readNativeParamsCookie();
|
|
16
16
|
this.environment = this.resolveEnvironment();
|
|
17
|
-
this.appVersion =
|
|
18
|
-
? nativeParams.appVersion
|
|
19
|
-
: '0.0.0';
|
|
17
|
+
this.appVersion = this.resolveAppVersion(nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.appVersion);
|
|
20
18
|
this.appId = this.getAppId(nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.iosAppId);
|
|
21
19
|
this.nextPageId = (nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.nextPageId) || null;
|
|
22
20
|
this.originalWebviewParams = (nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.originalWebviewParams) || null;
|
|
@@ -84,5 +82,14 @@ class NativeParamsService {
|
|
|
84
82
|
}
|
|
85
83
|
return window.Android ? 'android' : 'ios';
|
|
86
84
|
}
|
|
85
|
+
resolveAppVersion(versionFromCookie) {
|
|
86
|
+
var _a;
|
|
87
|
+
if (((_a = this.noop) === null || _a === void 0 ? void 0 : _a.enabled) && this.noop.appVersion) {
|
|
88
|
+
return this.noop.appVersion;
|
|
89
|
+
}
|
|
90
|
+
return NativeParamsService.isValidVersionFormat(versionFromCookie)
|
|
91
|
+
? versionFromCookie
|
|
92
|
+
: '0.0.0';
|
|
93
|
+
}
|
|
87
94
|
}
|
|
88
95
|
exports.NativeParamsService = NativeParamsService;
|
package/client/types.d.ts
CHANGED
|
@@ -3,12 +3,15 @@ export type BrowserHistoryApiWrappers = {
|
|
|
3
3
|
go?: (delta: number) => void;
|
|
4
4
|
replace?: (url: HistoryReplaceStateParams[2], state: HistoryReplaceStateParams[0]) => void;
|
|
5
5
|
};
|
|
6
|
-
export type Environment = 'android' | 'ios';
|
|
7
6
|
export type HistoryPushStateParams = Parameters<typeof window.history.pushState>;
|
|
8
7
|
export type HistoryReplaceStateParams = Parameters<typeof window.history.replaceState>;
|
|
9
8
|
export type LocationAssignParam = Parameters<typeof window.location.assign>[0];
|
|
10
9
|
export type LogError = (b2nErrorMessage: string, originalError: unknown) => void;
|
|
11
10
|
export type NativeFeatureKey = 'geolocation' | 'linksInBrowser' | 'savedBackStack';
|
|
11
|
+
export type NativeFeatureContext = {
|
|
12
|
+
feature: NativeFeatureKey;
|
|
13
|
+
fallbackReason?: string;
|
|
14
|
+
};
|
|
12
15
|
type NativeFeaturesParams = Readonly<Record<NativeFeatureKey, {
|
|
13
16
|
fromVersion: string;
|
|
14
17
|
}>>;
|
|
@@ -18,8 +21,4 @@ export type NativeFeaturesFromVersion = Readonly<{
|
|
|
18
21
|
}>;
|
|
19
22
|
export type PdfType = 'pdfFile' | 'base64' | 'binary';
|
|
20
23
|
export type Theme = 'light' | 'dark';
|
|
21
|
-
export type NoopOptions = {
|
|
22
|
-
enabled: boolean;
|
|
23
|
-
environment?: Environment;
|
|
24
|
-
};
|
|
25
24
|
export {};
|
package/package.json
CHANGED
|
@@ -11,6 +11,8 @@ exports.HEADER_KEY_USER_AGENT = 'user-agent';
|
|
|
11
11
|
*/
|
|
12
12
|
// Ключ cookie, с помощью которого серверная часть B2N передаст на клиент информацию об NA.
|
|
13
13
|
exports.COOKIE_KEY_BRIDGE_TO_NATIVE_DATA = 'bridgeToNativeData';
|
|
14
|
+
// Ключ cookie, с помощью которого серверная часть B2N передаст на клиент информацию об NA.
|
|
15
|
+
// export const B2N_MODE = 'b2n_mode';
|
|
14
16
|
// NA на обеих платформах подмешивает этот заголовок к запросу за HTML.
|
|
15
17
|
// TODO:
|
|
16
18
|
// * Исследовать, делает ли оно это при запросах к прочим ресурсам;
|
package/server/is-webview-env.js
CHANGED
|
@@ -10,23 +10,21 @@ const utils_1 = require("./utils");
|
|
|
10
10
|
* @param request Объект запроса (Request или IncomingMessage).
|
|
11
11
|
*/
|
|
12
12
|
function isWebviewEnv(request) {
|
|
13
|
-
const appVersion = (0, utils_1.getHeaderValue)(request, query_and_headers_keys_1.HEADER_KEY_NATIVE_APPVERSION);
|
|
14
|
-
const userAgent = (0, utils_1.getHeaderValue)(request, query_and_headers_keys_1.HEADER_KEY_USER_AGENT);
|
|
15
|
-
const isWebviewByHeaders =
|
|
16
|
-
// `app-version` в заголовках — основной индикатор запроса из вебвью.
|
|
17
|
-
(appVersion && regexp_patterns_1.versionPattern.test(appVersion)) ||
|
|
18
|
-
// Проверка «на всякий случай» для iOS — нет уверенности,
|
|
19
|
-
// что `app-version` стабильно и на всех версиях есть во всех запросах из вебвью.
|
|
20
|
-
(userAgent && regexp_patterns_1.webviewUaIOSPattern.test(userAgent));
|
|
21
|
-
if (isWebviewByHeaders)
|
|
22
|
-
return true;
|
|
23
|
-
const isBrowserEnv = userAgent && !regexp_patterns_1.webviewUaIOSPattern.test(userAgent) && !appVersion;
|
|
24
|
-
if (isBrowserEnv)
|
|
25
|
-
return false;
|
|
26
13
|
// Выставленная ранее кука — однозначный индикатор вебвью окружения.
|
|
27
14
|
const cookieHeader = (0, utils_1.getHeaderValue)(request, query_and_headers_keys_1.HEADER_KEY_COOKIE);
|
|
28
15
|
if ((0, utils_1.hasBridgeToNativeDataCookie)(cookieHeader)) {
|
|
29
16
|
return true;
|
|
30
17
|
}
|
|
18
|
+
const appVersion = (0, utils_1.getHeaderValue)(request, query_and_headers_keys_1.HEADER_KEY_NATIVE_APPVERSION);
|
|
19
|
+
// `app-version` в заголовках — основной индикатор запроса из вебвью.
|
|
20
|
+
if (appVersion && regexp_patterns_1.versionPattern.test(appVersion)) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
const userAgent = (0, utils_1.getHeaderValue)(request, query_and_headers_keys_1.HEADER_KEY_USER_AGENT);
|
|
24
|
+
// Проверка «на всякий случай» для iOS — нет уверенности,
|
|
25
|
+
// что `app-version` стабильно и на всех версиях есть во всех запросах из вебвью.
|
|
26
|
+
if (userAgent && regexp_patterns_1.webviewUaIOSPattern.test(userAgent)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
31
29
|
return false;
|
|
32
30
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type NativeParams } from '../types';
|
|
1
|
+
import { type NativeParams, type NoopOptions } from '../types';
|
|
2
2
|
import { type UniversalRequest } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Парсит запрос, доставая из него данные о нативном приложении,
|
|
@@ -11,4 +11,4 @@ import { type UniversalRequest } from './types';
|
|
|
11
11
|
* Нужно передать функцию, которая средствами используемого веб-сервера добавит заголовок в ответ.
|
|
12
12
|
* b2native с её помощью добавит `Set-Cookie` заголовок с некоторыми данными для своего клиентского кода.
|
|
13
13
|
*/
|
|
14
|
-
export declare function prepareNativeAppDetailsForClient(request: UniversalRequest, setResponseHeader: (headerKey: string, headerValue: string) => void): Partial<NativeParams>;
|
|
14
|
+
export declare function prepareNativeAppDetailsForClient(request: UniversalRequest, setResponseHeader: (headerKey: string, headerValue: string) => void, noop?: NoopOptions): Partial<NativeParams>;
|
|
@@ -16,15 +16,17 @@ const utils_1 = require("./utils");
|
|
|
16
16
|
* Нужно передать функцию, которая средствами используемого веб-сервера добавит заголовок в ответ.
|
|
17
17
|
* b2native с её помощью добавит `Set-Cookie` заголовок с некоторыми данными для своего клиентского кода.
|
|
18
18
|
*/
|
|
19
|
-
function prepareNativeAppDetailsForClient(request, setResponseHeader) {
|
|
19
|
+
function prepareNativeAppDetailsForClient(request, setResponseHeader, noop) {
|
|
20
20
|
// Поскольку вебвью модули имеют особенность сохранять сессионную куку подолгу,
|
|
21
21
|
// даже после перезагрузки устройства или обновления приложения/ОС, ее значение
|
|
22
22
|
// актуализируется при каждом запросе на сервер.
|
|
23
23
|
const cookieHeader = (0, utils_1.getHeaderValue)(request, query_and_headers_keys_1.HEADER_KEY_COOKIE);
|
|
24
24
|
const nativeParamsFromCookie = (0, utils_1.readNativeParamsFromCookie)(cookieHeader);
|
|
25
25
|
const nativeParams = buildNativeParams(request, nativeParamsFromCookie);
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
if (!noop?.enabled) {
|
|
27
|
+
const serializedNativeParams = encodeURIComponent(JSON.stringify(nativeParams));
|
|
28
|
+
setResponseHeader('Set-Cookie', `${query_and_headers_keys_1.COOKIE_KEY_BRIDGE_TO_NATIVE_DATA}=${serializedNativeParams}; Path=/`);
|
|
29
|
+
}
|
|
28
30
|
return nativeParams;
|
|
29
31
|
}
|
|
30
32
|
function buildNativeParams(request, nativeParamsFromCookie) {
|
package/server/utils.js
CHANGED
|
@@ -74,6 +74,8 @@ const getBridgeToNativeDataCookie = (cookieHeader) => {
|
|
|
74
74
|
return undefined;
|
|
75
75
|
};
|
|
76
76
|
exports.getBridgeToNativeDataCookie = getBridgeToNativeDataCookie;
|
|
77
|
+
// export const getBridgeToNativeDataCookie = (cookieHeader: string | null) =>
|
|
78
|
+
// getCookieValue(cookieHeader, COOKIE_KEY_BRIDGE_TO_NATIVE_DATA);
|
|
77
79
|
/**
|
|
78
80
|
* Возвращает десериализованные данные из `bridgeToNativeData` cookie.
|
|
79
81
|
*/
|
|
@@ -89,3 +91,10 @@ function readNativeParamsFromCookie(cookieHeader) {
|
|
|
89
91
|
return null;
|
|
90
92
|
}
|
|
91
93
|
}
|
|
94
|
+
// export function readModeFromCookie(cookieHeader: string | null) {
|
|
95
|
+
// const mode = getCookieValue(cookieHeader, B2N_MODE);
|
|
96
|
+
// if (!mode) {
|
|
97
|
+
// return null;
|
|
98
|
+
// }
|
|
99
|
+
// return mode as 'noop' | 'native';
|
|
100
|
+
// }
|
package/types.d.ts
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { type Environment, type NoopOptions } from '../types';
|
|
2
|
-
export declare class NativeExecuteService {
|
|
3
|
-
private isNoop?;
|
|
4
|
-
private environment?;
|
|
5
|
-
constructor(isNoop?: NoopOptions["enabled"] | undefined, environment?: Environment | undefined);
|
|
6
|
-
execute(action: string, fn: () => void, payload?: unknown): void;
|
|
7
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NativeExecuteService = void 0;
|
|
4
|
-
class NativeExecuteService {
|
|
5
|
-
constructor(isNoop, environment) {
|
|
6
|
-
this.isNoop = isNoop;
|
|
7
|
-
this.environment = environment;
|
|
8
|
-
}
|
|
9
|
-
execute(action, fn, payload) {
|
|
10
|
-
if (this.isNoop) {
|
|
11
|
-
console.info(`[B2N noop][${this.environment}] ${action}`, payload);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
fn();
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
exports.NativeExecuteService = NativeExecuteService;
|