@churchapps/content-providers 0.5.1 → 0.6.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/README.md +8 -2
- package/dist/index.cjs +49 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +49 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,8 +60,14 @@ import { BaseProvider, registerProvider } from '@churchapps/content-providers';
|
|
|
60
60
|
|
|
61
61
|
class MyProvider extends BaseProvider {
|
|
62
62
|
// Declare id/name/logos/config/requiresAuth/authTypes/capabilities and implement browse().
|
|
63
|
-
//
|
|
64
|
-
//
|
|
63
|
+
// Every declared authType/capability must be backed by its IProvider methods (enforced by
|
|
64
|
+
// tests/contentProviders.test.ts):
|
|
65
|
+
// oauth_pkce -> generateCodeVerifier / buildAuthUrl / buildAuthUrlFromChallenge / exchangeCodeForTokens
|
|
66
|
+
// (OAuthHelper implements the standard flow; delegate to it like SignPresenterProvider)
|
|
67
|
+
// device_flow -> initiateDeviceFlow / pollDeviceFlowToken (see DeviceFlowHelper)
|
|
68
|
+
// form_login -> performLogin
|
|
69
|
+
// playlist / instructions / mediaLicensing -> getPlaylist / getInstructions / checkMediaLicense
|
|
70
|
+
// The protected apiRequest() helper performs authenticated JSON fetches against config.apiBase.
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
registerProvider(new MyProvider());
|
package/dist/index.cjs
CHANGED
|
@@ -143,6 +143,9 @@ var OAuthHelper = class {
|
|
|
143
143
|
}
|
|
144
144
|
async buildAuthUrl(config, codeVerifier, redirectUri, state) {
|
|
145
145
|
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
146
|
+
return { url: this.buildAuthUrlFromChallenge(config, codeChallenge, redirectUri, state || ""), challengeMethod: "S256" };
|
|
147
|
+
}
|
|
148
|
+
buildAuthUrlFromChallenge(config, codeChallenge, redirectUri, state) {
|
|
146
149
|
const params = new URLSearchParams({
|
|
147
150
|
response_type: "code",
|
|
148
151
|
client_id: config.clientId,
|
|
@@ -150,9 +153,9 @@ var OAuthHelper = class {
|
|
|
150
153
|
scope: config.scopes.join(" "),
|
|
151
154
|
code_challenge: codeChallenge,
|
|
152
155
|
code_challenge_method: "S256",
|
|
153
|
-
state
|
|
156
|
+
state
|
|
154
157
|
});
|
|
155
|
-
return
|
|
158
|
+
return `${config.oauthBase}/authorize?${params.toString()}`;
|
|
156
159
|
}
|
|
157
160
|
async exchangeCodeForTokens(config, _providerId, code, codeVerifier, redirectUri) {
|
|
158
161
|
try {
|
|
@@ -334,12 +337,15 @@ function filesToInstructions(name, files, section) {
|
|
|
334
337
|
const items = section ? [{ id: section.id, itemType: "section", label: section.label ?? name, children: actions }] : actions;
|
|
335
338
|
return { name, items };
|
|
336
339
|
}
|
|
340
|
+
function instructionItemMediaType(item) {
|
|
341
|
+
return detectMediaType(`${item.downloadUrl || ""} ${item.label || ""}`, item.mediaType);
|
|
342
|
+
}
|
|
337
343
|
function instructionsToPlaylist(instructions) {
|
|
338
344
|
const files = [];
|
|
339
345
|
function extractFiles(items) {
|
|
340
346
|
for (const item of items) {
|
|
341
347
|
if (item.downloadUrl && (item.itemType === "file" || !item.children?.length)) {
|
|
342
|
-
files.push({ type: "file", id: item.id || item.relatedId || generateId(), title: item.label || "Untitled", mediaType:
|
|
348
|
+
files.push({ type: "file", id: item.id || item.relatedId || generateId(), title: item.label || "Untitled", mediaType: instructionItemMediaType(item), url: item.downloadUrl, downloadUrl: item.downloadUrl, seconds: item.seconds, thumbnail: item.thumbnail });
|
|
343
349
|
}
|
|
344
350
|
if (item.children) extractFiles(item.children);
|
|
345
351
|
}
|
|
@@ -449,6 +455,7 @@ function extractArray(response, ...keys) {
|
|
|
449
455
|
var APlayProvider = class extends BaseProvider {
|
|
450
456
|
constructor() {
|
|
451
457
|
super(...arguments);
|
|
458
|
+
this.oauthHelper = new OAuthHelper();
|
|
452
459
|
this.id = "aplay";
|
|
453
460
|
this.name = "APlay";
|
|
454
461
|
this.logos = { light: "https://www.joinamazing.com/_assets/v11/3ba846c5afd7e73d27bc4d87b63d423e7ae2dc73.svg", dark: "https://www.joinamazing.com/_assets/v11/3ba846c5afd7e73d27bc4d87b63d423e7ae2dc73.svg" };
|
|
@@ -518,6 +525,18 @@ var APlayProvider = class extends BaseProvider {
|
|
|
518
525
|
async checkMediaLicense(mediaId, auth) {
|
|
519
526
|
return checkMediaLicense(mediaId, auth);
|
|
520
527
|
}
|
|
528
|
+
generateCodeVerifier() {
|
|
529
|
+
return this.oauthHelper.generateCodeVerifier();
|
|
530
|
+
}
|
|
531
|
+
async buildAuthUrl(codeVerifier, redirectUri, state) {
|
|
532
|
+
return this.oauthHelper.buildAuthUrl(this.config, codeVerifier, redirectUri, state || this.id);
|
|
533
|
+
}
|
|
534
|
+
buildAuthUrlFromChallenge(codeChallenge, redirectUri, state) {
|
|
535
|
+
return this.oauthHelper.buildAuthUrlFromChallenge(this.config, codeChallenge, redirectUri, state);
|
|
536
|
+
}
|
|
537
|
+
async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
|
|
538
|
+
return this.oauthHelper.exchangeCodeForTokens(this.config, this.id, code, codeVerifier, redirectUri);
|
|
539
|
+
}
|
|
521
540
|
};
|
|
522
541
|
|
|
523
542
|
// src/providers/signPresenter/SignPresenterProvider.ts
|
|
@@ -602,6 +621,9 @@ var SignPresenterProvider = class extends BaseProvider {
|
|
|
602
621
|
async buildAuthUrl(codeVerifier, redirectUri, state) {
|
|
603
622
|
return this.oauthHelper.buildAuthUrl(this.config, codeVerifier, redirectUri, state || this.id);
|
|
604
623
|
}
|
|
624
|
+
buildAuthUrlFromChallenge(codeChallenge, redirectUri, state) {
|
|
625
|
+
return this.oauthHelper.buildAuthUrlFromChallenge(this.config, codeChallenge, redirectUri, state);
|
|
626
|
+
}
|
|
605
627
|
async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
|
|
606
628
|
return this.oauthHelper.exchangeCodeForTokens(this.config, this.id, code, codeVerifier, redirectUri);
|
|
607
629
|
}
|
|
@@ -974,8 +996,7 @@ function registerProvider(provider) {
|
|
|
974
996
|
}
|
|
975
997
|
|
|
976
998
|
// src/providers/b1Church/B1ChurchAuth.ts
|
|
977
|
-
|
|
978
|
-
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
999
|
+
function buildB1AuthUrlFromChallenge(config, appBase, redirectUri, codeChallenge, state) {
|
|
979
1000
|
const oauthParams = new URLSearchParams({
|
|
980
1001
|
response_type: "code",
|
|
981
1002
|
client_id: config.clientId,
|
|
@@ -983,10 +1004,13 @@ async function buildB1AuthUrl(config, appBase, redirectUri, codeVerifier, state)
|
|
|
983
1004
|
scope: config.scopes.join(" "),
|
|
984
1005
|
code_challenge: codeChallenge,
|
|
985
1006
|
code_challenge_method: "S256",
|
|
986
|
-
state
|
|
1007
|
+
state
|
|
987
1008
|
});
|
|
988
|
-
|
|
989
|
-
|
|
1009
|
+
return `${appBase}/oauth?${oauthParams.toString()}`;
|
|
1010
|
+
}
|
|
1011
|
+
async function buildB1AuthUrl(config, appBase, redirectUri, codeVerifier, state) {
|
|
1012
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
1013
|
+
return { url: buildB1AuthUrlFromChallenge(config, appBase, redirectUri, codeChallenge, state || ""), challengeMethod: "S256" };
|
|
990
1014
|
}
|
|
991
1015
|
async function exchangeCodeForTokensWithPKCE(config, code, redirectUri, codeVerifier) {
|
|
992
1016
|
try {
|
|
@@ -1218,6 +1242,7 @@ function collectFilesFromNode(node) {
|
|
|
1218
1242
|
id: node.id,
|
|
1219
1243
|
name: node.label || "",
|
|
1220
1244
|
url: node.downloadUrl,
|
|
1245
|
+
fileType: instructionItemMediaType(node),
|
|
1221
1246
|
seconds: node.seconds || 10
|
|
1222
1247
|
});
|
|
1223
1248
|
}
|
|
@@ -1283,6 +1308,9 @@ function findFirstThumbnail(items) {
|
|
|
1283
1308
|
}
|
|
1284
1309
|
return void 0;
|
|
1285
1310
|
}
|
|
1311
|
+
function isLessonsChurchContent(plan) {
|
|
1312
|
+
return !plan.providerId || plan.providerId === "lessonschurch";
|
|
1313
|
+
}
|
|
1286
1314
|
function isExternalProviderItem(item) {
|
|
1287
1315
|
if (!item.providerId || item.providerId === "b1church") return false;
|
|
1288
1316
|
if (item.providerPath) return true;
|
|
@@ -1309,10 +1337,16 @@ var B1ChurchProvider = class extends BaseProvider {
|
|
|
1309
1337
|
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
1310
1338
|
this.planTypeId = null;
|
|
1311
1339
|
}
|
|
1340
|
+
generateCodeVerifier() {
|
|
1341
|
+
return generateCodeVerifier();
|
|
1342
|
+
}
|
|
1312
1343
|
async buildAuthUrl(codeVerifier, redirectUri, state) {
|
|
1313
1344
|
return buildB1AuthUrl(this.config, this.appBase, redirectUri, codeVerifier, state);
|
|
1314
1345
|
}
|
|
1315
|
-
|
|
1346
|
+
buildAuthUrlFromChallenge(codeChallenge, redirectUri, state) {
|
|
1347
|
+
return buildB1AuthUrlFromChallenge(this.config, this.appBase, redirectUri, codeChallenge, state);
|
|
1348
|
+
}
|
|
1349
|
+
async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
|
|
1316
1350
|
return exchangeCodeForTokensWithPKCE(this.config, code, redirectUri, codeVerifier);
|
|
1317
1351
|
}
|
|
1318
1352
|
async exchangeCodeForTokensWithSecret(code, redirectUri, clientSecret) {
|
|
@@ -1448,7 +1482,7 @@ var B1ChurchProvider = class extends BaseProvider {
|
|
|
1448
1482
|
const planFolder = plans.find((p) => p.id === planId);
|
|
1449
1483
|
if (!planFolder) return null;
|
|
1450
1484
|
const churchId = planFolder.churchId;
|
|
1451
|
-
const venueId = planFolder.contentId;
|
|
1485
|
+
const venueId = isLessonsChurchContent(planFolder) ? planFolder.contentId : void 0;
|
|
1452
1486
|
const planTitle = planFolder.name || "Plan";
|
|
1453
1487
|
if (!churchId) {
|
|
1454
1488
|
console.warn("[B1Church getInstructions] planFolder missing churchId:", planFolder.id);
|
|
@@ -1557,7 +1591,7 @@ var B1ChurchProvider = class extends BaseProvider {
|
|
|
1557
1591
|
return null;
|
|
1558
1592
|
}
|
|
1559
1593
|
const churchId = planFolder.churchId;
|
|
1560
|
-
const venueId = planFolder.contentId;
|
|
1594
|
+
const venueId = isLessonsChurchContent(planFolder) ? planFolder.contentId : void 0;
|
|
1561
1595
|
if (!churchId) {
|
|
1562
1596
|
console.warn("[B1Church] getPlaylist: planFolder missing churchId:", planFolder.id);
|
|
1563
1597
|
return null;
|
|
@@ -1581,7 +1615,7 @@ var B1ChurchProvider = class extends BaseProvider {
|
|
|
1581
1615
|
const venueFeed = venueId ? await fetchVenueFeed(venueId) : null;
|
|
1582
1616
|
const files = [];
|
|
1583
1617
|
for (const sectionItem of planItems) {
|
|
1584
|
-
for (const child of sectionItem.children
|
|
1618
|
+
for (const child of sectionItem.children?.length ? sectionItem.children : [sectionItem]) {
|
|
1585
1619
|
const childItemType = child.itemType;
|
|
1586
1620
|
const isSectionType = childItemType === "section" || childItemType === "lessonSection" || childItemType === "providerSection";
|
|
1587
1621
|
const canExpandLocally = isSectionType && venueFeed && child.relatedId;
|
|
@@ -1897,7 +1931,8 @@ var PlanningCenterProvider = class extends BaseProvider {
|
|
|
1897
1931
|
this.logos = { light: "https://www.planningcenter.com/icons/icon-512x512.png", dark: "https://www.planningcenter.com/icons/icon-512x512.png" };
|
|
1898
1932
|
this.config = { id: "planningcenter", name: "Planning Center", apiBase: "https://api.planningcenteronline.com", oauthBase: "https://api.planningcenteronline.com/oauth", clientId: "", scopes: ["services"] };
|
|
1899
1933
|
this.requiresAuth = true;
|
|
1900
|
-
|
|
1934
|
+
// No client-side auth flow: clientId is unset and no PKCE methods exist. Auth tokens must be supplied externally (server-side).
|
|
1935
|
+
this.authTypes = [];
|
|
1901
1936
|
// Plan items come back without media URLs, so playlist/instructions are not actually supported yet.
|
|
1902
1937
|
this.capabilities = { browse: true, playlist: false, instructions: false, mediaLicensing: false };
|
|
1903
1938
|
}
|
|
@@ -16360,7 +16395,7 @@ function getAvailableProviders(ids) {
|
|
|
16360
16395
|
}
|
|
16361
16396
|
|
|
16362
16397
|
// src/index.ts
|
|
16363
|
-
var VERSION = true ? "0.
|
|
16398
|
+
var VERSION = true ? "0.6.0" : "dev";
|
|
16364
16399
|
// Annotate the CommonJS export names for ESM import in node:
|
|
16365
16400
|
0 && (module.exports = {
|
|
16366
16401
|
APlayProvider,
|