payment-kit 1.18.45 → 1.18.47

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.
@@ -0,0 +1,549 @@
1
+ // This helps generate pagination test cases
2
+
3
+ import { mergePaginate, defaultTimeOrderBy, DataSource } from '../../src/libs/pagination';
4
+
5
+ describe('mergePaginate', () => {
6
+ // Create test data source
7
+ const createTestDataSource = (items: any[]): DataSource<any> => ({
8
+ count: () => Promise.resolve(items.length),
9
+ fetch: (limit: number, offset: number = 0) => Promise.resolve(items.slice(offset, offset + limit)),
10
+ meta: {
11
+ type: 'database',
12
+ cacheable: false,
13
+ },
14
+ });
15
+
16
+ // Create test data source for sorting tests (cached type to enable in-memory sorting)
17
+ const createSortingTestDataSource = (items: any[]): DataSource<any> => ({
18
+ count: () => Promise.resolve(items.length),
19
+ fetch: (limit: number, offset: number = 0) => Promise.resolve(items.slice(offset, offset + limit)),
20
+ meta: {
21
+ type: 'cached',
22
+ cacheable: true,
23
+ },
24
+ });
25
+
26
+ // Create pre-sorted database data source (simulates database with ORDER BY)
27
+ const createSortedDatabaseDataSource = (items: any[], orderBy: (a: any, b: any) => number): DataSource<any> => {
28
+ const sortedItems = [...items].sort(orderBy);
29
+ return {
30
+ count: () => Promise.resolve(sortedItems.length),
31
+ fetch: (limit: number, offset: number = 0) => Promise.resolve(sortedItems.slice(offset, offset + limit)),
32
+ meta: {
33
+ type: 'database',
34
+ cacheable: false,
35
+ },
36
+ };
37
+ };
38
+
39
+ // Create test items
40
+ const createTestItems = (count: number, baseDate: Date = new Date()) => {
41
+ return Array.from({ length: count }, (_, i) => ({
42
+ id: `id_${i}`,
43
+ created_at: new Date(baseDate.getTime() + i * 1000).toISOString(),
44
+ value: i,
45
+ }));
46
+ };
47
+
48
+ describe('Single Data Source', () => {
49
+ it('should handle empty data source', async () => {
50
+ const source = createTestDataSource([]);
51
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy());
52
+
53
+ expect(result).toEqual({
54
+ total: 0,
55
+ data: [],
56
+ paging: {
57
+ page: 1,
58
+ pageSize: 10,
59
+ totalPages: 0,
60
+ },
61
+ });
62
+ });
63
+
64
+ it('should handle single data source with pagination', async () => {
65
+ const items = createTestItems(25);
66
+ const source = createTestDataSource(items);
67
+
68
+ const result = await mergePaginate([source], { page: 2, pageSize: 10 }, defaultTimeOrderBy());
69
+
70
+ expect(result.total).toBe(25);
71
+ expect(result.data).toHaveLength(10);
72
+ expect(result.paging).toEqual({
73
+ page: 2,
74
+ pageSize: 10,
75
+ totalPages: 3,
76
+ });
77
+ expect(result.data[0].value).toBe(10); // First item of second page
78
+ });
79
+
80
+ it('should handle single data source with empty page', async () => {
81
+ const items = createTestItems(5);
82
+ const source = createTestDataSource(items);
83
+
84
+ const result = await mergePaginate([source], { page: 2, pageSize: 10 }, defaultTimeOrderBy());
85
+
86
+ expect(result.total).toBe(5);
87
+ expect(result.data).toHaveLength(0);
88
+ expect(result.paging).toEqual({
89
+ page: 2,
90
+ pageSize: 10,
91
+ totalPages: 1,
92
+ });
93
+ });
94
+
95
+ it('should handle page size larger than total items', async () => {
96
+ const items = createTestItems(5);
97
+ const source = createTestDataSource(items);
98
+
99
+ const result = await mergePaginate([source], { page: 1, pageSize: 20 }, defaultTimeOrderBy());
100
+
101
+ expect(result.total).toBe(5);
102
+ expect(result.data).toHaveLength(5);
103
+ expect(result.paging).toEqual({
104
+ page: 1,
105
+ pageSize: 20,
106
+ totalPages: 1,
107
+ });
108
+ });
109
+
110
+ it('should handle page number out of range', async () => {
111
+ const items = createTestItems(15);
112
+ const source = createTestDataSource(items);
113
+
114
+ // Page number out of range
115
+ const result1 = await mergePaginate([source], { page: 0, pageSize: 10 }, defaultTimeOrderBy());
116
+ expect(result1.paging.page).toBe(1); // Should be corrected to first page
117
+ expect(result1.data).toHaveLength(10);
118
+
119
+ // Page number too large
120
+ const result2 = await mergePaginate([source], { page: 100, pageSize: 10 }, defaultTimeOrderBy());
121
+ expect(result2.paging.page).toBe(100);
122
+ expect(result2.data).toHaveLength(0);
123
+ });
124
+
125
+ it('should handle page size of 0', async () => {
126
+ const items = createTestItems(10);
127
+ const source = createTestDataSource(items);
128
+
129
+ const result = await mergePaginate([source], { page: 1, pageSize: 0 }, defaultTimeOrderBy());
130
+
131
+ expect(result.total).toBe(10);
132
+ expect(result.data).toHaveLength(10);
133
+ expect(result.paging).toEqual({
134
+ page: 1,
135
+ pageSize: 0,
136
+ totalPages: 1,
137
+ });
138
+ });
139
+
140
+ it('should return all data when pageSize is 0', async () => {
141
+ const items = createTestItems(10);
142
+ const source = createTestDataSource(items);
143
+
144
+ const result = await mergePaginate([source], { page: 1, pageSize: 0 }, defaultTimeOrderBy());
145
+
146
+ expect(result.total).toBe(10);
147
+ expect(result.data).toHaveLength(10);
148
+ expect(result.paging).toEqual({
149
+ page: 1,
150
+ pageSize: 0,
151
+ totalPages: 1,
152
+ });
153
+ });
154
+
155
+ it('should return all data when pageSize is undefined', async () => {
156
+ const items = createTestItems(10);
157
+ const source = createTestDataSource(items);
158
+
159
+ const result = await mergePaginate([source], { page: 1, pageSize: undefined as any }, defaultTimeOrderBy());
160
+
161
+ expect(result.total).toBe(10);
162
+ expect(result.data).toHaveLength(10);
163
+ expect(result.paging).toEqual({
164
+ page: 1,
165
+ pageSize: 0,
166
+ totalPages: 1,
167
+ });
168
+ });
169
+
170
+ it('should return all data from multiple sources when pageSize is 0', async () => {
171
+ const baseDate = new Date('2024-01-01T00:00:00Z');
172
+ const source1 = createTestDataSource(createTestItems(5, baseDate));
173
+ const source2 = createTestDataSource(createTestItems(5, new Date(baseDate.getTime() + 5000)));
174
+
175
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 0 }, defaultTimeOrderBy());
176
+
177
+ expect(result.total).toBe(10);
178
+ expect(result.data).toHaveLength(10);
179
+ expect(result.paging).toEqual({
180
+ page: 1,
181
+ pageSize: 0,
182
+ totalPages: 1,
183
+ });
184
+ });
185
+ });
186
+
187
+ describe('Multiple Data Sources', () => {
188
+ it('should merge multiple data sources correctly', async () => {
189
+ const baseDate = new Date('2024-01-01T00:00:00Z');
190
+ const items1 = [
191
+ { id: 'id_1', created_at: new Date(baseDate.getTime() + 1000).toISOString(), value: 1 },
192
+ { id: 'id_2', created_at: new Date(baseDate.getTime() + 2000).toISOString(), value: 2 },
193
+ ];
194
+ const items2 = [
195
+ { id: 'id_3', created_at: new Date(baseDate.getTime() + 3000).toISOString(), value: 3 },
196
+ { id: 'id_4', created_at: new Date(baseDate.getTime() + 4000).toISOString(), value: 4 },
197
+ ];
198
+
199
+ // Create pre-sorted database sources (simulating ORDER BY in database)
200
+ const orderBy = defaultTimeOrderBy('desc');
201
+ const source1 = createSortedDatabaseDataSource(items1, orderBy);
202
+ const source2 = createSortedDatabaseDataSource(items2, orderBy);
203
+
204
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, orderBy);
205
+
206
+ expect(result.total).toBe(4);
207
+ expect(result.data).toHaveLength(4);
208
+ expect(result.data[0].value).toBe(4); // Latest item should be first
209
+ expect(result.data[3].value).toBe(1); // Oldest item should be last
210
+ });
211
+
212
+ it('should handle pagination across multiple sources', async () => {
213
+ const baseDate = new Date('2024-01-01T00:00:00Z');
214
+ const items1 = createTestItems(5, baseDate);
215
+ const items2 = createTestItems(5, new Date(baseDate.getTime() + 5000));
216
+
217
+ // For pagination test, we can use default database sources since we're testing pagination logic
218
+ const source1 = createTestDataSource(items1);
219
+ const source2 = createTestDataSource(items2);
220
+
221
+ const result = await mergePaginate([source1, source2], { page: 2, pageSize: 3 }, defaultTimeOrderBy());
222
+
223
+ expect(result.total).toBe(10);
224
+ expect(result.data).toHaveLength(3);
225
+ expect(result.paging).toEqual({
226
+ page: 2,
227
+ pageSize: 3,
228
+ totalPages: 4,
229
+ });
230
+ });
231
+
232
+ it('should handle sources with different types', async () => {
233
+ const baseDate = new Date('2024-01-01T00:00:00Z');
234
+ const source1 = createTestDataSource(createTestItems(5, baseDate));
235
+ const source2: DataSource<any> = {
236
+ count: () => Promise.resolve(3),
237
+ fetch: (limit: number, offset: number = 0) =>
238
+ Promise.resolve(createTestItems(3, new Date(baseDate.getTime() + 10000)).slice(offset, offset + limit)),
239
+ meta: {
240
+ type: 'computed',
241
+ estimatedSize: 3,
242
+ cacheable: true,
243
+ },
244
+ };
245
+
246
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, defaultTimeOrderBy());
247
+
248
+ expect(result.total).toBe(8);
249
+ expect(result.data).toHaveLength(8);
250
+ });
251
+
252
+ it('should handle error in data source gracefully', async () => {
253
+ const source1 = createTestDataSource(createTestItems(5));
254
+ const source2: DataSource<any> = {
255
+ count: () => Promise.reject(new Error('Count error')),
256
+ fetch: () => Promise.reject(new Error('Fetch error')),
257
+ meta: {
258
+ type: 'database',
259
+ cacheable: false,
260
+ },
261
+ };
262
+
263
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, defaultTimeOrderBy());
264
+
265
+ expect(result.total).toBe(5);
266
+ expect(result.data).toHaveLength(5);
267
+ });
268
+
269
+ it('should handle empty data sources in the middle', async () => {
270
+ const baseDate = new Date('2024-01-01T00:00:00Z');
271
+ const source1 = createTestDataSource(createTestItems(5, baseDate));
272
+ const source2 = createTestDataSource([]);
273
+ const source3 = createTestDataSource(createTestItems(5, new Date(baseDate.getTime() + 5000)));
274
+
275
+ const result = await mergePaginate([source1, source2, source3], { page: 1, pageSize: 10 }, defaultTimeOrderBy());
276
+
277
+ expect(result.total).toBe(10);
278
+ expect(result.data).toHaveLength(10);
279
+ });
280
+
281
+ it('should handle multiple data sources with overlapping timestamps', async () => {
282
+ const baseDate = new Date('2024-01-01T00:00:00Z');
283
+ const items1 = [
284
+ { id: 'id_1', created_at: new Date(baseDate.getTime() + 1000).toISOString(), value: 1 },
285
+ { id: 'id_2', created_at: new Date(baseDate.getTime() + 3000).toISOString(), value: 2 },
286
+ ];
287
+ const items2 = [
288
+ { id: 'id_3', created_at: new Date(baseDate.getTime() + 2000).toISOString(), value: 3 },
289
+ { id: 'id_4', created_at: new Date(baseDate.getTime() + 4000).toISOString(), value: 4 },
290
+ ];
291
+
292
+ // Create pre-sorted database sources
293
+ const orderBy = defaultTimeOrderBy('desc');
294
+ const source1 = createSortedDatabaseDataSource(items1, orderBy);
295
+ const source2 = createSortedDatabaseDataSource(items2, orderBy);
296
+
297
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, orderBy);
298
+
299
+ // Verify sorting order: First by timestamp descending, then by ID descending
300
+ expect(result.data.map((item) => item.id)).toEqual(['id_4', 'id_2', 'id_3', 'id_1']);
301
+ });
302
+
303
+ it('should handle multiple data sources with late pages correctly', async () => {
304
+ const baseDate = new Date('2024-01-01T00:00:00Z');
305
+
306
+ // Create 3 data sources, each with 20 items (total 60 items)
307
+ const source1 = createTestDataSource(createTestItems(20, baseDate));
308
+ const source2 = createTestDataSource(createTestItems(20, new Date(baseDate.getTime() + 20000)));
309
+ const source3 = createTestDataSource(createTestItems(20, new Date(baseDate.getTime() + 40000)));
310
+
311
+ // Test page 4 (should have items 31-40 out of 60 total)
312
+ const result = await mergePaginate(
313
+ [source1, source2, source3],
314
+ { page: 4, pageSize: 10 },
315
+ defaultTimeOrderBy('desc')
316
+ );
317
+
318
+ expect(result.total).toBe(60);
319
+ expect(result.data).toHaveLength(10);
320
+ expect(result.paging).toEqual({
321
+ page: 4,
322
+ pageSize: 10,
323
+ totalPages: 6,
324
+ });
325
+
326
+ // Test the last page (page 6, should have items 51-60)
327
+ const lastPageResult = await mergePaginate(
328
+ [source1, source2, source3],
329
+ { page: 6, pageSize: 10 },
330
+ defaultTimeOrderBy('desc')
331
+ );
332
+
333
+ expect(lastPageResult.total).toBe(60);
334
+ expect(lastPageResult.data).toHaveLength(10);
335
+ expect(lastPageResult.paging).toEqual({
336
+ page: 6,
337
+ pageSize: 10,
338
+ totalPages: 6,
339
+ });
340
+ });
341
+ });
342
+
343
+ describe('Sorting', () => {
344
+ it('should sort items in ascending order', async () => {
345
+ const baseDate = new Date('2024-01-01T00:00:00Z');
346
+ const items1 = [
347
+ { id: 'id_1', created_at: new Date(baseDate.getTime() + 1000).toISOString(), value: 1 },
348
+ { id: 'id_2', created_at: new Date(baseDate.getTime() + 2000).toISOString(), value: 2 },
349
+ ];
350
+ const items2 = [
351
+ { id: 'id_3', created_at: new Date(baseDate.getTime() + 3000).toISOString(), value: 3 },
352
+ { id: 'id_4', created_at: new Date(baseDate.getTime() + 4000).toISOString(), value: 4 },
353
+ ];
354
+
355
+ // Create pre-sorted database sources
356
+ const orderBy = defaultTimeOrderBy('asc');
357
+ const source1 = createSortedDatabaseDataSource(items1, orderBy);
358
+ const source2 = createSortedDatabaseDataSource(items2, orderBy);
359
+
360
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, orderBy);
361
+
362
+ expect(result.data[0].value).toBe(1); // Oldest item should be first
363
+ expect(result.data[3].value).toBe(4); // Latest item should be last
364
+ });
365
+
366
+ it('should sort items in descending order', async () => {
367
+ const baseDate = new Date('2024-01-01T00:00:00Z');
368
+ const items1 = [
369
+ { id: 'id_1', created_at: new Date(baseDate.getTime() + 1000).toISOString(), value: 1 },
370
+ { id: 'id_2', created_at: new Date(baseDate.getTime() + 2000).toISOString(), value: 2 },
371
+ ];
372
+ const items2 = [
373
+ { id: 'id_3', created_at: new Date(baseDate.getTime() + 3000).toISOString(), value: 3 },
374
+ { id: 'id_4', created_at: new Date(baseDate.getTime() + 4000).toISOString(), value: 4 },
375
+ ];
376
+
377
+ // Create pre-sorted database sources
378
+ const orderBy = defaultTimeOrderBy('desc');
379
+ const source1 = createSortedDatabaseDataSource(items1, orderBy);
380
+ const source2 = createSortedDatabaseDataSource(items2, orderBy);
381
+
382
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, orderBy);
383
+
384
+ expect(result.data[0].value).toBe(4); // Latest item should be first
385
+ expect(result.data[3].value).toBe(1); // Oldest item should be last
386
+ });
387
+
388
+ it('should use id as secondary sort key', async () => {
389
+ const baseDate = new Date('2024-01-01T00:00:00Z');
390
+ const items = [
391
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 1 },
392
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 2 },
393
+ ];
394
+ const source = createSortingTestDataSource(items);
395
+
396
+ // Sort by timestamp ascending, then by id ascending
397
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('asc', 'id'));
398
+
399
+ // Verify secondary sort key: When timestamps are equal, sort by id in ascending order
400
+ expect(result.data[0].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb'); // L comes before r
401
+ expect(result.data[1].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5');
402
+ });
403
+
404
+ it('should use value as secondary sort key', async () => {
405
+ const baseDate = new Date('2024-01-01T00:00:00Z');
406
+ const items = [
407
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
408
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 1 },
409
+ ];
410
+ const source = createSortingTestDataSource(items);
411
+
412
+ // Sort by timestamp ascending, then by value ascending
413
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('asc', 'value'));
414
+
415
+ // Verify secondary sort key: When timestamps are equal, sort by value in ascending order
416
+ expect(result.data[0].value).toBe(1);
417
+ expect(result.data[1].value).toBe(2);
418
+ });
419
+
420
+ it('should respect primary sort order for secondary field', async () => {
421
+ const baseDate = new Date('2024-01-01T00:00:00Z');
422
+ const items = [
423
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 1 },
424
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 2 },
425
+ ];
426
+ const source = createSortingTestDataSource(items);
427
+
428
+ // Sort by timestamp descending, then by value descending
429
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc', 'value'));
430
+
431
+ // Verify secondary sort key: When timestamps are equal, sort by value in descending order
432
+ expect(result.data[0].value).toBe(2);
433
+ expect(result.data[1].value).toBe(1);
434
+ });
435
+
436
+ it('should handle items with same timestamp without secondary field', async () => {
437
+ const baseDate = new Date('2024-01-01T00:00:00Z');
438
+ const items = [
439
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
440
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 1 },
441
+ ];
442
+ const source = createSortingTestDataSource(items);
443
+
444
+ // Sort by timestamp only, without specifying secondary sort field (defaults to 'desc' order with 'id' secondary)
445
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc'));
446
+
447
+ // Verify: When timestamps are equal, sort by id in descending order (because primary sort is 'desc')
448
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5'); // r comes after L in descending order
449
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
450
+ });
451
+
452
+ it('should handle items with undefined secondary field values', async () => {
453
+ const baseDate = new Date('2024-01-01T00:00:00Z');
454
+ const items = [
455
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
456
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString() }, // value undefined
457
+ ];
458
+ const source = createSortingTestDataSource(items);
459
+
460
+ // Specify value as secondary sort field, but one item has no value (should fall back to id)
461
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc', 'value'));
462
+
463
+ // Verify: When secondary field value is undefined, use id as fallback sort in descending order
464
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5'); // r comes after L in descending order
465
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
466
+ });
467
+
468
+ it('should use id as default secondary sort key', async () => {
469
+ const baseDate = new Date('2024-01-01T00:00:00Z');
470
+ const items = [
471
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
472
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 1 },
473
+ ];
474
+ const source = createSortingTestDataSource(items);
475
+
476
+ // No secondary sort field specified, should use id by default with descending order
477
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc'));
478
+
479
+ // Verify: When timestamps are equal, sort by id in descending order
480
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5'); // r comes after L in descending order
481
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
482
+ });
483
+
484
+ it('should use id as fallback when secondary field is undefined', async () => {
485
+ const baseDate = new Date('2024-01-01T00:00:00Z');
486
+ const items = [
487
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
488
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString() }, // value undefined
489
+ ];
490
+ const source = createSortingTestDataSource(items);
491
+
492
+ // Specify value as secondary sort field, but one item has no value
493
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc', 'value'));
494
+
495
+ // Verify: When secondary field value is undefined, use id as fallback sort
496
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5');
497
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
498
+ });
499
+
500
+ it('should use id as fallback for unsupported field types', async () => {
501
+ const baseDate = new Date('2024-01-01T00:00:00Z');
502
+ const items = [
503
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: { complex: 'object' } },
504
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: { complex: 'object' } },
505
+ ];
506
+ const source = createSortingTestDataSource(items);
507
+
508
+ // Specify value as secondary sort field, but value is complex object
509
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc', 'value'));
510
+
511
+ // Verify: When secondary field type is unsupported, use id as fallback sort
512
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5');
513
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
514
+ });
515
+ });
516
+
517
+ describe('Performance', () => {
518
+ it('should handle large data sources efficiently', async () => {
519
+ const largeItems = createTestItems(1000);
520
+ const source = createTestDataSource(largeItems);
521
+
522
+ const startTime = Date.now();
523
+ const result = await mergePaginate([source], { page: 10, pageSize: 10 }, defaultTimeOrderBy());
524
+ const duration = Date.now() - startTime;
525
+
526
+ expect(result.total).toBe(1000);
527
+ expect(result.data).toHaveLength(10);
528
+ expect(duration).toBeLessThan(100); // Ensure processing time is within reasonable range
529
+ });
530
+
531
+ it('should not fetch all data when not necessary', async () => {
532
+ const source1 = createTestDataSource(createTestItems(100));
533
+ const source2 = createTestDataSource(createTestItems(100));
534
+
535
+ // Mock fetch method calls
536
+ const spy1 = jest.spyOn(source1, 'fetch');
537
+ const spy2 = jest.spyOn(source2, 'fetch');
538
+
539
+ await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, defaultTimeOrderBy());
540
+
541
+ // Ensure no data is fetched all at once
542
+ expect(spy1).toHaveBeenCalledWith(expect.any(Number), expect.any(Number));
543
+ expect(spy2).toHaveBeenCalledWith(expect.any(Number), expect.any(Number));
544
+
545
+ spy1.mockRestore();
546
+ spy2.mockRestore();
547
+ });
548
+ });
549
+ });
package/blocklet.yml CHANGED
@@ -14,7 +14,7 @@ repository:
14
14
  type: git
