@churchapps/content-providers 0.1.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/LICENSE +21 -0
- package/README.md +101 -0
- package/dist/index.cjs +12882 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +671 -0
- package/dist/index.d.ts +671 -0
- package/dist/index.js +12825 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
interface ContentProviderAuthData {
|
|
2
|
+
access_token: string;
|
|
3
|
+
refresh_token: string;
|
|
4
|
+
token_type: string;
|
|
5
|
+
created_at: number;
|
|
6
|
+
expires_in: number;
|
|
7
|
+
scope: string;
|
|
8
|
+
}
|
|
9
|
+
/** A single endpoint value - either a static string or a function that generates a path */
|
|
10
|
+
type EndpointValue = string | ((...args: string[]) => string);
|
|
11
|
+
/** Configuration for provider API endpoints */
|
|
12
|
+
type EndpointsConfig = Record<string, EndpointValue>;
|
|
13
|
+
interface ContentProviderConfig {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
apiBase: string;
|
|
17
|
+
oauthBase: string;
|
|
18
|
+
clientId: string;
|
|
19
|
+
scopes: string[];
|
|
20
|
+
supportsDeviceFlow?: boolean;
|
|
21
|
+
deviceAuthEndpoint?: string;
|
|
22
|
+
endpoints: EndpointsConfig;
|
|
23
|
+
}
|
|
24
|
+
interface DeviceAuthorizationResponse {
|
|
25
|
+
device_code: string;
|
|
26
|
+
user_code: string;
|
|
27
|
+
verification_uri: string;
|
|
28
|
+
verification_uri_complete?: string;
|
|
29
|
+
expires_in: number;
|
|
30
|
+
interval?: number;
|
|
31
|
+
}
|
|
32
|
+
interface DeviceFlowState {
|
|
33
|
+
status: "loading" | "awaiting_user" | "polling" | "success" | "error" | "expired";
|
|
34
|
+
deviceAuth?: DeviceAuthorizationResponse;
|
|
35
|
+
error?: string;
|
|
36
|
+
pollCount?: number;
|
|
37
|
+
}
|
|
38
|
+
type AuthType = "none" | "oauth_pkce" | "device_flow" | "form_login";
|
|
39
|
+
interface ProviderLogos {
|
|
40
|
+
light: string;
|
|
41
|
+
dark: string;
|
|
42
|
+
}
|
|
43
|
+
interface ProviderInfo {
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
logos: ProviderLogos;
|
|
47
|
+
implemented: boolean;
|
|
48
|
+
requiresAuth: boolean;
|
|
49
|
+
authTypes: AuthType[];
|
|
50
|
+
capabilities: ProviderCapabilities;
|
|
51
|
+
}
|
|
52
|
+
interface ContentFolder {
|
|
53
|
+
type: "folder";
|
|
54
|
+
id: string;
|
|
55
|
+
title: string;
|
|
56
|
+
thumbnail?: string;
|
|
57
|
+
isLeaf?: boolean;
|
|
58
|
+
path: string;
|
|
59
|
+
}
|
|
60
|
+
interface ContentFile {
|
|
61
|
+
type: "file";
|
|
62
|
+
id: string;
|
|
63
|
+
title: string;
|
|
64
|
+
mediaType: "video" | "image";
|
|
65
|
+
thumbnail?: string;
|
|
66
|
+
url: string;
|
|
67
|
+
downloadUrl?: string;
|
|
68
|
+
muxPlaybackId?: string;
|
|
69
|
+
decryptionKey?: string;
|
|
70
|
+
mediaId?: string;
|
|
71
|
+
pingbackUrl?: string;
|
|
72
|
+
seconds?: number;
|
|
73
|
+
loop?: boolean;
|
|
74
|
+
loopVideo?: boolean;
|
|
75
|
+
streamUrl?: string;
|
|
76
|
+
/** Provider-specific metadata that varies by provider implementation */
|
|
77
|
+
providerData?: Record<string, unknown>;
|
|
78
|
+
}
|
|
79
|
+
type ContentItem = ContentFolder | ContentFile;
|
|
80
|
+
declare function isContentFolder(item: ContentItem): item is ContentFolder;
|
|
81
|
+
declare function isContentFile(item: ContentItem): item is ContentFile;
|
|
82
|
+
type DeviceFlowPollResult = ContentProviderAuthData | {
|
|
83
|
+
error: string;
|
|
84
|
+
shouldSlowDown?: boolean;
|
|
85
|
+
} | null;
|
|
86
|
+
interface PlanPresentation {
|
|
87
|
+
id: string;
|
|
88
|
+
name: string;
|
|
89
|
+
actionType: "play" | "other";
|
|
90
|
+
files: ContentFile[];
|
|
91
|
+
providerData?: Record<string, unknown>;
|
|
92
|
+
}
|
|
93
|
+
interface PlanSection {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
presentations: PlanPresentation[];
|
|
97
|
+
}
|
|
98
|
+
interface Plan {
|
|
99
|
+
id: string;
|
|
100
|
+
name: string;
|
|
101
|
+
description?: string;
|
|
102
|
+
thumbnail?: string;
|
|
103
|
+
sections: PlanSection[];
|
|
104
|
+
allFiles: ContentFile[];
|
|
105
|
+
}
|
|
106
|
+
interface FeedFileInterface {
|
|
107
|
+
id?: string;
|
|
108
|
+
name?: string;
|
|
109
|
+
url?: string;
|
|
110
|
+
streamUrl?: string;
|
|
111
|
+
seconds?: number;
|
|
112
|
+
fileType?: string;
|
|
113
|
+
thumbnail?: string;
|
|
114
|
+
}
|
|
115
|
+
interface FeedActionInterface {
|
|
116
|
+
id?: string;
|
|
117
|
+
actionType?: string;
|
|
118
|
+
content?: string;
|
|
119
|
+
files?: FeedFileInterface[];
|
|
120
|
+
}
|
|
121
|
+
interface FeedSectionInterface {
|
|
122
|
+
id?: string;
|
|
123
|
+
name?: string;
|
|
124
|
+
actions?: FeedActionInterface[];
|
|
125
|
+
}
|
|
126
|
+
interface FeedVenueInterface {
|
|
127
|
+
id?: string;
|
|
128
|
+
lessonId?: string;
|
|
129
|
+
name?: string;
|
|
130
|
+
lessonName?: string;
|
|
131
|
+
lessonDescription?: string;
|
|
132
|
+
lessonImage?: string;
|
|
133
|
+
sections?: FeedSectionInterface[];
|
|
134
|
+
}
|
|
135
|
+
interface InstructionItem {
|
|
136
|
+
id?: string;
|
|
137
|
+
itemType?: string;
|
|
138
|
+
relatedId?: string;
|
|
139
|
+
label?: string;
|
|
140
|
+
actionType?: string;
|
|
141
|
+
content?: string;
|
|
142
|
+
seconds?: number;
|
|
143
|
+
children?: InstructionItem[];
|
|
144
|
+
downloadUrl?: string;
|
|
145
|
+
thumbnail?: string;
|
|
146
|
+
}
|
|
147
|
+
interface Instructions {
|
|
148
|
+
name?: string;
|
|
149
|
+
items: InstructionItem[];
|
|
150
|
+
}
|
|
151
|
+
interface VenueActionInterface {
|
|
152
|
+
id?: string;
|
|
153
|
+
name?: string;
|
|
154
|
+
actionType?: string;
|
|
155
|
+
seconds?: number;
|
|
156
|
+
}
|
|
157
|
+
interface VenueSectionActionsInterface {
|
|
158
|
+
id?: string;
|
|
159
|
+
name?: string;
|
|
160
|
+
actions?: VenueActionInterface[];
|
|
161
|
+
}
|
|
162
|
+
interface VenueActionsResponseInterface {
|
|
163
|
+
venueName?: string;
|
|
164
|
+
sections?: VenueSectionActionsInterface[];
|
|
165
|
+
}
|
|
166
|
+
interface ProviderCapabilities {
|
|
167
|
+
browse: boolean;
|
|
168
|
+
presentations: boolean;
|
|
169
|
+
playlist: boolean;
|
|
170
|
+
instructions: boolean;
|
|
171
|
+
mediaLicensing: boolean;
|
|
172
|
+
}
|
|
173
|
+
type MediaLicenseStatus = "valid" | "expired" | "not_licensed" | "unknown";
|
|
174
|
+
interface MediaLicenseResult {
|
|
175
|
+
mediaId: string;
|
|
176
|
+
status: MediaLicenseStatus;
|
|
177
|
+
message?: string;
|
|
178
|
+
expiresAt?: string | number;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Core provider interface - all providers should implement this
|
|
182
|
+
*/
|
|
183
|
+
interface IProvider {
|
|
184
|
+
readonly id: string;
|
|
185
|
+
readonly name: string;
|
|
186
|
+
readonly logos: ProviderLogos;
|
|
187
|
+
readonly config: ContentProviderConfig;
|
|
188
|
+
readonly requiresAuth: boolean;
|
|
189
|
+
readonly capabilities: ProviderCapabilities;
|
|
190
|
+
readonly authTypes: AuthType[];
|
|
191
|
+
browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
192
|
+
supportsDeviceFlow(): boolean;
|
|
193
|
+
generateCodeVerifier?(): string;
|
|
194
|
+
buildAuthUrl?(codeVerifier: string, redirectUri: string, state?: string): Promise<{
|
|
195
|
+
url: string;
|
|
196
|
+
challengeMethod: string;
|
|
197
|
+
}>;
|
|
198
|
+
exchangeCodeForTokens?(code: string, codeVerifier: string, redirectUri: string): Promise<ContentProviderAuthData | null>;
|
|
199
|
+
initiateDeviceFlow?(): Promise<DeviceAuthorizationResponse | null>;
|
|
200
|
+
pollDeviceFlowToken?(deviceCode: string): Promise<DeviceFlowPollResult>;
|
|
201
|
+
getPlaylist?(path: string, auth?: ContentProviderAuthData | null, resolution?: number): Promise<ContentFile[] | null>;
|
|
202
|
+
getInstructions?(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
203
|
+
checkMediaLicense?(mediaId: string, auth?: ContentProviderAuthData | null): Promise<MediaLicenseResult | null>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
declare function detectMediaType(url: string, explicitType?: string): "video" | "image";
|
|
207
|
+
declare function createFolder(id: string, title: string, path: string, thumbnail?: string, isLeaf?: boolean): ContentFolder;
|
|
208
|
+
declare function createFile(id: string, title: string, url: string, options?: {
|
|
209
|
+
mediaType?: "video" | "image";
|
|
210
|
+
thumbnail?: string;
|
|
211
|
+
muxPlaybackId?: string;
|
|
212
|
+
seconds?: number;
|
|
213
|
+
loop?: boolean;
|
|
214
|
+
loopVideo?: boolean;
|
|
215
|
+
streamUrl?: string;
|
|
216
|
+
}): ContentFile;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Path parsing utilities for content providers.
|
|
220
|
+
* Paths follow the format: /segment1/segment2/segment3/...
|
|
221
|
+
* Example: /lessons/programId/studyId/lessonId/venueId
|
|
222
|
+
*/
|
|
223
|
+
interface ParsedPath {
|
|
224
|
+
segments: string[];
|
|
225
|
+
depth: number;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Parse a path string into segments and depth.
|
|
229
|
+
* @param path - The path to parse (e.g., "/lessons/abc123/def456")
|
|
230
|
+
* @returns Object with segments array and depth count
|
|
231
|
+
*/
|
|
232
|
+
declare function parsePath(path: string | null | undefined): ParsedPath;
|
|
233
|
+
/**
|
|
234
|
+
* Get a specific segment from a path by index.
|
|
235
|
+
* @param path - The path to parse
|
|
236
|
+
* @param index - Zero-based index of the segment to retrieve
|
|
237
|
+
* @returns The segment at the given index, or null if not found
|
|
238
|
+
*/
|
|
239
|
+
declare function getSegment(path: string | null | undefined, index: number): string | null;
|
|
240
|
+
/**
|
|
241
|
+
* Build a path string from segments.
|
|
242
|
+
* @param segments - Array of path segments
|
|
243
|
+
* @returns Path string with leading slash
|
|
244
|
+
*/
|
|
245
|
+
declare function buildPath(segments: string[]): string;
|
|
246
|
+
/**
|
|
247
|
+
* Append a segment to an existing path.
|
|
248
|
+
* @param basePath - The base path
|
|
249
|
+
* @param segment - The segment to append
|
|
250
|
+
* @returns New path with segment appended
|
|
251
|
+
*/
|
|
252
|
+
declare function appendToPath(basePath: string | null | undefined, segment: string): string;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Navigate to a specific item using a dot-notation path.
|
|
256
|
+
* Path format: "0.2.1" means items[0].children[2].children[1]
|
|
257
|
+
*/
|
|
258
|
+
declare function navigateToPath(instructions: Instructions, path: string): InstructionItem | null;
|
|
259
|
+
/**
|
|
260
|
+
* Generate a path string for an item given its position in the tree.
|
|
261
|
+
* Used when selecting an item to store its path.
|
|
262
|
+
*/
|
|
263
|
+
declare function generatePath(indices: number[]): string;
|
|
264
|
+
|
|
265
|
+
interface DurationEstimationConfig {
|
|
266
|
+
secondsPerImage: number;
|
|
267
|
+
wordsPerMinute: number;
|
|
268
|
+
}
|
|
269
|
+
declare const DEFAULT_DURATION_CONFIG: DurationEstimationConfig;
|
|
270
|
+
/**
|
|
271
|
+
* Count words in text (splits on whitespace)
|
|
272
|
+
*/
|
|
273
|
+
declare function countWords(text: string): number;
|
|
274
|
+
/**
|
|
275
|
+
* Estimate duration for image content
|
|
276
|
+
* @returns Duration in seconds (default: 15)
|
|
277
|
+
*/
|
|
278
|
+
declare function estimateImageDuration(config?: Partial<DurationEstimationConfig>): number;
|
|
279
|
+
/**
|
|
280
|
+
* Estimate duration for text content based on word count
|
|
281
|
+
* @param text - The text content
|
|
282
|
+
* @param config - Optional configuration overrides
|
|
283
|
+
* @returns Duration in seconds
|
|
284
|
+
*/
|
|
285
|
+
declare function estimateTextDuration(text: string, config?: Partial<DurationEstimationConfig>): number;
|
|
286
|
+
/**
|
|
287
|
+
* Estimate duration based on media type
|
|
288
|
+
* @param mediaType - "video" | "image" | "text"
|
|
289
|
+
* @param options - Text content or word count for text estimation
|
|
290
|
+
* @returns Duration in seconds (0 for video/unknown)
|
|
291
|
+
*/
|
|
292
|
+
declare function estimateDuration(mediaType: "video" | "image" | "text", options?: {
|
|
293
|
+
text?: string;
|
|
294
|
+
wordCount?: number;
|
|
295
|
+
config?: Partial<DurationEstimationConfig>;
|
|
296
|
+
}): number;
|
|
297
|
+
|
|
298
|
+
declare function presentationsToPlaylist(plan: Plan): ContentFile[];
|
|
299
|
+
declare function presentationsToExpandedInstructions(plan: Plan): Instructions;
|
|
300
|
+
declare function instructionsToPlaylist(instructions: Instructions): ContentFile[];
|
|
301
|
+
declare const expandedInstructionsToPlaylist: typeof instructionsToPlaylist;
|
|
302
|
+
declare function instructionsToPresentations(instructions: Instructions, planId?: string): Plan;
|
|
303
|
+
declare const expandedInstructionsToPresentations: typeof instructionsToPresentations;
|
|
304
|
+
declare function playlistToPresentations(files: ContentFile[], planName?: string, sectionName?: string): Plan;
|
|
305
|
+
declare function playlistToInstructions(files: ContentFile[], name?: string): Instructions;
|
|
306
|
+
declare const playlistToExpandedInstructions: typeof playlistToInstructions;
|
|
307
|
+
|
|
308
|
+
declare const FormatConverters_expandedInstructionsToPlaylist: typeof expandedInstructionsToPlaylist;
|
|
309
|
+
declare const FormatConverters_expandedInstructionsToPresentations: typeof expandedInstructionsToPresentations;
|
|
310
|
+
declare const FormatConverters_instructionsToPlaylist: typeof instructionsToPlaylist;
|
|
311
|
+
declare const FormatConverters_instructionsToPresentations: typeof instructionsToPresentations;
|
|
312
|
+
declare const FormatConverters_playlistToExpandedInstructions: typeof playlistToExpandedInstructions;
|
|
313
|
+
declare const FormatConverters_playlistToInstructions: typeof playlistToInstructions;
|
|
314
|
+
declare const FormatConverters_playlistToPresentations: typeof playlistToPresentations;
|
|
315
|
+
declare const FormatConverters_presentationsToExpandedInstructions: typeof presentationsToExpandedInstructions;
|
|
316
|
+
declare const FormatConverters_presentationsToPlaylist: typeof presentationsToPlaylist;
|
|
317
|
+
declare namespace FormatConverters {
|
|
318
|
+
export { FormatConverters_expandedInstructionsToPlaylist as expandedInstructionsToPlaylist, FormatConverters_expandedInstructionsToPresentations as expandedInstructionsToPresentations, FormatConverters_instructionsToPlaylist as instructionsToPlaylist, FormatConverters_instructionsToPresentations as instructionsToPresentations, FormatConverters_playlistToExpandedInstructions as playlistToExpandedInstructions, FormatConverters_playlistToInstructions as playlistToInstructions, FormatConverters_playlistToPresentations as playlistToPresentations, FormatConverters_presentationsToExpandedInstructions as presentationsToExpandedInstructions, FormatConverters_presentationsToPlaylist as presentationsToPlaylist };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
interface FormatResolverOptions {
|
|
322
|
+
allowLossy?: boolean;
|
|
323
|
+
}
|
|
324
|
+
interface ResolvedFormatMeta {
|
|
325
|
+
isNative: boolean;
|
|
326
|
+
sourceFormat?: "playlist" | "presentations" | "instructions";
|
|
327
|
+
isLossy: boolean;
|
|
328
|
+
}
|
|
329
|
+
declare class FormatResolver {
|
|
330
|
+
private provider;
|
|
331
|
+
private options;
|
|
332
|
+
constructor(provider: IProvider, options?: FormatResolverOptions);
|
|
333
|
+
getProvider(): IProvider;
|
|
334
|
+
/** Extract the last segment from a path to use as fallback ID/title */
|
|
335
|
+
private getIdFromPath;
|
|
336
|
+
getPlaylist(path: string, auth?: ContentProviderAuthData | null): Promise<ContentFile[] | null>;
|
|
337
|
+
getPlaylistWithMeta(path: string, auth?: ContentProviderAuthData | null): Promise<{
|
|
338
|
+
data: ContentFile[] | null;
|
|
339
|
+
meta: ResolvedFormatMeta;
|
|
340
|
+
}>;
|
|
341
|
+
getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
342
|
+
getInstructionsWithMeta(path: string, auth?: ContentProviderAuthData | null): Promise<{
|
|
343
|
+
data: Instructions | null;
|
|
344
|
+
meta: ResolvedFormatMeta;
|
|
345
|
+
}>;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
declare class OAuthHelper {
|
|
349
|
+
generateCodeVerifier(): string;
|
|
350
|
+
generateCodeChallenge(verifier: string): Promise<string>;
|
|
351
|
+
buildAuthUrl(config: ContentProviderConfig, codeVerifier: string, redirectUri: string, state?: string): Promise<{
|
|
352
|
+
url: string;
|
|
353
|
+
challengeMethod: string;
|
|
354
|
+
}>;
|
|
355
|
+
exchangeCodeForTokens(config: ContentProviderConfig, _providerId: string, code: string, codeVerifier: string, redirectUri: string): Promise<ContentProviderAuthData | null>;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
declare class TokenHelper {
|
|
359
|
+
isAuthValid(auth: ContentProviderAuthData | null | undefined): boolean;
|
|
360
|
+
isTokenExpired(auth: ContentProviderAuthData): boolean;
|
|
361
|
+
refreshToken(config: ContentProviderConfig, auth: ContentProviderAuthData): Promise<ContentProviderAuthData | null>;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
declare class DeviceFlowHelper {
|
|
365
|
+
supportsDeviceFlow(config: ContentProviderConfig): boolean;
|
|
366
|
+
initiateDeviceFlow(config: ContentProviderConfig): Promise<DeviceAuthorizationResponse | null>;
|
|
367
|
+
pollDeviceFlowToken(config: ContentProviderConfig, deviceCode: string): Promise<DeviceFlowPollResult>;
|
|
368
|
+
calculatePollDelay(baseInterval?: number, slowDownCount?: number): number;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
declare class ApiHelper {
|
|
372
|
+
createAuthHeaders(auth: ContentProviderAuthData | null | undefined): Record<string, string> | null;
|
|
373
|
+
apiRequest<T>(config: ContentProviderConfig, _providerId: string, path: string, auth?: ContentProviderAuthData | null, method?: "GET" | "POST", body?: unknown): Promise<T | null>;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* APlay Provider
|
|
378
|
+
*
|
|
379
|
+
* Path structure (variable depth based on module products):
|
|
380
|
+
* /modules -> list modules
|
|
381
|
+
* /modules/{moduleId} -> list products OR libraries (depends on module)
|
|
382
|
+
* /modules/{moduleId}/products/{productId} -> list libraries (if module has multiple products)
|
|
383
|
+
* /modules/{moduleId}/products/{productId}/{libraryId} -> media files
|
|
384
|
+
* /modules/{moduleId}/libraries/{libraryId} -> media files (if module has 0-1 products)
|
|
385
|
+
*/
|
|
386
|
+
declare class APlayProvider implements IProvider {
|
|
387
|
+
private readonly apiHelper;
|
|
388
|
+
private apiRequest;
|
|
389
|
+
readonly id = "aplay";
|
|
390
|
+
readonly name = "APlay";
|
|
391
|
+
readonly logos: ProviderLogos;
|
|
392
|
+
readonly config: ContentProviderConfig;
|
|
393
|
+
readonly requiresAuth = true;
|
|
394
|
+
readonly authTypes: AuthType[];
|
|
395
|
+
readonly capabilities: ProviderCapabilities;
|
|
396
|
+
browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
397
|
+
private getModules;
|
|
398
|
+
private getModuleContent;
|
|
399
|
+
private getLibraryFolders;
|
|
400
|
+
private getMediaFiles;
|
|
401
|
+
getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
|
|
402
|
+
getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
403
|
+
checkMediaLicense(mediaId: string, auth?: ContentProviderAuthData | null): Promise<MediaLicenseResult | null>;
|
|
404
|
+
supportsDeviceFlow(): boolean;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* SignPresenter Provider
|
|
409
|
+
*
|
|
410
|
+
* Path structure:
|
|
411
|
+
* /playlists -> list playlists
|
|
412
|
+
* /playlists/{playlistId} -> list messages (files)
|
|
413
|
+
*/
|
|
414
|
+
declare class SignPresenterProvider implements IProvider {
|
|
415
|
+
private readonly apiHelper;
|
|
416
|
+
private readonly oauthHelper;
|
|
417
|
+
private readonly deviceFlowHelper;
|
|
418
|
+
private apiRequest;
|
|
419
|
+
readonly id = "signpresenter";
|
|
420
|
+
readonly name = "SignPresenter";
|
|
421
|
+
readonly logos: ProviderLogos;
|
|
422
|
+
readonly config: ContentProviderConfig;
|
|
423
|
+
readonly requiresAuth = true;
|
|
424
|
+
readonly authTypes: AuthType[];
|
|
425
|
+
readonly capabilities: ProviderCapabilities;
|
|
426
|
+
browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
427
|
+
private getPlaylists;
|
|
428
|
+
private getMessages;
|
|
429
|
+
getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
|
|
430
|
+
getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
431
|
+
supportsDeviceFlow(): boolean;
|
|
432
|
+
generateCodeVerifier(): string;
|
|
433
|
+
buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
|
|
434
|
+
url: string;
|
|
435
|
+
challengeMethod: string;
|
|
436
|
+
}>;
|
|
437
|
+
exchangeCodeForTokens(code: string, codeVerifier: string, redirectUri: string): Promise<ContentProviderAuthData | null>;
|
|
438
|
+
initiateDeviceFlow(): Promise<DeviceAuthorizationResponse | null>;
|
|
439
|
+
pollDeviceFlowToken(deviceCode: string): Promise<DeviceFlowPollResult>;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* LessonsChurch Provider
|
|
444
|
+
*
|
|
445
|
+
* Path structure:
|
|
446
|
+
* /lessons -> programs
|
|
447
|
+
* /lessons/{programId} -> studies
|
|
448
|
+
* /lessons/{programId}/{studyId} -> lessons
|
|
449
|
+
* /lessons/{programId}/{studyId}/{lessonId} -> venues
|
|
450
|
+
* /lessons/{programId}/{studyId}/{lessonId}/{venueId} -> playlist files
|
|
451
|
+
*
|
|
452
|
+
* /addons -> categories
|
|
453
|
+
* /addons/{category} -> add-on files
|
|
454
|
+
*/
|
|
455
|
+
declare class LessonsChurchProvider implements IProvider {
|
|
456
|
+
readonly id = "lessonschurch";
|
|
457
|
+
readonly name = "Lessons.church";
|
|
458
|
+
readonly logos: ProviderLogos;
|
|
459
|
+
readonly config: ContentProviderConfig;
|
|
460
|
+
readonly requiresAuth = false;
|
|
461
|
+
readonly authTypes: AuthType[];
|
|
462
|
+
readonly capabilities: ProviderCapabilities;
|
|
463
|
+
getPlaylist(path: string, _auth?: ContentProviderAuthData | null, resolution?: number): Promise<ContentFile[] | null>;
|
|
464
|
+
browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
465
|
+
private browseLessons;
|
|
466
|
+
private getPrograms;
|
|
467
|
+
private getStudies;
|
|
468
|
+
private getLessons;
|
|
469
|
+
private getVenues;
|
|
470
|
+
private getPlaylistFiles;
|
|
471
|
+
private browseAddOns;
|
|
472
|
+
private getAddOnCategories;
|
|
473
|
+
private getAddOnsByCategory;
|
|
474
|
+
getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
475
|
+
supportsDeviceFlow(): boolean;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
declare class B1ChurchProvider implements IProvider {
|
|
479
|
+
private readonly apiHelper;
|
|
480
|
+
private readonly externalContentCache;
|
|
481
|
+
private apiRequest;
|
|
482
|
+
readonly id = "b1church";
|
|
483
|
+
readonly name = "B1.Church";
|
|
484
|
+
readonly logos: ProviderLogos;
|
|
485
|
+
readonly config: ContentProviderConfig;
|
|
486
|
+
private appBase;
|
|
487
|
+
readonly requiresAuth = true;
|
|
488
|
+
readonly authTypes: AuthType[];
|
|
489
|
+
readonly capabilities: ProviderCapabilities;
|
|
490
|
+
buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
|
|
491
|
+
url: string;
|
|
492
|
+
challengeMethod: string;
|
|
493
|
+
}>;
|
|
494
|
+
exchangeCodeForTokensWithPKCE(code: string, redirectUri: string, codeVerifier: string): Promise<ContentProviderAuthData | null>;
|
|
495
|
+
exchangeCodeForTokensWithSecret(code: string, redirectUri: string, clientSecret: string): Promise<ContentProviderAuthData | null>;
|
|
496
|
+
refreshTokenWithSecret(authData: ContentProviderAuthData, clientSecret: string): Promise<ContentProviderAuthData | null>;
|
|
497
|
+
initiateDeviceFlow(): Promise<DeviceAuthorizationResponse | null>;
|
|
498
|
+
pollDeviceFlowToken(deviceCode: string): Promise<DeviceFlowPollResult>;
|
|
499
|
+
browse(path?: string | null, authData?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
500
|
+
getInstructions(path: string, authData?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
501
|
+
private processInstructionItems;
|
|
502
|
+
private findItemByPath;
|
|
503
|
+
private findPresentationByPath;
|
|
504
|
+
getPlaylist(path: string, authData?: ContentProviderAuthData | null, resolution?: number): Promise<ContentFile[] | null>;
|
|
505
|
+
supportsDeviceFlow(): boolean;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
declare class DropboxProvider implements IProvider {
|
|
509
|
+
private readonly oauthHelper;
|
|
510
|
+
readonly id = "dropbox";
|
|
511
|
+
readonly name = "Dropbox";
|
|
512
|
+
readonly logos: ProviderLogos;
|
|
513
|
+
readonly config: ContentProviderConfig;
|
|
514
|
+
readonly requiresAuth = true;
|
|
515
|
+
readonly authTypes: AuthType[];
|
|
516
|
+
readonly capabilities: ProviderCapabilities;
|
|
517
|
+
private dropboxPost;
|
|
518
|
+
private listAllEntries;
|
|
519
|
+
private getSharedLink;
|
|
520
|
+
private sharedLinkToRawUrl;
|
|
521
|
+
private getTemporaryLink;
|
|
522
|
+
private resolveFileLinks;
|
|
523
|
+
private checkIsLeaf;
|
|
524
|
+
browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
525
|
+
getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
|
|
526
|
+
getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
527
|
+
supportsDeviceFlow(): boolean;
|
|
528
|
+
generateCodeVerifier(): string;
|
|
529
|
+
buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
|
|
530
|
+
url: string;
|
|
531
|
+
challengeMethod: string;
|
|
532
|
+
}>;
|
|
533
|
+
exchangeCodeForTokens(code: string, codeVerifier: string, redirectUri: string): Promise<ContentProviderAuthData | null>;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* PlanningCenter Provider
|
|
538
|
+
*
|
|
539
|
+
* Path structure:
|
|
540
|
+
* /serviceTypes -> list service types
|
|
541
|
+
* /serviceTypes/{serviceTypeId} -> list plans
|
|
542
|
+
* /serviceTypes/{serviceTypeId}/{planId} -> plan items (leaf)
|
|
543
|
+
*/
|
|
544
|
+
declare class PlanningCenterProvider implements IProvider {
|
|
545
|
+
private readonly apiHelper;
|
|
546
|
+
private apiRequest;
|
|
547
|
+
readonly id = "planningcenter";
|
|
548
|
+
readonly name = "Planning Center";
|
|
549
|
+
readonly logos: ProviderLogos;
|
|
550
|
+
readonly config: ContentProviderConfig;
|
|
551
|
+
private readonly ONE_WEEK_MS;
|
|
552
|
+
readonly requiresAuth = true;
|
|
553
|
+
readonly authTypes: AuthType[];
|
|
554
|
+
readonly capabilities: ProviderCapabilities;
|
|
555
|
+
browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
556
|
+
private getServiceTypes;
|
|
557
|
+
private getPlans;
|
|
558
|
+
private getPlanItems;
|
|
559
|
+
supportsDeviceFlow(): boolean;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* BibleProject Provider
|
|
564
|
+
*
|
|
565
|
+
* Path structure:
|
|
566
|
+
* / -> list collections
|
|
567
|
+
* /{collectionSlug} -> list videos in collection
|
|
568
|
+
* /{collectionSlug}/{videoId} -> single video
|
|
569
|
+
*/
|
|
570
|
+
declare class BibleProjectProvider implements IProvider {
|
|
571
|
+
readonly id = "bibleproject";
|
|
572
|
+
readonly name = "The Bible Project";
|
|
573
|
+
readonly logos: ProviderLogos;
|
|
574
|
+
readonly config: ContentProviderConfig;
|
|
575
|
+
private data;
|
|
576
|
+
readonly requiresAuth = false;
|
|
577
|
+
readonly authTypes: AuthType[];
|
|
578
|
+
readonly capabilities: ProviderCapabilities;
|
|
579
|
+
browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
580
|
+
private getCollections;
|
|
581
|
+
private getLessonFolders;
|
|
582
|
+
private getVideoFile;
|
|
583
|
+
getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
|
|
584
|
+
getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
585
|
+
supportsDeviceFlow(): boolean;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* HighVoltageKids Provider
|
|
590
|
+
*
|
|
591
|
+
* Path structure:
|
|
592
|
+
* / -> list collections (Elementary, Preschool)
|
|
593
|
+
* /{collectionSlug} -> list studies
|
|
594
|
+
* /{collectionSlug}/{studyId} -> list lessons
|
|
595
|
+
* /{collectionSlug}/{studyId}/{lessonId} -> lesson files (leaf)
|
|
596
|
+
*/
|
|
597
|
+
declare class HighVoltageKidsProvider implements IProvider {
|
|
598
|
+
readonly id = "highvoltagekids";
|
|
599
|
+
readonly name = "High Voltage Kids";
|
|
600
|
+
readonly logos: ProviderLogos;
|
|
601
|
+
readonly config: ContentProviderConfig;
|
|
602
|
+
private data;
|
|
603
|
+
readonly requiresAuth = false;
|
|
604
|
+
readonly authTypes: AuthType[];
|
|
605
|
+
readonly capabilities: ProviderCapabilities;
|
|
606
|
+
browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
607
|
+
getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
|
|
608
|
+
getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
609
|
+
supportsDeviceFlow(): boolean;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Jesus Film Project Provider
|
|
614
|
+
*
|
|
615
|
+
* Uses the public Arclight API to browse video content from jesusfilm.org.
|
|
616
|
+
*
|
|
617
|
+
* Path structure:
|
|
618
|
+
* / -> categories (Feature Films, Series, Collections)
|
|
619
|
+
* /{category} -> list items in category
|
|
620
|
+
* /{category}/{mediaComponentId} -> single video file
|
|
621
|
+
*/
|
|
622
|
+
declare class JesusFilmProvider implements IProvider {
|
|
623
|
+
readonly id = "jesusfilm";
|
|
624
|
+
readonly name = "Jesus Film Project";
|
|
625
|
+
readonly logos: ProviderLogos;
|
|
626
|
+
readonly config: ContentProviderConfig;
|
|
627
|
+
readonly requiresAuth = false;
|
|
628
|
+
readonly authTypes: AuthType[];
|
|
629
|
+
readonly capabilities: ProviderCapabilities;
|
|
630
|
+
private fetchApi;
|
|
631
|
+
browse(path?: string | null, _auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
632
|
+
private getCategories;
|
|
633
|
+
private getItemsInCategory;
|
|
634
|
+
private getVideoFile;
|
|
635
|
+
private extractMuxPlaybackId;
|
|
636
|
+
getPlaylist(path: string, _auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
|
|
637
|
+
private fetchVideoFiles;
|
|
638
|
+
getInstructions(path: string, _auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
639
|
+
supportsDeviceFlow(): boolean;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Get a provider by ID.
|
|
644
|
+
*/
|
|
645
|
+
declare function getProvider(providerId: string): IProvider | null;
|
|
646
|
+
/**
|
|
647
|
+
* Get all registered providers.
|
|
648
|
+
*/
|
|
649
|
+
declare function getAllProviders(): IProvider[];
|
|
650
|
+
/**
|
|
651
|
+
* Register a custom provider.
|
|
652
|
+
*/
|
|
653
|
+
declare function registerProvider(provider: IProvider): void;
|
|
654
|
+
/**
|
|
655
|
+
* Get provider configuration by ID (for backward compatibility).
|
|
656
|
+
*/
|
|
657
|
+
declare function getProviderConfig(providerId: string): ContentProviderConfig | null;
|
|
658
|
+
/**
|
|
659
|
+
* Get list of available providers with their info including logos and auth types.
|
|
660
|
+
* Includes both implemented providers and coming soon providers.
|
|
661
|
+
* @param ids - Optional array of provider IDs to filter the results. If provided, only providers with matching IDs will be returned.
|
|
662
|
+
*/
|
|
663
|
+
declare function getAvailableProviders(ids?: string[]): ProviderInfo[];
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* @churchapps/content-provider-helper
|
|
667
|
+
* Helper classes for interacting with third party content providers
|
|
668
|
+
*/
|
|
669
|
+
declare const VERSION = "0.0.5";
|
|
670
|
+
|
|
671
|
+
export { APlayProvider, ApiHelper, type AuthType, B1ChurchProvider, BibleProjectProvider, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, DEFAULT_DURATION_CONFIG, type DeviceAuthorizationResponse, DeviceFlowHelper, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type DurationEstimationConfig, type EndpointValue, type EndpointsConfig, type FeedActionInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, FormatConverters, FormatResolver, type FormatResolverOptions, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, type MediaLicenseResult, type MediaLicenseStatus, OAuthHelper, type Plan, type PlanPresentation, type PlanSection, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, type ResolvedFormatMeta, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, appendToPath, buildPath, countWords, createFile, createFolder, detectMediaType, estimateDuration, estimateImageDuration, estimateTextDuration, generatePath, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, getSegment, isContentFile, isContentFolder, navigateToPath, parsePath, registerProvider };
|