@churchapps/content-providers 0.6.0 → 0.6.1

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
@@ -16,6 +16,8 @@ interface ContentProviderConfig {
16
16
  apiBase: string;
17
17
  oauthBase: string;
18
18
  clientId: string;
19
+ /** For confidential OAuth clients (e.g. WP OAuth Server); sent on token exchange and refresh. */
20
+ clientSecret?: string;
19
21
  scopes: string[];
20
22
  supportsDeviceFlow?: boolean;
21
23
  deviceAuthEndpoint?: string;
@@ -393,7 +395,7 @@ declare class B1ChurchProvider extends BaseProvider {
393
395
  private fetchPlanImages;
394
396
  private planTypeId;
395
397
  setPairingData(data: unknown): void;
396
- getCurrentPlan(_authData?: ContentProviderAuthData | null): Promise<CurrentPlan | null>;
398
+ getCurrentPlan(authData?: ContentProviderAuthData | null): Promise<CurrentPlan | null>;
397
399
  getInstructions(path: string, authData?: ContentProviderAuthData | null): Promise<Instructions | null>;
398
400
  private processInstructionItems;
399
401
  private findItemByPath;
package/dist/index.d.ts CHANGED
@@ -16,6 +16,8 @@ interface ContentProviderConfig {
16
16
  apiBase: string;
17
17
  oauthBase: string;
18
18
  clientId: string;
19
+ /** For confidential OAuth clients (e.g. WP OAuth Server); sent on token exchange and refresh. */
20
+ clientSecret?: string;
19
21
  scopes: string[];
20
22
  supportsDeviceFlow?: boolean;
21
23
  deviceAuthEndpoint?: string;
@@ -393,7 +395,7 @@ declare class B1ChurchProvider extends BaseProvider {
393
395
  private fetchPlanImages;
394
396
  private planTypeId;
395
397
  setPairingData(data: unknown): void;
396
- getCurrentPlan(_authData?: ContentProviderAuthData | null): Promise<CurrentPlan | null>;
398
+ getCurrentPlan(authData?: ContentProviderAuthData | null): Promise<CurrentPlan | null>;
397
399
  getInstructions(path: string, authData?: ContentProviderAuthData | null): Promise<Instructions | null>;
398
400
  private processInstructionItems;
399
401
  private findItemByPath;
package/dist/index.js CHANGED
@@ -47,6 +47,7 @@ var TokenHelper = class {
47
47
  refresh_token: auth.refresh_token,
48
48
  client_id: config.clientId
49
49
  });
50
+ if (config.clientSecret) params.set("client_secret", config.clientSecret);
50
51
  const response = await fetch(`${config.oauthBase}/token`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString() });
51
52
  if (!response.ok) {
52
53
  console.warn(`[TokenHelper] Token refresh failed: ${response.status} ${response.statusText}`);
@@ -116,6 +117,7 @@ var OAuthHelper = class {
116
117
  client_id: config.clientId,
117
118
  code_verifier: codeVerifier
118
119
  });
120
+ if (config.clientSecret) params.set("client_secret", config.clientSecret);
119
121
  const tokenUrl = `${config.oauthBase}/token`;
120
122
  const response = await fetch(tokenUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString() });
121
123
  if (!response.ok) {
@@ -933,18 +935,6 @@ var LessonsChurchProvider = class extends BaseProvider {
933
935
  }
934
936
  };
935
937
 
936
- // src/providers/registry.ts
937
- var providerRegistry = /* @__PURE__ */ new Map();
938
- function getProvider(providerId) {
939
- return providerRegistry.get(providerId) || null;
940
- }
941
- function getAllProviders() {
942
- return Array.from(providerRegistry.values());
943
- }
944
- function registerProvider(provider) {
945
- providerRegistry.set(provider.id, provider);
946
- }
947
-
948
938
  // src/providers/b1Church/B1ChurchAuth.ts
949
939
  function buildB1AuthUrlFromChallenge(config, appBase, redirectUri, codeChallenge, state) {
950
940
  const oauthParams = new URLSearchParams({
@@ -1403,14 +1393,12 @@ var B1ChurchProvider = class extends BaseProvider {
1403
1393
  this.planTypeId = null;
1404
1394
  }
1405
1395
  }
1406
- async getCurrentPlan(_authData) {
1396
+ async getCurrentPlan(authData) {
1407
1397
  if (!this.planTypeId) return null;
1408
1398
  const plan = await fetchCurrentPlanByType(this.planTypeId);
1409
- if (!plan?.providerId || !plan.providerPlanId) return null;
1399
+ if (!plan?.providerId || !plan.providerPlanId || !plan.ministryId) return null;
1410
1400
  const items = plan.churchId && plan.id ? await fetchPlanItems(plan.churchId, plan.id) : [];
1411
- const innerProvider = getProvider(plan.providerId);
1412
- if (!innerProvider?.getInstructions) return null;
1413
- const instructions = await innerProvider.getInstructions(plan.providerPlanId, null);
1401
+ const instructions = await fetchFromProviderProxy("getInstructions", plan.ministryId, plan.providerId, plan.providerPlanId, authData);
1414
1402
  if (!instructions) return null;
1415
1403
  const files = getOrderedFiles(instructions, items);
1416
1404
  const thumbnail = findFirstThumbnail(instructions.items);
@@ -16253,6 +16241,110 @@ var LifeChurchProvider = class extends BaseProvider {
16253
16241
  }
16254
16242
  };
16255
16243
 
16244
+ // src/providers/registry.ts
16245
+ var providerRegistry = /* @__PURE__ */ new Map();
16246
+ function getProvider(providerId) {
16247
+ return providerRegistry.get(providerId) || null;
16248
+ }
16249
+ function getAllProviders() {
16250
+ return Array.from(providerRegistry.values());
16251
+ }
16252
+ function registerProvider(provider) {
16253
+ providerRegistry.set(provider.id, provider);
16254
+ }
16255
+
16256
+ // src/providers/goCurriculum/data.json
16257
+ var data_default4 = {
16258
+ collections: []
16259
+ };
16260
+
16261
+ // src/providers/goCurriculum/GoCurriculumProvider.ts
16262
+ var GoCurriculumProvider = class extends BaseProvider {
16263
+ constructor() {
16264
+ super(...arguments);
16265
+ this.oauthHelper = new OAuthHelper();
16266
+ this.verifiedTokens = /* @__PURE__ */ new Set();
16267
+ this.id = "gocurriculum";
16268
+ this.name = "Go Curriculum";
16269
+ this.logos = {
16270
+ light: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png",
16271
+ dark: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png"
16272
+ };
16273
+ this.config = {
16274
+ id: "gocurriculum",
16275
+ name: "Go Curriculum",
16276
+ apiBase: "https://gocurriculum.com",
16277
+ oauthBase: "https://gocurriculum.com/oauth",
16278
+ clientId: "Rdrvz9jz9nTNf8rCsbpuAgVLdoWHZmcjdmmrP0Bw",
16279
+ clientSecret: "yfAbd2NERjzwVZP38g1AALdIvPPXwhFayCguiTCS",
16280
+ scopes: ["basic"]
16281
+ };
16282
+ this.data = data_default4;
16283
+ this.requiresAuth = true;
16284
+ this.authTypes = ["oauth_pkce"];
16285
+ this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
16286
+ }
16287
+ // ponytail: any valid login unlocks everything for the pilot — per-tier (MemberPress) filtering waits on Go's membership endpoint
16288
+ async verifyAuth(auth) {
16289
+ const token = auth?.access_token;
16290
+ if (!token) return false;
16291
+ if (this.verifiedTokens.has(token)) return true;
16292
+ try {
16293
+ const response = await fetch(`${this.config.oauthBase}/me`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ access_token: token }).toString() });
16294
+ if (!response.ok) return false;
16295
+ this.verifiedTokens.add(token);
16296
+ return true;
16297
+ } catch {
16298
+ return false;
16299
+ }
16300
+ }
16301
+ async browse(path, auth) {
16302
+ if (!await this.verifyAuth(auth)) return [];
16303
+ const { segments, depth } = parsePath(path);
16304
+ if (depth === 0) return this.data.collections.map((c) => createFolder(c.id, c.name, `/${c.id}`, c.image));
16305
+ const collection = this.data.collections.find((c) => c.id === segments[0]);
16306
+ if (!collection) return [];
16307
+ if (depth === 1) return collection.lessons.map((l) => createFolder(l.id, l.name, `/${collection.id}/${l.id}`, l.image || collection.image, true));
16308
+ if (depth === 2) return this.getLessonFiles(collection, segments[1]);
16309
+ return [];
16310
+ }
16311
+ getLessonFiles(collection, lessonId) {
16312
+ const lesson = collection.lessons.find((l) => l.id === lessonId);
16313
+ if (!lesson) return [];
16314
+ return lesson.files.map((f) => createFile(f.id, f.name, f.url, { mediaType: detectMediaType(`${f.url} ${f.name}`, f.fileType), thumbnail: f.thumbnail || lesson.image || collection.image, seconds: f.seconds, loop: f.loop, loopVideo: f.loopVideo }));
16315
+ }
16316
+ async getPlaylist(path, auth, _resolution) {
16317
+ if (!await this.verifyAuth(auth)) return null;
16318
+ const { segments, depth } = parsePath(path);
16319
+ if (depth !== 2) return null;
16320
+ const collection = this.data.collections.find((c) => c.id === segments[0]);
16321
+ if (!collection) return null;
16322
+ const files = this.getLessonFiles(collection, segments[1]);
16323
+ return files.length > 0 ? files : null;
16324
+ }
16325
+ async getInstructions(path, auth) {
16326
+ const { segments, depth } = parsePath(path);
16327
+ if (depth !== 2) return null;
16328
+ const files = await this.getPlaylist(path, auth);
16329
+ if (!files) return null;
16330
+ const collection = this.data.collections.find((c) => c.id === segments[0]);
16331
+ const lesson = collection?.lessons.find((l) => l.id === segments[1]);
16332
+ return filesToInstructions(lesson?.name || "Lesson", files);
16333
+ }
16334
+ generateCodeVerifier() {
16335
+ return this.oauthHelper.generateCodeVerifier();
16336
+ }
16337
+ async buildAuthUrl(codeVerifier, redirectUri, state) {
16338
+ return this.oauthHelper.buildAuthUrl(this.config, codeVerifier, redirectUri, state || this.id);
16339
+ }
16340
+ buildAuthUrlFromChallenge(codeChallenge, redirectUri, state) {
16341
+ return this.oauthHelper.buildAuthUrlFromChallenge(this.config, codeChallenge, redirectUri, state);
16342
+ }
16343
+ async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
16344
+ return this.oauthHelper.exchangeCodeForTokens(this.config, this.id, code, codeVerifier, redirectUri);
16345
+ }
16346
+ };
16347
+
16256
16348
  // src/providers/index.ts