15
15
  url: git+https://github.com/blocklet/payment-kit.git
16
16
  specVersion: 1.2.8
17
- version: 1.18.45
17
+ version: 1.18.47
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.18.45",
3
+ "version": "1.18.47",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "eject": "vite eject",
@@ -47,19 +47,19 @@
47
47
  "@abtnode/cron": "^1.16.43",
48
48
  "@arcblock/did": "^1.20.11",
49
49
  "@arcblock/did-auth-storage-nedb": "^1.7.1",
50
- "@arcblock/did-connect": "^2.13.40",
50
+ "@arcblock/did-connect": "^2.13.47",
51
51
  "@arcblock/did-util": "^1.20.11",
52
52
  "@arcblock/jwt": "^1.20.11",
53
- "@arcblock/ux": "^2.13.40",
53
+ "@arcblock/ux": "^2.13.47",
54
54
  "@arcblock/validator": "^1.20.11",
55
- "@blocklet/did-space-js": "^1.0.53",
55
+ "@blocklet/did-space-js": "^1.0.56",
56
56
  "@blocklet/js-sdk": "^1.16.43",
57
57
  "@blocklet/logger": "^1.16.43",
58
- "@blocklet/payment-react": "1.18.45",
58
+ "@blocklet/payment-react": "1.18.47",
59
59
  "@blocklet/sdk": "^1.16.43",
