tantan-typeorm-gs 1.0.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.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/bun.lock +300 -0
  4. package/docs/authentication.md +118 -0
  5. package/docs/configuration.md +680 -0
  6. package/docs/contributing.md +177 -0
  7. package/docs/crud.md +351 -0
  8. package/docs/custom-client.md +165 -0
  9. package/docs/development.md +243 -0
  10. package/docs/entities.md +502 -0
  11. package/docs/find-options.md +296 -0
  12. package/docs/google-cloud.md +101 -0
  13. package/docs/installation.md +51 -0
  14. package/docs/integration-testing.md +178 -0
  15. package/docs/limitations.md +223 -0
  16. package/docs/pagination.md +384 -0
  17. package/docs/performance.md +171 -0
  18. package/docs/security.md +153 -0
  19. package/docs/sorting.md +0 -0
  20. package/docs/supported-features.md +310 -0
  21. package/docs/synchronization.md +203 -0
  22. package/package.json +43 -0
  23. package/src/client/index.ts +589 -0
  24. package/src/core/data-source.ts +47 -0
  25. package/src/core/driver.ts +290 -0
  26. package/src/core/error.ts +144 -0
  27. package/src/core/memory.ts +152 -0
  28. package/src/core/query/interpreter.ts +949 -0
  29. package/src/core/query/runner.ts +1297 -0
  30. package/src/core/query/types.ts +155 -0
  31. package/src/core/schema-builder.ts +64 -0
  32. package/src/core/types.ts +113 -0
  33. package/src/core/utils.ts +13 -0
  34. package/src/index.ts +3 -0
  35. package/tantan-typeorm-gs.code-workspace +8 -0
  36. package/test/base/0001-data-source.test.ts +252 -0
  37. package/test/base/0002-operator.test.ts +616 -0
  38. package/test/base/0003-select.test.ts +281 -0
  39. package/test/base/0004-aggregate.test.ts +213 -0
  40. package/test/base/0005-transcation.test.ts +1566 -0
  41. package/test/base/0006-relation.test.ts +1611 -0
  42. package/test/base/0007-logging.test.ts +182 -0
  43. package/test/base/0008-soft-delete.test.ts +649 -0
  44. package/test/google-sheets/0001-client.test.ts +1705 -0
  45. package/test/google-sheets/0002-worksheet-management.test.ts +408 -0
  46. package/test/google-sheets/0003-data-source.test.ts +1935 -0
  47. package/test/google-sheets/0004-transactions.test.ts +952 -0
  48. package/test/google-sheets/0005-operator.test.ts +1124 -0
  49. package/test/google-sheets/0006-object-criteria.test.ts +283 -0
  50. package/test/google-sheets/0007-performance.test.ts +532 -0
  51. package/test/public-api.test.ts +34 -0
  52. package/tsconfig.build.json +21 -0
  53. package/tsconfig.json +34 -0
