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