@escapenavigator/utils 1.10.153 → 1.10.155
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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/is-stale-chunk-error.d.ts +7 -0
- package/dist/is-stale-chunk-error.js +49 -0
- package/dist/slot-representative-price.d.ts +5 -0
- package/dist/slot-representative-price.js +16 -7
- package/dist/slot-representative-price.spec.js +9 -0
- package/dist/validate-promocode.spec.js +0 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './get-order-cancelation-state';
|
|
|
15
15
|
export * from './get-service-error';
|
|
16
16
|
export * from './is-axios-error';
|
|
17
17
|
export * from './is-network-error';
|
|
18
|
+
export * from './is-stale-chunk-error';
|
|
18
19
|
export * from './phone';
|
|
19
20
|
export * from './pick';
|
|
20
21
|
export * from './promocode-error-codes';
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ __exportStar(require("./get-order-cancelation-state"), exports);
|
|
|
31
31
|
__exportStar(require("./get-service-error"), exports);
|
|
32
32
|
__exportStar(require("./is-axios-error"), exports);
|
|
33
33
|
__exportStar(require("./is-network-error"), exports);
|
|
34
|
+
__exportStar(require("./is-stale-chunk-error"), exports);
|
|
34
35
|
__exportStar(require("./phone"), exports);
|
|
35
36
|
__exportStar(require("./pick"), exports);
|
|
36
37
|
__exportStar(require("./promocode-error-codes"), exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Совпадает ли текст сообщения с сигнатурой протухшего чанка. */
|
|
2
|
+
export declare function isStaleChunkMessage(message?: string | null): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Проверка ошибки целиком: смотрим `message`, `name` (ChunkLoadError) и
|
|
5
|
+
* вложенный `cause` (новые браузеры заворачивают исходную ошибку).
|
|
6
|
+
*/
|
|
7
|
+
export declare function isStaleChunkError(error: unknown): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isStaleChunkMessage = isStaleChunkMessage;
|
|
4
|
+
exports.isStaleChunkError = isStaleChunkError;
|
|
5
|
+
/**
|
|
6
|
+
* Распознавание «протухшего чанка» (stale chunk) — общий matcher для всех
|
|
7
|
+
* фронтов (app / orders / widget).
|
|
8
|
+
*
|
|
9
|
+
* Кейс: у клиента открыта старая вкладка/сборка. После деплоя на CDN уже нет
|
|
10
|
+
* чанка со старым хешем → ленивый `import()` (`React.lazy`, Vite preload)
|
|
11
|
+
* падает. Браузеры формулируют это по-разному:
|
|
12
|
+
* - Chrome/Safari: "Failed to fetch dynamically imported module"
|
|
13
|
+
* - Firefox: "error loading dynamically imported module"
|
|
14
|
+
* - Vite preload: "Unable to preload CSS/module"
|
|
15
|
+
* - Webpack: "ChunkLoadError" / "Loading chunk N failed"
|
|
16
|
+
* - Safari SPA-fallback на index.html → отдаёт text/html вместо JS:
|
|
17
|
+
* "'text/html' is not a valid JavaScript MIME type" /
|
|
18
|
+
* "expected a JavaScript-or-Wasm module script"
|
|
19
|
+
*
|
|
20
|
+
* Держим список в ОДНОМ месте: новый браузерный текст добавляется здесь и
|
|
21
|
+
* сразу подхватывается lazyWithRetry (retry/reload) и глобальным recovery
|
|
22
|
+
* виджета. ВАЖНО: matcher не зависит от React — поэтому живёт в utils.
|
|
23
|
+
*/
|
|
24
|
+
const STALE_CHUNK_RE = /Failed to fetch dynamically imported module|error loading dynamically imported module|Importing a module script failed|Unable to preload (CSS|module)|Loading (CSS )?chunk \d+ failed|ChunkLoadError|is not a valid JavaScript MIME type|expected a JavaScript-or-Wasm module script/i;
|
|
25
|
+
/** Совпадает ли текст сообщения с сигнатурой протухшего чанка. */
|
|
26
|
+
function isStaleChunkMessage(message) {
|
|
27
|
+
return !!message && STALE_CHUNK_RE.test(message);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Проверка ошибки целиком: смотрим `message`, `name` (ChunkLoadError) и
|
|
31
|
+
* вложенный `cause` (новые браузеры заворачивают исходную ошибку).
|
|
32
|
+
*/
|
|
33
|
+
function isStaleChunkError(error) {
|
|
34
|
+
if (!error)
|
|
35
|
+
return false;
|
|
36
|
+
if (typeof error === 'string')
|
|
37
|
+
return isStaleChunkMessage(error);
|
|
38
|
+
const { message, name, cause } = error;
|
|
39
|
+
if (isStaleChunkMessage(message))
|
|
40
|
+
return true;
|
|
41
|
+
if (isStaleChunkMessage(name))
|
|
42
|
+
return true;
|
|
43
|
+
if (cause && cause !== error) {
|
|
44
|
+
const causeMessage = typeof cause === 'string' ? cause : cause?.message;
|
|
45
|
+
if (isStaleChunkMessage(causeMessage))
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
@@ -3,6 +3,11 @@ type SlotPriceSource = {
|
|
|
3
3
|
basePrice?: number;
|
|
4
4
|
discount?: number;
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* Плоская карта цен из тарифа слота.
|
|
8
|
+
* Принимает и `{ id, price: { "2": 1500 } }` (листинг), и `{ "2": 1500 }` (/slots/details).
|
|
9
|
+
*/
|
|
10
|
+
export declare const getTariffPriceMap: (tariff: unknown) => Record<string, number>;
|
|
6
11
|
/** Минимальная положительная цена из тарифа (без скидки слота). */
|
|
7
12
|
export declare const getTariffBasePrice: (tariff: unknown) => number | null;
|
|
8
13
|
/** Цена «от» для слота в расписании (с учётом скидки слота). */
|
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getSlotRepresentativePrice = exports.getTariffBasePrice = void 0;
|
|
3
|
+
exports.getSlotRepresentativePrice = exports.getTariffBasePrice = exports.getTariffPriceMap = void 0;
|
|
4
4
|
const applySlotDiscount = (base, discount) => {
|
|
5
5
|
const value = discount || 0;
|
|
6
6
|
if (!value)
|
|
7
7
|
return base;
|
|
8
8
|
return base - Math.floor((base / 10000) * value);
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Плоская карта цен из тарифа слота.
|
|
12
|
+
* Принимает и `{ id, price: { "2": 1500 } }` (листинг), и `{ "2": 1500 }` (/slots/details).
|
|
13
|
+
*/
|
|
14
|
+
const getTariffPriceMap = (tariff) => {
|
|
12
15
|
if (!tariff || typeof tariff !== 'object')
|
|
13
|
-
return
|
|
16
|
+
return {};
|
|
14
17
|
const raw = tariff;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
if (raw.price && typeof raw.price === 'object' && raw.price !== null) {
|
|
19
|
+
return raw.price;
|
|
20
|
+
}
|
|
21
|
+
return raw;
|
|
22
|
+
};
|
|
23
|
+
exports.getTariffPriceMap = getTariffPriceMap;
|
|
24
|
+
/** Минимальная положительная цена из тарифа (без скидки слота). */
|
|
25
|
+
const getTariffBasePrice = (tariff) => {
|
|
26
|
+
const priceMap = (0, exports.getTariffPriceMap)(tariff);
|
|
18
27
|
const keys = Object.keys(priceMap)
|
|
19
28
|
.filter((k) => k !== 'child' && !Number.isNaN(Number(k)))
|
|
20
29
|
.map(Number)
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const slot_representative_price_1 = require("./slot-representative-price");
|
|
4
4
|
describe('slot-representative-price', () => {
|
|
5
|
+
it('unwraps nested tariff.price map', () => {
|
|
6
|
+
expect((0, slot_representative_price_1.getTariffPriceMap)({
|
|
7
|
+
id: 1,
|
|
8
|
+
price: { 2: 10000, 3: 8000 },
|
|
9
|
+
})).toEqual({ 2: 10000, 3: 8000 });
|
|
10
|
+
});
|
|
11
|
+
it('returns plain price map as-is', () => {
|
|
12
|
+
expect((0, slot_representative_price_1.getTariffPriceMap)({ 2: 5000, 4: 4000 })).toEqual({ 2: 5000, 4: 4000 });
|
|
13
|
+
});
|
|
5
14
|
it('reads price from tariff.price map', () => {
|
|
6
15
|
expect((0, slot_representative_price_1.getTariffBasePrice)({
|
|
7
16
|
id: 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@escapenavigator/utils",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.155",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"test": "jest"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@escapenavigator/types": "^1.10.
|
|
17
|
+
"@escapenavigator/types": "^1.10.149",
|
|
18
18
|
"axios": "^0.21.4",
|
|
19
19
|
"class-transformer": "^0.5.1",
|
|
20
20
|
"class-validator": "^0.13.2",
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"ts-jest": "^29.1.1",
|
|
29
29
|
"typescript": "^5.6"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "e868f8962dfa6caab506d64bd4c6c091514e44a2"
|
|
32
32
|
}
|