@youversion/platform-core 1.3.0 → 1.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @youversion/platform-core@1.3.0 build /home/runner/work/platform-sdk-react/platform-sdk-react/packages/core
2
+ > @youversion/platform-core@1.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 41.47 KB
12
- ESM ⚡️ Build success in 34ms
13
- CJS dist/index.cjs 43.29 KB
14
- CJS ⚡️ Build success in 35ms
11
+ ESM dist/index.js 41.76 KB
12
+ ESM ⚡️ Build success in 39ms
13
+ CJS dist/index.cjs 43.59 KB
14
+ CJS ⚡️ Build success in 40ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 1804ms
17
- DTS dist/index.d.cts 32.84 KB
18
- DTS dist/index.d.ts 32.84 KB
16
+ DTS ⚡️ Build success in 1818ms
17
+ DTS dist/index.d.cts 32.92 KB
18
+ DTS dist/index.d.ts 32.92 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @youversion/platform-core
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6ff47de: feat(core): add pagination to the getVersions endpoint
8
+ - update tests to ensure that proper amount of responses are returned
9
+ based on the page_size query param.
10
+ - add the ability to specify a page_size to fetch a specific number of
11
+ items at a time.
12
+
13
+ ## 1.4.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 8275a27: feat(ui): add bible reader settings
18
+ - refactor popover component to have consistent styling across
19
+ multiple components and reduce duplication in code.
20
+ - add bible reader settings and save the users settings to localStorage.
21
+
3
22
  ## 1.3.0
4
23
 
