payment-kit 1.18.46 → 1.18.48

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,576 @@
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 29 records with last page showing correct 9 items', async () => {
304
+ const baseDate = new Date('2024-01-01T00:00:00Z');
305
+
306
+ // Create 3 data sources with uneven distribution: 10, 10, 9 records
307
+ const source1 = createTestDataSource(createTestItems(10, baseDate));
308
+ const source2 = createTestDataSource(createTestItems(10, new Date(baseDate.getTime() + 10000)));
309
+ const source3 = createTestDataSource(createTestItems(9, new Date(baseDate.getTime() + 20000)));
310
+
311
+ // Test the last page (page 3, should have 9 items: records 21-29)
312
+ const result = await mergePaginate(
313
+ [source1, source2, source3],
314
+ { page: 3, pageSize: 10 },
315
+ defaultTimeOrderBy('desc')
316
+ );
317
+
318
+ expect(result.total).toBe(29);
319
+ expect(result.data).toHaveLength(9); // Should show all 9 remaining items, not just 2
320
+ expect(result.paging).toEqual({
321
+ page: 3,
322
+ pageSize: 10,
323
+ totalPages: 3,
324
+ });
325
+
326
+ // Verify we got the correct range of items (the oldest ones)
327
+ expect(result.data.every((item) => item.value < 20)).toBe(true); // These should be the oldest items
328
+ });
329
+
330
+ it('should handle multiple data sources with late pages correctly', async () => {
331
+ const baseDate = new Date('2024-01-01T00:00:00Z');
332
+
333
+ // Create 3 data sources, each with 20 items (total 60 items)
334
+ const source1 = createTestDataSource(createTestItems(20, baseDate));
335
+ const source2 = createTestDataSource(createTestItems(20, new Date(baseDate.getTime() + 20000)));
336
+ const source3 = createTestDataSource(createTestItems(20, new Date(baseDate.getTime() + 40000)));
337
+
338
+ // Test page 4 (should have items 31-40 out of 60 total)
339
+ const result = await mergePaginate(
340
+ [source1, source2, source3],
341
+ { page: 4, pageSize: 10 },
342
+ defaultTimeOrderBy('desc')
343
+ );
344
+
345
+ expect(result.total).toBe(60);
346
+ expect(result.data).toHaveLength(10);
347
+ expect(result.paging).toEqual({
348
+ page: 4,
349
+ pageSize: 10,
350
+ totalPages: 6,
351
+ });
352
+
353
+ // Test the last page (page 6, should have items 51-60)
354
+ const lastPageResult = await mergePaginate(
355
+ [source1, source2, source3],
356
+ { page: 6, pageSize: 10 },
357
+ defaultTimeOrderBy('desc')
358
+ );
359
+
360
+ expect(lastPageResult.total).toBe(60);
361
+ expect(lastPageResult.data).toHaveLength(10);
362
+ expect(lastPageResult.paging).toEqual({
363
+ page: 6,
364
+ pageSize: 10,
365
+ totalPages: 6,
366
+ });
367
+ });
368
+ });
369
+
370
+ describe('Sorting', () => {
371
+ it('should sort items in ascending order', async () => {
372
+ const baseDate = new Date('2024-01-01T00:00:00Z');
373
+ const items1 = [
374
+ { id: 'id_1', created_at: new Date(baseDate.getTime() + 1000).toISOString(), value: 1 },
375
+ { id: 'id_2', created_at: new Date(baseDate.getTime() + 2000).toISOString(), value: 2 },
376
+ ];
377
+ const items2 = [
378
+ { id: 'id_3', created_at: new Date(baseDate.getTime() + 3000).toISOString(), value: 3 },
379
+ { id: 'id_4', created_at: new Date(baseDate.getTime() + 4000).toISOString(), value: 4 },
380
+ ];
381
+
382
+ // Create pre-sorted database sources
383
+ const orderBy = defaultTimeOrderBy('asc');
384
+ const source1 = createSortedDatabaseDataSource(items1, orderBy);
385
+ const source2 = createSortedDatabaseDataSource(items2, orderBy);
386
+
387
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, orderBy);
388
+
389
+ expect(result.data[0].value).toBe(1); // Oldest item should be first
390
+ expect(result.data[3].value).toBe(4); // Latest item should be last
391
+ });
392
+
393
+ it('should sort items in descending order', async () => {
394
+ const baseDate = new Date('2024-01-01T00:00:00Z');
395
+ const items1 = [
396
+ { id: 'id_1', created_at: new Date(baseDate.getTime() + 1000).toISOString(), value: 1 },
397
+ { id: 'id_2', created_at: new Date(baseDate.getTime() + 2000).toISOString(), value: 2 },
398
+ ];
399
+ const items2 = [
400
+ { id: 'id_3', created_at: new Date(baseDate.getTime() + 3000).toISOString(), value: 3 },
401
+ { id: 'id_4', created_at: new Date(baseDate.getTime() + 4000).toISOString(), value: 4 },
402
+ ];
403
+
404
+ // Create pre-sorted database sources
405
+ const orderBy = defaultTimeOrderBy('desc');
406
+ const source1 = createSortedDatabaseDataSource(items1, orderBy);
407
+ const source2 = createSortedDatabaseDataSource(items2, orderBy);
408
+
409
+ const result = await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, orderBy);
410
+
411
+ expect(result.data[0].value).toBe(4); // Latest item should be first
412
+ expect(result.data[3].value).toBe(1); // Oldest item should be last
413
+ });
414
+
415
+ it('should use id as secondary sort key', async () => {
416
+ const baseDate = new Date('2024-01-01T00:00:00Z');
417
+ const items = [
418
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 1 },
419
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 2 },
420
+ ];
421
+ const source = createSortingTestDataSource(items);
422
+
423
+ // Sort by timestamp ascending, then by id ascending
424
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('asc', 'id'));
425
+
426
+ // Verify secondary sort key: When timestamps are equal, sort by id in ascending order
427
+ expect(result.data[0].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb'); // L comes before r
428
+ expect(result.data[1].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5');
429
+ });
430
+
431
+ it('should use value as secondary sort key', async () => {
432
+ const baseDate = new Date('2024-01-01T00:00:00Z');
433
+ const items = [
434
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
435
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 1 },
436
+ ];
437
+ const source = createSortingTestDataSource(items);
438
+
439
+ // Sort by timestamp ascending, then by value ascending
440
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('asc', 'value'));
441
+
442
+ // Verify secondary sort key: When timestamps are equal, sort by value in ascending order
443
+ expect(result.data[0].value).toBe(1);
444
+ expect(result.data[1].value).toBe(2);
445
+ });
446
+
447
+ it('should respect primary sort order for secondary field', async () => {
448
+ const baseDate = new Date('2024-01-01T00:00:00Z');
449
+ const items = [
450
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 1 },
451
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 2 },
452
+ ];
453
+ const source = createSortingTestDataSource(items);
454
+
455
+ // Sort by timestamp descending, then by value descending
456
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc', 'value'));
457
+
458
+ // Verify secondary sort key: When timestamps are equal, sort by value in descending order
459
+ expect(result.data[0].value).toBe(2);
460
+ expect(result.data[1].value).toBe(1);
461
+ });
462
+
463
+ it('should handle items with same timestamp without secondary field', async () => {
464
+ const baseDate = new Date('2024-01-01T00:00:00Z');
465
+ const items = [
466
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
467
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 1 },
468
+ ];
469
+ const source = createSortingTestDataSource(items);
470
+
471
+ // Sort by timestamp only, without specifying secondary sort field (defaults to 'desc' order with 'id' secondary)
472
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc'));
473
+
474
+ // Verify: When timestamps are equal, sort by id in descending order (because primary sort is 'desc')
475
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5'); // r comes after L in descending order
476
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
477
+ });
478
+
479
+ it('should handle items with undefined secondary field values', async () => {
480
+ const baseDate = new Date('2024-01-01T00:00:00Z');
481
+ const items = [
482
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
483
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString() }, // value undefined
484
+ ];
485
+ const source = createSortingTestDataSource(items);
486
+
487
+ // Specify value as secondary sort field, but one item has no value (should fall back to id)
488
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc', 'value'));
489
+
490
+ // Verify: When secondary field value is undefined, use id as fallback sort in descending order
491
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5'); // r comes after L in descending order
492
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
493
+ });
494
+
495
+ it('should use id as default secondary sort key', async () => {
496
+ const baseDate = new Date('2024-01-01T00:00:00Z');
497
+ const items = [
498
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
499
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: 1 },
500
+ ];
501
+ const source = createSortingTestDataSource(items);
502
+
503
+ // No secondary sort field specified, should use id by default with descending order
504
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc'));
505
+
506
+ // Verify: When timestamps are equal, sort by id in descending order
507
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5'); // r comes after L in descending order
508
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
509
+ });
510
+
511
+ it('should use id as fallback when secondary field is undefined', async () => {
512
+ const baseDate = new Date('2024-01-01T00:00:00Z');
513
+ const items = [
514
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: 2 },
515
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString() }, // value undefined
516
+ ];
517
+ const source = createSortingTestDataSource(items);
518
+
519
+ // Specify value as secondary sort field, but one item has no value
520
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc', 'value'));
521
+
522
+ // Verify: When secondary field value is undefined, use id as fallback sort
523
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5');
524
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
525
+ });
526
+
527
+ it('should use id as fallback for unsupported field types', async () => {
528
+ const baseDate = new Date('2024-01-01T00:00:00Z');
529
+ const items = [
530
+ { id: 'in_rBgXh8srXYXAXPs1Sn4XsJy5', created_at: baseDate.toISOString(), value: { complex: 'object' } },
531
+ { id: 'in_LA0hts9lHaDycDii3TEfCzkb', created_at: baseDate.toISOString(), value: { complex: 'object' } },
532
+ ];
533
+ const source = createSortingTestDataSource(items);
534
+
535
+ // Specify value as secondary sort field, but value is complex object
536
+ const result = await mergePaginate([source], { page: 1, pageSize: 10 }, defaultTimeOrderBy('desc', 'value'));
537
+
538
+ // Verify: When secondary field type is unsupported, use id as fallback sort
539
+ expect(result.data[0].id).toBe('in_rBgXh8srXYXAXPs1Sn4XsJy5');
540
+ expect(result.data[1].id).toBe('in_LA0hts9lHaDycDii3TEfCzkb');
541
+ });
542
+ });
543
+
544
+ describe('Performance', () => {
545
+ it('should handle large data sources efficiently', async () => {
546
+ const largeItems = createTestItems(1000);
547
+ const source = createTestDataSource(largeItems);
548
+
549
+ const startTime = Date.now();
550
+ const result = await mergePaginate([source], { page: 10, pageSize: 10 }, defaultTimeOrderBy());
551
+ const duration = Date.now() - startTime;
552
+
553
+ expect(result.total).toBe(1000);
554
+ expect(result.data).toHaveLength(10);
555
+ expect(duration).toBeLessThan(100); // Ensure processing time is within reasonable range
556
+ });
557
+
558
+ it('should not fetch all data when not necessary', async () => {
559
+ const source1 = createTestDataSource(createTestItems(100));
560
+ const source2 = createTestDataSource(createTestItems(100));
561
+
562
+ // Mock fetch method calls
563
+ const spy1 = jest.spyOn(source1, 'fetch');
564
+ const spy2 = jest.spyOn(source2, 'fetch');
565
+
566
+ await mergePaginate([source1, source2], { page: 1, pageSize: 10 }, defaultTimeOrderBy());
567
+
568
+ // Ensure no data is fetched all at once
569
+ expect(spy1).toHaveBeenCalledWith(expect.any(Number), expect.any(Number));
570
+ expect(spy2).toHaveBeenCalledWith(expect.any(Number), expect.any(Number));
571
+
572
+ spy1.mockRestore();
573
+ spy2.mockRestore();
574
+ });
575
+ });
576
+ });
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.46
17
+ version: 1.18.48
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.46",
3
+ "version": "1.18.48",
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.41",
50
+ "@arcblock/did-connect": "^2.13.54",
51
51
  "@arcblock/did-util": "^1.20.11",