60
- "@blocklet/ui-react": "^2.13.40",
61
- "@blocklet/uploader": "^0.1.91",
62
- "@blocklet/xss": "^0.1.35",
60
+ "@blocklet/ui-react": "^2.13.47",
61
+ "@blocklet/uploader": "^0.1.93",
62
+ "@blocklet/xss": "^0.1.36",
63
63
  "@mui/icons-material": "^5.16.6",
64
64
  "@mui/lab": "^5.0.0-alpha.173",
65
65
  "@mui/material": "^5.16.6",
@@ -123,7 +123,7 @@
123
123
  "devDependencies": {
124
124
  "@abtnode/types": "^1.16.43",
125
125
  "@arcblock/eslint-config-ts": "^0.3.3",
126
- "@blocklet/payment-types": "1.18.45",
126
+ "@blocklet/payment-types": "1.18.47",
127
127
  "@types/cookie-parser": "^1.4.7",
128
128
  "@types/cors": "^2.8.17",
129
129
  "@types/debug": "^4.1.12",
@@ -169,5 +169,5 @@
169
169
  "parser": "typescript"
170
170
  }
171
171
  },
172
- "gitHead": "572fcb416607935c8eb338e7904b30f8a3e42306"
172
+ "gitHead": "e781286c5a20e54ef0eb7e029505f32c00cb33e2"
173
173
  }
