@youversion/platform-core 0.4.3 → 0.5.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/.env.example CHANGED
@@ -1,5 +1,5 @@
1
1
  # Your application ID from YouVersion Platform
2
2
  YVP_APP_KEY="ADD_YOUR_APP_KEY_HERE"
3
3
 
4
- # This should be left untouched unless you're helping test YouVersion's backend APIs.
4
+ # API host - defaults to production (api.youversion.com)
5
5
  YVP_API_HOST=api.youversion.com
@@ -1,5 +1,5 @@
1
1
 
2
- > @youversion/platform-core@0.4.3 build /home/runner/work/platform-sdk-react/platform-sdk-react/packages/core
2
+ > @youversion/platform-core@0.5.0 build /home/runner/work/platform-sdk-react/platform-sdk-react/packages/core
3
3
  > tsup src/index.ts --format cjs,esm --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -8,11 +8,11 @@
8
8
  CLI Target: es2022
9
9
  CJS Build start
10
10
  ESM Build start
11
- ESM dist/index.js 37.68 KB
11
+ ESM dist/index.js 37.59 KB
12
12
  ESM ⚡️ Build success in 37ms
13
- CJS dist/index.cjs 39.67 KB
13
+ CJS dist/index.cjs 39.59 KB
14
14
  CJS ⚡️ Build success in 37ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 2374ms
16
+ DTS ⚡️ Build success in 2331ms
17
17
  DTS dist/index.d.cts 34.08 KB
18
18
  DTS dist/index.d.ts 34.08 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @youversion/platform-core
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e07208d: feat(ui): add share button to verse of the day component
8
+
9
+ ## 0.4.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 8dee8f6: chore: allow setting apiHost from React code
14
+
3
15
  ## 0.4.3
4
16
 