52
52
  "@arcblock/jwt": "^1.20.11",
53
- "@arcblock/ux": "^2.13.41",
53
+ "@arcblock/ux": "^2.13.54",
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.46",
58
+ "@blocklet/payment-react": "1.18.48",
59
59
  "@blocklet/sdk": "^1.16.43",
60
- "@blocklet/ui-react": "^2.13.41",
61
- "@blocklet/uploader": "^0.1.91",
62
- "@blocklet/xss": "^0.1.35",
60
+ "@blocklet/ui-react": "^2.13.54",
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.46",
126
+ "@blocklet/payment-types": "1.18.48",
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": "3b82c845f7a0bf2e91bf6c485e42630743354409"
172
+ "gitHead": "4042dc2996b11ab6ccf6a973af53042cff913474"
173
173
  }
package/scripts/sdk.js CHANGED
@@ -539,6 +539,13 @@ const subscriptionModule = {
539
539
  console.log('createBatchUsageRecords', results);
540
540
  return results;
541
541
  },
542
+
543
+ // 返回质押
544
+ async returnStake() {
545
+ const result = await payment.subscriptions.returnStake('sub_pWYXj2fale49qeFfEpunTmZq');
546
+ console.log('returnStake', result);
547
+ return result;
548
+ },
542
549
  };
543
550
 
544
551
  const testModules = {