@alfalab/bridge-to-native 0.2.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/client/bridge-to-native.d.ts +220 -0
  2. package/client/bridge-to-native.js +267 -0
  3. package/client/constants.d.ts +13 -0
  4. package/client/constants.js +30 -0
  5. package/client/services-and-utils/close-webview-util.d.ts +1 -0
  6. package/client/services-and-utils/close-webview-util.js +11 -0
  7. package/client/services-and-utils/external-links-service.d.ts +15 -0
  8. package/client/services-and-utils/external-links-service.js +71 -0
  9. package/client/services-and-utils/native-navigation-and-title-service.d.ts +70 -0
  10. package/client/services-and-utils/native-navigation-and-title-service.js +236 -0
  11. package/client/services-and-utils/native-params-service.d.ts +24 -0
  12. package/client/services-and-utils/native-params-service.js +79 -0
  13. package/client/types.d.ts +19 -0
  14. package/client/types.js +2 -0
  15. package/package.json +79 -79
  16. package/query-and-headers-keys.d.ts +12 -0
  17. package/query-and-headers-keys.js +49 -0
  18. package/server/extract-native-service-queries.d.ts +9 -0
  19. package/server/extract-native-service-queries.js +41 -0
  20. package/server/index.d.ts +2 -0
  21. package/server/index.js +7 -0
  22. package/server/is-webview-env.d.ts +7 -0
  23. package/server/is-webview-env.js +30 -0
  24. package/server/prepare-native-app-details-for-client.d.ts +14 -0
  25. package/server/prepare-native-app-details-for-client.js +103 -0
  26. package/server/regexp-patterns.d.ts +4 -0
  27. package/server/regexp-patterns.js +10 -0
  28. package/server/types.d.ts +2 -0
  29. package/server/types.js +2 -0
  30. package/server/utils.d.ts +25 -0
  31. package/server/utils.js +53 -0
  32. package/types.d.ts +1 -32
  33. package/bridge-to-native.d.ts +0 -63
  34. package/bridge-to-native.js +0 -147
  35. package/constants.d.ts +0 -15
  36. package/constants.js +0 -32
  37. package/esm/bridge-to-native.d.ts +0 -63
  38. package/esm/bridge-to-native.js +0 -154
  39. package/esm/constants.d.ts +0 -15
  40. package/esm/constants.js +0 -29
  41. package/esm/index.d.ts +0 -2
  42. package/esm/native-fallbacks.d.ts +0 -64
  43. package/esm/native-fallbacks.js +0 -119
  44. package/esm/native-navigation-and-title.d.ts +0 -147
  45. package/esm/native-navigation-and-title.js +0 -326
  46. package/esm/types.d.ts +0 -39
  47. package/esm/types.js +0 -1
  48. package/esm/utils.d.ts +0 -23
  49. package/esm/utils.js +0 -62
  50. package/index.d.ts +0 -2
  51. package/native-fallbacks.d.ts +0 -64
  52. package/native-fallbacks.js +0 -124
  53. package/native-navigation-and-title.d.ts +0 -147
  54. package/native-navigation-and-title.js +0 -329
  55. package/utils.d.ts +0 -23
  56. package/utils.js +0 -70
  57. /package/{esm/index.js → client/index.d.ts} +0 -0
  58. /package/{index.js → client/index.js} +0 -0
