@churchapps/content-providers 0.4.0 → 0.5.0

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.cts CHANGED
@@ -19,7 +19,8 @@ interface ContentProviderConfig {
19
19
  scopes: string[];
20
20
  supportsDeviceFlow?: boolean;
21
21
  deviceAuthEndpoint?: string;
22
- endpoints: EndpointsConfig;
22
+ /** @deprecated URL templates now live in each provider; kept optional for type compatibility. */
23
+ endpoints?: EndpointsConfig;
23
24
  }
24
25
  interface DeviceAuthorizationResponse {
25
26
  device_code: string;
@@ -240,12 +241,54 @@ interface IProvider {
240
241
  */
241
242
  declare function navigateToPath(instructions: Instructions, path: string): InstructionItem | null;
242
243
 
244
+ declare class OAuthHelper {
245
+ generateCodeVerifier(): string;
246
+ generateCodeChallenge(verifier: string): Promise<string>;
247
+ buildAuthUrl(config: ContentProviderConfig, codeVerifier: string, redirectUri: string, state?: string): Promise<{
248
+ url: string;
249
+ challengeMethod: string;
250
+ }>;
251
+ exchangeCodeForTokens(config: ContentProviderConfig, _providerId: string, code: string, codeVerifier: string, redirectUri: string): Promise<ContentProviderAuthData | null>;
252
+ }
253
+
254
+ /** Map a raw OAuth token response to ContentProviderAuthData, stamping created_at. */
255
+ declare function toAuthData(data: Record<string, unknown>, fallbacks?: {
256
+ refreshToken?: string;
257
+ scope?: string;
258
+ }): ContentProviderAuthData;
243
259
  declare class TokenHelper {
244
260
  isAuthValid(auth: ContentProviderAuthData | null | undefined): boolean;
245
261
  isTokenExpired(auth: ContentProviderAuthData): boolean;
246
262
  refreshToken(config: ContentProviderConfig, auth: ContentProviderAuthData): Promise<ContentProviderAuthData | null>;
247
263
  }
248
264
 
265
+ declare class DeviceFlowHelper {
266
+ supportsDeviceFlow(config: ContentProviderConfig): boolean;
267
+ initiateDeviceFlow(config: ContentProviderConfig): Promise<DeviceAuthorizationResponse | null>;
268
+ pollDeviceFlowToken(config: ContentProviderConfig, deviceCode: string): Promise<DeviceFlowPollResult>;
269
+ calculatePollDelay(baseInterval?: number, slowDownCount?: number): number;
270
+ }
271
+
272
+ /**
273
+ * Shared base for providers: identity metadata, an authenticated fetch wrapper, and a
274
+ * config-driven supportsDeviceFlow. Auth-flow methods (initiateDeviceFlow, buildAuthUrl, ...)
275
+ * deliberately do NOT live here: consumers feature-detect them with `"method" in provider`,
276
+ * so they must exist only on the providers that actually support each flow.
277
+ */
278
+ declare abstract class BaseProvider implements IProvider {
279
+ abstract readonly id: string;
280
+ abstract readonly name: string;
281
+ abstract readonly logos: ProviderLogos;
282
+ abstract readonly config: ContentProviderConfig;
283
+ abstract readonly requiresAuth: boolean;
284
+ abstract readonly authTypes: AuthType[];
285
+ abstract readonly capabilities: ProviderCapabilities;
286
+ private readonly apiHelper;
287
+ protected apiRequest<T>(path: string, auth?: ContentProviderAuthData | null, method?: "GET" | "POST", body?: unknown): Promise<T | null>;
288
+ abstract browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
289
+ supportsDeviceFlow(): boolean;
290
+ }
291
+
249
292
  /**
250
293
  * APlay Provider
251
294
  *
@@ -256,9 +299,7 @@ declare class TokenHelper {
256
299
  * /modules/{moduleId}/products/{productId}/{libraryId} -> media files
257
300
  * /modules/{moduleId}/libraries/{libraryId} -> media files (if module has 0-1 products)
258
301
  */
259
- declare class APlayProvider implements IProvider {
260
- private readonly apiHelper;
261
- private apiRequest;
302
+ declare class APlayProvider extends BaseProvider {
262
303
  readonly id = "aplay";
263
304
  readonly name = "APlay";
264
305
  readonly logos: ProviderLogos;
@@ -274,7 +315,6 @@ declare class APlayProvider implements IProvider {
274
315
  getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
275
316
  getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
276
317
  checkMediaLicense(mediaId: string, auth?: ContentProviderAuthData | null): Promise<MediaLicenseResult | null>;
277
- supportsDeviceFlow(): boolean;
278
318
  }
279
319
 
280
320
  /**
@@ -284,11 +324,9 @@ declare class APlayProvider implements IProvider {
284
324
  * /playlists -> list playlists
285
325
  * /playlists/{playlistId} -> list messages (files)
286
326
  */
287
- declare class SignPresenterProvider implements IProvider {
288
- private readonly apiHelper;
327
+ declare class SignPresenterProvider extends BaseProvider {
289
328
  private readonly oauthHelper;
290
329
  private readonly deviceFlowHelper;
291
- private apiRequest;
292
330
  readonly id = "signpresenter";
293
331
  readonly name = "SignPresenter";
294
332
  readonly logos: ProviderLogos;
@@ -297,11 +335,11 @@ declare class SignPresenterProvider implements IProvider {
297
335
  readonly authTypes: AuthType[];
298
336
  readonly capabilities: ProviderCapabilities;
299
337
  browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
338
+ private extractList;
300
339
  private getPlaylists;
301
340
  private getMessages;
302
341
  getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
303
342
  getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
304
- supportsDeviceFlow(): boolean;
305
343
  generateCodeVerifier(): string;
306
344
  buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
307
345
  url: string;
@@ -326,7 +364,7 @@ declare class SignPresenterProvider implements IProvider {
326
364
  * /addons/{category} -> individual add-ons
327
365
  * /addons/{category}/{addOnId} -> single add-on file
328
366
  */
329
- declare class LessonsChurchProvider implements IProvider {
367
+ declare class LessonsChurchProvider extends BaseProvider {
330
368
  readonly id = "lessonschurch";
331
369
  readonly name = "Lessons.church";
332
370
  readonly logos: ProviderLogos;
@@ -347,14 +385,11 @@ declare class LessonsChurchProvider implements IProvider {
347
385
  private getAddOnCategories;
348
386
  private getAddOnsByCategory;
349
387
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
350
- supportsDeviceFlow(): boolean;
351
388
  }
352
389
 
353
- declare class B1ChurchProvider implements IProvider {
354
- private readonly apiHelper;
390
+ declare class B1ChurchProvider extends BaseProvider {
355
391
  private readonly deviceFlowHelper;
356
392
  private readonly externalContentCache;
357
- private apiRequest;
358
393
  readonly id = "b1church";
359
394
  readonly name = "B1.Church";
360
395
  readonly logos: ProviderLogos;
@@ -382,12 +417,10 @@ declare class B1ChurchProvider implements IProvider {
382
417
  private findItemByPath;
383
418
  private findPresentationByPath;
384
419
  getPlaylist(path: string, authData?: ContentProviderAuthData | null, resolution?: number): Promise<ContentFile[] | null>;
385
- supportsDeviceFlow(): boolean;
386
420
  }
387
421
 
388
- declare class DropboxProvider implements IProvider {
422
+ declare class DropboxProvider extends BaseProvider {
389
423
  private readonly oauthHelper;
390
- private readonly apiHelper;
391
424
  readonly id = "dropbox";
392
425
  readonly name = "Dropbox";
393
426
  readonly logos: ProviderLogos;
@@ -403,9 +436,10 @@ declare class DropboxProvider implements IProvider {
403
436
  private resolveFileLinks;
404
437
  private checkIsLeaf;
405
438
  browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
439
+ /** Resolve a folder path to playable files (list + media filter + link resolution). */
440
+ private resolveMediaFiles;
406
441
  getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
407
442
  getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
408
- supportsDeviceFlow(): boolean;
409
443
  generateCodeVerifier(): string;
410
444
  buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
411
445
  url: string;
@@ -424,14 +458,11 @@ declare class DropboxProvider implements IProvider {
424
458
  * /serviceTypes/{serviceTypeId} -> list plans
425
459
  * /serviceTypes/{serviceTypeId}/{planId} -> plan items (leaf)
426
460
  */
427
- declare class PlanningCenterProvider implements IProvider {
428
- private readonly apiHelper;
429
- private apiRequest;
461
+ declare class PlanningCenterProvider extends BaseProvider {
430
462
  readonly id = "planningcenter";
431
463
  readonly name = "Planning Center";
432
464
  readonly logos: ProviderLogos;
433
465
  readonly config: ContentProviderConfig;
434
- private readonly ONE_WEEK_MS;
435
466
  readonly requiresAuth = true;
436
467
  readonly authTypes: AuthType[];
437
468
  readonly capabilities: ProviderCapabilities;
@@ -439,7 +470,6 @@ declare class PlanningCenterProvider implements IProvider {
439
470
  private getServiceTypes;
440
471
  private getPlans;
441
472
  private getPlanItems;
442
- supportsDeviceFlow(): boolean;
443
473
  }
444
474
 
445
475
  /**
@@ -450,23 +480,22 @@ declare class PlanningCenterProvider implements IProvider {
450
480
  * /{collectionSlug} -> list videos in collection
451
481
  * /{collectionSlug}/{videoId} -> single video
452
482
  */
453
- declare class BibleProjectProvider implements IProvider {
483
+ declare class BibleProjectProvider extends BaseProvider {
454
484
  readonly id = "bibleproject";
455
485
  readonly name = "The Bible Project";
456
486
  readonly logos: ProviderLogos;
457
487
  readonly config: ContentProviderConfig;
458
- private data;
459
- private getMuxThumbnail;
460
488
  readonly requiresAuth = false;
461
489
  readonly authTypes: AuthType[];
462
490
  readonly capabilities: ProviderCapabilities;
491
+ private data;
492
+ private getMuxThumbnail;
493
+ private videoToFile;
494
+ /** Resolve a path to its collection and files: all videos at depth 1, a single video at depth 2. */
495
+ private resolve;
463
496
  browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
464
- private getCollections;
465
- private getLessonFolders;
466
- private getVideoFile;
467
497
  getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
468
498
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
469
- supportsDeviceFlow(): boolean;
470
499
  }
471
500
 
472
501
  /**
@@ -478,7 +507,7 @@ declare class BibleProjectProvider implements IProvider {
478
507
  * /{collectionSlug}/{studyId} -> list lessons
479
508
  * /{collectionSlug}/{studyId}/{lessonId} -> lesson files (leaf)
480
509
  */
481
- declare class HighVoltageKidsProvider implements IProvider {
510
+ declare class HighVoltageKidsProvider extends BaseProvider {
482
511
  readonly id = "highvoltagekids";
483
512
  readonly name = "High Voltage Kids";
484
513
  readonly logos: ProviderLogos;
@@ -490,7 +519,6 @@ declare class HighVoltageKidsProvider implements IProvider {
490
519
  browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
491
520
  getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
492
521
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
493
- supportsDeviceFlow(): boolean;
494
522
  }
495
523
 
496
524
  /**
@@ -504,7 +532,7 @@ declare class HighVoltageKidsProvider implements IProvider {
504
532
  * /{category}/{id} -> single video (feature film) or container children (series/collection)
505
533
  * /{category}/{...containerIds}/{id} -> nested containers or single video (supports arbitrary depth)
506
534
  */
507
- declare class JesusFilmProvider implements IProvider {
535
+ declare class JesusFilmProvider extends BaseProvider {
508
536
  readonly id = "jesusfilm";
509
537
  readonly name = "Jesus Film Project";
510
538
  readonly logos: ProviderLogos;
@@ -513,19 +541,19 @@ declare class JesusFilmProvider implements IProvider {
513
541
  readonly authTypes: AuthType[];
514
542
  readonly capabilities: ProviderCapabilities;
515
543
  private fetchApi;
544
+ private fetchCategoryComponents;
516
545
  browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
517
546
  private getCategories;
518
547
  private getItemsInCategory;
519
548
  private getVideoFile;
520
549
  private getContainerChildren;
521
550
  private extractMuxPlaybackId;
522
- getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
523
551
  private fetchVideoFiles;
524
552
  private fetchContainerVideoFiles;
553
+ getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
525
554
  private buildVideoInstructions;
526
555
  private buildContainerInstructions;
527
556
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
528
- supportsDeviceFlow(): boolean;
529
557
  }
530
558
 
531
559
  /**
@@ -539,10 +567,8 @@ declare class JesusFilmProvider implements IProvider {
539
567
  * /catalog/{courseId} -> lesson folders (GET /catalog/{courseId})
540
568
  * /catalog/{courseId}/{lessonId} -> video files (GET /lesson-playlist/{lessonId})
541
569
  */
542
- declare class CbnProvider implements IProvider {
543
- private readonly apiHelper;
570
+ declare class CbnProvider extends BaseProvider {
544
571
  private readonly deviceFlowHelper;
545
- private apiRequest;
546
572
  readonly id = "cbn";
547
573
  readonly name = "CBN";
548
574
  readonly logos: ProviderLogos;
@@ -551,13 +577,10 @@ declare class CbnProvider implements IProvider {
551
577
  readonly authTypes: AuthType[];
552
578
  readonly capabilities: ProviderCapabilities;
553
579
  browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
554
- private getCourses;
555
- private getLessons;
556
- private getVideos;
557
- private fetchPlaylist;
580
+ /** Resolve a leaf path (/catalog/{courseId}/{lessonId}) to its playlist files. */
581
+ private resolveFiles;
558
582
  getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
559
583
  getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
560
- supportsDeviceFlow(): boolean;
561
584
  initiateDeviceFlow(): Promise<DeviceAuthorizationResponse | null>;
562
585
  pollDeviceFlowToken(deviceCode: string): Promise<DeviceFlowPollResult>;
563
586
  }
@@ -582,7 +605,7 @@ declare class CbnProvider implements IProvider {
582
605
  * range requests — plays in any standard mp4 player including
583
606
  * react-native-video.
584
607
  */
585
- declare class LifeChurchProvider implements IProvider {
608
+ declare class LifeChurchProvider extends BaseProvider {
586
609
  readonly id = "lifechurch";
587
610
  readonly name = "Life.Church";
588
611
  readonly logos: ProviderLogos;
@@ -592,12 +615,12 @@ declare class LifeChurchProvider implements IProvider {
592
615
  readonly capabilities: ProviderCapabilities;
593
616
  private data;
594
617
  private findSeries;
595
- private findUnit;
596
- private findLesson;
597
618
  private findScheduled;
598
619
  /** Resolve a scheduled-lesson reference to the underlying lesson + unit + series. */
599
620
  private resolveScheduled;
600
621
  private lessonToFile;
622
+ /** Resolve a leaf-or-unit path to its files plus the name/section used for instructions. */
623
+ private resolve;
601
624
  browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
602
625
  getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
603
626
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
@@ -605,7 +628,6 @@ declare class LifeChurchProvider implements IProvider {
605
628
  * Returns the most recent scheduled lesson from data.scheduledLessons.
606
629
  */
607
630
  getCurrentPlan(_auth?: ContentProviderAuthData | null): Promise<CurrentPlan | null>;
608
- supportsDeviceFlow(): boolean;
609
631
  }
610
632
 
611
633
  declare function getProvider(providerId: string): IProvider | null;
@@ -629,4 +651,4 @@ declare function getAvailableProviders(ids?: string[]): ProviderInfo[];
629
651
  */
630
652
  declare const VERSION: string;
631
653
 
632
- export { APlayProvider, type AuthType, B1ChurchProvider, BibleProjectProvider, CbnProvider, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, type CurrentPlan, type DeviceAuthorizationResponse, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type EndpointValue, type EndpointsConfig, type FeedActionInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, LifeChurchProvider, type MediaLicenseResult, type MediaLicenseStatus, type MessageFileInterface, type Plan, type PlanPresentation, type PlanSection, type PlanTimelineItem, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, isContentFile, isContentFolder, navigateToPath, registerProvider };
654
+ export { APlayProvider, type AuthType, B1ChurchProvider, BaseProvider, BibleProjectProvider, CbnProvider, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, type CurrentPlan, type DeviceAuthorizationResponse, DeviceFlowHelper, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type EndpointValue, type EndpointsConfig, type FeedActionInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, LifeChurchProvider, type MediaLicenseResult, type MediaLicenseStatus, type MessageFileInterface, OAuthHelper, type Plan, type PlanPresentation, type PlanSection, type PlanTimelineItem, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, isContentFile, isContentFolder, navigateToPath, registerProvider, toAuthData };
package/dist/index.d.ts CHANGED
@@ -19,7 +19,8 @@ interface ContentProviderConfig {
19
19
  scopes: string[];
20
20
  supportsDeviceFlow?: boolean;
21
21
  deviceAuthEndpoint?: string;
22
- endpoints: EndpointsConfig;
22
+ /** @deprecated URL templates now live in each provider; kept optional for type compatibility. */
23
+ endpoints?: EndpointsConfig;
23
24
  }
24
25
  interface DeviceAuthorizationResponse {
25
26
  device_code: string;
@@ -240,12 +241,54 @@ interface IProvider {
240
241
  */
241
242
  declare function navigateToPath(instructions: Instructions, path: string): InstructionItem | null;
242
243
 
244
+ declare class OAuthHelper {
245
+ generateCodeVerifier(): string;
246
+ generateCodeChallenge(verifier: string): Promise<string>;
247
+ buildAuthUrl(config: ContentProviderConfig, codeVerifier: string, redirectUri: string, state?: string): Promise<{
248
+ url: string;
249
+ challengeMethod: string;
250
+ }>;
251
+ exchangeCodeForTokens(config: ContentProviderConfig, _providerId: string, code: string, codeVerifier: string, redirectUri: string): Promise<ContentProviderAuthData | null>;
252
+ }
253
+
254
+ /** Map a raw OAuth token response to ContentProviderAuthData, stamping created_at. */
255
+ declare function toAuthData(data: Record<string, unknown>, fallbacks?: {
256
+ refreshToken?: string;
257
+ scope?: string;
258
+ }): ContentProviderAuthData;
243
259
  declare class TokenHelper {
244
260
  isAuthValid(auth: ContentProviderAuthData | null | undefined): boolean;
245
261
  isTokenExpired(auth: ContentProviderAuthData): boolean;
246
262
  refreshToken(config: ContentProviderConfig, auth: ContentProviderAuthData): Promise<ContentProviderAuthData | null>;
247
263
  }
248
264
 
265
+ declare class DeviceFlowHelper {
266
+ supportsDeviceFlow(config: ContentProviderConfig): boolean;
267
+ initiateDeviceFlow(config: ContentProviderConfig): Promise<DeviceAuthorizationResponse | null>;
268
+ pollDeviceFlowToken(config: ContentProviderConfig, deviceCode: string): Promise<DeviceFlowPollResult>;
269
+ calculatePollDelay(baseInterval?: number, slowDownCount?: number): number;
270
+ }
271
+
272
+ /**
273
+ * Shared base for providers: identity metadata, an authenticated fetch wrapper, and a
274
+ * config-driven supportsDeviceFlow. Auth-flow methods (initiateDeviceFlow, buildAuthUrl, ...)
275
+ * deliberately do NOT live here: consumers feature-detect them with `"method" in provider`,
276
+ * so they must exist only on the providers that actually support each flow.
277
+ */
278
+ declare abstract class BaseProvider implements IProvider {
279
+ abstract readonly id: string;
280
+ abstract readonly name: string;
281
+ abstract readonly logos: ProviderLogos;
282
+ abstract readonly config: ContentProviderConfig;
283
+ abstract readonly requiresAuth: boolean;
284
+ abstract readonly authTypes: AuthType[];
285
+ abstract readonly capabilities: ProviderCapabilities;
286
+ private readonly apiHelper;
287
+ protected apiRequest<T>(path: string, auth?: ContentProviderAuthData | null, method?: "GET" | "POST", body?: unknown): Promise<T | null>;
288
+ abstract browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
289
+ supportsDeviceFlow(): boolean;
290
+ }
291
+
249
292
  /**
250
293
  * APlay Provider
251
294
  *
@@ -256,9 +299,7 @@ declare class TokenHelper {
256
299
  * /modules/{moduleId}/products/{productId}/{libraryId} -> media files
257
300
  * /modules/{moduleId}/libraries/{libraryId} -> media files (if module has 0-1 products)
258
301
  */
259
- declare class APlayProvider implements IProvider {
260
- private readonly apiHelper;
261
- private apiRequest;
302
+ declare class APlayProvider extends BaseProvider {
262
303
  readonly id = "aplay";
263
304
  readonly name = "APlay";
264
305
  readonly logos: ProviderLogos;
@@ -274,7 +315,6 @@ declare class APlayProvider implements IProvider {
274
315
  getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
275
316
  getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
276
317
  checkMediaLicense(mediaId: string, auth?: ContentProviderAuthData | null): Promise<MediaLicenseResult | null>;
277
- supportsDeviceFlow(): boolean;
278
318
  }
279
319
 
280
320
  /**
@@ -284,11 +324,9 @@ declare class APlayProvider implements IProvider {
284
324
  * /playlists -> list playlists
285
325
  * /playlists/{playlistId} -> list messages (files)
286
326
  */
287
- declare class SignPresenterProvider implements IProvider {
288
- private readonly apiHelper;
327
+ declare class SignPresenterProvider extends BaseProvider {
289
328
  private readonly oauthHelper;
290
329
  private readonly deviceFlowHelper;
291
- private apiRequest;
292
330
  readonly id = "signpresenter";
293
331
  readonly name = "SignPresenter";
294
332
  readonly logos: ProviderLogos;
@@ -297,11 +335,11 @@ declare class SignPresenterProvider implements IProvider {
297
335
  readonly authTypes: AuthType[];
298
336
  readonly capabilities: ProviderCapabilities;
299
337
  browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
338
+ private extractList;
300
339
  private getPlaylists;
301
340
  private getMessages;
302
341
  getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
303
342
  getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
304
- supportsDeviceFlow(): boolean;
305
343
  generateCodeVerifier(): string;
306
344
  buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
307
345
  url: string;
@@ -326,7 +364,7 @@ declare class SignPresenterProvider implements IProvider {
326
364
  * /addons/{category} -> individual add-ons
327
365
  * /addons/{category}/{addOnId} -> single add-on file
328
366
  */
329
- declare class LessonsChurchProvider implements IProvider {
367
+ declare class LessonsChurchProvider extends BaseProvider {
330
368
  readonly id = "lessonschurch";
331
369
  readonly name = "Lessons.church";
332
370
  readonly logos: ProviderLogos;
@@ -347,14 +385,11 @@ declare class LessonsChurchProvider implements IProvider {
347
385
  private getAddOnCategories;
348
386
  private getAddOnsByCategory;
349
387
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
350
- supportsDeviceFlow(): boolean;
351
388
  }
352
389
 
353
- declare class B1ChurchProvider implements IProvider {
354
- private readonly apiHelper;
390
+ declare class B1ChurchProvider extends BaseProvider {
355
391
  private readonly deviceFlowHelper;
356
392
  private readonly externalContentCache;
357
- private apiRequest;
358
393
  readonly id = "b1church";
359
394
  readonly name = "B1.Church";
360
395
  readonly logos: ProviderLogos;
@@ -382,12 +417,10 @@ declare class B1ChurchProvider implements IProvider {
382
417
  private findItemByPath;
383
418
  private findPresentationByPath;
384
419
  getPlaylist(path: string, authData?: ContentProviderAuthData | null, resolution?: number): Promise<ContentFile[] | null>;
385
- supportsDeviceFlow(): boolean;
386
420
  }
387
421
 
388
- declare class DropboxProvider implements IProvider {
422
+ declare class DropboxProvider extends BaseProvider {
389
423
  private readonly oauthHelper;
390
- private readonly apiHelper;
391
424
  readonly id = "dropbox";
392
425
  readonly name = "Dropbox";
393
426
  readonly logos: ProviderLogos;
@@ -403,9 +436,10 @@ declare class DropboxProvider implements IProvider {
403
436
  private resolveFileLinks;
404
437
  private checkIsLeaf;
405
438
  browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
439
+ /** Resolve a folder path to playable files (list + media filter + link resolution). */
440
+ private resolveMediaFiles;
406
441
  getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
407
442
  getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
408
- supportsDeviceFlow(): boolean;
409
443
  generateCodeVerifier(): string;
410
444
  buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
411
445
  url: string;
@@ -424,14 +458,11 @@ declare class DropboxProvider implements IProvider {
424
458
  * /serviceTypes/{serviceTypeId} -> list plans
425
459
  * /serviceTypes/{serviceTypeId}/{planId} -> plan items (leaf)
426
460
  */
427
- declare class PlanningCenterProvider implements IProvider {
428
- private readonly apiHelper;
429
- private apiRequest;
461
+ declare class PlanningCenterProvider extends BaseProvider {
430
462
  readonly id = "planningcenter";
431
463
  readonly name = "Planning Center";
432
464
  readonly logos: ProviderLogos;
433
465
  readonly config: ContentProviderConfig;
434
- private readonly ONE_WEEK_MS;
435
466
  readonly requiresAuth = true;
436
467
  readonly authTypes: AuthType[];
437
468
  readonly capabilities: ProviderCapabilities;
@@ -439,7 +470,6 @@ declare class PlanningCenterProvider implements IProvider {
439
470
  private getServiceTypes;
440
471
  private getPlans;
441
472
  private getPlanItems;
442
- supportsDeviceFlow(): boolean;
443
473
  }
444
474
 
445
475
  /**
@@ -450,23 +480,22 @@ declare class PlanningCenterProvider implements IProvider {
450
480
  * /{collectionSlug} -> list videos in collection
451
481
  * /{collectionSlug}/{videoId} -> single video
452
482
  */
453
- declare class BibleProjectProvider implements IProvider {
483
+ declare class BibleProjectProvider extends BaseProvider {
454
484
  readonly id = "bibleproject";
455
485
  readonly name = "The Bible Project";
456
486
  readonly logos: ProviderLogos;
457
487
  readonly config: ContentProviderConfig;
458
- private data;
459
- private getMuxThumbnail;
460
488
  readonly requiresAuth = false;
461
489
  readonly authTypes: AuthType[];
462
490
  readonly capabilities: ProviderCapabilities;
491
+ private data;
492
+ private getMuxThumbnail;
493
+ private videoToFile;
494
+ /** Resolve a path to its collection and files: all videos at depth 1, a single video at depth 2. */
495
+ private resolve;
463
496
  browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
464
- private getCollections;
465
- private getLessonFolders;
466
- private getVideoFile;
467
497
  getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
468
498
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
469
- supportsDeviceFlow(): boolean;
470
499
  }
471
500
 
472
501
  /**
@@ -478,7 +507,7 @@ declare class BibleProjectProvider implements IProvider {
478
507
  * /{collectionSlug}/{studyId} -> list lessons
479
508
  * /{collectionSlug}/{studyId}/{lessonId} -> lesson files (leaf)
480
509
  */
481
- declare class HighVoltageKidsProvider implements IProvider {
510
+ declare class HighVoltageKidsProvider extends BaseProvider {
482
511
  readonly id = "highvoltagekids";
483
512
  readonly name = "High Voltage Kids";
484
513
  readonly logos: ProviderLogos;
@@ -490,7 +519,6 @@ declare class HighVoltageKidsProvider implements IProvider {
490
519
  browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
491
520
  getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
492
521
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
493
- supportsDeviceFlow(): boolean;
494
522
  }
495
523
 
496
524
  /**
@@ -504,7 +532,7 @@ declare class HighVoltageKidsProvider implements IProvider {
504
532
  * /{category}/{id} -> single video (feature film) or container children (series/collection)
505
533
  * /{category}/{...containerIds}/{id} -> nested containers or single video (supports arbitrary depth)
506
534
  */
507
- declare class JesusFilmProvider implements IProvider {
535
+ declare class JesusFilmProvider extends BaseProvider {
508
536
  readonly id = "jesusfilm";
509
537
  readonly name = "Jesus Film Project";
510
538
  readonly logos: ProviderLogos;
@@ -513,19 +541,19 @@ declare class JesusFilmProvider implements IProvider {
513
541
  readonly authTypes: AuthType[];
514
542
  readonly capabilities: ProviderCapabilities;
515
543
  private fetchApi;
544
+ private fetchCategoryComponents;
516
545
  browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
517
546
  private getCategories;
518
547
  private getItemsInCategory;
519
548
  private getVideoFile;
520
549
  private getContainerChildren;
521
550
  private extractMuxPlaybackId;
522
- getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
523
551
  private fetchVideoFiles;
524
552
  private fetchContainerVideoFiles;
553
+ getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
525
554
  private buildVideoInstructions;
526
555
  private buildContainerInstructions;
527
556
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
528
- supportsDeviceFlow(): boolean;
529
557
  }
530
558
 
531
559
  /**
@@ -539,10 +567,8 @@ declare class JesusFilmProvider implements IProvider {
539
567
  * /catalog/{courseId} -> lesson folders (GET /catalog/{courseId})
540
568
  * /catalog/{courseId}/{lessonId} -> video files (GET /lesson-playlist/{lessonId})
541
569
  */
542
- declare class CbnProvider implements IProvider {
543
- private readonly apiHelper;
570
+ declare class CbnProvider extends BaseProvider {
544
571
  private readonly deviceFlowHelper;
545
- private apiRequest;
546
572
  readonly id = "cbn";
547
573
  readonly name = "CBN";
548
574
  readonly logos: ProviderLogos;
@@ -551,13 +577,10 @@ declare class CbnProvider implements IProvider {
551
577
  readonly authTypes: AuthType[];
552
578
  readonly capabilities: ProviderCapabilities;
553
579
  browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
554
- private getCourses;
555
- private getLessons;
556
- private getVideos;
557
- private fetchPlaylist;
580
+ /** Resolve a leaf path (/catalog/{courseId}/{lessonId}) to its playlist files. */
581
+ private resolveFiles;
558
582
  getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
559
583
  getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
560
- supportsDeviceFlow(): boolean;
561
584
  initiateDeviceFlow(): Promise<DeviceAuthorizationResponse | null>;
562
585
  pollDeviceFlowToken(deviceCode: string): Promise<DeviceFlowPollResult>;
563
586
  }
@@ -582,7 +605,7 @@ declare class CbnProvider implements IProvider {
582
605
  * range requests — plays in any standard mp4 player including
583
606
  * react-native-video.
584
607
  */
585
- declare class LifeChurchProvider implements IProvider {
608
+ declare class LifeChurchProvider extends BaseProvider {
586
609
  readonly id = "lifechurch";
587
610
  readonly name = "Life.Church";
588
611
  readonly logos: ProviderLogos;
@@ -592,12 +615,12 @@ declare class LifeChurchProvider implements IProvider {
592
615
  readonly capabilities: ProviderCapabilities;
593
616
  private data;
594
617
  private findSeries;
595
- private findUnit;
596
- private findLesson;
597
618
  private findScheduled;
598
619
  /** Resolve a scheduled-lesson reference to the underlying lesson + unit + series. */
599
620
  private resolveScheduled;
600
621
  private lessonToFile;
622
+ /** Resolve a leaf-or-unit path to its files plus the name/section used for instructions. */
623
+ private resolve;
601
624
  browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
602
625
  getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
603
626
  getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
@@ -605,7 +628,6 @@ declare class LifeChurchProvider implements IProvider {
605
628
  * Returns the most recent scheduled lesson from data.scheduledLessons.
606
629
  */
607
630
  getCurrentPlan(_auth?: ContentProviderAuthData | null): Promise<CurrentPlan | null>;
608
- supportsDeviceFlow(): boolean;
609
631
  }
610
632
 
611
633
  declare function getProvider(providerId: string): IProvider | null;
@@ -629,4 +651,4 @@ declare function getAvailableProviders(ids?: string[]): ProviderInfo[];
629
651
  */
630
652
  declare const VERSION: string;
631
653
 
632
- export { APlayProvider, type AuthType, B1ChurchProvider, BibleProjectProvider, CbnProvider, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, type CurrentPlan, type DeviceAuthorizationResponse, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type EndpointValue, type EndpointsConfig, type FeedActionInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, LifeChurchProvider, type MediaLicenseResult, type MediaLicenseStatus, type MessageFileInterface, type Plan, type PlanPresentation, type PlanSection, type PlanTimelineItem, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, isContentFile, isContentFolder, navigateToPath, registerProvider };
654
+ export { APlayProvider, type AuthType, B1ChurchProvider, BaseProvider, BibleProjectProvider, CbnProvider, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, type CurrentPlan, type DeviceAuthorizationResponse, DeviceFlowHelper, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type EndpointValue, type EndpointsConfig, type FeedActionInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, LifeChurchProvider, type MediaLicenseResult, type MediaLicenseStatus, type MessageFileInterface, OAuthHelper, type Plan, type PlanPresentation, type PlanSection, type PlanTimelineItem, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, isContentFile, isContentFolder, navigateToPath, registerProvider, toAuthData };