@@ -21,7 +21,7 @@ import SubscriptionDescription from '../description';
21
21
  import SubscriptionActions from './actions';
22
22
  import SubscriptionStatus from '../status';
23
23
  import useDelayedLoading from '../../../hooks/loading';
24
- import { isWillCanceled } from '../../../libs/util';
24
+ import { formatProxyUrl, isWillCanceled } from '../../../libs/util';
25
25
 
26
26
  type SubscriptionListResponse = {
27
27
  count: number;
@@ -161,31 +161,41 @@ export default function CurrentSubscriptions({
161
161
  justifyContent="space-between"
162
162
  onClick={() => onClickSubscription(subscription)}>
163
163
  <Stack direction="row" spacing={1.5} alignItems="center">
164
- <AvatarGroup
165
- max={2}
166
- sx={{
167
- '& .MuiAvatar-colorDefault': {
168
- ...size,
169
- boxSizing: 'border-box',
170
- },
171
- }}>
172
- {subscription.items.slice(0, 2).map((item) =>
173
- item.price.product.images.length > 0 ? (
174
- // @ts-ignore
175
- <Avatar
176
- key={item.price.product_id}
177
- src={item.price.product.images[0]}
178
- alt={item.price.product.name}
179
- variant="rounded"
180
- sx={size}
181
- />
182
- ) : (
183
- <Avatar key={item.price.product_id} variant="rounded" sx={size}>
184
- {item.price.product.name.slice(0, 1)}
185
- </Avatar>
186
- )
187
- )}
188
- </AvatarGroup>
164
+ {subscription.metadata?.appLogo ? (
165
+ <Avatar
166
+ src={formatProxyUrl(subscription.metadata?.appLogo)}
167
+ alt={subscription.metadata?.appName}
168
+ variant="rounded"
169
+ sx={size}
170
+ />
171
+ ) : (
172
+ <AvatarGroup
173
+ max={2}
174
+ sx={{
175
+ '& .MuiAvatar-colorDefault': {
176
+ ...size,
177
+ boxSizing: 'border-box',
178
+ },
179
+ }}>
180
+ {subscription.items.slice(0, 2).map((item) =>
181
+ item.price.product.images.length > 0 ? (
182
+ // @ts-ignore
183
+ <Avatar
184
+ key={item.price.product_id}
185
+ src={item.price.product.images[0]}
186
+ alt={item.price.product.name}
187
+ variant="rounded"
188
+ sx={size}
189
+ />
190
+ ) : (
191
+ <Avatar key={item.price.product_id} variant="rounded" sx={size}>
192
+ {item.price.product.name.slice(0, 1)}
193
+ </Avatar>
194
+ )
195
+ )}
196
+ </AvatarGroup>
197
+ )}
198
+
189
199
  <Stack direction="column" spacing={0.25}>
190
200
  <SubscriptionDescription
191
201
  subscription={subscription}