5
24
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -215,7 +215,7 @@ var BibleClient = class {
215
215
  * @param license_id - Optional license ID to filter versions by license.
216
216
  * @returns A promise that resolves to a collection of BibleVersion objects.
217
217
  */
218
- async getVersions(language_ranges, license_id) {
218
+ async getVersions(language_ranges, license_id, options) {
219
219
  const languageRangeArray = Array.isArray(language_ranges) ? language_ranges : [language_ranges];
220
220
  const parsedLanguageRanges = import_zod.z.array(this.languageRangesSchema).nonempty("At least one language range is required").parse(languageRangeArray);
221
221
  const params = {
@@ -224,6 +224,14 @@ var BibleClient = class {
224
224
  if (license_id !== void 0) {
225
225
  params.license_id = license_id;
226
226
  }
227
+ if (options?.page_size !== void 0) {
228
+ const pageSizeSchema = import_zod.z.number().int().positive();
229
+ pageSizeSchema.parse(options.page_size);
230
+ params.page_size = options.page_size;
231
+ }
232
+ if (options?.page_token !== void 0) {
233
+ params.page_token = options.page_token;
234
+ }
227
235
  return this.client.get(`/v1/bibles`, params);
228
236
  }
229
237
  /**
package/dist/index.d.cts CHANGED
@@ -338,7 +338,10 @@ declare class BibleClient {
338
338
  * @param license_id - Optional license ID to filter versions by license.
339
339
  * @returns A promise that resolves to a collection of BibleVersion objects.
340
340
  */
341
- getVersions(language_ranges: string | string[], license_id?: string | number): Promise<Collection<BibleVersion>>;
341
+ getVersions(language_ranges: string | string[], license_id?: string | number, options?: {
342
+ page_size?: number;
343
+ page_token?: string;
344
+ }): Promise<Collection<BibleVersion>>;
342
345
  /**
343
346
  * Fetches a Bible version by its ID.
344
347
  * @param id The version ID.
package/dist/index.d.ts CHANGED
@@ -338,7 +338,10 @@ declare class BibleClient {
338
338
  * @param license_id - Optional license ID to filter versions by license.
339
339
  * @returns A promise that resolves to a collection of BibleVersion objects.
340
340
  */
341
- getVersions(language_ranges: string | string[], license_id?: string | number): Promise<Collection<BibleVersion>>;
341
+ getVersions(language_ranges: string | string[], license_id?: string | number, options?: {
342
+ page_size?: number;
343
+ page_token?: string;
344
+ }): Promise<Collection<BibleVersion>>;
342
345
  /**
343
346
  * Fetches a Bible version by its ID.
344
347
  * @param id The version ID.
package/dist/index.js CHANGED
@@ -176,7 +176,7 @@ var BibleClient = class {
176
176
  * @param license_id - Optional license ID to filter versions by license.
177
177
  * @returns A promise that resolves to a collection of BibleVersion objects.
178
178
  */
179
- async getVersions(language_ranges, license_id) {
179
+ async getVersions(language_ranges, license_id, options) {
180
180
  const languageRangeArray = Array.isArray(language_ranges) ? language_ranges : [language_ranges];
181
181
  const parsedLanguageRanges = z.array(this.languageRangesSchema).nonempty("At least one language range is required").parse(languageRangeArray);
182
182
  const params = {
@@ -185,6 +185,14 @@ var BibleClient = class {
185
185
  if (license_id !== void 0) {
186
186
  params.license_id = license_id;
187
187
  }
188
+ if (options?.page_size !== void 0) {
189
+ const pageSizeSchema = z.number().int().positive();
190
+ pageSizeSchema.parse(options.page_size);
191
+ params.page_size = options.page_size;
192
+ }
193
+ if (options?.page_token !== void 0) {
194
+ params.page_token = options.page_token;
195
+ }
188
196
  return this.client.get(`/v1/bibles`, params);
189
197
  }
190
198
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youversion/platform-core",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -4,8 +4,8 @@ const baseBibleBooks = [
4
4
  {
5
5
  id: 'GEN',
6
6
  title: 'Genesis',
7
- full_title: 'The First Book of Moses, Called Genesis',
8
- abbreviation: 'Gen',
7
+ full_title: 'Genesis',
8
+ abbreviation: 'Gen.',
9
9
  canon: 'old_testament',
10
10
  chapters: mockGenesisChapters,
11
11
  },
@@ -27,6 +27,27 @@ describe('BibleClient', () => {
27
27
  });
28
28
 
29
29
  describe('getVersions', () => {
30
+ it('should fetch number of Bible versions specified by page_size param', async () => {
31
+ const versions = await bibleClient.getVersions('en*', undefined, { page_size: 11 });
32
+
33
+ expect(versions.data.length).toEqual(11);
34
+ });
35
+
36
+ it('should fetch next page using page_token from first response', async () => {
37
+ const firstPage = await bibleClient.getVersions('en*', undefined, { page_size: 5 });
38
+
39
+ expect(firstPage.data.length).toEqual(5);
40
+ expect(firstPage.next_page_token).toBeDefined();
41
+
42
+ const secondPage = await bibleClient.getVersions('en*', undefined, {
43
+ page_size: 5,
44
+ page_token: firstPage.next_page_token!,
45
+ });
46
+
47
+ expect(secondPage.data.length).toEqual(5);
48
+ expect(secondPage.data[0]?.id).not.toEqual(firstPage.data[0]?.id);
49
+ });
50
+
30
51
  it('should fetch Bible versions with language ranges', async () => {
31
52
  const versions = await bibleClient.getVersions('en*');
32
53
 
@@ -117,7 +138,7 @@ describe('BibleClient', () => {
117
138
 
118
139
  describe('getBooks', () => {
119
140
  it('should fetch all books for a version', async () => {
120
- const books = await bibleClient.getBooks(1);
141
+ const books = await bibleClient.getBooks(111);
121
142
 
122
143
  const { success } = BibleBookSchema.safeParse(books.data[0]);
123
144
  expect(success).toBe(true);
@@ -125,8 +146,8 @@ describe('BibleClient', () => {
125
146
  expect(books.data).toHaveLength(66);
126
147
  expect(books.data[0]).toHaveProperty('id', 'GEN');
127
148
  expect(books.data[0]).toHaveProperty('title', 'Genesis');
128
- expect(books.data[0]).toHaveProperty('full_title', 'The First Book of Moses, Called Genesis');
129
- expect(books.data[0]).toHaveProperty('abbreviation', 'Gen');
149
+ expect(books.data[0]).toHaveProperty('full_title', 'Genesis');
150
+ expect(books.data[0]).toHaveProperty('abbreviation', 'Gen.');
130
151
  expect(books.data[0]?.intro).toEqual({
131
152
  id: 'INTRO',
132
153
  passage_id: 'GEN.INTRO',
@@ -139,7 +160,7 @@ describe('BibleClient', () => {
139
160
 
140
161
  describe('getBook', () => {
141
162
  it('should fetch a specific book', async () => {
142
- const book = await bibleClient.getBook(1, 'GEN');
163
+ const book = await bibleClient.getBook(111, 'GEN');
143
164
 
144
165
  const { success } = BibleBookSchema.safeParse(book);
145
166
  expect(success).toBe(true);
@@ -147,7 +168,7 @@ describe('BibleClient', () => {
147
168
  expect(book.chapters).toHaveLength(50);
148
169
  expect(book).toHaveProperty('id', 'GEN');
149
170
  expect(book).toHaveProperty('title', 'Genesis');
150
- expect(book).toHaveProperty('abbreviation', 'Gen');
171
+ expect(book).toHaveProperty('abbreviation', 'Gen.');
151
172
  expect(book).toHaveProperty('intro');
152
173
  expect(book.intro).toEqual({
153
174
  id: 'INTRO',
@@ -106,11 +106,32 @@ export const handlers = [
106
106
  }),
107
107
 
108
108
  // Versions endpoints
109
- http.get(`https://${apiHost}/v1/bibles`, () => {
109
+ http.get(`https://${apiHost}/v1/bibles`, ({ request }) => {
110
+ const url = new URL(request.url);
111
+ const pageSize = url.searchParams.get('page_size');
112
+ const pageToken = url.searchParams.get('page_token');
113
+
114
+ const defaultPageSize = 25;
115
+ const size = pageSize ? parseInt(pageSize, 10) : defaultPageSize;
116
+ let start = 0;
117
+
118
+ if (pageToken) {
119
+ try {
120
+ const decoded = JSON.parse(atob(pageToken)) as { start?: number };
121
+ start = decoded.start || 0;
122
+ } catch {
123
+ start = 0;
124
+ }
125
+ }
126
+
127
+ const end = start + size;
128
+ const paginatedVersions = mockVersions.slice(start, end);
129
+ const hasMore = end < mockVersions.length;
130
+
110
131
  return HttpResponse.json({
111
- data: mockVersions,
112
- next_page_token: null,
113
- total_size: 14,
132
+ data: paginatedVersions,
133
+ next_page_token: hasMore ? btoa(JSON.stringify({ start: end })) : null,
134
+ total_size: mockVersions.length,
114
135
  });
115
136
  }),
116
137
 
@@ -127,7 +148,7 @@ export const handlers = [
127
148
  return HttpResponse.json(mockBibleGenesis);
128
149
  }),
129
150
 
130
- // Chaper endpoints
151
+ // Chapter endpoints
131
152
  http.get(`https://${apiHost}/v1/bibles/:bible_id/books/:book_id/chapters`, () => {
132
153
  return HttpResponse.json({ data: mockGenesisChapters });
133
154
  }),
@@ -32,7 +32,11 @@ describe('LanguagesClient', () => {
32
32
  const { success } = LanguageSchema.safeParse(languages.data[0]);
33
33
  expect(success).toBe(true);
34
34
  expect(languages.data).toHaveLength(20);
35
- expect(languages.data.every((language) => language.countries?.includes('US'))).toBe(true);
35
+ /** This is not true, it will always return the number provided in page_size
36
+ * and it will put the ones that have the country in their countries array
37
+ * at the top of the list.
38
+ */
39
+ // expect(languages.data.every((language) => language.countries?.includes('US'))).toBe(true);
36
40
  expect(languages.next_page_token).not.toBeNull();
37
41
  });
38
42
 
@@ -0,0 +1,29 @@
1
+ class LocalStorageMock {
2
+ private store: Record<string, string> = {};
3
+
4
+ getItem(key: string): string | null {
5
+ return this.store[key] ?? null;
6
+ }
7
+
8
+ setItem(key: string, value: string): void {
9
+ this.store[key] = value;
10
+ }
11
+
12
+ removeItem(key: string): void {
13
+ delete this.store[key];
14
+ }
15
+
16
+ clear(): void {
17
+ this.store = {};
18
+ }
19
+
20
+ get length(): number {
21
+ return Object.keys(this.store).length;
22
+ }
23
+
24
+ key(index: number): string | null {
25
+ return Object.keys(this.store)[index] ?? null;
26
+ }
27
+ }
28
+
29
+ globalThis.localStorage = new LocalStorageMock() as Storage;
package/src/bible.ts CHANGED
@@ -57,6 +57,7 @@ export class BibleClient {
57
57
  async getVersions(
58
58
  language_ranges: string | string[],
59
59
  license_id?: string | number,
60
+ options?: { page_size?: number; page_token?: string },
60
61
  ): Promise<Collection<BibleVersion>> {
61
62
  const languageRangeArray = Array.isArray(language_ranges) ? language_ranges : [language_ranges];
62
63
 
@@ -68,9 +69,20 @@ export class BibleClient {
68
69
  const params: Record<string, string | number | string[]> = {
69
70
  'language_ranges[]': parsedLanguageRanges,
70
71
  };
72
+
71
73
  if (license_id !== undefined) {
72
74
  params.license_id = license_id;
73
75
  }
76
+
77
+ if (options?.page_size !== undefined) {
78
+ const pageSizeSchema = z.number().int().positive();
79
+ pageSizeSchema.parse(options.page_size);
80
+ params.page_size = options.page_size;
81
+ }
82
+
83
+ if (options?.page_token !== undefined) {
84
+ params.page_token = options.page_token;
85
+ }
74
86
  return this.client.get<Collection<BibleVersion>>(`/v1/bibles`, params);
75
87
  }
76
88
 
package/vitest.config.ts CHANGED
@@ -3,7 +3,7 @@ import { defineConfig } from 'vitest/config';
3
3
  export default defineConfig({
4
4
  test: {
5
5
  environment: 'node',
6
- setupFiles: ['./src/__tests__/setup.ts'],
6
+ setupFiles: ['./src/__tests__/polyfills.ts', './src/__tests__/setup.ts'],
7
7
  testTimeout: 10_000,
8
8
  coverage: {
9
9
  provider: 'v8',