waha-shared 1.0.489 → 1.0.490
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/functions/auth.d.ts +17 -0
- package/dist/functions/auth.js +64 -0
- package/dist/functions/media.d.ts +2 -0
- package/dist/functions/media.js +8 -0
- package/dist/functions/scripturePassages.js +4 -3
- package/dist/functions/sets.js +6 -5
- package/dist/functions/utils.d.ts +5 -1
- package/dist/functions/utils.js +13 -4
- package/package.json +1 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AppTranslations } from '../types/languages';
|
|
2
|
+
/**
|
|
3
|
+
* Maps a Firebase Auth error to a user-readable message to display in the UI.
|
|
4
|
+
*/
|
|
5
|
+
export declare function mapFirebaseAuthError(app: AppTranslations, e: unknown): string;
|
|
6
|
+
/**
|
|
7
|
+
* Whether an auth error is a routine one we don't want reported to Sentry.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isExpectedAuthError(e: unknown): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether a thrown SSO error is just the user dismissing the provider's UI,
|
|
12
|
+
* rather than a real failure worth reporting. Each app passes the identifiers
|
|
13
|
+
* its own providers use: the native flows put Apple-on-Android's identifier on
|
|
14
|
+
* the error message and Apple-on-iOS's and Google's on `code`, while the web
|
|
15
|
+
* SDK reports a dismissed popup as a `code`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function ignoreError(ignoreIds: Set<string>, e: unknown): boolean;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapFirebaseAuthError = mapFirebaseAuthError;
|
|
4
|
+
exports.isExpectedAuthError = isExpectedAuthError;
|
|
5
|
+
exports.ignoreError = ignoreError;
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
/*
|
|
8
|
+
* The Firebase Auth error codes every Waha app shows a tailored message for.
|
|
9
|
+
* Anything not listed here falls back to the generic message, so adding a code
|
|
10
|
+
* in one place adds it everywhere.
|
|
11
|
+
*
|
|
12
|
+
* Two auth messages deliberately live outside this map because they aren't
|
|
13
|
+
* driven by a Firebase error code: `popups_auth_errors_provider_error` (an SSO
|
|
14
|
+
* provider failing before Firebase is ever reached, and it interpolates the
|
|
15
|
+
* provider name) and `popups_auth_errors_link_wrong_device` (a magic link
|
|
16
|
+
* opened where its email was never entered, which throws nothing at all).
|
|
17
|
+
*/
|
|
18
|
+
const authErrorMessages = (app) => new Map([
|
|
19
|
+
['auth/too-many-requests', app.popups_auth_errors_too_many_requests],
|
|
20
|
+
['auth/user-disabled', app.popups_auth_errors_user_disabled],
|
|
21
|
+
['auth/network-request-failed', app.connect_to_continue],
|
|
22
|
+
// Passwordless email-link (magic link) return leg. `invalid-action-code`
|
|
23
|
+
// and `expired-action-code` share a message — to the user, an expired link
|
|
24
|
+
// and an already-used one are the same story.
|
|
25
|
+
['auth/invalid-action-code', app.popups_auth_errors_link_expired],
|
|
26
|
+
['auth/expired-action-code', app.popups_auth_errors_link_expired],
|
|
27
|
+
]);
|
|
28
|
+
/**
|
|
29
|
+
* Maps a Firebase Auth error to a user-readable message to display in the UI.
|
|
30
|
+
*/
|
|
31
|
+
function mapFirebaseAuthError(app, e) {
|
|
32
|
+
const { code } = (0, utils_1.getErrorInfo)(e);
|
|
33
|
+
// A Map rather than an object literal: looked up on an object, an error
|
|
34
|
+
// carrying a code like `constructor` resolves up the prototype chain and
|
|
35
|
+
// hands back a function where this signature promises a string.
|
|
36
|
+
const message = code === undefined ? undefined : authErrorMessages(app).get(code);
|
|
37
|
+
return message || app.popups_auth_errors_generic;
|
|
38
|
+
}
|
|
39
|
+
/** Auth failures to not log to Sentry. */
|
|
40
|
+
const EXPECTED_AUTH_ERROR_CODES = new Set([
|
|
41
|
+
// A magic link that was already used, or has aged out.
|
|
42
|
+
'auth/invalid-action-code',
|
|
43
|
+
'auth/expired-action-code',
|
|
44
|
+
'auth/network-request-failed',
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* Whether an auth error is a routine one we don't want reported to Sentry.
|
|
48
|
+
*/
|
|
49
|
+
function isExpectedAuthError(e) {
|
|
50
|
+
const { code } = (0, utils_1.getErrorInfo)(e);
|
|
51
|
+
return code !== undefined && EXPECTED_AUTH_ERROR_CODES.has(code);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Whether a thrown SSO error is just the user dismissing the provider's UI,
|
|
55
|
+
* rather than a real failure worth reporting. Each app passes the identifiers
|
|
56
|
+
* its own providers use: the native flows put Apple-on-Android's identifier on
|
|
57
|
+
* the error message and Apple-on-iOS's and Google's on `code`, while the web
|
|
58
|
+
* SDK reports a dismissed popup as a `code`.
|
|
59
|
+
*/
|
|
60
|
+
function ignoreError(ignoreIds, e) {
|
|
61
|
+
const { code, message } = (0, utils_1.getErrorInfo)(e);
|
|
62
|
+
return ((code !== undefined && ignoreIds.has(code)) ||
|
|
63
|
+
(message !== undefined && ignoreIds.has(message)));
|
|
64
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCachedDuration = void 0;
|
|
4
|
+
const mediaDurations_1 = require("../data/mediaDurations");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
/** The pre-computed duration of a media file, in seconds. */
|
|
7
|
+
const getCachedDuration = (path) => mediaDurations_1.mediaDurations[(0, utils_1.first)(path)]?.[(0, utils_1.basename)(path)];
|
|
8
|
+
exports.getCachedDuration = getCachedDuration;
|
|
@@ -16,6 +16,7 @@ const languages_1 = require("../functions/languages");
|
|
|
16
16
|
const sets_1 = require("../types/sets");
|
|
17
17
|
const bibleBooks_1 = require("./bibleBooks");
|
|
18
18
|
const bibles_1 = require("./bibles");
|
|
19
|
+
const media_1 = require("./media");
|
|
19
20
|
const utils_1 = require("./utils");
|
|
20
21
|
var bibleBooks_2 = require("./bibleBooks");
|
|
21
22
|
Object.defineProperty(exports, "parseVerseRange", { enumerable: true, get: function () { return bibleBooks_2.parseVerseRange; } });
|
|
@@ -214,7 +215,7 @@ function verseToSuperscript(num) {
|
|
|
214
215
|
function getFtbDuration(section, lessonInfo) {
|
|
215
216
|
if (!section.ftbPath)
|
|
216
217
|
return 0;
|
|
217
|
-
const ftbDuration = (0,
|
|
218
|
+
const ftbDuration = (0, media_1.getCachedDuration)(section.ftbPath);
|
|
218
219
|
if (ftbDuration == null) {
|
|
219
220
|
console.warn(`FTB duration not found for ${(0, utils_1.basename)(section.ftbPath)}`);
|
|
220
221
|
}
|
|
@@ -244,7 +245,7 @@ function enrichSections(lessonInfo, scripture) {
|
|
|
244
245
|
const ignoreTimings = isStory && priorStoryLengthUnknown ? true : undefined;
|
|
245
246
|
const startTime = currentTime;
|
|
246
247
|
if (!isStory) {
|
|
247
|
-
length = (0,
|
|
248
|
+
length = (0, media_1.getCachedDuration)(section.path);
|
|
248
249
|
}
|
|
249
250
|
else {
|
|
250
251
|
currentTime += getFtbDuration(section, lessonInfo);
|
|
@@ -275,7 +276,7 @@ function enrichSections(lessonInfo, scripture) {
|
|
|
275
276
|
* slightly off.
|
|
276
277
|
*/
|
|
277
278
|
const path = lessonInfo.type === 'dbs' ? lessonInfo.fullPath : lessonInfo.videoPath;
|
|
278
|
-
const totalDuration = (0,
|
|
279
|
+
const totalDuration = (0, media_1.getCachedDuration)(path);
|
|
279
280
|
if (totalDuration) {
|
|
280
281
|
let timeFromEnd = totalDuration;
|
|
281
282
|
const applicationSections = enriched.filter((s) => s.chapter === sets_1.Chapter.APPLICATION);
|
package/dist/functions/sets.js
CHANGED
|
@@ -12,6 +12,7 @@ const youtubeVideos_1 = require("../data/youtubeVideos");
|
|
|
12
12
|
const scripturePassages_1 = require("../functions/scripturePassages");
|
|
13
13
|
const sets_2 = require("../types/sets");
|
|
14
14
|
const bibles_1 = require("./bibles");
|
|
15
|
+
const media_1 = require("./media");
|
|
15
16
|
const utils_1 = require("./utils");
|
|
16
17
|
function getSetInfo({ setId, languageId, setIds, t, }) {
|
|
17
18
|
const idComponents = setId.split('.');
|
|
@@ -219,12 +220,12 @@ function assembleLessonSections({ languageInfo, setInfo, lesson, t, useSpokenQue
|
|
|
219
220
|
.filter((s) => s.chapter === sets_2.Chapter.FELLOWSHIP)
|
|
220
221
|
.reduce((sum, section) => sum +
|
|
221
222
|
(section.pauseBefore ?? 0) +
|
|
222
|
-
((0,
|
|
223
|
+
((0, media_1.getCachedDuration)(section.path) ?? 0), 0),
|
|
223
224
|
applicationDuration: sections
|
|
224
225
|
.filter((s) => s.chapter === sets_2.Chapter.APPLICATION)
|
|
225
226
|
.reduce((sum, section) => sum +
|
|
226
227
|
(section.pauseBefore ?? 0) +
|
|
227
|
-
((0,
|
|
228
|
+
((0, media_1.getCachedDuration)(section.path) ?? 0), 0),
|
|
228
229
|
};
|
|
229
230
|
}
|
|
230
231
|
function getTrainingVideoPaths({ languageInfo, lessonId, }) {
|
|
@@ -362,18 +363,18 @@ function shouldShowLesson(lessonInfo) {
|
|
|
362
363
|
return false;
|
|
363
364
|
}
|
|
364
365
|
else if (lessonInfo.type === 'eq' &&
|
|
365
|
-
(0,
|
|
366
|
+
(0, media_1.getCachedDuration)(lessonInfo.eqPath) === undefined) {
|
|
366
367
|
console.log('Missing remote eq file for lesson:', lessonInfo.lessonId);
|
|
367
368
|
return false;
|
|
368
369
|
}
|
|
369
370
|
else if (lessonInfo.type === 'dbs' &&
|
|
370
|
-
(0,
|
|
371
|
+
(0, media_1.getCachedDuration)(lessonInfo.fullPath) === undefined) {
|
|
371
372
|
console.log('Missing remote dbs file for lesson:', lessonInfo.lessonId);
|
|
372
373
|
return false;
|
|
373
374
|
}
|
|
374
375
|
else if (lessonInfo.type === 'video' &&
|
|
375
376
|
lessonInfo.videoPath &&
|
|
376
|
-
(0,
|
|
377
|
+
(0, media_1.getCachedDuration)(lessonInfo.videoPath) === undefined) {
|
|
377
378
|
console.log('Missing remote video for lesson:', lessonInfo.lessonId);
|
|
378
379
|
return false;
|
|
379
380
|
}
|
|
@@ -4,4 +4,8 @@ export declare const first: (p: string) => string;
|
|
|
4
4
|
export declare const dirname: (p: string) => string;
|
|
5
5
|
export declare const extname: (p: string) => string;
|
|
6
6
|
export declare const basenamenoext: (p: string) => string;
|
|
7
|
-
|
|
7
|
+
/** Safely read `code`/`message` off an unknown thrown value. */
|
|
8
|
+
export declare function getErrorInfo(e: unknown): {
|
|
9
|
+
code?: string;
|
|
10
|
+
message?: string;
|
|
11
|
+
};
|
package/dist/functions/utils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
3
|
+
exports.basenamenoext = exports.extname = exports.dirname = exports.first = exports.basename = exports.join = void 0;
|
|
4
|
+
exports.getErrorInfo = getErrorInfo;
|
|
5
5
|
const join = (...parts) => parts.join('/').replace(/\/+/g, '/');
|
|
6
6
|
exports.join = join;
|
|
7
7
|
const basename = (p) => p.split('/').pop();
|
|
@@ -18,5 +18,14 @@ const basenamenoext = (p) => {
|
|
|
18
18
|
return dotIndex !== -1 ? base.slice(0, dotIndex) : base;
|
|
19
19
|
};
|
|
20
20
|
exports.basenamenoext = basenamenoext;
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/** Safely read `code`/`message` off an unknown thrown value. */
|
|
22
|
+
function getErrorInfo(e) {
|
|
23
|
+
const code = typeof e === 'object' &&
|
|
24
|
+
e !== null &&
|
|
25
|
+
'code' in e &&
|
|
26
|
+
typeof e.code === 'string'
|
|
27
|
+
? e.code
|
|
28
|
+
: undefined;
|
|
29
|
+
const message = e instanceof Error ? e.message : undefined;
|
|
30
|
+
return { code, message };
|
|
31
|
+
}
|