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.
@@ -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,2 @@
1
+ /** The pre-computed duration of a media file, in seconds. */
2
+ export declare const getCachedDuration: (path: string) => number | undefined;
@@ -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, utils_1.getCachedDuration)(section.ftbPath);
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, utils_1.getCachedDuration)(section.path);
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, utils_1.getCachedDuration)(path);
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);
@@ -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, utils_1.getCachedDuration)(section.path) ?? 0), 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, utils_1.getCachedDuration)(section.path) ?? 0), 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, utils_1.getCachedDuration)(lessonInfo.eqPath) === undefined) {
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, utils_1.getCachedDuration)(lessonInfo.fullPath) === undefined) {
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, utils_1.getCachedDuration)(lessonInfo.videoPath) === undefined) {
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
- export declare const getCachedDuration: (path: string) => number | undefined;
7
+ /** Safely read `code`/`message` off an unknown thrown value. */
8
+ export declare function getErrorInfo(e: unknown): {
9
+ code?: string;
10
+ message?: string;
11
+ };
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getCachedDuration = exports.basenamenoext = exports.extname = exports.dirname = exports.first = exports.basename = exports.join = void 0;
4
- const mediaDurations_1 = require("../data/mediaDurations");
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
- const getCachedDuration = (path) => mediaDurations_1.mediaDurations[(0, exports.first)(path)]?.[(0, exports.basename)(path)];
22
- exports.getCachedDuration = getCachedDuration;
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waha-shared",
3
- "version": "1.0.489",
3
+ "version": "1.0.490",
4
4
  "author": "Waha",
5
5
  "dependencies": {
6
6
  "@types/signale": "^1.4.7",