@@ -0,0 +1,70 @@
1
+
2
+ import { type BrowserHistoryApiWrappers, type HistoryPushStateParams, type LocationAssignParam, type LogError } from '../types';
3
+ import { type NativeParamsService } from './native-params-service';
4
+ /**
5
+ * Сервис, отвечающий за взаимодействие WA с WV компонентами NA —
6
+ * «заголовком» и кнопкой «назад».
7
+ */
8
+ export declare class NativeNavigationAndTitleService {
9
+ private nativeParamsService;
10
+ private browserHistoryApiWrappers?;
11
+ private logError?;
12
+ private nativeHistoryStack;
13
+ private numOfBackSteps;
14
+ private lastSetPageSettingsParams;
15
+ constructor(nativeParamsService: NativeParamsService, browserHistoryApiWrappers?: BrowserHistoryApiWrappers | undefined, logError?: LogError | undefined);
16
+ closeWebview(): void;
17
+ goBack(): void;
18
+ goBackAFewStepsClientSide(stepsNumber: number, autoCloseWebview?: boolean): void;
19
+ navigateClientSide(url: HistoryPushStateParams[2], state?: HistoryPushStateParams[0], nativeTitle?: string): void;
20
+ navigateServerSide(link: LocationAssignParam, nativeTitle?: string): void;
21
+ reload(): void;
22
+ setInitialView(nativeTitle?: string): void;
23
+ setTitle(nativeTitle: string): void;
24
+ /**
25
+ * Метод, вычисляющий `pageId`, который нужно послать в NA
26
+ * для правильной синхронизации с кнопкой "Назад". Также вычисляет `pageTitle`
27
+ * для отправки в NA.
28
+ *
29
+ * @returns Правильный pageId и pageTitle.
30
+ */
31
+ private getNativePageIdAndTitle;
32
+ /**
33
+ * Обработчик для `window.onpopstate` события. Который сработает
34
+ * после нажатия на кнопку «Назад» в NA, вызова `history.back()` и `history.go(-x)`.
35
+ */
36
+ private handleClientSideNavigationBack;
37
+ private static hasSavedHistoryStack;
38
+ /**
39
+ * Инициализирует `nativeHistoryStack`, учитывая варианты:
40
+ * - Инициализация при открытии WV (Сценарий 1);
41
+ * - Инициализация при server-side навигации в рамках одной WV-сессии (Сценарий 2);
42
+ * - Инициализация при server-side переходе «назад» по истории (Сценарий 3).
43
+ */
44
+ private initializeNativeHistoryStack;
45
+ /**
46
+ * Подготавливает ссылку для корректного перехода server-side навигацией.
47
+ *
48
+ * @param url URL для перехода внутри WA server-side навигацией.
49
+ * @return Подготовленная ссылка для экземпляра B2N следующего WA или
50
+ * экзепляра B2N следующей страницы текущего WA
51
+ */
52
+ private prepareExternalLinkBeforeOpen;
53
+ /**
54
+ * Читает сохраннённый в sessionStorage `nativeHistoryStack`,
55
+ * снова сохраняет его в sessionStorage, уменьшая список на одну запись,
56
+ * на случай, если будет дальнейший переход назад server-side навигацией.
57
+ *
58
+ * @returns Актуальное состояние `nativeHistoryStack` из sessionStorage.
59
+ */
60
+ private readAndUpdateNativeHistoryStackSessionStorage;
61
+ /**
62
+ * Сохранение состояния связи текущего WA с NA при server-side навигации в sessionStorage.
63
+ */
64
+ private saveNativeHistoryStack;
65
+ /**
66
+ * Синхронизирует состояние истории переходов и заголовок с NA в соответствии
67
+ * с `nativeHistoryStack`.
68
+ */
69
+ private syncHistoryWithNative;
70
+ }
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ /* eslint max-lines: ["error", {"skipComments": true}] */ // Много комментариев.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.NativeNavigationAndTitleService = void 0;
5
+ const query_and_headers_keys_1 = require("../../query-and-headers-keys");
6
+ const close_webview_util_1 = require("./close-webview-util");
7
+ /**
8
+ * Сервис, отвечающий за взаимодействие WA с WV компонентами NA —
9
+ * «заголовком» и кнопкой «назад».
10
+ */
11
+ class NativeNavigationAndTitleService {
12
+ constructor(nativeParamsService, browserHistoryApiWrappers, logError) {
13
+ this.nativeParamsService = nativeParamsService;
14
+ this.browserHistoryApiWrappers = browserHistoryApiWrappers;
15
+ this.logError = logError;
16
+ // Поле, помогающее правильно обработать переход «назад» на несколько шагов.
17
+ this.numOfBackSteps = 1;
18
+ // Здесь сохраняются параметры, которые в последний раз были отправлены
19
+ // в NA. Помогает предотвратить повторную отправку одинаковых параметров.
20
+ this.lastSetPageSettingsParams = '';
21
+ this.handleClientSideNavigationBack = this.handleClientSideNavigationBack.bind(this);
22
+ window.addEventListener('popstate', this.handleClientSideNavigationBack); // без отписки т.к. Сервис используется в течение всей жизни WA
23
+ this.initializeNativeHistoryStack();
24
+ }
25
+ // eslint-disable-next-line class-methods-use-this -- удобней использовать метод в контексте экземпляра.
26
+ closeWebview() {
27
+ (0, close_webview_util_1.closeWebviewUtil)();
28
+ }
29
+ goBack() {
30
+ this.goBackAFewStepsClientSide(-1, true);
31
+ }
32
+ goBackAFewStepsClientSide(stepsNumber, autoCloseWebview = false) {
33
+ var _a;
34
+ if (!stepsNumber) {
35
+ return;
36
+ }
37
+ const stepsToBack = Math.abs(stepsNumber);
38
+ const maxStepsToBack = this.nativeHistoryStack.length - 1;
39
+ if (stepsToBack > maxStepsToBack) {
40
+ if (autoCloseWebview) {
41
+ (0, close_webview_util_1.closeWebviewUtil)();
42
+ return;
43
+ }
44
+ this.numOfBackSteps = maxStepsToBack;
45
+ }
46
+ else {
47
+ this.numOfBackSteps = stepsToBack;
48
+ }
49
+ const steps = -this.numOfBackSteps;
50
+ if ((_a = this.browserHistoryApiWrappers) === null || _a === void 0 ? void 0 : _a.go) {
51
+ this.browserHistoryApiWrappers.go(steps);
52
+ }
53
+ else {
54
+ window.history.go(steps);
55
+ }
56
+ // Далее сработает подписка на `popstate`, см. метод `handleClientSideNavigationBack`.
57
+ }
58
+ navigateClientSide(url, state = null, nativeTitle = '') {
59
+ var _a, _b;
60
+ if ((_a = this.browserHistoryApiWrappers) === null || _a === void 0 ? void 0 : _a.push) {
61
+ (_b = this.browserHistoryApiWrappers) === null || _b === void 0 ? void 0 : _b.push(url, state);
62
+ }
63
+ else {
64
+ window.history.pushState(state, '', url);
65
+ }
66
+ this.nativeHistoryStack.push(nativeTitle);
67
+ this.syncHistoryWithNative();
68
+ }
69
+ navigateServerSide(link, nativeTitle = '') {
70
+ const url = link instanceof URL ? link : new URL(link);
71
+ if (nativeTitle) {
72
+ url.searchParams.set(query_and_headers_keys_1.QUERY_B2N_TITLE, nativeTitle);
73
+ }
74
+ // TODO: Предыдущая реализация на iOS открывала новое WV. Возможно, что-то плохо работало,
75
+ // обязательно протестировать.
76
+ this.saveNativeHistoryStack();
77
+ window.location.assign(this.prepareExternalLinkBeforeOpen(url));
78
+ }
79
+ reload() {
80
+ this.nativeHistoryStack.push(1 /* NativeHistoryStackSpecialValues.TemporaryReloadStub */); // небольшой костыль, чтобы переиспользовать server-side сценарий
81
+ this.saveNativeHistoryStack();
82
+ // информация для серверной стороны B2N, что происходит `reload` и парсить запрос на предмет NA параметров не нужно (в нем их скорее всего не будет)
83
+ document.cookie = `${query_and_headers_keys_1.COOKIE_KEY_BRIDGE_TO_NATIVE_RELOAD}=true; Path=/`;
84
+ }
85
+ setInitialView(nativeTitle = '') {
86
+ this.nativeHistoryStack = [nativeTitle];
87
+ this.syncHistoryWithNative();
88
+ }
89
+ setTitle(nativeTitle) {
90
+ this.nativeHistoryStack[this.nativeHistoryStack.length - 1] = nativeTitle;
91
+ this.syncHistoryWithNative();
92
+ }
93
+ /**
94
+ * Метод, вычисляющий `pageId`, который нужно послать в NA
95
+ * для правильной синхронизации с кнопкой "Назад". Также вычисляет `pageTitle`
96
+ * для отправки в NA.
97
+ *
98
+ * @returns Правильный pageId и pageTitle.
99
+ */
100
+ getNativePageIdAndTitle() {
101
+ // * В iOS для "первой" страницы не нужно слать `pageId`.
102
+ // * В Android важно, чтобы `pageId` «первой» страницы
103
+ // всегда был одинаковый.
104
+ const stackSize = this.nativeHistoryStack.length;
105
+ const pageTitle = this.nativeHistoryStack[this.nativeHistoryStack.length - 1];
106
+ if (this.nativeParamsService.environment === 'android') {
107
+ return { pageId: stackSize <= 1 ? 1 : stackSize, pageTitle };
108
+ }
109
+ return { pageId: stackSize <= 1 ? null : stackSize, pageTitle };
110
+ }
111
+ /**
112
+ * Обработчик для `window.onpopstate` события. Который сработает
113
+ * после нажатия на кнопку «Назад» в NA, вызова `history.back()` и `history.go(-x)`.
114
+ */
115
+ handleClientSideNavigationBack() {
116
+ this.nativeHistoryStack = this.nativeHistoryStack.slice(0, -this.numOfBackSteps);
117
+ this.numOfBackSteps = 1;
118
+ if (this.nativeHistoryStack.length < 1) {
119
+ (0, close_webview_util_1.closeWebviewUtil)();
120
+ return;
121
+ }
122
+ this.syncHistoryWithNative();
123
+ }
124
+ static hasSavedHistoryStack() {
125
+ return sessionStorage.getItem(query_and_headers_keys_1.SS_KEY_BRIDGE_TO_NATIVE_HISTORY_STACK) !== null;
126
+ }
127
+ /**
128
+ * Инициализирует `nativeHistoryStack`, учитывая варианты:
129
+ * - Инициализация при открытии WV (Сценарий 1);
130
+ * - Инициализация при server-side навигации в рамках одной WV-сессии (Сценарий 2);
131
+ * - Инициализация при server-side переходе «назад» по истории (Сценарий 3).
132
+ */
133
+ initializeNativeHistoryStack() {
134
+ const { nextPageId, title } = this.nativeParamsService;
135
+ if (nextPageId) {
136
+ // Сценарий 2 – `nextPageId` ставит метод `this.navigateServerSide`,
137
+ // т.е. это инициализация сразу после перехода server-side навигацией.
138
+ this.nativeHistoryStack = new Array(nextPageId).fill(0 /* NativeHistoryStackSpecialValues.ServerSideNavigationStub */);
139
+ this.nativeHistoryStack[this.nativeHistoryStack.length - 1] = title;
140
+ }
141
+ else if (NativeNavigationAndTitleService.hasSavedHistoryStack()) {
142
+ // Сценарий 3 - в sessionStorage есть сохранённый nativeHistoryStack,
143
+ // значит это инициализация сразу после перехода назад server-side навигацией,
144
+ // или инициализация после использования метода `reload`.
145
+ try {
146
+ this.nativeHistoryStack = this.readAndUpdateNativeHistoryStackSessionStorage();
147
+ }
148
+ catch (_a) {
149
+ this.nativeHistoryStack = [''];
150
+ }
151
+ }
152
+ else {
153
+ // Сценарий 1 - запись в sessionStorage ставит метод `this.navigateServerSide`,
154
+ // её нет, значит это инициализация сразу после открытия нового WV.
155
+ this.nativeHistoryStack = [title];
156
+ }
157
+ this.syncHistoryWithNative();
158
+ }
159
+ /**
160
+ * Подготавливает ссылку для корректного перехода server-side навигацией.
161
+ *
162
+ * @param url URL для перехода внутри WA server-side навигацией.
163
+ * @return Подготовленная ссылка для экземпляра B2N следующего WA или
164
+ * экзепляра B2N следующей страницы текущего WA
165
+ */
166
+ prepareExternalLinkBeforeOpen(url) {
167
+ const currentPageId = this.nativeHistoryStack.length;
168
+ const divider = new URL(url).searchParams.toString() ? '&' : '?';
169
+ const modifiedUrl = new URL(`${url}${divider}${this.nativeParamsService.originalWebviewParams}`);
170
+ modifiedUrl.searchParams.set(query_and_headers_keys_1.QUERY_B2N_NEXT_PAGEID, (currentPageId + 1).toString());
171
+ return modifiedUrl;
172
+ }
173
+ /**
174
+ * Читает сохраннённый в sessionStorage `nativeHistoryStack`,
175
+ * снова сохраняет его в sessionStorage, уменьшая список на одну запись,
176
+ * на случай, если будет дальнейший переход назад server-side навигацией.
177
+ *
178
+ * @returns Актуальное состояние `nativeHistoryStack` из sessionStorage.
179
+ */
180
+ readAndUpdateNativeHistoryStackSessionStorage() {
181
+ try {
182
+ const serializedNativeHistoryStack = sessionStorage.getItem(query_and_headers_keys_1.SS_KEY_BRIDGE_TO_NATIVE_HISTORY_STACK);
183
+ if (!serializedNativeHistoryStack) {
184
+ throw new Error();
185
+ }
186
+ const nativeHistoryStack = JSON.parse(serializedNativeHistoryStack); // происходит внутри оператора `catch`, поэтому кастинг типа приемлем
187
+ const nativeHistoryStackToSerialize = nativeHistoryStack.slice(0, -1);
188
+ sessionStorage.setItem(query_and_headers_keys_1.SS_KEY_BRIDGE_TO_NATIVE_HISTORY_STACK, JSON.stringify(nativeHistoryStackToSerialize));
189
+ if (nativeHistoryStack[nativeHistoryStack.length - 1] ===
190
+ 1 /* NativeHistoryStackSpecialValues.TemporaryReloadStub */) {
191
+ return nativeHistoryStack.slice(0, -1);
192
+ }
193
+ return nativeHistoryStack;
194
+ }
195
+ catch (e) {
196
+ if (this.logError) {
197
+ this.logError('Клиентский код B2N не смог восстановить `nativeHistoryStack` из sessionStorage. ' +
198
+ 'Могут возникнуть проблемы с кнопкой «Назад» в NA.', e);
199
+ }
200
+ throw new Error();
201
+ }
202
+ }
203
+ /**
204
+ * Сохранение состояния связи текущего WA с NA при server-side навигации в sessionStorage.
205
+ */
206
+ saveNativeHistoryStack() {
207
+ const serializedNativeHistoryStack = JSON.stringify(this.nativeHistoryStack);
208
+ sessionStorage.setItem(query_and_headers_keys_1.SS_KEY_BRIDGE_TO_NATIVE_HISTORY_STACK, serializedNativeHistoryStack);
209
+ }
210
+ /**
211
+ * Синхронизирует состояние истории переходов и заголовок с NA в соответствии
212
+ * с `nativeHistoryStack`.
213
+ */
214
+ syncHistoryWithNative() {
215
+ var _a;
216
+ const { pageId, pageTitle } = this.getNativePageIdAndTitle();
217
+ if (this.nativeParamsService.environment === 'android') {
218
+ const narrowedPageId = pageId !== null && pageId !== void 0 ? pageId : 1;
219
+ const paramsToSend = JSON.stringify({ pageId: narrowedPageId, pageTitle });
220
+ if (this.lastSetPageSettingsParams !== paramsToSend) {
221
+ (_a = this.nativeParamsService.AndroidBridge) === null || _a === void 0 ? void 0 : _a.setPageSettings(paramsToSend);
222
+ this.lastSetPageSettingsParams = paramsToSend;
223
+ }
224
+ }
225
+ else {
226
+ const pageTitleStr = `?pageTitle=${encodeURIComponent(pageTitle)}`;
227
+ const pageIdStr = pageId ? `&pageId=${pageId}` : '';
228
+ const paramsToSend = `ios:setPageSettings/${pageTitleStr + pageIdStr}`;
229
+ if (this.lastSetPageSettingsParams !== paramsToSend) {
230
+ window.location.replace(paramsToSend);
231
+ this.lastSetPageSettingsParams = paramsToSend;
232
+ }
233
+ }
234
+ }
235
+ }
236
+ exports.NativeNavigationAndTitleService = NativeNavigationAndTitleService;
@@ -0,0 +1,24 @@
1
+ import { type Environment, type LogError, type NativeFeatureKey, type Theme } from '../types';
2
+ /**
3
+ * Сервис, аккумулирующий детали о NA и предоставляющий методы, связанные с этим.
4
+ */
5
+ export declare class NativeParamsService {
6
+ private logError?;
7
+ AndroidBridge: {
8
+ setPageSettings: (params: string) => void;
9
+ } | undefined;
10
+ appId: string;
11
+ appVersion: string;
12
+ environment: Environment;
13
+ nativeParamsReadErrorFlag: boolean;
14
+ nextPageId: number | null;
15
+ originalWebviewParams: string | null;
16
+ theme: Theme;
17
+ title: string;
18
+ constructor(logError?: LogError | undefined);
19
+ canUseNativeFeature(feature: NativeFeatureKey): boolean;
20
+ isCurrentVersionHigherOrEqual(versionToCompare: string): boolean;
21
+ private static isValidVersionFormat;
22
+ private getAppId;
23
+ private readNativeParamsCookie;
24
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NativeParamsService = void 0;
4
+ const query_and_headers_keys_1 = require("../../query-and-headers-keys");
5
+ const constants_1 = require("../constants");
6
+ /**
7
+ * Сервис, аккумулирующий детали о NA и предоставляющий методы, связанные с этим.
8
+ */
9
+ class NativeParamsService {
10
+ constructor(logError) {
11
+ this.logError = logError;
12
+ this.AndroidBridge = window.Android;
13
+ this.environment = window.Android ? 'android' : 'ios';
14
+ this.nativeParamsReadErrorFlag = false;
15
+ const nativeParams = this.readNativeParamsCookie();
16
+ this.appVersion = NativeParamsService.isValidVersionFormat(nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.appVersion)
17
+ ? nativeParams.appVersion
18
+ : '0.0.0';
19
+ this.appId = this.getAppId(nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.iosAppId);
20
+ this.nextPageId = (nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.nextPageId) || null;
21
+ this.originalWebviewParams = (nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.originalWebviewParams) || null;
22
+ this.theme = (nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.theme) === 'dark' ? 'dark' : 'light';
23
+ this.title = (nativeParams === null || nativeParams === void 0 ? void 0 : nativeParams.title) || '';
24
+ }
25
+ canUseNativeFeature(feature) {
26
+ const { fromVersion } = constants_1.NATIVE_FEATURES_FROM_VERSION[this.environment][feature];
27
+ return this.isCurrentVersionHigherOrEqual(fromVersion);
28
+ }
29
+ isCurrentVersionHigherOrEqual(versionToCompare) {
30
+ if (!NativeParamsService.isValidVersionFormat(versionToCompare)) {
31
+ return false;
32
+ }
33
+ const matchPattern = /(\d+)\.(\d+)\.(\d+)/;
34
+ const [, ...appVersionComponents] = this.appVersion.match(matchPattern); // Формат версии проверен в конструкторе, можно смело убирать `null` из типа.
35
+ const [, ...versionToCompareComponents] = versionToCompare.match(matchPattern);
36
+ for (let i = 0; i < appVersionComponents.length; i++) {
37
+ if (appVersionComponents[i] !== versionToCompareComponents[i]) {
38
+ return appVersionComponents[i] >= versionToCompareComponents[i];
39
+ }
40
+ }
41
+ return true;
42
+ }
43
+ static isValidVersionFormat(version) {
44
+ if (!version)
45
+ return false;
46
+ const versionPattern = /^\d+\.\d+\.\d+$/;
47
+ return versionPattern.test(version);
48
+ }
49
+ getAppId(knownIosAppId) {
50
+ if (this.environment !== 'ios') {
51
+ return constants_1.ANDROID_APP_ID;
52
+ }
53
+ if (knownIosAppId) {
54
+ return knownIosAppId;
55
+ }
56
+ const keys = Object.keys(constants_1.VERSION_TO_IOS_APP_ID);
57
+ const rightKey = [...keys].reverse().find((version) => this.isCurrentVersionHigherOrEqual(version)) ||
58
+ keys[0];
59
+ return constants_1.VERSION_TO_IOS_APP_ID[rightKey];
60
+ }
61
+ readNativeParamsCookie() {
62
+ var _a;
63
+ const allCookies = document.cookie.split(';');
64
+ const nativeParamsCookie = allCookies.find((c) => c.trim().startsWith(query_and_headers_keys_1.COOKIE_KEY_BRIDGE_TO_NATIVE_DATA));
65
+ try {
66
+ const deserializedNativeParams = decodeURIComponent((_a = nativeParamsCookie === null || nativeParamsCookie === void 0 ? void 0 : nativeParamsCookie.split('=')[1]) !== null && _a !== void 0 ? _a : '');
67
+ return JSON.parse(deserializedNativeParams);
68
+ }
69
+ catch (e) {
70
+ this.nativeParamsReadErrorFlag = true;
71
+ if (this.logError) {
72
+ this.logError('Клиентский код B2N не смог получить информацию о NA из cookie. ' +
73
+ 'Некоторые методы B2N могут работать некорректно', e);
74
+ }
75
+ return null;
76
+ }
77
+ }
78
+ }
79
+ exports.NativeParamsService = NativeParamsService;
@@ -0,0 +1,19 @@
1
+ export type BrowserHistoryApiWrappers = {
2
+ push?: (url: HistoryPushStateParams[2], state: HistoryPushStateParams[0]) => void;
3
+ go?: (delta: number) => void;
4
+ };
5
+ export type Environment = 'android' | 'ios';
6
+ export type HistoryPushStateParams = Parameters<typeof window.history.pushState>;
7
+ export type LocationAssignParam = Parameters<typeof window.location.assign>[0];
8
+ export type LogError = (b2nErrorMessage: string, originalError: unknown) => void;
9
+ export type NativeFeatureKey = 'geolocation' | 'linksInBrowser' | 'savedBackStack';
10
+ type NativeFeaturesParams = Readonly<Record<NativeFeatureKey, {
11
+ fromVersion: string;
12
+ }>>;
13
+ export type NativeFeaturesFromVersion = Readonly<{
14
+ android: NativeFeaturesParams;
15
+ ios: NativeFeaturesParams;
16
+ }>;
17
+ export type PdfType = 'pdfFile' | 'base64' | 'binary';
18
+ export type Theme = 'light' | 'dark';
19
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,121 +1,121 @@
1
1
  {
2
- "license": "UNLICENSED",
3
2
  "name": "@alfalab/bridge-to-native",
4
- "version": "0.2.2",
3
+ "version": "1.0.1",
4
+ "license": "MIT",
5
+ "description": "Утилита для удобной работы веб приложения внутри нативного приложения и коммуникации с ним.",
6
+ "engines": {
7
+ "node": ">=20.19.2",
8
+ "npm": "please-use-yarn"
9
+ },
5
10
  "repository": {
6
11
  "type": "git",
7
12
  "url": "git+https://github.com/core-ds/bridge-to-native.git"
8
13
  },
9
- "main": "./index.js",
10
- "module": "./esm/index.js",
11
14
  "exports": {
12
- ".": {
13
- "import": "./esm/index.js",
14
- "require": "./index.js"
15
+ "./client": {
16
+ "import": "./client/index.js",
17
+ "require": "./client/index.js",
18
+ "types": "./client/index.d.ts"
15
19
  },
16
- "./*": {
17
- "import": "./esm/*",
18
- "require": "./*"
20
+ "./server": {
21
+ "import": "./server/index.js",
22
+ "require": "./server/index.js",
23
+ "types": "./server/index.d.ts"
19
24
  }
20
25
  },
21
26
  "sideEffects": false,
22
- "files": [
23
- "*"
24
- ],
25
27
  "bugs": {
26
28
  "url": "https://github.com/core-ds/bridge-to-native/issues"
27
29
  },
28
- "description": "Утилита для удобной работы веб приложения внутри нативного приложения и коммуникации с ним.",
29
30
  "scripts": {
30
- "build": "yarn compile",
31
+ "build": "yarn build:clean && yarn build:ts",
32
+ "build:clean": "shx rm -rf .publish",
33
+ "build:copy-package-json": "shx cp package.json .publish/package.json",
34
+ "build:ts": "tsc --build",
31
35
  "changelog": "bash bin/fill-changelog-file-and-notify-github.sh",
32
- "compile": "yarn compile:clean && yarn compile:ts && yarn compile:ts:esm && yarn compile:copy-resources",
33
- "compile:copy-package-json": "shx cp package.json .publish/package.json",
34
- "compile:copy-resources": "yarn copyfiles -e \"**/*.{[jt]s*(x),snap}\" -e \"**/*.json\" -u 1 \"src/**/*\" .publish",
35
- "compile:clean": "shx rm -rf .publish",
36
- "compile:ts": "tsc --project tsconfig.build.json",
37
- "compile:ts:esm": "tsc --project tsconfig.build.esm.json",
38
- "lint:scripts": "eslint \"**/*.{js,jsx,ts,tsx}\" --ext .js,.jsx,.ts,.tsx",
39
- "lint": "yarn lint:scripts && prettier --check \"./src/*.{ts,tsx,js,jsx,json}\"",
40
- "lint:fix": "yarn lint:scripts --fix",
36
+ "format": "arui-presets-lint format",
37
+ "format:check": "arui-presets-lint format:check",
38
+ "lint": "yarn lint:scripts && yarn format:check",
39
+ "lint:fix": "yarn lint:scripts --fix && yarn format",
40
+ "lint:scripts": "arui-presets-lint scripts",
41
41
  "pub": "npm publish .publish --userconfig \"../.npmrc\" --tag \"$TAG\"",
42
- "format": "prettier --write \"./**/*.{ts,tsx,js,jsx,css,json}\"",
43
- "test": "jest --silent --collect-coverage",
44
- "release": "yarn build && npm version \"$VERSION\" --no-git-tag-version && yarn compile:copy-package-json && yarn pub"
42
+ "release": "yarn build && npm version \"$VERSION\" --no-git-tag-version && yarn build:copy-package-json && yarn pub",
43
+ "test": "arui-scripts test --silent --collect-coverage"
45
44
  },
46
- "dependencies": {},
47
45
  "devDependencies": {
48
- "@types/jest": "27.5.2",
49
- "@types/node": "14.14.22",
50
- "@typescript-eslint/eslint-plugin": "^5.30.6",
51
- "@typescript-eslint/parser": "^5.30.6",
52
- "arui-presets-lint": "6.2.0",
53
- "arui-scripts": "15.10.3",
46
+ "@happy-dom/jest-environment": "18.0.1",
47
+ "@types/jest": "29.5.14",
48
+ "@types/node": "20.19.1",
49
+ "arui-presets-lint": "8.7.0",
50
+ "arui-scripts": "19.0.7",
54
51
  "copyfiles": "2.4.1",
55
- "eslint": "^8.20.0",
56
- "eslint-config-airbnb": "^19.0.4",
57
- "eslint-config-airbnb-typescript": "^17.0.0",
58
- "eslint-config-prettier": "^8.5.0",
59
- "eslint-import-resolver-typescript": "~3.1.5",
60
- "eslint-plugin-dirnames": "^1.0.3",
61
- "eslint-plugin-import": "^2.26.0",
62
- "eslint-plugin-simple-import-sort": "^7.0.0",
63
- "eslint-plugin-unicorn": "^42.0.0",
64
- "husky": "^4.3.8",
65
- "jest": "27.5.1",
66
52
  "jest-junit": "10.0.0",
67
53
  "lint-staged": "^12.5.0",
68
- "prettier": "^2.7.1",
69
54
  "promisify-child-process": "4.1.1",
70
- "stylelint": "^14.9.1",
71
- "stylelint-config-prettier": "^9.0.3",
72
- "ts-jest": "25.3.1",
73
- "typescript": "4.5.5",
74
- "shx": "0.3.4"
55
+ "shx": "0.3.4",
56
+ "typescript": "5.5.4"
57
+ },
58
+ "commitlint": {
59
+ "extends": "./node_modules/arui-presets-lint/commitlint"
60
+ },
61
+ "eslintConfig": {
62
+ "extends": "./node_modules/arui-presets-lint/eslint",
63
+ "parserOptions": {
64
+ "project": [
65
+ "./__tests__/tsconfig.json",
66
+ "./src/client/tsconfig.json",
67
+ "./src/server/tsconfig.json"
68
+ ]
69
+ },
70
+ "overrides": [
71
+ {
72
+ "files": [
73
+ "__tests__/**/*"
74
+ ],
75
+ "rules": {
76
+ "max-lines": "off"
77
+ }
78
+ }
79
+ ]
75
80
  },
76
- "peerDependencies": {},
77
81
  "jest": {
78
- "preset": "arui-scripts",
79
- "testEnvironment": "jsdom",
80
- "testRegex": "/test/.*\\.ts$",
81
- "moduleFileExtensions": [
82
- "ts",
83
- "js"
82
+ "projects": [
83
+ {
84
+ "displayName": "client-tests",
85
+ "testEnvironment": "@happy-dom/jest-environment",
86
+ "testPathIgnorePatterns": [
87
+ "/__tests__/server/"
88
+ ]
89
+ },
90
+ {
91
+ "displayName": "server-tests",
92
+ "testEnvironment": "node",
93
+ "testPathIgnorePatterns": [
94
+ "/__tests__/client/"
95
+ ]
96
+ }
84
97
  ],
85
- "coveragePathIgnorePatterns": [
86
- "/node_modules/",
87
- "/test/",
88
- "/src/index.ts"
89
- ],
90
- "transformIgnorePatterns": [
91
- "node_modules/(?!(uuid)/)"
98
+ "testRegex": [
99
+ "__tests__/.*\\.test\\.ts"
92
100
  ],
93
- "testPathIgnorePatterns": [
101
+ "coveragePathIgnorePatterns": [
94
102
  "/node_modules/",
95
- "/test/mock"
103
+ "/src/(client|server)/index.ts"
96
104
  ],
97
105
  "reporters": [
98
- "jest-junit",
99
- "default"
106
+ "default",
107
+ "jest-junit"
100
108
  ]
101
109
  },
102
- "jest-junit": {
103
- "output": "./test-results.xml"
104
- },
105
110
  "prettier": "arui-presets-lint/prettier",
106
- "eslintConfig": {
107
- "extends": "./node_modules/arui-presets-lint/eslint"
108
- },
109
111
  "stylelint": {
110
112
  "extends": "arui-presets-lint/stylelint",
111
113
  "ignoreFiles": [
112
114
  "coverage/**/*.js"
113
115
  ]
114
116
  },
115
- "commitlint": {
116
- "extends": "./node_modules/arui-presets-lint/commitlint"
117
- },
118
117
  "publishConfig": {
119
118
  "registry": "https://registry.npmjs.org"
120
- }
119
+ },
120
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
121
121
  }
@@ -0,0 +1,12 @@
1
+ export declare const HEADER_KEY_COOKIE = "cookie";
2
+ export declare const HEADER_KEY_USER_AGENT = "user-agent";
3
+ export declare const COOKIE_KEY_BRIDGE_TO_NATIVE_DATA = "bridgeToNativeData";
4
+ export declare const COOKIE_KEY_BRIDGE_TO_NATIVE_RELOAD = "bridgeToNativeReload";
5
+ export declare const HEADER_KEY_NATIVE_APPVERSION = "app-version";
6
+ export declare const QUERY_B2N_NEXT_PAGEID = "b2n-next-page-id";
7
+ export declare const QUERY_B2N_TITLE = "b2n-title";
8
+ export declare const QUERY_B2N_TITLE_DEPRECATED = "title";
9
+ export declare const QUERY_NATIVE_IOS_APPID = "applicationId";
10
+ export declare const QUERY_NATIVE_IOS_APPVERSION = "device_app_version";
11
+ export declare const QUERY_NATIVE_THEME = "theme";
12
+ export declare const SS_KEY_BRIDGE_TO_NATIVE_HISTORY_STACK = "bridgeToNativeHistoryStack";