5
17
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -56,11 +56,9 @@ var ApiClient = class {
56
56
  this.config = {
57
57
  ...config
58
58
  };
59
- const apiHost = config.apiHost ?? process.env.YVP_API_HOST ?? "api.youversion.com";
59
+ const apiHost = config.apiHost || "api.youversion.com";
60
60
  if (!apiHost) {
61
- throw new Error(
62
- "ApiClient requires a host name. Provide an apiHost in the config or set the YVP_API_HOST environment variable."
63
- );
61
+ throw new Error("ApiClient requires a host name. Provide an apiHost in the config.");
64
62
  }
65
63
  this.baseURL = "https://" + apiHost;
66
64
  this.timeout = config.timeout || 1e4;
package/dist/index.js CHANGED
@@ -13,11 +13,9 @@ var ApiClient = class {
13
13
  this.config = {
14
14
  ...config
15
15
  };
16
- const apiHost = config.apiHost ?? process.env.YVP_API_HOST ?? "api.youversion.com";
16
+ const apiHost = config.apiHost || "api.youversion.com";
17
17
  if (!apiHost) {
18
- throw new Error(
19
- "ApiClient requires a host name. Provide an apiHost in the config or set the YVP_API_HOST environment variable."
20
- );
18
+ throw new Error("ApiClient requires a host name. Provide an apiHost in the config.");
21
19
  }
22
20
  this.baseURL = "https://" + apiHost;
23
21
  this.timeout = config.timeout || 1e4;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youversion/platform-core",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -0,0 +1,95 @@
1
+ import type { Language } from '../types';
2
+
3
+ export const mockLanguages: Language[] = [
4
+ {
5
+ id: 'en',
6
+ language: 'en',
7
+ script: 'Latn',
8
+ script_name: 'Latin',
9
+ aliases: ['eng'],
10
+ display_names: { en: 'English' },
11
+ scripts: ['Latn'],
12
+ variants: [],
13
+ countries: ['US', 'GB', 'CA', 'AU'],
14
+ text_direction: 'ltr',
15
+ writing_population: 1500000000,
16
+ speaking_population: 1500000000,
17
+ default_bible_version_id: null,
18
+ },
19
+ {
20
+ id: 'es',
21
+ language: 'es',
22
+ script: 'Latn',
23
+ script_name: 'Latin',
24
+ aliases: ['spa'],
25
+ display_names: { en: 'Spanish', es: 'español' },
26
+ scripts: ['Latn'],
27
+ variants: [],
28
+ countries: ['ES', 'MX', 'AR', 'CO'],
29
+ text_direction: 'ltr',
30
+ writing_population: 500000000,
31
+ speaking_population: 500000000,
32
+ default_bible_version_id: null,
33
+ },
34
+ {
35
+ id: 'fr',
36
+ language: 'fr',
37
+ script: 'Latn',
38
+ script_name: 'Latin',
39
+ aliases: ['fra', 'fre'],
40
+ display_names: { en: 'French', fr: 'français' },
41
+ scripts: ['Latn'],
42
+ variants: [],
43
+ countries: ['FR', 'CA', 'BE', 'CH'],
44
+ text_direction: 'ltr',
45
+ writing_population: 300000000,
46
+ speaking_population: 300000000,
47
+ default_bible_version_id: null,
48
+ },
49
+ {
50
+ id: 'de',
51
+ language: 'de',
52
+ script: 'Latn',
53
+ script_name: 'Latin',
54
+ aliases: ['deu', 'ger'],
55
+ display_names: { en: 'German', de: 'Deutsch' },
56
+ scripts: ['Latn'],
57
+ variants: [],
58
+ countries: ['DE', 'AT', 'CH'],
59
+ text_direction: 'ltr',
60
+ writing_population: 100000000,
61
+ speaking_population: 100000000,
62
+ default_bible_version_id: null,
63
+ },
64
+ {
65
+ id: 'sr-Latn',
66
+ language: 'sr',
67
+ script: 'Latn',
68
+ script_name: 'latinica',
69
+ aliases: ['srp'],
70
+ display_names: { en: 'Serbian (Latin)', sr: 'srpski' },
71
+ scripts: ['Latn', 'Cyrl'],
72
+ variants: [],
73
+ countries: ['RS', 'BA', 'ME'],
74
+ text_direction: 'ltr',
75
+ writing_population: 8000000,
76
+ speaking_population: 8000000,
77
+ default_bible_version_id: null,
78
+ },
79
+ // Add more languages to reach 25 for default page size when filtering by 'US'
80
+ ...Array.from({ length: 24 }, (_, i) => ({
81
+ id: `lang${i + 1}`,
82
+ language: `lang${i + 1}`,
83
+ script: 'Latn',
84
+ script_name: null,
85
+ aliases: [],
86
+ display_names: {},
87
+ scripts: ['Latn'],
88
+ variants: [],
89
+ countries: ['US'],
90
+ text_direction: 'ltr' as const,
91
+ writing_population: 1000000,
92
+ speaking_population: 1000000,
93
+ default_bible_version_id: null,
94
+ })),
95
+ ];
@@ -14,6 +14,7 @@ describe('AuthClient', () => {
14
14
  global.fetch = vi.fn();
15
15
  apiClient = new ApiClient({
16
16
  appKey: 'test-app-key',
17
+ apiHost: process.env.YVP_API_HOST || '',
17
18
  });
18
19
  authClient = new AuthClient(apiClient);
19
20
  });
@@ -16,6 +16,7 @@ describe('BibleClient', () => {
16
16
 
17
17
  beforeEach(() => {
18
18
  apiClient = new ApiClient({
19
+ apiHost: process.env.YVP_API_HOST || '',
19
20
  appKey: process.env.YVP_APP_KEY || '',
20
21
  installationId: 'test-installation',
21
22
  });
@@ -1,5 +1,6 @@
1
1
  import { http, HttpResponse } from 'msw';
2
- import type { Collection, Highlight } from '../types';
2
+ import type { Collection, Highlight, Language } from '../types';
3
+ import { mockLanguages } from './MockLangauges';
3
4
 
4
5
  const apiHost = process.env.YVP_API_HOST;
5
6
  if (!apiHost) {
@@ -7,6 +8,54 @@ if (!apiHost) {
7
8
  }
8
9
 
9
10
  export const handlers = [
11
+ // Languages endpoints
12
+ http.get(`https://${apiHost}/v1/languages/:languageId`, ({ params }) => {
13
+ const { languageId } = params;
14
+ const language = mockLanguages.find((lang) => lang.id === languageId);
15
+
16
+ if (!language) {
17
+ return new HttpResponse(null, { status: 404 });
18
+ }
19
+
20
+ return HttpResponse.json(language);
21
+ }),
22
+
23
+ http.get(`https://${apiHost}/v1/languages`, ({ request }) => {
24
+ const url = new URL(request.url);
25
+ const country = url.searchParams.get('country');
26
+ const pageSize = url.searchParams.get('page_size');
27
+ const pageToken = url.searchParams.get('page_token');
28
+
29
+ const filteredLanguages = country
30
+ ? mockLanguages.filter((lang) => lang.countries?.includes(country))
31
+ : mockLanguages;
32
+
33
+ const defaultPageSize = 25;
34
+ const size = pageSize ? parseInt(pageSize, 10) : defaultPageSize;
35
+ let start = 0;
36
+
37
+ if (pageToken) {
38
+ try {
39
+ const decoded = JSON.parse(atob(pageToken)) as { start?: number };
40
+ start = decoded.start || 0;
41
+ } catch {
42
+ start = 0;
43
+ }
44
+ }
45
+
46
+ const end = start + size;
47
+ const paginatedLanguages = filteredLanguages.slice(start, end);
48
+ const hasMore = end < filteredLanguages.length;
49
+
50
+ const response: Collection<Language> = {
51
+ data: paginatedLanguages,
52
+ next_page_token: hasMore ? btoa(`{"start": ${end}}`) : null,
53
+ total_size: filteredLanguages.length,
54
+ };
55
+
56
+ return HttpResponse.json(response);
57
+ }),
58
+
10
59
  // Highlights endpoints
11
60
  http.get(`https://${apiHost}/v1/highlights`, ({ request }) => {
12
61
  const url = new URL(request.url);
@@ -9,6 +9,7 @@ describe('HighlightsClient', () => {
9
9
 
10
10
  beforeEach(() => {
11
11
  apiClient = new ApiClient({
12
+ apiHost: process.env.YVP_API_HOST || '',
12
13
  appKey: 'test-app',
13
14
  installationId: 'test-installation',
14
15
  });
@@ -9,6 +9,7 @@ describe('LanguagesClient', () => {
9
9
 
10
10
  beforeEach(() => {
11
11
  apiClient = new ApiClient({
12
+ apiHost: process.env.YVP_API_HOST || '',
12
13
  appKey: process.env.YVP_APP_KEY || '',
13
14
  installationId: 'test-installation',
14
15
  });
@@ -34,23 +35,6 @@ describe('LanguagesClient', () => {
34
35
  expect(languages.next_page_token).toBe('eyJzdGFydCI6IDEwfQ==');
35
36
  });
36
37
 
37
- it('should fetch languages with page_token option', async () => {
38
- const languages = await languagesClient.getLanguages({
39
- country: 'US',
40
- page_token: 'eyJzdGFydCI6IDEwMH0=',
41
- });
42
-
43
- const { success } = LanguageSchema.safeParse(languages.data[0]);
44
- expect(success).toBe(true);
45
- expect(languages.data).toHaveLength(25);
46
- });
47
-
48
- it('should uppercase country code', async () => {
49
- const languages = await languagesClient.getLanguages({ country: 'us' });
50
-
51
- expect(languages.data[0]?.countries).toContain('US');
52
- });
53
-
54
38
  it('should throw an error for invalid country code - empty string', async () => {
55
39
  await expect(languagesClient.getLanguages({ country: '' })).rejects.toThrow(
56
40
  'Country code must be a 2-character ISO 3166-1 alpha-2 code',
@@ -71,22 +55,6 @@ describe('LanguagesClient', () => {
71
55
  'Country code must be a 2-character ISO 3166-1 alpha-2 code',
72
56
  );
73
57
  });
74
-
75
- it('should throw an error for invalid page_size - zero', async () => {
76
- await expect(languagesClient.getLanguages({ country: 'US', page_size: 0 })).rejects.toThrow();
77
- });
78
-
79
- it('should throw an error for invalid page_size - negative', async () => {
80
- await expect(
81
- languagesClient.getLanguages({ country: 'US', page_size: -1 }),
82
- ).rejects.toThrow();
83
- });
84
-
85
- it('should throw an error for invalid page_size - non-integer', async () => {
86
- await expect(
87
- languagesClient.getLanguages({ country: 'US', page_size: 1.5 }),
88
- ).rejects.toThrow();
89
- });
90
58
  });
91
59
 
92
60
  describe('getLanguage', () => {
package/src/client.ts CHANGED
@@ -23,11 +23,9 @@ export class ApiClient {
23
23
  this.config = {
24
24
  ...config,
25
25
  };
26
- const apiHost = config.apiHost ?? process.env.YVP_API_HOST ?? 'api.youversion.com';
26
+ const apiHost = config.apiHost || 'api.youversion.com';
27
27
  if (!apiHost) {
28
- throw new Error(
29
- 'ApiClient requires a host name. Provide an apiHost in the config or set the YVP_API_HOST environment variable.',
30
- );
28
+ throw new Error('ApiClient requires a host name. Provide an apiHost in the config.');
31
29
  }
32
30
  this.baseURL = 'https://' + apiHost;
33
31
  this.timeout = config.timeout || 10000;