@@ -0,0 +1,1124 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import
3
+ {
4
+ Between,
5
+ Column,
6
+ Entity,
7
+ In,
8
+ IsNull,
9
+ LessThan,
10
+ LessThanOrEqual,
11
+ Like,
12
+ MoreThan,
13
+ MoreThanOrEqual,
14
+ Not,
15
+ PrimaryGeneratedColumn,
16
+ } from 'typeorm';
17
+ import { Memory } from '../../src/core/memory';
18
+ import { createGoogleSheetsDataSource, type GoogleSheetsRow } from '../../src';
19
+
20
+ describe('Query Operator', () =>
21
+ {
22
+ @Entity('query_features_users')
23
+ class QueryFeaturesUser
24
+ {
25
+ @PrimaryGeneratedColumn()
26
+ id!: number;
27
+
28
+ @Column()
29
+ name!: string | null;
30
+
31
+ @Column()
32
+ email!: string;
33
+
34
+ @Column()
35
+ age!: number;
36
+ }
37
+
38
+ async function createDataSource(
39
+ rows: GoogleSheetsRow[] = [],
40
+ )
41
+ {
42
+ const client =
43
+ new Memory({
44
+ query_features_users: rows,
45
+ });
46
+
47
+ await client.insertHeaders(
48
+ 'query_features_users',
49
+ [
50
+ 'id',
51
+ 'name',
52
+ 'email',
53
+ 'age',
54
+ ],
55
+ );
56
+
57
+ const dataSource =
58
+ createGoogleSheetsDataSource({
59
+ type: 'google-sheets',
60
+
61
+ client,
62
+
63
+ entities: [
64
+ QueryFeaturesUser,
65
+ ],
66
+ });
67
+
68
+ await dataSource.initialize();
69
+
70
+ return {
71
+ client,
72
+ dataSource,
73
+ };
74
+ }
75
+
76
+ test(
77
+ 'should support object criteria',
78
+ async () =>
79
+ {
80
+ const {
81
+ dataSource,
82
+ } =
83
+ await createDataSource([
84
+ {
85
+ id: 1,
86
+ name: 'John',
87
+ email: 'john@example.com',
88
+ age: 20,
89
+ },
90
+ {
91
+ id: 2,
92
+ name: 'Jane',
93
+ email: 'jane@example.com',
94
+ age: 25,
95
+ },
96
+ {
97
+ id: 3,
98
+ name: 'Bob',
99
+ email: 'bob@example.com',
100
+ age: 30,
101
+ },
102
+ ]);
103
+
104
+ try
105
+ {
106
+ const repository =
107
+ dataSource.getRepository(
108
+ QueryFeaturesUser,
109
+ );
110
+
111
+ const users =
112
+ await repository.find({
113
+ where: {
114
+ name: 'John',
115
+ },
116
+ });
117
+
118
+ expect(users)
119
+ .toEqual([
120
+ {
121
+ id: 1,
122
+ name: 'John',
123
+ email: 'john@example.com',
124
+ age: 20,
125
+ },
126
+ ]);
127
+ }
128
+ finally
129
+ {
130
+ if (dataSource.isInitialized)
131
+ {
132
+ await dataSource.destroy();
133
+ }
134
+ }
135
+ },
136
+ );
137
+
138
+ test(
139
+ 'should support In operator',
140
+ async () =>
141
+ {
142
+ const {
143
+ dataSource,
144
+ } =
145
+ await createDataSource([
146
+ {
147
+ id: 1,
148
+ name: 'John',
149
+ email: 'john@example.com',
150
+ age: 20,
151
+ },
152
+ {
153
+ id: 2,
154
+ name: 'Jane',
155
+ email: 'jane@example.com',
156
+ age: 25,
157
+ },
158
+ {
159
+ id: 3,
160
+ name: 'Bob',
161
+ email: 'bob@example.com',
162
+ age: 30,
163
+ },
164
+ {
165
+ id: 4,
166
+ name: 'Alice',
167
+ email: 'alice@example.com',
168
+ age: 35,
169
+ },
170
+ {
171
+ id: 5,
172
+ name: 'Johnny',
173
+ email: 'johnny@example.com',
174
+ age: 40,
175
+ },
176
+ ]);
177
+
178
+ try
179
+ {
180
+ const repository =
181
+ dataSource.getRepository(
182
+ QueryFeaturesUser,
183
+ );
184
+
185
+ const users =
186
+ await repository.find({
187
+ where: {
188
+ id: In([1, 3, 5]),
189
+ },
190
+ });
191
+
192
+ expect(users)
193
+ .toEqual([
194
+ {
195
+ id: 1,
196
+ name: 'John',
197
+ email: 'john@example.com',
198
+ age: 20,
199
+ },
200
+ {
201
+ id: 3,
202
+ name: 'Bob',
203
+ email: 'bob@example.com',
204
+ age: 30,
205
+ },
206
+ {
207
+ id: 5,
208
+ name: 'Johnny',
209
+ email: 'johnny@example.com',
210
+ age: 40,
211
+ },
212
+ ]);
213
+ }
214
+ finally
215
+ {
216
+ if (dataSource.isInitialized)
217
+ {
218
+ await dataSource.destroy();
219
+ }
220
+ }
221
+ },
222
+ );
223
+
224
+ test(
225
+ 'should support Not operator',
226
+ async () =>
227
+ {
228
+ const {
229
+ dataSource,
230
+ } =
231
+ await createDataSource([
232
+ {
233
+ id: 1,
234
+ name: 'John',
235
+ email: 'john@example.com',
236
+ age: 20,
237
+ },
238
+ {
239
+ id: 2,
240
+ name: 'Jane',
241
+ email: 'jane@example.com',
242
+ age: 25,
243
+ },
244
+ {
245
+ id: 3,
246
+ name: 'Bob',
247
+ email: 'bob@example.com',
248
+ age: 30,
249
+ },
250
+ ]);
251
+
252
+ try
253
+ {
254
+ const repository =
255
+ dataSource.getRepository(
256
+ QueryFeaturesUser,
257
+ );
258
+
259
+ const users =
260
+ await repository.find({
261
+ where: {
262
+ name: Not('John'),
263
+ },
264
+ });
265
+
266
+ expect(users)
267
+ .toEqual([
268
+ {
269
+ id: 2,
270
+ name: 'Jane',
271
+ email: 'jane@example.com',
272
+ age: 25,
273
+ },
274
+ {
275
+ id: 3,
276
+ name: 'Bob',
277
+ email: 'bob@example.com',
278
+ age: 30,
279
+ },
280
+ ]);
281
+ }
282
+ finally
283
+ {
284
+ if (dataSource.isInitialized)
285
+ {
286
+ await dataSource.destroy();
287
+ }
288
+ }
289
+ },
290
+ );
291
+
292
+ test(
293
+ 'should support Like operator',
294
+ async () =>
295
+ {
296
+ const {
297
+ dataSource,
298
+ } =
299
+ await createDataSource([
300
+ {
301
+ id: 1,
302
+ name: 'John',
303
+ email: 'john@example.com',
304
+ age: 20,
305
+ },
306
+ {
307
+ id: 2,
308
+ name: 'Jane',
309
+ email: 'jane@example.com',
310
+ age: 25,
311
+ },
312
+ {
313
+ id: 3,
314
+ name: 'Johnny',
315
+ email: 'johnny@example.com',
316
+ age: 40,
317
+ },
318
+ ]);
319
+
320
+ try
321
+ {
322
+ const repository =
323
+ dataSource.getRepository(
324
+ QueryFeaturesUser,
325
+ );
326
+
327
+ const users =
328
+ await repository.find({
329
+ where: {
330
+ name: Like('John%'),
331
+ },
332
+ });
333
+
334
+ expect(users)
335
+ .toEqual([
336
+ {
337
+ id: 1,
338
+ name: 'John',
339
+ email: 'john@example.com',
340
+ age: 20,
341
+ },
342
+ {
343
+ id: 3,
344
+ name: 'Johnny',
345
+ email: 'johnny@example.com',
346
+ age: 40,
347
+ },
348
+ ]);
349
+ }
350
+ finally
351
+ {
352
+ if (dataSource.isInitialized)
353
+ {
354
+ await dataSource.destroy();
355
+ }
356
+ }
357
+ },
358
+ );
359
+
360
+ test(
361
+ 'should support Between operator',
362
+ async () =>
363
+ {
364
+ const {
365
+ dataSource,
366
+ } =
367
+ await createDataSource([
368
+ {
369
+ id: 1,
370
+ name: 'John',
371
+ email: 'john@example.com',
372
+ age: 20,
373
+ },
374
+ {
375
+ id: 2,
376
+ name: 'Jane',
377
+ email: 'jane@example.com',
378
+ age: 25,
379
+ },
380
+ {
381
+ id: 3,
382
+ name: 'Bob',
383
+ email: 'bob@example.com',
384
+ age: 30,
385
+ },
386
+ {
387
+ id: 4,
388
+ name: 'Alice',
389
+ email: 'alice@example.com',
390
+ age: 35,
391
+ },
392
+ {
393
+ id: 5,
394
+ name: 'Johnny',
395
+ email: 'johnny@example.com',
396
+ age: 40,
397
+ },
398
+ ]);
399
+
400
+ try
401
+ {
402
+ const repository =
403
+ dataSource.getRepository(
404
+ QueryFeaturesUser,
405
+ );
406
+
407
+ const users =
408
+ await repository.find({
409
+ where: {
410
+ age: Between(25, 35),
411
+ },
412
+ });
413
+
414
+ expect(users)
415
+ .toEqual([
416
+ {
417
+ id: 2,
418
+ name: 'Jane',
419
+ email: 'jane@example.com',
420
+ age: 25,
421
+ },
422
+ {
423
+ id: 3,
424
+ name: 'Bob',
425
+ email: 'bob@example.com',
426
+ age: 30,
427
+ },
428
+ {
429
+ id: 4,
430
+ name: 'Alice',
431
+ email: 'alice@example.com',
432
+ age: 35,
433
+ },
434
+ ]);
435
+ }
436
+ finally
437
+ {
438
+ if (dataSource.isInitialized)
439
+ {
440
+ await dataSource.destroy();
441
+ }
442
+ }
443
+ },
444
+ );
445
+
446
+ test(
447
+ 'should support MoreThan operator',
448
+ async () =>
449
+ {
450
+ const {
451
+ dataSource,
452
+ } =
453
+ await createDataSource([
454
+ {
455
+ id: 1,
456
+ name: 'John',
457
+ email: 'john@example.com',
458
+ age: 20,
459
+ },
460
+ {
461
+ id: 2,
462
+ name: 'Jane',
463
+ email: 'jane@example.com',
464
+ age: 25,
465
+ },
466
+ {
467
+ id: 3,
468
+ name: 'Bob',
469
+ email: 'bob@example.com',
470
+ age: 30,
471
+ },
472
+ {
473
+ id: 4,
474
+ name: 'Alice',
475
+ email: 'alice@example.com',
476
+ age: 35,
477
+ },
478
+ ]);
479
+
480
+ try
481
+ {
482
+ const repository =
483
+ dataSource.getRepository(
484
+ QueryFeaturesUser,
485
+ );
486
+
487
+ const users =
488
+ await repository.find({
489
+ where: {
490
+ age: MoreThan(30),
491
+ },
492
+ });
493
+
494
+ expect(users)
495
+ .toEqual([
496
+ {
497
+ id: 4,
498
+ name: 'Alice',
499
+ email: 'alice@example.com',
500
+ age: 35,
501
+ },
502
+ ]);
503
+ }
504
+ finally
505
+ {
506
+ if (dataSource.isInitialized)
507
+ {
508
+ await dataSource.destroy();
509
+ }
510
+ }
511
+ },
512
+ );
513
+
514
+ test(
515
+ 'should support MoreThanOrEqual operator',
516
+ async () =>
517
+ {
518
+ const {
519
+ dataSource,
520
+ } =
521
+ await createDataSource([
522
+ {
523
+ id: 1,
524
+ name: 'John',
525
+ email: 'john@example.com',
526
+ age: 20,
527
+ },
528
+ {
529
+ id: 2,
530
+ name: 'Jane',
531
+ email: 'jane@example.com',
532
+ age: 25,
533
+ },
534
+ {
535
+ id: 3,
536
+ name: 'Bob',
537
+ email: 'bob@example.com',
538
+ age: 30,
539
+ },
540
+ {
541
+ id: 4,
542
+ name: 'Alice',
543
+ email: 'alice@example.com',
544
+ age: 35,
545
+ },
546
+ ]);
547
+
548
+ try
549
+ {
550
+ const repository =
551
+ dataSource.getRepository(
552
+ QueryFeaturesUser,
553
+ );
554
+
555
+ const users =
556
+ await repository.find({
557
+ where: {
558
+ age: MoreThanOrEqual(30),
559
+ },
560
+ });
561
+
562
+ expect(users)
563
+ .toEqual([
564
+ {
565
+ id: 3,
566
+ name: 'Bob',
567
+ email: 'bob@example.com',
568
+ age: 30,
569
+ },
570
+ {
571
+ id: 4,
572
+ name: 'Alice',
573
+ email: 'alice@example.com',
574
+ age: 35,
575
+ },
576
+ ]);
577
+ }
578
+ finally
579
+ {
580
+ if (dataSource.isInitialized)
581
+ {
582
+ await dataSource.destroy();
583
+ }
584
+ }
585
+ },
586
+ );
587
+
588
+ test(
589
+ 'should support LessThan operator',
590
+ async () =>
591
+ {
592
+ const {
593
+ dataSource,
594
+ } =
595
+ await createDataSource([
596
+ {
597
+ id: 1,
598
+ name: 'John',
599
+ email: 'john@example.com',
600
+ age: 20,
601
+ },
602
+ {
603
+ id: 2,
604
+ name: 'Jane',
605
+ email: 'jane@example.com',
606
+ age: 25,
607
+ },
608
+ {
609
+ id: 3,
610
+ name: 'Bob',
611
+ email: 'bob@example.com',
612
+ age: 30,
613
+ },
614
+ ]);
615
+
616
+ try
617
+ {
618
+ const repository =
619
+ dataSource.getRepository(
620
+ QueryFeaturesUser,
621
+ );
622
+
623
+ const users =
624
+ await repository.find({
625
+ where: {
626
+ age: LessThan(30),
627
+ },
628
+ });
629
+
630
+ expect(users)
631
+ .toEqual([
632
+ {
633
+ id: 1,
634
+ name: 'John',
635
+ email: 'john@example.com',
636
+ age: 20,
637
+ },
638
+ {
639
+ id: 2,
640
+ name: 'Jane',
641
+ email: 'jane@example.com',
642
+ age: 25,
643
+ },
644
+ ]);
645
+ }
646
+ finally
647
+ {
648
+ if (dataSource.isInitialized)
649
+ {
650
+ await dataSource.destroy();
651
+ }
652
+ }
653
+ },
654
+ );
655
+
656
+ test(
657
+ 'should support LessThanOrEqual operator',
658
+ async () =>
659
+ {
660
+ const {
661
+ dataSource,
662
+ } =
663
+ await createDataSource([
664
+ {
665
+ id: 1,
666
+ name: 'John',
667
+ email: 'john@example.com',
668
+ age: 20,
669
+ },
670
+ {
671
+ id: 2,
672
+ name: 'Jane',
673
+ email: 'jane@example.com',
674
+ age: 25,
675
+ },
676
+ {
677
+ id: 3,
678
+ name: 'Bob',
679
+ email: 'bob@example.com',
680
+ age: 30,
681
+ },
682
+ ]);
683
+
684
+ try
685
+ {
686
+ const repository =
687
+ dataSource.getRepository(
688
+ QueryFeaturesUser,
689
+ );
690
+
691
+ const users =
692
+ await repository.find({
693
+ where: {
694
+ age: LessThanOrEqual(25),
695
+ },
696
+ });
697
+
698
+ expect(users)
699
+ .toEqual([
700
+ {
701
+ id: 1,
702
+ name: 'John',
703
+ email: 'john@example.com',
704
+ age: 20,
705
+ },
706
+ {
707
+ id: 2,
708
+ name: 'Jane',
709
+ email: 'jane@example.com',
710
+ age: 25,
711
+ },
712
+ ]);
713
+ }
714
+ finally
715
+ {
716
+ if (dataSource.isInitialized)
717
+ {
718
+ await dataSource.destroy();
719
+ }
720
+ }
721
+ },
722
+ );
723
+
724
+ test(
725
+ 'should support IsNull operator',
726
+ async () =>
727
+ {
728
+ const {
729
+ dataSource,
730
+ } =
731
+ await createDataSource([
732
+ {
733
+ id: 1,
734
+ name: 'John',
735
+ email: 'john@example.com',
736
+ age: 20,
737
+ },
738
+ {
739
+ id: 2,
740
+ name: null,
741
+ email: 'null@example.com',
742
+ age: 25,
743
+ },
744
+ {
745
+ id: 3,
746
+ name: 'Bob',
747
+ email: 'bob@example.com',
748
+ age: 30,
749
+ },
750
+ ]);
751
+
752
+ try
753
+ {
754
+ const repository =
755
+ dataSource.getRepository(
756
+ QueryFeaturesUser,
757
+ );
758
+
759
+ const users =
760
+ await repository.find({
761
+ where: {
762
+ name: IsNull(),
763
+ },
764
+ });
765
+
766
+ expect(users)
767
+ .toEqual([
768
+ {
769
+ id: 2,
770
+ name: null,
771
+ email: 'null@example.com',
772
+ age: 25,
773
+ },
774
+ ]);
775
+ }
776
+ finally
777
+ {
778
+ if (dataSource.isInitialized)
779
+ {
780
+ await dataSource.destroy();
781
+ }
782
+ }
783
+ },
784
+ );
785
+
786
+ test(
787
+ 'should support ordering',
788
+ async () =>
789
+ {
790
+ const {
791
+ dataSource,
792
+ } =
793
+ await createDataSource([
794
+ {
795
+ id: 1,
796
+ name: 'John',
797
+ email: 'john@example.com',
798
+ age: 20,
799
+ },
800
+ {
801
+ id: 2,
802
+ name: 'Jane',
803
+ email: 'jane@example.com',
804
+ age: 25,
805
+ },
806
+ {
807
+ id: 3,
808
+ name: 'Bob',
809
+ email: 'bob@example.com',
810
+ age: 30,
811
+ },
812
+ ]);
813
+
814
+ try
815
+ {
816
+ const repository =
817
+ dataSource.getRepository(
818
+ QueryFeaturesUser,
819
+ );
820
+
821
+ const users =
822
+ await repository.find({
823
+ order: {
824
+ age: 'DESC',
825
+ },
826
+ });
827
+
828
+ expect(users)
829
+ .toEqual([
830
+ {
831
+ id: 3,
832
+ name: 'Bob',
833
+ email: 'bob@example.com',
834
+ age: 30,
835
+ },
836
+ {
837
+ id: 2,
838
+ name: 'Jane',
839
+ email: 'jane@example.com',
840
+ age: 25,
841
+ },
842
+ {
843
+ id: 1,
844
+ name: 'John',
845
+ email: 'john@example.com',
846
+ age: 20,
847
+ },
848
+ ]);
849
+ }
850
+ finally
851
+ {
852
+ if (dataSource.isInitialized)
853
+ {
854
+ await dataSource.destroy();
855
+ }
856
+ }
857
+ },
858
+ );
859
+
860
+ test(
861
+ 'should support skip',
862
+ async () =>
863
+ {
864
+ const {
865
+ dataSource,
866
+ } =
867
+ await createDataSource([
868
+ {
869
+ id: 1,
870
+ name: 'John',
871
+ email: 'john@example.com',
872
+ age: 20,
873
+ },
874
+ {
875
+ id: 2,
876
+ name: 'Jane',
877
+ email: 'jane@example.com',
878
+ age: 25,
879
+ },
880
+ {
881
+ id: 3,
882
+ name: 'Bob',
883
+ email: 'bob@example.com',
884
+ age: 30,
885
+ },
886
+ ]);
887
+
888
+ try
889
+ {
890
+ const repository =
891
+ dataSource.getRepository(
892
+ QueryFeaturesUser,
893
+ );
894
+
895
+ const users =
896
+ await repository.find({
897
+ skip: 1,
898
+ });
899
+
900
+ expect(users)
901
+ .toEqual([
902
+ {
903
+ id: 2,
904
+ name: 'Jane',
905
+ email: 'jane@example.com',
906
+ age: 25,
907
+ },
908
+ {
909
+ id: 3,
910
+ name: 'Bob',
911
+ email: 'bob@example.com',
912
+ age: 30,
913
+ },
914
+ ]);
915
+ }
916
+ finally
917
+ {
918
+ if (dataSource.isInitialized)
919
+ {
920
+ await dataSource.destroy();
921
+ }
922
+ }
923
+ },
924
+ );
925
+
926
+ test(
927
+ 'should support take',
928
+ async () =>
929
+ {
930
+ const {
931
+ dataSource,
932
+ } =
933
+ await createDataSource([
934
+ {
935
+ id: 1,
936
+ name: 'John',
937
+ email: 'john@example.com',
938
+ age: 20,
939
+ },
940
+ {
941
+ id: 2,
942
+ name: 'Jane',
943
+ email: 'jane@example.com',
944
+ age: 25,
945
+ },
946
+ {
947
+ id: 3,
948
+ name: 'Bob',
949
+ email: 'bob@example.com',
950
+ age: 30,
951
+ },
952
+ ]);
953
+
954
+ try
955
+ {
956
+ const repository =
957
+ dataSource.getRepository(
958
+ QueryFeaturesUser,
959
+ );
960
+
961
+ const users =
962
+ await repository.find({
963
+ take: 2,
964
+ });
965
+
966
+ expect(users)
967
+ .toEqual([
968
+ {
969
+ id: 1,
970
+ name: 'John',
971
+ email: 'john@example.com',
972
+ age: 20,
973
+ },
974
+ {
975
+ id: 2,
976
+ name: 'Jane',
977
+ email: 'jane@example.com',
978
+ age: 25,
979
+ },
980
+ ]);
981
+ }
982
+ finally
983
+ {
984
+ if (dataSource.isInitialized)
985
+ {
986
+ await dataSource.destroy();
987
+ }
988
+ }
989
+ },
990
+ );
991
+
992
+ test(
993
+ 'should support pagination using skip and take',
994
+ async () =>
995
+ {
996
+ const {
997
+ dataSource,
998
+ } =
999
+ await createDataSource([
1000
+ {
1001
+ id: 1,
1002
+ name: 'John',
1003
+ email: 'john@example.com',
1004
+ age: 20,
1005
+ },
1006
+ {
1007
+ id: 2,
1008
+ name: 'Jane',
1009
+ email: 'jane@example.com',
1010
+ age: 25,
1011
+ },
1012
+ {
1013
+ id: 3,
1014
+ name: 'Bob',
1015
+ email: 'bob@example.com',
1016
+ age: 30,
1017
+ },
1018
+ {
1019
+ id: 4,
1020
+ name: 'Alice',
1021
+ email: 'alice@example.com',
1022
+ age: 35,
1023
+ },
1024
+ ]);
1025
+
1026
+ try
1027
+ {
1028
+ const repository =
1029
+ dataSource.getRepository(
1030
+ QueryFeaturesUser,
1031
+ );
1032
+
1033
+ const users =
1034
+ await repository.find({
1035
+ skip: 1,
1036
+ take: 2,
1037
+ });
1038
+
1039
+ expect(users)
1040
+ .toEqual([
1041
+ {
1042
+ id: 2,
1043
+ name: 'Jane',
1044
+ email: 'jane@example.com',
1045
+ age: 25,
1046
+ },
1047
+ {
1048
+ id: 3,
1049
+ name: 'Bob',
1050
+ email: 'bob@example.com',
1051
+ age: 30,
1052
+ },
1053
+ ]);
1054
+ }
1055
+ finally
1056
+ {
1057
+ if (dataSource.isInitialized)
1058
+ {
1059
+ await dataSource.destroy();
1060
+ }
1061
+ }
1062
+ },
1063
+ );
1064
+
1065
+ test(
1066
+ 'should support partial select',
1067
+ async () =>
1068
+ {
1069
+ const {
1070
+ dataSource,
1071
+ } =
1072
+ await createDataSource([
1073
+ {
1074
+ id: 1,
1075
+ name: 'John',
1076
+ email: 'john@example.com',
1077
+ age: 20,
1078
+ },
1079
+ {
1080
+ id: 2,
1081
+ name: 'Jane',
1082
+ email: 'jane@example.com',
1083
+ age: 25,
1084
+ },
1085
+ ]);
1086
+
1087
+ try
1088
+ {
1089
+ const repository =
1090
+ dataSource.getRepository(
1091
+ QueryFeaturesUser,
1092
+ );
1093
+
1094
+ const users =
1095
+ await repository.find({
1096
+ select: {
1097
+ id: true,
1098
+ name: true,
1099
+ },
1100
+ });
1101
+
1102
+ expect(users as Partial<QueryFeaturesUser>[])
1103
+ .toEqual([
1104
+ {
1105
+ id: 1,
1106
+ name: 'John',
1107
+ },
1108
+ {
1109
+ id: 2,
1110
+ name: 'Jane',
1111
+ },
1112
+ ]);
1113
+ }
1114
+ finally
1115
+ {
1116
+ if (dataSource.isInitialized)
1117
+ {
1118
+ await dataSource.destroy();
1119
+ }
1120
+ }
1121
+ },
1122
+ );
1123
+ },
1124
+ );