16257
16349
  var unimplementedProviders = [
16258
16350
  {
@@ -16271,14 +16363,6 @@ var unimplementedProviders = [
16271
16363
  dark: "https://freeshow.app/images/favicon.png"
16272
16364
  }
16273
16365
  },
16274
- {
16275
- id: "gocurriculum",
16276
- name: "Go Curriculum",
16277
- logos: {
16278
- light: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png",
16279
- dark: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png"
16280
- }
16281
- },
16282
16366
  {
16283
16367
  id: "iteachchurch",
16284
16368
  name: "iTeachChurch",
@@ -16301,6 +16385,7 @@ function initializeProviders() {
16301
16385
  new APlayProvider(),
16302
16386
  new B1ChurchProvider(),
16303
16387
  new DropboxProvider(),
16388
+ new GoCurriculumProvider(),
16304
16389
  new BibleProjectProvider(),
16305
16390
  new HighVoltageKidsProvider(),
16306
16391
  new JesusFilmProvider(),
@@ -16345,7 +16430,7 @@ function getAvailableProviders(ids) {
16345
16430
  }
16346
16431
 
16347
16432
  // src/index.ts
16348
- var VERSION = true ? "0.6.0" : "dev";
16433
+ var VERSION = true ? "0.6.1" : "dev";
16349
16434
  export {
16350
16435
  APlayProvider,
16351
16436
  B1ChurchProvider,