@churchapps/content-providers 0.10.0 → 0.11.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 CHANGED
@@ -52,6 +52,7 @@ const plan = await provider.getPresentations(serviceId);
52
52
  - **CbnProvider** - CBN Superbook curriculum
53
53
  - **HighVoltageKidsProvider** - High Voltage Kids curriculum (static catalog)
54
54
  - **LifeChurchProvider** - Life.Church kids curriculum (static catalog)
55
+ - **FreeShowProvider** - FreeShow shows discovered on the local network (mocked announcements playlist)
55
56
 
56
57
  ### Create a Custom Provider
57
58
 
@@ -66,6 +67,7 @@ class MyProvider extends BaseProvider {
66
67
  // (OAuthHelper implements the standard flow; delegate to it like SignPresenterProvider)
67
68
  // device_flow -> initiateDeviceFlow / pollDeviceFlowToken (see DeviceFlowHelper)
68
69
  // form_login -> performLogin
70
+ // network_discovery -> discoverInstances
69
71
  // playlist / instructions / mediaLicensing -> getPlaylist / getInstructions / checkMediaLicense
70
72
  // The protected apiRequest() helper performs authenticated JSON fetches against config.apiBase.
71
73
  }
package/dist/index.cjs CHANGED
@@ -27,16 +27,19 @@ __export(index_exports, {
27
27
  CbnProvider: () => CbnProvider,
28
28
  DeviceFlowHelper: () => DeviceFlowHelper,
29
29
  DropboxProvider: () => DropboxProvider,
30
+ FreeShowProvider: () => FreeShowProvider,
30
31
  HighVoltageKidsProvider: () => HighVoltageKidsProvider,
31
32
  JesusFilmProvider: () => JesusFilmProvider,
32
33
  LessonsChurchProvider: () => LessonsChurchProvider,
33
34
  LifeChurchProvider: () => LifeChurchProvider,
35
+ MOCK_FREESHOW_INSTANCE: () => MOCK_FREESHOW_INSTANCE,
34
36
  OAuthHelper: () => OAuthHelper,
35
37
  PlanningCenterProvider: () => PlanningCenterProvider,
36
38
  SignPresenterProvider: () => SignPresenterProvider,
37
39
  TokenHelper: () => TokenHelper,
38
40
  VERSION: () => VERSION,
39
41
  authIsExpired: () => authIsExpired,
42
+ authToNetworkInstance: () => authToNetworkInstance,
40
43
  getAllProviders: () => getAllProviders,
41
44
  getAvailableProviders: () => getAvailableProviders,
42
45
  getProvider: () => getProvider,
@@ -44,6 +47,7 @@ __export(index_exports, {
44
47
  isContentFile: () => isContentFile,
45
48
  isContentFolder: () => isContentFolder,
46
49
  navigateToPath: () => navigateToPath,
50
+ networkInstanceToAuth: () => networkInstanceToAuth,
47
51
  registerProvider: () => registerProvider,
48
52
  setProviderSecret: () => setProviderSecret,
49
53
  toAuthData: () => toAuthData
@@ -12581,6 +12585,255 @@ var CbnProvider = class extends BaseProvider {
12581
12585
  }
12582
12586
  };
12583
12587
 
12588
+ // src/providers/freeShow/announcements.show.json
12589
+ var announcements_show_default = [
12590
+ "2f357194dfc",
12591
+ {
12592
+ name: "Announcements",
12593
+ private: false,
12594
+ category: "presentation",
12595
+ settings: {
12596
+ activeLayout: "f2f357194df",
12597
+ template: "default"
12598
+ },
12599
+ timestamps: {
12600
+ created: 1769712923789,
12601
+ modified: 1769713271120,
12602
+ used: 1769713271120
12603
+ },
12604
+ quickAccess: {},
12605
+ meta: {},
12606
+ slides: {
12607
+ da7b854ee5b: {
12608
+ group: "Kids Theme Loop",
12609
+ color: null,
12610
+ settings: {},
12611
+ notes: "",
12612
+ items: []
12613
+ },
12614
+ "5a99fba3e52": {
12615
+ group: "Preteen Theme",
12616
+ color: null,
12617
+ settings: {},
12618
+ notes: "",
12619
+ items: []
12620
+ },
12621
+ "52d2ca79bcd": {
12622
+ group: "Kids Theme Transition to Virtue",
12623
+ color: null,
12624
+ settings: {},
12625
+ notes: "",
12626
+ items: []
12627
+ },
12628
+ cd55e66060b: {
12629
+ group: "Theme",
12630
+ color: null,
12631
+ settings: {},
12632
+ notes: "",
12633
+ items: []
12634
+ }
12635
+ },
12636
+ layouts: {
12637
+ f2f357194df: {
12638
+ name: "Default",
12639
+ notes: "",
12640
+ slides: [
12641
+ {
12642
+ id: "da7b854ee5b",
12643
+ background: "a7b854ee5bf",
12644
+ actions: { nextAfterMedia: true }
12645
+ },
12646
+ {
12647
+ id: "5a99fba3e52",
12648
+ background: "a99fba3e52d",
12649
+ nextTimer: 7
12650
+ },
12651
+ {
12652
+ id: "52d2ca79bcd",
12653
+ background: "2d2ca79bcd5",
12654
+ actions: { nextAfterMedia: true }
12655
+ },
12656
+ {
12657
+ id: "cd55e66060b",
12658
+ background: "d55e66060b8",
12659
+ nextTimer: 7,
12660
+ end: true
12661
+ }
12662
+ ]
12663
+ }
12664
+ },
12665
+ media: {
12666
+ a7b854ee5bf: {
12667
+ name: "Kids Theme Loop",
12668
+ path: "https://stream.mux.com/kDsWzEqyN7TDoMM3Aykfq1QhEo01JhCWO7t2sABictzk/capped-1080p.mp4",
12669
+ type: "video",
12670
+ contentProvider: "amazinglife",
12671
+ muted: false,
12672
+ loop: false
12673
+ },
12674
+ a99fba3e52d: {
12675
+ name: "Preteen Theme",
12676
+ path: "https://www.datocms-assets.com/75190/1746649082-2507_screen_preteen_theme.jpg",
12677
+ type: "image",
12678
+ contentProvider: "amazinglife"
12679
+ },
12680
+ "2d2ca79bcd5": {
12681
+ name: "Kids Theme Transition to Virtue",
12682
+ path: "https://stream.mux.com/101lB00Wj00AMUsjbuNYkNofkNHQXpZeThL3mFZNsSB5A00/capped-1080p.mp4",
12683
+ type: "video",
12684
+ contentProvider: "amazinglife",
12685
+ muted: false,
12686
+ loop: false
12687
+ },
12688
+ d55e66060b8: {
12689
+ name: "Theme",
12690
+ path: "https://www.datocms-assets.com/75190/1746648669-2507_screen_kids_theme.jpg",
12691
+ type: "image",
12692
+ contentProvider: "amazinglife"
12693
+ }
12694
+ }
12695
+ }
12696
+ ];
12697
+
12698
+ // src/providers/freeShow/FreeShowInterfaces.ts
12699
+ var DEFAULT_SLIDE_SECONDS = 5;
12700
+
12701
+ // src/providers/freeShow/FreeShowConverters.ts
12702
+ var MOCK_FREESHOW_INSTANCE = {
12703
+ id: "mock-local",
12704
+ name: "This PC",
12705
+ host: "localhost",
12706
+ ip: "127.0.0.1",
12707
+ port: 5505
12708
+ };
12709
+ function parseShowExport(raw) {
12710
+ if (Array.isArray(raw) && raw.length >= 2 && typeof raw[0] === "string" && raw[1] && typeof raw[1] === "object") {
12711
+ return { id: raw[0], show: raw[1] };
12712
+ }
12713
+ if (raw && typeof raw === "object" && "layouts" in raw && "media" in raw) {
12714
+ const show = raw;
12715
+ return { id: show.id || "show", show };
12716
+ }
12717
+ return null;
12718
+ }
12719
+ function slideSeconds(ref, mediaType) {
12720
+ if (typeof ref.nextTimer === "number" && ref.nextTimer > 0) return ref.nextTimer;
12721
+ if (ref.actions?.nextAfterMedia && mediaType === "video") return void 0;
12722
+ return DEFAULT_SLIDE_SECONDS;
12723
+ }
12724
+ function showToFiles(show) {
12725
+ const layoutId = show.settings?.activeLayout || Object.keys(show.layouts || {})[0];
12726
+ const layout = layoutId ? show.layouts?.[layoutId] : void 0;
12727
+ const refs = layout?.slides || [];
12728
+ const loops = refs.some((ref) => ref.end === true);
12729
+ const files = [];
12730
+ for (const ref of refs) {
12731
+ if (ref.disabled || !ref.background) continue;
12732
+ const media = show.media?.[ref.background];
12733
+ const path = media?.path;
12734
+ if (!path) continue;
12735
+ const mediaType = detectMediaType(path, media?.type);
12736
+ const slide = show.slides?.[ref.id];
12737
+ const title = media?.name || slide?.group || "Slide";
12738
+ files.push(createFile(ref.id, title, path, {
12739
+ mediaType,
12740
+ thumbnail: mediaType === "image" ? path : void 0,
12741
+ seconds: slideSeconds(ref, mediaType),
12742
+ loop: loops,
12743
+ loopVideo: false
12744
+ }));
12745
+ }
12746
+ return files;
12747
+ }
12748
+ function showToFolder(id, show) {
12749
+ const files = showToFiles(show);
12750
+ const thumbnail = files.find((file) => file.mediaType === "image")?.url || files[0]?.thumbnail;
12751
+ return createFolder(id, show.name || "Show", `/${id}`, thumbnail, true);
12752
+ }
12753
+ function networkInstanceToAuth(instance) {
12754
+ return {
12755
+ access_token: instance.id,
12756
+ refresh_token: JSON.stringify(instance),
12757
+ token_type: "network",
12758
+ created_at: Math.floor(Date.now() / 1e3),
12759
+ expires_in: 10 * 365 * 24 * 3600,
12760
+ scope: "freeshow"
12761
+ };
12762
+ }
12763
+ function authToNetworkInstance(auth) {
12764
+ if (!auth?.refresh_token) return null;
12765
+ try {
12766
+ const parsed = JSON.parse(auth.refresh_token);
12767
+ if (parsed?.id && parsed?.name) return parsed;
12768
+ } catch {
12769
+ return null;
12770
+ }
12771
+ return null;
12772
+ }
12773
+
12774
+ // src/providers/freeShow/FreeShowProvider.ts
12775
+ var parsedMock = parseShowExport(announcements_show_default);
12776
+ var MOCK_SHOW_ID = parsedMock?.id || "announcements";
12777
+ var MOCK_SHOW = parsedMock?.show || { name: "Announcements", layouts: {}, media: {}, slides: {} };
12778
+ var FreeShowProvider = class extends BaseProvider {
12779
+ constructor() {
12780
+ super(...arguments);
12781
+ this.id = "freeshow";
12782
+ this.name = "FreeShow";
12783
+ this.logos = {
12784
+ light: "https://freeshow.app/images/favicon.png",
12785
+ dark: "https://freeshow.app/images/favicon.png"
12786
+ };
12787
+ this.config = {
12788
+ id: "freeshow",
12789
+ name: "FreeShow",
12790
+ apiBase: "",
12791
+ oauthBase: "",
12792
+ clientId: "",
12793
+ scopes: []
12794
+ };
12795
+ this.requiresAuth = true;
12796
+ this.authTypes = ["network_discovery"];
12797
+ this.capabilities = {
12798
+ browse: true,
12799
+ playlist: true,
12800
+ instructions: true,
12801
+ mediaLicensing: false
12802
+ };
12803
+ this.discoverer = null;
12804
+ }
12805
+ setDiscoverer(discoverer) {
12806
+ this.discoverer = discoverer;
12807
+ }
12808
+ async discoverInstances() {
12809
+ if (this.discoverer) return this.discoverer();
12810
+ await new Promise((resolve) => setTimeout(resolve, 600));
12811
+ return [MOCK_FREESHOW_INSTANCE];
12812
+ }
12813
+ toAuth(instance) {
12814
+ return networkInstanceToAuth(instance);
12815
+ }
12816
+ selectedInstance(auth) {
12817
+ return authToNetworkInstance(auth);
12818
+ }
12819
+ async browse(path, _auth) {
12820
+ const { depth } = parsePath(path);
12821
+ if (depth === 0) return [showToFolder(MOCK_SHOW_ID, MOCK_SHOW)];
12822
+ return [];
12823
+ }
12824
+ async getPlaylist(path, _auth, _resolution) {
12825
+ const { segments, depth } = parsePath(path);
12826
+ if (depth < 1 || segments[0] !== MOCK_SHOW_ID) return null;
12827
+ const files = showToFiles(MOCK_SHOW);
12828
+ return files.length > 0 ? files : null;
12829
+ }
12830
+ async getInstructions(path, auth) {
12831
+ const files = await this.getPlaylist(path, auth);
12832
+ if (!files) return null;
12833
+ return filesToInstructions(MOCK_SHOW.name || "Show", files);
12834
+ }
12835
+ };
12836
+
12584
12837
  // src/providers/lifeChurch/data.json
12585
12838
  var data_default3 = {
12586
12839
  generatedAt: "2026-05-09T20:14:53.089Z",
@@ -17985,14 +18238,6 @@ var unimplementedProviders = [
17985
18238
  dark: "https://www.awana.org/wp-content/uploads/2025/04/awana-logo-white.svg"
17986
18239
  }
17987
18240
  },
17988
- {
17989
- id: "freeshow",
17990
- name: "FreeShow",
17991
- logos: {
17992
- light: "https://freeshow.app/images/favicon.png",
17993
- dark: "https://freeshow.app/images/favicon.png"
17994
- }
17995
- },
17996
18241
  {
17997
18242
  id: "iteachchurch",
17998
18243
  name: "iTeachChurch",
@@ -18024,7 +18269,8 @@ function initializeProviders() {
18024
18269
  new LifeChurchProvider(),
18025
18270
  new PlanningCenterProvider(),
18026
18271
  new SignPresenterProvider(),
18027
- new CbnProvider()
18272
+ new CbnProvider(),
18273
+ new FreeShowProvider()
18028
18274
  ];
18029
18275
  for (const provider of providers) registerProvider(provider);
18030
18276
  }
@@ -18061,7 +18307,7 @@ function getAvailableProviders(ids) {
18061
18307
  }
18062
18308
 
18063
18309
  // src/index.ts
18064
- var VERSION = true ? "0.10.0" : "dev";
18310
+ var VERSION = true ? "0.11.0" : "dev";
18065
18311
  // Annotate the CommonJS export names for ESM import in node:
18066
18312
  0 && (module.exports = {
18067
18313
  APlayProvider,
@@ -18071,16 +18317,19 @@ var VERSION = true ? "0.10.0" : "dev";
18071
18317
  CbnProvider,
18072
18318
  DeviceFlowHelper,
18073
18319
  DropboxProvider,
18320
+ FreeShowProvider,
18074
18321
  HighVoltageKidsProvider,
18075
18322
  JesusFilmProvider,
18076
18323
  LessonsChurchProvider,
18077
18324
  LifeChurchProvider,
18325
+ MOCK_FREESHOW_INSTANCE,
18078
18326
  OAuthHelper,
18079
18327
  PlanningCenterProvider,
18080
18328
  SignPresenterProvider,
18081
18329
  TokenHelper,
18082
18330
  VERSION,
18083
18331
  authIsExpired,
18332
+ authToNetworkInstance,
18084
18333
  getAllProviders,
18085
18334
  getAvailableProviders,
18086
18335
  getProvider,
@@ -18088,6 +18337,7 @@ var VERSION = true ? "0.10.0" : "dev";
18088
18337
  isContentFile,
18089
18338
  isContentFolder,
18090
18339
  navigateToPath,
18340
+ networkInstanceToAuth,
18091
18341
  registerProvider,
18092
18342
  setProviderSecret,
18093
18343
  toAuthData